diff -r 000000000000 -r 4e1aa6a622a0 sysstatemgmt/systemstatereferenceplugins/clayer/src/startupadaptationadapter.cpp --- /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 + +#include + +#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(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(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(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(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(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(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(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 + }