locationrequestmgmt/locationserver/src/EPos_CPosLastKnownPosAreaHandler.cpp
changeset 0 9cfd9a3ee49c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/locationrequestmgmt/locationserver/src/EPos_CPosLastKnownPosAreaHandler.cpp	Tue Feb 02 01:50:39 2010 +0200
@@ -0,0 +1,303 @@
+/*
+* Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  	This class inherits the common functionalities for requests to the 
+*				Location Monitor from EPos_CPosLocMonitorReqHandlerBase.h and also
+*				implements the functions specific to Last Known Position Area request.
+*
+*/
+
+
+
+
+#include "EPos_CPosLastKnownPosAreaHandler.h"
+#include  "EPos_CPosCallbackTimer.h"
+
+// ============================ CONSTANTS ===========================================================
+#ifdef _DEBUG
+_LIT(KTraceFileName, "EPos_CPosLastKnownPosAreaHandler.cpp");
+#endif
+
+// ============================== MEMBER FUNCTIONS ===================================================
+CPosLastKnownPosAreaHandler* CPosLastKnownPosAreaHandler::NewL()
+	{
+	CPosLastKnownPosAreaHandler* self = new( ELeave ) CPosLastKnownPosAreaHandler();
+	CleanupStack::PushL( self );
+	self->ConstructL();
+	CleanupStack::Pop( self );
+	return self;
+	}
+
+CPosLastKnownPosAreaHandler::CPosLastKnownPosAreaHandler()
+	{
+	CActiveScheduler::Add(this);
+	}
+
+void CPosLastKnownPosAreaHandler::ConstructL()
+	{
+    TCallBack timeoutCallBack(HandleTimeOut, this);
+    iTimeoutTimer = CPosCallbackTimer::NewL(timeoutCallBack);
+	}
+
+CPosLastKnownPosAreaHandler::~CPosLastKnownPosAreaHandler()
+	{
+	
+	if (iStatus==KRequestPending)
+		{
+		// Cancel the request sent to the location monitor
+		Cancel();
+		}
+
+	if ( iLocMonAreaPositioner.SubSessionHandle() )
+		{
+		iLocMonAreaPositioner.Close();
+		}
+	
+	delete iTimeoutTimer;
+	
+	// The requests on the queue are completed by the base class destructor
+	}
+
+/** 
+ * GetLastKnownPosAreaL 
+ * 		>>  Initiate a new request with the location monitor if the request queue is empty. 
+ * 			Otherwise, check if the session and subsession id of any request on the queue matches that of the 
+ *			new request [ie. a duplicate request from the client]. If it matches panic the client. 
+ * 			If not add the new request to the queue. 
+ *
+ * @param  aLocMonSession    - The handle to the session with the location monitor passed on from
+ * 							   CPosLocMonitorReqHandlerHub.
+ * @param  aMessage  		 - The new request from the client 
+ */
+void CPosLastKnownPosAreaHandler::GetLastKnownPosAreaL(RLbsLocMonitorSession& aLocMonSession, const RMessage2& aMessage)
+	{
+	DEBUG_TRACE("CPosLastKnownPosAreaHandler::GetLastKnownPosAreaL", __LINE__)
+
+	if ( !(aLocMonSession.Handle()))
+		{
+		// Session with the location monitor is not found
+		RequestComplete(aMessage, KErrCouldNotConnect);
+		return;
+		}
+
+	if (!(iLocMonAreaPositioner.SubSessionHandle()))
+		{
+		iLocMonAreaPositioner.OpenL(aLocMonSession);
+		}
+	
+	// Copy the buffers from the address space of the client
+	HBufC8* lkposclientbuf = Global::CopyClientBuffer8LC(aMessage, KParamLKPAreaReqPos);
+	HBufC8* lkposareaclientbuf = Global::CopyClientBuffer8LC(aMessage, KParamLKPAreaReqArea);
+
+	TPositionInfoBase& posInfoBase = reinterpret_cast<TPositionInfoBase&>
+	(const_cast<TUint8&>(*lkposclientbuf->Ptr()));
+	TPositionAreaInfoBase& posAreaInfoBase = reinterpret_cast<TPositionAreaInfoBase&>
+	(const_cast<TUint8&>(*lkposareaclientbuf->Ptr()));
+
+	Global::ValidatePositionClassBufferL(posInfoBase, lkposclientbuf->Des());
+	Global::ValidatePositionClassTypeL(posInfoBase, EPositionInfoClass, KErrArgument);
+	Global::ValidatePositionClassBufferL(posAreaInfoBase, lkposareaclientbuf->Des());
+
+	switch (posAreaInfoBase.PositionClassType())
+		{
+		case EPositionAreaInfoClass:
+			Global::ValidatePositionClassTypeL(posAreaInfoBase, EPositionAreaInfoClass, KErrArgument);
+			break;
+		case (EPositionAreaExtendedInfoClass+EPositionAreaInfoClass): //TODO Check LbsAreaInfo.cpp [constructor]
+			Global::ValidatePositionClassTypeL(posAreaInfoBase, (EPositionAreaExtendedInfoClass+EPositionAreaInfoClass), KErrArgument);
+			break;
+		default:
+			User::Leave(KErrArgument); 								//TODO - Check if this is correct ?
+			break;
+		}
+
+	CleanupStack::PopAndDestroy(lkposareaclientbuf);
+	CleanupStack::PopAndDestroy(lkposclientbuf);
+
+	// Check the identity of the subsession and add the request to the queue
+	CheckAndAddReqToQueueL(EReqOnSubSession, aMessage);
+	
+	if ((iLocMonitorReqQ.Count()>0) && !IsActive())
+		{
+		// Always ask for extended information from the location monitor
+		// as initiating a new request for later clients that require extended information
+		// is inefficient
+		iParameters.iPositionAreaType = (EPositionAreaExtendedInfoClass | EPositionAreaInfoClass);
+		
+		// Initiate a new last known position request with the location monitor
+		iLocMonAreaPositioner.GetLastKnownPositionArea(iPositionInfo, iPositionAreaInfo, iParameters, iStatus);
+		SetActive();
+		
+	    // Start timer if necessary
+	    if (KLastKnownPosAreaTimeOut.Int64()>0)
+	        {
+	        DEBUG_TRACE("CPosLastKnownPosHandler::GetLastKnownPosAreaL() Start Timeout Timer", __LINE__)
+	        iTimeoutTimer->StartTimer(KLastKnownPosAreaTimeOut);
+	        }
+		}
+
+	}
+
+/** 
+ * CancelGetLastKnownPosAreaL 
+ * 		>> Cancel the outstanding request with the location monitor if there is only one request on the queue. 
+ *		>> Otherwise just complete the cancel request with KErrNone, remove the original request from the queue
+ * 		   and complete it with KErrCancel.
+ * @param  aMessage  		 - The cancel request from the client 
+ */
+void CPosLastKnownPosAreaHandler::CancelGetLastKnownPosAreaL(const RMessage2& aMessage)
+	{
+	DEBUG_TRACE("CPosLastKnownPosAreaHandler::CancelGetLastKnownPosAreaL", __LINE__)
+
+	// The subsession with the location monitor is not found
+	if ( !(iLocMonAreaPositioner.SubSessionHandle()) )
+		{
+		RequestComplete(aMessage, KErrNotFound);
+		return;
+		}
+	
+	// Call CancelRequest inherited from the baseclass
+	CancelRequest(EReqOnSubSession, aMessage);
+
+	}
+
+/** 
+ * NotifyOnEmptyLastKnownPosStoreReq 
+ * 		>> Cancel the outstanding get last known position area requests with KErrCancel
+ * 		   as an empty last known position store request has been issued.
+ */
+void  CPosLastKnownPosAreaHandler::NotifyOnEmptyLastKnownPosStoreReq()
+	{
+	// Complete all the requests on the queue with KErrCancel
+	QRequestsComplete(KErrCancel);
+	
+	if (iStatus==KRequestPending)
+		{
+		Cancel();
+		}
+	}
+
+/** 
+ * RunL 
+ * 		>> Complete all the requests on the queue.
+ */
+void CPosLastKnownPosAreaHandler::RunL()
+	{
+	
+	// Cancel the timeout timer
+	iTimeoutTimer->Cancel();
+	
+	// Serving all the outstanding requests based on the current update
+	// from the Location Monitor
+	while (iLocMonitorReqQ.Count()>0)
+		{
+		TInt numReqs = iLocMonitorReqQ.Count()-1;
+		// Retrieve the next request to be serviced [first element in the queue - FIFO]
+		if (iStatus.Int()==KErrNone)
+			{
+			// Copy the buffers from the address space of the client
+			const TUint8* startAddress = reinterpret_cast <const TUint8*>(&iPositionInfo)+sizeof(TPositionClassTypeBase);
+			TInt chunkSize = sizeof(TPositionInfo)-sizeof(TPositionClassTypeBase);
+			TPtr8 copyFromDesc(const_cast<TUint8*>(startAddress),chunkSize,chunkSize);
+			
+			TInt err = Global::Write(iLocMonitorReqQ[numReqs],KParamLKPAreaReqPos,copyFromDesc,sizeof(TPositionClassTypeBase));
+			//TInt err = iLocMonitorReqQ[numReqs].Write(KParamLKPAreaReqPos,copyFromDesc,sizeof(TPositionClassTypeBase));
+
+			// To identify the type of the request - last known position area / last known position area + extended info.
+			HBufC8* lkposareaclientbuf = Global::CopyClientBuffer8LC(iLocMonitorReqQ[numReqs], KParamLKPAreaReqArea);
+			TPositionAreaInfoBase& posAreaInfoBase = reinterpret_cast<TPositionAreaInfoBase&>(const_cast<TUint8&>(*lkposareaclientbuf->Ptr()));
+			startAddress = reinterpret_cast <const TUint8*>(&iPositionAreaInfo)+sizeof(TPositionClassTypeBase);
+			
+			switch (posAreaInfoBase.PositionClassType())
+				{
+				case EPositionAreaInfoClass:
+					chunkSize = sizeof(TPositionAreaInfo)-sizeof(TPositionClassTypeBase);
+					copyFromDesc.Set(const_cast<TUint8*>(startAddress),chunkSize,chunkSize);
+					//err = iLocMonitorReqQ[numReqs].Write(KParamLKPAreaReqArea,copyFromDesc,sizeof(TPositionClassTypeBase));
+					err = Global::Write(iLocMonitorReqQ[numReqs],KParamLKPAreaReqArea,copyFromDesc,sizeof(TPositionClassTypeBase));
+					RequestComplete(iLocMonitorReqQ[numReqs], err);
+					break;
+				case (EPositionAreaExtendedInfoClass+EPositionAreaInfoClass): //TODO Check LbsAreaInfo.cpp [constructor]
+					chunkSize = sizeof(TPositionAreaExtendedInfo)-sizeof(TPositionClassTypeBase);
+					copyFromDesc.Set(const_cast<TUint8*>(startAddress),chunkSize,chunkSize);
+					err = Global::Write(iLocMonitorReqQ[numReqs],KParamLKPAreaReqArea,copyFromDesc,sizeof(TPositionClassTypeBase));
+					//err = iLocMonitorReqQ[numReqs].Write(KParamLKPAreaReqArea,copyFromDesc,sizeof(TPositionClassTypeBase));		
+					RequestComplete(iLocMonitorReqQ[numReqs], err);
+					break;
+				default:
+					RequestComplete(iLocMonitorReqQ[numReqs], KErrArgument);								//TODO - Check if this is correct ?
+					break;
+				}
+			// Destroy the buffer used to hold the client's data
+			CleanupStack::PopAndDestroy(lkposareaclientbuf);
+			
+			}
+		else
+			{
+			// Complete the client request with aReason
+			RequestComplete(iLocMonitorReqQ[numReqs],iStatus.Int());
+			}
+
+		// Remove the request that has just been serviced [last element]
+		iLocMonitorReqQ.Remove(numReqs);
+		}
+	
+	// Close the subsession with the location monitor when we receive the last known position area from it
+	iLocMonAreaPositioner.Close();
+
+	}
+
+TInt CPosLastKnownPosAreaHandler::RunError(TInt aError)
+	{
+	return aError;
+	}
+
+
+/** 
+ * DoCancel 
+ * 		>> Cancel the active object.
+ */
+void CPosLastKnownPosAreaHandler::DoCancel()
+	{
+	// Cancel the timer as the request with the location monitor is going to be cancelled
+	iTimeoutTimer->Cancel();
+	
+	DEBUG_TRACE("calling RLbsAreaPositioner::CancelGetLastKnownPosition()", __LINE__)
+	__ASSERT_DEBUG((iLocMonAreaPositioner.SubSessionHandle())!=NULL, DebugPanic(EPosServerPanicPositionerNotInitialized));
+	
+	TInt err = iLocMonAreaPositioner.CancelGetLastKnownPositionArea();
+	// As the cancel request is immediately completed, this return value 
+	// is not useful.
+	}
+
+/** 
+ * HandleTimeOut 
+ * 		>> Complete all the requests on the queue with KErrTimedOut.
+ * @param  aRequestHandler - self pointer used to call the appropriate timeout handling method
+ */
+TInt CPosLastKnownPosAreaHandler::HandleTimeOut(TAny* aRequestHandler)
+    {
+
+    DEBUG_TRACE("CPosLastKnownPosAreaHandler::HandleTimeOut()", __LINE__)    
+    
+    CPosLastKnownPosAreaHandler* self = reinterpret_cast<CPosLastKnownPosAreaHandler*>(aRequestHandler);
+    // The request with the location monitor has timed out. So complete all the outstanding 
+    // requests with KErrTimedOut
+    self->QRequestsComplete(KErrTimedOut);
+    // Cancel the pending request with the location monitor
+    self->Cancel();
+
+    return KErrNone;
+    
+    }
+