sysstatemgmt/systemstatereferenceplugins/clayer/src/startupadaptationadapter.cpp
changeset 0 4e1aa6a622a0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysstatemgmt/systemstatereferenceplugins/clayer/src/startupadaptationadapter.cpp	Tue Feb 02 00:53:00 2010 +0200
@@ -0,0 +1,474 @@
+// Copyright (c) 2007-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:
+//
+
+#include "startupadaptationadapter.h"
+
+#include <ssm/startupadaptation.h>
+
+#include <ecom/ecom.h>
+
+#include "saastateadaptation.h"
+#include "saasimadaptation.h"
+#include "saartcadaptation.h"
+#include "saaemergencycallrfadaptation.h"
+#include "saamiscadaptation.h"
+
+#include "clayerpanic.h"
+
+#include "ssmdebug.h"
+
+
+
+/**
+ * Returns the singleton @c CStartupAdaptationAdapter.
+ * 
+ * @return The singleton CStartupAdaptationAdapter
+ * @leave KErrPermissionDenied - the caller does not have permission to perform this operation
+ * 
+ * @internalComponent
+ */
+CStartupAdaptationAdapter* CStartupAdaptationAdapter::GetL()
+	{
+	DEBUGVERBOSE1A("Checking TLS for CStartupAdaptationAdapter");
+	CStartupAdaptationAdapter* self =
+		static_cast<CStartupAdaptationAdapter*>(Dll::Tls());
+	if(self == 0)
+		{
+		// TLS uninitialised, need to create
+		DEBUGPRINT1A("Constructing CStartupAdaptationAdapter singleton");
+		self = CStartupAdaptationAdapter::NewLC();
+		DEBUGPRINT1A("Storing CStartupAdaptationAdapter singleton in TLS");
+		TInt err = Dll::SetTls(self);
+		SSMLOGLEAVEIFERROR(err);
+		CleanupStack::Pop(self);
+		}
+	DEBUGVERBOSE1A("Returning CStartupAdaptationAdapter singleton");
+	return self;
+	}
+
+/**
+ * Destroys the singleton @c CStartupAdaptationAdapter.
+ * 
+ * @internalComponent
+ */
+void CStartupAdaptationAdapter::Destroy()
+	{
+	CStartupAdaptationAdapter* self =
+			static_cast<CStartupAdaptationAdapter*>(Dll::Tls());
+	if(self != 0)
+		{
+		DEBUGPRINT1A("Destroying CStartupAdaptationAdapter singleton");
+		delete self;
+		TInt err = Dll::SetTls(0);
+		if(err != KErrNone)
+			{
+			DEBUGPRINT2A("Error clearing TLS: %d", err);
+			return;
+			}
+		}
+	}
+
+/**
+ * Creates a new CStartupAdaptationAdapter.
+ * 
+ * The CStartupAdaptationAdapter class should be accessed via a singleton pattern.
+ * GetL() is provided to manage a thread level singleton for this class.
+ * 
+ * @internalComponent
+ */
+CStartupAdaptationAdapter* CStartupAdaptationAdapter::NewLC()
+	{
+	CStartupAdaptationAdapter* self = new (ELeave) CStartupAdaptationAdapter();
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	return self;
+	}
+
+/**
+ * First phase constructor
+ * 
+ * @internalComponent
+ */
+
+CStartupAdaptationAdapter::CStartupAdaptationAdapter()
+: CActive(EPriorityStandard)
+	{
+	
+	}
+
+/**
+ * Second phase constructor
+ * 
+ * @internalComponent
+ */
+void CStartupAdaptationAdapter::ConstructL()
+	{ 
+	iStateAdaptation = CSaaStateAdaptation::NewL(this);
+	iSimAdaptation = CSaaSimAdaptation::NewL(this);
+	iRtcAdaptation = CSaaRtcAdaptation::NewL(this);
+	iEmergencyCallRfAdaptation = CSaaEmergencyCallRfAdaptation::NewL(this);
+	iMiscAdaptation = CSaaMiscAdaptation::NewL(this);
+	CActiveScheduler::Add(this);
+	}
+
+/**
+ * Destructor for CStartupAdaptationAdapters
+ * 
+ * @internalComponent
+ */
+CStartupAdaptationAdapter::~CStartupAdaptationAdapter()
+	{
+	Cancel();
+	
+	// destroy the adaptation, which is an ECOM plugin
+	delete iStartupAdaptation;
+	
+	// Signal to ECOM that it should cleanup
+	REComSession::FinalClose();
+	
+	// Cleanup other members
+	delete iStateAdaptation;
+	delete iSimAdaptation;
+	delete iRtcAdaptation;
+	delete iEmergencyCallRfAdaptation;
+	delete iMiscAdaptation;
+	}
+
+/**
+ * Returns an object conforming to the MStateAdaptation interface.
+ * 
+ * The objects returned from this method may be reference counted.
+ * This may mean that consecutive calls to this method will return the same
+ * address.
+ * 
+ * @internalComponent
+ */
+EXPORT_C MStateAdaptation* CStartupAdaptationAdapter::NewStateAdaptationL()
+	{
+	CStartupAdaptationAdapter* adapter = GetL();
+	return static_cast<MStateAdaptation*>(adapter->iStateAdaptation);
+	}
+
+/**
+ * Returns an object conforming to the MSimAdaptation interface.
+ * 
+ * The objects returned from this method may be reference counted.
+ * This may mean that consecutive calls to this method will return the same
+ * address.
+ * 
+ * @internalComponent
+ */
+EXPORT_C MSimAdaptation* CStartupAdaptationAdapter::NewSimAdaptationL()
+	{
+	CStartupAdaptationAdapter* adapter = GetL();
+	return static_cast<MSimAdaptation*>(adapter->iSimAdaptation);
+	}
+
+/**
+ * Returns an object conforming to the MRtcAdaptation interface.
+ * 
+ * The objects returned from this method may be reference counted.
+ * This may mean that consecutive calls to this method will return the same
+ * address.
+ * 
+ * @internalComponent
+ */
+EXPORT_C MRtcAdaptation* CStartupAdaptationAdapter::NewRtcAdaptationL()
+	{
+	CStartupAdaptationAdapter* adapter = GetL();
+	return static_cast<MRtcAdaptation*>(adapter->iRtcAdaptation);
+	}
+
+/**
+ * Returns an object conforming to the MEmergencyCallRfAdaptation interface.
+ * 
+ * The objects returned from this method may be reference counted.
+ * This may mean that consecutive calls to this method will return the same
+ * address.
+ * 
+ * @internalComponent
+ */
+EXPORT_C MEmergencyCallRfAdaptation* CStartupAdaptationAdapter::NewEmergencyCallRfAdaptationL()
+	{
+	CStartupAdaptationAdapter* adapter = GetL();
+	return static_cast<MEmergencyCallRfAdaptation*>(adapter->iEmergencyCallRfAdaptation);
+	}
+
+/**
+ * Returns an object conforming to the MMiscAdaptation interface.
+ * 
+ * The objects returned from this method may be reference counted.
+ * This may mean that consecutive calls to this method will return the same
+ * address.
+ * 
+ * @internalComponent
+ */
+EXPORT_C MMiscAdaptation* CStartupAdaptationAdapter::NewMiscAdaptationL()
+	{
+	CStartupAdaptationAdapter* adapter = GetL();
+	return static_cast<MMiscAdaptation*>(adapter->iMiscAdaptation);
+	}
+
+/**
+ * Returns a pointer to the adaptation class, creating and loading it if necessary 
+ * 
+ * @internalComponent 
+ */
+CStartupAdaptation* CStartupAdaptationAdapter::GetAdaptationL()
+	{
+	if(iStartupAdaptation == NULL)
+		{
+		iStartupAdaptation = CStartupAdaptation::NewL(*this);
+		}
+	return iStartupAdaptation;
+	}
+
+/**
+ * Dispatches or queues for dispatch the provided adaptation base class 
+ * 
+ * @internalComponent 
+ */
+void CStartupAdaptationAdapter::QueueDispatchL(CAdaptationBase* aAdaptation)
+	{
+	
+	if(iDispatchedAdaptation == NULL)
+		{
+		DEBUGPRINT2A("SAA - Dispatch request immediately commandId: %d", aAdaptation->CommandId());
+		// Nothing is waiting for a response, so dispatch immediately
+		iDispatchedAdaptation = aAdaptation;
+		GetAdaptationL()->CommandL(iDispatchedAdaptation->CommandId(), *iDispatchedAdaptation->ParameterPckg());
+		iDispatchedAdaptation->SetDispatched(ETrue);
+		}
+	else
+		{
+		DEBUGPRINT3A("SAA - Queueing request for commandId: %d queue size:", aAdaptation->CommandId(), iDispatchQueueSize);
+		// Check queue size
+		if (iDispatchQueueSize == KMaxAdaptationClasses)
+			{
+			CLAYER_PANIC(ECLayerMaximumQueueSize);
+			}
+		// Add to queue
+		iDispatchQueue[iDispatchQueueSize] = aAdaptation;
+		// Update queue size
+		++iDispatchQueueSize;
+		}
+	}
+
+/**
+ * Handles responses from the adaptation.
+ * 
+ * Defined in MStartupAdaptationObserver.
+ * 
+ * @internalComponent
+ */
+void CStartupAdaptationAdapter::ResponseL(const StartupAdaptation::TCommand aCommandId, TDesC8& aData)
+	{
+	DEBUGPRINT2A("SAA - Response received from adaptation with commandId: %d", aCommandId);
+	// Check we were expecting a response
+	if(iDispatchedAdaptation == NULL)
+		{
+		CLAYER_PANIC(ECLayerUnexpectedResponse);
+		}
+	// Indicate that it is complete
+	iDispatchedAdaptation->RequestComplete(aCommandId, aData);
+	
+	// clear the dispatched adaptation so it can be reused
+	iDispatchedAdaptation = NULL;
+	
+	// self complete to dispatch next queued request if any
+	SelfComplete(KErrNone);
+	}
+
+/**
+ * Handles events from the adaptation.
+ * 
+ * Defined in MStartupAdaptationObserver.
+ * 
+ * @internalComponent
+ */
+void CStartupAdaptationAdapter::EventL(const StartupAdaptation::TEvent aEventId, TDesC8& aData)
+	{
+	using namespace StartupAdaptation;
+	// Switch on event type
+	switch(aEventId)
+		{
+		case EFatalError:
+			{
+			TFatalErrorTypePckg fatalErrorPckg;
+			fatalErrorPckg.Copy(aData);
+			if(fatalErrorPckg() == ESimRemoved)
+				{
+				// SIM event
+				iSimAdaptation->ProcessEventL(ESsmSimRemoved);
+				}
+			else
+				{
+				// State event
+				iStateAdaptation->ProcessEventL(ESsmFatalCoopSysError);
+				}
+			break;
+			}
+		case EDOSOriginatedReset:
+			{
+			iStateAdaptation->ProcessEventL(ESsmRestartDevice);
+			break;
+			}
+		case EDOSOriginatedShutdown:
+			{
+			iStateAdaptation->ProcessEventL(ESsmShutdownDevice);
+			break;
+			}
+		case ESimEvent:
+			{
+			TSimEventTypePckg simEventPckg;
+			simEventPckg.Copy(aData);
+			switch(simEventPckg())
+			{
+				case ESimUsable:
+					iSimAdaptation->ProcessEventL(ESsmSimUsable);
+					break;
+				case ESimReadable:
+					iSimAdaptation->ProcessEventL(ESsmSimReadable);
+					break;
+				case ESimNotReady:
+					iSimAdaptation->ProcessEventL(ESsmSimNotReady);
+					break;
+				default:
+					DEBUGPRINT2A("SAA - Received unknown SIM event with SIM event id: %d - ignoring", simEventPckg());
+					break;
+			}
+			break;
+			}
+		default:
+			DEBUGPRINT2A("SAA - Received unknown event with event id: %d - ignoring", aEventId);
+			break;
+		}
+	}
+
+/**
+ * Cancels an already dispatched adaptation request
+ * 
+ * This should not be called if the response for this request has already been received.
+ * 
+ * @internalComponent
+ */
+void CStartupAdaptationAdapter::CancelDispatchedL(CAdaptationBase* aAdaptation)
+	{
+	DEBUGPRINT3A("SAA - Cancelling dispatched request with command id: %d dispatched command id: %d", aAdaptation->CommandId(), iDispatchedAdaptation->CommandId());
+	if(aAdaptation != iDispatchedAdaptation)
+		{
+		CLAYER_PANIC(ECLayerInCorrectDispatchedCancel);
+		}
+	// Request the startup adaptation cancel the command
+	GetAdaptationL()->CancelCommandL(iDispatchedAdaptation->CommandId());
+	iDispatchedAdaptation = NULL;
+	// Dispatch any items in the queue if present
+	DispatchQueued();
+	}
+
+/**
+ * Removes a queued adaptation request from the queue
+ * 
+ * This should not be called if the response for this request has already been dispatched.
+ * 
+ * @internalComponent
+ */
+void CStartupAdaptationAdapter::RemoveFromDispatchQueue(CAdaptationBase* aAdaptation)
+	{
+	DEBUGPRINT2A("SAA - Cancelling queued request with command id: %d ", aAdaptation->CommandId());
+	// Search for offset
+	TInt index;
+	for(index = 0; index < iDispatchQueueSize && iDispatchQueue[index] != aAdaptation; ++index)
+		{
+		// Do nothing
+		}
+	// remove from queue
+	if (index != iDispatchQueueSize)
+		{
+		// Found it at index so remove from array and shift ones above down
+		for(TInt j = index + 1; j < iDispatchQueueSize; ++j)
+			{
+			iDispatchQueue[j-1] = iDispatchQueue[j];
+			}
+		// Decrease queue size
+		--iDispatchQueueSize;
+		}
+	else
+		{
+		DEBUGPRINT2A("SAA - Couldn't find request to de-queue with command id: %d ", aAdaptation->CommandId());
+		}
+	}
+
+
+/**
+ * Dispatches the next adaptation request in the queue and removes it from the queue
+ * 
+ * @internalComponent
+ */
+void CStartupAdaptationAdapter::DispatchQueued()
+	{
+	// Dispatch the head of the queue if any items there
+	// retry as long as there are items in the queue
+	while(iDispatchQueueSize > 0 && iDispatchedAdaptation == NULL)
+		{
+		// Update the current pointer
+		iDispatchedAdaptation = iDispatchQueue[0];
+		// shift the queue down
+		for(TInt i = 1; i < iDispatchQueueSize; ++i)
+			{
+			iDispatchQueue[i - 1] = iDispatchQueue[i]; 
+			}
+		--iDispatchQueueSize;
+		// dispatch the new request
+		DEBUGPRINT2A("SAA - Dispatch queue non empty, dispatchign command with commandId: %d", iDispatchedAdaptation->CommandId());
+		TRAPD(err, GetAdaptationL()->CommandL(iDispatchedAdaptation->CommandId(), *iDispatchedAdaptation->ParameterPckg()));
+		if(err != KErrNone)
+			{
+			// failed to dispatch
+			// return error to client
+			iDispatchedAdaptation->CompleteRequestStatus(err);
+			// clear iDispatchedAdaptation so that the while loop tries again
+			iDispatchedAdaptation = NULL;
+			}
+		}
+	}
+
+void CStartupAdaptationAdapter::SelfComplete(TInt aError)
+	{
+	TRequestStatus* trs = &iStatus;
+	iStatus = KRequestPending;
+	User::RequestComplete(trs, aError);
+	SetActive();
+	}
+
+// From CActive
+
+void CStartupAdaptationAdapter::RunL()
+	{
+	// Dispatch any queued request
+	DispatchQueued();
+	}
+
+TInt CStartupAdaptationAdapter::RunError(TInt aError)
+	{
+	DEBUGPRINT2(_L("CStartupAdaptationAdapter::RunError() called with error %d"), aError);
+	// Return the error to the active scheduler to panic as this should never occur
+	return aError;
+	}
+
+void CStartupAdaptationAdapter::DoCancel()
+	{
+	// Nothing to cancel as iStatus should never be KRequestPending
+	}