Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h)
Have multiple extension sections in the bld.inf, one for each version
of the compiler. The RVCT version building the tools will build the
runtime libraries for its version, but make sure we extract all the other
versions from zip archives. Also add the archive for RVCT4.
// 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;
}