locationrequestmgmt/networkrequesthandler/src/privacyandlocationrequesthandler.cpp
changeset 0 9cfd9a3ee49c
child 27 aadfb18aaac1
child 48 81c9bee26a45
child 52 29dbbeac905d
equal deleted inserted replaced
-1:000000000000 0:9cfd9a3ee49c
       
     1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <e32std.h>
       
    17 #include <e32property.h>
       
    18 
       
    19 // LBS-specific
       
    20 #include <lbs.h>
       
    21 #include <lbs/lbsadmin.h>
       
    22 #include <lbs/lbslocerrors.h>
       
    23 #include <lbs/lbslocclasstypes.h>
       
    24 
       
    25 #include "nrhpanic.h"
       
    26 #include "lbsdevloggermacros.h"
       
    27 #include "lbsqualityprofile.h"
       
    28 
       
    29 #include "privacyandlocationrequesthandler.h"
       
    30 
       
    31 // Special 'invalid session' SessionId.
       
    32 const TLbsNetSessionIdInt KInvalidSessionId(TUid::Uid(0), 0);
       
    33 
       
    34 const TPositionModuleInfo::TTechnologyType KTerminalAssistedMode = (TPositionModuleInfo::ETechnologyNetwork |
       
    35 																	TPositionModuleInfo::ETechnologyAssisted);
       
    36 	
       
    37 // ----------------------------------------------------------------------------- 
       
    38 // 
       
    39 // ----------------------- Class CPrivacyAndLocationHandler --------------------
       
    40 //
       
    41 // State Machine class which owns the states of the Privacy and Location Handler
       
    42 //
       
    43 // ----------------------------------------------------------------------------- 
       
    44 //
       
    45 
       
    46 // ----------------------------------------------------------------------------- 
       
    47 // CPrivacyAndLocationHandler::NewL
       
    48 // Description: CPrivacyAndLocationHandler static constructor 
       
    49 // ----------------------------------------------------------------------------- 
       
    50 //
       
    51 CPrivacyAndLocationHandler* CPrivacyAndLocationHandler::NewL(CNGMessageSwitch& aMessageSwitch,
       
    52 											CLbsAdmin& aLbsAdmin,
       
    53 											RLbsNetworkRegistrationStatus& aNetRegStatus)
       
    54 	{
       
    55 	CPrivacyAndLocationHandler* self; 
       
    56 	self = new (ELeave) CPrivacyAndLocationHandler(aMessageSwitch, aNetRegStatus);
       
    57 	CleanupStack::PushL(self);
       
    58 	self->ConstructL(&aLbsAdmin);
       
    59 	CleanupStack::Pop(self);
       
    60 	return(self);	
       
    61 	}
       
    62 
       
    63 // ----------------------------------------------------------------------------- 
       
    64 // CPrivacyAndLocationHandler::CPrivacyAndLocationHandler
       
    65 // Description: CPrivacyAndLocationHandler constructor 
       
    66 // ----------------------------------------------------------------------------- 
       
    67 //
       
    68 CPrivacyAndLocationHandler::CPrivacyAndLocationHandler(CNGMessageSwitch& aMessageSwitch, 
       
    69 													   RLbsNetworkRegistrationStatus& aNetRegStatus)
       
    70 :	iNetRegStatus(aNetRegStatus),
       
    71 	iMessageSwitch(&aMessageSwitch),
       
    72 	iNumActiveSessions(0)
       
    73 	{	
       
    74 	}
       
    75 	
       
    76 // ----------------------------------------------------------------------------- 
       
    77 // CPrivacyAndLocationHandler::~CPrivacyAndLocationHandler
       
    78 // Description: CPrivacyAndLocationHandler destructor 
       
    79 // ----------------------------------------------------------------------------- 
       
    80 //
       
    81 CPrivacyAndLocationHandler::~CPrivacyAndLocationHandler()
       
    82 	{
       
    83 	// If iEmergencyFsm has been used by any outstanding request,
       
    84 	// it needs to be removed before calling ResetAndDestroy(),
       
    85 	// otherwise it will get double-deleted when delete iEmergencyFsm
       
    86 	// is called.
       
    87 			
       
    88 	TInt index = iFsmArray.Find(iEmergencyFsm);
       
    89 	if (index >= 0)
       
    90 		{
       
    91 		iFsmArray.Remove(index);
       
    92 		}
       
    93 	
       
    94 	iFsmArray.ResetAndDestroy();
       
    95 
       
    96 
       
    97 	delete iEmergencyFsm;
       
    98     delete iAgpsInterface;
       
    99     delete iPrivacyHandler;
       
   100 	}
       
   101 
       
   102 // ----------------------------------------------------------------------------- 
       
   103 // CPrivacyAndLocationHandler::ConstructL
       
   104 // Description: CPrivacyAndLocationHandler second-phase constructor.
       
   105 //              Creates the states of the system and the Privacy Handler.
       
   106 // ----------------------------------------------------------------------------- 
       
   107 //
       
   108 
       
   109 const TInt KLbsDefaultMaxNumLocationRequests   = 4;
       
   110 
       
   111 void CPrivacyAndLocationHandler::ConstructL(CLbsAdmin* aLbsAdmin)
       
   112 	{
       
   113 	iLbsAdmin = aLbsAdmin;
       
   114 	
       
   115 	iPrivacyHandler = CPrivacyHandler::CreateL(this, *iLbsAdmin, iNetRegStatus);
       
   116 	iMessageSwitch->RegisterObserver(this);
       
   117 
       
   118 	// Get the behaviour mode and device gps mode capabilities
       
   119 	TInt err = iLbsAdmin->Get(KLbsSettingBehaviourMode, iLbsBehaviourMode);
       
   120 	if (err != KErrNone)
       
   121 		{
       
   122 		iLbsBehaviourMode = CLbsAdmin::ELbsBehaviourCustom1;
       
   123 		}
       
   124 	// get device mode capabilities:
       
   125 	err = LbsModuleInfo::GetDeviceCapabilities(KLbsGpsLocManagerUid, iDeviceGpsModeCaps);
       
   126 	if(err != KErrNone || (iDeviceGpsModeCaps==TPositionModuleInfoExtended::EDeviceGpsModeNone))
       
   127 		{
       
   128 		// Assume module supports hybrid if it has not reported its capabilities in module info file
       
   129 		iDeviceGpsModeCaps = TPositionModuleInfoExtended::EDeviceGpsModeSimultaneousTATB;
       
   130 		}
       
   131 
       
   132 
       
   133 	err = iLbsAdmin->Get(KLbsSettingMaximumExternalLocateRequests, iMaxNumSessions);
       
   134 	if (err != KErrNone)
       
   135 		{
       
   136 		iMaxNumSessions = KLbsDefaultMaxNumLocationRequests;
       
   137 		}
       
   138 	
       
   139 	iAgpsInterface = CAgpsInterfaceHandler::NewL(*this, *iLbsAdmin, iNetRegStatus);
       
   140 
       
   141 
       
   142 #ifdef NRH_UNIT_TEST
       
   143 	// For testing use the Uid of the dummy NG
       
   144 	const TInt KTestNgUidInt = 0x1028226B;
       
   145 	const TUid KTestNgUid = {KTestNgUidInt};
       
   146 	iProtocolModuleUid = KTestNgUid;
       
   147 #else
       
   148 	ReadProtocolModuleAdminSetting();
       
   149 #endif
       
   150 	
       
   151 	iEmergencyFsm = CLbsPrivLocFsm::NewL(*this, KInvalidSessionId);
       
   152 	
       
   153 	// Reserve space for FSMs. Note "+1" because a pointer to the emergency Fsm gets added to this array
       
   154 	iFsmArray.ReserveL(iMaxNumSessions+1);
       
   155 
       
   156 	CLbsAdmin::TSpecialFeature specialFeature(CLbsAdmin::ESpecialFeatureOff);
       
   157 	err = iLbsAdmin->Get(KLbsSpecialFeatureIntermediateFutileUpdate, specialFeature);
       
   158 	if (err != KErrNone)
       
   159 		{
       
   160 		LBSLOG_ERR2(ELogP3, "Failed to get KLbsSpecialFeatureIntermediateFutileUpdate (err %d)", err);
       
   161 		}
       
   162 	LBSLOG2(ELogP3, "Using KLbsSpecialFeatureIntermediateFutileUpdate = %d", specialFeature);
       
   163 	iSpecialFeatureIntermediateFutileUpdate = (specialFeature == CLbsAdmin::ESpecialFeatureOn) ? ETrue : EFalse;
       
   164 	}
       
   165 
       
   166 
       
   167 
       
   168 /**
       
   169 Reads the Uid of a current Protocol Module from the Admin Settings.
       
   170 */
       
   171 void CPrivacyAndLocationHandler::ReadProtocolModuleAdminSetting()
       
   172 	{
       
   173 	LBSLOG(ELogP1, "CPrivacyAndLocationHandler::ReadProtocolModuleAdminSetting()");
       
   174 	TLbsProtocolModuleId protUid(KLbsProtocolNullModuleId);
       
   175 	
       
   176 	TInt err = iLbsAdmin->Get(KLbsSettingHomeProtocolModule, protUid);
       
   177 	if (err != KErrNone)
       
   178 		{
       
   179 		LBSLOG_ERR2(ELogP4, "Failed to get KLbsSettingHomeProtocolModule (err %d)", err);
       
   180 		}
       
   181 
       
   182 	iProtocolModuleUid = protUid;
       
   183 	}
       
   184 
       
   185 /** Compares sessionId for RPointerArray::Find().
       
   186 */
       
   187 TBool CPrivacyAndLocationHandler::IsSessionIdEqual(
       
   188 		const TLbsNetSessionIdInt* aSessionId,
       
   189 		const CLbsPrivLocFsm& aFsm)
       
   190 	{
       
   191 	return (*aSessionId == aFsm.SessionId());
       
   192 	}
       
   193 
       
   194 /** Compares session type for RPointerArray::Find().
       
   195 */
       
   196 TBool CPrivacyAndLocationHandler::IsSessionTypeEqual(
       
   197 		const TLbsNetworkEnumInt::TLbsNetProtocolServiceInt* aSessionType,
       
   198 		const CLbsPrivLocFsm& aFsm)
       
   199 	{
       
   200 	return (*aSessionType == const_cast<CLbsPrivLocFsm&>(aFsm).SessionType());
       
   201 	}
       
   202 
       
   203 // ----------------------------------------------------------------------------- 
       
   204 // CPrivacyAndLocationHandler::LookupFsm
       
   205 // Description: Lookup CLbsPrivLocFsm object by session ID.
       
   206 // ----------------------------------------------------------------------------- 
       
   207 //
       
   208 CLbsPrivLocFsm* CPrivacyAndLocationHandler::LookupFsm(const TLbsNetSessionIdInt& aSessionId)
       
   209 	{
       
   210 	LBSLOG2(ELogP3, "LookupFsm session=%d", aSessionId.SessionNum());
       
   211 
       
   212 	// Standard sessions always use the standard state machines.
       
   213 	TInt index = iFsmArray.Find(aSessionId, IsSessionIdEqual);
       
   214 	if (index >= 0)
       
   215 		{
       
   216 		LBSLOG(ELogP3, "LookupFsm: Existing standard FSM found");
       
   217 		return iFsmArray[index];
       
   218 		}
       
   219 	else
       
   220 		{
       
   221 		LBSLOG(ELogP3, "LookupFsm: No standard FSM found");
       
   222 		return NULL;		
       
   223 		}
       
   224 	}
       
   225 
       
   226 /** Get a new state machine to use for a new request.
       
   227 
       
   228 The state machine can either be re-using an existing FSM,
       
   229 or allocating a new one from the heap or, for emergencies one thats was prepared earlier is used.
       
   230 */
       
   231 CLbsPrivLocFsm* CPrivacyAndLocationHandler::GetNewFsm(
       
   232 		const TLbsNetSessionIdInt& aSessionId,
       
   233 		TLbsNetworkEnumInt::TLbsNetProtocolServiceInt aSessionType,
       
   234 		TBool aEmergency)
       
   235 	{
       
   236 	LBSLOG2(ELogP3, "LookupFsm session=%d", aSessionId.SessionNum());
       
   237 	
       
   238 	CLbsPrivLocFsm* fsm(NULL);
       
   239 
       
   240 	// If this is an emergency request, use the emergency FSM  
       
   241 	// Note, we only have to support ONE emergency at a time
       
   242 	// this implies that only one Protcol module may deal with emergencies
       
   243 	// So we do NOT support TWO emergencies .. one from each of the PMs
       
   244 	// Note: only MT-LR or NI-LR requests can be emergency requests.
       
   245 	if (aEmergency
       
   246 		&& (aSessionType == MLbsNetworkProtocolObserver::EServiceMobileTerminated
       
   247 		|| aSessionType == MLbsNetworkProtocolObserver::EServiceNetworkInduced))
       
   248 		{					
       
   249 		TInt index = iFsmArray.Find(iEmergencyFsm);
       
   250 		if (index >= 0)
       
   251 			{
       
   252 			iFsmArray.Remove(index);
       
   253 			iNumActiveSessions--;
       
   254 			}
       
   255 		// clean out Fsm
       
   256 		iEmergencyFsm->RefPosProcessed() = EFalse;
       
   257 		iEmergencyFsm->LocReqReceived() = EFalse;
       
   258 		iEmergencyFsm->LocationFixReceived()= EFalse;
       
   259 		iEmergencyFsm->TapMode() = EFalse;
       
   260 		iEmergencyFsm->WasPrivacyResponseReceivedStateExited() = EFalse;
       
   261 		iEmergencyFsm->NetSessionId()= aSessionId;
       
   262 		fsm = iEmergencyFsm;
       
   263 		}
       
   264 	else
       
   265 		{
       
   266 		if (iNumActiveSessions <= iMaxNumSessions)
       
   267 			{
       
   268 			// Create a new session to handle this privacy request
       
   269 			LBSLOG2(ELogP3, "Creating FSM for new standard request %d",aSessionId.SessionNum());
       
   270 			TRAPD(err, fsm = CLbsPrivLocFsm::NewL(*this, aSessionId)); 
       
   271 			if (err != KErrNone)
       
   272 				{
       
   273 				LBSLOG_ERR2(ELogP3, "Failed to create new FSM, error code : %d", err);
       
   274 				}
       
   275 			}
       
   276 		else
       
   277 			{
       
   278 			LBSLOG_ERR3(ELogP3, "Session start rejected! iNumActiveSessions=%d > iMaxNumSessions=%d", iNumActiveSessions, iMaxNumSessions);
       
   279 			}
       
   280 		}
       
   281 
       
   282 	if (fsm)
       
   283 		{
       
   284 		// Add the state machine to the buffer.
       
   285 		iFsmArray.Append(fsm);
       
   286 	
       
   287 		iNumActiveSessions++; // conceptually, a session starts when a Fsm is created for it
       
   288 
       
   289 		}
       
   290 	
       
   291 	return fsm;
       
   292 	}
       
   293 
       
   294 
       
   295 // ----------------------------------------------------------------------------- 
       
   296 // CPrivacyAndLocationHandler::PrivacyHandler
       
   297 // Description: Return a pointer to the privacy handler implementation
       
   298 //              (controller or notifier).
       
   299 // ----------------------------------------------------------------------------- 
       
   300 //
       
   301 CPrivacyHandler* CPrivacyAndLocationHandler::PrivacyHandler()
       
   302 	{
       
   303 	return iPrivacyHandler;
       
   304 	}
       
   305 	
       
   306 // ----------------------------------------------------------------------------- 
       
   307 // CPrivacyAndLocationHandler::MessageSwitch
       
   308 // Description: Return a pointer to the Network Gateway Message Switch
       
   309 // ----------------------------------------------------------------------------- 
       
   310 //
       
   311 CNGMessageSwitch* CPrivacyAndLocationHandler::MessageSwitch()
       
   312 	{
       
   313 	return iMessageSwitch;
       
   314 	}
       
   315 	
       
   316 // ----------------------------------------------------------------------------- 
       
   317 // CPrivacyAndLocationHandler::LbsAdmin
       
   318 // Description: Return a pointer to the Admin settings database
       
   319 // ----------------------------------------------------------------------------- 
       
   320 //
       
   321 CLbsAdmin* CPrivacyAndLocationHandler::LbsAdmin()
       
   322 	{
       
   323 	return iLbsAdmin;
       
   324 	}
       
   325 	
       
   326 // ----------------------------------------------------------------------------- 
       
   327 // CPrivacyAndLocationHandler::SetServerObserver
       
   328 // Description: Store a pointer to the NRH server which comunicates with the 
       
   329 // Privacy Controller.
       
   330 // ----------------------------------------------------------------------------- 
       
   331 //
       
   332 void CPrivacyAndLocationHandler::SetServerObserver(MLbsSessionObserver* aNrhServer)
       
   333     {
       
   334     PrivacyHandler()->SetServerObserver(aNrhServer);
       
   335     }
       
   336 
       
   337 // ----------------------------------------------------------------------------- 
       
   338 // CPrivacyAndLocationHandler::OnRespondNetworkLocationRequest
       
   339 // Description: Called by the Privacy Handler to report the result of a privacy
       
   340 // check. Handling of the response is delegated to the current state.
       
   341 // ----------------------------------------------------------------------------- 
       
   342 //
       
   343 void CPrivacyAndLocationHandler::OnRespondNetworkLocationRequest(const TLbsNetSessionIdInt& aRequestId, 
       
   344                             TLbsNetworkEnumInt::TLbsPrivacyResponseInt aRequestResult,
       
   345                             TInt aResponseReason)
       
   346 	{
       
   347 	LBSLOG2(ELogP3, "Received response %d to privacy request", aRequestResult);
       
   348 	CLbsPrivLocFsm* fsm = LookupFsm(aRequestId);
       
   349 	
       
   350 	if (NULL != fsm)
       
   351 		{
       
   352 		fsm->OnRespondNetworkLocationRequest(aRequestId, aRequestResult, aResponseReason);
       
   353 		}
       
   354 	else
       
   355 		{
       
   356 		LBSLOG_WARN(ELogP3, "Couldn't find a FSM with matching session Id");
       
   357 		}
       
   358     }
       
   359 
       
   360 // ----------------------------------------------------------------------------- 
       
   361 // CPrivacyAndLocationHandler::OnCancelNetworkLocationRequest
       
   362 // Description: Called by the Privacy Handler to report that a privacy check 
       
   363 // has been rejected. This may occur after it has already been accepted.
       
   364 // Handling of the response is delegated to the current state.
       
   365 // ----------------------------------------------------------------------------- 
       
   366 //
       
   367 void CPrivacyAndLocationHandler::OnCancelNetworkLocationRequest(const TLbsNetSessionIdInt& aRequestId)
       
   368     {
       
   369 	LBSLOG2(ELogP3, "Received cancellation to privacy request %d", aRequestId.SessionNum());
       
   370 	CLbsPrivLocFsm* fsm = LookupFsm(aRequestId);
       
   371 	
       
   372 	if (NULL != fsm)
       
   373 		{
       
   374 		fsm->OnCancelNetworkLocationRequest(aRequestId);
       
   375 		}
       
   376 	else
       
   377 		{
       
   378 		LBSLOG_WARN(ELogP3, "Couldn't find a FSM with matching session Id");
       
   379 		}
       
   380     }
       
   381 
       
   382 // ----------------------------------------------------------------------------- 
       
   383 // CPrivacyAndLocationHandler::OnMTLRRequest
       
   384 // Description: The Message Switch has forwarded a request to start an MTLR 
       
   385 // session.
       
   386 // Handling of the request is delegated to the current state.
       
   387 // ----------------------------------------------------------------------------- 
       
   388 //
       
   389 void CPrivacyAndLocationHandler::OnMTLRRequest(const TLbsNetSessionIdInt& aSessionId,
       
   390 					   TLbsNetworkEnumInt::TLbsNetProtocolServiceInt aSessionType, 
       
   391 					   TBool aIsEmergency,
       
   392 					   const TLbsExternalRequestInfo& aExternalRequestInfo,
       
   393 					   const TLbsNetPosRequestPrivacyInt& aNetPosRequestPrivacy)
       
   394 	{
       
   395 	LBSLOG2(ELogP3, "Received privacy request with id %d", aSessionId.SessionNum());
       
   396 	CLbsPrivLocFsm* fsm = LookupFsm(aSessionId);
       
   397 
       
   398 	if (fsm==NULL)
       
   399 		{
       
   400 		fsm = GetNewFsm(aSessionId, aSessionType, aIsEmergency);
       
   401 		}
       
   402 	
       
   403 	if (NULL != fsm)
       
   404 		{
       
   405 		fsm->OnMTLRRequest(aSessionId, 
       
   406 						   aSessionType, 
       
   407 						   aIsEmergency, 
       
   408 						   aExternalRequestInfo, 
       
   409 						   aNetPosRequestPrivacy);
       
   410 		}
       
   411 	else
       
   412 		{					
       
   413 		// Failed to create a state machine for this request,
       
   414 		// so simply reply with a privacy rejection.
       
   415 		iMessageSwitch->SendMTLRResponse(aSessionId, 
       
   416 										 TLbsNetworkEnumInt::EPrivacyResponseRejected,
       
   417 										 KErrGeneral, EFalse); // can't be an emergency cuase we know we have a Fsm for these!
       
   418 		}
       
   419 	}
       
   420 	
       
   421 // ----------------------------------------------------------------------------- 
       
   422 // CPrivacyAndLocationHandler::OnSessionComplete
       
   423 // Description: The Message Switch has reported that the session is
       
   424 // over (complete or aborted due to some error).
       
   425 // Handling of the message is delegated to the current state.
       
   426 // ----------------------------------------------------------------------------- 
       
   427 //
       
   428 void CPrivacyAndLocationHandler::OnSessionComplete(
       
   429 									const TLbsNetSessionIdInt& aSessionId,
       
   430 									TInt aReason)
       
   431 	{
       
   432 	LBSLOG3(ELogP3, "Received Session Complete for id %d, reason %d", aSessionId.SessionNum(), aReason);
       
   433 	CLbsPrivLocFsm* fsm = LookupFsm(aSessionId);
       
   434 	
       
   435 	if (NULL != fsm)
       
   436 		{
       
   437 		fsm->OnSessionComplete(aSessionId, aReason);
       
   438 
       
   439 		// The session complete marks the end of a session.
       
   440 		TInt index = iFsmArray.Find(fsm);
       
   441 		if (index != KErrNotFound)
       
   442 			{ 
       
   443 			
       
   444 			if (fsm->SessionType()== TLbsNetworkEnumInt::EServiceSelfLocation)
       
   445 				{
       
   446 				iMolRFsm = NULL;
       
   447 				}
       
   448 			else if (fsm->SessionType()== TLbsNetworkEnumInt::EServiceTransmitThirdParty)
       
   449 				{
       
   450 				iX3pFsm = NULL;
       
   451 				}
       
   452 			
       
   453 			// We should never delete the emergency FSM.
       
   454 			iFsmArray.Remove(index);
       
   455 			iNumActiveSessions--;
       
   456 			
       
   457 			if (fsm != iEmergencyFsm)
       
   458 				{
       
   459 				delete fsm;
       
   460 				}
       
   461 			}
       
   462 		}
       
   463 	else
       
   464 		{
       
   465 		LBSLOG_WARN(ELogP3, "Couldn't find a FSM with matching session Id");
       
   466 		}
       
   467 	}
       
   468 
       
   469 // ----------------------------------------------------------------------------- 
       
   470 // CPrivacyAndLocationHandler::OnNetLocRequest
       
   471 // Description: The Message Switch has passed on a request for a position update
       
   472 // Handling of the request is delegated to the current state.
       
   473 // ----------------------------------------------------------------------------- 
       
   474 //
       
   475 void CPrivacyAndLocationHandler::OnNetLocRequest(
       
   476 						const TLbsNetSessionIdInt& aSessionId, 
       
   477 						const TLbsNetPosRequestMethodInt& aPosRequestMethod,
       
   478 						TLbsNetworkEnumInt::TLbsNetProtocolServiceInt aSessionType, 
       
   479 						TBool aIsEmergency,
       
   480 						const TLbsNetPosRequestQualityInt& aQuality)
       
   481 	{
       
   482 	LBSLOG2(ELogP3, "Received position update request for id %d", aSessionId.SessionNum());
       
   483 	
       
   484 	TLbsNetSessionIdInt sessionId;
       
   485 	TPositionInfo    posInfo;
       
   486 	TPosition		 pos;
       
   487 	TTime 			 timeStamp;
       
   488 	TInt 			 err;
       
   489 	
       
   490 	TBool tapMode = EFalse;
       
   491 	TInt numMethods = aPosRequestMethod.NumPosMethods();
       
   492     if (numMethods==1)
       
   493     	{
       
   494     	TLbsNetPosMethodInt netPosMethod;
       
   495     	aPosRequestMethod.GetPosMethod(0,netPosMethod);
       
   496                  
       
   497     	if (netPosMethod.PosMode()== (TPositionModuleInfo::ETechnologyNetwork | TPositionModuleInfo::ETechnologyAssisted))
       
   498     		{
       
   499     		tapMode = ETrue;
       
   500     		}
       
   501     	}
       
   502 	
       
   503 	// This filtering used to be in the NG Message Switch, but has been moved
       
   504 	// here to get an access to the ref position bus
       
   505 	
       
   506 	if( (aSessionType == TLbsNetworkEnumInt::EServiceNetworkLocation) && !tapMode)
       
   507 		{
       
   508 		// A Network-based location request generates a location 
       
   509 		// request to the network request handler, but there's no point 
       
   510 		// passing it any further - the AGPS manager & privacy 
       
   511 		// controller aren't interested.
       
   512 		// Simply return the saved reference location
       
   513 		err = iMessageSwitch->GetNetworkReferencePosition(aSessionId, posInfo);			
       
   514 		posInfo.GetPosition(pos);
       
   515 		timeStamp = pos.Time();
       
   516 		TLbsNetPosRequestQualityInt dummyQuality;
       
   517 		MessageSwitch()->SendNetLocResponse(aSessionId, err, dummyQuality, posInfo, timeStamp, EFalse);
       
   518 		}
       
   519 	else
       
   520 		{
       
   521 		// we note that a self locate MoLr session can be implicitly
       
   522 		// cancelled by the start of a new session for a new client.
       
   523 		// In this case we complete the session before creating a new
       
   524 		// fsm for the new client 
       
   525 		CLbsPrivLocFsm* fsm = LookupFsm(aSessionId);
       
   526 		if (!fsm)
       
   527 			{
       
   528 			// here, we need to create a new fsm
       
   529 			// We note that only one self locate MolR (or X3p) is supported
       
   530 			// a new one will implicitly cancel any ongoing
       
   531 			if(aSessionType == TLbsNetworkEnumInt::EServiceSelfLocation)
       
   532 				{
       
   533 				if (iMolRFsm)
       
   534 					{
       
   535 					TInt index = iFsmArray.Find(iMolRFsm);
       
   536 					if (index != KErrNotFound)
       
   537 						{ 
       
   538 						iFsmArray.Remove(index);
       
   539 						iNumActiveSessions--;
       
   540 						delete iMolRFsm;
       
   541 						iMolRFsm = NULL;
       
   542 						}
       
   543 					}
       
   544 					
       
   545 				}
       
   546 			else if(aSessionType == TLbsNetworkEnumInt::EServiceTransmitThirdParty)
       
   547 				{
       
   548 				if (iX3pFsm)
       
   549 					{
       
   550 					TInt index = iFsmArray.Find(iX3pFsm);
       
   551 					if (index != KErrNotFound)
       
   552 						{ 
       
   553 						iFsmArray.Remove(index);
       
   554 						iNumActiveSessions--;
       
   555 						delete iX3pFsm;
       
   556 						iX3pFsm = NULL;
       
   557 						}
       
   558 					}
       
   559 				}
       
   560 				
       
   561 			fsm = GetNewFsm(aSessionId, aSessionType, aIsEmergency);
       
   562 			}
       
   563 		
       
   564 		if (NULL != fsm)
       
   565 			{
       
   566 			if(aSessionType == TLbsNetworkEnumInt::EServiceSelfLocation)
       
   567 				{
       
   568 				iMolRFsm = fsm;
       
   569 				}
       
   570 			else if(aSessionType == TLbsNetworkEnumInt::EServiceTransmitThirdParty)
       
   571 				{
       
   572 				iX3pFsm = fsm;
       
   573 				}
       
   574 			
       
   575 			fsm->OnNetLocRequest(aSessionId,
       
   576 					aPosRequestMethod, 
       
   577 			 					aSessionType, 
       
   578 								aIsEmergency, 
       
   579 								aQuality);
       
   580 			}			
       
   581 		else
       
   582 			{
       
   583 			// TODO: Return a dummy loc response with error code?
       
   584 			LBSLOG_WARN(ELogP3, "Couldn't find a FSM with matching session Id");
       
   585 			}
       
   586 		}
       
   587 	}
       
   588 
       
   589 /** Called when a reference position arrives from the network.
       
   590 */
       
   591 void CPrivacyAndLocationHandler::OnNetLocReferenceUpdate(
       
   592 		const TLbsNetSessionIdInt& aSessionId, 
       
   593 		const TPositionInfoBase& aPosInfo)
       
   594 	{
       
   595 	LBSLOG2(ELogP3, "Received reference position update for id %d", aSessionId.SessionNum());
       
   596 	CLbsPrivLocFsm* fsm = LookupFsm(aSessionId);
       
   597 	
       
   598 	if (NULL != fsm)
       
   599 		{
       
   600 		fsm->OnNetLocReferenceUpdate(aSessionId, aPosInfo);
       
   601 		}
       
   602 	else
       
   603 		{
       
   604 		LBSLOG_WARN(ELogP3, "Couldn't find a FSM with matching session Id");
       
   605 		}	
       
   606 	}
       
   607 
       
   608 /** Callend when a final location arrives from the network.
       
   609 */
       
   610 void CPrivacyAndLocationHandler::OnNetLocFinalUpdate(
       
   611 		const TLbsNetSessionIdInt& aSessionId, 
       
   612 		const TPositionInfoBase& aPosInfo)
       
   613 	{
       
   614 	LBSLOG2(ELogP3, "Received final network position update for id %d", aSessionId.SessionNum());
       
   615 	CLbsPrivLocFsm* fsm = LookupFsm(aSessionId);
       
   616 	
       
   617 	if (NULL != fsm)
       
   618 		{
       
   619 		fsm->OnNetLocFinalUpdate(aSessionId, aPosInfo);
       
   620 		}
       
   621 	else
       
   622 		{
       
   623 		LBSLOG_WARN(ELogP3, "Couldn't find a FSM with matching session Id");
       
   624 		}
       
   625 	}
       
   626 
       
   627 /** Callback when a GPS position update arrives from AGPS manager.
       
   628 */
       
   629 void CPrivacyAndLocationHandler::OnAgpsPositionUpdate(
       
   630 	TInt aReason,
       
   631 	const TPositionExtendedSatelliteInfo& aPosInfo,
       
   632 	const TTime& aTimeStamp)
       
   633 	{
       
   634 	// Broadcast the update to all state machines.
       
   635 	const TInt count = iFsmArray.Count();
       
   636 	for (TInt i = 0; i < count; i++)
       
   637 		{
       
   638 		iFsmArray[i]->OnAgpsPositionUpdate(aReason, aPosInfo, aTimeStamp);
       
   639 		}
       
   640 	}
       
   641 
       
   642 /** Callback when a GPS measurement results update arrives from AGPS manager.
       
   643 */
       
   644 void CPrivacyAndLocationHandler::OnAgpsMeasurementUpdate(
       
   645 	TInt aReason,
       
   646 	const TPositionGpsMeasurementInfo& aPosInfo,
       
   647 	const TTime& aTimeStamp)
       
   648 	{
       
   649 	// Broadcast the update to all state machines
       
   650 	const TInt count = iFsmArray.Count();
       
   651 	for (TInt i = 0; i < count; i++)
       
   652 		{
       
   653 		iFsmArray[i]->OnAgpsMeasurementUpdate(aReason, aPosInfo, aTimeStamp);
       
   654 		}
       
   655 	}
       
   656 
       
   657 /**
       
   658 */
       
   659 CAgpsInterfaceHandler* CPrivacyAndLocationHandler::AgpsHandler()
       
   660 	{
       
   661 	return iAgpsInterface;
       
   662 	}
       
   663 	
       
   664 // -----------------------------------------------------------------------------
       
   665 // CPrivacyAndLocationHandler::DeviceGpsModeCaps
       
   666 // Description: Return the device mode capabilities
       
   667 // -----------------------------------------------------------------------------
       
   668 //
       
   669 TPositionModuleInfoExtended::TDeviceGpsModeCapabilities CPrivacyAndLocationHandler::DeviceGpsModeCaps()
       
   670 	{
       
   671 	return iDeviceGpsModeCaps;
       
   672 	}
       
   673 
       
   674 // -----------------------------------------------------------------------------
       
   675 // CPrivacyAndLocationHandler::BehaviourMode
       
   676 // Description: Return the behaviour mode setting
       
   677 // -----------------------------------------------------------------------------
       
   678 //
       
   679 CLbsAdmin::TLbsBehaviourMode CPrivacyAndLocationHandler::BehaviourMode()
       
   680 	{
       
   681 	return iLbsBehaviourMode;
       
   682 	}
       
   683 
       
   684 RLbsNetworkRegistrationStatus& CPrivacyAndLocationHandler::NetworkRegistrationStatus()
       
   685 	{
       
   686 	return iNetRegStatus;
       
   687 	}
       
   688 	
       
   689 
       
   690 /**
       
   691 */
       
   692 MX3pStatusHandler& CPrivacyAndLocationHandler::X3pStatusHandler()
       
   693 	{
       
   694 	return *iAgpsInterface;
       
   695 	}
       
   696 
       
   697 /** Returns ETrue if KLbsSpecialFeatureIntermediateFutileUpdate is on.
       
   698 @return ETrue if the special feature is on, EFalse otherwise.
       
   699 */
       
   700 TBool CPrivacyAndLocationHandler::IsSpecialFeatureIntermediateFutileUpdateOn()
       
   701 	{
       
   702 	return iSpecialFeatureIntermediateFutileUpdate;
       
   703 	}
       
   704 
       
   705 // ----------------------------------------------------------------------------- 
       
   706 // 
       
   707 // ----------------------- Class CLbsPrivLocStateBase --------------------
       
   708 //
       
   709 // This class is not intended for instantiation. Implemented functions are
       
   710 // those common to multiple derived states
       
   711 //
       
   712 // ----------------------------------------------------------------------------- 
       
   713 //
       
   714 
       
   715 // ----------------------------------------------------------------------------- 
       
   716 // CLbsPrivLocStateBase::OnCancelNetworkLocationRequest
       
   717 // Description: Pass on a received privacy request cancel to the network gateway, 
       
   718 // if it relates to the current session. 
       
   719 // This behaviour is common to states EStateWaitLocationRequest,
       
   720 // EStateWaitLocationUpdate and EStateWaitPrivacyResponse.
       
   721 // Other states ignore the event.
       
   722 // ----------------------------------------------------------------------------- 
       
   723 //
       
   724 void CLbsPrivLocStateBase::OnCancelNetworkLocationRequest(const TLbsNetSessionIdInt& aSessionId)
       
   725 	{
       
   726 	/* Ignore the cancel if this is an emergency request */
       
   727 	if(!iFsm->IsEmergency())
       
   728 		{
       
   729 		// Also ignore it if the cancel doesn't relate to this session.
       
   730 		if(aSessionId == iFsm->SessionId())
       
   731 			{
       
   732 			iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitCancelledByPrivacyController, KErrCancel);
       
   733 			iFsm->ChangeState(CLbsPrivLocFsm::EStateIdle, aSessionId);
       
   734 			}
       
   735 		}
       
   736 	}
       
   737 
       
   738 // ----------------------------------------------------------------------------- 
       
   739 // CLbsPrivLocStateBase::OnEntry
       
   740 // Description: Handles initialisation actions which are common to multiple states. 
       
   741 // ----------------------------------------------------------------------------- 
       
   742 //
       
   743 void CLbsPrivLocStateBase::OnEntry(const TPrivLocCommonParams& /* aStateParams */)
       
   744 	{
       
   745 	// Exit reason should always be explicitly set by a state, 
       
   746 	// otherwise OnExit() will panic
       
   747 	iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitReasonNone, KErrNone);
       
   748 	}
       
   749 	
       
   750 	
       
   751 // ----------------------------------------------------------------------------- 
       
   752 // CLbsPrivLocStateBase::OnExit
       
   753 // Description: Handles exit actions which are common to multiple states. 
       
   754 // Any exit reason not handled here is delegated to the current state.
       
   755 // ----------------------------------------------------------------------------- 
       
   756 //
       
   757 TBool CLbsPrivLocStateBase::OnExit()
       
   758 	{
       
   759 	TBool consumed = ETrue;
       
   760 	switch(iFsm->iExitData.iExitReason)
       
   761 		{
       
   762 		case TPrivLocStateExitData::EExitSessionComplete:
       
   763 			{
       
   764 			// Tell the AGPS interface handle this location request has finished.
       
   765 			AgpsInterface()->StopPositioning(iFsm->SessionId());
       
   766 
       
   767 			// Tell the privacy controller this session is finished.
       
   768 			PrivacyHandler()->ProcessRequestComplete(iFsm->SessionId(),
       
   769 													 iFsm->ExitData().iExitInfo);
       
   770 			break;
       
   771 			}
       
   772 
       
   773 		case TPrivLocStateExitData::EExitCancelledByPrivacyController:
       
   774 			{
       
   775 			// Send a cancel to the network gateway
       
   776 			TPositionInfo dummyPosInfo;
       
   777 			TTime dummyTime;
       
   778 			TLbsNetPosRequestQualityInt dummyQuality;
       
   779 			MessageSwitch()->SendNetLocResponse(iFsm->SessionId(),
       
   780 												iFsm->ExitData().iExitInfo,
       
   781 												dummyQuality,
       
   782 												dummyPosInfo,
       
   783 												dummyTime,
       
   784 												iFsm->IsEmergency());
       
   785 			}
       
   786 			break;
       
   787 
       
   788 		case TPrivLocStateExitData::EExitLocReqReceived:
       
   789 			// No action required - request is issued on entry to next state.
       
   790 		case TPrivLocStateExitData::EExitPrivacyRequestReceived:
       
   791 			// No action required, state moves to waiting for loc request.
       
   792 			{
       
   793 			consumed = ETrue;
       
   794 			break;			
       
   795 			}
       
   796 			
       
   797 		default:
       
   798 			{
       
   799 			// Don't know what to do with it.
       
   800 			consumed = EFalse;
       
   801 			break;							
       
   802 			}
       
   803 		}
       
   804 	return(consumed);
       
   805 	}
       
   806 	
       
   807 // ----------------------------------------------------------------------------- 
       
   808 // CLbsPrivLocStateBase::HandleLocRequest
       
   809 // Description: Common handling of a location request received while the 
       
   810 // Privacy and Location Handler is dealing with a session.
       
   811 // 
       
   812 // If the session type is anything but MTLR, then it is processed, otherwise
       
   813 // a privacy request is generated
       
   814 // ----------------------------------------------------------------------------- 
       
   815 //
       
   816 void CLbsPrivLocStateBase::HandleLocRequest(const TLbsNetSessionIdInt& aSessionId, 
       
   817 						 const TLbsNetPosRequestMethodInt& aPosRequestMethod,
       
   818 						 TLbsNetworkEnumInt::TLbsNetProtocolServiceInt aSessionType, 
       
   819 						 TBool aIsEmergency,
       
   820 						 const TLbsNetPosRequestQualityInt& aQuality)
       
   821 	{
       
   822 	// MTLR.
       
   823 	if (aSessionType == TLbsNetworkEnumInt::EServiceMobileTerminated)
       
   824 		{
       
   825 		// An MTLR with out a prior privacy request is not supported, report error via
       
   826 		// RespondLocationRequest(dummy position).
       
   827 		TPositionInfo dummyPosInfo;
       
   828 		TTime dummyTime;
       
   829 		TLbsNetPosRequestQualityInt dummyQuality;
       
   830 
       
   831 		MessageSwitch()->SendNetLocResponse(aSessionId,
       
   832 											KErrNotSupported,
       
   833 											dummyQuality,
       
   834 											dummyPosInfo,
       
   835 											dummyTime, aIsEmergency); 
       
   836 		}
       
   837 
       
   838 	// Network Induced.	
       
   839 	else if (aSessionType == TLbsNetworkEnumInt::EServiceNetworkInduced)
       
   840 		{
       
   841 		// If a request for a position update has been received without
       
   842 		// a privacy request, then there's nothing to say how the user
       
   843 		// should be informed or what do do if there is no response.
       
   844 		// The safest thing is to get the user to confirm (verify)
       
   845 		// the request, and in the absence of confirmation to reject the
       
   846 		// request. For emergency requests we notify and accept.
       
   847 		
       
   848 		// Store the loc req.
       
   849 		iFsm->LocReqReceived() = ETrue;
       
   850 
       
   851 		iFsm->IsEmergency() = aIsEmergency;
       
   852 		iFsm->NetRequestQuality() = aQuality;
       
   853 		iFsm->PosRequestMethod() = aPosRequestMethod;
       
   854 
       
   855 
       
   856 		// The following notification types are chosen based on the emergency and network requests admin status.
       
   857 		//
       
   858 		// Emergency = On, Admin = Any, gives ENotifyLocationAccepted 
       
   859 		// Emergency = Off,	Admin = On, gives ENotifyLocationAccepted
       
   860 		// Emergency = Off,	Admin = OnButAlwayVerify, gives ENotifyAndVerifyLocationRejectedIfNoResponse
       
   861 		// Emergency = Off, Admin = Off, N/A the notifier or controller will not be called
       
   862 		// Emergency = Off, Admin = OffButNotify, gives ENotifyLocationRejected
       
   863 		TLbsNetPosRequestPrivacyInt requestPrivacy;
       
   864 		
       
   865 		requestPrivacy.SetRequestAdvice(TLbsNetPosRequestPrivacyInt::ERequestAdviceNotify);
       
   866 		requestPrivacy.SetRequestAction(TLbsNetPosRequestPrivacyInt::ERequestActionAllow);
       
   867 
       
   868 		// Verifications are rejected after timeout.
       
   869 		CLbsAdmin::TExternalLocateService externalLocate(CLbsAdmin::EExternalLocateOff);
       
   870 
       
   871 		ReadNetworkInducedAdminSetting(externalLocate);
       
   872 		if ((externalLocate == CLbsAdmin::EExternalLocateOnButAlwaysVerify) && (!aIsEmergency))
       
   873 			{
       
   874 	    	requestPrivacy.SetRequestAdvice(TLbsNetPosRequestPrivacyInt::ERequestAdviceVerify);
       
   875 	    	requestPrivacy.SetRequestAction(TLbsNetPosRequestPrivacyInt::ERequestActionReject);
       
   876 			}
       
   877 
       
   878 		// Similarly, default values have to be assigned to the external request info.
       
   879 		TLbsExternalRequestInfo requestInfo;
       
   880 		_LIT8(KUnknownExternalReqInfoField, "");
       
   881 		requestInfo.SetRequesterId(KUnknownExternalReqInfoField);
       
   882 		requestInfo.SetClientName(KUnknownExternalReqInfoField);
       
   883 		requestInfo.SetClientExternalId(KUnknownExternalReqInfoField);
       
   884 
       
   885 
       
   886 		// Process the privacy request.		
       
   887 		iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitLocReqReceived, KErrNone);
       
   888 		
       
   889 		TPrivLocWaitPrivResponseParams privacyRequestParams(aSessionId, aSessionType, requestInfo, requestPrivacy, aIsEmergency);
       
   890 		iFsm->ChangeState(CLbsPrivLocFsm::EStateWaitPrivacyResponse, privacyRequestParams);
       
   891 		}
       
   892 	
       
   893 	// All other location requests.
       
   894 	else
       
   895 		{
       
   896 		TPrivLocWaitLocationUpdateParams updateRequestParams(aSessionId,
       
   897 															aPosRequestMethod,
       
   898 															aSessionType,
       
   899 															aIsEmergency,
       
   900 															aQuality);
       
   901 		iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitSessionComplete, KErrCancel);
       
   902 		iFsm->ChangeState(CLbsPrivLocFsm::EStateWaitLocationUpdate, updateRequestParams);
       
   903 		}
       
   904 	}
       
   905 
       
   906 // ----------------------------------------------------------------------------- 
       
   907 // CLbsPrivLocStateBase::OnSessionComplete
       
   908 // Description: Common handling of a session complete message received other
       
   909 // than when it is expected as normal session completion.
       
   910 // ----------------------------------------------------------------------------- 
       
   911 //
       
   912 void CLbsPrivLocStateBase::OnSessionComplete(const TLbsNetSessionIdInt& aSessionId,
       
   913 																TInt aReason)
       
   914 	{
       
   915 	if(aSessionId == iFsm->SessionId())
       
   916 		{
       
   917 		iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitSessionComplete, aReason);
       
   918 		iFsm->ChangeState(CLbsPrivLocFsm::EStateIdle, aSessionId);	            
       
   919 		}		
       
   920 	}
       
   921 
       
   922 /** Called when a reference position arrives from the network.
       
   923 */
       
   924 void CLbsPrivLocStateBase::OnNetLocReferenceUpdate(
       
   925 		const TLbsNetSessionIdInt& /*aSessionId*/ , 
       
   926 		const TPositionInfoBase& aPosInfo)
       
   927 	{
       
   928 	TLbsNetworkEnumInt::TLbsNetProtocolServiceInt sessionType = iFsm->SessionType();
       
   929 	__ASSERT_DEBUG((sessionType != MLbsNetworkProtocolObserver::EServiceNone), Panic(ENrhPanicBadParamType));
       
   930 
       
   931 	if( ((sessionType == MLbsNetworkProtocolObserver::EServiceNetworkInduced) || 
       
   932 											   (sessionType == MLbsNetworkProtocolObserver::EServiceMobileTerminated)))
       
   933 		{
       
   934 		TPositionInfo posInfo = static_cast<const TPositionInfo&>(aPosInfo);
       
   935 		
       
   936 		// Set the module Id and position mode for the reference position.
       
   937 		// These values are not 'real' values, since this position
       
   938 		// came directly from the network and not one of the location
       
   939 		// managers within LBS.
       
   940 		posInfo.SetModuleId(KLbsGpsLocManagerUid);
       
   941 		posInfo.SetPositionMode(TPositionModuleInfo::ETechnologyNetwork);
       
   942 		posInfo.SetPositionModeReason(EPositionModeReasonNone);
       
   943 		posInfo.SetUpdateType(EPositionUpdateGeneral);
       
   944 		
       
   945 		if (!iFsm->RefPosProcessed())
       
   946 			{
       
   947 			iFsm->RefPosProcessed() = ETrue;
       
   948 			PrivacyHandler()->ProcessNetworkPositionUpdate(iFsm->SessionId(), posInfo);
       
   949 			}
       
   950 
       
   951 		}	
       
   952 	}
       
   953 
       
   954 /* Timer callback called when the MaxFixTime for a gps location update request has expired. 
       
   955 
       
   956 The default action is to ignore this callback. Any state interested in it must
       
   957 implement its own version.
       
   958 */
       
   959 void CLbsPrivLocStateBase::OnTimerEventL(TInt /*aTimerId*/)
       
   960 	{
       
   961 	}
       
   962 
       
   963 
       
   964 // ----------------------------------------------------------------------------- 
       
   965 // CLbsPrivLocStateBase::ReadNetworkInducedAdminSetting
       
   966 // Description: Determine the external location value from the admin settings for network induced location requests.
       
   967 // ----------------------------------------------------------------------------- 
       
   968 //
       
   969 void CLbsPrivLocStateBase::ReadNetworkInducedAdminSetting(CLbsAdmin::TExternalLocateService& aExternalLocateService)
       
   970 	{
       
   971 	CLbsAdmin::TExternalLocateService serviceStatus(CLbsAdmin::EExternalLocateOff);
       
   972 	RLbsNetworkRegistrationStatus::TLbsNetworkRegistrationStatus netRegStatus(RLbsNetworkRegistrationStatus::ENetworkRegistrationUnknown);	
       
   973 	TInt err = LbsNetworkRegistrationStatus().GetNetworkRegistrationStatus(netRegStatus);
       
   974 	if (err == KErrNone)
       
   975 		{
       
   976 		switch (netRegStatus)
       
   977 			{
       
   978 			case RLbsNetworkRegistrationStatus::ERegisteredHomeNetwork:
       
   979 				{
       
   980 				err = LbsAdmin()->Get(KLbsSettingHomeNetworkInducedLocate, serviceStatus);
       
   981 				break;
       
   982 				}
       
   983 			case RLbsNetworkRegistrationStatus::ERegisteredRoamingNetwork:
       
   984 			case RLbsNetworkRegistrationStatus::ENotRegistered:
       
   985 				{
       
   986 				err = LbsAdmin()->Get(KLbsSettingRoamingNetworkInducedLocate, serviceStatus);
       
   987 				break;
       
   988 				}		
       
   989 			case RLbsNetworkRegistrationStatus::ENetworkRegistrationUnknown:
       
   990 			default:
       
   991 				{
       
   992 				LBSLOG_WARN2(ELogP4, "Unrecognised TLbsNetworkRegistrationStatus (%d), defaulting to EExternalLocateOff",
       
   993 							 netRegStatus);
       
   994 				serviceStatus = CLbsAdmin::EExternalLocateOff;
       
   995 				break;
       
   996 				}
       
   997 			}
       
   998 		}
       
   999 	else
       
  1000 		{
       
  1001 		LBSLOG_WARN2(ELogP4, "Failed to get TExternalLocateService, couldn't read roaming status (err %d), defaulting to EExternalLocateOff",  
       
  1002 					 err);		
       
  1003 		}
       
  1004 	
       
  1005 	aExternalLocateService = serviceStatus;
       
  1006 	}
       
  1007 
       
  1008 // ----------------------------------------------------------------------------- 
       
  1009 // CLbsPrivLocStateBase::CLbsPrivLocStateBase
       
  1010 // Description: Constructor
       
  1011 // ----------------------------------------------------------------------------- 
       
  1012 //
       
  1013 CLbsPrivLocStateBase::CLbsPrivLocStateBase(CLbsPrivLocFsm* aFsm)
       
  1014 :	iFsm(aFsm)
       
  1015 	{	
       
  1016 	}
       
  1017 // ----------------------------------------------------------------------------- 
       
  1018 // CLbsPrivLocStateBase::PrivacyHandler, MessageSwitch, LbsAdmin
       
  1019 // Description: Allows concrete states access to NRH resources passed to
       
  1020 // the FSM
       
  1021 // Returns: pointers.
       
  1022 // ----------------------------------------------------------------------------- 
       
  1023 //
       
  1024 CPrivacyHandler* CLbsPrivLocStateBase::PrivacyHandler()
       
  1025 	{
       
  1026 	return iFsm->PrivLocHandler().PrivacyHandler();
       
  1027 	}
       
  1028 CNGMessageSwitch* CLbsPrivLocStateBase::MessageSwitch()
       
  1029 	{
       
  1030 	return iFsm->PrivLocHandler().MessageSwitch();
       
  1031 	}
       
  1032 CLbsAdmin* CLbsPrivLocStateBase::LbsAdmin()
       
  1033 	{
       
  1034 	return iFsm->PrivLocHandler().LbsAdmin();
       
  1035 	}
       
  1036 CAgpsInterfaceHandler* CLbsPrivLocStateBase::AgpsInterface()
       
  1037 	{
       
  1038 	return iFsm->PrivLocHandler().AgpsHandler();
       
  1039 	}
       
  1040 
       
  1041 
       
  1042 TPositionModuleInfoExtended::TDeviceGpsModeCapabilities CLbsPrivLocStateBase::DeviceGpsModeCaps()
       
  1043 	{
       
  1044 	return iFsm->PrivLocHandler().DeviceGpsModeCaps();
       
  1045 	}
       
  1046 
       
  1047 CLbsAdmin::TLbsBehaviourMode CLbsPrivLocStateBase::BehaviourMode()
       
  1048 	{
       
  1049 	return iFsm->PrivLocHandler().BehaviourMode();
       
  1050 	}
       
  1051 
       
  1052 RLbsNetworkRegistrationStatus& CLbsPrivLocStateBase::LbsNetworkRegistrationStatus()
       
  1053 	{
       
  1054 	return iFsm->PrivLocHandler().NetworkRegistrationStatus();
       
  1055 	}
       
  1056 
       
  1057 // ----------------------------------------------------------------------------- 
       
  1058 // 
       
  1059 // ----------------------- Class CLbsPrivLocIdleState --------------------
       
  1060 //
       
  1061 // Implements the Idle state of the Privacy and Location Request Handler
       
  1062 //
       
  1063 // ----------------------------------------------------------------------------- 
       
  1064 //
       
  1065 
       
  1066 // ----------------------------------------------------------------------------- 
       
  1067 // CLbsPrivLocIdleState::NewL
       
  1068 // Description: CLbsPrivLocIdleState static constructor 
       
  1069 // ----------------------------------------------------------------------------- 
       
  1070 //
       
  1071 CLbsPrivLocIdleState* CLbsPrivLocIdleState::NewL(CLbsPrivLocFsm* aFsm)
       
  1072 	{
       
  1073 	return new (ELeave) CLbsPrivLocIdleState(aFsm);
       
  1074 	}
       
  1075 	
       
  1076 // ----------------------------------------------------------------------------- 
       
  1077 // CLbsPrivLocIdleState::CLbsPrivLocIdleState
       
  1078 // Description: CLbsPrivLocIdleState constructor.
       
  1079 // ----------------------------------------------------------------------------- 
       
  1080 //
       
  1081 CLbsPrivLocIdleState::CLbsPrivLocIdleState(CLbsPrivLocFsm* aFsm) 
       
  1082 : CLbsPrivLocStateBase(aFsm)
       
  1083 	{
       
  1084 	}
       
  1085 
       
  1086 // ----------------------------------------------------------------------------- 
       
  1087 // CLbsPrivLocIdleState::OnEntry
       
  1088 // Description: Carries out tasks required on entry to the state.
       
  1089 // ----------------------------------------------------------------------------- 
       
  1090 //
       
  1091 void CLbsPrivLocIdleState::OnEntry(const TPrivLocCommonParams& aStateParams)
       
  1092 	{
       
  1093 	CLbsPrivLocStateBase::OnEntry(aStateParams);
       
  1094 	}
       
  1095 
       
  1096 // ----------------------------------------------------------------------------- 
       
  1097 // CLbsPrivLocIdleState::OnExit
       
  1098 // Description: Carries out tasks required on exit from the state.
       
  1099 // Panics if the exit reason is not handled by the base state exit
       
  1100 // ----------------------------------------------------------------------------- 
       
  1101 //
       
  1102 TBool CLbsPrivLocIdleState::OnExit()
       
  1103 	{
       
  1104 	TBool consumed = CLbsPrivLocStateBase::OnExit();
       
  1105 	// If the exit reason wasn't handled, panic (should only happen in development)
       
  1106 	__ASSERT_DEBUG(consumed, Panic(ENrhPanicIdleUnknownExitReason));
       
  1107 	
       
  1108 	return(consumed);
       
  1109 	}
       
  1110 	
       
  1111 // ----------------------------------------------------------------------------- 
       
  1112 // CLbsPrivLocIdleState::OnNetLocRequest
       
  1113 // Description: The Message Switch has forwarded a request for a control 
       
  1114 // measurement.
       
  1115 // If the session type is anything but MTLR, then it is processed, otherwise
       
  1116 // a privacy request is generated
       
  1117 // ----------------------------------------------------------------------------- 
       
  1118 //
       
  1119 void CLbsPrivLocIdleState::OnNetLocRequest(
       
  1120 		const TLbsNetSessionIdInt& aSessionId,
       
  1121 		const TLbsNetPosRequestMethodInt& aPosRequestMethod,
       
  1122 		TLbsNetworkEnumInt::TLbsNetProtocolServiceInt aSessionType, 
       
  1123 		TBool aIsEmergency,
       
  1124         const TLbsNetPosRequestQualityInt& aQuality)
       
  1125     {
       
  1126     iFsm->SessionType() = aSessionType;
       
  1127     if(iFsm->WasPrivacyResponseReceivedStateExited())
       
  1128         {
       
  1129         // The request relates to a rejected privacy request
       
  1130         // or a request for this session which has already been answered. 
       
  1131         // In either case, it should be refused. The message is sent to the
       
  1132         // network gateway as apart of exit from the state, but we want to 
       
  1133         // remain in Idle state.
       
  1134         iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitCancelledByPrivacyController, KErrAccessDenied);
       
  1135         iFsm->ChangeState(CLbsPrivLocFsm::EStateIdle, aSessionId);
       
  1136         }
       
  1137     else
       
  1138         {
       
  1139         TInt numMethods = aPosRequestMethod.NumPosMethods();
       
  1140         if (numMethods==1)
       
  1141             {
       
  1142             TLbsNetPosMethodInt netPosMethod;
       
  1143             aPosRequestMethod.GetPosMethod(0,netPosMethod);
       
  1144                     
       
  1145             if (netPosMethod.PosMode()== (TPositionModuleInfo::ETechnologyNetwork | TPositionModuleInfo::ETechnologyAssisted))
       
  1146                 {
       
  1147                 iFsm->TapMode() = ETrue;
       
  1148                 }
       
  1149             }
       
  1150         
       
  1151             
       
  1152         if ((aSessionType != MLbsNetworkProtocolObserver::EServiceMobileTerminated) &&
       
  1153             (aSessionType != MLbsNetworkProtocolObserver::EServiceNetworkInduced))
       
  1154             {
       
  1155             iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitLocReqReceived, KErrNone);
       
  1156             TPrivLocWaitLocationUpdateParams updateRequestParams(aSessionId,
       
  1157                                                             aPosRequestMethod,
       
  1158                                                             aSessionType,
       
  1159                                                             aIsEmergency,
       
  1160                                                             aQuality);
       
  1161             iFsm->ChangeState(CLbsPrivLocFsm::EStateWaitLocationUpdate, updateRequestParams);
       
  1162             }
       
  1163             else
       
  1164             {
       
  1165             // It's a request for a different session. Need to find out what to do with it.
       
  1166             HandleLocRequest(aSessionId, aPosRequestMethod, 
       
  1167                                     aSessionType,aIsEmergency,
       
  1168                                     aQuality);
       
  1169             }
       
  1170         }
       
  1171     }
       
  1172 
       
  1173 // ----------------------------------------------------------------------------- 
       
  1174 // CLbsPrivLocIdleState::OnMTLRRequest
       
  1175 // Description: The Message Switch has forwarded a request for a location update
       
  1176 // (a privacy request) 
       
  1177 // ----------------------------------------------------------------------------- 
       
  1178 //
       
  1179 void CLbsPrivLocIdleState::OnMTLRRequest(const TLbsNetSessionIdInt& aSessionId,
       
  1180 				TLbsNetworkEnumInt::TLbsNetProtocolServiceInt aSessionType,
       
  1181 				TBool aIsEmergency,
       
  1182 				const TLbsExternalRequestInfo& aExternalRequestInfo,
       
  1183 				const TLbsNetPosRequestPrivacyInt& aNetPosRequestPrivacy)
       
  1184 	{
       
  1185 	iFsm->SessionType() = aSessionType;
       
  1186 	iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitPrivacyRequestReceived, KErrNone);
       
  1187 	TPrivLocWaitPrivResponseParams privacyRequestParams(	aSessionId, 
       
  1188 													aSessionType,
       
  1189 													aExternalRequestInfo, 
       
  1190 													aNetPosRequestPrivacy,
       
  1191 													aIsEmergency);
       
  1192 	iFsm->ChangeState(CLbsPrivLocFsm::EStateWaitPrivacyResponse, privacyRequestParams);
       
  1193 	}
       
  1194 
       
  1195 /** Called when a reference position arrives from the network.
       
  1196  * 
       
  1197 */
       
  1198 void CLbsPrivLocIdleState::OnNetLocReferenceUpdate(
       
  1199 		const TLbsNetSessionIdInt& /*aSessionId*/, 
       
  1200 		const TPositionInfoBase& /* aPosInfo */)
       
  1201 	{
       
  1202 	// note that the reference postion is stored by the message switch
       
  1203 	// so here we don't need to save it again!
       
  1204 	}
       
  1205 	
       
  1206 // ----------------------------------------------------------------------------- 
       
  1207 // 
       
  1208 // ----------------------- Class CLbsPrivLocWaitPrivRespState --------------------
       
  1209 //
       
  1210 // Implements the Idle state of the Privacy and Location Request Handler
       
  1211 //
       
  1212 // ----------------------------------------------------------------------------- 
       
  1213 //
       
  1214 
       
  1215 // ----------------------------------------------------------------------------- 
       
  1216 // CLbsPrivLocWaitPrivRespState::NewL
       
  1217 // Description: CLbsPrivLocIdleState static constructor 
       
  1218 // ----------------------------------------------------------------------------- 
       
  1219 //
       
  1220 CLbsPrivLocWaitPrivRespState* CLbsPrivLocWaitPrivRespState::NewL(CLbsPrivLocFsm* aFsm)
       
  1221 	{
       
  1222 	return new (ELeave) CLbsPrivLocWaitPrivRespState(aFsm);
       
  1223 	}
       
  1224 	
       
  1225 // ----------------------------------------------------------------------------- 
       
  1226 // CLbsPrivLocWaitPrivRespState::CLbsPrivLocWaitPrivRespState
       
  1227 // Description: CLbsPrivLocWaitPrivRespState constructor.
       
  1228 // ----------------------------------------------------------------------------- 
       
  1229 //
       
  1230 CLbsPrivLocWaitPrivRespState::CLbsPrivLocWaitPrivRespState(CLbsPrivLocFsm* aFsm)
       
  1231 : CLbsPrivLocStateBase(aFsm)
       
  1232 	{
       
  1233 	}
       
  1234 
       
  1235 // ----------------------------------------------------------------------------- 
       
  1236 // CLbsPrivLocWaitPrivRespState::OnEntry
       
  1237 // Description: Actions performed when the state is entered.
       
  1238 // Unpack the parameters and issue the privacy request.
       
  1239 // ----------------------------------------------------------------------------- 
       
  1240 //
       
  1241 void CLbsPrivLocWaitPrivRespState::OnEntry(const TPrivLocCommonParams& aStateParams)
       
  1242 	{
       
  1243 	CLbsPrivLocStateBase::OnEntry(aStateParams);
       
  1244 	const TPrivLocWaitPrivResponseParams& params = TPrivLocWaitPrivResponseParams::Cast(const_cast<TPrivLocCommonParams&>(aStateParams));	
       
  1245 	iFsm->SessionType() = params.iSessionType;
       
  1246 	iFsm->IsEmergency() = params.iIsEmergency;
       
  1247 
       
  1248 	PrivacyHandler()->ProcessNetworkLocationRequest(iFsm->SessionId(), 
       
  1249 													iFsm->SessionType(),
       
  1250 													params.iExternalRequestInfo, 
       
  1251 													params.iNetPosRequestPrivacy,
       
  1252 													iFsm->IsEmergency());	
       
  1253 	}
       
  1254 
       
  1255 // ----------------------------------------------------------------------------- 
       
  1256 // CLbsPrivLocWaitPrivRespState::OnExit
       
  1257 // Description: Actions performed on leaving the state.
       
  1258 // ----------------------------------------------------------------------------- 
       
  1259 //
       
  1260 TBool CLbsPrivLocWaitPrivRespState::OnExit()
       
  1261 	{
       
  1262 	TInt consumed = EFalse;
       
  1263 	switch(iFsm->ExitData().iExitReason)
       
  1264 		{
       
  1265 		case TPrivLocStateExitData::EExitPrivacyResponseReceived:
       
  1266 			{
       
  1267             // Remember that we exited the privacy response received state 
       
  1268 			// so that we can deny the network location requests in the idle staet.
       
  1269 
       
  1270             iFsm->WasPrivacyResponseReceivedStateExited() = ETrue;
       
  1271 
       
  1272 			
       
  1273 			// For the NI case a Reference position may have arrived by now
       
  1274 			// So we must pass this onto the privacy handler.
       
  1275 
       
  1276 			if (iFsm->SessionType() == MLbsNetworkProtocolObserver::EServiceNetworkInduced) 
       
  1277 				{
       
  1278 				if (iFsm->PrivacyResponse() == CLbsNetworkProtocolBase::EPrivacyResponseAccepted)
       
  1279 					{
       
  1280 					TPositionInfo posInfo;
       
  1281 					TInt err = MessageSwitch()->GetNetworkReferencePosition(iFsm->SessionId(), posInfo);
       
  1282 					if (KErrNone == err)
       
  1283 						{
       
  1284 						if (!iFsm->RefPosProcessed())
       
  1285 							{
       
  1286 							iFsm->RefPosProcessed() = ETrue;
       
  1287 							PrivacyHandler()->ProcessNetworkPositionUpdate(iFsm->SessionId(), posInfo);
       
  1288 							}
       
  1289 				
       
  1290 						}
       
  1291 					
       
  1292 					}
       
  1293 				}		
       
  1294 				
       
  1295 			// For MtLrs the Protcol module should not
       
  1296 			// send a REF position until after we have sent the Priv response to the PM 
       
  1297 	            
       
  1298 			// Inform network of the privacy response for normal privacy requests.
       
  1299 			if (iFsm->SessionType() == TLbsNetworkEnumInt::EServiceMobileTerminated)
       
  1300 				{
       
  1301 				MessageSwitch()->SendMTLRResponse(iFsm->SessionId(), iFsm->PrivacyResponse(), iFsm->PrivacyResponseReason(), iFsm->IsEmergency());	
       
  1302 				}
       
  1303 
       
  1304 			// Inform network of a rejected privacy response via a "RespondLocationRequest" for faked privacy requests (generated internaly).
       
  1305 			else if ((iFsm->SessionType() == TLbsNetworkEnumInt::EServiceNetworkInduced) && (iFsm->PrivacyResponse() == TLbsNetworkEnumInt::EPrivacyResponseRejected))
       
  1306 				{
       
  1307 				// The faked privacy request was rejected, so reject the location request.
       
  1308 				TPositionInfo dummyPosInfo;
       
  1309 				TTime dummyTime;
       
  1310 				TLbsNetPosRequestQualityInt dummyQuality;
       
  1311 
       
  1312 				MessageSwitch()->SendNetLocResponse(iFsm->SessionId(),
       
  1313 													KErrAccessDenied,
       
  1314 													dummyQuality,
       
  1315 													dummyPosInfo,
       
  1316 													dummyTime,
       
  1317 													iFsm->IsEmergency());
       
  1318 				}
       
  1319 			
       
  1320 			consumed = ETrue;
       
  1321 			break;
       
  1322 			}
       
  1323 
       
  1324 		case TPrivLocStateExitData::EExitCancelledByPrivacyController:
       
  1325 			{
       
  1326 			// Send a cancel to the network gateway
       
  1327 			iFsm->PrivacyResponse() = TLbsNetworkEnumInt::EPrivacyResponseRejected;
       
  1328 			iFsm->PrivacyResponseReason() = KErrCancel;
       
  1329 			MessageSwitch()->SendMTLRResponse(iFsm->SessionId(), iFsm->PrivacyResponse(), iFsm->PrivacyResponseReason(), iFsm->IsEmergency());
       
  1330 			consumed = ETrue;
       
  1331 			}
       
  1332 			break;
       
  1333 
       
  1334 		default:
       
  1335 			{
       
  1336 			consumed = CLbsPrivLocStateBase::OnExit();
       
  1337 			// If the exit reason wasn't handled, panic (should only happen in development)
       
  1338 			__ASSERT_DEBUG(consumed, Panic(ENrhPanicWaitPrivRespUnknownExitReason));
       
  1339 			break;
       
  1340 			}
       
  1341 		}
       
  1342 		
       
  1343 	iFsm->LocReqReceived() = EFalse;
       
  1344 
       
  1345 	return(consumed);
       
  1346 	}
       
  1347 
       
  1348 // ----------------------------------------------------------------------------- 
       
  1349 // CLbsPrivLocWaitPrivRespState::OnRespondNetworkLocationRequest
       
  1350 // Description: Pass on a received privacy response to the network gateway, if
       
  1351 // it relates to the current session.
       
  1352 // ----------------------------------------------------------------------------- 
       
  1353 //
       
  1354 void CLbsPrivLocWaitPrivRespState::OnRespondNetworkLocationRequest(
       
  1355 											const TLbsNetSessionIdInt& aSessionId, 
       
  1356 											TLbsNetworkEnumInt::TLbsPrivacyResponseInt aRequestResult,
       
  1357 											TInt /* aResponseReason*/)
       
  1358 	{
       
  1359 
       
  1360 	if(aSessionId == iFsm->SessionId())
       
  1361 		{
       
  1362 		iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitPrivacyResponseReceived, KErrNone);
       
  1363 		iFsm->PrivacyResponse() = aRequestResult;
       
  1364 		if(iFsm->PrivacyResponse() == TLbsNetworkEnumInt::EPrivacyResponseAccepted)
       
  1365 			{
       
  1366 			// Tell the AGPS handler that we are going to start a location request soon.
       
  1367 			AgpsInterface()->PreStartPositioning(iFsm->SessionId(), iFsm->IsEmergency());
       
  1368 			
       
  1369 			if(iFsm->LocReqReceived())
       
  1370 				{				
       
  1371 				TPrivLocWaitLocationUpdateParams updateRequestParams(iFsm->SessionId(),
       
  1372 																iFsm->PosRequestMethod(),
       
  1373 																iFsm->SessionType(),
       
  1374 																iFsm->IsEmergency(),
       
  1375 																iFsm->NetRequestQuality());
       
  1376 				iFsm->ChangeState(CLbsPrivLocFsm::EStateWaitLocationUpdate, updateRequestParams);	            
       
  1377 				}
       
  1378 			else
       
  1379 				{
       
  1380 				TPrivLocWaitLocationRequestParams locationRequestParams(iFsm->SessionId(),
       
  1381 																		iFsm->IsEmergency(),
       
  1382 																		EFalse);
       
  1383 				iFsm->ChangeState(CLbsPrivLocFsm::EStateWaitLocationRequest, locationRequestParams);
       
  1384 				}
       
  1385 			}
       
  1386 		else
       
  1387 			{
       
  1388 			iFsm->ChangeState(CLbsPrivLocFsm::EStateIdle, aSessionId);
       
  1389 			}
       
  1390 		}
       
  1391 	}
       
  1392 	
       
  1393 // ----------------------------------------------------------------------------- 
       
  1394 // CLbsPrivLocWaitPrivRespState::OnNetLocRequest
       
  1395 // Description: The Message Switch has forwarded a request for a control 
       
  1396 // measurement.
       
  1397 // If the session Id is the same as the current one, then save the parameters
       
  1398 // so that the request can be issued when privacy is accepted.
       
  1399 // Otherwise (the session Id is different) a cancel is implied and we cancel 
       
  1400 // the current session and start another, which may or may not require a new 
       
  1401 // privacy query.
       
  1402 // ----------------------------------------------------------------------------- 
       
  1403 //
       
  1404 void CLbsPrivLocWaitPrivRespState::OnNetLocRequest(
       
  1405 		const TLbsNetSessionIdInt& aSessionId,
       
  1406 		const TLbsNetPosRequestMethodInt& aPosRequestMethod,
       
  1407 		TLbsNetworkEnumInt::TLbsNetProtocolServiceInt aSessionType, 
       
  1408 		TBool aIsEmergency,
       
  1409         const TLbsNetPosRequestQualityInt& aQuality)
       
  1410 	{	
       
  1411 	TInt numMethods = aPosRequestMethod.NumPosMethods();
       
  1412 	if (numMethods==1)
       
  1413 		{
       
  1414 		TLbsNetPosMethodInt netPosMethod;
       
  1415 		aPosRequestMethod.GetPosMethod(0,netPosMethod);
       
  1416 				
       
  1417 		if (netPosMethod.PosMode()== (TPositionModuleInfo::ETechnologyNetwork | TPositionModuleInfo::ETechnologyAssisted))
       
  1418 			{
       
  1419 			iFsm->TapMode() = ETrue;
       
  1420 			}
       
  1421 		}
       
  1422 	if(aSessionId == iFsm->SessionId() && 
       
  1423 		aIsEmergency == iFsm->IsEmergency() &&
       
  1424 		aSessionType == iFsm->SessionType())
       
  1425 		{
       
  1426 		iFsm->PosRequestMethod() = aPosRequestMethod;
       
  1427 		iFsm->NetRequestQuality() = aQuality;
       
  1428 		iFsm->LocReqReceived() = ETrue;
       
  1429 		}
       
  1430 	else
       
  1431 		{
       
  1432 		// It's a request for different session. Need to find out what to do with it.
       
  1433 		HandleLocRequest(aSessionId,aPosRequestMethod, 
       
  1434 							aSessionType,aIsEmergency,
       
  1435 							aQuality);
       
  1436 		}
       
  1437 	}
       
  1438 	
       
  1439 	
       
  1440 void CLbsPrivLocWaitPrivRespState::OnMTLRRequest(const TLbsNetSessionIdInt& /*aSessionId*/,
       
  1441 					   TLbsNetworkEnumInt::TLbsNetProtocolServiceInt /*aSessionType*/, 
       
  1442 					   TBool /*aIsEmergency*/,
       
  1443 					   const TLbsExternalRequestInfo& /*aExternalRequestInfo*/,
       
  1444 					   const TLbsNetPosRequestPrivacyInt& /*aNetPosRequestPrivacy*/)
       
  1445 	{
       
  1446 	// this can never happen. If the Fsm is in the WaitPrivRespState then 
       
  1447 	// any arrival of a MTLR request would start a new session (no implicit cancel!)
       
  1448 	// and the OnMTLRRequest()would be directed to that session not this one
       
  1449 	__ASSERT_DEBUG(EFalse, Panic(ENrhPanicBadParamType));
       
  1450 	}
       
  1451 
       
  1452 /** Called when a reference position arrives from the network.
       
  1453  *  
       
  1454 */
       
  1455 void CLbsPrivLocWaitPrivRespState::OnNetLocReferenceUpdate(
       
  1456 		const TLbsNetSessionIdInt& /*aSessionId*/, 
       
  1457 		const TPositionInfoBase& /*aPosInfo*/)
       
  1458 	{
       
  1459 	// note that the reference postion is stored by the message switch
       
  1460 	// so here we don't need to save it again!
       
  1461 	}
       
  1462 	
       
  1463 	
       
  1464 // ----------------------------------------------------------------------------- 
       
  1465 // 
       
  1466 // ----------------------- Class CLbsPrivLocWaitLocUpdateState --------------------
       
  1467 //
       
  1468 // Implements the Wait For Location Update state of the Privacy and Location 
       
  1469 // Request Handler
       
  1470 //
       
  1471 // On entry, issues a location update request then starts a timer and waits for 
       
  1472 // a response.
       
  1473 //
       
  1474 // ----------------------------------------------------------------------------- 
       
  1475 //
       
  1476 
       
  1477 // ----------------------------------------------------------------------------- 
       
  1478 // CLbsPrivLocWaitLocUpdateState::NewL
       
  1479 // Description: CLbsPrivLocWaitLocUpdateState static constructor 
       
  1480 // ----------------------------------------------------------------------------- 
       
  1481 //
       
  1482 CLbsPrivLocWaitLocUpdateState* CLbsPrivLocWaitLocUpdateState::NewL(CLbsPrivLocFsm* aFsm)
       
  1483 	{
       
  1484 	CLbsPrivLocWaitLocUpdateState* self; 
       
  1485 	self = new (ELeave) CLbsPrivLocWaitLocUpdateState(aFsm);
       
  1486 	CleanupStack::PushL(self);
       
  1487 	self->ConstructL();
       
  1488 	CleanupStack::Pop(self);
       
  1489 	return(self);	
       
  1490 	}
       
  1491 	
       
  1492 // ----------------------------------------------------------------------------- 
       
  1493 // CLbsPrivLocWaitLocUpdateState::CLbsPrivLocWaitLocUpdateState
       
  1494 // Description: CLbsPrivLocWaitLocUpdateState constructor.
       
  1495 // ----------------------------------------------------------------------------- 
       
  1496 //
       
  1497 CLbsPrivLocWaitLocUpdateState::CLbsPrivLocWaitLocUpdateState(CLbsPrivLocFsm* aFsm)
       
  1498 : CLbsPrivLocStateBase(aFsm)
       
  1499 	{
       
  1500 	}
       
  1501 
       
  1502 // ----------------------------------------------------------------------------- 
       
  1503 // CLbsPrivLocWaitLocUpdateState::~CLbsPrivLocWaitLocUpdateState
       
  1504 // Description: CLbsPrivLocWaitLocUpdateState destructor.
       
  1505 // ----------------------------------------------------------------------------- 
       
  1506 //
       
  1507 CLbsPrivLocWaitLocUpdateState::~CLbsPrivLocWaitLocUpdateState()
       
  1508 	{
       
  1509 	}
       
  1510 
       
  1511 // ----------------------------------------------------------------------------- 
       
  1512 // CLbsPrivLocIdleState::ConstructL
       
  1513 // Description: CLbsPrivLocIdleState second-phase constructor.
       
  1514 // ----------------------------------------------------------------------------- 
       
  1515 //
       
  1516 void CLbsPrivLocWaitLocUpdateState::ConstructL()
       
  1517 	{
       
  1518 	}
       
  1519 
       
  1520 
       
  1521 // ----------------------------------------------------------------------------- 
       
  1522 // CLbsPrivLocWaitLocUpdateState::OnEntry
       
  1523 // Description: Carries out tasks required on entry to the state.
       
  1524 // Issues the location update request and starts a timer.
       
  1525 // ----------------------------------------------------------------------------- 
       
  1526 //
       
  1527 void CLbsPrivLocWaitLocUpdateState::OnEntry(const TPrivLocCommonParams& aStateParams)
       
  1528 	{
       
  1529 	TInt err(KErrNone);
       
  1530 	
       
  1531 	CLbsPrivLocStateBase::OnEntry(aStateParams);
       
  1532 	const TPrivLocWaitLocationUpdateParams& params = TPrivLocWaitLocationUpdateParams::Cast(aStateParams);	
       
  1533 	iFsm->IsEmergency() = params.iIsEmergency;
       
  1534 	iFsm->SessionType() = params.iSessionType;
       
  1535 	iFsm->PosRequestMethod() = params.iPosRequestMethod;
       
  1536 
       
  1537 	// If the network has not specified a positioning method, get the default
       
  1538 	// one from the admin settings.
       
  1539 	TLbsNetPosMethodInt netReqMethod;
       
  1540 	iFsm->PosRequestMethod().GetPosMethod(0, netReqMethod);		
       
  1541 	if (iFsm->PosRequestMethod().NumPosMethods() == 1
       
  1542 		&& (netReqMethod.PosMode() == TPositionModuleInfo::ETechnologyUnknown))
       
  1543 		{
       
  1544 		AgpsInterface()->GetDefaultPosMethod(iFsm->PosRequestMethod());
       
  1545 		}
       
  1546 
       
  1547     // We may use two sources for the required quality for the
       
  1548     // new location request, either:
       
  1549     // 1) The quality from the network (aQuality)
       
  1550     // 2) The quality defined in a quality profile (which profile to
       
  1551     //    use depends on the service type, e.g. MT-LR or X3P)
       
  1552     //
       
  1553     // We decide which to use based on the required quality from the network.
       
  1554     // Any invalid/unsupplied parameter is read from the quality profile 
       
  1555     // for the ocation request type.
       
  1556    	TBool maxFixTimeRequired = params.iQuality.MaxFixTime() == 0;
       
  1557     TBool minVerticalAccuracyRequired = 
       
  1558     				Math::IsNaN(params.iQuality.MinVerticalAccuracy());
       
  1559     TBool minHorizontalAccuracyRequired = 
       
  1560     				Math::IsNaN(params.iQuality.MinHorizontalAccuracy());
       
  1561     
       
  1562     if (maxFixTimeRequired || minVerticalAccuracyRequired || minHorizontalAccuracyRequired)
       
  1563     	{
       
  1564     	// Select which LbsAdmin setting to use for the
       
  1565     	// quality profile Id based on the type of location
       
  1566     	// request.
       
  1567 	    TLbsAdminSetting adminSetting(KLbsSettingNone);
       
  1568 	    switch (iFsm->SessionType())
       
  1569 	    	{
       
  1570 	    	case TLbsNetworkEnumInt::EServiceMobileTerminated:
       
  1571 	    	case TLbsNetworkEnumInt::EServiceNetworkInduced:
       
  1572 	    		{
       
  1573 	    		adminSetting = KLbsSettingQualityProfileExternalLocate;
       
  1574 	    		break;
       
  1575 	    		}
       
  1576 	    	case TLbsNetworkEnumInt::EServiceTransmitThirdParty:
       
  1577 	    		{
       
  1578 	    		adminSetting = KLbsSettingQualityProfileTransmitLocate;
       
  1579 	    		break;
       
  1580 	    		}
       
  1581 	    	case TLbsNetworkEnumInt::EServiceTriggeredMolr:
       
  1582                 // SUPL 2.0 "Triggered MOLR" request uses Self Locate Quality Profile
       
  1583 	    	case TLbsNetworkEnumInt::EServiceNetworkLocation:
       
  1584 	    		// This type of request should only get here in the case of a TA MOLR. Treat as Self-Locate
       
  1585 	    	case TLbsNetworkEnumInt::EServiceSelfLocation:
       
  1586 	    		{
       
  1587 	    		adminSetting = KLbsSettingQualityProfileSelfLocate;
       
  1588 	    		break;
       
  1589 	    		}
       
  1590 	    	default:
       
  1591 	    		{
       
  1592 				// We must not fail if it is an emergency request
       
  1593 				if (!iFsm->IsEmergency())
       
  1594 					{
       
  1595 					LBSLOG2(ELogP3, 
       
  1596 					"Unable to select quality profile for TLbsNetProtocolService (%d), using quality data from network instead.",
       
  1597 		    				iFsm->SessionType());
       
  1598 					__ASSERT_DEBUG(EFalse, Panic(ENrhPanicNoQualityProfile));
       
  1599 					}
       
  1600 	    		else
       
  1601 	    			{
       
  1602 	   				adminSetting = KLbsSettingQualityProfileExternalLocate;
       
  1603 	   				}
       
  1604 	    		}
       
  1605 	    	}
       
  1606 
       
  1607 		// Retrieve the Id of the quality profile to use
       
  1608 	    TLbsQualityProfileId profileId(KLbsNullQualityProfileId);
       
  1609 	    if (adminSetting != KLbsSettingNone)
       
  1610 	    	{
       
  1611 	    	LbsAdmin()->Get(adminSetting, profileId);
       
  1612 	    	}
       
  1613 
       
  1614 	    // Retrieve the data for the quality profile
       
  1615     	TQualityProfile qualityProfile;
       
  1616     	err = LbsQualityProfile::GetQualityProfileById(profileId, qualityProfile);
       
  1617     	if (err == KErrNone)
       
  1618     		{
       
  1619     		// Use the quality data from the quality profile for any missing/invalid data
       
  1620 			if(maxFixTimeRequired)
       
  1621 				{
       
  1622 				iFsm->GpsRequestQuality().SetMaxFixTime(qualityProfile.MaxFixTime());
       
  1623 				}
       
  1624 			else
       
  1625 				{
       
  1626 				iFsm->GpsRequestQuality().SetMaxFixTime(params.iQuality.MaxFixTime());
       
  1627 				}
       
  1628 			if(minHorizontalAccuracyRequired)
       
  1629 				{
       
  1630 				iFsm->GpsRequestQuality().SetMinHorizontalAccuracy(qualityProfile.MinHorizontalAccuracy());
       
  1631 				}
       
  1632 			else
       
  1633 				{
       
  1634 				iFsm->GpsRequestQuality().SetMinHorizontalAccuracy(params.iQuality.MinHorizontalAccuracy());
       
  1635 				}
       
  1636 			if(minVerticalAccuracyRequired)
       
  1637 				{
       
  1638 				iFsm->GpsRequestQuality().SetMinVerticalAccuracy(qualityProfile.MinVerticalAccuracy());
       
  1639 				}
       
  1640 			else
       
  1641 				{
       
  1642 				iFsm->GpsRequestQuality().SetMinVerticalAccuracy(params.iQuality.MinVerticalAccuracy());				
       
  1643 				}
       
  1644     		}
       
  1645 		else
       
  1646 			{
       
  1647 			// We should not fail if we are emergency
       
  1648 			if (!iFsm->IsEmergency())
       
  1649 				{
       
  1650 				// We couldn't find the quality profile with the given Id.
       
  1651 				// This is an error, so reject the location request.
       
  1652 				TPositionInfo dummyPosInfo;
       
  1653 				TTime dummyTime;
       
  1654 				TLbsNetPosRequestQualityInt dummyQuality;
       
  1655 				MessageSwitch()->SendNetLocResponse(iFsm->SessionId(),
       
  1656 									KErrAccessDenied,
       
  1657 										dummyQuality,
       
  1658 										dummyPosInfo,
       
  1659 										dummyTime,
       
  1660 										iFsm->IsEmergency());
       
  1661 			
       
  1662 				// if this location request is the result of a privacy request,
       
  1663 				// then notify the privacy handler of the error
       
  1664 				if ((params.iSessionType == TLbsNetworkEnumInt::EServiceMobileTerminated) ||
       
  1665 					(params.iSessionType == TLbsNetworkEnumInt::EServiceNetworkInduced))
       
  1666 					{
       
  1667 					iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitSessionComplete, KErrAccessDenied);
       
  1668 					}
       
  1669 				else
       
  1670 					{
       
  1671 					iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitBadQualityProfile, KErrNone);
       
  1672 					}
       
  1673 
       
  1674 				// Whatever the result, this session is finished, so return to idle.
       
  1675 				iFsm->ChangeState(CLbsPrivLocFsm::EStateIdle, iFsm->SessionId());
       
  1676 				return;
       
  1677 				} // if (!iIsEmergency)
       
  1678 			else
       
  1679 				{
       
  1680 				// Just set some defaults
       
  1681 				TTimeIntervalMicroSeconds timeout(30000000);
       
  1682 				iFsm->GpsRequestQuality().SetMinHorizontalAccuracy(50);
       
  1683 				iFsm->GpsRequestQuality().SetMinVerticalAccuracy(1000);
       
  1684 				iFsm->GpsRequestQuality().SetMaxFixTime(timeout);
       
  1685 				}
       
  1686     		}
       
  1687     	}
       
  1688     else
       
  1689     	{
       
  1690     	// Use the quality parameters supplied with the request.
       
  1691     	iFsm->GpsRequestQuality().SetMinHorizontalAccuracy(params.iQuality.MinHorizontalAccuracy());
       
  1692     	iFsm->GpsRequestQuality().SetMinVerticalAccuracy(params.iQuality.MinVerticalAccuracy());
       
  1693     	iFsm->GpsRequestQuality().SetMaxFixTime(params.iQuality.MaxFixTime());
       
  1694     	}
       
  1695 
       
  1696 
       
  1697     // Check for any existing position updates in case they meet the
       
  1698     // MaxFixAge and quality requirements for this request.
       
  1699     TInt updateReason;
       
  1700     err = AgpsInterface()->GetPosition(updateReason, 
       
  1701     								   iFsm->GpsPosition(), 
       
  1702     								   iFsm->ActualTime());
       
  1703     if (err == KErrNone)
       
  1704     	{
       
  1705 		TPrivLocWaitLocationRequestParams locationRequestParams(iFsm->SessionId(),
       
  1706 																iFsm->IsEmergency(),
       
  1707 																EFalse,
       
  1708 																updateReason);
       
  1709 
       
  1710     	// Check the existing update in case it meets the MaxFixAge and quality requirements for this request.
       
  1711     	if (params.iQuality.MaxFixAge() > 0)
       
  1712     		{
       
  1713     		TTime now;
       
  1714     		now.UniversalTime();
       
  1715     		TTimeIntervalMicroSeconds age(Max((now.Int64() - iFsm->ActualTime().Int64()), TInt64(0)));
       
  1716     		if (updateReason == KErrNone
       
  1717     			&& (age <= params.iQuality.MaxFixAge())
       
  1718     			&& ReceivedFixIsAccurate())
       
  1719     			{
       
  1720     			// Accurate update that is within the MaxFixAge time limit,
       
  1721     			// so return it straight away.
       
  1722     			iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitLocFixReceived, updateReason);
       
  1723     			iFsm->ChangeState(CLbsPrivLocFsm::EStateWaitLocationRequest, locationRequestParams);
       
  1724     			return;
       
  1725     			}
       
  1726     		}
       
  1727     		
       
  1728 
       
  1729 		// Special feature behaviour!
       
  1730 		// If the admin setting KLbsSpecialFeatureIntermediateFutileUpdate is on,
       
  1731 		// it means that we should check to see if a futile update has happened
       
  1732 		// since the first location request of this session. This might happen
       
  1733 		// in a hybrid session, if the GPS module sends a futile update when there
       
  1734 		// is no outstanding location request in the NRH. E.g. in the gap between
       
  1735 		// sending the response for one hybrid loc request and getting the next
       
  1736 		// loc request from the network.
       
  1737 		//
       
  1738 		// Note: This only really applies to hybrid of TA position modes, because
       
  1739 		//       in TB or autonomous you only have one location request per 
       
  1740 		//       session.
       
  1741     	else if (iFsm->IsSpecialFeatureIntermediateFutileUpdateOn())
       
  1742     		{
       
  1743 		    // If this is the first request for a new sessionId, record the current session id.
       
  1744 		    // We need to know this for terminal assisted or hybrid requests, in case
       
  1745 		    // we need to check for a futile update that has happened in the gap between
       
  1746 		    // one location response and the next location update request.
       
  1747 		    if (iFsm->LastLocReqSessionId() != iFsm->SessionId())
       
  1748 		    	{
       
  1749 		    	iFsm->LastLocReqSessionId() = iFsm->SessionId();
       
  1750 		    	}
       
  1751 		    else
       
  1752 				{
       
  1753 				// Before sending the location request, see if a futile update has 
       
  1754 				// happened since the start of the session (in general only terminal-assisted 
       
  1755 				// and hybrid requests should have more than one location request
       
  1756 			    // per session, however the SUPL PM will have more than one for all request modes).
       
  1757    			    TGpsRequestMode gpsMode = AgpsInterface()->ConvertPosMethodToGpsRequestMode(iFsm->PosRequestMethod());
       
  1758 				if ((updateReason == KPositionCalculationFutile) && 
       
  1759 					((gpsMode == EGpsRequestModeTerminalAssisted) || (gpsMode == EGpsRequestModeHybrid)))
       
  1760 					{
       
  1761 					// Return last measurement straight away.
       
  1762 					iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitLocMeasurementResultsReceived, updateReason);
       
  1763 					iFsm->ChangeState(CLbsPrivLocFsm::EStateWaitLocationRequest, locationRequestParams);
       
  1764 		    		return;
       
  1765 					}
       
  1766 				}
       
  1767     		}
       
  1768     	}
       
  1769 
       
  1770     
       
  1771 	// Issue the request and supply pointers to the data to be updated
       
  1772     iFsm->LocationFixReceived() = EFalse;
       
  1773     iFsm->MeasurementInfoReceived() = EFalse;
       
  1774     err = AgpsInterface()->StartPositioning(iFsm->SessionId(),
       
  1775 								    		iFsm->PosRequestMethod(),
       
  1776 											iFsm->GpsRequestQuality(),
       
  1777 											iFsm->IsEmergency());
       
  1778 	if (KErrNone == err)
       
  1779 		{
       
  1780 		iFsm->LocationUpdateTimer().EventAfter(iFsm->GpsRequestQuality().MaxFixTime(), 1);
       
  1781     	iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitReasonNone, KErrNone);
       
  1782 		}
       
  1783 	else
       
  1784 		{
       
  1785 		// Error sending the location request, send a location response
       
  1786 		// with the error and go to Idle state.
       
  1787     	iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitBadLocationRequest, err);
       
  1788     	iFsm->ChangeState(CLbsPrivLocFsm::EStateIdle, iFsm->SessionId());
       
  1789 		}
       
  1790 	}
       
  1791 
       
  1792 // ----------------------------------------------------------------------------- 
       
  1793 // CLbsPrivLocWaitLocUpdateState::OnExit
       
  1794 // Description: Carries out tasks required on exit from the state.
       
  1795 // Cancels the location update request and stops the timer.
       
  1796 // ----------------------------------------------------------------------------- 
       
  1797 //
       
  1798 TBool CLbsPrivLocWaitLocUpdateState::OnExit()
       
  1799 	{	
       
  1800 	// Cancel the update timer.
       
  1801 	iFsm->LocationUpdateTimer().Cancel();
       
  1802 	
       
  1803 	TInt consumed = EFalse;
       
  1804 	switch(iFsm->ExitData().iExitReason)
       
  1805 		{
       
  1806 		case TPrivLocStateExitData::EExitLocFixReceived:
       
  1807 			{
       
  1808 			// Don't cancel the location request yet, but tell the AGPS interface
       
  1809 			// handler to put it on 'hold'. If we are in a hybrid or terminal-assisted
       
  1810 			// request then we are going to get another location request very shortly
       
  1811 			// anyway...
       
  1812 			AgpsInterface()->HoldPositioning(iFsm->SessionId(), KErrNone);
       
  1813 	
       
  1814 			// Report the position to the message switch
       
  1815 			MessageSwitch()->SendNetLocResponse(iFsm->SessionId(),
       
  1816 												iFsm->ExitData().iExitInfo,
       
  1817             	                             	iFsm->GpsRequestQuality(),
       
  1818             	                             	iFsm->GpsPosition(),
       
  1819             	                             	iFsm->ActualTime(),
       
  1820             	                             	iFsm->IsEmergency());
       
  1821 
       
  1822 			// For MTLR pass the data to the privacy handler 
       
  1823 			// in case the Privacy Controller wants it.
       
  1824 			if ((iFsm->ExitData().iExitInfo >= KErrNone) &&
       
  1825 				(iFsm->ExitData().iExitInfo != KPositionCalculationFutile) && 
       
  1826 				((iFsm->SessionType() == TLbsNetworkEnumInt::EServiceMobileTerminated) ||
       
  1827 				(iFsm->SessionType() == TLbsNetworkEnumInt::EServiceNetworkInduced)))
       
  1828 				{
       
  1829 				PrivacyHandler()->ProcessNetworkPositionUpdate(iFsm->SessionId(), 
       
  1830 						iFsm->GpsPosition());
       
  1831 				}
       
  1832 
       
  1833 			consumed = ETrue;
       
  1834 			break;
       
  1835 			}
       
  1836 
       
  1837 		case TPrivLocStateExitData::EExitLocMeasurementResultsReceived:
       
  1838 			{
       
  1839 			// Don't cancel the location request yet, but tell the AGPS interface
       
  1840 			// handler to put it on 'hold'. If we are in a hybrid or terminal-assisted
       
  1841 			// request then we are going to get another location request very shortly
       
  1842 			// anyway...
       
  1843 			AgpsInterface()->HoldPositioning(iFsm->SessionId(), KErrNone);
       
  1844 
       
  1845 			// Report the measurement data to the message switch, even if we
       
  1846 			// didn't get any. The error code will indicate that the data
       
  1847 			// is rubbish in that case.
       
  1848 			LBSLOG2(ELogP3, "CLbsPrivLocWaitLocUpdateState:returning with reason %d", iFsm->MeasurementInfoError());
       
  1849 
       
  1850 			MessageSwitch()->SendNetLocResponse(iFsm->SessionId(),
       
  1851 												iFsm->ExitData().iExitInfo,
       
  1852 												iFsm->GpsRequestQuality(),
       
  1853             	                             	iFsm->GpsMeasurementInfo(),
       
  1854             	                             	iFsm->ActualTime(),
       
  1855             	                             	iFsm->IsEmergency());
       
  1856 			break;	
       
  1857 			}
       
  1858 		
       
  1859 		case TPrivLocStateExitData::EExitTimedOut:
       
  1860 			{
       
  1861 			// Don't cancel the location request yet, but tell the AGPS interface
       
  1862 			// handler to put it on 'hold'. If we are in a hybrid or terminal-assisted
       
  1863 			// request then we are going to get another location request very shortly
       
  1864 			// anyway...
       
  1865 			AgpsInterface()->HoldPositioning(iFsm->SessionId(), KErrNone);
       
  1866 
       
  1867 			// If the request has timed out, then return whatever position 
       
  1868 			// data we have, but make it clear it's not what was requested.
       
  1869 			// If there's an error (probably KErrTimedOut) there's
       
  1870 			// nothing to report, so send dummy data with the error.			
       
  1871 			MessageSwitch()->SendNetLocResponse(iFsm->SessionId(), 
       
  1872 												iFsm->ExitData().iExitInfo,
       
  1873 												iFsm->GpsRequestQuality(),
       
  1874 												iFsm->GpsPosition(),
       
  1875 												iFsm->ActualTime(),
       
  1876 												iFsm->IsEmergency());
       
  1877 
       
  1878 			// For MTLR, pass the data to the privacy handler in case the Privacy
       
  1879 			// Controller wants it.
       
  1880 			// NB Don't send the update if the error is KErrTimedOut, as that means there's
       
  1881 			// nothing to report.
       
  1882 			if((iFsm->SessionType() == TLbsNetworkEnumInt::EServiceMobileTerminated) &&
       
  1883 			    (iFsm->ExitData().iExitInfo == KPositionQualityLoss))
       
  1884 				{
       
  1885 				PrivacyHandler()->ProcessNetworkPositionUpdate(iFsm->SessionId(), 
       
  1886 						iFsm->GpsPosition());
       
  1887 				}
       
  1888 
       
  1889 			consumed = ETrue;
       
  1890 			break;
       
  1891 			}
       
  1892 			
       
  1893 		case TPrivLocStateExitData::EExitCancelledByPrivacyController:
       
  1894 			{
       
  1895 			// Stop the location request immediately.
       
  1896 			AgpsInterface()->StopPositioning(iFsm->SessionId());
       
  1897 			
       
  1898 			// Send a SendExternalLocateCancel to NetGateWay- if the protcol module does not support this then
       
  1899 			// the Gateway will do nothing
       
  1900 			MessageSwitch()->SendExternalLocateCancel(iFsm->SessionId(), KErrCancel);
       
  1901 				
       
  1902 			// Send a location response with 'cancel' set to the network
       
  1903 			TPositionInfo dummyPosInfo;
       
  1904 			TTime dummyTime;
       
  1905 			TLbsNetPosRequestQualityInt dummyQuality;
       
  1906 			MessageSwitch()->SendNetLocResponse(iFsm->SessionId(),
       
  1907 												iFsm->ExitData().iExitInfo,
       
  1908 												dummyQuality,
       
  1909 												dummyPosInfo,
       
  1910 												dummyTime,
       
  1911 												iFsm->IsEmergency());
       
  1912 			
       
  1913 			consumed = ETrue;
       
  1914 			}
       
  1915 			break;
       
  1916 
       
  1917 		case TPrivLocStateExitData::EExitBadQualityProfile:
       
  1918 			{
       
  1919 			// Do nothing; we're just going back to Idle state
       
  1920 			consumed = ETrue;
       
  1921 			break;
       
  1922 			}
       
  1923 		
       
  1924 		case TPrivLocStateExitData::EExitBadLocationRequest:
       
  1925 			{
       
  1926 			// Error processing the location request - 
       
  1927 			// send a dummy response with an error code.
       
  1928 			TPositionInfo dummyPosInfo;
       
  1929 			TTime dummyTime;
       
  1930 			TLbsNetPosRequestQualityInt dummyQuality;
       
  1931 			MessageSwitch()->SendNetLocResponse(iFsm->SessionId(),
       
  1932 												iFsm->ExitData().iExitInfo,
       
  1933 												dummyQuality,
       
  1934 												dummyPosInfo,
       
  1935 												dummyTime,
       
  1936 												iFsm->IsEmergency());
       
  1937 			
       
  1938 			consumed = ETrue;
       
  1939 			break;
       
  1940 			}
       
  1941 		
       
  1942 		default:
       
  1943 			{
       
  1944 			consumed = CLbsPrivLocStateBase::OnExit();
       
  1945 			// If the exit reason wasn't handled, panic (should only happen in development)
       
  1946 			__ASSERT_DEBUG(consumed, Panic(ENrhPanicWaitLocUpdateUnknownExitReason));
       
  1947 			}
       
  1948 		}
       
  1949 	return(consumed);
       
  1950 	}
       
  1951 
       
  1952 // ----------------------------------------------------------------------------- 
       
  1953 // CLbsPrivLocIdleState::OnNetLocRequest
       
  1954 // Description: The Message Switch has forwarded a request for a network 
       
  1955 // location.
       
  1956 // ----------------------------------------------------------------------------- 
       
  1957 //
       
  1958 void CLbsPrivLocWaitLocUpdateState::OnNetLocRequest(const TLbsNetSessionIdInt& aSessionId, 
       
  1959 						const TLbsNetPosRequestMethodInt& aPosRequestMethod,
       
  1960 						 TLbsNetworkEnumInt::TLbsNetProtocolServiceInt aSessionType, 
       
  1961 						 TBool aIsEmergency,
       
  1962 						 const TLbsNetPosRequestQualityInt& aQuality)
       
  1963 	{
       
  1964 	TInt numMethods = aPosRequestMethod.NumPosMethods();
       
  1965 	if (numMethods==1)
       
  1966 		{
       
  1967 		TLbsNetPosMethodInt netPosMethod;
       
  1968 		aPosRequestMethod.GetPosMethod(0,netPosMethod);
       
  1969 				
       
  1970 		if (netPosMethod.PosMode()== (TPositionModuleInfo::ETechnologyNetwork | TPositionModuleInfo::ETechnologyAssisted))
       
  1971 			{
       
  1972 			iFsm->TapMode() = ETrue;
       
  1973 			}
       
  1974 		}
       
  1975 	if(aSessionId != iFsm->SessionId())
       
  1976 		{
       
  1977 		/* This request is for a different session. Cancel the current one 
       
  1978 		 * and start a new one.
       
  1979 		 */
       
  1980 		HandleLocRequest(aSessionId,aPosRequestMethod,
       
  1981 							aSessionType,aIsEmergency,
       
  1982 							aQuality);
       
  1983 		}
       
  1984 	else
       
  1985 		{
       
  1986 		LBSLOG(ELogP3, "CLbsPrivLocWaitLocUpdateState::OnNetLocRequest: Matching SessionId.");
       
  1987 		TPrivLocWaitLocationUpdateParams updateRequestParams(aSessionId,
       
  1988 				aPosRequestMethod,
       
  1989 				aSessionType,
       
  1990 				aIsEmergency,
       
  1991 				aQuality);
       
  1992 		iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitLocReqReceived, KErrNone);
       
  1993 		iFsm->ChangeState(CLbsPrivLocFsm::EStateWaitLocationUpdate, updateRequestParams);
       
  1994 		}
       
  1995 	}
       
  1996 
       
  1997 
       
  1998 void CLbsPrivLocWaitLocUpdateState::OnMTLRRequest(const TLbsNetSessionIdInt& /*aSessionId*/,
       
  1999 					   TLbsNetworkEnumInt::TLbsNetProtocolServiceInt /*aSessionType*/, 
       
  2000 					   TBool /*aIsEmergency*/,
       
  2001 					   const TLbsExternalRequestInfo& /*aExternalRequestInfo*/,
       
  2002 					   const TLbsNetPosRequestPrivacyInt& /*aNetPosRequestPrivacy*/)
       
  2003 	{
       
  2004 	// this can never happen. If the Fsm is in the WaitLocUpdateState then 
       
  2005 	// any arrival of a MTLR request would start a new session and not
       
  2006 	// implicitly cancel the ongoing MTLR and the OnMTLRRequest()
       
  2007 	// would be directed to that session not this one
       
  2008 		
       
  2009 	}
       
  2010 	
       
  2011 // ----------------------------------------------------------------------------- 
       
  2012 // CLbsPrivLocWaitLocUpdateState::OnTimerEventL
       
  2013 // Description: The Location Update timer has expired.
       
  2014 // Cancel the request, and pass on the response if any has been received,
       
  2015 // otherwise report failure.
       
  2016 // ----------------------------------------------------------------------------- 
       
  2017 //
       
  2018 void CLbsPrivLocWaitLocUpdateState::OnTimerEventL(TInt /*aTimerId*/)
       
  2019 	{	
       
  2020 	LBSLOG(ELogP3, "CLbsPrivLocWaitLocUpdateState::OnTimerEventL");
       
  2021 	
       
  2022 	if(iFsm->MeasurementInfoReceived())
       
  2023 		{
       
  2024 		// A position fix may have been received, but it can't be accurate enough
       
  2025 		// (otherwise the request would have been completed before timeout), so 
       
  2026 		// return the most recent measurement info		
       
  2027 		LBSLOG(ELogP3, "OnTimerEventL, measurement data received");
       
  2028 		iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitLocMeasurementResultsReceived, 
       
  2029 									 iFsm->MeasurementInfoError());
       
  2030 		}
       
  2031 	else if(iFsm->LocationFixReceived())
       
  2032 		{
       
  2033 		// position received, but not accurate enough (or request would already have been completed)
       
  2034 		LBSLOG(ELogP3, "OnTimerEventL, inaccurate location data received");
       
  2035 		iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitTimedOut, 
       
  2036 									 KPositionQualityLoss);
       
  2037 		}
       
  2038 	else
       
  2039 		{
       
  2040 		// we've received no update (position / measurements)
       
  2041 		LBSLOG(ELogP3, "OnTimerEventL, NO measurement data received");
       
  2042 		LBSLOG(ELogP3, "(Setting exit info KErrPositionNoGpsUpdate");
       
  2043 		iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitTimedOut, 
       
  2044 									 KErrPositionNoGpsUpdate);
       
  2045 		}
       
  2046 
       
  2047 	SetExitState();	
       
  2048 	}
       
  2049 
       
  2050 // ----------------------------------------------------------------------------- 
       
  2051 // CLbsPrivLocWaitLocUpdateState::SetExitState
       
  2052 // Description: Works out the next state on the basis of the current session 
       
  2053 // type and whether any update has been received.
       
  2054 // ----------------------------------------------------------------------------- 
       
  2055 //
       
  2056 void CLbsPrivLocWaitLocUpdateState::SetExitState()
       
  2057 	{
       
  2058 	TPrivLocWaitLocationRequestParams locationRequestParams(iFsm->SessionId(),
       
  2059 															iFsm->IsEmergency(),
       
  2060 															EFalse,
       
  2061 															iFsm->ExitData().iExitInfo);
       
  2062 	iFsm->ChangeState(CLbsPrivLocFsm::EStateWaitLocationRequest, 
       
  2063 					locationRequestParams);
       
  2064 	}
       
  2065 
       
  2066 TBool CLbsPrivLocWaitLocUpdateState::ReceivedFixIsAccurate()
       
  2067 	{    
       
  2068 	TBool fixIsAccurate = EFalse;
       
  2069 
       
  2070 	// Compare the accuracy to the request values.
       
  2071 	// Make sure the location update is (A)GPS and not Network based.
       
  2072 	TPosition latestPosition;
       
  2073 	iFsm->GpsPosition().GetPosition(latestPosition);
       
  2074 	
       
  2075 	if ((latestPosition.HorizontalAccuracy() <= iFsm->GpsRequestQuality().MinHorizontalAccuracy()) &&
       
  2076 		(latestPosition.VerticalAccuracy() <= iFsm->GpsRequestQuality().MinVerticalAccuracy()) &&
       
  2077 		(iFsm->GpsPosition().PositionMode() != TPositionModuleInfo::ETechnologyNetwork))//Pure Reference Location
       
  2078 		{
       
  2079 		fixIsAccurate = ETrue;
       
  2080 		}
       
  2081 
       
  2082 	return(fixIsAccurate);
       
  2083     }
       
  2084 
       
  2085 /** Callback when a GPS position update arrives from AGPS manager.
       
  2086 */
       
  2087 void CLbsPrivLocWaitLocUpdateState::OnAgpsPositionUpdate(
       
  2088 	TInt aReason,
       
  2089 	const TPositionExtendedSatelliteInfo& aPosInfo,
       
  2090 	const TTime& aTimeStamp)
       
  2091 	{
       
  2092 	iFsm->GpsPosition() = aPosInfo;
       
  2093 	iFsm->ActualTime() = aTimeStamp;
       
  2094 	iFsm->LocationFixReceived() = ETrue;
       
  2095 	iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitLocFixReceived, aReason);
       
  2096 
       
  2097 	if (KErrNone == aReason)
       
  2098 		{
       
  2099 		if (iFsm->TapMode())
       
  2100 			{
       
  2101 			LBSLOG(ELogP1,"TAP mode) - NOT sending position to network");	
       
  2102 			return; // do NOT return AGPS postions to TAP mode sessions
       
  2103 			}
       
  2104 		// See if the reported accuracy matches the specified quality.
       
  2105 		// If the accuracy is good enough, report the position
       
  2106 		
       
  2107 		// if this session is TAP then discard the position
       
  2108 		
       
  2109 		if(ReceivedFixIsAccurate())
       
  2110 			{
       
  2111 			SetExitState();
       
  2112 			}
       
  2113 		}
       
  2114 	else if ((aReason <= KErrNone) || (KPositionCalculationFutile == aReason))
       
  2115 		{
       
  2116 		// GPS Manager can't provide a location update. return what we do have.
       
  2117 		if(iFsm->MeasurementInfoReceived())
       
  2118 			{
       
  2119 			LBSLOG(ELogP1,"CLbsPrivLocWaitLocUpdateState::OnPositionUpdate() - measurement received");	
       
  2120 			iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitLocMeasurementResultsReceived, aReason);
       
  2121 			}
       
  2122 		else
       
  2123 			{
       
  2124 			iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitLocFixReceived, aReason);				
       
  2125 			}
       
  2126 		SetExitState();
       
  2127 		}
       
  2128 	else if (KPositionEarlyComplete == aReason)
       
  2129 		{
       
  2130 		// Not an error. Report back what was accepted.
       
  2131 		iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitLocFixReceived, KErrNone);				
       
  2132 		SetExitState();	
       
  2133 		}
       
  2134 	else
       
  2135 		{
       
  2136 		// A real error
       
  2137 		SetExitState();
       
  2138 		}
       
  2139 	}
       
  2140 
       
  2141 /** Callback when a GPS measurement results update arrives from AGPS manager.
       
  2142 
       
  2143 Only location requests that are 'hybrid' or 'terminal assisted' should record 
       
  2144 the measurement results. Other types of request (autonomous, terminal based)
       
  2145 are only interested in the GPS position update.
       
  2146 */
       
  2147 void CLbsPrivLocWaitLocUpdateState::OnAgpsMeasurementUpdate(
       
  2148 	TInt aReason,
       
  2149 	const TPositionGpsMeasurementInfo& aPosInfo,
       
  2150 	const TTime& /*aTimeStamp*/)
       
  2151 	{
       
  2152 	// Check that we should be listening for measurement updates.
       
  2153 	
       
  2154 	TBool positionCalculationPossible = aPosInfo.PositionCalculationPossible();
       
  2155 	
       
  2156 	const TInt methodCount = iFsm->PosRequestMethod().NumPosMethods();
       
  2157 	for(TInt i = 0; i < methodCount; ++i)
       
  2158 		{
       
  2159 		TLbsNetPosMethodInt posMethod;
       
  2160 		iFsm->PosRequestMethod().GetPosMethod(i, posMethod);
       
  2161 		if((posMethod.PosMode() & KTerminalAssistedMode) == KTerminalAssistedMode)
       
  2162 			{
       
  2163 			iFsm->MeasurementInfoReceived() = ETrue;
       
  2164 			iFsm->MeasurementInfoError() = aReason;
       
  2165 			iFsm->GpsMeasurementInfo() = aPosInfo;
       
  2166 
       
  2167 			// don't wait until alpha2 time expires, instead
       
  2168 			// return measuremnts now
       
  2169 			if (positionCalculationPossible)
       
  2170 				{
       
  2171 				iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitLocMeasurementResultsReceived, 
       
  2172 											 iFsm->MeasurementInfoError());
       
  2173 				SetExitState();	
       
  2174 				}
       
  2175 			break;
       
  2176 			}
       
  2177 		}
       
  2178 	}
       
  2179 
       
  2180 /** Callback when a GPS measurement results update arrives from AGPS manager.
       
  2181 
       
  2182 Only location requests that are 'hybrid' or 'terminal assisted' should record 
       
  2183 the measurement results. Other types of request (autonomous, terminal based)
       
  2184 are only interested in the GPS position update.
       
  2185 */
       
  2186 void CLbsPrivLocWaitLocUpdateState::OnNetLocReferenceUpdate(
       
  2187 		const TLbsNetSessionIdInt& aSessionId, 
       
  2188 		const TPositionInfoBase& aPosInfo)
       
  2189 	{
       
  2190 	CLbsPrivLocStateBase::OnNetLocReferenceUpdate(aSessionId,aPosInfo);
       
  2191 	}
       
  2192 
       
  2193 
       
  2194 // ----------------------------------------------------------------------------- 
       
  2195 // 
       
  2196 // ----------------------- Class CLbsPrivLocWaitLocReqState --------------------
       
  2197 //
       
  2198 // Implements the Wait For Location Request state of the Privacy and Location 
       
  2199 // Request Handler
       
  2200 //
       
  2201 // ----------------------------------------------------------------------------- 
       
  2202 //
       
  2203 CLbsPrivLocWaitLocReqState* CLbsPrivLocWaitLocReqState::NewL(CLbsPrivLocFsm* aFsm)
       
  2204 	{
       
  2205 	return new(ELeave)CLbsPrivLocWaitLocReqState(aFsm);
       
  2206 	}
       
  2207 	
       
  2208 CLbsPrivLocWaitLocReqState::CLbsPrivLocWaitLocReqState(CLbsPrivLocFsm* aFsm)	
       
  2209 : CLbsPrivLocStateBase(aFsm)
       
  2210 	{
       
  2211 	}
       
  2212 
       
  2213 // ----------------------------------------------------------------------------- 
       
  2214 // CLbsPrivLocWaitLocReqState::OnEntry
       
  2215 // Description: Carries out tasks required on entry to the state.
       
  2216 // ----------------------------------------------------------------------------- 
       
  2217 //
       
  2218 void CLbsPrivLocWaitLocReqState::OnEntry(const TPrivLocCommonParams& aStateParams)
       
  2219 	{
       
  2220 	CLbsPrivLocStateBase::OnEntry(aStateParams);
       
  2221 	const TPrivLocWaitLocationRequestParams& params = TPrivLocWaitLocationRequestParams::Cast(aStateParams);	
       
  2222 	iFsm->IsEmergency() = params.iIsEmergency;
       
  2223 	iFsm->PrivacyRequestCancelled() = params.iReqCancelled;
       
  2224 	iFsm->PreviousStateExitInfo() = params.iPreviousStateExitInfo;
       
  2225 	}
       
  2226 
       
  2227 	
       
  2228 // ----------------------------------------------------------------------------- 
       
  2229 // CLbsPrivLocWaitLocReqState::OnExit
       
  2230 // Description: Carries out tasks required on exit from the state.
       
  2231 // Panics if the exit reason is not handled by the base state exit
       
  2232 // ----------------------------------------------------------------------------- 
       
  2233 //
       
  2234 TBool CLbsPrivLocWaitLocReqState::OnExit()
       
  2235 	{
       
  2236 	TBool consumed = CLbsPrivLocStateBase::OnExit();
       
  2237 	// If the exit reason wasn't handled, panic (should only happen in development)
       
  2238 	__ASSERT_DEBUG(consumed, Panic(ENrhPanicWaitLocReqUnknownExitReason));
       
  2239 	return(consumed);
       
  2240 	}
       
  2241 
       
  2242 void CLbsPrivLocWaitLocReqState::OnMTLRRequest(const TLbsNetSessionIdInt& /*aSessionId*/,
       
  2243 					   TLbsNetworkEnumInt::TLbsNetProtocolServiceInt /*aSessionType*/, 
       
  2244 					   TBool /*aIsEmergency*/,
       
  2245 					   const TLbsExternalRequestInfo& /*aExternalRequestInfo*/,
       
  2246 					   const TLbsNetPosRequestPrivacyInt& /*aNetPosRequestPrivacy*/)
       
  2247 	{
       
  2248 	// this can never happen. If the Fsm is in the WaitLocReqState then 
       
  2249 	// any arrival of a MTLR request would start a new session and the OnMTLRRequest()
       
  2250 	// would be directed to that session not this one
       
  2251 	__ASSERT_DEBUG(EFalse, Panic(ENrhPanicBadParamType)); 
       
  2252 	}
       
  2253 	
       
  2254 void CLbsPrivLocWaitLocReqState::OnNetLocRequest(const TLbsNetSessionIdInt& aSessionId, 
       
  2255 						const TLbsNetPosRequestMethodInt& aPosRequestMethod,
       
  2256 						 TLbsNetworkEnumInt::TLbsNetProtocolServiceInt aSessionType, 
       
  2257 						 TBool aIsEmergency,
       
  2258 						 const TLbsNetPosRequestQualityInt& aQuality)
       
  2259 	{
       
  2260 	TInt numMethods = aPosRequestMethod.NumPosMethods();
       
  2261 	if (numMethods==1)
       
  2262 		{
       
  2263 		TLbsNetPosMethodInt netPosMethod;
       
  2264 		aPosRequestMethod.GetPosMethod(0,netPosMethod);
       
  2265 				
       
  2266 		if (netPosMethod.PosMode()== (TPositionModuleInfo::ETechnologyNetwork | TPositionModuleInfo::ETechnologyAssisted))
       
  2267 			{
       
  2268 			iFsm->TapMode() = ETrue;
       
  2269 			}
       
  2270 		}
       
  2271 	
       
  2272 	
       
  2273 	if(aSessionId == iFsm->SessionId())
       
  2274 		{
       
  2275 		if (iFsm->PrivacyRequestCancelled())
       
  2276 			{
       
  2277 			iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitCancelledByPrivacyController, KErrCancel);
       
  2278 			TPrivLocWaitLocationRequestParams locationRequestParams(iFsm->SessionId(), 
       
  2279 																	iFsm->IsEmergency(), 
       
  2280 																	iFsm->PrivacyRequestCancelled());
       
  2281 			iFsm->ChangeState(CLbsPrivLocFsm::EStateWaitLocationRequest, locationRequestParams);
       
  2282 			}
       
  2283 		else
       
  2284 			{
       
  2285 			iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitLocReqReceived, KErrNone);
       
  2286 			TPrivLocWaitLocationUpdateParams updateRequestParams(aSessionId,
       
  2287 																 aPosRequestMethod,
       
  2288 																 aSessionType,
       
  2289 																 aIsEmergency,
       
  2290 																 aQuality);
       
  2291 			iFsm->ChangeState(CLbsPrivLocFsm::EStateWaitLocationUpdate, updateRequestParams);
       
  2292 			}
       
  2293 		}
       
  2294 	else
       
  2295 		{
       
  2296 		HandleLocRequest(aSessionId,aPosRequestMethod,
       
  2297 							aSessionType,aIsEmergency,
       
  2298 							aQuality);
       
  2299 		}
       
  2300 	}
       
  2301 
       
  2302 void CLbsPrivLocWaitLocReqState::OnCancelNetworkLocationRequest(const TLbsNetSessionIdInt& aSessionId)
       
  2303 	{
       
  2304 	if (!iFsm->IsEmergency() && (aSessionId == iFsm->SessionId()))
       
  2305 			{
       
  2306 			if (!iFsm->PrivacyRequestCancelled() )
       
  2307 				{
       
  2308 				TLbsNetSessionIdInt sessionId = iFsm->SessionId();
       
  2309 				MessageSwitch()->SendExternalLocateCancel(sessionId,KErrCancel);
       
  2310 				}
       
  2311 			iFsm->PrivacyRequestCancelled() = ETrue;
       
  2312 			}
       
  2313 	}
       
  2314 
       
  2315 
       
  2316 /** Called when a reference position arrives from the network.
       
  2317 */
       
  2318 void CLbsPrivLocWaitLocReqState::OnNetLocReferenceUpdate(
       
  2319 		const TLbsNetSessionIdInt& aSessionId, 
       
  2320 		const TPositionInfoBase& aPosInfo)
       
  2321 	{
       
  2322 	// if the MTLR is still active (has not been cancelled by the privacy handler)
       
  2323 	if (!iFsm->PrivacyRequestCancelled())
       
  2324 		{
       
  2325 		CLbsPrivLocStateBase::OnNetLocReferenceUpdate(aSessionId, aPosInfo);
       
  2326 		}	
       
  2327 	}
       
  2328 
       
  2329 // ----------------------------------------------------------------------------- 
       
  2330 // CLbsPrivLocWaitLocReqState::OnSessionComplete
       
  2331 // Description: handling of a session complete message
       
  2332 // ----------------------------------------------------------------------------- 
       
  2333 //
       
  2334 void CLbsPrivLocWaitLocReqState::OnSessionComplete(const TLbsNetSessionIdInt& aSessionId,
       
  2335 																TInt aReason)
       
  2336 	{
       
  2337 	
       
  2338 	
       
  2339 	if(aSessionId == iFsm->SessionId())
       
  2340 		{
       
  2341 		// Make sure the reason passed with the Session Complete is sent to the
       
  2342  		// Privacy Controller EXCEPT when the update previously passed to the 
       
  2343  		// network didn't meet the quality criteria. In this case use the
       
  2344  		// KPositionQualityLoss status.
       
  2345 		TInt completionReason = aReason;
       
  2346 		if(aReason == KErrNone)
       
  2347  			{
       
  2348  			if(KPositionQualityLoss == iFsm->PreviousStateExitInfo())
       
  2349  				{
       
  2350  				completionReason = KPositionQualityLoss;
       
  2351  				}
       
  2352  			}
       
  2353 		
       
  2354 		iFsm->ExitData().SetExitData(TPrivLocStateExitData::EExitSessionComplete, completionReason);
       
  2355 		iFsm->ChangeState(CLbsPrivLocFsm::EStateIdle, aSessionId);	            
       
  2356 		}		
       
  2357 	}
       
  2358 
       
  2359 // ----------------------------------------------------------------------------- 
       
  2360 //
       
  2361 // Package classes
       
  2362 //
       
  2363 // ----------------------------------------------------------------------------- 
       
  2364 //
       
  2365 TPrivLocCommonParams::TPrivLocCommonParams()
       
  2366 	{	
       
  2367 	}
       
  2368 TPrivLocCommonParams::TPrivLocCommonParams(TLbsNetSessionIdInt aSessionId)
       
  2369 	{
       
  2370 	iSessionId = aSessionId;												
       
  2371 	}
       
  2372 
       
  2373 TPrivLocWaitLocationRequestParams::TPrivLocWaitLocationRequestParams()
       
  2374 	{
       
  2375 	}
       
  2376 TPrivLocWaitLocationRequestParams::TPrivLocWaitLocationRequestParams(
       
  2377 			const TLbsNetSessionIdInt& aSessionId,
       
  2378 			TBool	aIsEmergency,
       
  2379 			TBool   aReqCancelled,
       
  2380 			TInt    aPreviousStateExitInfo) :
       
  2381 	TPrivLocCommonParams(aSessionId),
       
  2382 	iIsEmergency(aIsEmergency),
       
  2383 	iReqCancelled(aReqCancelled),
       
  2384 	iPreviousStateExitInfo(aPreviousStateExitInfo)
       
  2385 	{
       
  2386 	}
       
  2387 
       
  2388 TPrivLocWaitLocationUpdateParams::TPrivLocWaitLocationUpdateParams()
       
  2389 	{	
       
  2390 	}
       
  2391 TPrivLocWaitLocationUpdateParams::TPrivLocWaitLocationUpdateParams(
       
  2392 			const TLbsNetSessionIdInt& aSessionId,
       
  2393 			const TLbsNetPosRequestMethodInt& aPosRequestMethod,
       
  2394 			TLbsNetworkEnumInt::TLbsNetProtocolServiceInt  aSessionType,
       
  2395 			TBool aIsEmergency,
       
  2396 			const TLbsNetPosRequestQualityInt& aQuality) :
       
  2397 	TPrivLocCommonParams(aSessionId),
       
  2398 	iSessionType(aSessionType),
       
  2399 	iIsEmergency(aIsEmergency),
       
  2400 	iQuality(aQuality),
       
  2401 	iPosRequestMethod(aPosRequestMethod)
       
  2402 	{
       
  2403 	}
       
  2404 
       
  2405 TPrivLocWaitPrivResponseParams::TPrivLocWaitPrivResponseParams()
       
  2406 	{
       
  2407 	
       
  2408 	}
       
  2409 TPrivLocWaitPrivResponseParams::TPrivLocWaitPrivResponseParams(
       
  2410 			const TLbsNetSessionIdInt& aSessionId,
       
  2411 			const TLbsNetworkEnumInt::TLbsNetProtocolServiceInt aSessionType,
       
  2412 			const TLbsExternalRequestInfo& aExternalRequestInfo,
       
  2413 			const TLbsNetPosRequestPrivacyInt& aNetPosRequestPrivacy,
       
  2414 			TBool aIsEmergency) :
       
  2415 	TPrivLocCommonParams(aSessionId),
       
  2416 	iNetPosRequestPrivacy(aNetPosRequestPrivacy),
       
  2417 	iIsEmergency(aIsEmergency),
       
  2418 	iSessionType(aSessionType)
       
  2419 	{
       
  2420 	// Need to check the type of aExternalRequestInfo before 
       
  2421 	// copying it into this class.
       
  2422 	if (aExternalRequestInfo.ClassType() == EExternalRequestInfoClass)
       
  2423 		{
       
  2424 		__ASSERT_DEBUG(aExternalRequestInfo.ClassSize() == sizeof(TLbsExternalRequestInfo), 
       
  2425 					   Panic(ENrhPanicInvalidExternalRequestInfoType));
       
  2426 		
       
  2427 		Mem::Copy(&iExternalRequestInfo, 
       
  2428 				  &aExternalRequestInfo, 
       
  2429 				  sizeof(TLbsExternalRequestInfo));
       
  2430 		}
       
  2431 	else 
       
  2432 		{
       
  2433 		if (aExternalRequestInfo.ClassType() == (EExternalRequestInfoClass | EExternalRequestInfoClass2))
       
  2434 			{
       
  2435 			__ASSERT_DEBUG(aExternalRequestInfo.ClassSize() == sizeof(TLbsExternalRequestInfo2), 
       
  2436 						   Panic(ENrhPanicInvalidExternalRequestInfoType));
       
  2437 
       
  2438 			Mem::Copy(&iExternalRequestInfo, 
       
  2439 					  &aExternalRequestInfo, 
       
  2440 					  sizeof(TLbsExternalRequestInfo2));
       
  2441 			}
       
  2442 		else
       
  2443 			{
       
  2444 			Panic(ENrhPanicInvalidExternalRequestInfoType);
       
  2445 			}
       
  2446 		}
       
  2447 	}
       
  2448 
       
  2449 // ----------------------------------------------------------------------------- 
       
  2450 // 
       
  2451 // ----------------------------- Class CLbsPrivLocFsm --------------------------
       
  2452 //
       
  2453 // State Machine class which owns the states of the Privacy and Location Handler
       
  2454 //
       
  2455 // ----------------------------------------------------------------------------- 
       
  2456 //
       
  2457 
       
  2458 // ----------------------------------------------------------------------------- 
       
  2459 // CLbsPrivLocFsm::NewL
       
  2460 // Description: CLbsPrivLocFsm static constructor 
       
  2461 // ----------------------------------------------------------------------------- 
       
  2462 //
       
  2463 CLbsPrivLocFsm* CLbsPrivLocFsm::NewL(
       
  2464 		CPrivacyAndLocationHandler& aPrivLocHandler,
       
  2465 		const TLbsNetSessionIdInt& aSessionId)
       
  2466 	{
       
  2467 	CLbsPrivLocFsm* self; 
       
  2468 	self = new (ELeave) CLbsPrivLocFsm(aPrivLocHandler, aSessionId);
       
  2469 	CleanupStack::PushL(self);
       
  2470 	self->ConstructL();
       
  2471 	CleanupStack::Pop(self);
       
  2472 	return(self);	
       
  2473 	}
       
  2474 
       
  2475 // ----------------------------------------------------------------------------- 
       
  2476 // CLbsPrivLocFsm::CLbsPrivLocFsm
       
  2477 // Description: CLbsPrivLocFsm constructor 
       
  2478 // ----------------------------------------------------------------------------- 
       
  2479 //
       
  2480 CLbsPrivLocFsm::CLbsPrivLocFsm(
       
  2481 		CPrivacyAndLocationHandler& aPrivLocHandler,
       
  2482 		const TLbsNetSessionIdInt& aSessionId) :
       
  2483 	iPrivLocHandler(aPrivLocHandler),
       
  2484 	iSessionId(aSessionId),
       
  2485 	iIsEmergency(EFalse),
       
  2486 	iSessionType(TLbsNetworkEnumInt::EServiceNone),
       
  2487 	iRefPosProcessed(EFalse),
       
  2488 	iLocReqReceived(EFalse),
       
  2489 	iReqCancelled(EFalse),
       
  2490 	iWasPrivacyResponseReceivedStateExited(EFalse)
       
  2491 	{	
       
  2492 	}
       
  2493 	
       
  2494 // ----------------------------------------------------------------------------- 
       
  2495 // CLbsPrivLocFsm::~CLbsPrivLocFsm
       
  2496 // Description: CLbsPrivLocFsm destructor 
       
  2497 // ----------------------------------------------------------------------------- 
       
  2498 //
       
  2499 CLbsPrivLocFsm::~CLbsPrivLocFsm()
       
  2500 	{
       
  2501 	delete iLocationUpdateTimer;
       
  2502 	iStates.DeleteAll();
       
  2503 	iStates.Reset();
       
  2504 	}
       
  2505 
       
  2506 // ----------------------------------------------------------------------------- 
       
  2507 // CLbsPrivLocFsm::SessionId
       
  2508 // Description: Get the current session Id for this FSM.
       
  2509 // ----------------------------------------------------------------------------- 
       
  2510 //
       
  2511 const TLbsNetSessionIdInt& CLbsPrivLocFsm::SessionId() const
       
  2512 	{
       
  2513 	return iSessionId;
       
  2514 	}
       
  2515 
       
  2516 // ----------------------------------------------------------------------------- 
       
  2517 // CLbsPrivLocFsm::ConstructL
       
  2518 // Description: CLbsPrivLocFsm second-phase constructor.
       
  2519 //              Creates the states of the system and the Privacy Handler.
       
  2520 // ----------------------------------------------------------------------------- 
       
  2521 //
       
  2522 void CLbsPrivLocFsm::ConstructL()
       
  2523 	{
       
  2524 	// Create the states
       
  2525 	iStates.At(EStateIdle) = CLbsPrivLocIdleState::NewL(this);
       
  2526 	iStates.At(EStateWaitPrivacyResponse) = CLbsPrivLocWaitPrivRespState::NewL(this);
       
  2527 	iStates.At(EStateWaitLocationRequest) = CLbsPrivLocWaitLocReqState::NewL(this);
       
  2528 	iStates.At(EStateWaitLocationUpdate) = CLbsPrivLocWaitLocUpdateState::NewL(this);
       
  2529 
       
  2530 	iCurrentState = iStates.At(EStateIdle);
       
  2531     // When waiting for an update, there is a maximum duration specified by the
       
  2532     // LBS admin data to avoid the risk of hanging around forever in the event of 
       
  2533     // a problem with the A-GPS module. Create a timer to deal with this.
       
  2534     iLocationUpdateTimer = CLbsCallbackTimer::NewL(*this);
       
  2535 	}
       
  2536 	
       
  2537 	
       
  2538 TBool CLbsPrivLocFsm::IsSpecialFeatureIntermediateFutileUpdateOn()
       
  2539 	{
       
  2540 	return PrivLocHandler().IsSpecialFeatureIntermediateFutileUpdateOn();
       
  2541 	}
       
  2542 
       
  2543 // ----------------------------------------------------------------------------- 
       
  2544 // CPrivacyAndLocationHandler::SetServerObserver
       
  2545 // Description: Store a pointer to the NRH server which comunicates with the 
       
  2546 // Privacy Controller.
       
  2547 // ----------------------------------------------------------------------------- 
       
  2548 //
       
  2549 void CLbsPrivLocFsm::SetServerObserver(MLbsSessionObserver* aNrhServer)
       
  2550     {
       
  2551     PrivLocHandler().PrivacyHandler()->SetServerObserver(aNrhServer);
       
  2552     }
       
  2553 
       
  2554 // ----------------------------------------------------------------------------- 
       
  2555 // CLbsPrivLocFsm::OnRespondNetworkLocationRequest
       
  2556 // Description: Called by the Privacy Handler to report the result of a privacy
       
  2557 // check. Handling of the response is delegated to the current state.
       
  2558 // ----------------------------------------------------------------------------- 
       
  2559 //
       
  2560 void CLbsPrivLocFsm::OnRespondNetworkLocationRequest(const TLbsNetSessionIdInt& aRequestId, 
       
  2561                             TLbsNetworkEnumInt::TLbsPrivacyResponseInt aRequestResult,
       
  2562                             TInt aResponseReason)
       
  2563 	{
       
  2564 	LBSLOG3(ELogP3, "FSM(%d) OnRespondNetworkLocationRequest response=%d",iSessionId.SessionNum(),aRequestResult);
       
  2565 	iCurrentState->OnRespondNetworkLocationRequest(aRequestId, aRequestResult, aResponseReason);
       
  2566     }
       
  2567 
       
  2568 // ----------------------------------------------------------------------------- 
       
  2569 // CLbsPrivLocFsm::OnCancelNetworkLocationRequest
       
  2570 // Description: Called by the Privacy Handler to report that a privacy check 
       
  2571 // has been rejected. This may occur after it has already been accepted.
       
  2572 // Handling of the response is delegated to the current state.
       
  2573 // ----------------------------------------------------------------------------- 
       
  2574 //
       
  2575 void CLbsPrivLocFsm::OnCancelNetworkLocationRequest(const TLbsNetSessionIdInt& aRequestId)
       
  2576     {
       
  2577 	LBSLOG2(ELogP3, "FSM(%d) OnCancelNetworkLocationRequest",iSessionId.SessionNum());
       
  2578 	iCurrentState->OnCancelNetworkLocationRequest(aRequestId);
       
  2579     }
       
  2580 
       
  2581 // ----------------------------------------------------------------------------- 
       
  2582 // CLbsPrivLocFsm::OnMTLRRequest
       
  2583 // Description: The Message Switch has forwarded a request to start an MTLR 
       
  2584 // session.
       
  2585 // Handling of the request is delegated to the current state.
       
  2586 // ----------------------------------------------------------------------------- 
       
  2587 //
       
  2588 void CLbsPrivLocFsm::OnMTLRRequest(const TLbsNetSessionIdInt& aSessionId,
       
  2589 					   TLbsNetworkEnumInt::TLbsNetProtocolServiceInt aSessionType, 
       
  2590 					   TBool aIsEmergency,
       
  2591 					   const TLbsExternalRequestInfo& aExternalRequestInfo,
       
  2592 					   const TLbsNetPosRequestPrivacyInt& aNetPosRequestPrivacy)
       
  2593 	{
       
  2594 	LBSLOG2(ELogP3, "FSM(%d) OnMTLRRequest",iSessionId.SessionNum());
       
  2595 	iCurrentState->OnMTLRRequest(aSessionId, 
       
  2596 								aSessionType, 
       
  2597 								aIsEmergency, 
       
  2598 								aExternalRequestInfo, 
       
  2599 								aNetPosRequestPrivacy);
       
  2600 	}
       
  2601 	
       
  2602 // ----------------------------------------------------------------------------- 
       
  2603 // CLbsPrivLocFsm::OnSessionComplete
       
  2604 // Description: The Message Switch has reported that the session is
       
  2605 // over (complete or aborted due to some error).
       
  2606 // Handling of the message is delegated to the current state.
       
  2607 // ----------------------------------------------------------------------------- 
       
  2608 //
       
  2609 void CLbsPrivLocFsm::OnSessionComplete(
       
  2610 									const TLbsNetSessionIdInt& aSessionId,
       
  2611 									TInt aReason)
       
  2612 	{
       
  2613 	LBSLOG3(ELogP3, "FSM(%d) OnSessionComplete reason=%d",iSessionId.SessionNum(),aReason);
       
  2614 	iCurrentState->OnSessionComplete(aSessionId, aReason);
       
  2615 	}
       
  2616 
       
  2617 // ----------------------------------------------------------------------------- 
       
  2618 // CLbsPrivLocFsm::OnNetLocRequest
       
  2619 // Description: The Message Switch has passed on a request for a position update
       
  2620 // Handling of the request is delegated to the current state.
       
  2621 // ----------------------------------------------------------------------------- 
       
  2622 //
       
  2623 void CLbsPrivLocFsm::OnNetLocRequest(
       
  2624 						const TLbsNetSessionIdInt& aSessionId, 
       
  2625 						const TLbsNetPosRequestMethodInt& aPosRequestMethod,
       
  2626 						TLbsNetworkEnumInt::TLbsNetProtocolServiceInt aSessionType, 
       
  2627 						TBool aIsEmergency,
       
  2628 						const TLbsNetPosRequestQualityInt& aQuality)
       
  2629 	{
       
  2630 	LBSLOG2(ELogP3, "FSM(%d) OnNetLocRequest",iSessionId.SessionNum());
       
  2631 	iCurrentState->OnNetLocRequest(aSessionId,
       
  2632 	 					aPosRequestMethod, 
       
  2633 	 					aSessionType, 
       
  2634 						aIsEmergency, 
       
  2635 						aQuality);
       
  2636 	}
       
  2637 
       
  2638 /** Called when a reference position arrives from the network.
       
  2639 */
       
  2640 void CLbsPrivLocFsm::OnNetLocReferenceUpdate(
       
  2641 		const TLbsNetSessionIdInt& aSessionId, 
       
  2642 		const TPositionInfoBase& aPosInfo)
       
  2643 	{
       
  2644 	LBSLOG2(ELogP3, "FSM(%d) OnNetLocReferenceUpdate",iSessionId.SessionNum());
       
  2645 	iCurrentState->OnNetLocReferenceUpdate(aSessionId, aPosInfo);	
       
  2646 	}
       
  2647 
       
  2648 /** Callend when a final location arrives from the network.
       
  2649 
       
  2650 Currently the final network position is never used by the 
       
  2651 state machine - it is only needed by the X3P handler. 
       
  2652 So this function just ignores the update.
       
  2653 */
       
  2654 void CLbsPrivLocFsm::OnNetLocFinalUpdate(
       
  2655 		const TLbsNetSessionIdInt& /*aSessionId*/, 
       
  2656 		const TPositionInfoBase& /*aPosInfo*/)
       
  2657 	{
       
  2658 	// Final network position not used by CLbsPrivLocFsm, so ignore it.
       
  2659 	}
       
  2660 
       
  2661 // ----------------------------------------------------------------------------- 
       
  2662 // CLbsPrivLocFsm::ChangeState
       
  2663 // Description: Called by a state of the FSM when a transition is required.
       
  2664 // ----------------------------------------------------------------------------- 
       
  2665 //
       
  2666 void CLbsPrivLocFsm::ChangeState(TLocPrivacyHandlerState aNewStateId,const TPrivLocCommonParams& aStateParams)
       
  2667 	{
       
  2668 	// Tidy up the old state
       
  2669 	if(iCurrentState)
       
  2670 		{
       
  2671 		// coverity[unchecked_value]
       
  2672 		// We're not interested in whether it was consumed here
       
  2673 		iCurrentState->OnExit();
       
  2674 		}
       
  2675 
       
  2676 	// Note, here the session ID has already being set when the Fsm was created (when session first came into being)
       
  2677 	// so no need to do this ... iSessionId = aStateParams.iSessionId;
       
  2678 
       
  2679 	// Set the new state
       
  2680 	iCurrentState = iStates.At(aNewStateId);
       
  2681 
       
  2682 	LBSLOG3(ELogP3, "FSM(%d) Entering state %d",iSessionId.SessionNum(), aNewStateId);
       
  2683 	
       
  2684 	// Do any initialisation for the new state.
       
  2685 	iCurrentState->OnEntry(aStateParams);
       
  2686 	}
       
  2687 
       
  2688 // ----------------------------------------------------------------------------- 
       
  2689 // CLbsPrivLocFsm::ChangeState
       
  2690 // Description: Called by a state of the FSM when a transition is required to a 
       
  2691 // state which only requires the session Id
       
  2692 // ----------------------------------------------------------------------------- 
       
  2693 //
       
  2694 void CLbsPrivLocFsm::ChangeState(TLocPrivacyHandlerState aNewStateId,
       
  2695 											const TLbsNetSessionIdInt& aSessionId)
       
  2696 	{
       
  2697 	TPrivLocCommonParams commonParams(aSessionId);
       
  2698 	ChangeState(aNewStateId, commonParams);
       
  2699 	}
       
  2700 
       
  2701 // ----------------------------------------------------------------------------- 
       
  2702 // CLbsPrivLocFsm::PrivLocHandler
       
  2703 // Description: Get the CPrivacyAndLocationHandler object
       
  2704 // ----------------------------------------------------------------------------- 
       
  2705 //
       
  2706 CPrivacyAndLocationHandler& CLbsPrivLocFsm::PrivLocHandler()
       
  2707 	{
       
  2708 	return iPrivLocHandler;
       
  2709 	}
       
  2710 
       
  2711 // ----------------------------------------------------------------------------- 
       
  2712 // CLbsPrivLocWaitLocUpdateState::OnTimerEventL
       
  2713 // Description: The Location Update timer has expired.
       
  2714 // Cancel the request, and pass on the response if any has been received,
       
  2715 // otherwise report failure.
       
  2716 // ----------------------------------------------------------------------------- 
       
  2717 //
       
  2718 void CLbsPrivLocFsm::OnTimerEventL(TInt aTimerId)
       
  2719 	{	
       
  2720 	LBSLOG2(ELogP3, "FSM(%d) OnTimerEventL", iSessionId.SessionNum());
       
  2721 	iCurrentState->OnTimerEventL(aTimerId);
       
  2722 	}
       
  2723 
       
  2724 /** Called if OnTimerEventL leaves */
       
  2725 TInt CLbsPrivLocFsm::OnTimerError(TInt /*aTimerId*/, TInt aError)
       
  2726 	{
       
  2727 	__ASSERT_DEBUG(EFalse, Panic(ENrhPanicLocationTimerError));
       
  2728 	return(aError);
       
  2729 	}
       
  2730 
       
  2731 /** Callback when a GPS position update arrives from AGPS manager.
       
  2732 */
       
  2733 void CLbsPrivLocFsm::OnAgpsPositionUpdate(
       
  2734 	TInt aReason,
       
  2735 	const TPositionExtendedSatelliteInfo& aPosInfo,
       
  2736 	const TTime& aTimeStamp)
       
  2737 	{
       
  2738 	LBSLOG2(ELogP3, "FSM(%d) OnAgpsPositionUpdate", iSessionId.SessionNum());
       
  2739 	iCurrentState->OnAgpsPositionUpdate(aReason, aPosInfo, aTimeStamp);
       
  2740 	}
       
  2741 
       
  2742 /** Callback when a GPS measurement results update arrives from AGPS manager.
       
  2743 */
       
  2744 void CLbsPrivLocFsm::OnAgpsMeasurementUpdate(
       
  2745 	TInt aReason,
       
  2746 	const TPositionGpsMeasurementInfo& aPosInfo,
       
  2747 	const TTime& aTimeStamp)
       
  2748 	{
       
  2749 	LBSLOG2(ELogP3, "FSM(%d) OnAgpsMeasurementUpdate", iSessionId.SessionNum());
       
  2750 	iCurrentState->OnAgpsMeasurementUpdate(aReason, aPosInfo, aTimeStamp);
       
  2751 	}