diff -r a2efdd544abf -r b47902b73a93 locationrequestmgmt/networkrequesthandler/src/privacyandlocationrequesthandler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/locationrequestmgmt/networkrequesthandler/src/privacyandlocationrequesthandler.cpp Fri Jun 04 10:34:15 2010 +0100 @@ -0,0 +1,2835 @@ +// 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: +// + +#include +#include +#include + +#ifdef SYMBIAN_FEATURE_MANAGER + #include + #include +#endif + +// LBS-specific +#include +#include +#include +#include + +#include "nrhpanic.h" +#include "lbsdevloggermacros.h" +#include "lbsqualityprofile.h" +#include "lbsrootcenrepdefs.h" +#include "lbspositioningstatusprops.h" + +#include "privacyandlocationrequesthandler.h" + +// Special 'invalid session' SessionId. +const TLbsNetSessionIdInt KInvalidSessionId(TUid::Uid(0), 0); + +const TPositionModuleInfo::TTechnologyType KTerminalAssistedMode = (TPositionModuleInfo::ETechnologyNetwork | + TPositionModuleInfo::ETechnologyAssisted); + +// ----------------------------------------------------------------------------- +// +// ----------------------- Class CPrivacyAndLocationHandler -------------------- +// +// State Machine class which owns the states of the Privacy and Location Handler +// +// ----------------------------------------------------------------------------- +// + +// ----------------------------------------------------------------------------- +// CPrivacyAndLocationHandler::NewL +// Description: CPrivacyAndLocationHandler static constructor +// ----------------------------------------------------------------------------- +// +CPrivacyAndLocationHandler* CPrivacyAndLocationHandler::NewL(CNGMessageSwitch& aMessageSwitch, + CLbsAdmin& aLbsAdmin, + RLbsNetworkRegistrationStatus& aNetRegStatus) + { + CPrivacyAndLocationHandler* self; + self = new (ELeave) CPrivacyAndLocationHandler(aMessageSwitch, aNetRegStatus); + CleanupStack::PushL(self); + self->ConstructL(&aLbsAdmin); + CleanupStack::Pop(self); + return(self); + } + +// ----------------------------------------------------------------------------- +// CPrivacyAndLocationHandler::CPrivacyAndLocationHandler +// Description: CPrivacyAndLocationHandler constructor +// ----------------------------------------------------------------------------- +// +CPrivacyAndLocationHandler::CPrivacyAndLocationHandler(CNGMessageSwitch& aMessageSwitch, + RLbsNetworkRegistrationStatus& aNetRegStatus) +: iNetRegStatus(aNetRegStatus), + iMessageSwitch(&aMessageSwitch), + iNumActiveSessions(0) + { + } + +// ----------------------------------------------------------------------------- +// CPrivacyAndLocationHandler::~CPrivacyAndLocationHandler +// Description: CPrivacyAndLocationHandler destructor +// ----------------------------------------------------------------------------- +// +CPrivacyAndLocationHandler::~CPrivacyAndLocationHandler() + { + // If iEmergencyFsm has been used by any outstanding request, + // it needs to be removed before calling ResetAndDestroy(), + // otherwise it will get double-deleted when delete iEmergencyFsm + // is called. + + TInt index = iFsmArray.Find(iEmergencyFsm); + if (index >= 0) + { + iFsmArray.Remove(index); + } + + iFsmArray.ResetAndDestroy(); + + // force the count of active network initiated positioning sessions to 0 + // this supports the pre-APE centric architecture wherein the NRH is + // destroyed on completion of network initiated positioning. + RProperty::Set(iPosStatusCategory, KLbsNiPositioningStatusKey, 0); + + delete iEmergencyFsm; + delete iAgpsInterface; + delete iPrivacyHandler; + } + +// ----------------------------------------------------------------------------- +// CPrivacyAndLocationHandler::ConstructL +// Description: CPrivacyAndLocationHandler second-phase constructor. +// Creates the states of the system and the Privacy Handler. +// ----------------------------------------------------------------------------- +// + +const TInt KLbsDefaultMaxNumLocationRequests = 4; + +void CPrivacyAndLocationHandler::ConstructL(CLbsAdmin* aLbsAdmin) + { + iLbsAdmin = aLbsAdmin; + + iPrivacyHandler = CPrivacyHandler::CreateL(this, *iLbsAdmin, iNetRegStatus); + iMessageSwitch->RegisterObserver(this); + + // Get the behaviour mode and device gps mode capabilities + TInt err = iLbsAdmin->Get(KLbsSettingBehaviourMode, iLbsBehaviourMode); + if (err != KErrNone) + { + iLbsBehaviourMode = CLbsAdmin::ELbsBehaviourCustom1; + } + // get device mode capabilities: + err = LbsModuleInfo::GetDeviceCapabilities(KLbsGpsLocManagerUid, iDeviceGpsModeCaps); + if(err != KErrNone || (iDeviceGpsModeCaps==TPositionModuleInfoExtended::EDeviceGpsModeNone)) + { + // Assume module supports hybrid if it has not reported its capabilities in module info file + iDeviceGpsModeCaps = TPositionModuleInfoExtended::EDeviceGpsModeSimultaneousTATB; + } + + + err = iLbsAdmin->Get(KLbsSettingMaximumExternalLocateRequests, iMaxNumSessions); + if (err != KErrNone) + { + iMaxNumSessions = KLbsDefaultMaxNumLocationRequests; + } + + iAgpsInterface = CAgpsInterfaceHandler::NewL(*this, *iLbsAdmin, iNetRegStatus); + + +#ifdef NRH_UNIT_TEST + // For testing use the Uid of the dummy NG + const TInt KTestNgUidInt = 0x1028226B; + const TUid KTestNgUid = {KTestNgUidInt}; + iProtocolModuleUid = KTestNgUid; +#else + ReadProtocolModuleAdminSetting(); +#endif + + iEmergencyFsm = CLbsPrivLocFsm::NewL(*this, KInvalidSessionId); + + // Reserve space for FSMs. Note "+1" because a pointer to the emergency Fsm gets added to this array + iFsmArray.ReserveL(iMaxNumSessions+1); + + CLbsAdmin::TSpecialFeature specialFeature(CLbsAdmin::ESpecialFeatureOff); + err = iLbsAdmin->Get(KLbsSpecialFeatureIntermediateFutileUpdate, specialFeature); + if (err != KErrNone) + { + LBSLOG_ERR2(ELogP3, "Failed to get KLbsSpecialFeatureIntermediateFutileUpdate (err %d)", err); + } + LBSLOG2(ELogP3, "Using KLbsSpecialFeatureIntermediateFutileUpdate = %d", specialFeature); + iSpecialFeatureIntermediateFutileUpdate = (specialFeature == CLbsAdmin::ESpecialFeatureOn) ? ETrue : EFalse; + +#ifdef SYMBIAN_FEATURE_MANAGER + iLocationManagementSupported = CFeatureDiscovery::IsFeatureSupportedL(NFeature::KLocationManagement); +#else + __ASSERT_ALWAYS(EFalse, User::Invariant()); // Would happen on older versions of symbian OS if this code ever backported +#endif + + // Get the CategoryUid from the cenrep file owned by LbsRoot for accessing Positioning Status P&S Keys + CRepository* rep = CRepository::NewLC(KLbsCenRepUid); + TInt posStatusCategory; + err = rep->Get(KNiPositioningStatusAPIKey, posStatusCategory); + User::LeaveIfError(err); + CleanupStack::PopAndDestroy(rep); + iPosStatusCategory = TUid::Uid(posStatusCategory); + } + + + +/** +Reads the Uid of a current Protocol Module from the Admin Settings. +*/ +void CPrivacyAndLocationHandler::ReadProtocolModuleAdminSetting() + { + LBSLOG(ELogP1, "CPrivacyAndLocationHandler::ReadProtocolModuleAdminSetting()"); + TLbsProtocolModuleId protUid(KLbsProtocolNullModuleId); + + TInt err = iLbsAdmin->Get(KLbsSettingHomeProtocolModule, protUid); + if (err != KErrNone) + { + LBSLOG_ERR2(ELogP4, "Failed to get KLbsSettingHomeProtocolModule (err %d)", err); + } + + iProtocolModuleUid = protUid; + } + +/** Compares sessionId for RPointerArray::Find(). +*/ +TBool CPrivacyAndLocationHandler::IsSessionIdEqual( + const TLbsNetSessionIdInt* aSessionId, + const CLbsPrivLocFsm& aFsm) + { + return (*aSessionId == aFsm.SessionId()); + } + +/** Compares session type for RPointerArray::Find(). +*/ +TBool CPrivacyAndLocationHandler::IsSessionTypeEqual( + const TLbsNetworkEnumInt::TLbsNetProtocolServiceInt* aSessionType, + const CLbsPrivLocFsm& aFsm) + { + return (*aSessionType == const_cast(aFsm).SessionType()); + } + +// ----------------------------------------------------------------------------- +// CPrivacyAndLocationHandler::LookupFsm +// Description: Lookup CLbsPrivLocFsm object by session ID. +// ----------------------------------------------------------------------------- +// +CLbsPrivLocFsm* CPrivacyAndLocationHandler::LookupFsm(const TLbsNetSessionIdInt& aSessionId) + { + LBSLOG2(ELogP3, "LookupFsm session=%d", aSessionId.SessionNum()); + + // Standard sessions always use the standard state machines. + TInt index = iFsmArray.Find(aSessionId, IsSessionIdEqual); + if (index >= 0) + { + LBSLOG(ELogP3, "LookupFsm: Existing standard FSM found"); + return iFsmArray[index]; + } + else + { + LBSLOG(ELogP3, "LookupFsm: No standard FSM found"); + return NULL; + } + } + +/** Get a new state machine to use for a new request. + +The state machine can either be re-using an existing FSM, +or allocating a new one from the heap or, for emergencies one thats was prepared earlier is used. +*/ +CLbsPrivLocFsm* CPrivacyAndLocationHandler::GetNewFsm( + const TLbsNetSessionIdInt& aSessionId, + TLbsNetworkEnumInt::TLbsNetProtocolServiceInt aSessionType, + TBool aEmergency) + { + LBSLOG2(ELogP3, "LookupFsm session=%d", aSessionId.SessionNum()); + + CLbsPrivLocFsm* fsm(NULL); + + // If this is an emergency request, use the emergency FSM + // Note, we only have to support ONE emergency at a time + // this implies that only one Protcol module may deal with emergencies + // So we do NOT support TWO emergencies .. one from each of the PMs + // Note: only MT-LR or NI-LR requests can be emergency requests. + if (aEmergency + && (aSessionType == MLbsNetworkProtocolObserver::EServiceMobileTerminated + || aSessionType == MLbsNetworkProtocolObserver::EServiceNetworkInduced)) + { + TInt index = iFsmArray.Find(iEmergencyFsm); + if (index >= 0) + { + iFsmArray.Remove(index); + iNumActiveSessions--; + } + // clean out Fsm + iEmergencyFsm->RefPosProcessed() = EFalse; + iEmergencyFsm->LocReqReceived() = EFalse; + iEmergencyFsm->LocationFixReceived()= EFalse; + iEmergencyFsm->TapMode() = EFalse; + iEmergencyFsm->WasPrivacyResponseReceivedStateExited() = EFalse; + iEmergencyFsm->NetSessionId()= aSessionId; + fsm = iEmergencyFsm; + } + else + { + if (iNumActiveSessions <= iMaxNumSessions) + { + // Create a new session to handle this privacy request + LBSLOG2(ELogP3, "Creating FSM for new standard request %d",aSessionId.SessionNum()); + TRAPD(err, fsm = CLbsPrivLocFsm::NewL(*this, aSessionId)); + if (err != KErrNone) + { + LBSLOG_ERR2(ELogP3, "Failed to create new FSM, error code : %d", err); + } + } + else + { + LBSLOG_ERR3(ELogP3, "Session start rejected! iNumActiveSessions=%d > iMaxNumSessions=%d", iNumActiveSessions, iMaxNumSessions); + } + } + + if (fsm) + { + // Add the state machine to the buffer. + iFsmArray.Append(fsm); + + iNumActiveSessions++; // conceptually, a session starts when a Fsm is created for it + + } + + return fsm; + } + + +// ----------------------------------------------------------------------------- +// CPrivacyAndLocationHandler::PrivacyHandler +// Description: Return a pointer to the privacy handler implementation +// (controller or notifier). +// ----------------------------------------------------------------------------- +// +CPrivacyHandler* CPrivacyAndLocationHandler::PrivacyHandler() + { + return iPrivacyHandler; + } + +// ----------------------------------------------------------------------------- +// CPrivacyAndLocationHandler::MessageSwitch +// Description: Return a pointer to the Network Gateway Message Switch +// ----------------------------------------------------------------------------- +// +CNGMessageSwitch* CPrivacyAndLocationHandler::MessageSwitch() + { + return iMessageSwitch; + } + +// ----------------------------------------------------------------------------- +// CPrivacyAndLocationHandler::LbsAdmin +// Description: Return a pointer to the Admin settings database +// ----------------------------------------------------------------------------- +// +CLbsAdmin* CPrivacyAndLocationHandler::LbsAdmin() + { + return iLbsAdmin; + } + +// ----------------------------------------------------------------------------- +// CPrivacyAndLocationHandler::SetServerObserver +// Description: Store a pointer to the NRH server which comunicates with the +// Privacy Controller. +// ----------------------------------------------------------------------------- +// +void CPrivacyAndLocationHandler::SetServerObserver(MLbsSessionObserver* aNrhServer) + { + PrivacyHandler()->SetServerObserver(aNrhServer); + } + +// ----------------------------------------------------------------------------- +// CPrivacyAndLocationHandler::OnRespondNetworkLocationRequest +// Description: Called by the Privacy Handler to report the result of a privacy +// check. Handling of the response is delegated to the current state. +// ----------------------------------------------------------------------------- +// +void CPrivacyAndLocationHandler::OnRespondNetworkLocationRequest(const TLbsNetSessionIdInt& aRequestId, + TLbsNetworkEnumInt::TLbsPrivacyResponseInt aRequestResult, + TInt aResponseReason) + { + LBSLOG2(ELogP3, "Received response %d to privacy request", aRequestResult); + CLbsPrivLocFsm* fsm = LookupFsm(aRequestId); + + if (NULL != fsm) + { + fsm->OnRespondNetworkLocationRequest(aRequestId, aRequestResult, aResponseReason); + } + else + { + LBSLOG_WARN(ELogP3, "Couldn't find a FSM with matching session Id"); + } + } + +// ----------------------------------------------------------------------------- +// CPrivacyAndLocationHandler::OnCancelNetworkLocationRequest +// Description: Called by the Privacy Handler to report that a privacy check +// has been rejected. This may occur after it has already been accepted. +// Handling of the response is delegated to the current state. +// ----------------------------------------------------------------------------- +// +void CPrivacyAndLocationHandler::OnCancelNetworkLocationRequest(const TLbsNetSessionIdInt& aRequestId) + { + LBSLOG2(ELogP3, "Received cancellation to privacy request %d", aRequestId.SessionNum()); + CLbsPrivLocFsm* fsm = LookupFsm(aRequestId); + + if (NULL != fsm) + { + fsm->OnCancelNetworkLocationRequest(aRequestId); + } + else + { + LBSLOG_WARN(ELogP3, "Couldn't find a FSM with matching session Id"); + } + } + +// ----------------------------------------------------------------------------- +// CPrivacyAndLocationHandler::OnMTLRRequest +// Description: The Message Switch has forwarded a request to start an MTLR +// session. +// Handling of the request is delegated to the current state. +// ----------------------------------------------------------------------------- +// +void CPrivacyAndLocationHandler::OnMTLRRequest(const TLbsNetSessionIdInt& aSessionId, + TLbsNetworkEnumInt::TLbsNetProtocolServiceInt aSessionType, + TBool aIsEmergency, + const TLbsExternalRequestInfo& aExternalRequestInfo, + const TLbsNetPosRequestPrivacyInt& aNetPosRequestPrivacy) + { + LBSLOG2(ELogP3, "Received privacy request with id %d", aSessionId.SessionNum()); + CLbsPrivLocFsm* fsm = LookupFsm(aSessionId); + + if (fsm==NULL) + { + fsm = GetNewFsm(aSessionId, aSessionType, aIsEmergency); + } + + if (NULL != fsm) + { + fsm->OnMTLRRequest(aSessionId, + aSessionType, + aIsEmergency, + aExternalRequestInfo, + aNetPosRequestPrivacy); + } + else + { + // Failed to create a state machine for this request, + // so simply reply with a privacy rejection. + iMessageSwitch->SendMTLRResponse(aSessionId, + TLbsNetworkEnumInt::EPrivacyResponseRejected, + KErrGeneral, EFalse); // can't be an emergency cuase we know we have a Fsm for these! + } + } + +// ----------------------------------------------------------------------------- +// CPrivacyAndLocationHandler::OnSessionComplete +// Description: The Message Switch has reported that the session is +// over (complete or aborted due to some error). +// Handling of the message is delegated to the current state. +// ----------------------------------------------------------------------------- +// +void CPrivacyAndLocationHandler::OnSessionComplete( + const TLbsNetSessionIdInt& aSessionId, + TInt aReason) + { + LBSLOG3(ELogP3, "Received Session Complete for id %d, reason %d", aSessionId.SessionNum(), aReason); + CLbsPrivLocFsm* fsm = LookupFsm(aSessionId); + + if (NULL != fsm) + { + fsm->OnSessionComplete(aSessionId, aReason); + + // The session complete marks the end of a session. + TInt index = iFsmArray.Find(fsm); + if (index != KErrNotFound) + { + + if (fsm->SessionType()== TLbsNetworkEnumInt::EServiceSelfLocation) + { + iMolRFsm = NULL; + } + else if (fsm->SessionType()== TLbsNetworkEnumInt::EServiceTransmitThirdParty) + { + iX3pFsm = NULL; + } + + // We should never delete the emergency FSM. + iFsmArray.Remove(index); + iNumActiveSessions--; + + if (fsm != iEmergencyFsm) + { + delete fsm; + } + } + } + else + { + LBSLOG_WARN(ELogP3, "Couldn't find a FSM with matching session Id"); + } + } + +// ----------------------------------------------------------------------------- +// CPrivacyAndLocationHandler::OnNetLocRequest +// Description: The Message Switch has passed on a request for a position update +// Handling of the request is delegated to the current state. +// ----------------------------------------------------------------------------- +// +void CPrivacyAndLocationHandler::OnNetLocRequest( + const TLbsNetSessionIdInt& aSessionId, + const TLbsNetPosRequestMethodInt& aPosRequestMethod, + TLbsNetworkEnumInt::TLbsNetProtocolServiceInt aSessionType, + TBool aIsEmergency, + const TLbsNetPosRequestQualityInt& aQuality) + { + LBSLOG2(ELogP3, "Received position update request for id %d", aSessionId.SessionNum()); + + TLbsNetSessionIdInt sessionId; + TPositionInfo posInfo; + TPosition pos; + TTime timeStamp; + TInt err; + + TBool tapMode = EFalse; + TInt numMethods = aPosRequestMethod.NumPosMethods(); + if (numMethods==1) + { + TLbsNetPosMethodInt netPosMethod; + aPosRequestMethod.GetPosMethod(0,netPosMethod); + + if (netPosMethod.PosMode()== (TPositionModuleInfo::ETechnologyNetwork | TPositionModuleInfo::ETechnologyAssisted)) + { + tapMode = ETrue; + } + } + + // This filtering used to be in the NG Message Switch, but has been moved + // here to get an access to the ref position bus + + if( (aSessionType == TLbsNetworkEnumInt::EServiceNetworkLocation) && !tapMode) + { + // A Network-based location request generates a location + // request to the network request handler, but there's no point + // passing it any further - the AGPS manager & privacy + // controller aren't interested. + // Simply return the saved reference location + err = iMessageSwitch->GetNetworkReferencePosition(aSessionId, posInfo); + posInfo.GetPosition(pos); + timeStamp = pos.Time(); + TLbsNetPosRequestQualityInt dummyQuality; + MessageSwitch()->SendNetLocResponse(aSessionId, err, dummyQuality, posInfo, timeStamp, EFalse); + } + else + { + // we note that a self locate MoLr session can be implicitly + // cancelled by the start of a new session for a new client. + // In this case we complete the session before creating a new + // fsm for the new client + CLbsPrivLocFsm* fsm = LookupFsm(aSessionId); + if (!fsm) + { + // here, we need to create a new fsm + // We note that only one self locate MolR (or X3p) is supported + // a new one will implicitly cancel any ongoing + if(aSessionType == TLbsNetworkEnumInt::EServiceSelfLocation) + { + if (iMolRFsm) + { + TInt index = iFsmArray.Find(iMolRFsm); + if (index != KErrNotFound) + { + iFsmArray.Remove(index); + iNumActiveSessions--; + delete iMolRFsm; + iMolRFsm = NULL; + } + } + + } + else if(aSessionType == TLbsNetworkEnumInt::EServiceTransmitThirdParty) + { + if (iX3pFsm) + { + TInt index = iFsmArray.Find(iX3pFsm); + if (index != KErrNotFound) + { + iFsmArray.Remove(index); + iNumActiveSessions--; + delete iX3pFsm; + iX3pFsm = NULL; + } + } + } + + fsm = GetNewFsm(aSessionId, aSessionType, aIsEmergency); + } + + if (NULL != fsm) + { + if(aSessionType == TLbsNetworkEnumInt::EServiceSelfLocation) + { + iMolRFsm = fsm; + } + else if(aSessionType == TLbsNetworkEnumInt::EServiceTransmitThirdParty) + { + iX3pFsm = fsm; + } + + fsm->OnNetLocRequest(aSessionId, + aPosRequestMethod, + aSessionType, + aIsEmergency, + aQuality); + } + else + { + // TODO: Return a dummy loc response with error code? + LBSLOG_WARN(ELogP3, "Couldn't find a FSM with matching session Id"); + } + } + } + +/** Called when a reference position arrives from the network. +*/ +void CPrivacyAndLocationHandler::OnNetLocReferenceUpdate( + const TLbsNetSessionIdInt& aSessionId, + const TPositionInfoBase& aPosInfo) + { + LBSLOG2(ELogP3, "Received reference position update for id %d", aSessionId.SessionNum()); + CLbsPrivLocFsm* fsm = LookupFsm(aSessionId); + + if (NULL != fsm) + { + fsm->OnNetLocReferenceUpdate(aSessionId, aPosInfo); + } + else + { + LBSLOG_WARN(ELogP3, "Couldn't find a FSM with matching session Id"); + } + } + +/** Callend when a final location arrives from the network. +*/ +void CPrivacyAndLocationHandler::OnNetLocFinalUpdate( + const TLbsNetSessionIdInt& aSessionId, + const TPositionInfoBase& aPosInfo) + { + LBSLOG2(ELogP3, "Received final network position update for id %d", aSessionId.SessionNum()); + CLbsPrivLocFsm* fsm = LookupFsm(aSessionId); + + if (NULL != fsm) + { + fsm->OnNetLocFinalUpdate(aSessionId, aPosInfo); + } + else + { + LBSLOG_WARN(ELogP3, "Couldn't find a FSM with matching session Id"); + } + } + +/** Callback when a GPS position update arrives from AGPS manager. +*/ +void CPrivacyAndLocationHandler::OnAgpsPositionUpdate( + TInt aReason, + const TPositionExtendedSatelliteInfo& aPosInfo, + const TTime& aTimeStamp) + { + // Broadcast the update to all state machines. + const TInt count = iFsmArray.Count(); + for (TInt i = 0; i < count; i++) + { + iFsmArray[i]->OnAgpsPositionUpdate(aReason, aPosInfo, aTimeStamp); + } + } + +/** Callback when a GPS measurement results update arrives from AGPS manager. +*/ +void CPrivacyAndLocationHandler::OnAgpsMeasurementUpdate( + TInt aReason, + const TPositionGpsMeasurementInfo& aPosInfo, + const TTime& aTimeStamp) + { + // Broadcast the update to all state machines + const TInt count = iFsmArray.Count(); + for (TInt i = 0; i < count; i++) + { + iFsmArray[i]->OnAgpsMeasurementUpdate(aReason, aPosInfo, aTimeStamp); + } + } + +/** +*/ +CAgpsInterfaceHandler* CPrivacyAndLocationHandler::AgpsHandler() + { + return iAgpsInterface; + } + +// ----------------------------------------------------------------------------- +// CPrivacyAndLocationHandler::DeviceGpsModeCaps +// Description: Return the device mode capabilities +// ----------------------------------------------------------------------------- +// +TPositionModuleInfoExtended::TDeviceGpsModeCapabilities CPrivacyAndLocationHandler::DeviceGpsModeCaps() + { + return iDeviceGpsModeCaps; + } + +// ----------------------------------------------------------------------------- +// CPrivacyAndLocationHandler::BehaviourMode +// Description: Return the behaviour mode setting +// ----------------------------------------------------------------------------- +// +CLbsAdmin::TLbsBehaviourMode CPrivacyAndLocationHandler::BehaviourMode() + { + return iLbsBehaviourMode; + } + +RLbsNetworkRegistrationStatus& CPrivacyAndLocationHandler::NetworkRegistrationStatus() + { + return iNetRegStatus; + } + +// increments the P&S key tracking mobile terminated positioning requests +void CPrivacyAndLocationHandler::IncrementPositioningStatus() + { + TInt count; + RProperty::Get(iPosStatusCategory, KLbsNiPositioningStatusKey, count); + RProperty::Set(iPosStatusCategory, KLbsNiPositioningStatusKey, count+1); + } + +// decrements the P&S key tracking mobile terminated positioning requests +// if location management is supported. In the alternative architecture, +// the NRH is not aware of the positioning session's progress, but is +// transient. Therefore the positioning status is set to zero in the +// class destructor. +void CPrivacyAndLocationHandler::DecrementPositioningStatus() + { + if (iLocationManagementSupported) + { + TInt count; + RProperty::Get(iPosStatusCategory, KLbsNiPositioningStatusKey, count); + if(count>0) + { + RProperty::Set(iPosStatusCategory, KLbsNiPositioningStatusKey, count-1); + } + else + { + LBSLOG_ERR(ELogP3, "CPrivacyAndLocationHandler::DecrementPositioningStatus() - Incorrect Positioning Status count\n"); + } + } + } + + +/** +*/ +MX3pStatusHandler& CPrivacyAndLocationHandler::X3pStatusHandler() + { + return *iAgpsInterface; + } + +/** Returns ETrue if KLbsSpecialFeatureIntermediateFutileUpdate is on. +@return ETrue if the special feature is on, EFalse otherwise. +*/ +TBool CPrivacyAndLocationHandler::IsSpecialFeatureIntermediateFutileUpdateOn() + { + return iSpecialFeatureIntermediateFutileUpdate; + } + +// ----------------------------------------------------------------------------- +// +// ----------------------- Class CLbsPrivLocStateBase -------------------- +// +// This class is not intended for instantiation. Implemented functions are +// those common to multiple derived states +// +// ----------------------------------------------------------------------------- +// + +// ----------------------------------------------------------------------------- +// CLbsPrivLocStateBase::OnCancelNetworkLocationRequest +// Description: Pass on a received privacy request cancel to the network gateway, +// if it relates to the current session. +// This behaviour is common to states EStateWaitLocationRequest, +// EStateWaitLocationUpdate and EStateWaitPrivacyResponse. +// Other states ignore the event. +// ----------------------------------------------------------------------------- +// +void CLbsPrivLocStateBase::OnCancelNetworkLocationRequest(const TLbsNetSessionIdInt& aSessionId) + { + /* Ignore the cancel if this is an emergency request */ + if(!iFsm->IsEmergency()) + { + // Also ignore it if the cancel doesn't relate to this session. + if(aSessionId == iFsm->SessionId()) + { + iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitCancelledByPrivacyController, KErrCancel); + iFsm->ChangeState(CLbsPrivLocFsm::EStateIdle, aSessionId); + } + } + } + +// ----------------------------------------------------------------------------- +// CLbsPrivLocStateBase::OnEntry +// Description: Handles initialisation actions which are common to multiple states. +// ----------------------------------------------------------------------------- +// +void CLbsPrivLocStateBase::OnEntry(const TPrivLocCommonParams& /* aStateParams */) + { + // Exit reason should always be explicitly set by a state, + // otherwise OnExit() will panic + iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitReasonNone, KErrNone); + } + + +// ----------------------------------------------------------------------------- +// CLbsPrivLocStateBase::OnExit +// Description: Handles exit actions which are common to multiple states. +// Any exit reason not handled here is delegated to the current state. +// ----------------------------------------------------------------------------- +// +TBool CLbsPrivLocStateBase::OnExit() + { + TBool consumed = ETrue; + switch(iFsm->iExitData.iExitReason) + { + case TPrivLocStateExitData::EExitSessionComplete: + { + // Tell the AGPS interface handle this location request has finished. + AgpsInterface()->StopPositioning(iFsm->SessionId()); + + // Tell the privacy controller this session is finished. + PrivacyHandler()->ProcessRequestComplete(iFsm->SessionId(), + iFsm->ExitData().iExitInfo); + break; + } + + case TPrivLocStateExitData::EExitCancelledByPrivacyController: + { + // Send a cancel to the network gateway + TPositionInfo dummyPosInfo; + TTime dummyTime; + TLbsNetPosRequestQualityInt dummyQuality; + MessageSwitch()->SendNetLocResponse(iFsm->SessionId(), + iFsm->ExitData().iExitInfo, + dummyQuality, + dummyPosInfo, + dummyTime, + iFsm->IsEmergency()); + } + break; + + case TPrivLocStateExitData::EExitLocReqReceived: + // No action required - request is issued on entry to next state. + case TPrivLocStateExitData::EExitPrivacyRequestReceived: + // No action required, state moves to waiting for loc request. + { + consumed = ETrue; + break; + } + + default: + { + // Don't know what to do with it. + consumed = EFalse; + break; + } + } + return(consumed); + } + +// ----------------------------------------------------------------------------- +// CLbsPrivLocStateBase::HandleLocRequest +// Description: Common handling of a location request received while the +// Privacy and Location Handler is dealing with a session. +// +// If the session type is anything but MTLR, then it is processed, otherwise +// a privacy request is generated +// ----------------------------------------------------------------------------- +// +void CLbsPrivLocStateBase::HandleLocRequest(const TLbsNetSessionIdInt& aSessionId, + const TLbsNetPosRequestMethodInt& aPosRequestMethod, + TLbsNetworkEnumInt::TLbsNetProtocolServiceInt aSessionType, + TBool aIsEmergency, + const TLbsNetPosRequestQualityInt& aQuality) + { + // MTLR. + if (aSessionType == TLbsNetworkEnumInt::EServiceMobileTerminated) + { + // An MTLR with out a prior privacy request is not supported, report error via + // RespondLocationRequest(dummy position). + TPositionInfo dummyPosInfo; + TTime dummyTime; + TLbsNetPosRequestQualityInt dummyQuality; + + MessageSwitch()->SendNetLocResponse(aSessionId, + KErrNotSupported, + dummyQuality, + dummyPosInfo, + dummyTime, aIsEmergency); + } + + // Network Induced. + else if (aSessionType == TLbsNetworkEnumInt::EServiceNetworkInduced) + { + // If a request for a position update has been received without + // a privacy request, then there's nothing to say how the user + // should be informed or what do do if there is no response. + // The safest thing is to get the user to confirm (verify) + // the request, and in the absence of confirmation to reject the + // request. For emergency requests we notify and accept. + + // Store the loc req. + iFsm->LocReqReceived() = ETrue; + + iFsm->IsEmergency() = aIsEmergency; + iFsm->NetRequestQuality() = aQuality; + iFsm->PosRequestMethod() = aPosRequestMethod; + + + // The following notification types are chosen based on the emergency and network requests admin status. + // + // Emergency = On, Admin = Any, gives ENotifyLocationAccepted + // Emergency = Off, Admin = On, gives ENotifyLocationAccepted + // Emergency = Off, Admin = OnButAlwayVerify, gives ENotifyAndVerifyLocationRejectedIfNoResponse + // Emergency = Off, Admin = Off, N/A the notifier or controller will not be called + // Emergency = Off, Admin = OffButNotify, gives ENotifyLocationRejected + TLbsNetPosRequestPrivacyInt requestPrivacy; + + requestPrivacy.SetRequestAdvice(TLbsNetPosRequestPrivacyInt::ERequestAdviceNotify); + requestPrivacy.SetRequestAction(TLbsNetPosRequestPrivacyInt::ERequestActionAllow); + + // Verifications are rejected after timeout. + CLbsAdmin::TExternalLocateService externalLocate(CLbsAdmin::EExternalLocateOff); + + ReadNetworkInducedAdminSetting(externalLocate); + if ((externalLocate == CLbsAdmin::EExternalLocateOnButAlwaysVerify) && (!aIsEmergency)) + { + requestPrivacy.SetRequestAdvice(TLbsNetPosRequestPrivacyInt::ERequestAdviceVerify); + requestPrivacy.SetRequestAction(TLbsNetPosRequestPrivacyInt::ERequestActionReject); + } + + // Similarly, default values have to be assigned to the external request info. + TLbsExternalRequestInfo requestInfo; + _LIT8(KUnknownExternalReqInfoField, ""); + requestInfo.SetRequesterId(KUnknownExternalReqInfoField); + requestInfo.SetClientName(KUnknownExternalReqInfoField); + requestInfo.SetClientExternalId(KUnknownExternalReqInfoField); + + + // Process the privacy request. + iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitLocReqReceived, KErrNone); + + TPrivLocWaitPrivResponseParams privacyRequestParams(aSessionId, aSessionType, requestInfo, requestPrivacy, aIsEmergency); + iFsm->ChangeState(CLbsPrivLocFsm::EStateWaitPrivacyResponse, privacyRequestParams); + } + + // All other location requests. + else + { + TPrivLocWaitLocationUpdateParams updateRequestParams(aSessionId, + aPosRequestMethod, + aSessionType, + aIsEmergency, + aQuality); + iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitSessionComplete, KErrCancel); + iFsm->ChangeState(CLbsPrivLocFsm::EStateWaitLocationUpdate, updateRequestParams); + } + } + +// ----------------------------------------------------------------------------- +// CLbsPrivLocStateBase::OnSessionComplete +// Description: Common handling of a session complete message received other +// than when it is expected as normal session completion. +// ----------------------------------------------------------------------------- +// +void CLbsPrivLocStateBase::OnSessionComplete(const TLbsNetSessionIdInt& aSessionId, + TInt aReason) + { + if(aSessionId == iFsm->SessionId()) + { + iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitSessionComplete, aReason); + iFsm->ChangeState(CLbsPrivLocFsm::EStateIdle, aSessionId); + } + } + +/** Called when a reference position arrives from the network. +*/ +void CLbsPrivLocStateBase::OnNetLocReferenceUpdate( + const TLbsNetSessionIdInt& /*aSessionId*/ , + const TPositionInfoBase& aPosInfo) + { + TLbsNetworkEnumInt::TLbsNetProtocolServiceInt sessionType = iFsm->SessionType(); + __ASSERT_DEBUG((sessionType != MLbsNetworkProtocolObserver::EServiceNone), Panic(ENrhPanicBadParamType)); + + if( ((sessionType == MLbsNetworkProtocolObserver::EServiceNetworkInduced) || + (sessionType == MLbsNetworkProtocolObserver::EServiceMobileTerminated))) + { + TPositionInfo posInfo = static_cast(aPosInfo); + + // Set the module Id and position mode for the reference position. + // These values are not 'real' values, since this position + // came directly from the network and not one of the location + // managers within LBS. + posInfo.SetModuleId(KLbsGpsLocManagerUid); + posInfo.SetPositionMode(TPositionModuleInfo::ETechnologyNetwork); + posInfo.SetPositionModeReason(EPositionModeReasonNone); + posInfo.SetUpdateType(EPositionUpdateGeneral); + + if (!iFsm->RefPosProcessed()) + { + iFsm->RefPosProcessed() = ETrue; + PrivacyHandler()->ProcessNetworkPositionUpdate(iFsm->SessionId(), posInfo); + } + + } + } + +/* Timer callback called when the MaxFixTime for a gps location update request has expired. + +The default action is to ignore this callback. Any state interested in it must +implement its own version. +*/ +void CLbsPrivLocStateBase::OnTimerEventL(TInt /*aTimerId*/) + { + } + + +// ----------------------------------------------------------------------------- +// CLbsPrivLocStateBase::ReadNetworkInducedAdminSetting +// Description: Determine the external location value from the admin settings for network induced location requests. +// ----------------------------------------------------------------------------- +// +void CLbsPrivLocStateBase::ReadNetworkInducedAdminSetting(CLbsAdmin::TExternalLocateService& aExternalLocateService) + { + CLbsAdmin::TExternalLocateService serviceStatus(CLbsAdmin::EExternalLocateOff); + RLbsNetworkRegistrationStatus::TLbsNetworkRegistrationStatus netRegStatus(RLbsNetworkRegistrationStatus::ENetworkRegistrationUnknown); + TInt err = LbsNetworkRegistrationStatus().GetNetworkRegistrationStatus(netRegStatus); + if (err == KErrNone) + { + switch (netRegStatus) + { + case RLbsNetworkRegistrationStatus::ERegisteredHomeNetwork: + { + err = LbsAdmin()->Get(KLbsSettingHomeNetworkInducedLocate, serviceStatus); + break; + } + case RLbsNetworkRegistrationStatus::ERegisteredRoamingNetwork: + case RLbsNetworkRegistrationStatus::ENotRegistered: + { + err = LbsAdmin()->Get(KLbsSettingRoamingNetworkInducedLocate, serviceStatus); + break; + } + case RLbsNetworkRegistrationStatus::ENetworkRegistrationUnknown: + default: + { + LBSLOG_WARN2(ELogP4, "Unrecognised TLbsNetworkRegistrationStatus (%d), defaulting to EExternalLocateOff", + netRegStatus); + serviceStatus = CLbsAdmin::EExternalLocateOff; + break; + } + } + } + else + { + LBSLOG_WARN2(ELogP4, "Failed to get TExternalLocateService, couldn't read roaming status (err %d), defaulting to EExternalLocateOff", + err); + } + + aExternalLocateService = serviceStatus; + } + +// ----------------------------------------------------------------------------- +// CLbsPrivLocStateBase::CLbsPrivLocStateBase +// Description: Constructor +// ----------------------------------------------------------------------------- +// +CLbsPrivLocStateBase::CLbsPrivLocStateBase(CLbsPrivLocFsm* aFsm) +: iFsm(aFsm) + { + } +// ----------------------------------------------------------------------------- +// CLbsPrivLocStateBase::PrivacyHandler, MessageSwitch, LbsAdmin +// Description: Allows concrete states access to NRH resources passed to +// the FSM +// Returns: pointers. +// ----------------------------------------------------------------------------- +// +CPrivacyHandler* CLbsPrivLocStateBase::PrivacyHandler() + { + return iFsm->PrivLocHandler().PrivacyHandler(); + } +CNGMessageSwitch* CLbsPrivLocStateBase::MessageSwitch() + { + return iFsm->PrivLocHandler().MessageSwitch(); + } +CLbsAdmin* CLbsPrivLocStateBase::LbsAdmin() + { + return iFsm->PrivLocHandler().LbsAdmin(); + } +CAgpsInterfaceHandler* CLbsPrivLocStateBase::AgpsInterface() + { + return iFsm->PrivLocHandler().AgpsHandler(); + } + + +TPositionModuleInfoExtended::TDeviceGpsModeCapabilities CLbsPrivLocStateBase::DeviceGpsModeCaps() + { + return iFsm->PrivLocHandler().DeviceGpsModeCaps(); + } + +CLbsAdmin::TLbsBehaviourMode CLbsPrivLocStateBase::BehaviourMode() + { + return iFsm->PrivLocHandler().BehaviourMode(); + } + +RLbsNetworkRegistrationStatus& CLbsPrivLocStateBase::LbsNetworkRegistrationStatus() + { + return iFsm->PrivLocHandler().NetworkRegistrationStatus(); + } + +/* + * increments the network initiated positioning status count + * and remembers that it has done + */ +void CLbsPrivLocStateBase::IncrementPositioningStatus() + { + iFsm->PrivLocHandler().IncrementPositioningStatus(); + iFsm->WasPositioningStatusIncremented() = ETrue; + } + + +// ----------------------------------------------------------------------------- +// +// ----------------------- Class CLbsPrivLocIdleState -------------------- +// +// Implements the Idle state of the Privacy and Location Request Handler +// +// ----------------------------------------------------------------------------- +// + +// ----------------------------------------------------------------------------- +// CLbsPrivLocIdleState::NewL +// Description: CLbsPrivLocIdleState static constructor +// ----------------------------------------------------------------------------- +// +CLbsPrivLocIdleState* CLbsPrivLocIdleState::NewL(CLbsPrivLocFsm* aFsm) + { + return new (ELeave) CLbsPrivLocIdleState(aFsm); + } + +// ----------------------------------------------------------------------------- +// CLbsPrivLocIdleState::CLbsPrivLocIdleState +// Description: CLbsPrivLocIdleState constructor. +// ----------------------------------------------------------------------------- +// +CLbsPrivLocIdleState::CLbsPrivLocIdleState(CLbsPrivLocFsm* aFsm) +: CLbsPrivLocStateBase(aFsm) + { + } + +// ----------------------------------------------------------------------------- +// CLbsPrivLocIdleState::OnEntry +// Description: Carries out tasks required on entry to the state. +// ----------------------------------------------------------------------------- +// +void CLbsPrivLocIdleState::OnEntry(const TPrivLocCommonParams& aStateParams) + { + CLbsPrivLocStateBase::OnEntry(aStateParams); + } + +// ----------------------------------------------------------------------------- +// CLbsPrivLocIdleState::OnExit +// Description: Carries out tasks required on exit from the state. +// Panics if the exit reason is not handled by the base state exit +// ----------------------------------------------------------------------------- +// +TBool CLbsPrivLocIdleState::OnExit() + { + TBool consumed = CLbsPrivLocStateBase::OnExit(); + // If the exit reason wasn't handled, panic (should only happen in development) + __ASSERT_DEBUG(consumed, Panic(ENrhPanicIdleUnknownExitReason)); + + return(consumed); + } + +// ----------------------------------------------------------------------------- +// CLbsPrivLocIdleState::OnNetLocRequest +// Description: The Message Switch has forwarded a request for a control +// measurement. +// If the session type is anything but MTLR, then it is processed, otherwise +// a privacy request is generated +// ----------------------------------------------------------------------------- +// +void CLbsPrivLocIdleState::OnNetLocRequest( + const TLbsNetSessionIdInt& aSessionId, + const TLbsNetPosRequestMethodInt& aPosRequestMethod, + TLbsNetworkEnumInt::TLbsNetProtocolServiceInt aSessionType, + TBool aIsEmergency, + const TLbsNetPosRequestQualityInt& aQuality) + { + iFsm->SessionType() = aSessionType; + if(iFsm->WasPrivacyResponseReceivedStateExited()) + { + // The request relates to a rejected privacy request + // or a request for this session which has already been answered. + // In either case, it should be refused. The message is sent to the + // network gateway as a part of exit from the state, but we want to + // remain in Idle state. + iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitCancelledByPrivacyController, KErrAccessDenied); + iFsm->ChangeState(CLbsPrivLocFsm::EStateIdle, aSessionId); + } + else + { + TInt numMethods = aPosRequestMethod.NumPosMethods(); + if (numMethods==1) + { + TLbsNetPosMethodInt netPosMethod; + aPosRequestMethod.GetPosMethod(0,netPosMethod); + + if (netPosMethod.PosMode()== (TPositionModuleInfo::ETechnologyNetwork | TPositionModuleInfo::ETechnologyAssisted)) + { + iFsm->TapMode() = ETrue; + } + } + + + if ((aSessionType != MLbsNetworkProtocolObserver::EServiceMobileTerminated) && + (aSessionType != MLbsNetworkProtocolObserver::EServiceNetworkInduced)) + { + iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitLocReqReceived, KErrNone); + TPrivLocWaitLocationUpdateParams updateRequestParams(aSessionId, + aPosRequestMethod, + aSessionType, + aIsEmergency, + aQuality); + iFsm->ChangeState(CLbsPrivLocFsm::EStateWaitLocationUpdate, updateRequestParams); + } + else + { + // It's a request for a different session. Need to find out what to do with it. + HandleLocRequest(aSessionId, aPosRequestMethod, + aSessionType,aIsEmergency, + aQuality); + } + } + } + +// ----------------------------------------------------------------------------- +// CLbsPrivLocIdleState::OnMTLRRequest +// Description: The Message Switch has forwarded a request for a location update +// (a privacy request) +// ----------------------------------------------------------------------------- +// +void CLbsPrivLocIdleState::OnMTLRRequest(const TLbsNetSessionIdInt& aSessionId, + TLbsNetworkEnumInt::TLbsNetProtocolServiceInt aSessionType, + TBool aIsEmergency, + const TLbsExternalRequestInfo& aExternalRequestInfo, + const TLbsNetPosRequestPrivacyInt& aNetPosRequestPrivacy) + { + iFsm->SessionType() = aSessionType; + iFsm->ExternalRequestType() = aExternalRequestInfo.RequestType(); + iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitPrivacyRequestReceived, KErrNone); + TPrivLocWaitPrivResponseParams privacyRequestParams( aSessionId, + aSessionType, + aExternalRequestInfo, + aNetPosRequestPrivacy, + aIsEmergency); + iFsm->ChangeState(CLbsPrivLocFsm::EStateWaitPrivacyResponse, privacyRequestParams); + } + +/** Called when a reference position arrives from the network. + * +*/ +void CLbsPrivLocIdleState::OnNetLocReferenceUpdate( + const TLbsNetSessionIdInt& /*aSessionId*/, + const TPositionInfoBase& /* aPosInfo */) + { + // note that the reference postion is stored by the message switch + // so here we don't need to save it again! + } + +// ----------------------------------------------------------------------------- +// +// ----------------------- Class CLbsPrivLocWaitPrivRespState -------------------- +// +// Implements the Idle state of the Privacy and Location Request Handler +// +// ----------------------------------------------------------------------------- +// + +// ----------------------------------------------------------------------------- +// CLbsPrivLocWaitPrivRespState::NewL +// Description: CLbsPrivLocIdleState static constructor +// ----------------------------------------------------------------------------- +// +CLbsPrivLocWaitPrivRespState* CLbsPrivLocWaitPrivRespState::NewL(CLbsPrivLocFsm* aFsm) + { + return new (ELeave) CLbsPrivLocWaitPrivRespState(aFsm); + } + +// ----------------------------------------------------------------------------- +// CLbsPrivLocWaitPrivRespState::CLbsPrivLocWaitPrivRespState +// Description: CLbsPrivLocWaitPrivRespState constructor. +// ----------------------------------------------------------------------------- +// +CLbsPrivLocWaitPrivRespState::CLbsPrivLocWaitPrivRespState(CLbsPrivLocFsm* aFsm) +: CLbsPrivLocStateBase(aFsm) + { + } + +// ----------------------------------------------------------------------------- +// CLbsPrivLocWaitPrivRespState::OnEntry +// Description: Actions performed when the state is entered. +// Unpack the parameters and issue the privacy request. +// ----------------------------------------------------------------------------- +// +void CLbsPrivLocWaitPrivRespState::OnEntry(const TPrivLocCommonParams& aStateParams) + { + CLbsPrivLocStateBase::OnEntry(aStateParams); + const TPrivLocWaitPrivResponseParams& params = TPrivLocWaitPrivResponseParams::Cast(const_cast(aStateParams)); + iFsm->SessionType() = params.iSessionType; + iFsm->IsEmergency() = params.iIsEmergency; + + PrivacyHandler()->ProcessNetworkLocationRequest(iFsm->SessionId(), + iFsm->SessionType(), + params.iExternalRequestInfo, + params.iNetPosRequestPrivacy, + iFsm->IsEmergency()); + } + +// ----------------------------------------------------------------------------- +// CLbsPrivLocWaitPrivRespState::OnExit +// Description: Actions performed on leaving the state. +// ----------------------------------------------------------------------------- +// +TBool CLbsPrivLocWaitPrivRespState::OnExit() + { + TInt consumed = EFalse; + switch(iFsm->ExitData().iExitReason) + { + case TPrivLocStateExitData::EExitPrivacyResponseReceived: + { + // Remember that we exited the privacy response received state + // so that we can deny the network location requests in the idle staet. + + iFsm->WasPrivacyResponseReceivedStateExited() = ETrue; + + + // For the NI case a Reference position may have arrived by now + // So we must pass this onto the privacy handler. + + if (iFsm->SessionType() == MLbsNetworkProtocolObserver::EServiceNetworkInduced) + { + if (iFsm->PrivacyResponse() == CLbsNetworkProtocolBase::EPrivacyResponseAccepted) + { + TPositionInfo posInfo; + TInt err = MessageSwitch()->GetNetworkReferencePosition(iFsm->SessionId(), posInfo); + if (KErrNone == err) + { + if (!iFsm->RefPosProcessed()) + { + iFsm->RefPosProcessed() = ETrue; + PrivacyHandler()->ProcessNetworkPositionUpdate(iFsm->SessionId(), posInfo); + } + + } + + } + } + + // For MtLrs the Protocol module should not + // send a REF position until after we have sent the Priv response to the PM + + // Inform network of the privacy response for normal privacy requests. + if (iFsm->SessionType() == TLbsNetworkEnumInt::EServiceMobileTerminated) + { + MessageSwitch()->SendMTLRResponse(iFsm->SessionId(), iFsm->PrivacyResponse(), iFsm->PrivacyResponseReason(), iFsm->IsEmergency()); + } + + // Inform network of a rejected privacy response via a "RespondLocationRequest" for faked privacy requests (generated internaly). + else if ((iFsm->SessionType() == TLbsNetworkEnumInt::EServiceNetworkInduced) && (iFsm->PrivacyResponse() == TLbsNetworkEnumInt::EPrivacyResponseRejected)) + { + // The faked privacy request was rejected, so reject the location request. + TPositionInfo dummyPosInfo; + TTime dummyTime; + TLbsNetPosRequestQualityInt dummyQuality; + + MessageSwitch()->SendNetLocResponse(iFsm->SessionId(), + KErrAccessDenied, + dummyQuality, + dummyPosInfo, + dummyTime, + iFsm->IsEmergency()); + } + + consumed = ETrue; + break; + } + + case TPrivLocStateExitData::EExitCancelledByPrivacyController: + { + // Send a cancel to the network gateway + iFsm->PrivacyResponse() = TLbsNetworkEnumInt::EPrivacyResponseRejected; + iFsm->PrivacyResponseReason() = KErrCancel; + MessageSwitch()->SendMTLRResponse(iFsm->SessionId(), iFsm->PrivacyResponse(), iFsm->PrivacyResponseReason(), iFsm->IsEmergency()); + consumed = ETrue; + } + break; + + default: + { + consumed = CLbsPrivLocStateBase::OnExit(); + // If the exit reason wasn't handled, panic (should only happen in development) + __ASSERT_DEBUG(consumed, Panic(ENrhPanicWaitPrivRespUnknownExitReason)); + break; + } + } + + iFsm->LocReqReceived() = EFalse; + + return(consumed); + } + +// ----------------------------------------------------------------------------- +// CLbsPrivLocWaitPrivRespState::OnRespondNetworkLocationRequest +// Description: Pass on a received privacy response to the network gateway, if +// it relates to the current session. +// ----------------------------------------------------------------------------- +// +void CLbsPrivLocWaitPrivRespState::OnRespondNetworkLocationRequest( + const TLbsNetSessionIdInt& aSessionId, + TLbsNetworkEnumInt::TLbsPrivacyResponseInt aRequestResult, + TInt /* aResponseReason*/) + { + + if(aSessionId == iFsm->SessionId()) + { + iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitPrivacyResponseReceived, KErrNone); + iFsm->PrivacyResponse() = aRequestResult; + if(iFsm->PrivacyResponse() == TLbsNetworkEnumInt::EPrivacyResponseAccepted) + { + // Tell the AGPS handler that we are going to start a location request soon. + AgpsInterface()->PreStartPositioning(iFsm->SessionId(), iFsm->IsEmergency()); + + // Set the Positioning Status for the UI indicator. + // Not done for silent requests. + if (iFsm->ExternalRequestType() < TLbsExternalRequestInfo::ERequestSingleShotSilent) + { + IncrementPositioningStatus(); + } + + if(iFsm->LocReqReceived()) + { + TPrivLocWaitLocationUpdateParams updateRequestParams(iFsm->SessionId(), + iFsm->PosRequestMethod(), + iFsm->SessionType(), + iFsm->IsEmergency(), + iFsm->NetRequestQuality()); + iFsm->ChangeState(CLbsPrivLocFsm::EStateWaitLocationUpdate, updateRequestParams); + } + else + { + TPrivLocWaitLocationRequestParams locationRequestParams(iFsm->SessionId(), + iFsm->IsEmergency(), + EFalse); + iFsm->ChangeState(CLbsPrivLocFsm::EStateWaitLocationRequest, locationRequestParams); + } + } + else + { + iFsm->ChangeState(CLbsPrivLocFsm::EStateIdle, aSessionId); + } + } + } + +// ----------------------------------------------------------------------------- +// CLbsPrivLocWaitPrivRespState::OnNetLocRequest +// Description: The Message Switch has forwarded a request for a control +// measurement. +// If the session Id is the same as the current one, then save the parameters +// so that the request can be issued when privacy is accepted. +// Otherwise (the session Id is different) a cancel is implied and we cancel +// the current session and start another, which may or may not require a new +// privacy query. +// ----------------------------------------------------------------------------- +// +void CLbsPrivLocWaitPrivRespState::OnNetLocRequest( + const TLbsNetSessionIdInt& aSessionId, + const TLbsNetPosRequestMethodInt& aPosRequestMethod, + TLbsNetworkEnumInt::TLbsNetProtocolServiceInt aSessionType, + TBool aIsEmergency, + const TLbsNetPosRequestQualityInt& aQuality) + { + TInt numMethods = aPosRequestMethod.NumPosMethods(); + if (numMethods==1) + { + TLbsNetPosMethodInt netPosMethod; + aPosRequestMethod.GetPosMethod(0,netPosMethod); + + if (netPosMethod.PosMode()== (TPositionModuleInfo::ETechnologyNetwork | TPositionModuleInfo::ETechnologyAssisted)) + { + iFsm->TapMode() = ETrue; + } + } + if(aSessionId == iFsm->SessionId() && + aIsEmergency == iFsm->IsEmergency() && + aSessionType == iFsm->SessionType()) + { + iFsm->PosRequestMethod() = aPosRequestMethod; + iFsm->NetRequestQuality() = aQuality; + iFsm->LocReqReceived() = ETrue; + } + else + { + // It's a request for different session. Need to find out what to do with it. + HandleLocRequest(aSessionId,aPosRequestMethod, + aSessionType,aIsEmergency, + aQuality); + } + } + + +void CLbsPrivLocWaitPrivRespState::OnMTLRRequest(const TLbsNetSessionIdInt& /*aSessionId*/, + TLbsNetworkEnumInt::TLbsNetProtocolServiceInt /*aSessionType*/, + TBool /*aIsEmergency*/, + const TLbsExternalRequestInfo& /*aExternalRequestInfo*/, + const TLbsNetPosRequestPrivacyInt& /*aNetPosRequestPrivacy*/) + { + // this can never happen. If the Fsm is in the WaitPrivRespState then + // any arrival of a MTLR request would start a new session (no implicit cancel!) + // and the OnMTLRRequest()would be directed to that session not this one + __ASSERT_DEBUG(EFalse, Panic(ENrhPanicBadParamType)); + } + +/** Called when a reference position arrives from the network. + * +*/ +void CLbsPrivLocWaitPrivRespState::OnNetLocReferenceUpdate( + const TLbsNetSessionIdInt& /*aSessionId*/, + const TPositionInfoBase& /*aPosInfo*/) + { + // note that the reference postion is stored by the message switch + // so here we don't need to save it again! + } + + +// ----------------------------------------------------------------------------- +// +// ----------------------- Class CLbsPrivLocWaitLocUpdateState -------------------- +// +// Implements the Wait For Location Update state of the Privacy and Location +// Request Handler +// +// On entry, issues a location update request then starts a timer and waits for +// a response. +// +// ----------------------------------------------------------------------------- +// + +// ----------------------------------------------------------------------------- +// CLbsPrivLocWaitLocUpdateState::NewL +// Description: CLbsPrivLocWaitLocUpdateState static constructor +// ----------------------------------------------------------------------------- +// +CLbsPrivLocWaitLocUpdateState* CLbsPrivLocWaitLocUpdateState::NewL(CLbsPrivLocFsm* aFsm) + { + CLbsPrivLocWaitLocUpdateState* self; + self = new (ELeave) CLbsPrivLocWaitLocUpdateState(aFsm); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return(self); + } + +// ----------------------------------------------------------------------------- +// CLbsPrivLocWaitLocUpdateState::CLbsPrivLocWaitLocUpdateState +// Description: CLbsPrivLocWaitLocUpdateState constructor. +// ----------------------------------------------------------------------------- +// +CLbsPrivLocWaitLocUpdateState::CLbsPrivLocWaitLocUpdateState(CLbsPrivLocFsm* aFsm) +: CLbsPrivLocStateBase(aFsm) + { + } + +// ----------------------------------------------------------------------------- +// CLbsPrivLocWaitLocUpdateState::~CLbsPrivLocWaitLocUpdateState +// Description: CLbsPrivLocWaitLocUpdateState destructor. +// ----------------------------------------------------------------------------- +// +CLbsPrivLocWaitLocUpdateState::~CLbsPrivLocWaitLocUpdateState() + { + } + +// ----------------------------------------------------------------------------- +// CLbsPrivLocIdleState::ConstructL +// Description: CLbsPrivLocIdleState second-phase constructor. +// ----------------------------------------------------------------------------- +// +void CLbsPrivLocWaitLocUpdateState::ConstructL() + { + } + + +// ----------------------------------------------------------------------------- +// CLbsPrivLocWaitLocUpdateState::OnEntry +// Description: Carries out tasks required on entry to the state. +// Issues the location update request and starts a timer. +// ----------------------------------------------------------------------------- +// +void CLbsPrivLocWaitLocUpdateState::OnEntry(const TPrivLocCommonParams& aStateParams) + { + TInt err(KErrNone); + + CLbsPrivLocStateBase::OnEntry(aStateParams); + const TPrivLocWaitLocationUpdateParams& params = TPrivLocWaitLocationUpdateParams::Cast(aStateParams); + iFsm->IsEmergency() = params.iIsEmergency; + iFsm->SessionType() = params.iSessionType; + iFsm->PosRequestMethod() = params.iPosRequestMethod; + + // If the network has not specified a positioning method, get the default + // one from the admin settings. + TLbsNetPosMethodInt netReqMethod; + iFsm->PosRequestMethod().GetPosMethod(0, netReqMethod); + if (iFsm->PosRequestMethod().NumPosMethods() == 1 + && (netReqMethod.PosMode() == TPositionModuleInfo::ETechnologyUnknown)) + { + AgpsInterface()->GetDefaultPosMethod(iFsm->PosRequestMethod()); + } + + // We may use two sources for the required quality for the + // new location request, either: + // 1) The quality from the network (aQuality) + // 2) The quality defined in a quality profile (which profile to + // use depends on the service type, e.g. MT-LR or X3P) + // + // We decide which to use based on the required quality from the network. + // Any invalid/unsupplied parameter is read from the quality profile + // for the ocation request type. + TBool maxFixTimeRequired = params.iQuality.MaxFixTime() == 0; + TBool minVerticalAccuracyRequired = + Math::IsNaN(params.iQuality.MinVerticalAccuracy()); + TBool minHorizontalAccuracyRequired = + Math::IsNaN(params.iQuality.MinHorizontalAccuracy()); + + if (maxFixTimeRequired || minVerticalAccuracyRequired || minHorizontalAccuracyRequired) + { + // Select which LbsAdmin setting to use for the + // quality profile Id based on the type of location + // request. + TLbsAdminSetting adminSetting(KLbsSettingNone); + switch (iFsm->SessionType()) + { + case TLbsNetworkEnumInt::EServiceMobileTerminated: + case TLbsNetworkEnumInt::EServiceNetworkInduced: + { + adminSetting = KLbsSettingQualityProfileExternalLocate; + break; + } + case TLbsNetworkEnumInt::EServiceTransmitThirdParty: + { + adminSetting = KLbsSettingQualityProfileTransmitLocate; + break; + } + case TLbsNetworkEnumInt::EServiceTriggeredMolr: + // SUPL 2.0 "Triggered MOLR" request uses Self Locate Quality Profile + case TLbsNetworkEnumInt::EServiceNetworkLocation: + // This type of request should only get here in the case of a TA MOLR. Treat as Self-Locate + case TLbsNetworkEnumInt::EServiceSelfLocation: + { + adminSetting = KLbsSettingQualityProfileSelfLocate; + break; + } + default: + { + // We must not fail if it is an emergency request + if (!iFsm->IsEmergency()) + { + LBSLOG2(ELogP3, + "Unable to select quality profile for TLbsNetProtocolService (%d), using quality data from network instead.", + iFsm->SessionType()); + __ASSERT_DEBUG(EFalse, Panic(ENrhPanicNoQualityProfile)); + } + else + { + adminSetting = KLbsSettingQualityProfileExternalLocate; + } + } + } + + // Retrieve the Id of the quality profile to use + TLbsQualityProfileId profileId(KLbsNullQualityProfileId); + if (adminSetting != KLbsSettingNone) + { + LbsAdmin()->Get(adminSetting, profileId); + } + + // Retrieve the data for the quality profile + TQualityProfile qualityProfile; + err = LbsQualityProfile::GetQualityProfileById(profileId, qualityProfile); + if (err == KErrNone) + { + // Use the quality data from the quality profile for any missing/invalid data + if(maxFixTimeRequired) + { + iFsm->GpsRequestQuality().SetMaxFixTime(qualityProfile.MaxFixTime()); + } + else + { + iFsm->GpsRequestQuality().SetMaxFixTime(params.iQuality.MaxFixTime()); + } + if(minHorizontalAccuracyRequired) + { + iFsm->GpsRequestQuality().SetMinHorizontalAccuracy(qualityProfile.MinHorizontalAccuracy()); + } + else + { + iFsm->GpsRequestQuality().SetMinHorizontalAccuracy(params.iQuality.MinHorizontalAccuracy()); + } + if(minVerticalAccuracyRequired) + { + iFsm->GpsRequestQuality().SetMinVerticalAccuracy(qualityProfile.MinVerticalAccuracy()); + } + else + { + iFsm->GpsRequestQuality().SetMinVerticalAccuracy(params.iQuality.MinVerticalAccuracy()); + } + } + else + { + // We should not fail if we are emergency + if (!iFsm->IsEmergency()) + { + // We couldn't find the quality profile with the given Id. + // This is an error, so reject the location request. + TPositionInfo dummyPosInfo; + TTime dummyTime; + TLbsNetPosRequestQualityInt dummyQuality; + MessageSwitch()->SendNetLocResponse(iFsm->SessionId(), + KErrAccessDenied, + dummyQuality, + dummyPosInfo, + dummyTime, + iFsm->IsEmergency()); + + // if this location request is the result of a privacy request, + // then notify the privacy handler of the error + if ((params.iSessionType == TLbsNetworkEnumInt::EServiceMobileTerminated) || + (params.iSessionType == TLbsNetworkEnumInt::EServiceNetworkInduced)) + { + iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitSessionComplete, KErrAccessDenied); + } + else + { + iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitBadQualityProfile, KErrNone); + } + + // Whatever the result, this session is finished, so return to idle. + iFsm->ChangeState(CLbsPrivLocFsm::EStateIdle, iFsm->SessionId()); + return; + } // if (!iIsEmergency) + else + { + // Just set some defaults + TTimeIntervalMicroSeconds timeout(30000000); + iFsm->GpsRequestQuality().SetMinHorizontalAccuracy(50); + iFsm->GpsRequestQuality().SetMinVerticalAccuracy(1000); + iFsm->GpsRequestQuality().SetMaxFixTime(timeout); + } + } + } + else + { + // Use the quality parameters supplied with the request. + iFsm->GpsRequestQuality().SetMinHorizontalAccuracy(params.iQuality.MinHorizontalAccuracy()); + iFsm->GpsRequestQuality().SetMinVerticalAccuracy(params.iQuality.MinVerticalAccuracy()); + iFsm->GpsRequestQuality().SetMaxFixTime(params.iQuality.MaxFixTime()); + } + + + // Check for any existing position updates in case they meet the + // MaxFixAge and quality requirements for this request. + TInt updateReason; + err = AgpsInterface()->GetPosition(updateReason, + iFsm->GpsPosition(), + iFsm->ActualTime()); + if (err == KErrNone) + { + TPrivLocWaitLocationRequestParams locationRequestParams(iFsm->SessionId(), + iFsm->IsEmergency(), + EFalse, + updateReason); + + // Check the existing update in case it meets the MaxFixAge and quality requirements for this request. + if (params.iQuality.MaxFixAge() > 0) + { + TTime now; + now.UniversalTime(); + TTimeIntervalMicroSeconds age(Max((now.Int64() - iFsm->ActualTime().Int64()), TInt64(0))); + if (updateReason == KErrNone + && (age <= params.iQuality.MaxFixAge()) + && ReceivedFixIsAccurate()) + { + // Accurate update that is within the MaxFixAge time limit, + // so return it straight away. + iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitLocFixReceived, updateReason); + iFsm->ChangeState(CLbsPrivLocFsm::EStateWaitLocationRequest, locationRequestParams); + return; + } + } + + + // Special feature behaviour! + // If the admin setting KLbsSpecialFeatureIntermediateFutileUpdate is on, + // it means that we should check to see if a futile update has happened + // since the first location request of this session. This might happen + // in a hybrid session, if the GPS module sends a futile update when there + // is no outstanding location request in the NRH. E.g. in the gap between + // sending the response for one hybrid loc request and getting the next + // loc request from the network. + // + // Note: This only really applies to hybrid of TA position modes, because + // in TB or autonomous you only have one location request per + // session. + else if (iFsm->IsSpecialFeatureIntermediateFutileUpdateOn()) + { + // If this is the first request for a new sessionId, record the current session id. + // We need to know this for terminal assisted or hybrid requests, in case + // we need to check for a futile update that has happened in the gap between + // one location response and the next location update request. + if (iFsm->LastLocReqSessionId() != iFsm->SessionId()) + { + iFsm->LastLocReqSessionId() = iFsm->SessionId(); + } + else + { + // Before sending the location request, see if a futile update has + // happened since the start of the session (in general only terminal-assisted + // and hybrid requests should have more than one location request + // per session, however the SUPL PM will have more than one for all request modes). + TGpsRequestMode gpsMode = AgpsInterface()->ConvertPosMethodToGpsRequestMode(iFsm->PosRequestMethod()); + if ((updateReason == KPositionCalculationFutile) && + ((gpsMode == EGpsRequestModeTerminalAssisted) || (gpsMode == EGpsRequestModeHybrid))) + { + // Return last measurement straight away. + iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitLocMeasurementResultsReceived, updateReason); + iFsm->ChangeState(CLbsPrivLocFsm::EStateWaitLocationRequest, locationRequestParams); + return; + } + } + } + } + + + // Issue the request and supply pointers to the data to be updated + iFsm->LocationFixReceived() = EFalse; + iFsm->MeasurementInfoReceived() = EFalse; + err = AgpsInterface()->StartPositioning(iFsm->SessionId(), + iFsm->PosRequestMethod(), + iFsm->GpsRequestQuality(), + iFsm->IsEmergency()); + if (KErrNone == err) + { + iFsm->LocationUpdateTimer().EventAfter(iFsm->GpsRequestQuality().MaxFixTime(), 1); + iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitReasonNone, KErrNone); + } + else + { + // Error sending the location request, send a location response + // with the error and go to Idle state. + iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitBadLocationRequest, err); + iFsm->ChangeState(CLbsPrivLocFsm::EStateIdle, iFsm->SessionId()); + } + } + +// ----------------------------------------------------------------------------- +// CLbsPrivLocWaitLocUpdateState::OnExit +// Description: Carries out tasks required on exit from the state. +// Cancels the location update request and stops the timer. +// ----------------------------------------------------------------------------- +// +TBool CLbsPrivLocWaitLocUpdateState::OnExit() + { + // Cancel the update timer. + iFsm->LocationUpdateTimer().Cancel(); + + TInt consumed = EFalse; + switch(iFsm->ExitData().iExitReason) + { + case TPrivLocStateExitData::EExitLocFixReceived: + { + // Don't cancel the location request yet, but tell the AGPS interface + // handler to put it on 'hold'. If we are in a hybrid or terminal-assisted + // request then we are going to get another location request very shortly + // anyway... + AgpsInterface()->HoldPositioning(iFsm->SessionId(), KErrNone); + + // Report the position to the message switch + MessageSwitch()->SendNetLocResponse(iFsm->SessionId(), + iFsm->ExitData().iExitInfo, + iFsm->GpsRequestQuality(), + iFsm->GpsPosition(), + iFsm->ActualTime(), + iFsm->IsEmergency()); + + // For MTLR pass the data to the privacy handler + // in case the Privacy Controller wants it. + if ((iFsm->ExitData().iExitInfo >= KErrNone) && + (iFsm->ExitData().iExitInfo != KPositionCalculationFutile) && + ((iFsm->SessionType() == TLbsNetworkEnumInt::EServiceMobileTerminated) || + (iFsm->SessionType() == TLbsNetworkEnumInt::EServiceNetworkInduced))) + { + PrivacyHandler()->ProcessNetworkPositionUpdate(iFsm->SessionId(), + iFsm->GpsPosition()); + } + + consumed = ETrue; + break; + } + + case TPrivLocStateExitData::EExitLocMeasurementResultsReceived: + { + // Don't cancel the location request yet, but tell the AGPS interface + // handler to put it on 'hold'. If we are in a hybrid or terminal-assisted + // request then we are going to get another location request very shortly + // anyway... + AgpsInterface()->HoldPositioning(iFsm->SessionId(), KErrNone); + + // Report the measurement data to the message switch, even if we + // didn't get any. The error code will indicate that the data + // is rubbish in that case. + LBSLOG2(ELogP3, "CLbsPrivLocWaitLocUpdateState:returning with reason %d", iFsm->MeasurementInfoError()); + + MessageSwitch()->SendNetLocResponse(iFsm->SessionId(), + iFsm->ExitData().iExitInfo, + iFsm->GpsRequestQuality(), + iFsm->GpsMeasurementInfo(), + iFsm->ActualTime(), + iFsm->IsEmergency()); + break; + } + + case TPrivLocStateExitData::EExitTimedOut: + { + // Don't cancel the location request yet, but tell the AGPS interface + // handler to put it on 'hold'. If we are in a hybrid or terminal-assisted + // request then we are going to get another location request very shortly + // anyway... + AgpsInterface()->HoldPositioning(iFsm->SessionId(), KErrNone); + + // If the request has timed out, then return whatever position + // data we have, but make it clear it's not what was requested. + // If there's an error (probably KErrTimedOut) there's + // nothing to report, so send dummy data with the error. + MessageSwitch()->SendNetLocResponse(iFsm->SessionId(), + iFsm->ExitData().iExitInfo, + iFsm->GpsRequestQuality(), + iFsm->GpsPosition(), + iFsm->ActualTime(), + iFsm->IsEmergency()); + + // For MTLR, pass the data to the privacy handler in case the Privacy + // Controller wants it. + // NB Don't send the update if the error is KErrTimedOut, as that means there's + // nothing to report. + if((iFsm->SessionType() == TLbsNetworkEnumInt::EServiceMobileTerminated) && + (iFsm->ExitData().iExitInfo == KPositionQualityLoss)) + { + PrivacyHandler()->ProcessNetworkPositionUpdate(iFsm->SessionId(), + iFsm->GpsPosition()); + } + + consumed = ETrue; + break; + } + + case TPrivLocStateExitData::EExitCancelledByPrivacyController: + { + // Stop the location request immediately. + AgpsInterface()->StopPositioning(iFsm->SessionId()); + + // Send a SendExternalLocateCancel to NetGateWay- if the protcol module does not support this then + // the Gateway will do nothing + MessageSwitch()->SendExternalLocateCancel(iFsm->SessionId(), KErrCancel); + + // Send a location response with 'cancel' set to the network + TPositionInfo dummyPosInfo; + TTime dummyTime; + TLbsNetPosRequestQualityInt dummyQuality; + MessageSwitch()->SendNetLocResponse(iFsm->SessionId(), + iFsm->ExitData().iExitInfo, + dummyQuality, + dummyPosInfo, + dummyTime, + iFsm->IsEmergency()); + + consumed = ETrue; + } + break; + + case TPrivLocStateExitData::EExitBadQualityProfile: + { + // Do nothing; we're just going back to Idle state + consumed = ETrue; + break; + } + + case TPrivLocStateExitData::EExitBadLocationRequest: + { + // Error processing the location request - + // send a dummy response with an error code. + TPositionInfo dummyPosInfo; + TTime dummyTime; + TLbsNetPosRequestQualityInt dummyQuality; + MessageSwitch()->SendNetLocResponse(iFsm->SessionId(), + iFsm->ExitData().iExitInfo, + dummyQuality, + dummyPosInfo, + dummyTime, + iFsm->IsEmergency()); + + consumed = ETrue; + break; + } + + default: + { + consumed = CLbsPrivLocStateBase::OnExit(); + // If the exit reason wasn't handled, panic (should only happen in development) + __ASSERT_DEBUG(consumed, Panic(ENrhPanicWaitLocUpdateUnknownExitReason)); + } + } + return(consumed); + } + +// ----------------------------------------------------------------------------- +// CLbsPrivLocIdleState::OnNetLocRequest +// Description: The Message Switch has forwarded a request for a network +// location. +// ----------------------------------------------------------------------------- +// +void CLbsPrivLocWaitLocUpdateState::OnNetLocRequest(const TLbsNetSessionIdInt& aSessionId, + const TLbsNetPosRequestMethodInt& aPosRequestMethod, + TLbsNetworkEnumInt::TLbsNetProtocolServiceInt aSessionType, + TBool aIsEmergency, + const TLbsNetPosRequestQualityInt& aQuality) + { + TInt numMethods = aPosRequestMethod.NumPosMethods(); + if (numMethods==1) + { + TLbsNetPosMethodInt netPosMethod; + aPosRequestMethod.GetPosMethod(0,netPosMethod); + + if (netPosMethod.PosMode()== (TPositionModuleInfo::ETechnologyNetwork | TPositionModuleInfo::ETechnologyAssisted)) + { + iFsm->TapMode() = ETrue; + } + } + if(aSessionId != iFsm->SessionId()) + { + /* This request is for a different session. Cancel the current one + * and start a new one. + */ + HandleLocRequest(aSessionId,aPosRequestMethod, + aSessionType,aIsEmergency, + aQuality); + } + else + { + LBSLOG(ELogP3, "CLbsPrivLocWaitLocUpdateState::OnNetLocRequest: Matching SessionId."); + TPrivLocWaitLocationUpdateParams updateRequestParams(aSessionId, + aPosRequestMethod, + aSessionType, + aIsEmergency, + aQuality); + iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitLocReqReceived, KErrNone); + iFsm->ChangeState(CLbsPrivLocFsm::EStateWaitLocationUpdate, updateRequestParams); + } + } + + +void CLbsPrivLocWaitLocUpdateState::OnMTLRRequest(const TLbsNetSessionIdInt& /*aSessionId*/, + TLbsNetworkEnumInt::TLbsNetProtocolServiceInt /*aSessionType*/, + TBool /*aIsEmergency*/, + const TLbsExternalRequestInfo& /*aExternalRequestInfo*/, + const TLbsNetPosRequestPrivacyInt& /*aNetPosRequestPrivacy*/) + { + // this can never happen. If the Fsm is in the WaitLocUpdateState then + // any arrival of a MTLR request would start a new session and not + // implicitly cancel the ongoing MTLR and the OnMTLRRequest() + // would be directed to that session not this one + + } + +// ----------------------------------------------------------------------------- +// CLbsPrivLocWaitLocUpdateState::OnTimerEventL +// Description: The Location Update timer has expired. +// Cancel the request, and pass on the response if any has been received, +// otherwise report failure. +// ----------------------------------------------------------------------------- +// +void CLbsPrivLocWaitLocUpdateState::OnTimerEventL(TInt /*aTimerId*/) + { + LBSLOG(ELogP3, "CLbsPrivLocWaitLocUpdateState::OnTimerEventL"); + + if(iFsm->MeasurementInfoReceived()) + { + // A position fix may have been received, but it can't be accurate enough + // (otherwise the request would have been completed before timeout), so + // return the most recent measurement info + LBSLOG(ELogP3, "OnTimerEventL, measurement data received"); + iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitLocMeasurementResultsReceived, + iFsm->MeasurementInfoError()); + } + else if(iFsm->LocationFixReceived()) + { + // position received, but not accurate enough (or request would already have been completed) + LBSLOG(ELogP3, "OnTimerEventL, inaccurate location data received"); + iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitTimedOut, + KPositionQualityLoss); + } + else + { + // we've received no update (position / measurements) + LBSLOG(ELogP3, "OnTimerEventL, NO measurement data received"); + LBSLOG(ELogP3, "(Setting exit info KErrPositionNoGpsUpdate"); + iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitTimedOut, + KErrPositionNoGpsUpdate); + } + + SetExitState(); + } + +// ----------------------------------------------------------------------------- +// CLbsPrivLocWaitLocUpdateState::SetExitState +// Description: Works out the next state on the basis of the current session +// type and whether any update has been received. +// ----------------------------------------------------------------------------- +// +void CLbsPrivLocWaitLocUpdateState::SetExitState() + { + TPrivLocWaitLocationRequestParams locationRequestParams(iFsm->SessionId(), + iFsm->IsEmergency(), + EFalse, + iFsm->ExitData().iExitInfo); + iFsm->ChangeState(CLbsPrivLocFsm::EStateWaitLocationRequest, + locationRequestParams); + } + +TBool CLbsPrivLocWaitLocUpdateState::ReceivedFixIsAccurate() + { + TBool fixIsAccurate = EFalse; + + // Compare the accuracy to the request values. + // Make sure the location update is (A)GPS and not Network based. + TPosition latestPosition; + iFsm->GpsPosition().GetPosition(latestPosition); + + if ((latestPosition.HorizontalAccuracy() <= iFsm->GpsRequestQuality().MinHorizontalAccuracy()) && + (latestPosition.VerticalAccuracy() <= iFsm->GpsRequestQuality().MinVerticalAccuracy()) && + (iFsm->GpsPosition().PositionMode() != TPositionModuleInfo::ETechnologyNetwork))//Pure Reference Location + { + fixIsAccurate = ETrue; + } + + return(fixIsAccurate); + } + +/** Callback when a GPS position update arrives from AGPS manager. +*/ +void CLbsPrivLocWaitLocUpdateState::OnAgpsPositionUpdate( + TInt aReason, + const TPositionExtendedSatelliteInfo& aPosInfo, + const TTime& aTimeStamp) + { + iFsm->GpsPosition() = aPosInfo; + iFsm->ActualTime() = aTimeStamp; + iFsm->LocationFixReceived() = ETrue; + iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitLocFixReceived, aReason); + + if (KErrNone == aReason) + { + if (iFsm->TapMode()) + { + LBSLOG(ELogP1,"TAP mode) - NOT sending position to network"); + return; // do NOT return AGPS postions to TAP mode sessions + } + // See if the reported accuracy matches the specified quality. + // If the accuracy is good enough, report the position + + // if this session is TAP then discard the position + + if(ReceivedFixIsAccurate()) + { + SetExitState(); + } + } + else if ((aReason <= KErrNone) || (KPositionCalculationFutile == aReason)) + { + // GPS Manager can't provide a location update. return what we do have. + if(iFsm->MeasurementInfoReceived()) + { + LBSLOG(ELogP1,"CLbsPrivLocWaitLocUpdateState::OnPositionUpdate() - measurement received"); + iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitLocMeasurementResultsReceived, aReason); + } + else + { + iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitLocFixReceived, aReason); + } + SetExitState(); + } + else if (KPositionEarlyComplete == aReason) + { + // Not an error. Report back what was accepted. + iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitLocFixReceived, KErrNone); + SetExitState(); + } + else + { + // A real error + SetExitState(); + } + } + +/** Callback when a GPS measurement results update arrives from AGPS manager. + +Only location requests that are 'hybrid' or 'terminal assisted' should record +the measurement results. Other types of request (autonomous, terminal based) +are only interested in the GPS position update. +*/ +void CLbsPrivLocWaitLocUpdateState::OnAgpsMeasurementUpdate( + TInt aReason, + const TPositionGpsMeasurementInfo& aPosInfo, + const TTime& /*aTimeStamp*/) + { + // Check that we should be listening for measurement updates. + + TBool positionCalculationPossible = aPosInfo.PositionCalculationPossible(); + + const TInt methodCount = iFsm->PosRequestMethod().NumPosMethods(); + for(TInt i = 0; i < methodCount; ++i) + { + TLbsNetPosMethodInt posMethod; + iFsm->PosRequestMethod().GetPosMethod(i, posMethod); + if((posMethod.PosMode() & KTerminalAssistedMode) == KTerminalAssistedMode) + { + iFsm->MeasurementInfoReceived() = ETrue; + iFsm->MeasurementInfoError() = aReason; + iFsm->GpsMeasurementInfo() = aPosInfo; + + // don't wait until alpha2 time expires, instead + // return measuremnts now + if (positionCalculationPossible) + { + iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitLocMeasurementResultsReceived, + iFsm->MeasurementInfoError()); + SetExitState(); + } + break; + } + } + } + +/** Callback when a GPS measurement results update arrives from AGPS manager. + +Only location requests that are 'hybrid' or 'terminal assisted' should record +the measurement results. Other types of request (autonomous, terminal based) +are only interested in the GPS position update. +*/ +void CLbsPrivLocWaitLocUpdateState::OnNetLocReferenceUpdate( + const TLbsNetSessionIdInt& aSessionId, + const TPositionInfoBase& aPosInfo) + { + CLbsPrivLocStateBase::OnNetLocReferenceUpdate(aSessionId,aPosInfo); + } + + +// ----------------------------------------------------------------------------- +// +// ----------------------- Class CLbsPrivLocWaitLocReqState -------------------- +// +// Implements the Wait For Location Request state of the Privacy and Location +// Request Handler +// +// ----------------------------------------------------------------------------- +// +CLbsPrivLocWaitLocReqState* CLbsPrivLocWaitLocReqState::NewL(CLbsPrivLocFsm* aFsm) + { + return new(ELeave)CLbsPrivLocWaitLocReqState(aFsm); + } + +CLbsPrivLocWaitLocReqState::CLbsPrivLocWaitLocReqState(CLbsPrivLocFsm* aFsm) +: CLbsPrivLocStateBase(aFsm) + { + } + +// ----------------------------------------------------------------------------- +// CLbsPrivLocWaitLocReqState::OnEntry +// Description: Carries out tasks required on entry to the state. +// ----------------------------------------------------------------------------- +// +void CLbsPrivLocWaitLocReqState::OnEntry(const TPrivLocCommonParams& aStateParams) + { + CLbsPrivLocStateBase::OnEntry(aStateParams); + const TPrivLocWaitLocationRequestParams& params = TPrivLocWaitLocationRequestParams::Cast(aStateParams); + iFsm->IsEmergency() = params.iIsEmergency; + iFsm->PrivacyRequestCancelled() = params.iReqCancelled; + iFsm->PreviousStateExitInfo() = params.iPreviousStateExitInfo; + } + + +// ----------------------------------------------------------------------------- +// CLbsPrivLocWaitLocReqState::OnExit +// Description: Carries out tasks required on exit from the state. +// Panics if the exit reason is not handled by the base state exit +// ----------------------------------------------------------------------------- +// +TBool CLbsPrivLocWaitLocReqState::OnExit() + { + TBool consumed = CLbsPrivLocStateBase::OnExit(); + // If the exit reason wasn't handled, panic (should only happen in development) + __ASSERT_DEBUG(consumed, Panic(ENrhPanicWaitLocReqUnknownExitReason)); + return(consumed); + } + +void CLbsPrivLocWaitLocReqState::OnMTLRRequest(const TLbsNetSessionIdInt& /*aSessionId*/, + TLbsNetworkEnumInt::TLbsNetProtocolServiceInt /*aSessionType*/, + TBool /*aIsEmergency*/, + const TLbsExternalRequestInfo& /*aExternalRequestInfo*/, + const TLbsNetPosRequestPrivacyInt& /*aNetPosRequestPrivacy*/) + { + // this can never happen. If the Fsm is in the WaitLocReqState then + // any arrival of a MTLR request would start a new session and the OnMTLRRequest() + // would be directed to that session not this one + __ASSERT_DEBUG(EFalse, Panic(ENrhPanicBadParamType)); + } + +void CLbsPrivLocWaitLocReqState::OnNetLocRequest(const TLbsNetSessionIdInt& aSessionId, + const TLbsNetPosRequestMethodInt& aPosRequestMethod, + TLbsNetworkEnumInt::TLbsNetProtocolServiceInt aSessionType, + TBool aIsEmergency, + const TLbsNetPosRequestQualityInt& aQuality) + { + TInt numMethods = aPosRequestMethod.NumPosMethods(); + if (numMethods==1) + { + TLbsNetPosMethodInt netPosMethod; + aPosRequestMethod.GetPosMethod(0,netPosMethod); + + if (netPosMethod.PosMode()== (TPositionModuleInfo::ETechnologyNetwork | TPositionModuleInfo::ETechnologyAssisted)) + { + iFsm->TapMode() = ETrue; + } + } + + + if(aSessionId == iFsm->SessionId()) + { + if (iFsm->PrivacyRequestCancelled()) + { + iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitCancelledByPrivacyController, KErrCancel); + TPrivLocWaitLocationRequestParams locationRequestParams(iFsm->SessionId(), + iFsm->IsEmergency(), + iFsm->PrivacyRequestCancelled()); + iFsm->ChangeState(CLbsPrivLocFsm::EStateWaitLocationRequest, locationRequestParams); + } + else + { + iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitLocReqReceived, KErrNone); + TPrivLocWaitLocationUpdateParams updateRequestParams(aSessionId, + aPosRequestMethod, + aSessionType, + aIsEmergency, + aQuality); + iFsm->ChangeState(CLbsPrivLocFsm::EStateWaitLocationUpdate, updateRequestParams); + } + } + else + { + HandleLocRequest(aSessionId,aPosRequestMethod, + aSessionType,aIsEmergency, + aQuality); + } + } + +void CLbsPrivLocWaitLocReqState::OnCancelNetworkLocationRequest(const TLbsNetSessionIdInt& aSessionId) + { + if (!iFsm->IsEmergency() && (aSessionId == iFsm->SessionId())) + { + if (!iFsm->PrivacyRequestCancelled() ) + { + TLbsNetSessionIdInt sessionId = iFsm->SessionId(); + MessageSwitch()->SendExternalLocateCancel(sessionId,KErrCancel); + } + iFsm->PrivacyRequestCancelled() = ETrue; + } + } + + +/** Called when a reference position arrives from the network. +*/ +void CLbsPrivLocWaitLocReqState::OnNetLocReferenceUpdate( + const TLbsNetSessionIdInt& aSessionId, + const TPositionInfoBase& aPosInfo) + { + // if the MTLR is still active (has not been cancelled by the privacy handler) + if (!iFsm->PrivacyRequestCancelled()) + { + CLbsPrivLocStateBase::OnNetLocReferenceUpdate(aSessionId, aPosInfo); + } + } + +// ----------------------------------------------------------------------------- +// CLbsPrivLocWaitLocReqState::OnSessionComplete +// Description: handling of a session complete message +// ----------------------------------------------------------------------------- +// +void CLbsPrivLocWaitLocReqState::OnSessionComplete(const TLbsNetSessionIdInt& aSessionId, + TInt aReason) + { + + + if(aSessionId == iFsm->SessionId()) + { + // Make sure the reason passed with the Session Complete is sent to the + // Privacy Controller EXCEPT when the update previously passed to the + // network didn't meet the quality criteria. In this case use the + // KPositionQualityLoss status. + TInt completionReason = aReason; + if(aReason == KErrNone) + { + if(KPositionQualityLoss == iFsm->PreviousStateExitInfo()) + { + completionReason = KPositionQualityLoss; + } + } + + iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitSessionComplete, completionReason); + iFsm->ChangeState(CLbsPrivLocFsm::EStateIdle, aSessionId); + } + } + +// ----------------------------------------------------------------------------- +// +// Package classes +// +// ----------------------------------------------------------------------------- +// +TPrivLocCommonParams::TPrivLocCommonParams() + { + } +TPrivLocCommonParams::TPrivLocCommonParams(TLbsNetSessionIdInt aSessionId) + { + iSessionId = aSessionId; + } + +TPrivLocWaitLocationRequestParams::TPrivLocWaitLocationRequestParams() + { + } +TPrivLocWaitLocationRequestParams::TPrivLocWaitLocationRequestParams( + const TLbsNetSessionIdInt& aSessionId, + TBool aIsEmergency, + TBool aReqCancelled, + TInt aPreviousStateExitInfo) : + TPrivLocCommonParams(aSessionId), + iIsEmergency(aIsEmergency), + iReqCancelled(aReqCancelled), + iPreviousStateExitInfo(aPreviousStateExitInfo) + { + } + +TPrivLocWaitLocationUpdateParams::TPrivLocWaitLocationUpdateParams() + { + } +TPrivLocWaitLocationUpdateParams::TPrivLocWaitLocationUpdateParams( + const TLbsNetSessionIdInt& aSessionId, + const TLbsNetPosRequestMethodInt& aPosRequestMethod, + TLbsNetworkEnumInt::TLbsNetProtocolServiceInt aSessionType, + TBool aIsEmergency, + const TLbsNetPosRequestQualityInt& aQuality) : + TPrivLocCommonParams(aSessionId), + iSessionType(aSessionType), + iIsEmergency(aIsEmergency), + iQuality(aQuality), + iPosRequestMethod(aPosRequestMethod) + { + } + +TPrivLocWaitPrivResponseParams::TPrivLocWaitPrivResponseParams() + { + + } +TPrivLocWaitPrivResponseParams::TPrivLocWaitPrivResponseParams( + const TLbsNetSessionIdInt& aSessionId, + const TLbsNetworkEnumInt::TLbsNetProtocolServiceInt aSessionType, + const TLbsExternalRequestInfo& aExternalRequestInfo, + const TLbsNetPosRequestPrivacyInt& aNetPosRequestPrivacy, + TBool aIsEmergency) : + TPrivLocCommonParams(aSessionId), + iNetPosRequestPrivacy(aNetPosRequestPrivacy), + iIsEmergency(aIsEmergency), + iSessionType(aSessionType) + { + // Need to check the type of aExternalRequestInfo before + // copying it into this class. + if (aExternalRequestInfo.ClassType() == EExternalRequestInfoClass) + { + __ASSERT_DEBUG(aExternalRequestInfo.ClassSize() == sizeof(TLbsExternalRequestInfo), + Panic(ENrhPanicInvalidExternalRequestInfoType)); + + Mem::Copy(&iExternalRequestInfo, + &aExternalRequestInfo, + sizeof(TLbsExternalRequestInfo)); + } + else + { + if (aExternalRequestInfo.ClassType() == (EExternalRequestInfoClass | EExternalRequestInfoClass2)) + { + __ASSERT_DEBUG(aExternalRequestInfo.ClassSize() == sizeof(TLbsExternalRequestInfo2), + Panic(ENrhPanicInvalidExternalRequestInfoType)); + + Mem::Copy(&iExternalRequestInfo, + &aExternalRequestInfo, + sizeof(TLbsExternalRequestInfo2)); + } + else + { + Panic(ENrhPanicInvalidExternalRequestInfoType); + } + } + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------- Class CLbsPrivLocFsm -------------------------- +// +// State Machine class which owns the states of the Privacy and Location Handler +// +// ----------------------------------------------------------------------------- +// + +// ----------------------------------------------------------------------------- +// CLbsPrivLocFsm::NewL +// Description: CLbsPrivLocFsm static constructor +// ----------------------------------------------------------------------------- +// +CLbsPrivLocFsm* CLbsPrivLocFsm::NewL( + CPrivacyAndLocationHandler& aPrivLocHandler, + const TLbsNetSessionIdInt& aSessionId) + { + CLbsPrivLocFsm* self; + self = new (ELeave) CLbsPrivLocFsm(aPrivLocHandler, aSessionId); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return(self); + } + +// ----------------------------------------------------------------------------- +// CLbsPrivLocFsm::CLbsPrivLocFsm +// Description: CLbsPrivLocFsm constructor +// ----------------------------------------------------------------------------- +// +CLbsPrivLocFsm::CLbsPrivLocFsm( + CPrivacyAndLocationHandler& aPrivLocHandler, + const TLbsNetSessionIdInt& aSessionId) : + iPrivLocHandler(aPrivLocHandler), + iSessionId(aSessionId), + iIsEmergency(EFalse), + iSessionType(TLbsNetworkEnumInt::EServiceNone), + iRefPosProcessed(EFalse), + iLocReqReceived(EFalse), + iReqCancelled(EFalse), + iWasPrivacyResponseReceivedStateExited(EFalse), + iPositioningStatusIncremented(EFalse) + { + } + +// ----------------------------------------------------------------------------- +// CLbsPrivLocFsm::~CLbsPrivLocFsm +// Description: CLbsPrivLocFsm destructor +// ----------------------------------------------------------------------------- +// +CLbsPrivLocFsm::~CLbsPrivLocFsm() + { + delete iLocationUpdateTimer; + iStates.DeleteAll(); + iStates.Reset(); + } + +// ----------------------------------------------------------------------------- +// CLbsPrivLocFsm::SessionId +// Description: Get the current session Id for this FSM. +// ----------------------------------------------------------------------------- +// +const TLbsNetSessionIdInt& CLbsPrivLocFsm::SessionId() const + { + return iSessionId; + } + +// ----------------------------------------------------------------------------- +// CLbsPrivLocFsm::ConstructL +// Description: CLbsPrivLocFsm second-phase constructor. +// Creates the states of the system and the Privacy Handler. +// ----------------------------------------------------------------------------- +// +void CLbsPrivLocFsm::ConstructL() + { + // Create the states + iStates.At(EStateIdle) = CLbsPrivLocIdleState::NewL(this); + iStates.At(EStateWaitPrivacyResponse) = CLbsPrivLocWaitPrivRespState::NewL(this); + iStates.At(EStateWaitLocationRequest) = CLbsPrivLocWaitLocReqState::NewL(this); + iStates.At(EStateWaitLocationUpdate) = CLbsPrivLocWaitLocUpdateState::NewL(this); + + iCurrentState = iStates.At(EStateIdle); + // When waiting for an update, there is a maximum duration specified by the + // LBS admin data to avoid the risk of hanging around forever in the event of + // a problem with the A-GPS module. Create a timer to deal with this. + iLocationUpdateTimer = CLbsCallbackTimer::NewL(*this); + } + + +TBool CLbsPrivLocFsm::IsSpecialFeatureIntermediateFutileUpdateOn() + { + return PrivLocHandler().IsSpecialFeatureIntermediateFutileUpdateOn(); + } + +// ----------------------------------------------------------------------------- +// CPrivacyAndLocationHandler::SetServerObserver +// Description: Store a pointer to the NRH server which comunicates with the +// Privacy Controller. +// ----------------------------------------------------------------------------- +// +void CLbsPrivLocFsm::SetServerObserver(MLbsSessionObserver* aNrhServer) + { + PrivLocHandler().PrivacyHandler()->SetServerObserver(aNrhServer); + } + +// ----------------------------------------------------------------------------- +// CLbsPrivLocFsm::OnRespondNetworkLocationRequest +// Description: Called by the Privacy Handler to report the result of a privacy +// check. Handling of the response is delegated to the current state. +// ----------------------------------------------------------------------------- +// +void CLbsPrivLocFsm::OnRespondNetworkLocationRequest(const TLbsNetSessionIdInt& aRequestId, + TLbsNetworkEnumInt::TLbsPrivacyResponseInt aRequestResult, + TInt aResponseReason) + { + LBSLOG3(ELogP3, "FSM(%d) OnRespondNetworkLocationRequest response=%d",iSessionId.SessionNum(),aRequestResult); + iCurrentState->OnRespondNetworkLocationRequest(aRequestId, aRequestResult, aResponseReason); + } + +// ----------------------------------------------------------------------------- +// CLbsPrivLocFsm::OnCancelNetworkLocationRequest +// Description: Called by the Privacy Handler to report that a privacy check +// has been rejected. This may occur after it has already been accepted. +// Handling of the response is delegated to the current state. +// ----------------------------------------------------------------------------- +// +void CLbsPrivLocFsm::OnCancelNetworkLocationRequest(const TLbsNetSessionIdInt& aRequestId) + { + LBSLOG2(ELogP3, "FSM(%d) OnCancelNetworkLocationRequest",iSessionId.SessionNum()); + iCurrentState->OnCancelNetworkLocationRequest(aRequestId); + } + +// ----------------------------------------------------------------------------- +// CLbsPrivLocFsm::OnMTLRRequest +// Description: The Message Switch has forwarded a request to start an MTLR +// session. +// Handling of the request is delegated to the current state. +// ----------------------------------------------------------------------------- +// +void CLbsPrivLocFsm::OnMTLRRequest(const TLbsNetSessionIdInt& aSessionId, + TLbsNetworkEnumInt::TLbsNetProtocolServiceInt aSessionType, + TBool aIsEmergency, + const TLbsExternalRequestInfo& aExternalRequestInfo, + const TLbsNetPosRequestPrivacyInt& aNetPosRequestPrivacy) + { + LBSLOG2(ELogP3, "FSM(%d) OnMTLRRequest",iSessionId.SessionNum()); + iCurrentState->OnMTLRRequest(aSessionId, + aSessionType, + aIsEmergency, + aExternalRequestInfo, + aNetPosRequestPrivacy); + } + +// ----------------------------------------------------------------------------- +// CLbsPrivLocFsm::OnSessionComplete +// Description: The Message Switch has reported that the session is +// over (complete or aborted due to some error). +// Handling of the message is delegated to the current state. +// ----------------------------------------------------------------------------- +// +void CLbsPrivLocFsm::OnSessionComplete( + const TLbsNetSessionIdInt& aSessionId, + TInt aReason) + { + LBSLOG3(ELogP3, "FSM(%d) OnSessionComplete reason=%d",iSessionId.SessionNum(),aReason); + iCurrentState->OnSessionComplete(aSessionId, aReason); + + // update the positioning status. Note this is updated only if it was previously + // incremented as a result of this session. + if (WasPositioningStatusIncremented()) + { + PrivLocHandler().DecrementPositioningStatus(); + WasPositioningStatusIncremented() = EFalse; + } + } + +// ----------------------------------------------------------------------------- +// CLbsPrivLocFsm::OnNetLocRequest +// Description: The Message Switch has passed on a request for a position update +// Handling of the request is delegated to the current state. +// ----------------------------------------------------------------------------- +// +void CLbsPrivLocFsm::OnNetLocRequest( + const TLbsNetSessionIdInt& aSessionId, + const TLbsNetPosRequestMethodInt& aPosRequestMethod, + TLbsNetworkEnumInt::TLbsNetProtocolServiceInt aSessionType, + TBool aIsEmergency, + const TLbsNetPosRequestQualityInt& aQuality) + { + LBSLOG2(ELogP3, "FSM(%d) OnNetLocRequest",iSessionId.SessionNum()); + iCurrentState->OnNetLocRequest(aSessionId, + aPosRequestMethod, + aSessionType, + aIsEmergency, + aQuality); + } + +/** Called when a reference position arrives from the network. +*/ +void CLbsPrivLocFsm::OnNetLocReferenceUpdate( + const TLbsNetSessionIdInt& aSessionId, + const TPositionInfoBase& aPosInfo) + { + LBSLOG2(ELogP3, "FSM(%d) OnNetLocReferenceUpdate",iSessionId.SessionNum()); + iCurrentState->OnNetLocReferenceUpdate(aSessionId, aPosInfo); + } + +/** Callend when a final location arrives from the network. + +Currently the final network position is never used by the +state machine - it is only needed by the X3P handler. +So this function just ignores the update. +*/ +void CLbsPrivLocFsm::OnNetLocFinalUpdate( + const TLbsNetSessionIdInt& /*aSessionId*/, + const TPositionInfoBase& /*aPosInfo*/) + { + // Final network position not used by CLbsPrivLocFsm, so ignore it. + } + +// ----------------------------------------------------------------------------- +// CLbsPrivLocFsm::ChangeState +// Description: Called by a state of the FSM when a transition is required. +// ----------------------------------------------------------------------------- +// +void CLbsPrivLocFsm::ChangeState(TLocPrivacyHandlerState aNewStateId,const TPrivLocCommonParams& aStateParams) + { + // Tidy up the old state + if(iCurrentState) + { + // coverity[unchecked_value] + // We're not interested in whether it was consumed here + iCurrentState->OnExit(); + } + + // Note, here the session ID has already being set when the Fsm was created (when session first came into being) + // so no need to do this ... iSessionId = aStateParams.iSessionId; + + // Set the new state + iCurrentState = iStates.At(aNewStateId); + + LBSLOG3(ELogP3, "FSM(%d) Entering state %d",iSessionId.SessionNum(), aNewStateId); + + // Do any initialisation for the new state. + iCurrentState->OnEntry(aStateParams); + } + +// ----------------------------------------------------------------------------- +// CLbsPrivLocFsm::ChangeState +// Description: Called by a state of the FSM when a transition is required to a +// state which only requires the session Id +// ----------------------------------------------------------------------------- +// +void CLbsPrivLocFsm::ChangeState(TLocPrivacyHandlerState aNewStateId, + const TLbsNetSessionIdInt& aSessionId) + { + TPrivLocCommonParams commonParams(aSessionId); + ChangeState(aNewStateId, commonParams); + } + +// ----------------------------------------------------------------------------- +// CLbsPrivLocFsm::PrivLocHandler +// Description: Get the CPrivacyAndLocationHandler object +// ----------------------------------------------------------------------------- +// +CPrivacyAndLocationHandler& CLbsPrivLocFsm::PrivLocHandler() + { + return iPrivLocHandler; + } + +// ----------------------------------------------------------------------------- +// CLbsPrivLocWaitLocUpdateState::OnTimerEventL +// Description: The Location Update timer has expired. +// Cancel the request, and pass on the response if any has been received, +// otherwise report failure. +// ----------------------------------------------------------------------------- +// +void CLbsPrivLocFsm::OnTimerEventL(TInt aTimerId) + { + LBSLOG2(ELogP3, "FSM(%d) OnTimerEventL", iSessionId.SessionNum()); + iCurrentState->OnTimerEventL(aTimerId); + } + +/** Called if OnTimerEventL leaves */ +TInt CLbsPrivLocFsm::OnTimerError(TInt /*aTimerId*/, TInt aError) + { + __ASSERT_DEBUG(EFalse, Panic(ENrhPanicLocationTimerError)); + return(aError); + } + +/** Callback when a GPS position update arrives from AGPS manager. +*/ +void CLbsPrivLocFsm::OnAgpsPositionUpdate( + TInt aReason, + const TPositionExtendedSatelliteInfo& aPosInfo, + const TTime& aTimeStamp) + { + LBSLOG2(ELogP3, "FSM(%d) OnAgpsPositionUpdate", iSessionId.SessionNum()); + iCurrentState->OnAgpsPositionUpdate(aReason, aPosInfo, aTimeStamp); + } + +/** Callback when a GPS measurement results update arrives from AGPS manager. +*/ +void CLbsPrivLocFsm::OnAgpsMeasurementUpdate( + TInt aReason, + const TPositionGpsMeasurementInfo& aPosInfo, + const TTime& aTimeStamp) + { + LBSLOG2(ELogP3, "FSM(%d) OnAgpsMeasurementUpdate", iSessionId.SessionNum()); + iCurrentState->OnAgpsMeasurementUpdate(aReason, aPosInfo, aTimeStamp); + }