--- /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;
+
+ }
+