diff -r 000000000000 -r bde4ae8d615e os/kernelhwsrv/userlibandfileserver/domainmgr/src/domainsrv.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/os/kernelhwsrv/userlibandfileserver/domainmgr/src/domainsrv.cpp Fri Jun 15 03:10:57 2012 +0200 @@ -0,0 +1,1618 @@ +// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "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: +// domain\src\domainsrv.cpp +// +// + +#include <e32debug.h> +#include <e32base.h> +#include <e32base_private.h> +#include <e32property.h> +#include <f32file.h> + +#include <domainpolicy.h> +#include "domainsrv.h" + +#define __DS_PANIC(aError) User::Panic(_L("domainSrv.cpp"), (-(aError)) | (__LINE__ << 16)) +#define __DS_ASSERT(aCond) ((aCond) || (User::Panic(_L("domainSrv.cpp; assertion failed"), __LINE__), 1)) + +//#define __DS_DEBUG + +#ifdef __DS_DEBUG +#define __DS_TRACE(s) RDebug::Print s +#else +#define __DS_TRACE(s) +#endif + +static _LIT_SECURITY_POLICY_PASS(KAllowAllPolicy); +static _LIT_SECURITY_POLICY_C1(KPowerMgmtPolicy,ECapabilityPowerMgmt); + +// forward refs +class CSvrDomain; +class CDmHierarchy; +class CPowerUpHandler; +class CDmHierarchyPower; +class CDmSvrManager; +class CDmDomainServer; +class CDmDomainSession; +class CDmManagerServer; +class CDmManagerSession; + + + +// CSvrDomain +class CSvrDomain : public CTimer + { +public: + static CSvrDomain* New(CDmHierarchy& aHierarchy, const TDmDomainSpec&); + + // from CTimer + void RunL(); + + void Attach(CDmDomainSession*); + void Detach(CDmDomainSession*); + void AddChild(CSvrDomain*); + CSvrDomain* Lookup(TDmDomainId); + TBool CheckPropValue(TInt aPropValue); + void RequestDomainTransition(); + void CompleteMemberTransition(TInt aError); + void CancelTransition(); + void SetObserver(TBool aSet); + TDmDomainState State(); + +private: + CSvrDomain(CDmHierarchy& aHierarchy, const TDmDomainSpec*); + void Construct(const TDmDomainSpec* spec); + + void RequestMembersTransition(); + void RequestChildrenTransition(); + void MembersTransitionDone(); + void ChildrenTransitionDone(); + void CompleteDomainTransition(); + +private: + CDmHierarchy& iHierarchy; + CSvrDomain* iParent; + CSvrDomain* iPeer; + CSvrDomain* iChild; + RProperty iProperty; + CDmDomainSession* iSessions; + TUint16 iChildrenCount; + TUint16 iTransCount; + TTimeIntervalMicroSeconds32 iTransTimeBudget; + +public: + const TSecurityPolicy iJoinPolicy; + TBool iIsObserved; + TDmDomainId iId; + }; + + +// CDmHierarchy +class CDmHierarchy : public CBase + { +public: + static CDmHierarchy* New(TDmHierarchyId aHierarchyId, TDmHierarchyPolicy& aPolicy); + + CSvrDomain* LookupDomain(TDmDomainId aDomainId); + TInt RequestDomainTransition(TDmDomainId, TDmDomainState aTargetState, TDmTraverseDirection aTraverseDirection, const RMessage2* aMessage); + void RequestTransition(const RMessage2* aMessage); + TInt StartObserver( TDmDomainId aDomainId,TDmNotifyType aNotifyType); + void SetNotifyMessage(const RMessage2* aMessage); + void CompleteNotification(TInt aError); + TBool OutstandingNotification(); + void StopObserver(); + virtual TInt RequestSystemTransition(TDmDomainState aTargetState, TDmTraverseDirection aTraverseDirection, const RMessage2* aMessage); + virtual void CompleteTransition(TInt aError); + virtual void NotifyCompletion(TInt aReason); + +protected: + CDmHierarchy(TDmHierarchyId aHierarchyId, TDmHierarchyPolicy& aPolicy); + void SetState(TDmDomainState aTargetState, TDmTraverseDirection aTraverseDirection = ETraverseDefault); + +private: + RMessagePtr2 iTransMessagePtr; + RMessagePtr2 iObsvrMessagePtr; + CSvrDomain* iObservedDomain; + TBool iOutstandingNotification; +public: + TDmHierarchyId iHierarchyId; + CSvrDomain* iRootDomain; + CSvrDomain* iTransDomain; + TInt iTransPropValue; + TDmDomainState iTransState; + TDmTraverseDirection iTraverseDirection; + TUint8 iTransId; + CDmManagerSession* iControllerSession; // only one controller per hierarchy + TDmHierarchyPolicy iPolicy; + RArray<TTransitionFailure> iTransitionFailures; + + // observer stuff + TBool iObserverStarted; + TDmNotifyType iNotifyType; + RArray<TTransInfo> iTransitions; + CDmManagerSession* iObserverSession; // only one observer per hierarchy + TInt iObservedChildren; + }; + + +// CPowerUpHandler +// Active object used to receive power-up notifications +// from the Kernel-level power manager +class CPowerUpHandler : public CActive + { +public: + static CPowerUpHandler* New(CDmHierarchyPower& aHierarchyPower); + + // from CActive + void RunL(); + void DoCancel(); + + void RequestWakeupEventNotification(); + void Cancel(); + +private: + CPowerUpHandler(CDmHierarchyPower& aHierarchyPower); + void Construct(); + +private: + CDmHierarchyPower& iHierarchyPower; + }; + + +// CDmHierarchyPower +// CDmHierarchy-derived class +// Interfaces to the Kernel-level power manager +class CDmHierarchyPower : public CDmHierarchy + { +public: + static CDmHierarchyPower* New(TDmHierarchyId aHierarchyId, TDmHierarchyPolicy& aPolicy); + + // from CDmHierarchy + virtual TInt RequestSystemTransition(TDmDomainState, TDmTraverseDirection aTraverseDirection, const RMessage2* aMessage); + virtual void CompleteTransition(TInt aError); + virtual void NotifyCompletion(TInt aReason); + + void PowerUp(); // called from CPowerUpHandler + +private: + CDmHierarchyPower(TDmHierarchyId aHierarchyId, TDmHierarchyPolicy& aPolicy); + void Construct(); + +private: + enum + { + EPoweringDown = 0x01, + }; + TUint8 iTransStatus; + CPowerUpHandler* iPowerUpHandler; + }; + + +// CDmSvrManager +class CDmSvrManager : public CBase + { +public: + static CDmSvrManager* New(); + + TInt BuildDomainTree(TDmHierarchyId aHierarchyId, CDmHierarchy*& aHierarchy); + CDmHierarchy* LookupHierarchy(TDmHierarchyId aHierarchyId); + TInt LookupDomain(TDmHierarchyId aHierarchyId, TDmDomainId aDomainId, CSvrDomain*& aDomain); + +private: + CDmSvrManager(); + void Construct(); + +private: + RPointerArray<CDmHierarchy> iDomainHierarchies; + }; + +// CDmDomainServer +class CDmDomainServer : public CServer2 + { +public: + // from CServer2 + CSession2* NewSessionL(const TVersion& aVer) const; + CSession2* NewSessionL(const TVersion& aVer, const RMessage2& aMessage) const; + + CDmDomainServer(CDmSvrManager* aManager) : CServer2(CActive::EPriorityStandard), iManager(aManager) + {} + +public: + CDmSvrManager* iManager; + }; + +// CDmDomainSession +class CDmDomainSession : public CSession2 + { +public: + // from CBase + ~CDmDomainSession(); + + // from CSession2 + void ServiceL(const RMessage2& aMessage); + +private: + CSvrDomain* iDomain; + +public: + CDmDomainSession* iNext; + TUint8 iPending; + TBool iNotificationEnabled; + }; + +class CDmManagerServer : public CServer2 + { +public: + // from CServer2 + CSession2* NewSessionL(const TVersion& aVer) const; + CSession2* NewSessionL(const TVersion& aVer, const RMessage2&) const; + + CDmManagerServer(CDmSvrManager* aManager) : CServer2(CActive::EPriorityStandard), iManager(aManager) + {} + CDmSvrManager* iManager; + }; + +class CDmManagerSession : public CSession2 + { +public: + // from CBase + ~CDmManagerSession(); + + // from CSession2 + void ServiceL(const RMessage2& aMessage); + + CDmManagerSession(); +private: + CDmHierarchy* iHierarchy; // not owned + }; + + + + +//********************************************************* +// TTransitionFailure +//********************************************************* +/** +@internalTechnology + +Constructor for transition failure info. + +@param aDomainID Id of the domain of interest +@param aError error code of transition +*/ +TTransitionFailure::TTransitionFailure(TDmDomainId aDomainId, TInt aError) : + iDomainId(aDomainId), iError(aError) + { + } + +//********************************************************* +// TTransInfo +//********************************************************* + +/** +@internalTechnology + +Constructor for transition failure info. + +@param aDomainID Id of the domain of interest +@param aState State of the domain after transition +@param aError error code of transition +*/ +TTransInfo::TTransInfo(TDmDomainId aDomainId, TDmDomainState aState, TInt aError) : + iDomainId(aDomainId), iState(aState), iError(aError) + { + } + +//********************************************************* +// CSvrDomain +//********************************************************* + + +CSvrDomain::CSvrDomain(CDmHierarchy& aHierarchy, const TDmDomainSpec* spec) + : CTimer(CActive::EPriorityStandard), + iHierarchy(aHierarchy), + iTransTimeBudget(spec->iTimeBudgetUs), + iJoinPolicy(spec->iJoinPolicy), + iId(spec->iId) + {} + +CSvrDomain* CSvrDomain::New(CDmHierarchy& aHierarchy, const TDmDomainSpec& aSpec) + { + + CSvrDomain* self = new CSvrDomain(aHierarchy, &aSpec); + + if (!self) + __DS_PANIC(KErrNoMemory); + self->Construct(&aSpec); + return self; + } + +void CSvrDomain::Construct(const TDmDomainSpec* spec) + { + TInt r = iProperty.Define( + KUidDmPropertyCategory, + DmStatePropertyKey(iHierarchy.iHierarchyId, iId), + RProperty::EInt, + KAllowAllPolicy,KPowerMgmtPolicy); + + if (r != KErrNone) + __DS_PANIC(r); + + r = iProperty.Attach(KUidDmPropertyCategory, DmStatePropertyKey( + iHierarchy.iHierarchyId, + iId)); + + if (r != KErrNone) + __DS_PANIC(r); + + r = iProperty.Set(DmStatePropertyValue(0, spec->iInitState)); + if (r != KErrNone) + __DS_PANIC(r); + + TRAP(r, CTimer::ConstructL()); + if (r != KErrNone) + __DS_PANIC(r); + CActiveScheduler::Add(this); + } + +void CSvrDomain::Attach(CDmDomainSession* aSession) + { + aSession->iNext = iSessions; + iSessions = aSession; + } + +void CSvrDomain::Detach(CDmDomainSession* aSession) + { + CDmDomainSession** prevp = &iSessions; + while (*prevp != aSession) + { + prevp = &((*prevp)->iNext); + __DS_ASSERT(*prevp); + } + *(prevp) = aSession->iNext; + } + +void CSvrDomain::AddChild(CSvrDomain* aChild) + { + ++iChildrenCount; + aChild->iParent = this; + if(iIsObserved) + aChild->iIsObserved=ETrue; + // Insert the child in the list of its peers + aChild->iPeer = iChild; + iChild = aChild; + } + +CSvrDomain* CSvrDomain::Lookup(TDmDomainId aDomainId) + { + if (iId == aDomainId) + return this; + + CSvrDomain* child = iChild; + while (child) + { + CSvrDomain* domain = child->Lookup(aDomainId); + if (domain) + return domain; + child = child->iPeer; + } + return NULL; + } + +TBool CSvrDomain::CheckPropValue(TInt aPropValue) + { return iHierarchy.iTransPropValue == aPropValue; } + +void CSvrDomain::RequestMembersTransition() + { + __DS_TRACE((_L("CSvrDomain::RequestMembersTransition() hierarchy=%d, domain=0x%x"), iHierarchy.iHierarchyId, iId)); + __DS_ASSERT(iTransCount == 0); + + for(CDmDomainSession* s = iSessions; s; s = s->iNext) + if (s->iNotificationEnabled) + { + ++iTransCount; + s->iPending = ETrue; + // notifications will be disabled until the client makes another + // call to RDmDomain::RequestTransitionNotification() + s->iNotificationEnabled = EFalse; + } + + if(iIsObserved) + { + if((iHierarchy.iNotifyType&EDmNotifyTransRequest)==EDmNotifyTransRequest) + { + TTransInfo transInfo(iId,State(),KDmErrOutstanding); + iHierarchy.iTransitions.Append(transInfo); + if(iHierarchy.OutstandingNotification()) + iHierarchy.CompleteNotification(KErrNone); + } + } + if (iTransCount > 0) + CTimer::After(iTransTimeBudget); + iProperty.Set(iHierarchy.iTransPropValue); + if (iTransCount == 0) + MembersTransitionDone(); + } + + +void CSvrDomain::RequestChildrenTransition() + { + __DS_TRACE((_L("CSvrDomain::RequestChildrenTransition() hierarchy=%d, domain=0x%x"), iHierarchy.iHierarchyId, iId)); + __DS_ASSERT(iTransCount == 0); + iTransCount = iChildrenCount; + if (iTransCount) + { + CSvrDomain* child = iChild; + __DS_ASSERT(child); + do { + child->RequestDomainTransition(); + child = child->iPeer; + } + while(child); + } + else + ChildrenTransitionDone(); + } + +void CSvrDomain::RequestDomainTransition() + { + __DS_TRACE((_L("CSvrDomain::RequestDomainTransition() hierarchy=%d, domain=0x%x state=0x%x prop=0x%x"), + iHierarchy.iHierarchyId, iId, iHierarchy.iTransState, iHierarchy.iTransPropValue)); + __DS_ASSERT(iTransCount == 0); + if (iHierarchy.iTraverseDirection == ETraverseChildrenFirst) + RequestChildrenTransition(); + else + RequestMembersTransition(); + } + +void CSvrDomain::MembersTransitionDone() + { + __DS_TRACE((_L("CSvrDomain::MembersTransitionDone() hierarchy=%d, domain=0x%x"), iHierarchy.iHierarchyId, iId)); + __DS_ASSERT(iTransCount == 0); + if (iHierarchy.iTraverseDirection == ETraverseChildrenFirst) + CompleteDomainTransition(); + else + RequestChildrenTransition(); + } + +void CSvrDomain::ChildrenTransitionDone() + { + __DS_TRACE((_L("CSvrDomain::ChildrenTransitionDone() hierarchy=%d, domain=0x%x"), iHierarchy.iHierarchyId, iId)); + __DS_ASSERT(iTransCount == 0); + if (iHierarchy.iTraverseDirection == ETraverseChildrenFirst) + RequestMembersTransition(); + else + CompleteDomainTransition(); + } + +void CSvrDomain::CompleteMemberTransition(TInt aError) + { + __DS_TRACE((_L("CSvrDomain::CompleteMemberTransition() hierarchy=%d, domain=0x%x, aError = %d"), iHierarchy.iHierarchyId, iId, aError)); + __DS_ASSERT(iTransCount); + + if (aError) + { + // Add a transition failure to the array + TTransitionFailure failure(iId, aError); + iHierarchy.iTransitionFailures.Append(failure); + + if(iIsObserved) + { + if((iHierarchy.iNotifyType&EDmNotifyFail)==EDmNotifyFail) + { + TTransInfo transInfo(iId,State(),aError); + iHierarchy.iTransitions.Append(transInfo); + if(iHierarchy.OutstandingNotification()) + iHierarchy.CompleteNotification(KErrNone); + } + } + // examine the failure policy to work out what to do + if (iHierarchy.iPolicy.iFailurePolicy == ETransitionFailureStop) + { + iHierarchy.CompleteTransition(aError); + return; + } + } + else if(iIsObserved) + { + if((iHierarchy.iNotifyType&EDmNotifyPass) == EDmNotifyPass) + { + TTransInfo transInfo(iId,State(),aError); + iHierarchy.iTransitions.Append(transInfo); + if(iHierarchy.OutstandingNotification()) + iHierarchy.CompleteNotification(KErrNone); + } + } + + if (--iTransCount == 0) + { + CTimer::Cancel(); + MembersTransitionDone(); + } + } + +void CSvrDomain::RunL() + { // Timer expired + __DS_TRACE((_L("CSvrDomain::RunL() Members transition timeout hierarchy=%d, domain=0x%x"), iHierarchy.iHierarchyId, iId)); + + // Add a transition failure to the array + TTransitionFailure failure(iId,KErrTimedOut); + iHierarchy.iTransitionFailures.Append(failure); + + + // examine the failure policy to work out what to do + if (iHierarchy.iPolicy.iFailurePolicy == ETransitionFailureStop) + { + iHierarchy.CompleteTransition(KErrTimedOut); + return; + } + + if (iTransCount) + { // Complete transition of all members + CDmDomainSession* session = iSessions; + while (session) + { + session->iPending = EFalse; + session = session->iNext; + } + iTransCount = 0; + MembersTransitionDone(); + } + } + + +void CSvrDomain::CompleteDomainTransition() + { + __DS_TRACE((_L("CSvrDomain::CompleteDomainTransition() hierarchy=%d, domain=0x%x"), iHierarchy.iHierarchyId, iId)); + __DS_ASSERT(iTransCount == 0); + if (iHierarchy.iTransDomain == this) + { + const TInt err = (iHierarchy.iTransitionFailures.Count() > 0)? + iHierarchy.iTransitionFailures[0].iError : KErrNone; + iHierarchy.CompleteTransition(err); + } + else + { + __DS_ASSERT(iParent); + __DS_ASSERT(iParent->iTransCount); + if (--iParent->iTransCount == 0) + iParent->ChildrenTransitionDone(); + } + } + +void CSvrDomain::CancelTransition() + { + __DS_TRACE((_L("CSvrDomain::CancelTransition() hierarchy=%d, domain=0x%x"), iHierarchy.iHierarchyId, iId)); + CTimer::Cancel(); + CSvrDomain* child = iChild; + while (child) + { + child->CancelTransition(); + child = child->iPeer; + } + CDmDomainSession* session = iSessions; + while (session) + { + session->iPending = EFalse; + session = session->iNext; + } + iTransCount = 0; + } + +void CSvrDomain::SetObserver(TBool aSet) + { + iIsObserved=aSet; + if(aSet) + { + iHierarchy.iObservedChildren++; + } + else + { + // this should be zero at the end + iHierarchy.iObservedChildren--; + } + if(iChildrenCount!=0) + { + CSvrDomain* domain=iChild; + do { + domain->SetObserver(aSet); + domain = domain->iPeer; + } + while(domain); + } + } + +TDmDomainState CSvrDomain::State() + { + TInt value; + iProperty.Get(value); + return DmStateFromPropertyValue(value); + } + +//********************************************************* +// CDmHierarchy +//********************************************************* + +CDmHierarchy* CDmHierarchy::New(TDmHierarchyId aHierarchyId, TDmHierarchyPolicy& aPolicy) + { + CDmHierarchy* self; + + if (aHierarchyId == KDmHierarchyIdPower) + self = CDmHierarchyPower::New(aHierarchyId, aPolicy); + else + self = new CDmHierarchy(aHierarchyId, aPolicy); + + if (!self) + __DS_PANIC(KErrNoMemory); + + return self; + } + +CDmHierarchy::CDmHierarchy(TDmHierarchyId aHierarchyId, TDmHierarchyPolicy& aPolicy) : + iOutstandingNotification(EFalse), + iHierarchyId(aHierarchyId), + iPolicy(aPolicy) + { + iTransitionFailures.Reset(); + } + +CSvrDomain* CDmHierarchy::LookupDomain(TDmDomainId aDomainId) + { + return iRootDomain ? iRootDomain->Lookup(aDomainId) : NULL; + } + +void CDmHierarchy::RequestTransition(const RMessage2* aMessage) + { + // reset the array of transition failures + iTransitionFailures.Reset(); + + if (aMessage) + iTransMessagePtr = *aMessage; + iTransPropValue = DmStatePropertyValue(++iTransId, iTransState); + + iTransDomain->RequestDomainTransition(); + } + + +TInt CDmHierarchy::StartObserver(TDmDomainId aDomainId,TDmNotifyType aNotifyType) + { + iObservedDomain = LookupDomain(aDomainId); + + if(iObservedDomain==NULL) + return KDmErrBadDomainId; + + + iObservedDomain->SetObserver(ETrue); + iNotifyType=aNotifyType; + iObserverStarted=ETrue; + return KErrNone; + } + +void CDmHierarchy::SetNotifyMessage(const RMessage2* aMessage) + { + if (aMessage) + { + iObsvrMessagePtr = *aMessage; + iOutstandingNotification=ETrue; + } + } + +TBool CDmHierarchy::OutstandingNotification() + { + return iOutstandingNotification; + } + +void CDmHierarchy::CompleteNotification(TInt aError) + { + if(iOutstandingNotification) + { + iObsvrMessagePtr.Complete(aError); + iOutstandingNotification=EFalse; + } + } + +void CDmHierarchy::StopObserver() + { + + iObservedDomain->SetObserver(EFalse); + iTransitions.Reset(); + iObserverStarted=EFalse; + } +void CDmHierarchy::NotifyCompletion(TInt aReason) + { + iTransDomain = NULL; + iTransPropValue = 0; + iTransMessagePtr.Complete(aReason); + } + +TInt CDmHierarchy::RequestSystemTransition(TDmDomainState aTargetState, TDmTraverseDirection aTraverseDirection, const RMessage2* aMessage) + { + iTransDomain = iRootDomain; + SetState(aTargetState, aTraverseDirection); + RequestTransition(aMessage); + return KErrNone; + } + + +TInt CDmHierarchy::RequestDomainTransition( + TDmDomainId aDomainId, + TDmDomainState aTargetState, + TDmTraverseDirection aTraverseDirection, + const RMessage2* aMessage) + { + __DS_TRACE((_L("CDmHierarchy::RequestTransition() hierarchy=%d domain=0x%x state=0x%x"), iHierarchyId, aDomainId, aTargetState)); + iTransDomain = LookupDomain(aDomainId); + if (!iTransDomain) + return KDmErrBadDomainId; + SetState(aTargetState, aTraverseDirection); + RequestTransition(aMessage); + return KErrNone; + } + +void CDmHierarchy::CompleteTransition(TInt aError) + { + if (!iTransDomain) + return; + + __DS_TRACE((_L("CDmHierarchy::CompleteTransition() hierarchy=%d, domain=0x%x, aError=%d"), iHierarchyId, iTransDomain->iId, aError)); + + if (iTransDomain) + { + iTransDomain->CancelTransition(); + NotifyCompletion(aError); + } + } + +void CDmHierarchy::SetState(TDmDomainState aTargetState, TDmTraverseDirection aTraverseDirection) + { + __DS_ASSERT(iTransDomain); + + + if (aTraverseDirection == ETraverseDefault) + { + TDmDomainState oldState = iTransDomain->State(); + + if (aTargetState >= oldState) + iTraverseDirection = iPolicy.iPositiveTransitions; + else + iTraverseDirection = iPolicy.iNegativeTransitions; + } + else + iTraverseDirection = aTraverseDirection; + + __DS_ASSERT(iTraverseDirection < ETraverseMax); + + iTransState = aTargetState; + } + +//********************************************************* +// CPowerUpHandler +//********************************************************* + +CPowerUpHandler* CPowerUpHandler::New(CDmHierarchyPower& aHierarchyPower) + { + CPowerUpHandler* self = new CPowerUpHandler(aHierarchyPower); + if (!self) + __DS_PANIC(KErrNoMemory); + self->Construct(); + return self; + } + +CPowerUpHandler::CPowerUpHandler(CDmHierarchyPower& aHierarchyPower) : + CActive(CActive::EPriorityStandard), + iHierarchyPower(aHierarchyPower) + { + } + +void CPowerUpHandler::Construct() + { + CActiveScheduler::Add(this); + } + + +void CPowerUpHandler::RequestWakeupEventNotification() + { + Power::RequestWakeupEventNotification(iStatus); + SetActive(); + } + + +void CPowerUpHandler::Cancel() + { + CActive::Cancel(); + } + +void CPowerUpHandler::RunL() + { + // power wakeup event + iHierarchyPower.PowerUp(); + } + + +void CPowerUpHandler::DoCancel() + { + Power::DisableWakeupEvents(); + Power::CancelWakeupEventNotification(); + } + + + +//********************************************************* +// CDmHierarchyPower +//********************************************************* +CDmHierarchyPower* CDmHierarchyPower::New(TDmHierarchyId aHierarchyId, TDmHierarchyPolicy& aPolicy) + { + CDmHierarchyPower* self; + + self = new CDmHierarchyPower(aHierarchyId, aPolicy); + + if (!self) + __DS_PANIC(KErrNoMemory); + + self->Construct(); + + return self; + } + +CDmHierarchyPower::CDmHierarchyPower(TDmHierarchyId aHierarchyId, TDmHierarchyPolicy& aPolicy) : + CDmHierarchy(aHierarchyId, aPolicy) + { + } + + +void CDmHierarchyPower::Construct() + { + iPowerUpHandler = CPowerUpHandler::New(*this); + if (!iPowerUpHandler) + __DS_PANIC(KErrNoMemory); + } + +void CDmHierarchyPower::NotifyCompletion(TInt aReason) + { + iTransStatus = 0; + CDmHierarchy::NotifyCompletion(aReason); + } + +TInt CDmHierarchyPower::RequestSystemTransition(TDmDomainState aTargetState, TDmTraverseDirection aTraverseDirection, const RMessage2* aMessage) + { + __DS_TRACE((_L("CDmSvrManager::RequestSystemTransition() state = 0x%x"), aTargetState)); + + TInt r = Power::EnableWakeupEvents((TPowerState) aTargetState); + if (r != KErrNone) + return r; + + iPowerUpHandler->RequestWakeupEventNotification(); + + iTransStatus |= EPoweringDown; + + return CDmHierarchy::RequestSystemTransition(aTargetState, aTraverseDirection, aMessage); + } + +void CDmHierarchyPower::CompleteTransition(TInt aError) + { + if (!iTransDomain) + return; + + __DS_TRACE((_L("CDmHierarchyPower::CompleteTransition() domain=0x%x"), iTransDomain->iId)); + + if (iTransDomain && aError == KErrCancel) + iPowerUpHandler->Cancel(); + + if (iTransStatus & EPoweringDown) + { + RFs fs; + TInt r=fs.Connect(); + __DS_ASSERT(r==KErrNone); + __DS_TRACE((_L("CDmSvrManager::CompleteTransition() Calling FinaliseDrives"))); + r=fs.FinaliseDrives(); + __DS_TRACE((_L("CDmSvrManager::CompleteTransition() Finalise returned %d"),r)); + fs.Close(); + + Power::PowerDown(); + __DS_ASSERT(iTransState != (TDmDomainState) EPwOff); + __DS_ASSERT(iPowerUpHandler->iStatus.Int() == KErrNone); + } + else + { + CDmHierarchy::CompleteTransition(aError); + } + } + + +void CDmHierarchyPower::PowerUp() + { + __DS_TRACE((_L("CDmHierarchyPower::RunL() Wakeup Event"))); + __DS_ASSERT(iTransDomain); + + Power::DisableWakeupEvents(); + + iTransStatus &= ~EPoweringDown; + iTransDomain->CancelTransition(); + SetState((TDmDomainState) EPwActive); + RequestTransition(NULL); + } + + +//********************************************************* +// CDmSvrManager +//********************************************************* + +CDmSvrManager* CDmSvrManager::New() + { + CDmSvrManager* self = new CDmSvrManager(); + if (!self) + __DS_PANIC(KErrNoMemory); + self->Construct(); + return self; + } + +CDmSvrManager::CDmSvrManager() + { + } + +void CDmSvrManager::Construct() + { + // load the power hierarchy- Other hieratchies need to be loaded + // explicitly using RDmDomainManager::AddDomainHierarchy() + CDmHierarchy* hierarchy; + TInt r = BuildDomainTree(KDmHierarchyIdPower, hierarchy); + if (r != KErrNone) + __DS_PANIC(r); + + + RProperty prop; + r = prop.Define(KUidDmPropertyCategory, KDmPropertyKeyInit, RProperty::EInt, + KAllowAllPolicy,KPowerMgmtPolicy); + if (r != KErrNone) + __DS_PANIC(r); + + prop.Set(KUidDmPropertyCategory, KDmPropertyKeyInit, ETrue); + } + +TInt CDmSvrManager::BuildDomainTree(TDmHierarchyId aHierarchyId, CDmHierarchy*& aHierarchy) + { + + aHierarchy = NULL; + + // assume we have already checked that the hierarchy doesn't already exist + + // Get the name of the policy Dll + // This will be "domainPolicy.dll" for the power hierarchy + // and "domainPolicy<n>.dll" for other hierarchies where <n> is the hierarchy ID. + // + // If the hierarchy ID is less than KMaxCriticalPolicyDll, load only from ROM + + TFullName dllName; + + // is this policy "critical" i.e non-replaceable ? + _LIT(KSysBin,"z:\\sys\\bin\\"); + // const TInt KMaxCriticalPolicyDll = 1000; + // if (aHierarchyId < KMaxCriticalPolicyDll) // <-- cannot be false while aHierarchyId is a TUint8 (typedef'd to TDmHierarchyId) + dllName.Append(KSysBin); + + dllName.Append(_L("domainPolicy")); + if (aHierarchyId != KDmHierarchyIdPower) + dllName.AppendNum(aHierarchyId); + + dllName.Append(_L(".dll")); + RLibrary lib; + TInt r = lib.Load(dllName); + if (r == KErrNotFound) + return KErrBadHierarchyId; + else if (r != KErrNone) + return r; + + TLibraryFunction ordinal1 = lib.Lookup(EDmPolicyGetDomainSpecs); + DmPolicyGetDomainSpecs getDomainSpecs = reinterpret_cast<DmPolicyGetDomainSpecs>(ordinal1); + if (getDomainSpecs == NULL) + r = KErrBadHierarchyId; + + TLibraryFunction ordinal2 = lib.Lookup(EDmPolicyRelease); + DmPolicyRelease release = reinterpret_cast<DmPolicyRelease>(ordinal2); + if (release == NULL) + r = KErrBadHierarchyId; + + TLibraryFunction ordinal3 = lib.Lookup(EDmPolicyGetPolicy); + DmPolicyGetPolicy getPolicy = reinterpret_cast<DmPolicyGetPolicy>(ordinal3); + if (getPolicy == NULL) + r = KErrBadHierarchyId; + + + // get the domain spec for this hierarchy + const TDmDomainSpec* spec = NULL; + + if (r == KErrNone) + { + spec = (*getDomainSpecs)(); + if (spec == NULL) + r = KErrBadHierarchyId; + } + // get the policy + TDmHierarchyPolicy hierarchyPolicy; + if (r == KErrNone) + { + r = (*getPolicy)(hierarchyPolicy); + if (r == KErrNone) + { + __DS_ASSERT(hierarchyPolicy.iPositiveTransitions < ETraverseMax); + __DS_ASSERT(hierarchyPolicy.iNegativeTransitions < ETraverseMax); + } + } + + if (r != KErrNone) + { + lib.Close(); + return r; + } + + CDmHierarchy* hierarchy = CDmHierarchy::New(aHierarchyId, hierarchyPolicy); + if (hierarchy == NULL) + __DS_PANIC(KErrNoMemory); + + while (r == KErrNone && spec->iId != KDmIdNone) + { + // make sure the domain doesn't already exist in this hierarchy + CSvrDomain* domain = hierarchy->LookupDomain(spec->iId); + if (domain) + { + r = KErrBadHierarchyId; + break; + } + + domain = CSvrDomain::New(*hierarchy, *spec); + __DS_ASSERT(domain); + + if (spec->iParentId == KDmIdNone) + { + if (hierarchy->iRootDomain) + { + r = KDmErrBadDomainSpec; + break; + } + hierarchy->iRootDomain = domain; + } + else + { + CSvrDomain* parent = hierarchy->LookupDomain(spec->iParentId); + if (!parent) + { + r = KDmErrBadDomainSpec; + break; + } + parent->AddChild(domain); + } + ++spec; + } + + if (spec) + (*release)(spec); + + + if (r == KErrNone) + { + __DS_ASSERT(hierarchy->iRootDomain); + iDomainHierarchies.Append(hierarchy); + aHierarchy = hierarchy; + } + else + { + delete hierarchy; + hierarchy = NULL; + } + + lib.Close(); + + return r; + } + +CDmHierarchy* CDmSvrManager::LookupHierarchy(TDmHierarchyId aHierarchyId) + + { + // need to find the correct hierarchy first + TInt len = iDomainHierarchies.Count(); + + CDmHierarchy* hierarchy = NULL; + for (TInt n=0; n<len; n++) + { + if (iDomainHierarchies[n]->iHierarchyId == aHierarchyId) + { + hierarchy = iDomainHierarchies[n]; + break; + } + } + + return hierarchy; + } + + +TInt CDmSvrManager::LookupDomain(TDmHierarchyId aHierarchyId, TDmDomainId aDomainId, CSvrDomain*& aDomain) + { + // need to find the correct hierarchy first + CDmHierarchy* hierarchy = LookupHierarchy(aHierarchyId); + if (hierarchy == NULL) + return KErrBadHierarchyId; + + aDomain = hierarchy->LookupDomain(aDomainId); + if (aDomain == NULL) + return KDmErrBadDomainId; + + return KErrNone; + } + +CSession2* CDmManagerServer::NewSessionL(const TVersion&, const RMessage2& aMessage) const + { + + // If the client does not have ECapabilityPowerMgmt capability, then it has no + // right to make this request. Blow it up. + if (!KPowerMgmtPolicy.CheckPolicy(aMessage)) + { + + User::Leave(KErrPermissionDenied); + + } + + return new CDmManagerSession(); + } + +CSession2* CDmManagerServer::NewSessionL(const TVersion&) const + { + __DS_PANIC(KErrGeneral); + return 0; + } + +CDmManagerSession::CDmManagerSession() + {} + +CDmManagerSession::~CDmManagerSession() + { + if (iHierarchy && iHierarchy->iControllerSession == this) + iHierarchy->iControllerSession = NULL; + if (iHierarchy && iHierarchy->iObserverSession == this) + iHierarchy->iObserverSession = NULL; + } + +class MyMessage : public RMessage2 + { +public: + TInt* ArgRef(TInt i) + { return &iArgs[i]; } + }; + +void CDmManagerSession::ServiceL(const RMessage2& aMessage) + { + TInt r; + CDmSvrManager* manager = ((CDmManagerServer*) Server()) -> iManager; + + // Check client has ECapabilityPowerMgmt capability +/* + if (!KPowerMgmtPolicy.CheckPolicy(aMessage)) + { + aMessage.Complete(KErrPermissionDenied); + return; + } +*/ + switch (aMessage.Function()) + { + case EDmHierarchyAdd: + { + r = KErrNone; + TDmHierarchyId hierarchyId = (TDmHierarchyId) aMessage.Int0(); + + CDmHierarchy* hierarchy = manager->LookupHierarchy(hierarchyId); + if (hierarchy == NULL) + r = manager->BuildDomainTree(hierarchyId, hierarchy); + aMessage.Complete(r); + } + break; + + case EDmHierarchyJoin: + { + r = KErrNone; + TDmHierarchyId hierarchyId = (TDmHierarchyId) aMessage.Int0(); + + iHierarchy = manager->LookupHierarchy(hierarchyId); + if (iHierarchy == NULL) + r = KErrBadHierarchyId; + + if (r == KErrNone) + { + // is the hierarchy already in use ? + if (iHierarchy->iControllerSession) + r = KErrInUse; + else + iHierarchy->iControllerSession = this; + } + + aMessage.Complete(r); + } + break; + + case EDmRequestSystemTransition: + if (iHierarchy==NULL) + { + aMessage.Complete(KErrBadHierarchyId); + break; + } + if (iHierarchy->iTransDomain) + { + aMessage.Complete(KDmErrBadSequence); + break; + } + + r = iHierarchy->RequestSystemTransition( + (TDmDomainState) aMessage.Int0(), + (TDmTraverseDirection) aMessage.Int1(), + &aMessage); + + if (r != KErrNone) + aMessage.Complete(r); + break; + + case EDmRequestDomainTransition: + if (iHierarchy==NULL) + { + aMessage.Complete(KErrBadHierarchyId); + break; + } + if (iHierarchy->iTransDomain) + { + aMessage.Complete(KDmErrBadSequence); + break; + } + r = iHierarchy->RequestDomainTransition( + (TDmDomainId) aMessage.Int0(), + (TDmDomainState) aMessage.Int1(), + (TDmTraverseDirection) aMessage.Int2(), + &aMessage); + + if (r != KErrNone) + aMessage.Complete(r); + break; + + case EDmGetTransitionFailureCount: + { + if (iHierarchy==NULL) + { + aMessage.Complete(KErrBadHierarchyId); + break; + } + TInt failureCount = iHierarchy->iTransitionFailures.Count(); + aMessage.Complete(failureCount); + } + break; + + case EDmGetTransitionFailures: + { + if (iHierarchy==NULL) + { + aMessage.Complete(KErrBadHierarchyId); + break; + } + TInt failureCount = iHierarchy->iTransitionFailures.Count(); + TInt clientFailureSize = aMessage.GetDesMaxLength(0); + TInt clientFailureCount = clientFailureSize / sizeof(TTransitionFailure); + __DS_ASSERT( (clientFailureSize % sizeof(TTransitionFailure)) == 0); + __DS_ASSERT(failureCount >= clientFailureCount); + + HBufC8* hBuf = HBufC8::New(clientFailureSize); + if(hBuf == NULL) + { + aMessage.Complete(KErrNoMemory); + break; + } + TPtr8 pBuf = hBuf->Des(); + pBuf.Zero(); + for (TInt i=0; i<clientFailureCount; i++) + { + TPtrC8 ptr = TPtrC8((TUint8*) &iHierarchy->iTransitionFailures[i], sizeof(TTransitionFailure)); + pBuf.Append(ptr); + } + r = aMessage.Write(0, pBuf); + delete hBuf; + + aMessage.Complete(r); + } + break; + + case EDmCancelTransition: + if (iHierarchy == NULL) + { + aMessage.Complete(KErrBadHierarchyId); + break; + } + iHierarchy->CompleteTransition(KErrCancel); + if (iHierarchy->iObserverStarted) + { + iHierarchy->CompleteNotification(KErrCancel); + iHierarchy->StopObserver(); + } + aMessage.Complete(KErrNone); + break; + case EDmObserverCancel: + if (iHierarchy == NULL) + { + aMessage.Complete(KErrBadHierarchyId); + break; + } + if(!iHierarchy->iObserverSession) + { + aMessage.Complete(KDmErrBadSequence); + break; + } + if (iHierarchy->iObserverStarted) + { + iHierarchy->CompleteNotification(KErrCancel); + iHierarchy->StopObserver(); + } + aMessage.Complete(KErrNone); + break; + + case EDmObserverJoin: + { + TDmHierarchyId hierarchyId = (TDmHierarchyId) aMessage.Int0(); + + iHierarchy = manager->LookupHierarchy(hierarchyId); + if(iHierarchy==NULL) + { + aMessage.Complete(KErrBadHierarchyId); + break; + } + if(iHierarchy->iObserverSession) + { + aMessage.Complete(KDmErrBadSequence); + break; + } + iHierarchy->iTransitions.Reset(); + iHierarchy->iObserverSession = this; + aMessage.Complete(KErrNone); + } + break; + + case EDmObserverStart: + { + if (iHierarchy==NULL) + { + aMessage.Complete(KErrBadHierarchyId); + break; + } + + if(iHierarchy->iObserverStarted || iHierarchy->iObserverSession != this) + { + aMessage.Complete(KDmErrBadSequence); + break; + } + TInt ret= iHierarchy->StartObserver((TDmDomainId)aMessage.Int0(),(TDmNotifyType)aMessage.Int1()); + aMessage.Complete(ret); + } + break; + + case EDmObserverNotify: + { + if (iHierarchy==NULL) + { + aMessage.Complete(KErrBadHierarchyId); + break; + } + if(!iHierarchy->iObserverStarted || iHierarchy->iObserverSession != this) + { + aMessage.Complete(KDmErrBadSequence); + break; + } + // Check to see if we have any events stored + // If so, then notify the client + if(iHierarchy->iTransitions.Count()>0) + { + aMessage.Complete(KErrNone); + break; + } + // No events are stored. complete this message later + iHierarchy->SetNotifyMessage(&aMessage); + } + break; + + case EDmObserverEventCount: + { + if (iHierarchy==NULL) + { + aMessage.Complete(KErrBadHierarchyId); + break; + } + if(!iHierarchy->iObserverStarted || iHierarchy->iObserverSession != this) + { + aMessage.Complete(KDmErrBadSequence); + break; + } + TInt count = iHierarchy->iTransitions.Count(); + aMessage.Complete(count); + } + break; + + case EDmObserverGetEvent: + { + if (iHierarchy==NULL) + { + aMessage.Complete(KErrBadHierarchyId); + break; + } + if(!iHierarchy->iObserverStarted || iHierarchy->iObserverSession != this) + { + aMessage.Complete(KDmErrBadSequence); + break; + } + TInt transitionCount = iHierarchy->iTransitions.Count(); + TInt clientTransitionSize = aMessage.GetDesMaxLength(0); + TInt clientTransitionCount = clientTransitionSize / sizeof(TTransInfo); + __DS_ASSERT( (clientTransitionSize % sizeof(TTransInfo)) == 0); + __DS_ASSERT(transitionCount >= clientTransitionCount); + + HBufC8* hBuf = HBufC8::New(clientTransitionSize); + if(hBuf == NULL) + { + aMessage.Complete(KErrNoMemory); + break; + } + TPtr8 pBuf = hBuf->Des(); + pBuf.Zero(); + for (TInt i=0; i<clientTransitionCount; i++) + { + TPtrC8 ptr = TPtrC8((TUint8*) &iHierarchy->iTransitions[0], sizeof(TTransInfo)); + pBuf.Append(ptr); + iHierarchy->iTransitions.Remove(0); + } + r = aMessage.Write(0, pBuf); + delete hBuf; + + aMessage.Complete(r); + } + break; + case EDmObserveredCount: + { + if (iHierarchy==NULL) + { + aMessage.Complete(KErrBadHierarchyId); + break; + } + if(!iHierarchy->iObserverStarted || iHierarchy->iObserverSession != this) + { + aMessage.Complete(KDmErrBadSequence); + break; + } + aMessage.Complete(iHierarchy->iObservedChildren); + } + break; + default: + aMessage.Complete(KDmErrBadRequest); + break; + } + } + +CSession2* CDmDomainServer::NewSessionL(const TVersion&, const RMessage2&) const + { + + return new CDmDomainSession(); + } + +CSession2* CDmDomainServer::NewSessionL(const TVersion&) const + { + __DS_PANIC(KErrGeneral); + return 0; + } + +CDmDomainSession::~CDmDomainSession() + { + if (iPending) + iDomain->CompleteMemberTransition(KErrNone); + if (iDomain) + iDomain->Detach(this); + } + +void CDmDomainSession::ServiceL(const RMessage2& aMessage) + { + TInt r = KErrNone; + CDmSvrManager* manager = ((CDmManagerServer*) Server()) -> iManager; + + switch (aMessage.Function()) + { + case EDmDomainJoin: + { + TDmHierarchyId hierarchyId = (TDmHierarchyId) aMessage.Int0(); + TDmDomainId domainId = (TDmDomainId) aMessage.Int1(); + + r = manager->LookupDomain(hierarchyId, domainId, iDomain); + + if (r != KErrNone) + break; + + // Check client has capability to join the domain + if (!iDomain->iJoinPolicy.CheckPolicy(aMessage)) + { + r = KErrPermissionDenied; + iDomain = NULL; + break; + } + + iDomain->Attach(this); + break; + } + + case EDmStateRequestTransitionNotification: + iNotificationEnabled = ETrue; + break; + + case EDmStateCancelTransitionNotification: + iNotificationEnabled = EFalse; + break; + + case EDmStateAcknowledge: + { + TInt propValue = aMessage.Int0(); + TInt error = aMessage.Int1(); + if (!iDomain) + { + r = KDmErrNotJoin; + break; + } + if (iPending && iDomain->CheckPropValue(propValue)) + { + iPending = EFalse; + iDomain->CompleteMemberTransition(error); + } + } + break; + default: + r = KDmErrBadRequest; + break; + } + aMessage.Complete(r); + } + + +TInt E32Main() + { + CTrapCleanup* cleanupStack = CTrapCleanup::New(); + if(!cleanupStack) + __DS_PANIC(KErrNoMemory); + + CActiveScheduler* sched = new CActiveScheduler(); + if (!sched) + __DS_PANIC(KErrNoMemory); + + CActiveScheduler::Install(sched); + + CDmSvrManager* mngr = CDmSvrManager::New(); + __DS_ASSERT(mngr); + + CDmManagerServer* msrv = new CDmManagerServer(mngr); + if (!msrv) + __DS_PANIC(KErrNoMemory); + + TInt r=msrv->Start(KDmManagerServerNameLit); + if (r != KErrNone) + __DS_PANIC(r); + + CDmDomainServer* dsrv = new CDmDomainServer(mngr); + if (!dsrv) + __DS_PANIC(KErrNoMemory); + + r=dsrv->Start(KDmDomainServerNameLit); + if (r != KErrNone) + __DS_PANIC(r); + + CActiveScheduler::Start(); + + __DS_PANIC(0); + + return KErrNone; + }