diff -r 2b433474f2ba -r 957c583b417b userlibandfileserver/domainmgr/src/domainsrv.cpp --- a/userlibandfileserver/domainmgr/src/domainsrv.cpp Tue Sep 28 15:28:31 2010 +0100 +++ b/userlibandfileserver/domainmgr/src/domainsrv.cpp Mon Oct 04 12:03:52 2010 +0100 @@ -1,4 +1,4 @@ -// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). +// Copyright (c) 2002-2010 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" @@ -11,8 +11,8 @@ // Contributors: // // Description: -// domain\src\domainsrv.cpp -// +// domainmgr/src/domainsrv.cpp +// // #include @@ -23,20 +23,18 @@ #include #include "domainsrv.h" +#include "domaincfg.h" #define __DS_PANIC(aError) User::Panic(_L("domainSrv.cpp"), (-(aError)) | (__LINE__ << 16)) +#define __DS_PANIC_IFERR(aError) ((aError == KErrNone) || (User::Panic(_L("domainSrv.cpp"), (-(aError)) | (__LINE__ << 16)), 1)) +#define __DS_PANIC_IFNUL(aPtr) ((aPtr != NULL) || (User::Panic(_L("domainSrv.cpp"), (-(KErrNoMemory)) | (__LINE__ << 16)), 1)) #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 +#define __DS_ASSERT_STARTUP(aCond) ((aCond) || (User::Panic(_L("Domain Server start-up error, server exiting"), __LINE__), 1)) static _LIT_SECURITY_POLICY_PASS(KAllowAllPolicy); -static _LIT_SECURITY_POLICY_C1(KPowerMgmtPolicy,ECapabilityPowerMgmt); +static _LIT_SECURITY_POLICY_C1(KPowerMgmtPolicy, ECapabilityPowerMgmt); +static _LIT_SECURITY_POLICY_C1(KWddPolicy, ECapabilityWriteDeviceData); +static _LIT_SECURITY_POLICY_C1(KProtServPolicy, ECapabilityProtServ); // forward refs class CSvrDomain; @@ -50,12 +48,22 @@ class CDmManagerSession; +#if defined(_DEBUG) || defined(__DS_DEBUG) +void GetClientNameFromMessageL(const RMessagePtr2& aMessage, TDes& aBuffer) + { + RThread clientThread; + aMessage.ClientL(clientThread); + aBuffer = clientThread.FullName(); + clientThread.Close(); + } +#endif // CSvrDomain class CSvrDomain : public CTimer { public: static CSvrDomain* New(CDmHierarchy& aHierarchy, const TDmDomainSpec&); + ~CSvrDomain(); // from CTimer void RunL(); @@ -81,6 +89,9 @@ void ChildrenTransitionDone(); void CompleteDomainTransition(); + void SetMemberDeferralBudgets(); + TBool ExpireMemberDeferrals(); + private: CDmHierarchy& iHierarchy; CSvrDomain* iParent; @@ -90,7 +101,13 @@ CDmDomainSession* iSessions; TUint16 iChildrenCount; TUint16 iTransCount; - TTimeIntervalMicroSeconds32 iTransTimeBudget; + + TOverrideableSetting + iTransTimeBudget; + + + TOverrideableSetting + iTransitionDeferralBudget; public: const TSecurityPolicy iJoinPolicy; @@ -103,6 +120,8 @@ class CDmHierarchy : public CBase { public: + ~CDmHierarchy(); + static CDmHierarchy* New(TDmHierarchyId aHierarchyId, TDmHierarchyPolicy& aPolicy); CSvrDomain* LookupDomain(TDmDomainId aDomainId); @@ -116,17 +135,32 @@ virtual TInt RequestSystemTransition(TDmDomainState aTargetState, TDmTraverseDirection aTraverseDirection, const RMessage2* aMessage); virtual void CompleteTransition(TInt aError); virtual void NotifyCompletion(TInt aReason); - + + CHierarchySettings& HierachySettings() + { + return *iSettings; + } + protected: CDmHierarchy(TDmHierarchyId aHierarchyId, TDmHierarchyPolicy& aPolicy); void SetState(TDmDomainState aTargetState, TDmTraverseDirection aTraverseDirection = ETraverseDefault); private: - RMessagePtr2 iTransMessagePtr; - RMessagePtr2 iObsvrMessagePtr; CSvrDomain* iObservedDomain; - TBool iOutstandingNotification; + + CHierarchySettings* iSettings; + + /** Direction of traversal if target state is after current state */ + TDmTraverseDirection iPositiveTransitions; + + /** Direction of traversal if target state is before current state */ + TDmTraverseDirection iNegativeTransitions; + public: + /** Policy which outlines the action upon transition failure */ + TOverrideableSetting + iFailurePolicy; + TDmHierarchyId iHierarchyId; CSvrDomain* iRootDomain; CSvrDomain* iTransDomain; @@ -135,9 +169,10 @@ TDmTraverseDirection iTraverseDirection; TUint8 iTransId; CDmManagerSession* iControllerSession; // only one controller per hierarchy - TDmHierarchyPolicy iPolicy; + + RArray iTransitionFailures; - + // observer stuff TBool iObserverStarted; TDmNotifyType iNotifyType; @@ -206,7 +241,7 @@ public: static CDmSvrManager* New(); - TInt BuildDomainTree(TDmHierarchyId aHierarchyId, CDmHierarchy*& aHierarchy); + TInt BuildDomainTree(TDmHierarchyId aHierarchyId); CDmHierarchy* LookupHierarchy(TDmHierarchyId aHierarchyId); TInt LookupDomain(TDmHierarchyId aHierarchyId, TDmDomainId aDomainId, CSvrDomain*& aDomain); @@ -214,6 +249,8 @@ CDmSvrManager(); void Construct(); + TInt LoadStateSpecs(RLibrary& aLib, CDmHierarchy* aHierarchy); + private: RPointerArray iDomainHierarchies; }; @@ -223,10 +260,11 @@ { 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) + // Note, tracing of client thread names relies upon + // EUnsharableSessions being used + CDmDomainServer(CDmSvrManager* aManager) : CServer2(CActive::EPriorityStandard, EUnsharableSessions), iManager(aManager) {} public: @@ -238,28 +276,45 @@ { public: // from CBase + CDmDomainSession(); ~CDmDomainSession(); // from CSession2 void ServiceL(const RMessage2& aMessage); + // Called by CSvrDomain + void SetDeferralBudget(TInt); + TBool DeferralActive() const; + void ExpireDeferral(); + void CancelDeferral(); + private: + // Handle client calls + void DeferAcknowledgment(const RMessage2&); + void CompleteDeferral(TInt); + void ObsoleteDeferral(); + CSvrDomain* iDomain; + TInt iDeferralsRemaining; + RMessagePtr2 iDeferralMsg; + public: CDmDomainSession* iNext; - TUint8 iPending; + TUint8 iAcknPending; ///< Indicates if an acknowledgment is pending 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) + // Note, tracing of client thread names relies upon + // EUnsharableSessions being used + CDmManagerServer(CDmSvrManager* aManager) : CServer2(CActive::EPriorityStandard, EUnsharableSessions), iManager(aManager) {} CDmSvrManager* iManager; }; @@ -268,12 +323,15 @@ { public: // from CBase + CDmManagerSession(); ~CDmManagerSession(); // from CSession2 void ServiceL(const RMessage2& aMessage); - CDmManagerSession(); + RMessagePtr2 iTransMessagePtr; + RMessagePtr2 iObsvrMessagePtr; + private: CDmHierarchy* iHierarchy; // not owned }; @@ -323,22 +381,46 @@ CSvrDomain::CSvrDomain(CDmHierarchy& aHierarchy, const TDmDomainSpec* spec) : CTimer(CActive::EPriorityStandard), iHierarchy(aHierarchy), - iTransTimeBudget(spec->iTimeBudgetUs), + iParent(NULL), + iPeer(NULL), + iChild(NULL), + iChildrenCount(0), + iTransTimeBudget(TTimeIntervalMicroSeconds32(spec->iTimeBudgetUs), &iHierarchy.HierachySettings()), + iTransitionDeferralBudget(0, &iHierarchy.HierachySettings()), iJoinPolicy(spec->iJoinPolicy), iId(spec->iId) - {} + { + __DS_TRACE((_L("DM: CSvrDomain() @0x%08x, id 0x%x, hierachy id %d"), this, iId, iHierarchy.iHierarchyId)); + } CSvrDomain* CSvrDomain::New(CDmHierarchy& aHierarchy, const TDmDomainSpec& aSpec) { - CSvrDomain* self = new CSvrDomain(aHierarchy, &aSpec); + __DS_PANIC_IFNUL(self); - if (!self) - __DS_PANIC(KErrNoMemory); self->Construct(&aSpec); return self; } +CSvrDomain::~CSvrDomain() + { + __DS_TRACE((_L("DM: ~CSvrDomain() @0x%08x"), this)); + + // delete children + CSvrDomain* child = iChild; + while(child) + { + CSvrDomain* nextChild = child->iPeer; + delete child; + child = nextChild; + iChildrenCount--; + } + __DS_ASSERT(iChildrenCount==0); + + TInt r = iProperty.Delete(DmStatePropertyKey(iHierarchy.iHierarchyId, iId)); + __DS_PANIC_IFERR(r); + } + void CSvrDomain::Construct(const TDmDomainSpec* spec) { TInt r = iProperty.Define( @@ -347,23 +429,20 @@ RProperty::EInt, KAllowAllPolicy,KPowerMgmtPolicy); - if (r != KErrNone) - __DS_PANIC(r); + __DS_PANIC_IFERR(r); r = iProperty.Attach(KUidDmPropertyCategory, DmStatePropertyKey( iHierarchy.iHierarchyId, iId)); - if (r != KErrNone) - __DS_PANIC(r); + __DS_PANIC_IFERR(r); r = iProperty.Set(DmStatePropertyValue(0, spec->iInitState)); - if (r != KErrNone) - __DS_PANIC(r); + __DS_PANIC_IFERR(r); TRAP(r, CTimer::ConstructL()); - if (r != KErrNone) - __DS_PANIC(r); + __DS_PANIC_IFERR(r); + CActiveScheduler::Add(this); } @@ -416,14 +495,16 @@ void CSvrDomain::RequestMembersTransition() { - __DS_TRACE((_L("CSvrDomain::RequestMembersTransition() hierarchy=%d, domain=0x%x"), iHierarchy.iHierarchyId, iId)); + __DS_TRACE((_L("DM: CSvrDomain::RequestMembersTransition() hierarchy=%d, domain=0x%x"), iHierarchy.iHierarchyId, iId)); __DS_ASSERT(iTransCount == 0); - + + SetMemberDeferralBudgets(); + for(CDmDomainSession* s = iSessions; s; s = s->iNext) if (s->iNotificationEnabled) { ++iTransCount; - s->iPending = ETrue; + s->iAcknPending = ETrue; // notifications will be disabled until the client makes another // call to RDmDomain::RequestTransitionNotification() s->iNotificationEnabled = EFalse; @@ -440,7 +521,7 @@ } } if (iTransCount > 0) - CTimer::After(iTransTimeBudget); + CTimer::After(iTransTimeBudget()); iProperty.Set(iHierarchy.iTransPropValue); if (iTransCount == 0) MembersTransitionDone(); @@ -449,7 +530,7 @@ void CSvrDomain::RequestChildrenTransition() { - __DS_TRACE((_L("CSvrDomain::RequestChildrenTransition() hierarchy=%d, domain=0x%x"), iHierarchy.iHierarchyId, iId)); + __DS_TRACE((_L("DM: CSvrDomain::RequestChildrenTransition() hierarchy=%d, domain=0x%x"), iHierarchy.iHierarchyId, iId)); __DS_ASSERT(iTransCount == 0); iTransCount = iChildrenCount; if (iTransCount) @@ -468,7 +549,7 @@ void CSvrDomain::RequestDomainTransition() { - __DS_TRACE((_L("CSvrDomain::RequestDomainTransition() hierarchy=%d, domain=0x%x state=0x%x prop=0x%x"), + __DS_TRACE((_L("DM: 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) @@ -479,7 +560,7 @@ void CSvrDomain::MembersTransitionDone() { - __DS_TRACE((_L("CSvrDomain::MembersTransitionDone() hierarchy=%d, domain=0x%x"), iHierarchy.iHierarchyId, iId)); + __DS_TRACE((_L("DM: CSvrDomain::MembersTransitionDone() hierarchy=%d, domain=0x%x"), iHierarchy.iHierarchyId, iId)); __DS_ASSERT(iTransCount == 0); if (iHierarchy.iTraverseDirection == ETraverseChildrenFirst) CompleteDomainTransition(); @@ -489,7 +570,7 @@ void CSvrDomain::ChildrenTransitionDone() { - __DS_TRACE((_L("CSvrDomain::ChildrenTransitionDone() hierarchy=%d, domain=0x%x"), iHierarchy.iHierarchyId, iId)); + __DS_TRACE((_L("DM: CSvrDomain::ChildrenTransitionDone() hierarchy=%d, domain=0x%x"), iHierarchy.iHierarchyId, iId)); __DS_ASSERT(iTransCount == 0); if (iHierarchy.iTraverseDirection == ETraverseChildrenFirst) RequestMembersTransition(); @@ -499,7 +580,7 @@ void CSvrDomain::CompleteMemberTransition(TInt aError) { - __DS_TRACE((_L("CSvrDomain::CompleteMemberTransition() hierarchy=%d, domain=0x%x, aError = %d"), iHierarchy.iHierarchyId, iId, aError)); + __DS_TRACE((_L("DM: CSvrDomain::CompleteMemberTransition() hierarchy=%d, domain=0x%x, aError = %d"), iHierarchy.iHierarchyId, iId, aError)); __DS_ASSERT(iTransCount); if (aError) @@ -519,7 +600,7 @@ } } // examine the failure policy to work out what to do - if (iHierarchy.iPolicy.iFailurePolicy == ETransitionFailureStop) + if (iHierarchy.iFailurePolicy() == ETransitionFailureStop) { iHierarchy.CompleteTransition(aError); return; @@ -545,16 +626,26 @@ void CSvrDomain::RunL() { // Timer expired - __DS_TRACE((_L("CSvrDomain::RunL() Members transition timeout hierarchy=%d, domain=0x%x"), iHierarchy.iHierarchyId, iId)); + + if (ExpireMemberDeferrals()) + { + __DS_TRACE((_L("DM: CSvrDomain::RunL() Deferring transition timeout hierarchy=%d, domain=0x%x"), iHierarchy.iHierarchyId, iId)); + CTimer::After(iTransTimeBudget()); + return; + } + + __DS_TRACE((_L("DM: CSvrDomain::RunL() Members transition timeout hierarchy=%d, domain=0x%x, iTransCount=%d"), iHierarchy.iHierarchyId, iId, iTransCount)); // 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) + // Examine the failure policy to work out what to do + if (iHierarchy.iFailurePolicy() == ETransitionFailureStop) { + // CompleteTransition will in turn call CancelTransition, + // which will reset iTransCount and the iAcknPending flags iHierarchy.CompleteTransition(KErrTimedOut); return; } @@ -564,7 +655,11 @@ CDmDomainSession* session = iSessions; while (session) { - session->iPending = EFalse; + if (session->iAcknPending) + { + __DS_TRACE((_L("DM: Member transition timeout domain=0x%x: CDmDomainSession Object 0x%08x"), iId, session)); + session->iAcknPending = EFalse; + } session = session->iNext; } iTransCount = 0; @@ -575,7 +670,7 @@ void CSvrDomain::CompleteDomainTransition() { - __DS_TRACE((_L("CSvrDomain::CompleteDomainTransition() hierarchy=%d, domain=0x%x"), iHierarchy.iHierarchyId, iId)); + __DS_TRACE((_L("DM: CSvrDomain::CompleteDomainTransition() hierarchy=%d, domain=0x%x"), iHierarchy.iHierarchyId, iId)); __DS_ASSERT(iTransCount == 0); if (iHierarchy.iTransDomain == this) { @@ -594,7 +689,7 @@ void CSvrDomain::CancelTransition() { - __DS_TRACE((_L("CSvrDomain::CancelTransition() hierarchy=%d, domain=0x%x"), iHierarchy.iHierarchyId, iId)); + __DS_TRACE((_L("DM: CSvrDomain::CancelTransition() hierarchy=%d, domain=0x%x"), iHierarchy.iHierarchyId, iId)); CTimer::Cancel(); CSvrDomain* child = iChild; while (child) @@ -605,7 +700,14 @@ CDmDomainSession* session = iSessions; while (session) { - session->iPending = EFalse; + // At this point the server says that the current transition may no + // longer be acknowledged. Therefore, cancel the deferral + if (session->DeferralActive()) + { + session->CancelDeferral(); + } + + session->iAcknPending = EFalse; session = session->iNext; } iTransCount = 0; @@ -641,6 +743,46 @@ return DmStateFromPropertyValue(value); } +/** +Called before members are notified of a transition. +*/ +void CSvrDomain::SetMemberDeferralBudgets() + { + const TInt deferralBudget = iTransitionDeferralBudget(); + CDmDomainSession* session = iSessions; + while (session) + { + __DS_ASSERT(!session->DeferralActive()); + __DS_ASSERT(!session->iAcknPending); + session->SetDeferralBudget(deferralBudget); + session = session->iNext; + } + } + +/** +Called upon completion of the domain's timeout + +@return True if at least one member had an active deferral +*/ +TBool CSvrDomain::ExpireMemberDeferrals() + { + TBool deferDomain = EFalse; + CDmDomainSession* session = iSessions; + while (session) + { + if (session->DeferralActive()) + { + __DS_ASSERT(session->iAcknPending); + + deferDomain = ETrue; + session->ExpireDeferral(); + } + session = session->iNext; + } + + return deferDomain; + } + //********************************************************* // CDmHierarchy //********************************************************* @@ -654,20 +796,39 @@ else self = new CDmHierarchy(aHierarchyId, aPolicy); - if (!self) - __DS_PANIC(KErrNoMemory); + __DS_PANIC_IFNUL(self); + + self->iSettings = new CHierarchySettings(); + __DS_TRACE((_L("DM: CDmHierarchy::New() @0x%08x, CHierarchySettings @0x%08x"), self, self->iSettings)); + + __DS_PANIC_IFNUL(self->iSettings); + + self->iFailurePolicy.SetSettings(self->iSettings); return self; } CDmHierarchy::CDmHierarchy(TDmHierarchyId aHierarchyId, TDmHierarchyPolicy& aPolicy) : - iOutstandingNotification(EFalse), - iHierarchyId(aHierarchyId), - iPolicy(aPolicy) + iPositiveTransitions(aPolicy.iPositiveTransitions), + iNegativeTransitions(aPolicy.iNegativeTransitions), + iFailurePolicy(aPolicy.iFailurePolicy, iSettings), + iHierarchyId(aHierarchyId) { + __DS_TRACE((_L("DM: CDmHierarchy::CDmHierarchy() @0x%08x, hierarchy=%d"), this, iHierarchyId)); + iTransitionFailures.Reset(); } +CDmHierarchy::~CDmHierarchy() + { + __DS_TRACE((_L("DM: CDmHierarchy::~CDmHierarchy() @0x%08x"), this)); + + delete iRootDomain; + delete iSettings; + iTransitionFailures.Close(); + iTransitions.Close(); + } + CSvrDomain* CDmHierarchy::LookupDomain(TDmDomainId aDomainId) { return iRootDomain ? iRootDomain->Lookup(aDomainId) : NULL; @@ -679,7 +840,13 @@ iTransitionFailures.Reset(); if (aMessage) - iTransMessagePtr = *aMessage; + { + __DS_PANIC_IFNUL(iControllerSession); + iControllerSession->iTransMessagePtr = *aMessage; + } + + iSettings->SetCurrentTargetTransition(iTransState); + iTransPropValue = DmStatePropertyValue(++iTransId, iTransState); iTransDomain->RequestDomainTransition(); @@ -704,22 +871,21 @@ { if (aMessage) { - iObsvrMessagePtr = *aMessage; - iOutstandingNotification=ETrue; - } + __DS_PANIC_IFNUL(iObserverSession); + iObserverSession->iObsvrMessagePtr = *aMessage; + } } TBool CDmHierarchy::OutstandingNotification() { - return iOutstandingNotification; + return iObserverSession && !(iObserverSession->iObsvrMessagePtr.IsNull()); } void CDmHierarchy::CompleteNotification(TInt aError) { - if(iOutstandingNotification) + if (OutstandingNotification()) { - iObsvrMessagePtr.Complete(aError); - iOutstandingNotification=EFalse; + iObserverSession->iObsvrMessagePtr.Complete(aError); } } @@ -730,11 +896,17 @@ iTransitions.Reset(); iObserverStarted=EFalse; } + void CDmHierarchy::NotifyCompletion(TInt aReason) { iTransDomain = NULL; iTransPropValue = 0; - iTransMessagePtr.Complete(aReason); + + if(iControllerSession) + { + __DS_ASSERT(!(iControllerSession->iTransMessagePtr.IsNull())); + iControllerSession->iTransMessagePtr.Complete(aReason); + } } TInt CDmHierarchy::RequestSystemTransition(TDmDomainState aTargetState, TDmTraverseDirection aTraverseDirection, const RMessage2* aMessage) @@ -752,7 +924,7 @@ TDmTraverseDirection aTraverseDirection, const RMessage2* aMessage) { - __DS_TRACE((_L("CDmHierarchy::RequestTransition() hierarchy=%d domain=0x%x state=0x%x"), iHierarchyId, aDomainId, aTargetState)); + __DS_TRACE((_L("DM: CDmHierarchy::RequestTransition() hierarchy=%d domain=0x%x state=0x%x"), iHierarchyId, aDomainId, aTargetState)); iTransDomain = LookupDomain(aDomainId); if (!iTransDomain) return KDmErrBadDomainId; @@ -766,7 +938,7 @@ if (!iTransDomain) return; - __DS_TRACE((_L("CDmHierarchy::CompleteTransition() hierarchy=%d, domain=0x%x, aError=%d"), iHierarchyId, iTransDomain->iId, aError)); + __DS_TRACE((_L("DM: CDmHierarchy::CompleteTransition() hierarchy=%d, domain=0x%x, aError=%d"), iHierarchyId, iTransDomain->iId, aError)); if (iTransDomain) { @@ -785,9 +957,9 @@ TDmDomainState oldState = iTransDomain->State(); if (aTargetState >= oldState) - iTraverseDirection = iPolicy.iPositiveTransitions; + iTraverseDirection = iPositiveTransitions; else - iTraverseDirection = iPolicy.iNegativeTransitions; + iTraverseDirection = iNegativeTransitions; } else iTraverseDirection = aTraverseDirection; @@ -804,8 +976,8 @@ CPowerUpHandler* CPowerUpHandler::New(CDmHierarchyPower& aHierarchyPower) { CPowerUpHandler* self = new CPowerUpHandler(aHierarchyPower); - if (!self) - __DS_PANIC(KErrNoMemory); + __DS_PANIC_IFNUL(self); + self->Construct(); return self; } @@ -858,8 +1030,7 @@ self = new CDmHierarchyPower(aHierarchyId, aPolicy); - if (!self) - __DS_PANIC(KErrNoMemory); + __DS_PANIC_IFNUL(self); self->Construct(); @@ -875,8 +1046,7 @@ void CDmHierarchyPower::Construct() { iPowerUpHandler = CPowerUpHandler::New(*this); - if (!iPowerUpHandler) - __DS_PANIC(KErrNoMemory); + __DS_PANIC_IFNUL(iPowerUpHandler); } void CDmHierarchyPower::NotifyCompletion(TInt aReason) @@ -887,7 +1057,7 @@ TInt CDmHierarchyPower::RequestSystemTransition(TDmDomainState aTargetState, TDmTraverseDirection aTraverseDirection, const RMessage2* aMessage) { - __DS_TRACE((_L("CDmSvrManager::RequestSystemTransition() state = 0x%x"), aTargetState)); + __DS_TRACE((_L("DM: CDmHierarchyPower::RequestSystemTransition() state = 0x%x"), aTargetState)); TInt r = Power::EnableWakeupEvents((TPowerState) aTargetState); if (r != KErrNone) @@ -905,19 +1075,20 @@ if (!iTransDomain) return; - __DS_TRACE((_L("CDmHierarchyPower::CompleteTransition() domain=0x%x"), iTransDomain->iId)); + __DS_TRACE((_L("DM: CDmHierarchyPower::CompleteTransition() domain=0x%x error=%d"), + iTransDomain->iId, aError)); if (iTransDomain && aError == KErrCancel) iPowerUpHandler->Cancel(); - if (iTransStatus & EPoweringDown) + if ((iTransStatus & EPoweringDown) && (aError != KErrCancel)) { RFs fs; TInt r=fs.Connect(); __DS_ASSERT(r==KErrNone); - __DS_TRACE((_L("CDmSvrManager::CompleteTransition() Calling FinaliseDrives"))); + __DS_TRACE((_L("DM: CDmSvrManager::CompleteTransition() Calling FinaliseDrives"))); r=fs.FinaliseDrives(); - __DS_TRACE((_L("CDmSvrManager::CompleteTransition() Finalise returned %d"),r)); + __DS_TRACE((_L("DM: CDmSvrManager::CompleteTransition() Finalise returned %d"),r)); fs.Close(); Power::PowerDown(); @@ -933,7 +1104,7 @@ void CDmHierarchyPower::PowerUp() { - __DS_TRACE((_L("CDmHierarchyPower::RunL() Wakeup Event"))); + __DS_TRACE((_L("DM: CDmHierarchyPower::RunL() Wakeup Event"))); __DS_ASSERT(iTransDomain); Power::DisableWakeupEvents(); @@ -952,8 +1123,8 @@ CDmSvrManager* CDmSvrManager::New() { CDmSvrManager* self = new CDmSvrManager(); - if (!self) - __DS_PANIC(KErrNoMemory); + __DS_PANIC_IFNUL(self); + self->Construct(); return self; } @@ -964,44 +1135,30 @@ void CDmSvrManager::Construct() { - // load the power hierarchy- Other hieratchies need to be loaded + // Load the power hierarchy - other hierarchies need to be loaded // explicitly using RDmDomainManager::AddDomainHierarchy() - CDmHierarchy* hierarchy; - TInt r = BuildDomainTree(KDmHierarchyIdPower, hierarchy); - if (r != KErrNone) - __DS_PANIC(r); - + TInt r = BuildDomainTree(KDmHierarchyIdPower); + __DS_PANIC_IFERR(r); RProperty prop; r = prop.Define(KUidDmPropertyCategory, KDmPropertyKeyInit, RProperty::EInt, - KAllowAllPolicy,KPowerMgmtPolicy); - if (r != KErrNone) - __DS_PANIC(r); + KAllowAllPolicy,KPowerMgmtPolicy); + __DS_PANIC_IFERR(r); prop.Set(KUidDmPropertyCategory, KDmPropertyKeyInit, ETrue); } -TInt CDmSvrManager::BuildDomainTree(TDmHierarchyId aHierarchyId, CDmHierarchy*& aHierarchy) +TInt CDmSvrManager::BuildDomainTree(TDmHierarchyId aHierarchyId) { + // We have already checked that the hierarchy doesn't already exist. - aHierarchy = NULL; - - // assume we have already checked that the hierarchy doesn't already exist - - // Get the name of the policy Dll + // Get the name of the policy DLL. // This will be "domainPolicy.dll" for the power hierarchy // and "domainPolicy.dll" for other hierarchies where 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) + _LIT(KSysBin,"z:\\sys\\bin\\"); dllName.Append(KSysBin); - dllName.Append(_L("domainPolicy")); if (aHierarchyId != KDmHierarchyIdPower) dllName.AppendNum(aHierarchyId); @@ -1058,8 +1215,7 @@ } CDmHierarchy* hierarchy = CDmHierarchy::New(aHierarchyId, hierarchyPolicy); - if (hierarchy == NULL) - __DS_PANIC(KErrNoMemory); + __DS_PANIC_IFNUL(hierarchy); while (r == KErrNone && spec->iId != KDmIdNone) { @@ -1073,11 +1229,13 @@ domain = CSvrDomain::New(*hierarchy, *spec); __DS_ASSERT(domain); - + if (spec->iParentId == KDmIdNone) { if (hierarchy->iRootDomain) { + delete domain; + domain = NULL; r = KDmErrBadDomainSpec; break; } @@ -1088,6 +1246,8 @@ CSvrDomain* parent = hierarchy->LookupDomain(spec->iParentId); if (!parent) { + delete domain; + domain = NULL; r = KDmErrBadDomainSpec; break; } @@ -1096,15 +1256,28 @@ ++spec; } + + if (spec) (*release)(spec); + // Load state specs + if (r == KErrNone) + { + TInt err = LoadStateSpecs(lib, hierarchy); + + // KErrNotFound indicates that policy does not contain state + // specs i.e. it is Version 1 + if ( (err !=KErrNone) && (err !=KErrNotFound)) + { + r = err; + } + } if (r == KErrNone) { __DS_ASSERT(hierarchy->iRootDomain); iDomainHierarchies.Append(hierarchy); - aHierarchy = hierarchy; } else { @@ -1117,6 +1290,76 @@ return r; } +TInt CDmSvrManager::LoadStateSpecs(RLibrary& aLib, CDmHierarchy* aHierarchy) + { + __DS_TRACE((_L("DM: CDmSvrManager::LoadStateSpecs() on CDmHierarchy @0x%08x"), aHierarchy)); + TLibraryFunction ordinal4 = aLib.Lookup(EDmPolicyGetStateSpec); + DmPolicyGetStateSpec getStateSpec = reinterpret_cast(ordinal4); + if (getStateSpec == NULL) + return KErrNotFound; + + TLibraryFunction ordinal5 = aLib.Lookup(EDmPolicyReleaseStateSpec); + DmPolicyReleaseStateSpec releaseStateSpec = reinterpret_cast(ordinal5); + if (releaseStateSpec == NULL) + return KErrNotFound; + + TAny* spec = NULL; + TUint count = 0; + TInt version = (*getStateSpec)(spec, count); + TInt r = KErrNone; + + switch (version) + { + case 0: + { + r = KErrNotFound; + break; + } + case 1: + { + if (count < 1) + { + r = KDmErrBadDomainSpec; + break; + } + + SDmStateSpecV1* specV1 = reinterpret_cast(spec); + for(TUint i = 0; iHierachySettings().StoreConfigL(transitionCfg)); + if (r != KErrNone) + { + break; + } + } + break; + } + default: + { + if (version > 1) + { + r = KDmErrBadDomainSpec; + } + else + { + r = version; + } + break; + } + } + + if(spec) + (*releaseStateSpec)(spec); + + return r; + } + CDmHierarchy* CDmSvrManager::LookupHierarchy(TDmHierarchyId aHierarchyId) { @@ -1150,69 +1393,75 @@ 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(); - } + CDmManagerSession* session = new CDmManagerSession(); +#if defined(_DEBUG) || defined(__DS_DEBUG) + CleanupStack::PushL(session); + TFullName clientName; + GetClientNameFromMessageL(aMessage, clientName); -CSession2* CDmManagerServer::NewSessionL(const TVersion&) const - { - __DS_PANIC(KErrGeneral); - return 0; + // Sessions on this server may not be shared by clients + __DS_TRACE((_L("DM: New CDmManagerSession @0x%08x, client %S"), session, &clientName)); + CleanupStack::Pop(); +#else + (void)aMessage; +#endif + return session; } CDmManagerSession::CDmManagerSession() - {} + { + __DS_TRACE((_L("DM: CDmManagerSession() @0x%08x"), this)); + } CDmManagerSession::~CDmManagerSession() { - if (iHierarchy && iHierarchy->iControllerSession == this) - iHierarchy->iControllerSession = NULL; - if (iHierarchy && iHierarchy->iObserverSession == this) - iHierarchy->iObserverSession = NULL; - } + __DS_TRACE((_L("DM: ~CDmManagerSession() @0x%08x"), this)); -class MyMessage : public RMessage2 - { -public: - TInt* ArgRef(TInt i) - { return &iArgs[i]; } - }; + if (iHierarchy) + { + if (iHierarchy->iControllerSession == this) + { + iHierarchy->iControllerSession = NULL; + } + if (iHierarchy->iObserverSession == this) + { + iHierarchy->iObserverSession = NULL; + } + } + + if(!iTransMessagePtr.IsNull()) + iTransMessagePtr.Complete(KErrCancel); + + if(!iObsvrMessagePtr.IsNull()) + iObsvrMessagePtr.Complete(KErrCancel); + } 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(); + __DS_TRACE((_L("DM: CDmManagerSession::ServiceL @0x%08x EDmHierarchyAdd, HierarchyId %d"), this, hierarchyId)); - CDmHierarchy* hierarchy = manager->LookupHierarchy(hierarchyId); - if (hierarchy == NULL) - r = manager->BuildDomainTree(hierarchyId, hierarchy); + if (manager->LookupHierarchy(hierarchyId) == NULL) + r = manager->BuildDomainTree(hierarchyId); aMessage.Complete(r); } break; @@ -1221,6 +1470,7 @@ { r = KErrNone; TDmHierarchyId hierarchyId = (TDmHierarchyId) aMessage.Int0(); + __DS_TRACE((_L("DM: CDmManagerSession::ServiceL @0x%08x EDmHierarchyJoin, HierarchyId %d"), this, hierarchyId)); iHierarchy = manager->LookupHierarchy(hierarchyId); if (iHierarchy == NULL) @@ -1240,6 +1490,13 @@ break; case EDmRequestSystemTransition: + { + const TDmDomainState targetState = aMessage.Int0(); + const TDmTraverseDirection direction = (TDmTraverseDirection)aMessage.Int1(); + + __DS_TRACE((_L("DM: CDmManagerSession::ServiceL @0x%08x EDmRequestSystemTransition, TargetState %d, Direction %d"), + this, targetState, direction)); + if (iHierarchy==NULL) { aMessage.Complete(KErrBadHierarchyId); @@ -1252,15 +1509,24 @@ } r = iHierarchy->RequestSystemTransition( - (TDmDomainState) aMessage.Int0(), - (TDmTraverseDirection) aMessage.Int1(), + targetState, + direction, &aMessage); if (r != KErrNone) aMessage.Complete(r); break; + } case EDmRequestDomainTransition: + { + const TDmDomainId domain = (TDmDomainId)aMessage.Int0(); + const TDmDomainState targetState = aMessage.Int1(); + const TDmTraverseDirection direction = (TDmTraverseDirection)aMessage.Int2(); + + __DS_TRACE((_L("DM: CDmManagerSession::ServiceL @0x%08x EDmRequestDomainTransition, Domain 0x%x, TargetState %d, Direction %d"), + this, domain, targetState, direction)); + if (iHierarchy==NULL) { aMessage.Complete(KErrBadHierarchyId); @@ -1271,15 +1537,17 @@ aMessage.Complete(KDmErrBadSequence); break; } + r = iHierarchy->RequestDomainTransition( - (TDmDomainId) aMessage.Int0(), - (TDmDomainState) aMessage.Int1(), - (TDmTraverseDirection) aMessage.Int2(), + domain, + targetState, + direction, &aMessage); if (r != KErrNone) aMessage.Complete(r); break; + } case EDmGetTransitionFailureCount: { @@ -1327,6 +1595,9 @@ break; case EDmCancelTransition: + { + __DS_TRACE((_L("DM: CDmManagerSession::ServiceL @0x%08x EDmCancelTransition"), this)); + if (iHierarchy == NULL) { aMessage.Complete(KErrBadHierarchyId); @@ -1340,6 +1611,7 @@ } aMessage.Complete(KErrNone); break; + } case EDmObserverCancel: if (iHierarchy == NULL) { @@ -1498,24 +1770,38 @@ } } -CSession2* CDmDomainServer::NewSessionL(const TVersion&, const RMessage2&) const +CSession2* CDmDomainServer::NewSessionL(const TVersion&, const RMessage2& aMessage) const { + CDmDomainSession* session = new (ELeave) CDmDomainSession; +#ifdef __DS_DEBUG + CleanupStack::PushL(session); + TFullName clientName; + GetClientNameFromMessageL(aMessage, clientName); - return new CDmDomainSession(); + // Sessions on this server may not be shared by clients + __DS_TRACE((_L("DM: New CDmDomainSession @0x%08x, client %S"), session, &clientName)); + CleanupStack::Pop(); +#else + (void)aMessage; +#endif + return session; } -CSession2* CDmDomainServer::NewSessionL(const TVersion&) const +CDmDomainSession::CDmDomainSession() + : iDeferralsRemaining(0) { - __DS_PANIC(KErrGeneral); - return 0; + __DS_TRACE((_L("DM: CDmDomainSession() @0x%08x"), this)); } CDmDomainSession::~CDmDomainSession() { - if (iPending) + __DS_TRACE((_L("DM: ~CDmDomainSession() @0x%08x"), this)); + if (iAcknPending) iDomain->CompleteMemberTransition(KErrNone); if (iDomain) iDomain->Detach(this); + if (DeferralActive()) + CancelDeferral(); } void CDmDomainSession::ServiceL(const RMessage2& aMessage) @@ -1530,6 +1816,8 @@ TDmHierarchyId hierarchyId = (TDmHierarchyId) aMessage.Int0(); TDmDomainId domainId = (TDmDomainId) aMessage.Int1(); + __DS_TRACE((_L("DM: CDmDomainSession::ServiceL @0x%08x EDmDomainJoin, HierarchyId %d, DomainId 0x%x"), this, hierarchyId, domainId)); + r = manager->LookupDomain(hierarchyId, domainId, iDomain); if (r != KErrNone) @@ -1548,10 +1836,12 @@ } case EDmStateRequestTransitionNotification: + __DS_TRACE((_L("DM: CDmDomainSession::ServiceL @0x%08x EDmStateRequestTransitionNotification"), this)); iNotificationEnabled = ETrue; break; case EDmStateCancelTransitionNotification: + __DS_TRACE((_L("DM: CDmDomainSession::ServiceL @0x%08x EDmStateCancelTransitionNotification"), this)); iNotificationEnabled = EFalse; break; @@ -1559,59 +1849,165 @@ { TInt propValue = aMessage.Int0(); TInt error = aMessage.Int1(); + + __DS_TRACE((_L("DM: CDmDomainSession::ServiceL @0x%08x EDmStateAcknowledge, error %d"), this, error)); + if (!iDomain) { r = KDmErrNotJoin; break; } - if (iPending && iDomain->CheckPropValue(propValue)) + if (iAcknPending && iDomain->CheckPropValue(propValue)) { - iPending = EFalse; + if (DeferralActive()) + ObsoleteDeferral(); + + iAcknPending = EFalse; iDomain->CompleteMemberTransition(error); } + else + { + // This error code indicates that there was no pending transition + // corresponding to the cookie supplied in propValue. + r = KErrNotFound; + } + + break; } + + case EDmStateDeferAcknowledgement: + { + __DS_TRACE((_L("DM: CDmDomainSession::ServiceL @0x%08x EDmStateDeferAcknowledgement"), this)); + + // PlatSec check + if (!KWddPolicy.CheckPolicy(aMessage, + __PLATSEC_DIAGNOSTIC_STRING("KWriteDeviceDataPolicy")) && + !KProtServPolicy.CheckPolicy(aMessage, + __PLATSEC_DIAGNOSTIC_STRING("KProtServPolicy"))) + { + // Try harder... + r = KErrPermissionDenied; + break; + } + DeferAcknowledgment(aMessage); + return; // return, not break + } + + case EDmStateCancelDeferral: + { + __DS_TRACE((_L("DM: CDmDomainSession::ServiceL @0x%08x EDmStateCancelDeferral"), this)); + CancelDeferral(); break; + } default: r = KDmErrBadRequest; break; } + aMessage.Complete(r); } - +void CDmDomainSession::SetDeferralBudget(TInt aDeferralCount) + { + __DS_ASSERT(!DeferralActive()); + iDeferralsRemaining = aDeferralCount; + } + +TBool CDmDomainSession::DeferralActive() const + { + return (!iDeferralMsg.IsNull()); + } + +void CDmDomainSession::ExpireDeferral() + { + __DS_ASSERT(DeferralActive()); + __DS_ASSERT(iDeferralsRemaining >= 0); + + CompleteDeferral(KErrNone); + } + +void CDmDomainSession::DeferAcknowledgment(const RMessage2& aMessage) + { + __DS_ASSERT(aMessage.Function() == EDmStateDeferAcknowledgement); + __DS_ASSERT(!DeferralActive()); + + TInt r = KErrNone; + + if (!iAcknPending) + { + r = KErrNotReady; + } + else if (iDeferralsRemaining == 0) + { + r = KErrNotSupported; + } + + if(KErrNone != r) + { + aMessage.Complete(r); + return; + } + + --iDeferralsRemaining; + iDeferralMsg = aMessage; + } + +void CDmDomainSession::CancelDeferral() + { + if (DeferralActive()) + { + CompleteDeferral(KErrCancel); + } + } + +void CDmDomainSession::ObsoleteDeferral() + { + __DS_ASSERT(DeferralActive()); + + CompleteDeferral(KErrCompletion); + } + +void CDmDomainSession::CompleteDeferral(TInt aError) + { + __DS_TRACE((_L("DM: CDmDomainSession::CompleteDeferral() @0x%08x, aError %d"), this, aError)); + __DS_ASSERT(DeferralActive()); + + iDeferralMsg.Complete(aError); + } + + TInt E32Main() { + // Make DM a system critical server + User::SetProcessCritical(User::ESystemCritical); + User::SetCritical(User::ESystemCritical); + CTrapCleanup* cleanupStack = CTrapCleanup::New(); - if(!cleanupStack) - __DS_PANIC(KErrNoMemory); + __DS_ASSERT_STARTUP(cleanupStack); CActiveScheduler* sched = new CActiveScheduler(); - if (!sched) - __DS_PANIC(KErrNoMemory); + __DS_ASSERT_STARTUP(sched); CActiveScheduler::Install(sched); CDmSvrManager* mngr = CDmSvrManager::New(); - __DS_ASSERT(mngr); + __DS_ASSERT_STARTUP(mngr); CDmManagerServer* msrv = new CDmManagerServer(mngr); - if (!msrv) - __DS_PANIC(KErrNoMemory); + __DS_ASSERT_STARTUP(msrv); TInt r=msrv->Start(KDmManagerServerNameLit); - if (r != KErrNone) - __DS_PANIC(r); + __DS_ASSERT_STARTUP(r == KErrNone); CDmDomainServer* dsrv = new CDmDomainServer(mngr); - if (!dsrv) - __DS_PANIC(KErrNoMemory); + __DS_ASSERT_STARTUP(dsrv); r=dsrv->Start(KDmDomainServerNameLit); - if (r != KErrNone) - __DS_PANIC(r); + __DS_ASSERT_STARTUP(r == KErrNone); CActiveScheduler::Start(); + // Server should never shutdown, hence panic to highlight such an event __DS_PANIC(0); return KErrNone;