diff -r 000000000000 -r 9cfd9a3ee49c networkprotocolmodules/networkprotocolmodule/LbsProtocolModule/src/cmolrstatemachine.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/networkprotocolmodules/networkprotocolmodule/LbsProtocolModule/src/cmolrstatemachine.cpp Tue Feb 02 01:50:39 2010 +0200 @@ -0,0 +1,631 @@ +// Copyright (c) 2006-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: +// This file provides the implementation of the class for +// the MO-LR protocol state machine. +// +// + +/** + @file + @internalTechnology + @released +*/ + +#include "cmolrstatemachine.h" +#include "cmolrstatehandler.h" + + +/** KMoLrReqIssuedTimerEvent +Identity of timer for when MO-LR request issued to network +*/ +const TInt KMoLrReqIssuedTimerEvent = 0x100; + +/** KMoLrReqIssuedTimerDurationInSec +Timer duration for when MO-LR request issued to network +*/ +const TInt KMoLrReqIssuedTimerDurationInSec = 20; + +/** KLocRespTimerEvent +Identity of timer for when location response expected by network +*/ +const TInt KLocRespTimerEvent = 0x200; + +/** KLocRespTimerDurationInSec +Timer duration for when location response expected by network +*/ +const TInt KLocRespTimerDurationInSec = 64; + +/** KFacResultTimerEvent +Identity of timer for when facility result expected from network +*/ +const TInt KFacResultTimerEvent = 0x300; + +/** KFacResultTimerDurationInSec +Timer duration for when facility result expected from network +*/ +const TInt KFacResultTimerDurationInSec = 10; + +/** KMaxQueueEntry +Maximum entries in this state machine request queue. +*/ +const TInt KMaxQueueEntry = 5; + + +/** Static constructor. +@param aObserver Reference to state machine observer. +@return A new instance of the CMoLrStateMachine class +*/ +CMoLrStateMachine* CMoLrStateMachine::NewL(MStateMachineObserver& aObserver) + { + CMoLrStateMachine* self = new (ELeave) CMoLrStateMachine(aObserver); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + + +/** Standard constructor. +@param aObserver Reference to state machine observer. +*/ +CMoLrStateMachine::CMoLrStateMachine(MStateMachineObserver& aObserver) +: CStateMachineBase(aObserver) + { + iLocReqType = MLbsNetworkProtocolObserver::EServiceSelfLocation; + } + + +/** Standard destructor. +*/ +CMoLrStateMachine::~CMoLrStateMachine() + { + delete iFacResultTimer; + delete iLocRespTimer; + delete iMoLrReqIssuedTimer; + } + + +/** Private second-stage constructor. +*/ +void CMoLrStateMachine::ConstructL() + { + CActiveScheduler::Add(this); + + // Create state handler + iStateHandler = CMoLrStateHandler::NewL(*this); + + // Create timers used during MO-LR protocol procedure + iMoLrReqIssuedTimer = CLbsCallbackTimer::NewL(*this); + iLocRespTimer = CLbsCallbackTimer::NewL(*this); + iFacResultTimer = CLbsCallbackTimer::NewL(*this); + iAssistDataTimer = CLbsCallbackTimer::NewL(*this); + + // Create request queue + iQueue = CStateQueue::NewL(KMaxQueueEntry); + } + + +/** Retrieve current MO-Lr state +@return TMoLrState Current MO-LR state +*/ +CMoLrStateMachine::TMoLrState CMoLrStateMachine::CurrentState() + { + return iCurrentState; + } + + +/** Start MO-LR request timer +The state handler calls this when it has issued an MO-LR request +to the network and it requires a response before the timer expires. +*/ +void CMoLrStateMachine::StartMoLrReqTimer() + { + if(iMoLrReqIssuedTimer->IsActive()) + { + iMoLrReqIssuedTimer->Cancel(); + } + iMoLrReqIssuedTimer->EventAfter(TTimeIntervalSeconds(KMoLrReqIssuedTimerDurationInSec), KMoLrReqIssuedTimerEvent); + } + + +/** Start location response timer +The state handler calls this when it has sent a location request +to the client and requires a response before the timer expires. +*/ +void CMoLrStateMachine::StartLocRespTimer() + { + if(iLocRespTimer->IsActive()) + { + iLocRespTimer->Cancel(); + } + iLocRespTimer->EventAfter(TTimeIntervalSeconds(KLocRespTimerDurationInSec), KLocRespTimerEvent); + } + + +/** Start facility result timer +The state handler calls this when it has sent a location report +to the network and requires a result before the timer expires. +*/ +void CMoLrStateMachine::StartFacResultTimer() + { + if(iFacResultTimer->IsActive()) + { + iFacResultTimer->Cancel(); + } + iFacResultTimer->EventAfter(TTimeIntervalSeconds(KFacResultTimerDurationInSec), KFacResultTimerEvent); + } + + +/** Indicates if location request has been sent to LBS. +@return TBool ETrue if location request has been sent to LBS. +*/ +TBool CMoLrStateMachine::IsLocReqSentToLbs() const + { + return iIsLocReqSentToLbs; + } + + +/** Network Result Location. +This is called by state handlers to retrieve the most +recent reported network result location. +@return TPositionInfoBase Currently held network result position +*/ +const TPositionInfoBase& CMoLrStateMachine::NetResultLoc() const + { + return iNetResultPosInfo; + } + + +/** Store network resulting location +@param aPosInfo Network result location information +*/ +void CMoLrStateMachine::StoreNetResultLoc(const TPositionInfoBase& aPosInfo) + { + iNetResultPosInfo = reinterpret_cast (aPosInfo); + } + + +/** Initialise internal state attributes. +This is used when new MO-LR procedure commences. +*/ +void CMoLrStateMachine::InitialiseProcedure() + { + // Initialise state machine + InitialiseMachineBase(); + + iIsLocReqSentToLbs = EFalse; + iIsNetResultLocAvailable = EFalse; + + ASSERT(iStateHandler != NULL); + iStateHandler->Initialise(); + } + + +/** Prepare state transition. +*/ +void CMoLrStateMachine::PreStateTransition() + { + } + + +/** State transition. +This method determines the next state to be adopted by the state machine. +*/ +void CMoLrStateMachine::StateTransition() + { + if (CancelPending()) + { + SetMachineAsCancelling(); + iCurrentState = EStateCancelling; + } + else + { + // Set new state + switch (iCurrentState) + { + + case EStateNull: + iCurrentState = EStateClientReqRecvd; + break; + + case EStateClientReqRecvd: + iCurrentState = EStateNetSessStarted; + break; + + case EStateNetSessStarted: + iCurrentState = EStateMeasureDataRecvd; + break; + + case EStateMeasureDataRecvd: + iCurrentState = EStateNetBasedLocSent; + break; + + case EStateNetBasedLocSent: + iCurrentState = EStateLocReqByNet; + iIsMeasureControlHandled = ETrue; + iIsLocReqSentToLbs = ETrue; + break; + + case EStateLocReqByNet: + iCurrentState = EStateLocRespRecvd; + break; + + case EStateLocRespRecvd: + iCurrentState = EStateLocSentToNet; + break; + + case EStateLocSentToNet: + iCurrentState = EStateNetSessToClose; + break; + + case EStateNetSessToClose: + // If a network result is provided then it is sent to LBS + // otherwise the LBS client session closes + iCurrentState = iIsNetResultLocAvailable ? EStateNetResultSent : EStateClientSessToClose; + break; + + case EStateNetResultSent: + iCurrentState = EStateClientSessToClose; + break; + + case EStateClientSessToClose: + iCurrentState = EStateSessionsClosed; + break; + + case EStateSessionsClosed: + // Procedure has completed + CompleteProcedure(); + break; + + case EStateCancelling: + iCurrentState = EStateNetSessToClose; + break; + + default: + User::Panic(KProtocolModulePanic, EProtocolModuleMoLrState); + break; + }; + } + + } + + +/** Complete the procedure. +*/ +void CMoLrStateMachine::CompleteProcedure() + { + iCurrentState = EStateNull; + // Complete state machine + CompleteMachineBase(); + } + + +/** Complete a state transition. +This is called by the base class when a state transition has +concluded and it provides an opportunity for the state machine +to perform actions required immediately after this transition. + +The method can also initiate a further change of state. This is +relevant when the state machine is required to perform an autonomous +transition from one state to another e.g. this occurs when several +interactions are required arising from a single external trigger. +*/ +void CMoLrStateMachine::PostStateTransition() + { + // Some states are transitory i.e. they require + // an automatic transition to the next state + if ( CancelPending() || + (EStateClientReqRecvd == iCurrentState) || + (EStateMeasureDataRecvd == iCurrentState) || + (EStateNetBasedLocSent == iCurrentState) || + (EStateLocRespRecvd == iCurrentState) || + (EStateNetSessToClose == iCurrentState) || + (EStateNetResultSent == iCurrentState) || + (EStateClientSessToClose == iCurrentState) || + (EStateSessionsClosed == iCurrentState) || + (EStateCancelling == iCurrentState) + ) + { + // Perform a state transition + PerformStateTransition(); + } + } + + +/** Do actions required for a queued request. +This currently only initiates another state change but it +has the scope for further actions to be carried out according +to the nature of a queued request. +*/ +void CMoLrStateMachine::DoQueuedRequest(TInt aRequest) + { + switch (aRequest) + { + case EQueueLocResponse: + case EQueueMeasurementControl: + case EQueueNetworkResult: + // Perform a state transition + PerformStateTransition(); + break; + + default: + User::Panic(KProtocolModulePanic, EProtocolModuleQueueRequestId); + break; + }; + + } + + +/** Cancel the active procedure +*/ +void CMoLrStateMachine::CancelProcedure() + { + // Kill all timers + iMoLrReqIssuedTimer->Cancel(); + iLocRespTimer->Cancel(); + iFacResultTimer->Cancel(); + iAssistDataTimer->Cancel(); + } + + +/** Timer expired callback. +This is called by a CStateTimer object when the timer +has expired - the event is identified by aEvent parameter. +@param aTimerId The timer event identifier. +*/ +void CMoLrStateMachine::OnTimerEventL(TInt aTimerId) + { + // Perform relevant action for the expired timer + switch (aTimerId) + { + + // MO-LR request timer + case KMoLrReqIssuedTimerEvent: + // Inform protocol manager + Observer().MeasurementControlTimeout(); + break; + + // Additional assistance data timer + case KAssistDataTimerEvent: + iLocRespReason = KErrTimedOut; + // Inform protocol manager + Observer().MeasurementControlTimeout(); + break; + + // Facility result timer + case KFacResultTimerEvent: + CancelMachine(ECancelNetworkTimeout); + break; + + // Location response timer + case KLocRespTimerEvent: + iLocRespReason = KErrTimedOut; + CancelMachine(ECancelClientTimeout); + break; + + // Ignore unknown timer events + default: + break; + + }; + + } + + +/** Timer callback error handler. +This is called if the timer expiry callback leaves. +@see CMoLrStateMachine::OnTimerEventL() +@param aTimerId The timer event identifier. +@param aError Error value. +*/ +TInt CMoLrStateMachine::OnTimerError(TInt /*aTimerId*/, TInt aError) + { + return aError; + } + + +/** Handle Measurement Control timeout +*/ +void CMoLrStateMachine::MeasurementControlTimeout() + { + // Ensure assistance data action is performed upon cancellation + iAssistanceDataActionRequired = ETrue; + + // Cancel procedure + CancelMachine(ECancelNetworkTimeout); + } + + +/** Handle LBS request for MO-LR +@param aSessionId The session ID supplied by LBS. +*/ +void CMoLrStateMachine::MoLrReq(const TLbsNetSessionId& aSessionId) + { + // Store the supplied ID information + SessionId(aSessionId); + + // Initialise the new procedure + InitialiseProcedure(); + + // This state machine requires assistance data actions + // to be performed immediately immediate + iObserver.DoAssistanceDataActions(); + + // Perform a state transition + PerformStateTransition(); + } + + +/** Queue an LBS request for MO-LR +@param aSessionId The session ID supplied by LBS. +*/ +void CMoLrStateMachine::QueueMoLrReq(const TLbsNetSessionId& aSessionId) + { + // Store the session ID + QueueSessionId(aSessionId); + + CStateMachineBase::SetMachineAsQueued(); + } + + +/** Start previously queued state machine. +*/ +void CMoLrStateMachine::StartQueuedMachine() + { + MoLrReq(iQueueSessionId); + } + + +/** Handle LBS Location response +@param aReason Location response error reason. +@param aPosInfo The location information response from LBS. +*/ +void CMoLrStateMachine::LocationResp(TInt aReason, const TPositionInfoBase& aPosInfo) + { + // Store location response data + StoreLocationResp(aReason, aPosInfo); + + // Kill the timer related to location response expected by network + iLocRespTimer->Cancel(); + + // Is the state machine inactive? + if (!IsActive()) + { + // Perform a state transition + PerformStateTransition(); + } + else + { + // Queue the request + iQueue->AddRequest(EQueueLocResponse); + } + } + + +/** Handle Network Measurement Control indication. +A measurement control indication has been received from the network. +Note: At this stage the assistance data has already been stored by the +protocol manager and is thus not passed into this method. + +@param aPosInfo Reference location information provided in the measurement control +@param aQuality Location request quality specified in the measuerment control +*/ +void CMoLrStateMachine::MeasurementControlInd(const TPositionInfoBase& aPosInfo, + const TLbsNetPosRequestQuality& aQuality, const TLbsNetPosRequestMethod& aPosMethod) + { + // Kill timer related to the MO-LR request + iMoLrReqIssuedTimer->Cancel(); + + // Perform base class actions + CStateMachineBase::MeasurementControlInd(aPosInfo, aQuality, aPosMethod); + + // Is the state machine inactive? + if (!IsActive()) + { + // Perform a state transition + PerformStateTransition(); + } + else + { + // Queue the request + iQueue->AddRequest(EQueueMeasurementControl); + } + } + + +/** Handle Network Measurement Control Error indication +This is called by the protocol manager durinq an active MO-LR when +a measurement control error is received from the network. +*/ +void CMoLrStateMachine::MeasurementControlErrorInd(TInt aReason) + { + TBool cancelRequired = EFalse; + TBool assistActionRequired = ETrue; + + // If there is no outstanding assistance data request then + // inhibit assistance data error responses. + if (!iMoLrReqIssuedTimer->IsActive() && + !iAssistDataTimer->IsActive()) + { + assistActionRequired = EFalse; + } + + // Is this the first measurement control received? + if (!IsLocReqReceived() || (KErrCancel == aReason)) + { + // Kill timer related to the MO-LR request + iMoLrReqIssuedTimer->Cancel(); + cancelRequired = ETrue; + } + + // Perform base class actions + CStateMachineBase::HandleMeasureControlError(cancelRequired, aReason); + + // Ensure assistance data action only happens if necessary + iAssistanceDataActionRequired = assistActionRequired; + } + + +/** Handle Network Session Result +@param aResult The error result from network session closure. +@param aPosInfo A pointer to final result location information from the network. + This can be null if there is not final position provided. +*/ +void CMoLrStateMachine::SessionResult(TInt aResult, const TPositionInfoBase* aPosInfo) + { + // Kill timer related to the facility result + iFacResultTimer->Cancel(); + + iNetSessionResult = aResult; + + // Is a position provided? + if (aPosInfo) + { + // Store network resulting location + StoreNetResultLoc(*aPosInfo); + iIsNetResultLocAvailable = ETrue; + } + else + { + iIsNetResultLocAvailable = EFalse; + } + + // Is state machine inactive? + if (!IsActive()) + { + // Perform a state transition + PerformStateTransition(); + } + else + { + // Queue request + iQueue->AddRequest(EQueueNetworkResult); + } + } + + +/** Handle a network error indication. +*/ +void CMoLrStateMachine::NetworkErrorInd() + { + // Do we need to report assistance data errors? + if (!IsLocReqReceived()) + { + iAssistanceDataActionRequired = ETrue; + } + + // Perform base class actions + CStateMachineBase::NetworkErrorInd(); + } +