networkprotocolmodules/suplprotocolmodule/SuplProtocol/src/suplassistancedatamgr.cpp
changeset 36 b47902b73a93
parent 0 9cfd9a3ee49c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/networkprotocolmodules/suplprotocolmodule/SuplProtocol/src/suplassistancedatamgr.cpp	Fri Jun 04 10:34:15 2010 +0100
@@ -0,0 +1,478 @@
+// 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:
+// This file provides the implementation of the class that manages
+// assistance data during location requests.
+// 
+//
+
+/**
+ @file
+ @internalTechnology
+ @deprecated
+*/
+
+
+#include <e32base.h>
+#include <lbs/lbsnetcommon.h>
+#include <lbs/lbsnetprotocolbase.h>
+#include <lbs/lbsassistancereferencelocation.h>
+#include "suplassistancedatamgr.h"
+#include "supldevloggermacros.h"
+
+/** Constant to identify an empty set of assistance data.
+*/
+const TInt KAssistDataEmpty = 0;
+
+/** KAssistDataReportTimer
+Identity of timer
+*/
+const TInt KAssistDataReportTimer = 0x01;
+
+/** KAssistDataReportTimerDurationInSec
+Timer duration for when assistance data is expected from network
+*/
+const TInt KAssistDataReportTimerDurationInSec = 1;
+
+/** Static constructor.
+@return A new instance of the CSuplAssistanceDataManager class.
+*/  
+CSuplAssistanceDataManager* CSuplAssistanceDataManager::NewL(MSuplProtocolManagerObserver& aGateway)
+	{
+	SUPLLOG(ELogP1, "CSuplAssistanceDataManager::NewL() Begin\n");
+	CSuplAssistanceDataManager* self = new (ELeave) CSuplAssistanceDataManager(aGateway);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	SUPLLOG(ELogP1, "CSuplAssistanceDataManager::NewL() End\n");
+	return self;
+	}
+
+
+/** Standard constructor.
+*/  
+CSuplAssistanceDataManager::CSuplAssistanceDataManager(MSuplProtocolManagerObserver& aGateway):
+							iGateway(aGateway)
+	{
+	SUPLLOG(ELogP1, "CSuplAssistanceDataManager::CSuplAssistanceDataManager() Begin\n");
+	SUPLLOG(ELogP1, "CSuplAssistanceDataManager::CSuplAssistanceDataManager() End\n");
+	}
+
+
+/** Standard destructor.
+*/  
+CSuplAssistanceDataManager::~CSuplAssistanceDataManager()
+	{
+	SUPLLOG(ELogP1, "CSuplAssistanceDataManager::~CSuplAssistanceDataManager() Begin\n");
+	delete iAssistDataReportTimer;
+	SUPLLOG(ELogP1, "CSuplAssistanceDataManager::~CSuplAssistanceDataManager() End\n");
+	}
+
+
+/** Private second-stage constructor.
+*/  
+void CSuplAssistanceDataManager::ConstructL()
+	{
+	SUPLLOG(ELogP1, "CSuplAssistanceDataManager::ConstructL() Begin\n");
+	iAssistDataReportTimer = CLbsCallbackTimer::NewL(*this);
+	SUPLLOG(ELogP1, "CSuplAssistanceDataManager::ConstructL() End\n");
+	}
+
+
+/** Process assistance data request.
+This is called by the protocol manager to process an assistance data request
+received from LBS.
+
+The method first identifies any errors in the assistance data request mask. If any
+assistance data types are unsupported, this method sends a response to LBS
+for those types with error code KErrArgument.
+
+Then, if there are any state machines ready to handle an assistance data request, the
+iPendingDataMask mask is added to aDataRequestMask and then cleared. Otherwise, it is
+aDataRequestMask that is added to iPendingDataMask.
+
+The state machines that must receive the assitance data request are returned by this
+method as a mask of type MLbsNetworkProtocolObserver::TLbsNetProtocolServiceMask.
+
+@param aDataRequest The set of assistance data requested by LBS.
+@return aDataRequest The set of assistance data that must be requested from the state machines
+@return MLbsNetworkProtocolObserver::TLbsNetProtocolServiceMask the state machine that
+		must receive the assistance data request.
+*/
+MLbsNetworkProtocolObserver::TLbsNetProtocolServiceMask CSuplAssistanceDataManager::ProcessDataRequest(TLbsAsistanceDataGroup& aDataRequestMask)
+	{
+	SUPLLOG(ELogP1, "CSuplAssistanceDataManager::ProcessDataRequest() Begin\n");
+
+	// state machines ready for assistance data requests
+	MLbsNetworkProtocolObserver::TLbsNetProtocolServiceMask readyMachinesMask = MLbsNetworkProtocolObserver::EServiceNone;
+
+	// Identify invalid parts of the request.
+	TLbsAsistanceDataGroup validSet = EAssistanceDataAquisitionAssistance
+									 | EAssistanceDataBadSatList
+									 | EAssistanceDataNavigationModel
+									 | EAssistanceDataReferenceTime
+									 | EAssistanceDataIonosphericModel
+									 | EAssistanceDataReferenceLocation
+									 | EAssistanceDataAlmanac
+									 | EAssistanceDataPositioningGpsUtcModel;
+
+	// Create a request error mask for any invalid parts of the request
+	TLbsAsistanceDataGroup requestErrorMask = aDataRequestMask & ~validSet;
+
+	if (requestErrorMask != 0)
+		{
+		// Send an error back to LBS for the assistance data types in the
+		// error mask
+		//
+		RLbsAssistanceDataBuilderSet dummyAssistanceData; //ignored by LBS when error is not KErrNone
+		iGateway.AssistanceDataInd(requestErrorMask, dummyAssistanceData, KErrArgument);
+		}
+
+	// Remove from the request mask any assistance data types reported to LBS
+	// within the last second. Those need not be requested again. Remove also
+	// invalid assitance data types
+	aDataRequestMask = aDataRequestMask & ~iReportedDataMask & validSet;
+
+	// See if there are any state machines ready to process assistance data requests
+	// (they must get an assistance data request even if it is empty)
+	if (iReadyMachinesMask != MLbsNetworkProtocolObserver::EServiceNone)
+		{
+		// Add pending assistance data to the request and clear the pending mask;
+		aDataRequestMask = aDataRequestMask | iPendingDataMask;
+		iPendingDataMask = KAssistDataEmpty;
+
+		// The request will be forwarded to all the ready machines. After that
+		// they are no longer ready for new assistance data requests (until they
+		// reported as ready again with MachineReadyForAssistanceDataRequest())
+		readyMachinesMask = iReadyMachinesMask;
+		iReadyMachinesMask = MLbsNetworkProtocolObserver::EServiceNone;
+		}
+	else
+		{
+		// Add requested assistance data types to the pending ones
+		iPendingDataMask = iPendingDataMask | aDataRequestMask;
+		}
+
+	// If any machine is going to get the assistance data request, remember what 
+	// assistance data types are going to be retrieved by each state machine.
+	if (readyMachinesMask != MLbsNetworkProtocolObserver::EServiceNone)
+		{
+		if (readyMachinesMask & MLbsNetworkProtocolObserver::EServiceSelfLocation)
+			{
+			iMoLrRequestedDataMask = aDataRequestMask;
+			}
+		
+		if (readyMachinesMask & MLbsNetworkProtocolObserver::EServiceMobileTerminated)
+			{
+			iMtLrRequestedDataMask = aDataRequestMask;
+			}
+		}
+	SUPLLOG(ELogP1, "CSuplAssistanceDataManager::ProcessDataRequest() End\n");
+	return readyMachinesMask;
+	}
+
+
+/** Process Assistance Data Report
+
+Called by the Protocol Manager when a state machine (aStateMachine) has reported that it
+has obtained assistance data. The assistance data types reported in this call are those in
+aDataReportMask. If the error code aReason is KErrNone, then the assistance data is be available
+in aAssistanceDataBuilder.
+
+The error in aReason applies to all of the assistance data types in aDataReportMask.
+
+This method sends the Assistance Data (or error indication) to LBS.
+
+If Reference Location is part of the reported set of assistance data, it is extracted,
+converted to the format expected by LBS and sent to LBS.
+
+@param aAssistanceData. The actual assistance data being reported when aReason is KErrNone
+@param aDataReportMask. The assistanced data types being reported
+@param aReason. If KErrNone, assistance data are being reported, otherwise, a failure to collect
+				the assistance data types in aDataReportMask is what is being reported in this call.
+@param aStateMachine. The service type of the state machine reporting the assistance data types.
+					Used to identify the machine. @see MLbsNetworkProtocolObserver.
+@param aSessionId. The unique ID of the session being conducted by the state machine that is reporting
+					assistance data. Used when sendig reference location back to LBS.
+*/
+void CSuplAssistanceDataManager::AssistanceDataReport(const RLbsAssistanceDataBuilderSet& aAssistanceData,
+						  const TLbsAsistanceDataGroup& aDataReportMask, TInt aReason,
+						  const MLbsNetworkProtocolObserver::TLbsNetProtocolService& aStateMachine,
+						  const TLbsNetSessionId& aSessionId)
+	{
+	SUPLLOG(ELogP1, "CSuplAssistanceDataManager::AssistanceDataReport() Begin\n");
+
+	TLbsAsistanceDataGroup missingDataTypes = KAssistDataEmpty;
+
+	if (aReason != KErrNone)
+		{
+		// Errored assistance data should be reported to LBS.
+		TLbsAsistanceDataGroup reportDataMask = KAssistDataEmpty;
+
+		if (MLbsNetworkProtocolObserver::EServiceSelfLocation == aStateMachine)
+			{
+			// Report error on only those assistance data types that are not being
+			// collected by any other state machines and have not been
+			// reported recently
+			reportDataMask = aDataReportMask & ~iMtLrRequestedDataMask & ~iReportedDataMask;
+			iMoLrRequestedDataMask = KAssistDataEmpty;
+			}
+		else if (MLbsNetworkProtocolObserver::EServiceMobileTerminated == aStateMachine)
+			{
+			// Report error on only those assistance data types that are not being
+			// collected by any other state machines and have not been
+			// reported recently
+			reportDataMask = aDataReportMask & ~iMoLrRequestedDataMask & ~iReportedDataMask;
+			iMtLrRequestedDataMask = KAssistDataEmpty;
+			}
+		else
+			{
+			// This should not happen
+			ASSERT(EFalse);
+			}
+
+		if (reportDataMask != KAssistDataEmpty)
+			{
+			iGateway.AssistanceDataInd(reportDataMask, aAssistanceData, KErrArgument);
+			}
+		}
+	else
+		{
+		// Extract Reference Location from the reported assistance data if present and 
+		// send it to LBS as a Location Update.
+		//
+		if (EAssistanceDataReferenceLocation == (aDataReportMask & EAssistanceDataReferenceLocation))
+			{
+			RReferenceLocationBuilder* refLocBuilderPtr;
+			RLbsAssistanceDataBuilderSet& data = const_cast<RLbsAssistanceDataBuilderSet&>(aAssistanceData);
+			if (KErrNone == data.GetDataBuilder(refLocBuilderPtr))
+				{
+ 				if (refLocBuilderPtr->IsDataAvailable())
+					{
+					// Create a Ref Loc Reader with data from the Builder
+		            RReferenceLocationReader refLocReader;
+					TInt err = KErrNone;
+					TRAP(err,refLocReader.OpenL());
+					if (KErrNone == err)
+						{
+						refLocReader.DataBuffer() = refLocBuilderPtr->DataBuffer();
+
+						// Obtain position info from the Ref Loc Reader and set it in a TPositionInfo
+						if(refLocReader.FieldExists(TReferenceLocation::EEllipsoidPointAltitudeEllipsoide))
+							{
+							REllipsoidPointAltitudeEllipsoideReader ellipsoidReader;
+							refLocReader.GetFieldReader(TReferenceLocation::EEllipsoidPointAltitudeEllipsoide, ellipsoidReader);
+							TPositionInfo positionInfo;
+							TPosition position;
+							TUint tempUint;
+							TInt  tempInt;
+							TReal64 latitudeDegrees;
+							TReal64 longitudeDegrees;
+							TReal32 altitudeMeters;
+							TReal aux = 0;
+							TReal32 uncertainty;
+
+							position.SetCurrentTime();
+							// Get latitude and convert to degrees
+							ellipsoidReader.GetField(TEllipsoidPointAltitudeEllipsoide::ELatitudeSign, tempInt);
+							ellipsoidReader.GetField(TEllipsoidPointAltitudeEllipsoide::ELatitude, tempUint);
+							latitudeDegrees = (tempUint * 90.0) / 8388608.0; //*90/2^23 ; ETSI TS 123.032
+	                        latitudeDegrees *= (tempInt == TEllipsoidPointAltitudeEllipsoide::ESouth)? -1: 1;
+
+							// Get longitude and convert to degreees
+							ellipsoidReader.GetField(TEllipsoidPointAltitudeEllipsoide::ELongitude, tempInt);
+							longitudeDegrees = (tempInt * 45.0) / 2097152.0; //*360/2^24; ETSI TS 123.032
+
+							// Get altitude (meters) and apply sign
+							ellipsoidReader.GetField(TEllipsoidPointAltitudeEllipsoide::EAltitudeDirection, tempInt);
+							ellipsoidReader.GetField(TEllipsoidPointAltitudeEllipsoide::EAltitude, tempUint);
+							altitudeMeters = tempUint; // ETSI TS 123.032
+							altitudeMeters *= (tempInt == TEllipsoidPointAltitudeEllipsoide::EDepth)? -1: 1;
+								
+							position.SetCoordinate(latitudeDegrees, longitudeDegrees, altitudeMeters);
+
+							// Get both horizontal uncertainties, convert to meters and set Horizontal Accuracy to the largest
+							ellipsoidReader.GetField(TEllipsoidPointAltitudeEllipsoide::EUncertaintySemiMajor, tempUint);
+							Math::Pow(aux, 1.1, tempUint);
+						    uncertainty = 10*(aux - 1); // ETSI TS 123.032 : C(((1+x)^k) -1);  x = 0.1; C= 10
+							ellipsoidReader.GetField(TEllipsoidPointAltitudeEllipsoide::EUncertaintySemiMinor, tempUint);
+							Math::Pow(aux, 1.1, tempUint);
+							uncertainty = uncertainty > (10*(aux - 1))? uncertainty : (10*(aux - 1));
+							
+							position.SetHorizontalAccuracy(uncertainty);
+
+							// Get vertical uncertainty, convert to meters and set Vertical Accuracy
+							ellipsoidReader.GetField(TEllipsoidPointAltitudeEllipsoide::EUncertaintyAltitude, tempUint);
+							Math::Pow(aux,1.025, tempUint);
+						    uncertainty = 45*(aux - 1); //ETSI TS 123.032; C(((1+x)^k) -1); C=45; x=0.025
+							position.SetVerticalAccuracy(uncertainty);
+
+							positionInfo.SetPosition(position);
+
+							const TPositionModuleId id = {KSuplv1UidValue};
+							positionInfo.SetModuleId(id);
+							positionInfo.SetUpdateType(EPositionUpdateGeneral);
+							positionInfo.SetPositionMode(TPositionModuleInfo::ETechnologyNetwork);
+							positionInfo.SetPositionModeReason(EPositionModeReasonNone);
+							
+							refLocReader.Close();
+							// Send the position to LBS
+							iGateway.NetworkLocationInd(aSessionId, positionInfo);
+							}
+						}
+					}
+				}
+
+			}
+
+		// Check if all of the assistance data types expected from the machine sending this
+		// assistance data report are being reported. Send to LBS an error for the missing
+		// assistance data types if they are not being collected from another machine.
+		if (MLbsNetworkProtocolObserver::EServiceSelfLocation == aStateMachine)
+			{
+			if (aDataReportMask != iMoLrRequestedDataMask)
+				{
+				// Some data types are missing from the report. Pick those not being
+				// taken care of by the MTLR state machine.
+				missingDataTypes = iMoLrRequestedDataMask & ~aDataReportMask & ~iMtLrRequestedDataMask;
+				}
+				
+			// No longer expecting assistance data from this machine
+			iMoLrRequestedDataMask = KAssistDataEmpty;			
+			}
+		else if (MLbsNetworkProtocolObserver::EServiceMobileTerminated == aStateMachine)
+			{		
+			if (aDataReportMask != iMtLrRequestedDataMask)
+				{
+				// Some data types are missing from the report. Pick those not being
+				// taken care of by the MOLR state machine.
+				missingDataTypes = iMtLrRequestedDataMask & ~aDataReportMask & ~iMoLrRequestedDataMask;
+				}
+				
+			// No longer expecting assistance data from this machine
+			iMtLrRequestedDataMask = KAssistDataEmpty;
+			}
+
+		if (KAssistDataEmpty != missingDataTypes)
+			{
+			RLbsAssistanceDataBuilderSet dummyAssistanceData; //ignored by LBS when error is not KErrNone
+			iGateway.AssistanceDataInd(missingDataTypes, dummyAssistanceData, KErrNotFound);
+			}
+
+
+		// Send received assistance data to LBS
+		iGateway.AssistanceDataInd(aDataReportMask, aAssistanceData, KErrNone);
+
+		// Remember this report for one second to guard agains this report
+		// crossing in transit with a request from LBS which includes some
+		// of the assitance data types being reported.
+		iReportedDataMask = iReportedDataMask | aDataReportMask;
+		if (iAssistDataReportTimer->IsActive())
+			{
+			iAssistDataReportTimer->Cancel();
+			}
+		iAssistDataReportTimer->EventAfter(TTimeIntervalSeconds(KAssistDataReportTimerDurationInSec), KAssistDataReportTimer);
+		}
+	SUPLLOG(ELogP1, "CSuplAssistanceDataManager::AssistanceDataReport() End\n");
+	}
+
+/** Set a machine as able to handle assistance data requests
+
+This method is called by the Protocol Manager when it detects that a SUPL state machin
+has sent a Location Request to LBS (which signals the point when it must/can received
+an assistance data request)
+*/
+void CSuplAssistanceDataManager::MachineReadyForAssistanceDataRequest(const MLbsNetworkProtocolObserver::TLbsNetProtocolService& aStateMachine)
+	{
+	SUPLLOG(ELogP1, "CSuplAssistanceDataManager::MachineReadyForAssistanceDataRequest() Begin\n");
+	// Add this machine to the "ready" state machines mask
+	iReadyMachinesMask = iReadyMachinesMask | aStateMachine;
+	SUPLLOG(ELogP1, "CSuplAssistanceDataManager::MachineReadyForAssistanceDataRequest() End\n");
+	}
+
+
+/** Inform that a state machine is no longer active
+
+This method is called by the Protocol Manager when it detects that a SUPL state machine
+has terminated. If any assistance data were expected from this machine, an assistance data
+report with KErrNotFound is sent to LBS for those assistance data types.
+*/
+void CSuplAssistanceDataManager::MachineTerminated(const MLbsNetworkProtocolObserver::TLbsNetProtocolService& aStateMachine)
+	{
+	SUPLLOG(ELogP1, "CSuplAssistanceDataManager::MachineTerminated() Begin\n");
+	TLbsAsistanceDataGroup orphanedDataRequestMask = KAssistDataEmpty;
+
+	// Remove this machine from the "ready" state machines mask
+	iReadyMachinesMask = iReadyMachinesMask &  ~aStateMachine;
+
+	// If any assistance data was being collected from the machine (and not being collected from
+	// another machine), a failure to collect those assistance data types must be reported to LBS 
+	if ( (MLbsNetworkProtocolObserver::EServiceSelfLocation == aStateMachine)
+		&& (KAssistDataEmpty != iMoLrRequestedDataMask))
+		{
+		orphanedDataRequestMask = iMoLrRequestedDataMask & ~iMtLrRequestedDataMask;
+		}
+	else if ( (MLbsNetworkProtocolObserver::EServiceMobileTerminated == aStateMachine)
+			&& (KAssistDataEmpty != iMtLrRequestedDataMask))
+		{
+		orphanedDataRequestMask = iMtLrRequestedDataMask & ~iMoLrRequestedDataMask;
+		}
+
+	// Add the pending assistance data to the orphaned mask and clear the pending mask
+	orphanedDataRequestMask = orphanedDataRequestMask | iPendingDataMask;
+	iPendingDataMask = KAssistDataEmpty;
+	
+	if (KAssistDataEmpty != orphanedDataRequestMask)
+		{
+		RLbsAssistanceDataBuilderSet dummyAssistanceData; //ignored by LBS when error is not KErrNone
+		iGateway.AssistanceDataInd(orphanedDataRequestMask, dummyAssistanceData, KErrNotFound);
+		}
+	SUPLLOG(ELogP1, "CSuplAssistanceDataManager::MachineTerminated() End\n");
+	}
+
+/** Timer expired callback.
+This is used for clearing the reportedassistance
+data mask one second after sending the assistance
+data to LBS.
+@param aTimerId The timer event identifier.
+*/
+void CSuplAssistanceDataManager::OnTimerEventL(TInt aTimerId)
+	{
+	SUPLLOG(ELogP1, "CSuplAssistanceDataManager::OnTimerEventL() Begin\n");
+	// Perform relevant action for the expired timer
+	switch (aTimerId)
+		{
+		// Additional assistance data timer
+		case KAssistDataReportTimer:
+			iReportedDataMask = KAssistDataEmpty;
+			break;
+
+		// Ignore unknown timer events
+		default:
+			break;
+		};
+	SUPLLOG(ELogP1, "CSuplAssistanceDataManager::OnTimerEventL() End\n");
+	}
+
+/** Timer callback error handler.
+This is called if the timer expiry callback leaves.
+
+@param aTimerId The timer event identifier.
+@param aError Error value.
+*/
+TInt CSuplAssistanceDataManager::OnTimerError(TInt /*aTimerId*/, TInt aError)
+	{
+	SUPLLOG(ELogP1, "CSuplAssistanceDataManager::OnTimerError() Begin\n");
+	SUPLLOG(ELogP1, "CSuplAssistanceDataManager::OnTimerError() End\n");
+	return aError;
+	}