--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/datasourceadaptation/gpsdatasourceadaptation/common/src/cadaptationpositioner.cpp Tue Feb 02 01:50:39 2010 +0200
@@ -0,0 +1,646 @@
+// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+/**
+ @file
+ @InternalComponent
+*/
+
+#include <e32base.h>
+#include <lbs/epos_mpositionerstatus.h>
+#include <ecom/implementationproxy.h>
+#include <lbssatellite.h>
+#include "utilfunctions.h"
+
+#include "crequesthandler.h"
+#include "cresponsehandler.h"
+#include "cadaptationpositioner.h"
+#include "psypanic.h"
+#include "psylogging.h"
+#include "lbsprocessuiddefs.h"
+#include "lbsdevloggermacros.h"
+
+const TUint KWarmDownTimeout = 10000000;//10s
+
+CAdaptationPositioner::CAdaptationPositioner()
+ {
+ LBSLOG(ELogP1, "CAdaptationPositioner::CAdaptationPositioner()");
+ iState = ERequestStateInitial;
+ }
+
+/**
+* Destructor
+*/
+CAdaptationPositioner::~CAdaptationPositioner()
+ {
+ LBSLOG(ELogP1, "CAdaptationPositioner::~CAdaptationPositioner()");
+
+ StopMaxFixTimer();
+ delete iMaxFixTimer;
+ iMaxFixTimer = NULL;
+ StopWarmDownTimer();
+ delete iWarmDownTimer;
+ iWarmDownTimer = NULL;
+
+ CancelNotifyPositionUpdate();
+
+ if(iEnvironment)
+ {
+ iEnvironment->CloseInstance();
+ }
+ }
+
+/**
+* CancelNotifyPositionUpdate implements CAdaptationPositioner::CancelNotifyPositionUpdate
+* Cancels position info request.
+*/
+void CAdaptationPositioner::CancelNotifyPositionUpdate()
+ {
+ LBSLOG(ELogP1, "CAdaptationPositioner::CancelNotifyPositionUpdate()");
+ // Stop timers
+ StopMaxFixTimer();
+ StopWarmDownTimer();
+ CancelNotifyPositionUpdate(KErrCancel);
+ }
+
+/**
+* CancelNotifyPositionUpdate implements CAdaptationPositioner::CancelNotifyPositionUpdate(TInt)
+* Cancels position info request with reason. This reason allows the S60 Loc Server to distinguish between a real user cancel
+* and a timeout - in the case of the latter the LS calls CancelNotifyPositionUpdate(KErrTimedOut),
+* in the former he passes no error.
+*/
+void CAdaptationPositioner::CancelNotifyPositionUpdate(TInt aError)
+ {
+ LBSLOG2(ELogP1, "CAdaptationPositioner::CancelNotifyPositionUpdate(aError) %d", aError);
+
+ if( iActive )
+ {
+ LBSLOG2(ELogP1, "CAdaptationPositioner::Complete request error = %d", aError);
+
+ UpdateFailed(KErrCancel);
+ TRAP_IGNORE(iRequestHandler->ReMergeWithCancelRequestL(aError)); // Nothing we can do about a leave here
+ if(aError == KErrTimedOut && IsTracking())
+ {
+ // The last tracking request timedout so we need to schedule one for the next interval
+ TTime timeNow;
+ timeNow.UniversalTime();
+ iActive = ETrue;
+ UpdateTrackingTime(timeNow);
+ TRAPD(error, iRequestHandler->SubmitNewRequestL(this)); // Nothing we can do about a leave here
+ if(!error)
+ {
+ TRAP_IGNORE(StartMaxFixTimerL());// (re)start maxfix timer so that we know when the module has stopped trying
+ }
+ }
+ }
+ }
+
+
+/**
+* Indicate if the PSY has overridden tracking. The default
+* implementation returns EFalse.
+* @return ETrue if PSY has own timer, otherwise EFalse.
+*/
+TBool CAdaptationPositioner::TrackingOverridden() const
+ {
+ return ETrue;
+ }
+
+
+/**
+* Initiate a tracking session.
+*
+* @param aInterval Interval for position requests.
+*/
+void CAdaptationPositioner::StartTrackingL(const TTimeIntervalMicroSeconds& aInterval)
+ {
+ LBSLOG2(ELogP1, "CAdaptationPositioner::StartTrackingL, interval = %d", aInterval);
+
+ TTime timeNow;
+
+ TTime trackingTime = LbsTimerUtils::AddUpInt64TimersWithOverflowCheck(iTargetTime, aInterval);
+ timeNow.UniversalTime();
+
+ iTrackingInterval = aInterval;
+
+ if(! (trackingTime < timeNow)) // if this is not a default proxy call to StartTracking
+ {
+ LBSLOG(ELogP1, "Non-DefProxy Start");
+ SetupTrackingRequestL();
+ iRequestHandler->SubmitNewRequestL(this);
+ }
+ }
+
+/**
+* Stop a periodic update session.
+*/
+void CAdaptationPositioner::StopTracking()
+ {
+ LBSLOG(ELogP1, "CAdaptationPositioner::StopTracking");
+
+ iTrackingInterval = 0;
+ }
+
+/**
+* Restart tracking after a missed update
+*/
+void CAdaptationPositioner::UpdateTrackingTime(TTime& aTimeNow)
+ {
+ LBSLOG(ELogP1, "CAdaptationPositioner::UpdateTrackingTime restarting tracking");
+
+ TUint multiplier = ( (aTimeNow.Int64() - iTargetTime.Int64()) / iTrackingInterval.Int64() );
+ TTimeIntervalMicroSeconds timeToAdd = ( (multiplier + 1) * iTrackingInterval.Int64() );
+
+ if (timeToAdd < 0)
+ {
+ iTargetTime = Time::MaxTTime();
+ }
+ else
+ {
+ iTargetTime = LbsTimerUtils::AddUpInt64TimersWithOverflowCheck(iTargetTime, timeToAdd);
+ }
+ }
+
+/**
+* Submit a request with the target time in the future.
+* The positionerQ will deal with issuing a merged request from
+* all active positioners.
+*/
+void CAdaptationPositioner::SetupTrackingRequestL()
+ {
+ if(IsTracking())
+ {
+ LBSLOG(ELogP1, "CAdaptationPositioner::SetupTrackingRequestL");
+
+ iPosInfo = NULL; // This will be filled in by the NPUD when it arrives
+ iActive = ETrue;
+
+ iTargetTime.UniversalTime();
+
+ #ifdef _DEBUG
+ TDateTime timeNow = iTargetTime.DateTime();
+ LBSLOG3(ELogP1, "Time Now = %d.%d", timeNow.Second(), timeNow.MicroSecond());
+ #endif
+
+ iTargetTime = LbsTimerUtils::AddUpInt64TimersWithOverflowCheck(iTargetTime, iTrackingInterval);
+
+ #ifdef _DEBUG
+ timeNow = iTargetTime.DateTime();
+ LBSLOG3(ELogP1, "Target Time = %d.%d", timeNow.Second(), timeNow.MicroSecond());
+ #endif
+
+ StartMaxFixTimerL();
+ }
+ }
+
+/**
+* Check if we're tracking.
+*
+* @return ETrue if we are tracking
+*/
+TBool CAdaptationPositioner::IsTracking()
+ {
+ return (iTrackingInterval != 0);
+ }
+
+/**
+* Attempt to use an old position
+*
+* @param aPosInfo The clients position info
+* @return ETrue if the old position was used
+*/
+TBool CAdaptationPositioner::UseLastLocation(TPositionInfoBase& aPosInfo)
+ {
+ TTime maxAge;
+ TBool result = EFalse;
+
+ GetMaxAge(maxAge);
+
+ if(maxAge > 0)
+ {
+ CResponseHandler* responseHandler = iEnvironment->GetResponseHandler();
+
+ result = responseHandler->GetLastPosition(aPosInfo, maxAge, IsPartialUpdateAllowed());
+
+ if( result ) // Use last location
+ {
+ TInt err = KErrNone;
+ TPosition pos;
+ static_cast<TPositionInfo&>(aPosInfo).GetPosition(pos);
+ if(Partial(pos))
+ {
+ err = KPositionPartialUpdate;
+ }
+ LBSLOG(ELogP1, "CAdaptationPositioner::NotifyPositionUpdate returning old position");
+ // nb: this will deal with tracking requests properly:
+ if(CompleteRequest(static_cast<TPositionInfo&>(aPosInfo), err))
+ {
+ TRAP_IGNORE(SetupTrackingRequestL());
+ }
+ }
+ }
+
+ return result;
+ }
+
+/**
+* Attempt to complete an outstanding request if there is one
+*
+* @param aPositionInfo The retrieved fix.
+* @param aError The error code if the request is failed.
+* @param aActualTime time of the location update
+*/
+void CAdaptationPositioner::RequestCompleteNotify(const TPositionInfo& aPositionInfo, TInt aError, TTime& aActualTime)
+ {
+ LBSLOG(ELogP1, "CAdaptationPositioner::RequestCompleteNotify start...");
+
+ TBool startWarmDown = EFalse;
+ TBool completed = EFalse;
+
+ if(iActive)
+ {
+ TPositionModuleInfo::TTechnologyType mode = aPositionInfo.PositionMode();
+
+ if( (aActualTime >= iTargetTime) || (aError == KPositionCalculationFutile) )
+ {
+ // Check if the update is partial and if partial updates are allowed
+ TPosition pos;
+ aPositionInfo.GetPosition(pos);
+
+ TBool partial = Partial(pos);
+
+ TBool isFNP = (aPositionInfo.PositionMode() == (TPositionModuleInfo::ETechnologyNetwork | TPositionModuleInfo::ETechnologyAssisted));
+
+ if(isFNP)
+ {
+ LBSLOG(ELogP1, "Complete with FNP");
+ /* removing this for now until we decide how to deal with the qualityloss issue on s60
+ * since on s60 qualityloss means no position was generated
+ if(partial)
+ {
+ CompleteRequest(aPositionInfo, KPositionQualityLoss);
+ }
+
+ else
+ */
+ {
+ completed = CompleteRequest(aPositionInfo, KErrNone);
+
+ // Stop the AGPS Manager if there are no other outstanding requests
+ TRAP_IGNORE(iRequestHandler->CancelRequestL());
+ }
+ }
+ else if(partial && IsPartialUpdateAllowed())
+ {
+ LBSLOG(ELogP1, "Complete with partial");
+ completed = CompleteRequest(aPositionInfo, KPositionPartialUpdate);
+ startWarmDown = ETrue;
+ }
+ else if(!partial)
+ {
+ LBSLOG(ELogP1, "Complete with non-partial");
+ completed = CompleteRequest(aPositionInfo, KErrNone);
+
+ // did the module produce an accurate update or is it still trying?
+ if(!IsAccurate(aPositionInfo))
+ {
+ startWarmDown = ETrue;
+ }
+ else // it might be an accurate reference position
+ {
+ TBool isRefPos = (aPositionInfo.ModuleId() == KLbsGpsLocManagerUid) &&
+ (aPositionInfo.PositionMode() == TPositionModuleInfo::ETechnologyNetwork);
+ if(isRefPos)
+ {
+ startWarmDown = ETrue;
+ }
+ }
+ }
+ else if(aError == KPositionCalculationFutile)
+ {
+ // if autonomous return immediately otherwise wait for FNP
+ if(mode & TPositionModuleInfo::ETechnologyTerminal)
+ {
+ LBSLOG(ELogP1, "Complete with futile");
+ completed = CompleteRequest(aPositionInfo, KPositionQualityLoss);
+ }
+ }
+ else
+ {
+ // position is not futile and is partial but partials are not
+ // allowed. In this case do nothing and wait for further updates
+ }
+ }
+ else
+ {
+ LBSLOG(ELogP1, "CAdaptationPositioner::RequestCompleteNotify Ignoring early response");
+ }
+ }
+
+ if (completed)
+ {
+ TRAP_IGNORE(SetupTrackingRequestL());
+ }
+
+ if(startWarmDown) // we need to start a warmdown timer
+ {
+ TRAP_IGNORE(StartWarmDownTimerL()); // not much we can do here if warmdown timer not started
+ }
+ LBSLOG(ELogP1, "CAdaptationPositioner::RequestCompleteNotify end");
+ }
+
+/**
+* Attempt to complete an outstanding request if there is one with an error
+*
+* @param aError The error code if the request is failed.
+*/
+void CAdaptationPositioner::UpdateFailed(TInt aError)
+ {
+ LBSLOG(ELogP1, "CAdaptationPositioner::UpdateFailed()");
+ if(iActive)
+ {
+ LBSLOG2(ELogP1, "CAdaptationPositioner::Complete request error = %d", aError);
+
+ iActive = EFalse;
+ ClearPositionInfo(*iPosInfo);
+
+ if(iClientStatus)
+ {
+ User::RequestComplete(iClientStatus, aError);
+ iClientStatus = NULL;
+ }
+ LBSLOG2(ELogP1, "iState -> ERequestStatePostInitial from %d", iState);
+ iState = ERequestStatePostInitial;
+ }
+ }
+
+/**
+* Complete the outstanding request and reset internal state
+*
+* @param aPositionInfo The retrieved fix.
+* @param aError The error code if the request is failed.
+*/
+TBool CAdaptationPositioner::CompleteRequest(const TPositionInfo& aPositionInfo, TInt aError)
+ {
+ LBSLOG2(ELogP1, "CAdaptationPositioner::CompleteRequest() with error %d", aError);
+ TBool completed = EFalse;
+ iActive = EFalse; // Stop another request being sent for this instance of the PSY
+
+ if(iPosInfo)
+ {
+ TInt error = CopyPositionTypes(*iPosInfo, aPositionInfo);
+ __ASSERT_DEBUG(error == KErrNone,
+ User::Panic(KAdaptationPanicCategory, EPanicPositionCopyFailed));
+ error = error; // this is to stop arm build warnings
+
+ SetModuleId(iPosInfo); // Delegate to the derived class
+ User::RequestComplete(iClientStatus, aError);
+ iClientStatus = NULL;
+ LBSLOG2(ELogP1, "iState -> ERequestStatePostInitial from %d", iState);
+ iState = ERequestStatePostInitial;
+ completed = ETrue;
+ }
+ else
+ {
+ LBSLOG(ELogP1, "CAdaptationPositioner::RequestCompleteNotify iPosInfo not set");
+ }
+
+ return completed;
+ }
+
+/**
+* CAdaptationPositioner::ReportStatus
+* Reports the PSY status to the MLFW
+*
+* @param aStatus The new position module status
+*/
+void CAdaptationPositioner::ReportStatus(const TPositionModuleStatus& aStatus)
+ {
+ MPositionerStatus* statusInf = this->PositionerStatus();
+ statusInf->ReportStatus(aStatus);
+ }
+
+/**
+ * Clears the fields of the aPosInfo
+ * @param aPosInfo The position information to return
+ */
+void CAdaptationPositioner::ClearPositionInfo(TPositionInfoBase& aPosInfo)
+ {
+ if(&aPosInfo != NULL)
+ {
+ if (aPosInfo.PositionClassType() & EPositionSatelliteInfoClass)
+ {
+ // TPositionSatelliteInfo
+ (void) new (&aPosInfo) (TPositionSatelliteInfo);
+ }
+ else if (aPosInfo.PositionClassType() & EPositionCourseInfoClass)
+ {
+ // TPositionCourseInfo
+ (void) new (&aPosInfo) (TPositionCourseInfo);
+ }
+ else if (aPosInfo.PositionClassType() & EPositionGenericInfoClass)
+ {
+ // HPositionGenericInfo
+ HPositionGenericInfo* genInfo =
+ static_cast<HPositionGenericInfo*> ( &aPosInfo );
+
+ genInfo->ClearPositionData();
+ }
+ else if (aPosInfo.PositionClassType() & EPositionInfoClass)
+ {
+ // TPositionInfo
+ (void) new (&aPosInfo) (TPositionInfo);
+ }
+ else
+ {
+ // Unknown type, this should never happen
+ // --> Panic if we get here
+ __ASSERT_DEBUG(0, User::Panic(KAdaptationPanicCategory, EPanicUnknownPositioningClass));
+ }
+
+ aPosInfo.SetModuleId(ImplementationUid());
+ }
+ }
+
+
+TBool CAdaptationPositioner::IsActive()
+ {
+ return iActive;
+ }
+
+TBool CAdaptationPositioner::IsWarmingDown()
+ {
+ if(iWarmDownTimer)
+ {
+ return iWarmDownTimer->IsActive();
+ }
+ return EFalse;
+ }
+
+void CAdaptationPositioner::StartMaxFixTimerL()
+ {
+ LBSLOG(ELogP1, "CAdaptationPositioner::StartMaxFixTimerL()");
+ if(iMaxFixTimer) // stop any that's currently running
+ {
+ iMaxFixTimer->Cancel();
+ }
+ else
+ {
+ iMaxFixTimer = CLbsCallbackTimer::NewL(*this);
+ }
+
+ iMaxFixTimer->EventAfter(iTimeOutInterval, EMaxFixTimerEvent);
+ }
+
+void CAdaptationPositioner::StopMaxFixTimer()
+ {
+ LBSLOG(ELogP1, "CAdaptationPositioner::StopMaxFixTimer()");
+ if(iMaxFixTimer)
+ {
+ iMaxFixTimer->Cancel();
+ }
+ }
+
+void CAdaptationPositioner::StartWarmDownTimerL()
+ {
+ TTimeIntervalMicroSeconds32 timeout = KWarmDownTimeout;
+ LBSLOG(ELogP1, "CAdaptationPositioner::StartWarmDownTimerL()");
+ if(iWarmDownTimer) // stop any that's currently running
+ {
+ iWarmDownTimer->Cancel();
+ }
+ else
+ {
+ iWarmDownTimer = CLbsCallbackTimer::NewL(*this);
+ }
+ iWarmDownTimer->EventAfter(timeout, EWarmDownTimerEvent);
+ }
+
+void CAdaptationPositioner::StopWarmDownTimer()
+ {
+ LBSLOG(ELogP1, "CAdaptationPositioner::StopWarmDownTimer()");
+ if(iWarmDownTimer)
+ {
+ iWarmDownTimer->Cancel();
+ }
+ }
+
+/**
+MaxFixTimerEvent handling
+
+Stop warmdown timer
+*/
+void CAdaptationPositioner::MaxFixTimerEvent()
+ {
+ LBSLOG(ELogP1, "CAdaptationPositioner::MaxFixTimerEvent()");
+
+ // Cancel the warmdown timer since the module has stopped trying
+ StopWarmDownTimer();
+ }
+
+/**
+MaxFixTimer error handling
+*/
+TInt CAdaptationPositioner::MaxFixTimerError(TInt /*aError*/)
+ {
+ return KErrNone;
+ }
+
+/**
+MaxFixTimerEvent handling
+
+Stop warmdown timer
+*/
+void CAdaptationPositioner::WarmDownTimerEvent()
+ {
+ LBSLOG(ELogP1, "CAdaptationPositioner::MaxFixTimerEvent()");
+
+ // tell positioner Q that our warmdown timer has fired
+ iRequestHandler->WarmDownTimerExpired();
+ }
+
+/**
+WarmDown error handling
+*/
+TInt CAdaptationPositioner::WarmDownTimerError(TInt /*aError*/)
+ {
+ return KErrNone;
+ }
+
+
+/**
+from MLbsCallbackTimerObserver
+
+@param aTimerId Time event ID to identify different time events
+*/
+void CAdaptationPositioner::OnTimerEventL(TInt aTimerId)
+ {
+ switch(aTimerId)
+ {
+ case EMaxFixTimerEvent:
+ MaxFixTimerEvent();
+ break;
+ case EWarmDownTimerEvent:
+ WarmDownTimerEvent();
+ break;
+ default:
+ __ASSERT_DEBUG(0, User::Panic(KAdaptationPanicCategory, EPanicUnknownTimerEventId));
+ }
+ }
+/**
+Timer error handling
+
+@param aError Time error code
+@param aTimerId Time event ID to identify two different time events
+*/
+TInt CAdaptationPositioner::OnTimerError(TInt aError, TInt aTimerId)
+ {
+ switch(aTimerId)
+ {
+ case EMaxFixTimerEvent:
+ MaxFixTimerError(aError);
+ break;
+ case EWarmDownTimerEvent:
+ WarmDownTimerError(aError);
+ break;
+ default:
+ __ASSERT_DEBUG(0, User::Panic(KAdaptationPanicCategory, EPanicUnknownTimerEventId));
+ }
+ return KErrNone; // we have handled the error locally
+ }
+
+
+TBool CAdaptationPositioner::IsAccurate(const TPositionInfo& aPositionInfo)
+ {
+ TBool accurate = ETrue;
+ TPositionQuality reqQuality;
+ iCriteria.GetRequiredQuality(reqQuality);
+ TPosition pos;
+
+ aPositionInfo.GetPosition(pos);
+ if(pos.HorizontalAccuracy() > reqQuality.HorizontalAccuracy() )
+ {
+ accurate = EFalse;
+ }
+ return accurate;
+ }
+
+TUint CAdaptationPositioner::InactivityTimeout()
+ {
+ return iInactivityTimeout;
+ }
+
+
+// End of File