locationrequestmgmt/networkrequesthandler/src/agpsinterfacehandler.cpp
changeset 0 9cfd9a3ee49c
equal deleted inserted replaced
-1:000000000000 0:9cfd9a3ee49c
       
     1 // Copyright (c) 2008-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 /**
       
    17  @file
       
    18  @internalTechnology
       
    19  @released
       
    20 */
       
    21 
       
    22 #include "lbsdevloggermacros.h"
       
    23 #include "agpsinterfacehandler.h"
       
    24 #include "nrhpanic.h"
       
    25 #include "lbsnetregstatusint.h"
       
    26 
       
    27 
       
    28 // Pre-defined technology types for common positioning modes.
       
    29 const TPositionModuleInfo::TTechnologyType KTerminalAssistedMode = 
       
    30 		(TPositionModuleInfo::ETechnologyNetwork |
       
    31 		 TPositionModuleInfo::ETechnologyAssisted);
       
    32 const TPositionModuleInfo::TTechnologyType KTerminalBasedMode = 
       
    33 		(TPositionModuleInfo::ETechnologyTerminal |
       
    34 		 TPositionModuleInfo::ETechnologyAssisted);
       
    35 const TPositionModuleInfo::TTechnologyType KAutonomousMode = 
       
    36 		(TPositionModuleInfo::ETechnologyTerminal);
       
    37 
       
    38 /** Constructor.
       
    39 */
       
    40 CAgpsInterfaceHandler::CAgpsInterfaceHandler(
       
    41 		MAgpsInterfaceHandlerObserver& aObserver,
       
    42 		CLbsAdmin& aAdmin,
       
    43 		RLbsNetworkRegistrationStatus& aNetRegStatus) :
       
    44 	iObserver(aObserver),
       
    45 	iAdmin(aAdmin),
       
    46 	iNetRegStatus(aNetRegStatus),
       
    47 	iX3pStatus(EX3pStatusIdle),
       
    48 	iCombinedPowerModeAdvice(TLbsPositionUpdateRequestBase::EPowerAdviceOff),
       
    49 	iCombinedRequestGpsMode(EGpsRequestModeUnknown)
       
    50 	{
       
    51 	}
       
    52 
       
    53 /** Destructor.
       
    54 */
       
    55 CAgpsInterfaceHandler::~CAgpsInterfaceHandler()
       
    56 	{
       
    57 	iRequests.Close();
       
    58 	delete iMeasurementUpdateMonitor;
       
    59 	delete iLocationUpdateMonitor;
       
    60 	}
       
    61 
       
    62 /**
       
    63 */
       
    64 CAgpsInterfaceHandler* CAgpsInterfaceHandler::NewL(
       
    65 		MAgpsInterfaceHandlerObserver& aObserver,
       
    66 		CLbsAdmin& aAdmin,
       
    67 		RLbsNetworkRegistrationStatus& aNetRegStatus)
       
    68 	{
       
    69 	CAgpsInterfaceHandler* self = new (ELeave) CAgpsInterfaceHandler(aObserver, aAdmin, aNetRegStatus);
       
    70 	CleanupStack::PushL(self);
       
    71 	self->ConstructL();
       
    72 	CleanupStack::Pop(self);
       
    73 	return self;
       
    74 	}
       
    75 
       
    76 /**
       
    77 */
       
    78 
       
    79 const TInt KLbsDefaultMaxNumLocationRequests   = 4;
       
    80 
       
    81 void CAgpsInterfaceHandler::ConstructL()
       
    82 	{
       
    83 	iLocationUpdateMonitor = CLbsLocUpdateMonitor::NewL(*this);
       
    84 	iMeasurementUpdateMonitor = CLbsMeasurementInfoMonitor::NewL(*this);
       
    85 	
       
    86 	TInt err = iAdmin.Get(KLbsSettingMaximumExternalLocateRequests, iMaxNumLocationRequests);
       
    87 	if (err != KErrNone)
       
    88 		{
       
    89 		iMaxNumLocationRequests = KLbsDefaultMaxNumLocationRequests;
       
    90 		}
       
    91 
       
    92 	iRequests.ReserveL(iMaxNumLocationRequests+1); // +1 for processing emergencies
       
    93 
       
    94 	// Get the A-GPS device mode capabilities:
       
    95 	err = LbsModuleInfo::GetDeviceCapabilities(KLbsGpsLocManagerUid, iDeviceGpsModeCaps);
       
    96 	if(err != KErrNone || (iDeviceGpsModeCaps==TPositionModuleInfoExtended::EDeviceGpsModeNone))
       
    97 		{
       
    98 		// Assume module supports hybrid if it has not reported its capabilities in module info file
       
    99 		iDeviceGpsModeCaps = TPositionModuleInfoExtended::EDeviceGpsModeSimultaneousTATB;
       
   100 		}
       
   101 	
       
   102 
       
   103 	}
       
   104 	
       
   105 /** Called to initialise a location request.
       
   106 
       
   107 This is used to tell the AGPS Interface that a GPS location request
       
   108 is goind to happen 'soon'. Usually, this means we should update the
       
   109 power mode advice to at least 'standby', to give the GPS hardware
       
   110 as much time as possible to warm up.
       
   111 
       
   112 @param aSessionId Session Id of the request that is started.
       
   113 
       
   114 @return KErrNone if no problems, or one of the standard Symbian
       
   115 		error codes if there was a problem storing the new request.
       
   116 */
       
   117 TInt CAgpsInterfaceHandler::PreStartPositioning(
       
   118 		const TLbsNetSessionIdInt& aSessionId, TBool aEmergency)
       
   119 	{
       
   120 	// Add the request to the array
       
   121 	TAgpsRequest newRequest;
       
   122 	newRequest.iSessionId = &aSessionId;
       
   123 	newRequest.iState = EAgpsRequestStateIdle;
       
   124 
       
   125 	TInt err = AddOrUpdateRequest(newRequest, aEmergency);
       
   126 
       
   127 	if (err != KErrNone)
       
   128 		{
       
   129 		return err;
       
   130 		}
       
   131 	
       
   132 	// Update the GPS power mode advice to the AGPS Manager
       
   133 	TLbsPositionUpdateRequestBase::TPowerAdvice newPowerAdvice;
       
   134 	CalculateCombinedPowerModeAdvice(newPowerAdvice);
       
   135 	if (newPowerAdvice != iCombinedPowerModeAdvice)
       
   136 		{
       
   137 		iCombinedPowerModeAdvice = newPowerAdvice;
       
   138 		iLocationUpdateMonitor->SendPowerAdviceRequest(iCombinedPowerModeAdvice);
       
   139 		}
       
   140 	
       
   141 	return err;
       
   142 	}
       
   143 
       
   144 /** Called to start a location request.
       
   145 
       
   146 This is used when the CLbsPrivLocFsm actually wants to send
       
   147 a location request to the AGPS Manager.
       
   148 
       
   149 This function must combine the new request with any existing
       
   150 request(s) - this includes quality params and GPS mode, before
       
   151 sending a request to the AGPS Manager.
       
   152 
       
   153 @param aSessionId Session Id of the request that is started.
       
   154 @param aMethod GPS mode(s) to use, as set by the network.
       
   155 @param aQuality quality params to use, as set by the network.
       
   156 
       
   157 @return KErrNone if no problems, or one of the standard Symbian
       
   158 		error codes if there was a problem storing the new request.
       
   159 */
       
   160 TInt CAgpsInterfaceHandler::StartPositioning(
       
   161 		const TLbsNetSessionIdInt& aSessionId,
       
   162 		const TLbsNetPosRequestMethodInt& aMethod,
       
   163 		const TLbsNetPosRequestQualityInt& aQuality,
       
   164 		TBool aEmergency)
       
   165 	{
       
   166 	// Check that the new request GPS mode is valid
       
   167 	TGpsRequestMode newRequestGpsMode = ConvertPosMethodToGpsRequestMode(aMethod);
       
   168 	TGpsRequestMode newCombinedGpsMode;
       
   169 	TInt err = CalculateNewCombinedRequestMethod(
       
   170 								iCombinedRequestGpsMode,
       
   171 								newRequestGpsMode,
       
   172 								newCombinedGpsMode,
       
   173 								aEmergency);
       
   174 	if (err != KErrNone)
       
   175 		{
       
   176 		RemoveRequest(aSessionId);
       
   177 		return err;
       
   178 		}
       
   179 	
       
   180 	// Add (or update) the request to the buffer
       
   181 	TAgpsRequest newRequest;
       
   182 	newRequest.iSessionId = &aSessionId;
       
   183 	newRequest.iState = EAgpsRequestStateActive;
       
   184 	newRequest.iGpsMode = newRequestGpsMode;
       
   185 	newRequest.iPosQuality = &aQuality;
       
   186 	TTime now;
       
   187 	now.UniversalTime();
       
   188 	newRequest.iEndTime = (now + aQuality.MaxFixTime());
       
   189 	newRequest.iGpsTimingOfCellFramesRequested = aMethod.GpsTimingOfCellFramesRequested();
       
   190 	err = AddOrUpdateRequest(newRequest, aEmergency);
       
   191 	if (err != KErrNone)
       
   192 		{
       
   193 		return err;
       
   194 		}
       
   195 	
       
   196 	// Use the new combined GPS mode
       
   197 	iCombinedRequestGpsMode = newCombinedGpsMode;
       
   198 	
       
   199 	// Combine Quality.
       
   200 	CalculateCombinedRequestQuality();
       
   201 
       
   202 	// Send the new combined request to the AGPS manager.
       
   203 	SendCombinedLocationRequest();
       
   204 
       
   205 	return err;
       
   206 	}
       
   207 
       
   208 /** Temporarily stop an existing location request.
       
   209 
       
   210 This function is used when a location request has finished,
       
   211 but the session it belongs to hasn't finished yet. For example,
       
   212 in terminal assisted or hybrid mode, there is more than one location
       
   213 request within a session, so the it should not be removed from the
       
   214 list until it has completely finished.
       
   215 */
       
   216 void CAgpsInterfaceHandler::HoldPositioning(
       
   217 		const TLbsNetSessionIdInt& aSessionId, 
       
   218 		TInt /*aReason*/)
       
   219 	{
       
   220 	// Find a matching request.
       
   221 	TInt index = iRequests.Find(aSessionId, IsSessionIdEqual);
       
   222 	if (index == KErrNotFound)
       
   223 		{
       
   224 		// If can't find one, just ignore it (but LBSLOG_ERR)?
       
   225 		LBSLOG_ERR2(ELogP3, "Failed to find a match for sessionId %d.", aSessionId.SessionNum());
       
   226 		return;
       
   227 		}
       
   228 
       
   229 	// Set the request to 'hold'.
       
   230 	iRequests[index].iState = EAgpsRequestStateHold;
       
   231 	}
       
   232 
       
   233 /** Stop and remove a location request.
       
   234 
       
   235 This function is used when a session has finished, and
       
   236 the location request can be removed from the list.
       
   237 */
       
   238 void CAgpsInterfaceHandler::StopPositioning(
       
   239 		const TLbsNetSessionIdInt& aSessionId)
       
   240 	{	
       
   241 	// Remove request from iRequests.
       
   242 	RemoveRequest(aSessionId);
       
   243 	
       
   244 	if (IsAnyRequestState(EAgpsRequestStateActive))
       
   245 		{
       
   246 		// If there are any other active requests, combine them and send
       
   247 		// a new location request.
       
   248 		
       
   249 		// Combine quality
       
   250 		CalculateCombinedRequestQuality();
       
   251 
       
   252 		// Send the new combined request to the AGPS manager.
       
   253 		SendCombinedLocationRequest();
       
   254 		}
       
   255 	else if (!IsAnyRequestState(EAgpsRequestStateHold)
       
   256 			 && iLocationRequestActive)
       
   257 		{
       
   258 		// There are no requests that are either active or on hold, so send 
       
   259 		// a cancel message to the AGPS manager.
       
   260 		CalculateCombinedPowerModeAdvice(iCombinedPowerModeAdvice);
       
   261 		iLocationUpdateMonitor->SendCancelRequest(iCombinedPowerModeAdvice);
       
   262 		iLocationRequestActive = EFalse;
       
   263 		
       
   264 		// Also reset the combined request parameters
       
   265 		iCombinedRequestGpsMode = EGpsRequestModeUnknown;
       
   266 		}
       
   267 	else
       
   268 		{
       
   269 		// Update the GPS power mode advice to the AGPS Manager
       
   270 		TLbsPositionUpdateRequestBase::TPowerAdvice newPowerAdvice;
       
   271 		CalculateCombinedPowerModeAdvice(newPowerAdvice);
       
   272 		if (newPowerAdvice != iCombinedPowerModeAdvice)
       
   273 			{
       
   274 			iCombinedPowerModeAdvice = newPowerAdvice;
       
   275 			iLocationUpdateMonitor->SendPowerAdviceRequest(iCombinedPowerModeAdvice);
       
   276 			}		
       
   277 		}
       
   278 	}
       
   279 
       
   280 /** Check that it is ok to send the position update to state machine(s).
       
   281 
       
   282 Some position updates should be ignored by the NRH, these are:
       
   283 1) Conflict control updates (aConflictControl = ETrue), only the 
       
   284    LocServer is interested in these.
       
   285 2) In hybrid, if the params are 'invalid'. Some licensees use special
       
   286    values in the position update to flag that it should not be used,
       
   287    e.g. if the horizontal accuracy is 0.
       
   288 */
       
   289 TBool CAgpsInterfaceHandler::CheckPositionUpdateIsValid(
       
   290 		TBool aConflictControl,
       
   291 		TInt aReason,
       
   292 		const TPositionExtendedSatelliteInfo& aPosInfo,
       
   293 		const TTime& /*aActualTime*/)
       
   294 	{
       
   295 	// Some updates are only meant for the LocServer - they
       
   296 	// have aConflictControl == ETrue. We shouldn't send these
       
   297 	// to the PrivLocHandler.
       
   298 	if (aConflictControl)
       
   299 		{
       
   300 		return EFalse;
       
   301 		}
       
   302 
       
   303 	// For hybrid position, first check whether the data is valid. If any of 
       
   304 	// longitude, latitude, or horizontal accuracy is missing, or horizontal 
       
   305 	// accuracy is zero, then it's not valid, so there's no point going any 
       
   306 	// further.
       
   307 	if ((iCombinedRequestGpsMode == EGpsRequestModeHybrid) && (aReason == KErrNone))
       
   308 		{
       
   309 		TPosition pos;
       
   310 		aPosInfo.GetPosition(pos);
       
   311 		if (Math::IsNaN(pos.Latitude()) || 
       
   312 			Math::IsNaN(pos.Longitude()) || 
       
   313 			Math::IsNaN(pos.HorizontalAccuracy()) || 
       
   314 			(pos.HorizontalAccuracy() == 0))
       
   315 			{
       
   316 			return EFalse;
       
   317 			}
       
   318 		}
       
   319 	
       
   320 	return ETrue;
       
   321 	}
       
   322 	
       
   323 /** Get the latest update value from the GPS position bus.
       
   324 
       
   325 Note: Some updates are intended only for the LocServer, these
       
   326 all have conflictControl == ETrue, so in this case we return 
       
   327 KErrNotFound to tell the caller it shouldn't be used.
       
   328 
       
   329 @param aReason Reason code for the update. Set by the AGPS manager.
       
   330 @param aPosInfo Position data for the update.
       
   331 @param aTimeStamp Time the update arrived in the LBS system.
       
   332 
       
   333 @return KErrNone usually, but KErrNotFound if the update is invalid.
       
   334 */
       
   335 TInt CAgpsInterfaceHandler::GetPosition(
       
   336 		TInt& aReason,
       
   337 		TPositionExtendedSatelliteInfo& aPosInfo,
       
   338 		TTime& aTimeStamp)
       
   339 	{
       
   340 	TBool conflictControl;
       
   341 	iLocationUpdateMonitor->GetPosition(
       
   342 			conflictControl,
       
   343 			aReason,
       
   344 			aPosInfo,
       
   345 			aTimeStamp);
       
   346 			
       
   347 	if (CheckPositionUpdateIsValid(conflictControl,
       
   348 								   aReason,
       
   349 								   aPosInfo,
       
   350 								   aTimeStamp))
       
   351 		{
       
   352 		return KErrNone;
       
   353 		}
       
   354 	else
       
   355 		{
       
   356 		return KErrNotFound;
       
   357 		}
       
   358 	}
       
   359 
       
   360 /** Get the latest update from the GPS measurement results bus.
       
   361 */
       
   362 void CAgpsInterfaceHandler::GetMeasurement(
       
   363 		TInt& aReason,
       
   364 		TPositionGpsMeasurementInfo& aPosInfo,
       
   365 		TTime& aTimeStamp)
       
   366 	{
       
   367 	iMeasurementUpdateMonitor->GetMeasurement(aReason, aPosInfo, aTimeStamp);
       
   368 	}
       
   369 
       
   370 /** Callback for when a GPS update is sent by the AGPS manager.
       
   371 */
       
   372 void CAgpsInterfaceHandler::OnPositionUpdate(
       
   373 			TBool aConflictControl,
       
   374 			TInt aReason,
       
   375 			const TPositionExtendedSatelliteInfo& aPosInfo,
       
   376 			const TTime& aActualTime)
       
   377 	{	
       
   378 	LBSLOG(ELogP1, "CAgpsInterfaceHandler::OnPositionUpdate");
       
   379 	if (CheckPositionUpdateIsValid(aConflictControl,
       
   380 								   aReason,
       
   381 								   aPosInfo,
       
   382 								   aActualTime))
       
   383 		{
       
   384 		// Send the update to the PrivLocHandler
       
   385 		iObserver.OnAgpsPositionUpdate(aReason, aPosInfo, aActualTime);
       
   386 		}
       
   387 	}
       
   388 
       
   389 /** Callback for when a GPS Measured Results update is sent by the AGPS manager.
       
   390 */
       
   391 void CAgpsInterfaceHandler::OnMeasurementInfoUpdate(
       
   392 			TInt aReason, 
       
   393 			const TPositionGpsMeasurementInfo& aMeasurementResults,
       
   394 			const TTime& aActualTime)
       
   395 	{
       
   396 	// Send result to observer
       
   397 	iObserver.OnAgpsMeasurementUpdate(aReason, aMeasurementResults, aActualTime);
       
   398 	}
       
   399 
       
   400 /** Combines the quality parameters of all the active requests.
       
   401 
       
   402 Note: Only requests which are 'active' should be considered when
       
   403 combining the quality params.
       
   404 */
       
   405 void CAgpsInterfaceHandler::CalculateCombinedRequestQuality()
       
   406 	{
       
   407 	// Set the initial values to start from
       
   408 	TReal32 minHorizAcc(10000000000000000.0);
       
   409 	TReal32 minVertAcc(10000000000000000.0);
       
   410 	TTimeIntervalMicroSeconds maxMaxFixTime(0);
       
   411 	TTime now;
       
   412 	now.UniversalTime();
       
   413 	
       
   414 	// Combine each request in turn but only if it is 'active'.
       
   415 	const TInt count = iRequests.Count();
       
   416 	for (TInt i = 0; i < count; i++)
       
   417 		{
       
   418 		if (iRequests[i].iState == EAgpsRequestStateActive)
       
   419 			{
       
   420 			// Horizontal accuracy = strictest accuracy.
       
   421 			minHorizAcc = Min(minHorizAcc,
       
   422 							  iRequests[i].iPosQuality->MinHorizontalAccuracy());
       
   423 	
       
   424 			// Vertical accuracy = strictest accuracy.
       
   425 			minVertAcc = Min(minVertAcc,
       
   426 							 iRequests[i].iPosQuality->MinVerticalAccuracy());
       
   427 			
       
   428 			// Max fix time = greatest/longest time.
       
   429 			TTimeIntervalMicroSeconds maxFixTime = (iRequests[i].iEndTime.Int64() - now.Int64());
       
   430 			maxMaxFixTime = Max(maxMaxFixTime, maxFixTime);
       
   431 			}
       
   432 		}
       
   433 	
       
   434 	// Set the combined accuracy
       
   435 	iCombinedRequestQuality.SetMinHorizontalAccuracy(minHorizAcc);
       
   436 	iCombinedRequestQuality.SetMinVerticalAccuracy(minVertAcc);
       
   437 	iCombinedRequestQuality.SetMaxFixTime(maxMaxFixTime);
       
   438 	}
       
   439 
       
   440 /** Calculates the power mode advice to send to the AGPS manager.
       
   441 
       
   442 Use the state of the X3P handler and the combined state of the current
       
   443 requests to calculate the power mode advice to send to the AGPS
       
   444 manager.
       
   445 */
       
   446 void CAgpsInterfaceHandler::CalculateCombinedPowerModeAdvice(
       
   447 		TLbsPositionUpdateRequestBase::TPowerAdvice& aCombinedPowerAdvice)
       
   448 	{
       
   449 	// Calculate combined state for all requests
       
   450 	TAgpsRequestState combinedState(EAgpsRequestStateUnknown);
       
   451 	if (IsAnyRequestState(EAgpsRequestStateActive))
       
   452 		{
       
   453 		combinedState = EAgpsRequestStateActive;
       
   454 		}
       
   455 	else if (IsAnyRequestState(EAgpsRequestStateHold))
       
   456 		{
       
   457 		combinedState = EAgpsRequestStateHold;
       
   458 		}
       
   459 	else if (IsAnyRequestState(EAgpsRequestStateIdle))
       
   460 		{
       
   461 		combinedState = EAgpsRequestStateIdle;
       
   462 		}
       
   463 	
       
   464 	// Select the power advice to send to the AGPS manager by using
       
   465 	// a look-up table.
       
   466 	//
       
   467 	// The look-up table below is described in the NRH design document,
       
   468 	// so if it is changed, the design doc should also be updated to 
       
   469 	// keep it in sync.
       
   470 	const TInt KNumX3pStates = 3;
       
   471 	const TInt KNumLocRequestStates = 4;
       
   472 	static const TLbsPositionUpdateRequestBase::TPowerAdvice KPowerAdviceTable[KNumX3pStates][KNumLocRequestStates] = 
       
   473 		{
       
   474 			{ TLbsPositionUpdateRequestBase::EPowerAdviceOff, 
       
   475 			  TLbsPositionUpdateRequestBase::EPowerAdviceOn, 
       
   476 			  TLbsPositionUpdateRequestBase::EPowerAdviceOn, 
       
   477 			  TLbsPositionUpdateRequestBase::EPowerAdviceOn },
       
   478 			  
       
   479 			{ TLbsPositionUpdateRequestBase::EPowerAdviceStandby, 
       
   480 			  TLbsPositionUpdateRequestBase::EPowerAdviceOn, 
       
   481 			  TLbsPositionUpdateRequestBase::EPowerAdviceOn, 
       
   482 			  TLbsPositionUpdateRequestBase::EPowerAdviceOn },
       
   483 			  
       
   484 			{ TLbsPositionUpdateRequestBase::EPowerAdviceOn, 
       
   485 			  TLbsPositionUpdateRequestBase::EPowerAdviceOn, 
       
   486 			  TLbsPositionUpdateRequestBase::EPowerAdviceOn, 
       
   487 			  TLbsPositionUpdateRequestBase::EPowerAdviceOn }
       
   488 		};
       
   489 	
       
   490 	// Note: Because this table uses the enum values directly as indices,
       
   491 	//       if either enum changes, you need to re-do the table above as well.
       
   492 	__ASSERT_ALWAYS(iX3pStatus < KNumX3pStates, Panic(ENrhPanicInvalidPowerModeAdviceIndex));
       
   493 	aCombinedPowerAdvice = KPowerAdviceTable[iX3pStatus][combinedState];
       
   494 	}
       
   495 
       
   496 /**
       
   497  Goes through all requests and decides if the timing of cell frames is requested or not
       
   498  
       
   499  @return ETrue if the timing of cell frames is requested
       
   500  */
       
   501 TBool CAgpsInterfaceHandler::CalculateCombinedTimingOfCellFramesRequested()
       
   502 	{
       
   503 	TBool timingOfCellFramesRequested(EFalse);
       
   504 	
       
   505 	// Combine each request in turn but only if it is 'active'.
       
   506 	const TInt count = iRequests.Count();
       
   507 	// Make the flag to be ETrue if there are any requests active or on hold that have the flag
       
   508 	// set to ETrue
       
   509 	for (TInt i = 0; i < count; i++)
       
   510 		{
       
   511 		if((iRequests[i].iState == EAgpsRequestStateActive || 
       
   512 				iRequests[i].iState == EAgpsRequestStateHold) && 
       
   513 			iRequests[i].iGpsTimingOfCellFramesRequested)
       
   514 			{
       
   515 			timingOfCellFramesRequested = ETrue;
       
   516 			break;
       
   517 			}
       
   518 		}
       
   519 	return timingOfCellFramesRequested;
       
   520 	}
       
   521 
       
   522 /** Performs the common actions for sending a location request to the AGPS manager.
       
   523 
       
   524 This function does common tasks such as calculating the power mode to send,
       
   525 starting or stopping the needed monitors and actually sending the combined
       
   526 request.
       
   527 
       
   528 Note: Combining the quality params and/or GPS mode params is done differently
       
   529       depending on whether a request is being started, stopped or put on hold,
       
   530       so that is not done in this function.
       
   531 */
       
   532 void CAgpsInterfaceHandler::SendCombinedLocationRequest()
       
   533 	{	
       
   534 	// Always start the GPS position update monitor, even in TA mode,
       
   535 	// because we use this update bus to listen for error codes, 
       
   536 	// e.g. KPositionEarlyComplete.
       
   537 	iLocationUpdateMonitor->StartMonitor();
       
   538 	
       
   539 	// Start measurement monitor if combined request has GPS mode 
       
   540 	// with Terminal-Assisted or hybrid:
       
   541 	if (iCombinedRequestGpsMode == EGpsRequestModeTerminalAssisted
       
   542 		|| iCombinedRequestGpsMode == EGpsRequestModeHybrid)
       
   543 		{
       
   544 		iMeasurementUpdateMonitor->StartMonitor();
       
   545 		}
       
   546 	else
       
   547 		{
       
   548 		iMeasurementUpdateMonitor->StopMonitor();
       
   549 		}
       
   550 	
       
   551 	// Convert the TGpsRequestMode into TLbsNetPosRequestMethodInt
       
   552 	TLbsNetPosRequestMethodInt posMethod;
       
   553 	posMethod.SetGpsTimingOfCellFramesRequested(CalculateCombinedTimingOfCellFramesRequested());
       
   554 	ConvertGpsRequestModeToPosMethod(iCombinedRequestGpsMode, posMethod);
       
   555 
       
   556 	// Calculate the current power advice.
       
   557 	CalculateCombinedPowerModeAdvice(iCombinedPowerModeAdvice);
       
   558 	
       
   559 	// Send combined location request.
       
   560 	iLocationUpdateMonitor->SendLocationRequest(
       
   561 			iCombinedPowerModeAdvice, 
       
   562 			posMethod, 
       
   563 			iCombinedRequestQuality);
       
   564 	iLocationRequestActive = ETrue;	
       
   565 	}
       
   566 
       
   567 /** Called by CX3pHandler tp update the state of X3P requests.
       
   568 
       
   569 For X3P, if there is a client connected to the NRH server, we assume that
       
   570 there will a request soon, so we can send 'standby' power mode advice, to 
       
   571 allow the GPS hardware to prepare for a location request before the request
       
   572 has actually arrived.
       
   573 */
       
   574 void CAgpsInterfaceHandler::SetX3pStatus(MX3pStatusHandler::TX3pStatus aStatus)
       
   575 	{
       
   576 	// Only send a power advice if the X3P status has actually changed.
       
   577 	if (aStatus != iX3pStatus)
       
   578 		{
       
   579 		iX3pStatus = aStatus;
       
   580 		TLbsPositionUpdateRequestBase::TPowerAdvice newPowerAdvice;
       
   581 		CalculateCombinedPowerModeAdvice(newPowerAdvice);
       
   582 		if (newPowerAdvice != iCombinedPowerModeAdvice)
       
   583 			{
       
   584 			iCombinedPowerModeAdvice = newPowerAdvice;
       
   585 			iLocationUpdateMonitor->SendPowerAdviceRequest(iCombinedPowerModeAdvice);
       
   586 			}
       
   587 		}
       
   588 	}
       
   589 
       
   590 /** Comparison function for use with RArray::Find()
       
   591 
       
   592 @return ETrue if session Ids match, EFalse otherwise.
       
   593 */
       
   594 TBool CAgpsInterfaceHandler::IsSessionIdEqual(
       
   595 		const TLbsNetSessionIdInt* aSessionId, 
       
   596 		const TAgpsRequest& aRequest)
       
   597 	{
       
   598 	return (*aSessionId == *aRequest.iSessionId);
       
   599 	}
       
   600 
       
   601 /** Comparison function for use with RArray::Find()
       
   602 
       
   603 @return ETrue if states match, EFalse otherwise.
       
   604 */
       
   605 TBool CAgpsInterfaceHandler::IsRequestStateEqual(
       
   606 		const TAgpsRequestState* aState, 
       
   607 		const TAgpsRequest& aRequest)
       
   608 	{
       
   609 	return (*aState == aRequest.iState);
       
   610 	}
       
   611 
       
   612 /** Add or update a location request in the buffer.
       
   613 
       
   614 If the request already exists on the list then its parameters are updated.
       
   615 If it doesn't exist then the request is appended to the list.
       
   616 For emergencies we haveone reserved slot used just for the emergency location request
       
   617 */
       
   618 TInt CAgpsInterfaceHandler::AddOrUpdateRequest(const TAgpsRequest& aRequest, TBool aEmergency)
       
   619 	{
       
   620 	TInt err(KErrNone);
       
   621 	TInt index = iRequests.Find(*aRequest.iSessionId, IsSessionIdEqual);
       
   622 	if (index >= 0)
       
   623 		{
       
   624 		// Update params of existing request
       
   625 		iRequests[index] = aRequest;
       
   626 		}
       
   627 	else if (aEmergency)
       
   628 	    {
       
   629 	    // Note that we can guarantee at least ONE free slot. See below.
       
   630 	    // add emergency request to list
       
   631 	    err = iRequests.Append(aRequest);
       
   632 	    }
       
   633 	else if (iRequests.Count() <= iMaxNumLocationRequests)
       
   634 		{
       
   635 		// Add new request to iRequests. Note, only allocate up to 
       
   636 		// iMaxNumLocationRequests slots and leave at least one free for use for emergency
       
   637 		err = iRequests.Append(aRequest);
       
   638 		}
       
   639 	else
       
   640 		{
       
   641 		// Exceeded the max number of requests, reject it!
       
   642 		LBSLOG_ERR3(ELogP3,
       
   643 					"CAgpsInterfaceHandler::AddOrUpdateRequest: Can't add new request, active requests (%d), limit (%d)", 
       
   644 					iRequests.Count(), 
       
   645 					iMaxNumLocationRequests);
       
   646 		return KErrInUse;		
       
   647 		}
       
   648 	return err;
       
   649 	}
       
   650 
       
   651 /** Remove a request from the buffer.
       
   652 
       
   653 @param aSessionId SessionId of the request to remove.
       
   654 */
       
   655 void CAgpsInterfaceHandler::RemoveRequest(const TLbsNetSessionIdInt& aSessionId)
       
   656 	{
       
   657 	TInt index = iRequests.Find(aSessionId, IsSessionIdEqual);
       
   658 	if (index >= 0)
       
   659 		{
       
   660 		iRequests.Remove(index);
       
   661 		}
       
   662 	else
       
   663 		{
       
   664 		LBSLOG_WARN2(ELogP3, "CAgpsInterfaceHandler::RemoveRequest: Failed to find match for sessionId %d.", aSessionId.SessionNum());
       
   665 		}
       
   666 	}
       
   667 
       
   668 /** Search to find if any requests' state matches the given state.
       
   669 
       
   670 @param aState Request state to compare to.
       
   671 
       
   672 @return ETrue if any state has a matching state. EFalse otherwise.
       
   673 */
       
   674 TBool CAgpsInterfaceHandler::IsAnyRequestState(
       
   675 		TAgpsRequestState aState)
       
   676 	{
       
   677 	TInt index = iRequests.Find(aState, IsRequestStateEqual);
       
   678 	return (index >= 0);
       
   679 	}
       
   680 
       
   681 /** Convert a TLbsNetPosRequestMethodInt into a TGpsRequestMode enum.
       
   682 */
       
   683 TGpsRequestMode CAgpsInterfaceHandler::ConvertPosMethodToGpsRequestMode(
       
   684 		const TLbsNetPosRequestMethodInt& aPosMethod)
       
   685 	{
       
   686 	TGpsRequestMode gpsMode(EGpsRequestModeUnknown);
       
   687 	
       
   688 	const TInt count = aPosMethod.NumPosMethods();
       
   689 	for (TInt i = 0; i < count; i++)
       
   690 		{
       
   691 		TLbsNetPosMethodInt method;
       
   692 		aPosMethod.GetPosMethod(i, method);
       
   693 		switch (method.PosMode())
       
   694 			{
       
   695 			case KAutonomousMode:
       
   696 				{
       
   697 				if (gpsMode == EGpsRequestModeTerminalAssisted)
       
   698 					{
       
   699 					gpsMode = EGpsRequestModeHybrid;
       
   700 					}
       
   701 				else
       
   702 					{
       
   703 					gpsMode = EGpsRequestModeAutonomous;
       
   704 					}
       
   705 				break;
       
   706 				}
       
   707 			case KTerminalBasedMode:
       
   708 				{
       
   709 				if (gpsMode == EGpsRequestModeTerminalAssisted)
       
   710 					{
       
   711 					gpsMode = EGpsRequestModeHybrid;
       
   712 					}
       
   713 				else
       
   714 					{
       
   715 					gpsMode = EGpsRequestModeTerminalBased;
       
   716 					}
       
   717 				break;
       
   718 				}
       
   719 			case KTerminalAssistedMode:
       
   720 				{
       
   721 				if (gpsMode == EGpsRequestModeTerminalBased
       
   722 					|| gpsMode == EGpsRequestModeAutonomous)
       
   723 					{
       
   724 					gpsMode = EGpsRequestModeHybrid;
       
   725 					}
       
   726 				else
       
   727 					{
       
   728 					gpsMode = EGpsRequestModeTerminalAssisted;
       
   729 					}
       
   730 				break;
       
   731 				}
       
   732 			}
       
   733 		}
       
   734 	
       
   735 	return gpsMode;
       
   736 	}
       
   737 
       
   738 
       
   739 /** Convert a TGpsRequestMode enum into a TLbsNetPosRequestMethodInt.
       
   740 */
       
   741 void CAgpsInterfaceHandler::ConvertGpsRequestModeToPosMethod(
       
   742 		TGpsRequestMode aMode, 
       
   743 		TLbsNetPosRequestMethodInt& aPosMethod)
       
   744 	{
       
   745 	TLbsNetPosMethodInt methods[2];
       
   746 	switch (aMode)
       
   747 		{
       
   748 		case EGpsRequestModeAutonomous:
       
   749 			{
       
   750 			methods[0].SetPosMethod(KLbsPositioningMeansGpsInt, KAutonomousMode);
       
   751 			aPosMethod.SetPosMethods(methods, 1);
       
   752 			break;
       
   753 			}
       
   754 		case EGpsRequestModeTerminalBased:
       
   755 			{
       
   756 			methods[0].SetPosMethod(KLbsPositioningMeansGpsInt, KTerminalBasedMode);
       
   757 			aPosMethod.SetPosMethods(methods, 1);
       
   758 			break;
       
   759 			}
       
   760 		case EGpsRequestModeTerminalAssisted:
       
   761 			{
       
   762 			methods[0].SetPosMethod(KLbsPositioningMeansGpsInt, KTerminalAssistedMode);
       
   763 			aPosMethod.SetPosMethods(methods, 1);
       
   764 			break;
       
   765 			}
       
   766 		case EGpsRequestModeHybrid:
       
   767 			{
       
   768 			methods[0].SetPosMethod(KLbsPositioningMeansGpsInt, KTerminalBasedMode);
       
   769 			methods[1].SetPosMethod(KLbsPositioningMeansGpsInt, KTerminalAssistedMode);
       
   770 			aPosMethod.SetPosMethods(methods, 2);
       
   771 			break;
       
   772 			}
       
   773 
       
   774 		case EGpsRequestModeUnknown:
       
   775 		default:
       
   776 			{
       
   777 			GetDefaultPosMethod(aPosMethod);
       
   778 			break;
       
   779 			}
       
   780 		}
       
   781 
       
   782 	}
       
   783 
       
   784 /** Calculate the new combined GPS mode when a new request is added.
       
   785 
       
   786 The new combined GPS mode depends on a combination of:
       
   787 1) The GPS mode(s) the module supports.
       
   788 2) The current combined GPS mode.
       
   789 3) The GPS mode of the new request.
       
   790 
       
   791 @param aCurrentPosMethod [In] The GPS mode of the current combined request.
       
   792 @param aNewRequestPosMethod [In] The GPS mode of the new request.
       
   793 @param aCurrentPosMethod [Out] The GPS mode of the newly combined requests.
       
   794 
       
   795 @return KErrNone if the GPS mode was combined successfully, KErrNotSupported
       
   796         if the GPS mode of the new request is not supported by the GPS module,
       
   797         KErrInUse if the new request GPS mode clashes with the current combined
       
   798         request GPS mode, e.g. if the module supports either TA or TB, but not
       
   799         both and the new request is TB but the current request is TA.
       
   800 */
       
   801 TInt CAgpsInterfaceHandler::CalculateNewCombinedRequestMethod(
       
   802 		TGpsRequestMode aCurrentGpsMode,
       
   803 		TGpsRequestMode aNewRequestGpsMode,
       
   804 		TGpsRequestMode& aCombinedGpsMode,
       
   805 		TBool aEmergency)
       
   806 	{
       
   807 	// Table entry
       
   808 	struct TGpsModeTableEntry
       
   809 		{
       
   810 		TGpsRequestMode iCurrentGpsMode;
       
   811 		TGpsRequestMode iNewRequestGpsMode;
       
   812 		TGpsRequestMode iCombinedGpsMode;
       
   813 		TInt iErrorCode;
       
   814 		};
       
   815 	
       
   816 	// Each of the tables below are taken directly from the 
       
   817 	// NRH design document. If any of them are changed (e.g.
       
   818 	// for a defect fix), the table in the design doc should
       
   819 	// also be updated to match.
       
   820 
       
   821 	// Module supports Terminal-Based only.
       
   822 	static const TGpsModeTableEntry KGpsModeCombinationTableTB[] = 
       
   823 	{
       
   824 	// Current request mode				// New request mode				// Newly combined request mode	// Error
       
   825 	{EGpsRequestModeUnknown,			EGpsRequestModeTerminalBased,	EGpsRequestModeTerminalBased,	KErrNone},
       
   826 	{EGpsRequestModeUnknown,			EGpsRequestModeHybrid,			EGpsRequestModeTerminalBased,	KErrNone},
       
   827 	{EGpsRequestModeUnknown,			EGpsRequestModeTerminalAssisted,EGpsRequestModeUnknown,			KErrNotSupported},
       
   828 	{EGpsRequestModeUnknown,			EGpsRequestModeAutonomous,		EGpsRequestModeAutonomous,		KErrNone},
       
   829 	
       
   830 	{EGpsRequestModeAutonomous,			EGpsRequestModeTerminalBased,	EGpsRequestModeTerminalBased,	KErrNone},
       
   831 	{EGpsRequestModeAutonomous,			EGpsRequestModeHybrid,			EGpsRequestModeTerminalBased,	KErrNone},
       
   832 	{EGpsRequestModeAutonomous,			EGpsRequestModeTerminalAssisted,EGpsRequestModeUnknown,			KErrNotSupported},
       
   833 	{EGpsRequestModeAutonomous,			EGpsRequestModeAutonomous,		EGpsRequestModeAutonomous,		KErrNone},
       
   834 	
       
   835 	{EGpsRequestModeTerminalBased,		EGpsRequestModeTerminalBased,	EGpsRequestModeTerminalBased,	KErrNone},
       
   836 	{EGpsRequestModeTerminalBased,		EGpsRequestModeHybrid,			EGpsRequestModeTerminalBased,	KErrNone},
       
   837 	{EGpsRequestModeTerminalBased,		EGpsRequestModeTerminalAssisted,EGpsRequestModeUnknown,			KErrNotSupported},
       
   838 	{EGpsRequestModeTerminalBased,		EGpsRequestModeAutonomous,		EGpsRequestModeTerminalBased,	KErrNone}
       
   839 	};
       
   840 	static const TInt KGpsModeCombinationTableTBCount(sizeof(KGpsModeCombinationTableTB) 
       
   841 													  / sizeof(TGpsModeTableEntry));
       
   842 
       
   843 	// Module supports Terminal-Assisted only.
       
   844 	static const TGpsModeTableEntry KGpsModeCombinationTableTA[] = 
       
   845 	{
       
   846 	{EGpsRequestModeUnknown,			EGpsRequestModeTerminalBased,	EGpsRequestModeUnknown,			KErrNotSupported},
       
   847 	{EGpsRequestModeUnknown,			EGpsRequestModeHybrid,			EGpsRequestModeTerminalAssisted,KErrNone},
       
   848 	{EGpsRequestModeUnknown,			EGpsRequestModeTerminalAssisted,EGpsRequestModeTerminalAssisted,KErrNone},
       
   849 	{EGpsRequestModeUnknown,			EGpsRequestModeAutonomous,		EGpsRequestModeUnknown,			KErrNotSupported},
       
   850 
       
   851 	{EGpsRequestModeTerminalAssisted,	EGpsRequestModeTerminalBased,	EGpsRequestModeUnknown,			KErrNotSupported},
       
   852 	{EGpsRequestModeTerminalAssisted,	EGpsRequestModeHybrid,			EGpsRequestModeTerminalAssisted,KErrNone},
       
   853 	{EGpsRequestModeTerminalAssisted,	EGpsRequestModeTerminalAssisted,EGpsRequestModeTerminalAssisted,KErrNone},
       
   854 	{EGpsRequestModeTerminalAssisted,	EGpsRequestModeAutonomous,		EGpsRequestModeUnknown,			KErrNotSupported}
       
   855 	};
       
   856 	static const TInt KGpsModeCombinationTableTACount(sizeof(KGpsModeCombinationTableTA) 
       
   857 													  / sizeof(TGpsModeTableEntry));
       
   858 	
       
   859 	// Module supports either Terminal-Assisted or Terminal-Based (but not both at the same time).
       
   860 	static const TGpsModeTableEntry KGpsModeCombinationTableTBOrTA[] = 
       
   861 	{
       
   862 	{EGpsRequestModeUnknown,			EGpsRequestModeTerminalBased,	EGpsRequestModeTerminalBased,	KErrNone},
       
   863 	{EGpsRequestModeUnknown,			EGpsRequestModeHybrid,			EGpsSpecialTreatmentForHybrid,	KErrNone},
       
   864 	{EGpsRequestModeUnknown,			EGpsRequestModeTerminalAssisted,EGpsRequestModeTerminalAssisted,KErrNone},
       
   865 	{EGpsRequestModeUnknown,			EGpsRequestModeAutonomous,		EGpsRequestModeAutonomous,		KErrNone},
       
   866 
       
   867 	{EGpsRequestModeAutonomous,			EGpsRequestModeTerminalBased,	EGpsRequestModeTerminalBased,	KErrNone},
       
   868 	{EGpsRequestModeAutonomous,			EGpsRequestModeHybrid,			EGpsRequestModeTerminalBased,	KErrNone},
       
   869 	{EGpsRequestModeAutonomous,			EGpsRequestModeTerminalAssisted,EGpsRequestModeUnknown,			KErrInUse},
       
   870 	{EGpsRequestModeAutonomous,			EGpsRequestModeAutonomous,		EGpsRequestModeAutonomous,		KErrNone},
       
   871 
       
   872 	{EGpsRequestModeTerminalBased,		EGpsRequestModeTerminalBased,	EGpsRequestModeTerminalBased,	KErrNone},
       
   873 	{EGpsRequestModeTerminalBased,		EGpsRequestModeHybrid,			EGpsRequestModeTerminalBased,	KErrNone},
       
   874 	{EGpsRequestModeTerminalBased,		EGpsRequestModeTerminalAssisted,EGpsRequestModeUnknown,			KErrInUse},
       
   875 	{EGpsRequestModeTerminalBased,		EGpsRequestModeAutonomous,		EGpsRequestModeTerminalBased,	KErrNone},
       
   876 
       
   877 	{EGpsRequestModeTerminalAssisted,	EGpsRequestModeTerminalBased,	EGpsRequestModeUnknown,			KErrInUse},
       
   878 	{EGpsRequestModeTerminalAssisted,	EGpsRequestModeHybrid,			EGpsRequestModeTerminalAssisted,KErrNone},
       
   879 	{EGpsRequestModeTerminalAssisted,	EGpsRequestModeTerminalAssisted,EGpsRequestModeTerminalAssisted,KErrNone},
       
   880 	{EGpsRequestModeTerminalAssisted,	EGpsRequestModeAutonomous,		EGpsRequestModeUnknown,			KErrInUse}
       
   881 	};
       
   882 	static const TInt KGpsModeCombinationTableTBOrTACount(sizeof(KGpsModeCombinationTableTBOrTA) 
       
   883 														  / sizeof(TGpsModeTableEntry));
       
   884 
       
   885 	// Module supports Terminal-Assisted and Terminal-Base simultaneously.
       
   886 	static const TGpsModeTableEntry KGpsModeCombinationTableTBAndTA[] = 
       
   887 	{
       
   888 	{EGpsRequestModeUnknown,			EGpsRequestModeTerminalBased,	EGpsRequestModeTerminalBased,	KErrNone},
       
   889 	{EGpsRequestModeUnknown,			EGpsRequestModeHybrid,			EGpsRequestModeHybrid,			KErrNone},
       
   890 	{EGpsRequestModeUnknown,			EGpsRequestModeTerminalAssisted,EGpsRequestModeTerminalAssisted,KErrNone},
       
   891 	{EGpsRequestModeUnknown,			EGpsRequestModeAutonomous,		EGpsRequestModeAutonomous,		KErrNone},
       
   892 
       
   893 	{EGpsRequestModeAutonomous,			EGpsRequestModeTerminalBased,	EGpsRequestModeTerminalBased,	KErrNone},
       
   894 	{EGpsRequestModeAutonomous,			EGpsRequestModeHybrid,			EGpsRequestModeHybrid,			KErrNone},
       
   895 	{EGpsRequestModeAutonomous,			EGpsRequestModeTerminalAssisted,EGpsRequestModeHybrid,			KErrNone},
       
   896 	{EGpsRequestModeAutonomous,			EGpsRequestModeAutonomous,		EGpsRequestModeAutonomous,		KErrNone},
       
   897 
       
   898 	{EGpsRequestModeTerminalBased,		EGpsRequestModeTerminalBased,	EGpsRequestModeTerminalBased,	KErrNone},
       
   899 	{EGpsRequestModeTerminalBased,		EGpsRequestModeHybrid,			EGpsRequestModeHybrid,			KErrNone},
       
   900 	{EGpsRequestModeTerminalBased,		EGpsRequestModeTerminalAssisted,EGpsRequestModeHybrid,			KErrNone},
       
   901 	{EGpsRequestModeTerminalBased,		EGpsRequestModeAutonomous,		EGpsRequestModeTerminalBased,	KErrNone},
       
   902 
       
   903 	{EGpsRequestModeTerminalAssisted,	EGpsRequestModeTerminalBased,	EGpsRequestModeHybrid,			KErrNone},
       
   904 	{EGpsRequestModeTerminalAssisted,	EGpsRequestModeHybrid,			EGpsRequestModeHybrid,			KErrNone},
       
   905 	{EGpsRequestModeTerminalAssisted,	EGpsRequestModeTerminalAssisted,EGpsRequestModeTerminalAssisted,KErrNone},
       
   906 	{EGpsRequestModeTerminalAssisted,	EGpsRequestModeAutonomous,		EGpsRequestModeHybrid,			KErrNone},
       
   907 	
       
   908 	{EGpsRequestModeHybrid,				EGpsRequestModeTerminalBased,	EGpsRequestModeHybrid,			KErrNone},
       
   909 	{EGpsRequestModeHybrid,				EGpsRequestModeHybrid,			EGpsRequestModeHybrid,			KErrNone},
       
   910 	{EGpsRequestModeHybrid,				EGpsRequestModeTerminalAssisted,EGpsRequestModeHybrid,			KErrNone},
       
   911 	{EGpsRequestModeHybrid,				EGpsRequestModeAutonomous,		EGpsRequestModeHybrid,			KErrNone}
       
   912 	};
       
   913 	static const TInt KGpsModeCombinationTableTBAndTACount(sizeof(KGpsModeCombinationTableTBAndTA) 
       
   914 														   / sizeof(TGpsModeTableEntry));
       
   915 	
       
   916 	// Decide which table to use
       
   917 	const TGpsModeTableEntry* modeTable(NULL);
       
   918 	TInt modeEntryCount(0);
       
   919 	switch (iDeviceGpsModeCaps)
       
   920 		{
       
   921 		case TPositionModuleInfoExtended::EDeviceGpsModeTerminalBased:
       
   922 			{
       
   923 			modeTable = KGpsModeCombinationTableTB;
       
   924 			modeEntryCount = KGpsModeCombinationTableTBCount;
       
   925 			break;
       
   926 			}
       
   927 		case TPositionModuleInfoExtended::EDeviceGpsModeTerminalAssisted:
       
   928 			{
       
   929 			modeTable = KGpsModeCombinationTableTA;
       
   930 			modeEntryCount = KGpsModeCombinationTableTACount;
       
   931 			break;
       
   932 			}
       
   933 		case (TPositionModuleInfoExtended::EDeviceGpsModeTerminalBased
       
   934 			  | TPositionModuleInfoExtended::EDeviceGpsModeTerminalAssisted):
       
   935 			{
       
   936 			modeTable = KGpsModeCombinationTableTBOrTA;
       
   937 			modeEntryCount = KGpsModeCombinationTableTBOrTACount;
       
   938 			break;
       
   939 			}
       
   940 		case TPositionModuleInfoExtended::EDeviceGpsModeSimultaneousTATB:
       
   941 			{
       
   942 			modeTable = KGpsModeCombinationTableTBAndTA;
       
   943 			modeEntryCount = KGpsModeCombinationTableTBAndTACount;
       
   944 			break;
       
   945 			}
       
   946 		}
       
   947 	
       
   948 	// Search the table to find a matching entry and get the new combined mode
       
   949 	aCombinedGpsMode = EGpsRequestModeUnknown;
       
   950 	TInt combinedReason(KErrNotSupported);
       
   951 	if (modeTable)
       
   952 		{
       
   953 		for (TInt i = 0; i < modeEntryCount; i++)
       
   954 			{
       
   955 			if (modeTable->iCurrentGpsMode == aCurrentGpsMode
       
   956 				&& modeTable->iNewRequestGpsMode == aNewRequestGpsMode)
       
   957 				{
       
   958 				aCombinedGpsMode = modeTable->iCombinedGpsMode;
       
   959 				combinedReason = modeTable->iErrorCode;
       
   960 				break;
       
   961 				}
       
   962 			
       
   963 			modeTable++;
       
   964 			}
       
   965 		}
       
   966 	
       
   967 	if (aEmergency && (combinedReason == KErrInUse))
       
   968 		{
       
   969 		combinedReason = KErrNone;
       
   970 		aCombinedGpsMode = aNewRequestGpsMode;
       
   971 		
       
   972 		}
       
   973 	else if (combinedReason == KErrNone && aCombinedGpsMode == EGpsSpecialTreatmentForHybrid)
       
   974 		{
       
   975 		TLbsNetPosRequestMethodInt posMethod;
       
   976 		GetPosSpecialTeatmentForHybrid(posMethod);
       
   977 		aCombinedGpsMode = ConvertPosMethodToGpsRequestMode(posMethod);
       
   978 		}
       
   979 	else if (combinedReason == KErrNone && aCombinedGpsMode == EGpsRequestModeUnknown)
       
   980 
       
   981 		{
       
   982 		// If the new combined mode is not set but there was no error,
       
   983 		// it means we should use the default mode from the admin settings.
       
   984 		TLbsNetPosRequestMethodInt posMethod;
       
   985 		GetDefaultPosMethod(posMethod);
       
   986 		aCombinedGpsMode = ConvertPosMethodToGpsRequestMode(posMethod);
       
   987 		}
       
   988 
       
   989 
       
   990 	return combinedReason;
       
   991 	}
       
   992 
       
   993 
       
   994 /** Get GPS positioning mode based on admin settings for the case
       
   995  *	when the capabiliies are TA or TB but a hybrid request has arrived.
       
   996 
       
   997 @param aPosMethod The default positioning method is written in to this parameter.
       
   998 
       
   999 @return KErrNone usually, but one of the standard Symbian OS error codes if there
       
  1000         was an error obtaining the positioning method.
       
  1001 */
       
  1002 void CAgpsInterfaceHandler::GetPosSpecialTeatmentForHybrid(TLbsNetPosRequestMethodInt& aPosMethod)
       
  1003 	{	
       
  1004 	
       
  1005 	// Get the current network registration status.
       
  1006 	RLbsNetworkRegistrationStatus::TLbsNetworkRegistrationStatus status;
       
  1007 	TLbsAdminSetting setting;
       
  1008 	TInt err = iNetRegStatus.GetNetworkRegistrationStatus(status);
       
  1009 	if (KErrNone != err)
       
  1010 		{
       
  1011 		LBSLOG_WARN(ELogP3, 
       
  1012 			   "CAgpsInterfaceHandler::GetDefaultPosMethod: Failed to read network registration status, using RLbsNetworkRegistrationStatus::ENetworkRegistrationUnknown");
       
  1013 		status = RLbsNetworkRegistrationStatus::ENetworkRegistrationUnknown;
       
  1014 		}
       
  1015 	
       
  1016 	switch (status)
       
  1017 		{
       
  1018 		case RLbsNetworkRegistrationStatus::ERegisteredHomeNetwork:
       
  1019 			{
       
  1020 			setting = KLbsSettingHomeGpsMode;
       
  1021 			break;
       
  1022 			}
       
  1023 		case RLbsNetworkRegistrationStatus::ERegisteredRoamingNetwork:
       
  1024 		case RLbsNetworkRegistrationStatus::ENotRegistered:
       
  1025 		case RLbsNetworkRegistrationStatus::ENetworkRegistrationUnknown:
       
  1026 		default:
       
  1027 			{
       
  1028 			setting = KLbsSettingRoamingGpsMode;
       
  1029 			break;
       
  1030 			}
       
  1031 		}
       
  1032 
       
  1033 	// Get the default mode from admin settings.
       
  1034 	CLbsAdmin::TGpsMode gpsMode;
       
  1035 	err = iAdmin.Get(setting, gpsMode);
       
  1036 	if (KErrNone != err)
       
  1037 		{
       
  1038 		LBSLOG_WARN2(ELogP3, 
       
  1039 				"CAgpsInterfaceHandler::GetDefaultPosMethod: Failed to read admin setting: 0x%x, using CLbsAdmin::EGpsModeUnknown",
       
  1040 				setting);
       
  1041 		gpsMode = CLbsAdmin::EGpsModeUnknown;
       
  1042 		}
       
  1043 
       
  1044 	switch (gpsMode)
       
  1045 		{
       
  1046 
       
  1047 		case CLbsAdmin::EGpsAutonomous:
       
  1048 		case CLbsAdmin::EGpsPreferTerminalBased:
       
  1049 		case CLbsAdmin::EGpsAlwaysTerminalBased:
       
  1050 			{
       
  1051 			TLbsNetPosMethodInt methodTB;
       
  1052 			methodTB.SetPosMethod(KLbsPositioningMeansGps, KTerminalBasedMode);
       
  1053 			aPosMethod.SetPosMethods(&methodTB, 1);
       
  1054 			break;
       
  1055 			}
       
  1056 		case CLbsAdmin::EGpsPreferTerminalAssisted:
       
  1057 		case CLbsAdmin::EGpsAlwaysTerminalAssisted:
       
  1058 			{
       
  1059 			TLbsNetPosMethodInt methodTA;
       
  1060 			methodTA.SetPosMethod(KLbsPositioningMeansGps, KTerminalAssistedMode);
       
  1061 			aPosMethod.SetPosMethods(&methodTA, 1);
       
  1062 			break;
       
  1063 			}
       
  1064 	
       
  1065 		default:
       
  1066 			{
       
  1067 			// Default to terminal based mode.
       
  1068 			TLbsNetPosMethodInt methodTB;
       
  1069 			methodTB.SetPosMethod(KLbsPositioningMeansGps, KTerminalBasedMode);
       
  1070 			aPosMethod.SetPosMethods(&methodTB, 1);
       
  1071 			break;
       
  1072 			}
       
  1073 		}
       
  1074 	}
       
  1075 /** Get the default GPS positioning mode, based on admin settings, etc.
       
  1076 
       
  1077 @param aPosMethod The default positioning method is written in to this parameter.
       
  1078 
       
  1079 @return KErrNone usually, but one of the standard Symbian OS error codes if there
       
  1080         was an error obtaining the default positioning method.
       
  1081 */
       
  1082 void CAgpsInterfaceHandler::GetDefaultPosMethod(TLbsNetPosRequestMethodInt& aPosMethod)
       
  1083 	{	
       
  1084 	
       
  1085 	// Get the current network registration status.
       
  1086 	RLbsNetworkRegistrationStatus::TLbsNetworkRegistrationStatus status;
       
  1087 	TLbsAdminSetting setting;
       
  1088 	TInt err = iNetRegStatus.GetNetworkRegistrationStatus(status);
       
  1089 	if (KErrNone != err)
       
  1090 		{
       
  1091 		LBSLOG_WARN(ELogP3, 
       
  1092 			   "CAgpsInterfaceHandler::GetDefaultPosMethod: Failed to read network registration status, using RLbsNetworkRegistrationStatus::ENetworkRegistrationUnknown");
       
  1093 		status = RLbsNetworkRegistrationStatus::ENetworkRegistrationUnknown;
       
  1094 		}
       
  1095 	
       
  1096 	switch (status)
       
  1097 		{
       
  1098 		case RLbsNetworkRegistrationStatus::ERegisteredHomeNetwork:
       
  1099 			{
       
  1100 			setting = KLbsSettingHomeGpsMode;
       
  1101 			break;
       
  1102 			}
       
  1103 		case RLbsNetworkRegistrationStatus::ERegisteredRoamingNetwork:
       
  1104 		case RLbsNetworkRegistrationStatus::ENotRegistered:
       
  1105 		case RLbsNetworkRegistrationStatus::ENetworkRegistrationUnknown:
       
  1106 		default:
       
  1107 			{
       
  1108 			setting = KLbsSettingRoamingGpsMode;
       
  1109 			break;
       
  1110 			}
       
  1111 		}
       
  1112 
       
  1113 	// Get the default mode from admin settings.
       
  1114 	CLbsAdmin::TGpsMode gpsMode;
       
  1115 	err = iAdmin.Get(setting, gpsMode);
       
  1116 	if (KErrNone != err)
       
  1117 		{
       
  1118 		LBSLOG_WARN2(ELogP3, 
       
  1119 				"CAgpsInterfaceHandler::GetDefaultPosMethod: Failed to read admin setting: 0x%x, using CLbsAdmin::EGpsModeUnknown",
       
  1120 				setting);
       
  1121 		gpsMode = CLbsAdmin::EGpsModeUnknown;
       
  1122 		}
       
  1123 
       
  1124 	switch (gpsMode)
       
  1125 		{
       
  1126 		case CLbsAdmin::EGpsPreferTerminalBased:
       
  1127 		case CLbsAdmin::EGpsAlwaysTerminalBased:
       
  1128 			{
       
  1129 			TLbsNetPosMethodInt methodTB;
       
  1130 			methodTB.SetPosMethod(KLbsPositioningMeansGpsInt, KTerminalBasedMode);
       
  1131 			aPosMethod.SetPosMethods(&methodTB, 1);
       
  1132 			break;
       
  1133 			}
       
  1134 		case CLbsAdmin::EGpsPreferTerminalAssisted:
       
  1135 		case CLbsAdmin::EGpsAlwaysTerminalAssisted:
       
  1136 			{
       
  1137 			TLbsNetPosMethodInt methodTA;
       
  1138 			methodTA.SetPosMethod(KLbsPositioningMeansGpsInt, KTerminalAssistedMode);
       
  1139 			aPosMethod.SetPosMethods(&methodTA, 1);
       
  1140 			break;
       
  1141 			}
       
  1142 		case CLbsAdmin::EGpsAutonomous:
       
  1143 			{
       
  1144 			TLbsNetPosMethodInt methodA;
       
  1145 			methodA.SetPosMethod(KLbsPositioningMeansGpsInt, KAutonomousMode);
       
  1146 			aPosMethod.SetPosMethods(&methodA, 1);
       
  1147 			break;
       
  1148 			}
       
  1149 		default:
       
  1150 			{
       
  1151 			// Default to terminal based mode.
       
  1152 			TLbsNetPosMethodInt methodTB;
       
  1153 			methodTB.SetPosMethod(KLbsPositioningMeansGpsInt, KTerminalBasedMode);
       
  1154 			aPosMethod.SetPosMethods(&methodTB, 1);
       
  1155 			break;
       
  1156 			}
       
  1157 		}
       
  1158 	}
       
  1159