locationrequestmgmt/networkrequesthandler/src/agpsinterfacehandler.cpp
changeset 0 9cfd9a3ee49c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/locationrequestmgmt/networkrequesthandler/src/agpsinterfacehandler.cpp	Tue Feb 02 01:50:39 2010 +0200
@@ -0,0 +1,1159 @@
+// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#include "lbsdevloggermacros.h"
+#include "agpsinterfacehandler.h"
+#include "nrhpanic.h"
+#include "lbsnetregstatusint.h"
+
+
+// Pre-defined technology types for common positioning modes.
+const TPositionModuleInfo::TTechnologyType KTerminalAssistedMode = 
+		(TPositionModuleInfo::ETechnologyNetwork |
+		 TPositionModuleInfo::ETechnologyAssisted);
+const TPositionModuleInfo::TTechnologyType KTerminalBasedMode = 
+		(TPositionModuleInfo::ETechnologyTerminal |
+		 TPositionModuleInfo::ETechnologyAssisted);
+const TPositionModuleInfo::TTechnologyType KAutonomousMode = 
+		(TPositionModuleInfo::ETechnologyTerminal);
+
+/** Constructor.
+*/
+CAgpsInterfaceHandler::CAgpsInterfaceHandler(
+		MAgpsInterfaceHandlerObserver& aObserver,
+		CLbsAdmin& aAdmin,
+		RLbsNetworkRegistrationStatus& aNetRegStatus) :
+	iObserver(aObserver),
+	iAdmin(aAdmin),
+	iNetRegStatus(aNetRegStatus),
+	iX3pStatus(EX3pStatusIdle),
+	iCombinedPowerModeAdvice(TLbsPositionUpdateRequestBase::EPowerAdviceOff),
+	iCombinedRequestGpsMode(EGpsRequestModeUnknown)
+	{
+	}
+
+/** Destructor.
+*/
+CAgpsInterfaceHandler::~CAgpsInterfaceHandler()
+	{
+	iRequests.Close();
+	delete iMeasurementUpdateMonitor;
+	delete iLocationUpdateMonitor;
+	}
+
+/**
+*/
+CAgpsInterfaceHandler* CAgpsInterfaceHandler::NewL(
+		MAgpsInterfaceHandlerObserver& aObserver,
+		CLbsAdmin& aAdmin,
+		RLbsNetworkRegistrationStatus& aNetRegStatus)
+	{
+	CAgpsInterfaceHandler* self = new (ELeave) CAgpsInterfaceHandler(aObserver, aAdmin, aNetRegStatus);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+/**
+*/
+
+const TInt KLbsDefaultMaxNumLocationRequests   = 4;
+
+void CAgpsInterfaceHandler::ConstructL()
+	{
+	iLocationUpdateMonitor = CLbsLocUpdateMonitor::NewL(*this);
+	iMeasurementUpdateMonitor = CLbsMeasurementInfoMonitor::NewL(*this);
+	
+	TInt err = iAdmin.Get(KLbsSettingMaximumExternalLocateRequests, iMaxNumLocationRequests);
+	if (err != KErrNone)
+		{
+		iMaxNumLocationRequests = KLbsDefaultMaxNumLocationRequests;
+		}
+
+	iRequests.ReserveL(iMaxNumLocationRequests+1); // +1 for processing emergencies
+
+	// Get the A-GPS device mode capabilities:
+	err = LbsModuleInfo::GetDeviceCapabilities(KLbsGpsLocManagerUid, iDeviceGpsModeCaps);
+	if(err != KErrNone || (iDeviceGpsModeCaps==TPositionModuleInfoExtended::EDeviceGpsModeNone))
+		{
+		// Assume module supports hybrid if it has not reported its capabilities in module info file
+		iDeviceGpsModeCaps = TPositionModuleInfoExtended::EDeviceGpsModeSimultaneousTATB;
+		}
+	
+
+	}
+	
+/** Called to initialise a location request.
+
+This is used to tell the AGPS Interface that a GPS location request
+is goind to happen 'soon'. Usually, this means we should update the
+power mode advice to at least 'standby', to give the GPS hardware
+as much time as possible to warm up.
+
+@param aSessionId Session Id of the request that is started.
+
+@return KErrNone if no problems, or one of the standard Symbian
+		error codes if there was a problem storing the new request.
+*/
+TInt CAgpsInterfaceHandler::PreStartPositioning(
+		const TLbsNetSessionIdInt& aSessionId, TBool aEmergency)
+	{
+	// Add the request to the array
+	TAgpsRequest newRequest;
+	newRequest.iSessionId = &aSessionId;
+	newRequest.iState = EAgpsRequestStateIdle;
+
+	TInt err = AddOrUpdateRequest(newRequest, aEmergency);
+
+	if (err != KErrNone)
+		{
+		return err;
+		}
+	
+	// Update the GPS power mode advice to the AGPS Manager
+	TLbsPositionUpdateRequestBase::TPowerAdvice newPowerAdvice;
+	CalculateCombinedPowerModeAdvice(newPowerAdvice);
+	if (newPowerAdvice != iCombinedPowerModeAdvice)
+		{
+		iCombinedPowerModeAdvice = newPowerAdvice;
+		iLocationUpdateMonitor->SendPowerAdviceRequest(iCombinedPowerModeAdvice);
+		}
+	
+	return err;
+	}
+
+/** Called to start a location request.
+
+This is used when the CLbsPrivLocFsm actually wants to send
+a location request to the AGPS Manager.
+
+This function must combine the new request with any existing
+request(s) - this includes quality params and GPS mode, before
+sending a request to the AGPS Manager.
+
+@param aSessionId Session Id of the request that is started.
+@param aMethod GPS mode(s) to use, as set by the network.
+@param aQuality quality params to use, as set by the network.
+
+@return KErrNone if no problems, or one of the standard Symbian
+		error codes if there was a problem storing the new request.
+*/
+TInt CAgpsInterfaceHandler::StartPositioning(
+		const TLbsNetSessionIdInt& aSessionId,
+		const TLbsNetPosRequestMethodInt& aMethod,
+		const TLbsNetPosRequestQualityInt& aQuality,
+		TBool aEmergency)
+	{
+	// Check that the new request GPS mode is valid
+	TGpsRequestMode newRequestGpsMode = ConvertPosMethodToGpsRequestMode(aMethod);
+	TGpsRequestMode newCombinedGpsMode;
+	TInt err = CalculateNewCombinedRequestMethod(
+								iCombinedRequestGpsMode,
+								newRequestGpsMode,
+								newCombinedGpsMode,
+								aEmergency);
+	if (err != KErrNone)
+		{
+		RemoveRequest(aSessionId);
+		return err;
+		}
+	
+	// Add (or update) the request to the buffer
+	TAgpsRequest newRequest;
+	newRequest.iSessionId = &aSessionId;
+	newRequest.iState = EAgpsRequestStateActive;
+	newRequest.iGpsMode = newRequestGpsMode;
+	newRequest.iPosQuality = &aQuality;
+	TTime now;
+	now.UniversalTime();
+	newRequest.iEndTime = (now + aQuality.MaxFixTime());
+	newRequest.iGpsTimingOfCellFramesRequested = aMethod.GpsTimingOfCellFramesRequested();
+	err = AddOrUpdateRequest(newRequest, aEmergency);
+	if (err != KErrNone)
+		{
+		return err;
+		}
+	
+	// Use the new combined GPS mode
+	iCombinedRequestGpsMode = newCombinedGpsMode;
+	
+	// Combine Quality.
+	CalculateCombinedRequestQuality();
+
+	// Send the new combined request to the AGPS manager.
+	SendCombinedLocationRequest();
+
+	return err;
+	}
+
+/** Temporarily stop an existing location request.
+
+This function is used when a location request has finished,
+but the session it belongs to hasn't finished yet. For example,
+in terminal assisted or hybrid mode, there is more than one location
+request within a session, so the it should not be removed from the
+list until it has completely finished.
+*/
+void CAgpsInterfaceHandler::HoldPositioning(
+		const TLbsNetSessionIdInt& aSessionId, 
+		TInt /*aReason*/)
+	{
+	// Find a matching request.
+	TInt index = iRequests.Find(aSessionId, IsSessionIdEqual);
+	if (index == KErrNotFound)
+		{
+		// If can't find one, just ignore it (but LBSLOG_ERR)?
+		LBSLOG_ERR2(ELogP3, "Failed to find a match for sessionId %d.", aSessionId.SessionNum());
+		return;
+		}
+
+	// Set the request to 'hold'.
+	iRequests[index].iState = EAgpsRequestStateHold;
+	}
+
+/** Stop and remove a location request.
+
+This function is used when a session has finished, and
+the location request can be removed from the list.
+*/
+void CAgpsInterfaceHandler::StopPositioning(
+		const TLbsNetSessionIdInt& aSessionId)
+	{	
+	// Remove request from iRequests.
+	RemoveRequest(aSessionId);
+	
+	if (IsAnyRequestState(EAgpsRequestStateActive))
+		{
+		// If there are any other active requests, combine them and send
+		// a new location request.
+		
+		// Combine quality
+		CalculateCombinedRequestQuality();
+
+		// Send the new combined request to the AGPS manager.
+		SendCombinedLocationRequest();
+		}
+	else if (!IsAnyRequestState(EAgpsRequestStateHold)
+			 && iLocationRequestActive)
+		{
+		// There are no requests that are either active or on hold, so send 
+		// a cancel message to the AGPS manager.
+		CalculateCombinedPowerModeAdvice(iCombinedPowerModeAdvice);
+		iLocationUpdateMonitor->SendCancelRequest(iCombinedPowerModeAdvice);
+		iLocationRequestActive = EFalse;
+		
+		// Also reset the combined request parameters
+		iCombinedRequestGpsMode = EGpsRequestModeUnknown;
+		}
+	else
+		{
+		// Update the GPS power mode advice to the AGPS Manager
+		TLbsPositionUpdateRequestBase::TPowerAdvice newPowerAdvice;
+		CalculateCombinedPowerModeAdvice(newPowerAdvice);
+		if (newPowerAdvice != iCombinedPowerModeAdvice)
+			{
+			iCombinedPowerModeAdvice = newPowerAdvice;
+			iLocationUpdateMonitor->SendPowerAdviceRequest(iCombinedPowerModeAdvice);
+			}		
+		}
+	}
+
+/** Check that it is ok to send the position update to state machine(s).
+
+Some position updates should be ignored by the NRH, these are:
+1) Conflict control updates (aConflictControl = ETrue), only the 
+   LocServer is interested in these.
+2) In hybrid, if the params are 'invalid'. Some licensees use special
+   values in the position update to flag that it should not be used,
+   e.g. if the horizontal accuracy is 0.
+*/
+TBool CAgpsInterfaceHandler::CheckPositionUpdateIsValid(
+		TBool aConflictControl,
+		TInt aReason,
+		const TPositionExtendedSatelliteInfo& aPosInfo,
+		const TTime& /*aActualTime*/)
+	{
+	// Some updates are only meant for the LocServer - they
+	// have aConflictControl == ETrue. We shouldn't send these
+	// to the PrivLocHandler.
+	if (aConflictControl)
+		{
+		return EFalse;
+		}
+
+	// For hybrid position, first check whether the data is valid. If any of 
+	// longitude, latitude, or horizontal accuracy is missing, or horizontal 
+	// accuracy is zero, then it's not valid, so there's no point going any 
+	// further.
+	if ((iCombinedRequestGpsMode == EGpsRequestModeHybrid) && (aReason == KErrNone))
+		{
+		TPosition pos;
+		aPosInfo.GetPosition(pos);
+		if (Math::IsNaN(pos.Latitude()) || 
+			Math::IsNaN(pos.Longitude()) || 
+			Math::IsNaN(pos.HorizontalAccuracy()) || 
+			(pos.HorizontalAccuracy() == 0))
+			{
+			return EFalse;
+			}
+		}
+	
+	return ETrue;
+	}
+	
+/** Get the latest update value from the GPS position bus.
+
+Note: Some updates are intended only for the LocServer, these
+all have conflictControl == ETrue, so in this case we return 
+KErrNotFound to tell the caller it shouldn't be used.
+
+@param aReason Reason code for the update. Set by the AGPS manager.
+@param aPosInfo Position data for the update.
+@param aTimeStamp Time the update arrived in the LBS system.
+
+@return KErrNone usually, but KErrNotFound if the update is invalid.
+*/
+TInt CAgpsInterfaceHandler::GetPosition(
+		TInt& aReason,
+		TPositionExtendedSatelliteInfo& aPosInfo,
+		TTime& aTimeStamp)
+	{
+	TBool conflictControl;
+	iLocationUpdateMonitor->GetPosition(
+			conflictControl,
+			aReason,
+			aPosInfo,
+			aTimeStamp);
+			
+	if (CheckPositionUpdateIsValid(conflictControl,
+								   aReason,
+								   aPosInfo,
+								   aTimeStamp))
+		{
+		return KErrNone;
+		}
+	else
+		{
+		return KErrNotFound;
+		}
+	}
+
+/** Get the latest update from the GPS measurement results bus.
+*/
+void CAgpsInterfaceHandler::GetMeasurement(
+		TInt& aReason,
+		TPositionGpsMeasurementInfo& aPosInfo,
+		TTime& aTimeStamp)
+	{
+	iMeasurementUpdateMonitor->GetMeasurement(aReason, aPosInfo, aTimeStamp);
+	}
+
+/** Callback for when a GPS update is sent by the AGPS manager.
+*/
+void CAgpsInterfaceHandler::OnPositionUpdate(
+			TBool aConflictControl,
+			TInt aReason,
+			const TPositionExtendedSatelliteInfo& aPosInfo,
+			const TTime& aActualTime)
+	{	
+	LBSLOG(ELogP1, "CAgpsInterfaceHandler::OnPositionUpdate");
+	if (CheckPositionUpdateIsValid(aConflictControl,
+								   aReason,
+								   aPosInfo,
+								   aActualTime))
+		{
+		// Send the update to the PrivLocHandler
+		iObserver.OnAgpsPositionUpdate(aReason, aPosInfo, aActualTime);
+		}
+	}
+
+/** Callback for when a GPS Measured Results update is sent by the AGPS manager.
+*/
+void CAgpsInterfaceHandler::OnMeasurementInfoUpdate(
+			TInt aReason, 
+			const TPositionGpsMeasurementInfo& aMeasurementResults,
+			const TTime& aActualTime)
+	{
+	// Send result to observer
+	iObserver.OnAgpsMeasurementUpdate(aReason, aMeasurementResults, aActualTime);
+	}
+
+/** Combines the quality parameters of all the active requests.
+
+Note: Only requests which are 'active' should be considered when
+combining the quality params.
+*/
+void CAgpsInterfaceHandler::CalculateCombinedRequestQuality()
+	{
+	// Set the initial values to start from
+	TReal32 minHorizAcc(10000000000000000.0);
+	TReal32 minVertAcc(10000000000000000.0);
+	TTimeIntervalMicroSeconds maxMaxFixTime(0);
+	TTime now;
+	now.UniversalTime();
+	
+	// Combine each request in turn but only if it is 'active'.
+	const TInt count = iRequests.Count();
+	for (TInt i = 0; i < count; i++)
+		{
+		if (iRequests[i].iState == EAgpsRequestStateActive)
+			{
+			// Horizontal accuracy = strictest accuracy.
+			minHorizAcc = Min(minHorizAcc,
+							  iRequests[i].iPosQuality->MinHorizontalAccuracy());
+	
+			// Vertical accuracy = strictest accuracy.
+			minVertAcc = Min(minVertAcc,
+							 iRequests[i].iPosQuality->MinVerticalAccuracy());
+			
+			// Max fix time = greatest/longest time.
+			TTimeIntervalMicroSeconds maxFixTime = (iRequests[i].iEndTime.Int64() - now.Int64());
+			maxMaxFixTime = Max(maxMaxFixTime, maxFixTime);
+			}
+		}
+	
+	// Set the combined accuracy
+	iCombinedRequestQuality.SetMinHorizontalAccuracy(minHorizAcc);
+	iCombinedRequestQuality.SetMinVerticalAccuracy(minVertAcc);
+	iCombinedRequestQuality.SetMaxFixTime(maxMaxFixTime);
+	}
+
+/** Calculates the power mode advice to send to the AGPS manager.
+
+Use the state of the X3P handler and the combined state of the current
+requests to calculate the power mode advice to send to the AGPS
+manager.
+*/
+void CAgpsInterfaceHandler::CalculateCombinedPowerModeAdvice(
+		TLbsPositionUpdateRequestBase::TPowerAdvice& aCombinedPowerAdvice)
+	{
+	// Calculate combined state for all requests
+	TAgpsRequestState combinedState(EAgpsRequestStateUnknown);
+	if (IsAnyRequestState(EAgpsRequestStateActive))
+		{
+		combinedState = EAgpsRequestStateActive;
+		}
+	else if (IsAnyRequestState(EAgpsRequestStateHold))
+		{
+		combinedState = EAgpsRequestStateHold;
+		}
+	else if (IsAnyRequestState(EAgpsRequestStateIdle))
+		{
+		combinedState = EAgpsRequestStateIdle;
+		}
+	
+	// Select the power advice to send to the AGPS manager by using
+	// a look-up table.
+	//
+	// The look-up table below is described in the NRH design document,
+	// so if it is changed, the design doc should also be updated to 
+	// keep it in sync.
+	const TInt KNumX3pStates = 3;
+	const TInt KNumLocRequestStates = 4;
+	static const TLbsPositionUpdateRequestBase::TPowerAdvice KPowerAdviceTable[KNumX3pStates][KNumLocRequestStates] = 
+		{
+			{ TLbsPositionUpdateRequestBase::EPowerAdviceOff, 
+			  TLbsPositionUpdateRequestBase::EPowerAdviceOn, 
+			  TLbsPositionUpdateRequestBase::EPowerAdviceOn, 
+			  TLbsPositionUpdateRequestBase::EPowerAdviceOn },
+			  
+			{ TLbsPositionUpdateRequestBase::EPowerAdviceStandby, 
+			  TLbsPositionUpdateRequestBase::EPowerAdviceOn, 
+			  TLbsPositionUpdateRequestBase::EPowerAdviceOn, 
+			  TLbsPositionUpdateRequestBase::EPowerAdviceOn },
+			  
+			{ TLbsPositionUpdateRequestBase::EPowerAdviceOn, 
+			  TLbsPositionUpdateRequestBase::EPowerAdviceOn, 
+			  TLbsPositionUpdateRequestBase::EPowerAdviceOn, 
+			  TLbsPositionUpdateRequestBase::EPowerAdviceOn }
+		};
+	
+	// Note: Because this table uses the enum values directly as indices,
+	//       if either enum changes, you need to re-do the table above as well.
+	__ASSERT_ALWAYS(iX3pStatus < KNumX3pStates, Panic(ENrhPanicInvalidPowerModeAdviceIndex));
+	aCombinedPowerAdvice = KPowerAdviceTable[iX3pStatus][combinedState];
+	}
+
+/**
+ Goes through all requests and decides if the timing of cell frames is requested or not
+ 
+ @return ETrue if the timing of cell frames is requested
+ */
+TBool CAgpsInterfaceHandler::CalculateCombinedTimingOfCellFramesRequested()
+	{
+	TBool timingOfCellFramesRequested(EFalse);
+	
+	// Combine each request in turn but only if it is 'active'.
+	const TInt count = iRequests.Count();
+	// Make the flag to be ETrue if there are any requests active or on hold that have the flag
+	// set to ETrue
+	for (TInt i = 0; i < count; i++)
+		{
+		if((iRequests[i].iState == EAgpsRequestStateActive || 
+				iRequests[i].iState == EAgpsRequestStateHold) && 
+			iRequests[i].iGpsTimingOfCellFramesRequested)
+			{
+			timingOfCellFramesRequested = ETrue;
+			break;
+			}
+		}
+	return timingOfCellFramesRequested;
+	}
+
+/** Performs the common actions for sending a location request to the AGPS manager.
+
+This function does common tasks such as calculating the power mode to send,
+starting or stopping the needed monitors and actually sending the combined
+request.
+
+Note: Combining the quality params and/or GPS mode params is done differently
+      depending on whether a request is being started, stopped or put on hold,
+      so that is not done in this function.
+*/
+void CAgpsInterfaceHandler::SendCombinedLocationRequest()
+	{	
+	// Always start the GPS position update monitor, even in TA mode,
+	// because we use this update bus to listen for error codes, 
+	// e.g. KPositionEarlyComplete.
+	iLocationUpdateMonitor->StartMonitor();
+	
+	// Start measurement monitor if combined request has GPS mode 
+	// with Terminal-Assisted or hybrid:
+	if (iCombinedRequestGpsMode == EGpsRequestModeTerminalAssisted
+		|| iCombinedRequestGpsMode == EGpsRequestModeHybrid)
+		{
+		iMeasurementUpdateMonitor->StartMonitor();
+		}
+	else
+		{
+		iMeasurementUpdateMonitor->StopMonitor();
+		}
+	
+	// Convert the TGpsRequestMode into TLbsNetPosRequestMethodInt
+	TLbsNetPosRequestMethodInt posMethod;
+	posMethod.SetGpsTimingOfCellFramesRequested(CalculateCombinedTimingOfCellFramesRequested());
+	ConvertGpsRequestModeToPosMethod(iCombinedRequestGpsMode, posMethod);
+
+	// Calculate the current power advice.
+	CalculateCombinedPowerModeAdvice(iCombinedPowerModeAdvice);
+	
+	// Send combined location request.
+	iLocationUpdateMonitor->SendLocationRequest(
+			iCombinedPowerModeAdvice, 
+			posMethod, 
+			iCombinedRequestQuality);
+	iLocationRequestActive = ETrue;	
+	}
+
+/** Called by CX3pHandler tp update the state of X3P requests.
+
+For X3P, if there is a client connected to the NRH server, we assume that
+there will a request soon, so we can send 'standby' power mode advice, to 
+allow the GPS hardware to prepare for a location request before the request
+has actually arrived.
+*/
+void CAgpsInterfaceHandler::SetX3pStatus(MX3pStatusHandler::TX3pStatus aStatus)
+	{
+	// Only send a power advice if the X3P status has actually changed.
+	if (aStatus != iX3pStatus)
+		{
+		iX3pStatus = aStatus;
+		TLbsPositionUpdateRequestBase::TPowerAdvice newPowerAdvice;
+		CalculateCombinedPowerModeAdvice(newPowerAdvice);
+		if (newPowerAdvice != iCombinedPowerModeAdvice)
+			{
+			iCombinedPowerModeAdvice = newPowerAdvice;
+			iLocationUpdateMonitor->SendPowerAdviceRequest(iCombinedPowerModeAdvice);
+			}
+		}
+	}
+
+/** Comparison function for use with RArray::Find()
+
+@return ETrue if session Ids match, EFalse otherwise.
+*/
+TBool CAgpsInterfaceHandler::IsSessionIdEqual(
+		const TLbsNetSessionIdInt* aSessionId, 
+		const TAgpsRequest& aRequest)
+	{
+	return (*aSessionId == *aRequest.iSessionId);
+	}
+
+/** Comparison function for use with RArray::Find()
+
+@return ETrue if states match, EFalse otherwise.
+*/
+TBool CAgpsInterfaceHandler::IsRequestStateEqual(
+		const TAgpsRequestState* aState, 
+		const TAgpsRequest& aRequest)
+	{
+	return (*aState == aRequest.iState);
+	}
+
+/** Add or update a location request in the buffer.
+
+If the request already exists on the list then its parameters are updated.
+If it doesn't exist then the request is appended to the list.
+For emergencies we haveone reserved slot used just for the emergency location request
+*/
+TInt CAgpsInterfaceHandler::AddOrUpdateRequest(const TAgpsRequest& aRequest, TBool aEmergency)
+	{
+	TInt err(KErrNone);
+	TInt index = iRequests.Find(*aRequest.iSessionId, IsSessionIdEqual);
+	if (index >= 0)
+		{
+		// Update params of existing request
+		iRequests[index] = aRequest;
+		}
+	else if (aEmergency)
+	    {
+	    // Note that we can guarantee at least ONE free slot. See below.
+	    // add emergency request to list
+	    err = iRequests.Append(aRequest);
+	    }
+	else if (iRequests.Count() <= iMaxNumLocationRequests)
+		{
+		// Add new request to iRequests. Note, only allocate up to 
+		// iMaxNumLocationRequests slots and leave at least one free for use for emergency
+		err = iRequests.Append(aRequest);
+		}
+	else
+		{
+		// Exceeded the max number of requests, reject it!
+		LBSLOG_ERR3(ELogP3,
+					"CAgpsInterfaceHandler::AddOrUpdateRequest: Can't add new request, active requests (%d), limit (%d)", 
+					iRequests.Count(), 
+					iMaxNumLocationRequests);
+		return KErrInUse;		
+		}
+	return err;
+	}
+
+/** Remove a request from the buffer.
+
+@param aSessionId SessionId of the request to remove.
+*/
+void CAgpsInterfaceHandler::RemoveRequest(const TLbsNetSessionIdInt& aSessionId)
+	{
+	TInt index = iRequests.Find(aSessionId, IsSessionIdEqual);
+	if (index >= 0)
+		{
+		iRequests.Remove(index);
+		}
+	else
+		{
+		LBSLOG_WARN2(ELogP3, "CAgpsInterfaceHandler::RemoveRequest: Failed to find match for sessionId %d.", aSessionId.SessionNum());
+		}
+	}
+
+/** Search to find if any requests' state matches the given state.
+
+@param aState Request state to compare to.
+
+@return ETrue if any state has a matching state. EFalse otherwise.
+*/
+TBool CAgpsInterfaceHandler::IsAnyRequestState(
+		TAgpsRequestState aState)
+	{
+	TInt index = iRequests.Find(aState, IsRequestStateEqual);
+	return (index >= 0);
+	}
+
+/** Convert a TLbsNetPosRequestMethodInt into a TGpsRequestMode enum.
+*/
+TGpsRequestMode CAgpsInterfaceHandler::ConvertPosMethodToGpsRequestMode(
+		const TLbsNetPosRequestMethodInt& aPosMethod)
+	{
+	TGpsRequestMode gpsMode(EGpsRequestModeUnknown);
+	
+	const TInt count = aPosMethod.NumPosMethods();
+	for (TInt i = 0; i < count; i++)
+		{
+		TLbsNetPosMethodInt method;
+		aPosMethod.GetPosMethod(i, method);
+		switch (method.PosMode())
+			{
+			case KAutonomousMode:
+				{
+				if (gpsMode == EGpsRequestModeTerminalAssisted)
+					{
+					gpsMode = EGpsRequestModeHybrid;
+					}
+				else
+					{
+					gpsMode = EGpsRequestModeAutonomous;
+					}
+				break;
+				}
+			case KTerminalBasedMode:
+				{
+				if (gpsMode == EGpsRequestModeTerminalAssisted)
+					{
+					gpsMode = EGpsRequestModeHybrid;
+					}
+				else
+					{
+					gpsMode = EGpsRequestModeTerminalBased;
+					}
+				break;
+				}
+			case KTerminalAssistedMode:
+				{
+				if (gpsMode == EGpsRequestModeTerminalBased
+					|| gpsMode == EGpsRequestModeAutonomous)
+					{
+					gpsMode = EGpsRequestModeHybrid;
+					}
+				else
+					{
+					gpsMode = EGpsRequestModeTerminalAssisted;
+					}
+				break;
+				}
+			}
+		}
+	
+	return gpsMode;
+	}
+
+
+/** Convert a TGpsRequestMode enum into a TLbsNetPosRequestMethodInt.
+*/
+void CAgpsInterfaceHandler::ConvertGpsRequestModeToPosMethod(
+		TGpsRequestMode aMode, 
+		TLbsNetPosRequestMethodInt& aPosMethod)
+	{
+	TLbsNetPosMethodInt methods[2];
+	switch (aMode)
+		{
+		case EGpsRequestModeAutonomous:
+			{
+			methods[0].SetPosMethod(KLbsPositioningMeansGpsInt, KAutonomousMode);
+			aPosMethod.SetPosMethods(methods, 1);
+			break;
+			}
+		case EGpsRequestModeTerminalBased:
+			{
+			methods[0].SetPosMethod(KLbsPositioningMeansGpsInt, KTerminalBasedMode);
+			aPosMethod.SetPosMethods(methods, 1);
+			break;
+			}
+		case EGpsRequestModeTerminalAssisted:
+			{
+			methods[0].SetPosMethod(KLbsPositioningMeansGpsInt, KTerminalAssistedMode);
+			aPosMethod.SetPosMethods(methods, 1);
+			break;
+			}
+		case EGpsRequestModeHybrid:
+			{
+			methods[0].SetPosMethod(KLbsPositioningMeansGpsInt, KTerminalBasedMode);
+			methods[1].SetPosMethod(KLbsPositioningMeansGpsInt, KTerminalAssistedMode);
+			aPosMethod.SetPosMethods(methods, 2);
+			break;
+			}
+
+		case EGpsRequestModeUnknown:
+		default:
+			{
+			GetDefaultPosMethod(aPosMethod);
+			break;
+			}
+		}
+
+	}
+
+/** Calculate the new combined GPS mode when a new request is added.
+
+The new combined GPS mode depends on a combination of:
+1) The GPS mode(s) the module supports.
+2) The current combined GPS mode.
+3) The GPS mode of the new request.
+
+@param aCurrentPosMethod [In] The GPS mode of the current combined request.
+@param aNewRequestPosMethod [In] The GPS mode of the new request.
+@param aCurrentPosMethod [Out] The GPS mode of the newly combined requests.
+
+@return KErrNone if the GPS mode was combined successfully, KErrNotSupported
+        if the GPS mode of the new request is not supported by the GPS module,
+        KErrInUse if the new request GPS mode clashes with the current combined
+        request GPS mode, e.g. if the module supports either TA or TB, but not
+        both and the new request is TB but the current request is TA.
+*/
+TInt CAgpsInterfaceHandler::CalculateNewCombinedRequestMethod(
+		TGpsRequestMode aCurrentGpsMode,
+		TGpsRequestMode aNewRequestGpsMode,
+		TGpsRequestMode& aCombinedGpsMode,
+		TBool aEmergency)
+	{
+	// Table entry
+	struct TGpsModeTableEntry
+		{
+		TGpsRequestMode iCurrentGpsMode;
+		TGpsRequestMode iNewRequestGpsMode;
+		TGpsRequestMode iCombinedGpsMode;
+		TInt iErrorCode;
+		};
+	
+	// Each of the tables below are taken directly from the 
+	// NRH design document. If any of them are changed (e.g.
+	// for a defect fix), the table in the design doc should
+	// also be updated to match.
+
+	// Module supports Terminal-Based only.
+	static const TGpsModeTableEntry KGpsModeCombinationTableTB[] = 
+	{
+	// Current request mode				// New request mode				// Newly combined request mode	// Error
+	{EGpsRequestModeUnknown,			EGpsRequestModeTerminalBased,	EGpsRequestModeTerminalBased,	KErrNone},
+	{EGpsRequestModeUnknown,			EGpsRequestModeHybrid,			EGpsRequestModeTerminalBased,	KErrNone},
+	{EGpsRequestModeUnknown,			EGpsRequestModeTerminalAssisted,EGpsRequestModeUnknown,			KErrNotSupported},
+	{EGpsRequestModeUnknown,			EGpsRequestModeAutonomous,		EGpsRequestModeAutonomous,		KErrNone},
+	
+	{EGpsRequestModeAutonomous,			EGpsRequestModeTerminalBased,	EGpsRequestModeTerminalBased,	KErrNone},
+	{EGpsRequestModeAutonomous,			EGpsRequestModeHybrid,			EGpsRequestModeTerminalBased,	KErrNone},
+	{EGpsRequestModeAutonomous,			EGpsRequestModeTerminalAssisted,EGpsRequestModeUnknown,			KErrNotSupported},
+	{EGpsRequestModeAutonomous,			EGpsRequestModeAutonomous,		EGpsRequestModeAutonomous,		KErrNone},
+	
+	{EGpsRequestModeTerminalBased,		EGpsRequestModeTerminalBased,	EGpsRequestModeTerminalBased,	KErrNone},
+	{EGpsRequestModeTerminalBased,		EGpsRequestModeHybrid,			EGpsRequestModeTerminalBased,	KErrNone},
+	{EGpsRequestModeTerminalBased,		EGpsRequestModeTerminalAssisted,EGpsRequestModeUnknown,			KErrNotSupported},
+	{EGpsRequestModeTerminalBased,		EGpsRequestModeAutonomous,		EGpsRequestModeTerminalBased,	KErrNone}
+	};
+	static const TInt KGpsModeCombinationTableTBCount(sizeof(KGpsModeCombinationTableTB) 
+													  / sizeof(TGpsModeTableEntry));
+
+	// Module supports Terminal-Assisted only.
+	static const TGpsModeTableEntry KGpsModeCombinationTableTA[] = 
+	{
+	{EGpsRequestModeUnknown,			EGpsRequestModeTerminalBased,	EGpsRequestModeUnknown,			KErrNotSupported},
+	{EGpsRequestModeUnknown,			EGpsRequestModeHybrid,			EGpsRequestModeTerminalAssisted,KErrNone},
+	{EGpsRequestModeUnknown,			EGpsRequestModeTerminalAssisted,EGpsRequestModeTerminalAssisted,KErrNone},
+	{EGpsRequestModeUnknown,			EGpsRequestModeAutonomous,		EGpsRequestModeUnknown,			KErrNotSupported},
+
+	{EGpsRequestModeTerminalAssisted,	EGpsRequestModeTerminalBased,	EGpsRequestModeUnknown,			KErrNotSupported},
+	{EGpsRequestModeTerminalAssisted,	EGpsRequestModeHybrid,			EGpsRequestModeTerminalAssisted,KErrNone},
+	{EGpsRequestModeTerminalAssisted,	EGpsRequestModeTerminalAssisted,EGpsRequestModeTerminalAssisted,KErrNone},
+	{EGpsRequestModeTerminalAssisted,	EGpsRequestModeAutonomous,		EGpsRequestModeUnknown,			KErrNotSupported}
+	};
+	static const TInt KGpsModeCombinationTableTACount(sizeof(KGpsModeCombinationTableTA) 
+													  / sizeof(TGpsModeTableEntry));
+	
+	// Module supports either Terminal-Assisted or Terminal-Based (but not both at the same time).
+	static const TGpsModeTableEntry KGpsModeCombinationTableTBOrTA[] = 
+	{
+	{EGpsRequestModeUnknown,			EGpsRequestModeTerminalBased,	EGpsRequestModeTerminalBased,	KErrNone},
+	{EGpsRequestModeUnknown,			EGpsRequestModeHybrid,			EGpsSpecialTreatmentForHybrid,	KErrNone},
+	{EGpsRequestModeUnknown,			EGpsRequestModeTerminalAssisted,EGpsRequestModeTerminalAssisted,KErrNone},
+	{EGpsRequestModeUnknown,			EGpsRequestModeAutonomous,		EGpsRequestModeAutonomous,		KErrNone},
+
+	{EGpsRequestModeAutonomous,			EGpsRequestModeTerminalBased,	EGpsRequestModeTerminalBased,	KErrNone},
+	{EGpsRequestModeAutonomous,			EGpsRequestModeHybrid,			EGpsRequestModeTerminalBased,	KErrNone},
+	{EGpsRequestModeAutonomous,			EGpsRequestModeTerminalAssisted,EGpsRequestModeUnknown,			KErrInUse},
+	{EGpsRequestModeAutonomous,			EGpsRequestModeAutonomous,		EGpsRequestModeAutonomous,		KErrNone},
+
+	{EGpsRequestModeTerminalBased,		EGpsRequestModeTerminalBased,	EGpsRequestModeTerminalBased,	KErrNone},
+	{EGpsRequestModeTerminalBased,		EGpsRequestModeHybrid,			EGpsRequestModeTerminalBased,	KErrNone},
+	{EGpsRequestModeTerminalBased,		EGpsRequestModeTerminalAssisted,EGpsRequestModeUnknown,			KErrInUse},
+	{EGpsRequestModeTerminalBased,		EGpsRequestModeAutonomous,		EGpsRequestModeTerminalBased,	KErrNone},
+
+	{EGpsRequestModeTerminalAssisted,	EGpsRequestModeTerminalBased,	EGpsRequestModeUnknown,			KErrInUse},
+	{EGpsRequestModeTerminalAssisted,	EGpsRequestModeHybrid,			EGpsRequestModeTerminalAssisted,KErrNone},
+	{EGpsRequestModeTerminalAssisted,	EGpsRequestModeTerminalAssisted,EGpsRequestModeTerminalAssisted,KErrNone},
+	{EGpsRequestModeTerminalAssisted,	EGpsRequestModeAutonomous,		EGpsRequestModeUnknown,			KErrInUse}
+	};
+	static const TInt KGpsModeCombinationTableTBOrTACount(sizeof(KGpsModeCombinationTableTBOrTA) 
+														  / sizeof(TGpsModeTableEntry));
+
+	// Module supports Terminal-Assisted and Terminal-Base simultaneously.
+	static const TGpsModeTableEntry KGpsModeCombinationTableTBAndTA[] = 
+	{
+	{EGpsRequestModeUnknown,			EGpsRequestModeTerminalBased,	EGpsRequestModeTerminalBased,	KErrNone},
+	{EGpsRequestModeUnknown,			EGpsRequestModeHybrid,			EGpsRequestModeHybrid,			KErrNone},
+	{EGpsRequestModeUnknown,			EGpsRequestModeTerminalAssisted,EGpsRequestModeTerminalAssisted,KErrNone},
+	{EGpsRequestModeUnknown,			EGpsRequestModeAutonomous,		EGpsRequestModeAutonomous,		KErrNone},
+
+	{EGpsRequestModeAutonomous,			EGpsRequestModeTerminalBased,	EGpsRequestModeTerminalBased,	KErrNone},
+	{EGpsRequestModeAutonomous,			EGpsRequestModeHybrid,			EGpsRequestModeHybrid,			KErrNone},
+	{EGpsRequestModeAutonomous,			EGpsRequestModeTerminalAssisted,EGpsRequestModeHybrid,			KErrNone},
+	{EGpsRequestModeAutonomous,			EGpsRequestModeAutonomous,		EGpsRequestModeAutonomous,		KErrNone},
+
+	{EGpsRequestModeTerminalBased,		EGpsRequestModeTerminalBased,	EGpsRequestModeTerminalBased,	KErrNone},
+	{EGpsRequestModeTerminalBased,		EGpsRequestModeHybrid,			EGpsRequestModeHybrid,			KErrNone},
+	{EGpsRequestModeTerminalBased,		EGpsRequestModeTerminalAssisted,EGpsRequestModeHybrid,			KErrNone},
+	{EGpsRequestModeTerminalBased,		EGpsRequestModeAutonomous,		EGpsRequestModeTerminalBased,	KErrNone},
+
+	{EGpsRequestModeTerminalAssisted,	EGpsRequestModeTerminalBased,	EGpsRequestModeHybrid,			KErrNone},
+	{EGpsRequestModeTerminalAssisted,	EGpsRequestModeHybrid,			EGpsRequestModeHybrid,			KErrNone},
+	{EGpsRequestModeTerminalAssisted,	EGpsRequestModeTerminalAssisted,EGpsRequestModeTerminalAssisted,KErrNone},
+	{EGpsRequestModeTerminalAssisted,	EGpsRequestModeAutonomous,		EGpsRequestModeHybrid,			KErrNone},
+	
+	{EGpsRequestModeHybrid,				EGpsRequestModeTerminalBased,	EGpsRequestModeHybrid,			KErrNone},
+	{EGpsRequestModeHybrid,				EGpsRequestModeHybrid,			EGpsRequestModeHybrid,			KErrNone},
+	{EGpsRequestModeHybrid,				EGpsRequestModeTerminalAssisted,EGpsRequestModeHybrid,			KErrNone},
+	{EGpsRequestModeHybrid,				EGpsRequestModeAutonomous,		EGpsRequestModeHybrid,			KErrNone}
+	};
+	static const TInt KGpsModeCombinationTableTBAndTACount(sizeof(KGpsModeCombinationTableTBAndTA) 
+														   / sizeof(TGpsModeTableEntry));
+	
+	// Decide which table to use
+	const TGpsModeTableEntry* modeTable(NULL);
+	TInt modeEntryCount(0);
+	switch (iDeviceGpsModeCaps)
+		{
+		case TPositionModuleInfoExtended::EDeviceGpsModeTerminalBased:
+			{
+			modeTable = KGpsModeCombinationTableTB;
+			modeEntryCount = KGpsModeCombinationTableTBCount;
+			break;
+			}
+		case TPositionModuleInfoExtended::EDeviceGpsModeTerminalAssisted:
+			{
+			modeTable = KGpsModeCombinationTableTA;
+			modeEntryCount = KGpsModeCombinationTableTACount;
+			break;
+			}
+		case (TPositionModuleInfoExtended::EDeviceGpsModeTerminalBased
+			  | TPositionModuleInfoExtended::EDeviceGpsModeTerminalAssisted):
+			{
+			modeTable = KGpsModeCombinationTableTBOrTA;
+			modeEntryCount = KGpsModeCombinationTableTBOrTACount;
+			break;
+			}
+		case TPositionModuleInfoExtended::EDeviceGpsModeSimultaneousTATB:
+			{
+			modeTable = KGpsModeCombinationTableTBAndTA;
+			modeEntryCount = KGpsModeCombinationTableTBAndTACount;
+			break;
+			}
+		}
+	
+	// Search the table to find a matching entry and get the new combined mode
+	aCombinedGpsMode = EGpsRequestModeUnknown;
+	TInt combinedReason(KErrNotSupported);
+	if (modeTable)
+		{
+		for (TInt i = 0; i < modeEntryCount; i++)
+			{
+			if (modeTable->iCurrentGpsMode == aCurrentGpsMode
+				&& modeTable->iNewRequestGpsMode == aNewRequestGpsMode)
+				{
+				aCombinedGpsMode = modeTable->iCombinedGpsMode;
+				combinedReason = modeTable->iErrorCode;
+				break;
+				}
+			
+			modeTable++;
+			}
+		}
+	
+	if (aEmergency && (combinedReason == KErrInUse))
+		{
+		combinedReason = KErrNone;
+		aCombinedGpsMode = aNewRequestGpsMode;
+		
+		}
+	else if (combinedReason == KErrNone && aCombinedGpsMode == EGpsSpecialTreatmentForHybrid)
+		{
+		TLbsNetPosRequestMethodInt posMethod;
+		GetPosSpecialTeatmentForHybrid(posMethod);
+		aCombinedGpsMode = ConvertPosMethodToGpsRequestMode(posMethod);
+		}
+	else if (combinedReason == KErrNone && aCombinedGpsMode == EGpsRequestModeUnknown)
+
+		{
+		// If the new combined mode is not set but there was no error,
+		// it means we should use the default mode from the admin settings.
+		TLbsNetPosRequestMethodInt posMethod;
+		GetDefaultPosMethod(posMethod);
+		aCombinedGpsMode = ConvertPosMethodToGpsRequestMode(posMethod);
+		}
+
+
+	return combinedReason;
+	}
+
+
+/** Get GPS positioning mode based on admin settings for the case
+ *	when the capabiliies are TA or TB but a hybrid request has arrived.
+
+@param aPosMethod The default positioning method is written in to this parameter.
+
+@return KErrNone usually, but one of the standard Symbian OS error codes if there
+        was an error obtaining the positioning method.
+*/
+void CAgpsInterfaceHandler::GetPosSpecialTeatmentForHybrid(TLbsNetPosRequestMethodInt& aPosMethod)
+	{	
+	
+	// Get the current network registration status.
+	RLbsNetworkRegistrationStatus::TLbsNetworkRegistrationStatus status;
+	TLbsAdminSetting setting;
+	TInt err = iNetRegStatus.GetNetworkRegistrationStatus(status);
+	if (KErrNone != err)
+		{
+		LBSLOG_WARN(ELogP3, 
+			   "CAgpsInterfaceHandler::GetDefaultPosMethod: Failed to read network registration status, using RLbsNetworkRegistrationStatus::ENetworkRegistrationUnknown");
+		status = RLbsNetworkRegistrationStatus::ENetworkRegistrationUnknown;
+		}
+	
+	switch (status)
+		{
+		case RLbsNetworkRegistrationStatus::ERegisteredHomeNetwork:
+			{
+			setting = KLbsSettingHomeGpsMode;
+			break;
+			}
+		case RLbsNetworkRegistrationStatus::ERegisteredRoamingNetwork:
+		case RLbsNetworkRegistrationStatus::ENotRegistered:
+		case RLbsNetworkRegistrationStatus::ENetworkRegistrationUnknown:
+		default:
+			{
+			setting = KLbsSettingRoamingGpsMode;
+			break;
+			}
+		}
+
+	// Get the default mode from admin settings.
+	CLbsAdmin::TGpsMode gpsMode;
+	err = iAdmin.Get(setting, gpsMode);
+	if (KErrNone != err)
+		{
+		LBSLOG_WARN2(ELogP3, 
+				"CAgpsInterfaceHandler::GetDefaultPosMethod: Failed to read admin setting: 0x%x, using CLbsAdmin::EGpsModeUnknown",
+				setting);
+		gpsMode = CLbsAdmin::EGpsModeUnknown;
+		}
+
+	switch (gpsMode)
+		{
+
+		case CLbsAdmin::EGpsAutonomous:
+		case CLbsAdmin::EGpsPreferTerminalBased:
+		case CLbsAdmin::EGpsAlwaysTerminalBased:
+			{
+			TLbsNetPosMethodInt methodTB;
+			methodTB.SetPosMethod(KLbsPositioningMeansGps, KTerminalBasedMode);
+			aPosMethod.SetPosMethods(&methodTB, 1);
+			break;
+			}
+		case CLbsAdmin::EGpsPreferTerminalAssisted:
+		case CLbsAdmin::EGpsAlwaysTerminalAssisted:
+			{
+			TLbsNetPosMethodInt methodTA;
+			methodTA.SetPosMethod(KLbsPositioningMeansGps, KTerminalAssistedMode);
+			aPosMethod.SetPosMethods(&methodTA, 1);
+			break;
+			}
+	
+		default:
+			{
+			// Default to terminal based mode.
+			TLbsNetPosMethodInt methodTB;
+			methodTB.SetPosMethod(KLbsPositioningMeansGps, KTerminalBasedMode);
+			aPosMethod.SetPosMethods(&methodTB, 1);
+			break;
+			}
+		}
+	}
+/** Get the default GPS positioning mode, based on admin settings, etc.
+
+@param aPosMethod The default positioning method is written in to this parameter.
+
+@return KErrNone usually, but one of the standard Symbian OS error codes if there
+        was an error obtaining the default positioning method.
+*/
+void CAgpsInterfaceHandler::GetDefaultPosMethod(TLbsNetPosRequestMethodInt& aPosMethod)
+	{	
+	
+	// Get the current network registration status.
+	RLbsNetworkRegistrationStatus::TLbsNetworkRegistrationStatus status;
+	TLbsAdminSetting setting;
+	TInt err = iNetRegStatus.GetNetworkRegistrationStatus(status);
+	if (KErrNone != err)
+		{
+		LBSLOG_WARN(ELogP3, 
+			   "CAgpsInterfaceHandler::GetDefaultPosMethod: Failed to read network registration status, using RLbsNetworkRegistrationStatus::ENetworkRegistrationUnknown");
+		status = RLbsNetworkRegistrationStatus::ENetworkRegistrationUnknown;
+		}
+	
+	switch (status)
+		{
+		case RLbsNetworkRegistrationStatus::ERegisteredHomeNetwork:
+			{
+			setting = KLbsSettingHomeGpsMode;
+			break;
+			}
+		case RLbsNetworkRegistrationStatus::ERegisteredRoamingNetwork:
+		case RLbsNetworkRegistrationStatus::ENotRegistered:
+		case RLbsNetworkRegistrationStatus::ENetworkRegistrationUnknown:
+		default:
+			{
+			setting = KLbsSettingRoamingGpsMode;
+			break;
+			}
+		}
+
+	// Get the default mode from admin settings.
+	CLbsAdmin::TGpsMode gpsMode;
+	err = iAdmin.Get(setting, gpsMode);
+	if (KErrNone != err)
+		{
+		LBSLOG_WARN2(ELogP3, 
+				"CAgpsInterfaceHandler::GetDefaultPosMethod: Failed to read admin setting: 0x%x, using CLbsAdmin::EGpsModeUnknown",
+				setting);
+		gpsMode = CLbsAdmin::EGpsModeUnknown;
+		}
+
+	switch (gpsMode)
+		{
+		case CLbsAdmin::EGpsPreferTerminalBased:
+		case CLbsAdmin::EGpsAlwaysTerminalBased:
+			{
+			TLbsNetPosMethodInt methodTB;
+			methodTB.SetPosMethod(KLbsPositioningMeansGpsInt, KTerminalBasedMode);
+			aPosMethod.SetPosMethods(&methodTB, 1);
+			break;
+			}
+		case CLbsAdmin::EGpsPreferTerminalAssisted:
+		case CLbsAdmin::EGpsAlwaysTerminalAssisted:
+			{
+			TLbsNetPosMethodInt methodTA;
+			methodTA.SetPosMethod(KLbsPositioningMeansGpsInt, KTerminalAssistedMode);
+			aPosMethod.SetPosMethods(&methodTA, 1);
+			break;
+			}
+		case CLbsAdmin::EGpsAutonomous:
+			{
+			TLbsNetPosMethodInt methodA;
+			methodA.SetPosMethod(KLbsPositioningMeansGpsInt, KAutonomousMode);
+			aPosMethod.SetPosMethods(&methodA, 1);
+			break;
+			}
+		default:
+			{
+			// Default to terminal based mode.
+			TLbsNetPosMethodInt methodTB;
+			methodTB.SetPosMethod(KLbsPositioningMeansGpsInt, KTerminalBasedMode);
+			aPosMethod.SetPosMethods(&methodTB, 1);
+			break;
+			}
+		}
+	}
+