os/kernelhwsrv/userlibandfileserver/domainmgr/src/domainsrv.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // domain\src\domainsrv.cpp
    15 // 
    16 //
    17 
    18 #include <e32debug.h>
    19 #include <e32base.h>
    20 #include <e32base_private.h>
    21 #include <e32property.h>
    22 #include <f32file.h>
    23 
    24 #include <domainpolicy.h>
    25 #include "domainsrv.h"
    26 
    27 #define __DS_PANIC(aError) User::Panic(_L("domainSrv.cpp"), (-(aError)) | (__LINE__ << 16))
    28 #define __DS_ASSERT(aCond) ((aCond) || (User::Panic(_L("domainSrv.cpp; assertion failed"), __LINE__), 1))
    29 
    30 //#define __DS_DEBUG
    31 
    32 #ifdef __DS_DEBUG
    33 #define __DS_TRACE(s) RDebug::Print s
    34 #else
    35 #define __DS_TRACE(s)
    36 #endif
    37 
    38 static _LIT_SECURITY_POLICY_PASS(KAllowAllPolicy);
    39 static _LIT_SECURITY_POLICY_C1(KPowerMgmtPolicy,ECapabilityPowerMgmt);
    40 
    41 // forward refs
    42 class CSvrDomain;
    43 class CDmHierarchy;
    44 class CPowerUpHandler;
    45 class CDmHierarchyPower;
    46 class CDmSvrManager;
    47 class CDmDomainServer;
    48 class CDmDomainSession;
    49 class CDmManagerServer;
    50 class CDmManagerSession;
    51 
    52 
    53 
    54 // CSvrDomain
    55 class CSvrDomain : public CTimer
    56 	{
    57 public: 
    58 	static CSvrDomain* New(CDmHierarchy& aHierarchy, const TDmDomainSpec&);
    59 
    60 	// from CTimer
    61 	void RunL();
    62 
    63 	void Attach(CDmDomainSession*);
    64 	void Detach(CDmDomainSession*);
    65 	void AddChild(CSvrDomain*);
    66 	CSvrDomain* Lookup(TDmDomainId);
    67 	TBool CheckPropValue(TInt aPropValue);
    68 	void RequestDomainTransition();
    69 	void CompleteMemberTransition(TInt aError);
    70 	void CancelTransition();
    71 	void SetObserver(TBool aSet);
    72 	TDmDomainState State();
    73 
    74 private:
    75 	CSvrDomain(CDmHierarchy& aHierarchy, const TDmDomainSpec*);
    76 	void Construct(const TDmDomainSpec* spec);
    77 
    78 	void RequestMembersTransition();
    79 	void RequestChildrenTransition();
    80 	void MembersTransitionDone();
    81 	void ChildrenTransitionDone();
    82 	void CompleteDomainTransition();
    83 
    84 private:
    85 	CDmHierarchy&		iHierarchy;
    86 	CSvrDomain*			iParent;
    87 	CSvrDomain*			iPeer;
    88 	CSvrDomain*			iChild;
    89 	RProperty			iProperty;
    90 	CDmDomainSession*	iSessions;
    91 	TUint16				iChildrenCount;
    92 	TUint16				iTransCount;
    93 	TTimeIntervalMicroSeconds32	iTransTimeBudget;
    94 
    95 public:
    96 	const TSecurityPolicy	iJoinPolicy;
    97 	TBool iIsObserved;
    98 	TDmDomainId			iId;
    99 	};
   100 
   101 
   102 // CDmHierarchy
   103 class CDmHierarchy : public CBase
   104 	{
   105 public:
   106 	static CDmHierarchy* New(TDmHierarchyId aHierarchyId, TDmHierarchyPolicy& aPolicy);
   107 
   108 	CSvrDomain* LookupDomain(TDmDomainId aDomainId);
   109 	TInt RequestDomainTransition(TDmDomainId, TDmDomainState aTargetState, TDmTraverseDirection aTraverseDirection, const RMessage2* aMessage);
   110 	void RequestTransition(const RMessage2* aMessage);
   111 	TInt StartObserver( TDmDomainId aDomainId,TDmNotifyType aNotifyType);
   112 	void SetNotifyMessage(const RMessage2* aMessage);
   113 	void CompleteNotification(TInt aError);
   114 	TBool OutstandingNotification();
   115 	void StopObserver();
   116 	virtual TInt RequestSystemTransition(TDmDomainState aTargetState, TDmTraverseDirection aTraverseDirection, const RMessage2* aMessage);
   117 	virtual void CompleteTransition(TInt aError);
   118 	virtual void NotifyCompletion(TInt aReason);
   119 	
   120 protected:
   121 	CDmHierarchy(TDmHierarchyId aHierarchyId, TDmHierarchyPolicy& aPolicy);
   122 	void SetState(TDmDomainState aTargetState, TDmTraverseDirection aTraverseDirection = ETraverseDefault);
   123 
   124 private:
   125 	RMessagePtr2	iTransMessagePtr;
   126 	RMessagePtr2	iObsvrMessagePtr;
   127 	CSvrDomain*		iObservedDomain;
   128 	TBool			iOutstandingNotification;
   129 public:
   130 	TDmHierarchyId	iHierarchyId;
   131 	CSvrDomain*		iRootDomain;
   132 	CSvrDomain*		iTransDomain;
   133 	TInt			iTransPropValue;
   134 	TDmDomainState	iTransState;
   135 	TDmTraverseDirection	iTraverseDirection;
   136 	TUint8			iTransId;
   137 	CDmManagerSession* iControllerSession;	// only one controller per hierarchy
   138 	TDmHierarchyPolicy iPolicy;
   139 	RArray<TTransitionFailure> iTransitionFailures;
   140 	
   141 	// observer stuff
   142 	TBool			iObserverStarted;
   143 	TDmNotifyType	iNotifyType;
   144 	RArray<TTransInfo>	iTransitions;
   145 	CDmManagerSession* iObserverSession;	// only one observer per hierarchy
   146 	TInt			iObservedChildren;
   147 	};
   148 
   149 
   150 // CPowerUpHandler
   151 // Active object used to receive power-up notifications 
   152 // from the Kernel-level power manager
   153 class CPowerUpHandler : public CActive
   154 	{
   155 public: 
   156 	static CPowerUpHandler* New(CDmHierarchyPower& aHierarchyPower);
   157 	
   158 	// from CActive
   159 	void RunL();
   160 	void DoCancel();
   161 
   162 	void RequestWakeupEventNotification();
   163 	void Cancel();
   164 
   165 private:
   166 	CPowerUpHandler(CDmHierarchyPower& aHierarchyPower);
   167 	void Construct();
   168 
   169 private:
   170 	CDmHierarchyPower& iHierarchyPower;
   171 	};
   172 
   173 
   174 // CDmHierarchyPower
   175 // CDmHierarchy-derived class 
   176 // Interfaces to the Kernel-level power manager
   177 class CDmHierarchyPower : public CDmHierarchy
   178 	{
   179 public:
   180 	static CDmHierarchyPower* New(TDmHierarchyId aHierarchyId, TDmHierarchyPolicy& aPolicy);
   181 
   182 	// from CDmHierarchy
   183 	virtual TInt RequestSystemTransition(TDmDomainState, TDmTraverseDirection aTraverseDirection, const RMessage2* aMessage);
   184 	virtual void CompleteTransition(TInt aError);
   185 	virtual void NotifyCompletion(TInt aReason);
   186 
   187 	void PowerUp();	// called from CPowerUpHandler
   188 
   189 private:
   190 	CDmHierarchyPower(TDmHierarchyId aHierarchyId, TDmHierarchyPolicy& aPolicy);
   191 	void Construct();
   192 
   193 private:
   194 	enum 
   195 		{
   196 		EPoweringDown	= 0x01,
   197 		};
   198 	TUint8			iTransStatus;
   199 	CPowerUpHandler* iPowerUpHandler;
   200 	};
   201 
   202 
   203 // CDmSvrManager
   204 class CDmSvrManager : public CBase
   205 	{
   206 public:
   207 	static CDmSvrManager* New();
   208 
   209 	TInt BuildDomainTree(TDmHierarchyId aHierarchyId, CDmHierarchy*& aHierarchy);
   210 	CDmHierarchy* LookupHierarchy(TDmHierarchyId aHierarchyId);
   211 	TInt LookupDomain(TDmHierarchyId aHierarchyId, TDmDomainId aDomainId, CSvrDomain*& aDomain);
   212 
   213 private:
   214 	CDmSvrManager();
   215 	void Construct();
   216 
   217 private:
   218 	RPointerArray<CDmHierarchy> iDomainHierarchies;
   219 	};
   220 
   221 // CDmDomainServer
   222 class CDmDomainServer : public CServer2
   223 	{
   224 public: 
   225 	// from CServer2
   226 	CSession2* NewSessionL(const TVersion& aVer) const;
   227 	CSession2* NewSessionL(const TVersion& aVer, const RMessage2& aMessage) const;
   228 
   229 	CDmDomainServer(CDmSvrManager* aManager) : CServer2(CActive::EPriorityStandard), iManager(aManager)
   230 		{}
   231 
   232 public:
   233 	CDmSvrManager*	iManager;
   234 	};
   235 
   236 // CDmDomainSession
   237 class CDmDomainSession : public CSession2
   238 	{
   239 public: 
   240 	// from CBase
   241 	~CDmDomainSession();
   242 
   243 	// from CSession2
   244 	void ServiceL(const RMessage2& aMessage);
   245 
   246 private:
   247 	CSvrDomain*			iDomain;
   248 
   249 public:
   250 	CDmDomainSession*	iNext;
   251 	TUint8				iPending;
   252 	TBool				iNotificationEnabled;
   253 	};
   254 
   255 class CDmManagerServer : public CServer2
   256 	{
   257 public: 
   258 	// from CServer2
   259 	CSession2* NewSessionL(const TVersion& aVer) const;
   260 	CSession2* NewSessionL(const TVersion& aVer, const RMessage2&) const;
   261 
   262 	CDmManagerServer(CDmSvrManager* aManager) : CServer2(CActive::EPriorityStandard), iManager(aManager)
   263 		{}
   264 	CDmSvrManager*	iManager;
   265 	};
   266 
   267 class CDmManagerSession : public CSession2
   268 	{
   269 public: 
   270 	// from CBase
   271 	~CDmManagerSession();
   272 	
   273 	// from CSession2
   274 	void ServiceL(const RMessage2& aMessage);
   275 
   276 	CDmManagerSession();
   277 private:
   278 	CDmHierarchy* iHierarchy;	// not owned
   279 	};
   280 
   281 
   282 
   283 
   284 //*********************************************************
   285 // TTransitionFailure
   286 //*********************************************************
   287 /**
   288 @internalTechnology
   289 
   290 Constructor for transition failure info.
   291 
   292 @param aDomainID	Id of the domain of interest
   293 @param aError		error code of transition	 
   294 */
   295 TTransitionFailure::TTransitionFailure(TDmDomainId aDomainId, TInt aError) :
   296 	iDomainId(aDomainId), iError(aError)
   297 	{
   298 	}
   299 
   300 //*********************************************************
   301 // TTransInfo
   302 //*********************************************************
   303 
   304 /**
   305 @internalTechnology
   306 
   307 Constructor for transition failure info.
   308 
   309 @param aDomainID	Id of the domain of interest
   310 @param aState		State of the domain after transition
   311 @param aError		error code of transition	 
   312 */
   313 TTransInfo::TTransInfo(TDmDomainId aDomainId, TDmDomainState aState, TInt aError) :
   314 	iDomainId(aDomainId), iState(aState), iError(aError)
   315 	{
   316 	}
   317 
   318 //*********************************************************
   319 // CSvrDomain
   320 //*********************************************************
   321 
   322 
   323 CSvrDomain::CSvrDomain(CDmHierarchy& aHierarchy, const TDmDomainSpec* spec)
   324 	:	CTimer(CActive::EPriorityStandard), 
   325 		iHierarchy(aHierarchy),
   326 		iTransTimeBudget(spec->iTimeBudgetUs),
   327 		iJoinPolicy(spec->iJoinPolicy),
   328 		iId(spec->iId)
   329 	{}
   330 
   331 CSvrDomain* CSvrDomain::New(CDmHierarchy& aHierarchy, const TDmDomainSpec& aSpec)
   332 	{
   333 
   334 	CSvrDomain* self = new CSvrDomain(aHierarchy, &aSpec);
   335 
   336 	if (!self)
   337 		__DS_PANIC(KErrNoMemory);
   338 	self->Construct(&aSpec);
   339 	return self;
   340 	}
   341 
   342 void CSvrDomain::Construct(const TDmDomainSpec* spec)
   343 	{
   344 	TInt r = iProperty.Define(
   345 		KUidDmPropertyCategory, 
   346 		DmStatePropertyKey(iHierarchy.iHierarchyId, iId), 
   347 		RProperty::EInt,
   348 		KAllowAllPolicy,KPowerMgmtPolicy);
   349 
   350 	if (r != KErrNone)
   351 		__DS_PANIC(r);
   352 	
   353 	r = iProperty.Attach(KUidDmPropertyCategory, DmStatePropertyKey(
   354 		iHierarchy.iHierarchyId, 
   355 		iId));
   356 
   357 	if (r != KErrNone)
   358 		__DS_PANIC(r);
   359 
   360 	r = iProperty.Set(DmStatePropertyValue(0, spec->iInitState));
   361 	if (r != KErrNone)
   362 		__DS_PANIC(r);
   363 
   364 	TRAP(r, CTimer::ConstructL());
   365 	if (r != KErrNone)
   366 		__DS_PANIC(r);
   367 	CActiveScheduler::Add(this);
   368 	}
   369 
   370 void CSvrDomain::Attach(CDmDomainSession* aSession)
   371 	{
   372 	aSession->iNext = iSessions;
   373 	iSessions = aSession;
   374 	}
   375 
   376 void CSvrDomain::Detach(CDmDomainSession* aSession)
   377 	{
   378 	CDmDomainSession** prevp = &iSessions;
   379 	while (*prevp != aSession)
   380 		{
   381 		prevp = &((*prevp)->iNext);
   382 		__DS_ASSERT(*prevp);
   383 		}
   384 	*(prevp) = aSession->iNext;
   385 	}
   386 
   387 void CSvrDomain::AddChild(CSvrDomain* aChild)
   388 	{
   389 	++iChildrenCount;
   390 	aChild->iParent = this;
   391 	if(iIsObserved)
   392 		aChild->iIsObserved=ETrue;
   393 	// Insert the child in the list of its peers
   394 	aChild->iPeer = iChild;
   395 	iChild = aChild;
   396 	}
   397 
   398 CSvrDomain* CSvrDomain::Lookup(TDmDomainId aDomainId)
   399 	{
   400 	if (iId == aDomainId)
   401 		return this;
   402 
   403 	CSvrDomain* child = iChild;
   404 	while (child)
   405 		{
   406 		CSvrDomain* domain = child->Lookup(aDomainId);
   407 		if (domain)
   408 			return domain;
   409 		child = child->iPeer;
   410 		}
   411 	return NULL;
   412 	}
   413 
   414 TBool CSvrDomain::CheckPropValue(TInt aPropValue)
   415 	{ return iHierarchy.iTransPropValue == aPropValue; }
   416 
   417 void CSvrDomain::RequestMembersTransition()
   418 	{
   419 	__DS_TRACE((_L("CSvrDomain::RequestMembersTransition() hierarchy=%d, domain=0x%x"), iHierarchy.iHierarchyId, iId));
   420 	__DS_ASSERT(iTransCount == 0);
   421 	
   422 	for(CDmDomainSession* s = iSessions; s; s = s->iNext)
   423 		if (s->iNotificationEnabled)
   424 			{
   425 			++iTransCount;
   426 			s->iPending = ETrue;
   427 			// notifications will be disabled until the client makes another 
   428 			// call to RDmDomain::RequestTransitionNotification()
   429 			s->iNotificationEnabled = EFalse;
   430 			}
   431 
   432 	if(iIsObserved)
   433 		{
   434 		if((iHierarchy.iNotifyType&EDmNotifyTransRequest)==EDmNotifyTransRequest)
   435 			{
   436 			TTransInfo transInfo(iId,State(),KDmErrOutstanding);
   437 			iHierarchy.iTransitions.Append(transInfo);
   438 			if(iHierarchy.OutstandingNotification())
   439 					iHierarchy.CompleteNotification(KErrNone);	
   440 			}
   441 		}
   442 	if (iTransCount > 0)
   443 		CTimer::After(iTransTimeBudget);
   444 	iProperty.Set(iHierarchy.iTransPropValue);
   445 	if (iTransCount == 0)
   446 		MembersTransitionDone();
   447 	}
   448 
   449 
   450 void CSvrDomain::RequestChildrenTransition()
   451 	{
   452 	__DS_TRACE((_L("CSvrDomain::RequestChildrenTransition() hierarchy=%d, domain=0x%x"), iHierarchy.iHierarchyId, iId));
   453 	__DS_ASSERT(iTransCount == 0);
   454 	iTransCount = iChildrenCount;
   455 	if (iTransCount)
   456 		{
   457 		CSvrDomain* child = iChild;
   458 		__DS_ASSERT(child);
   459 		do	{
   460 			child->RequestDomainTransition();
   461 			child = child->iPeer;
   462 			}
   463 		while(child);
   464 		}
   465 	else
   466 		ChildrenTransitionDone();
   467 	}
   468 
   469 void CSvrDomain::RequestDomainTransition()
   470 	{
   471 	__DS_TRACE((_L("CSvrDomain::RequestDomainTransition() hierarchy=%d, domain=0x%x state=0x%x prop=0x%x"), 
   472 						iHierarchy.iHierarchyId, iId, iHierarchy.iTransState, iHierarchy.iTransPropValue));
   473 	__DS_ASSERT(iTransCount == 0);
   474 	if (iHierarchy.iTraverseDirection == ETraverseChildrenFirst)
   475 		RequestChildrenTransition();
   476 	else
   477 		RequestMembersTransition();
   478 	}
   479 		
   480 void CSvrDomain::MembersTransitionDone()
   481 	{
   482 	__DS_TRACE((_L("CSvrDomain::MembersTransitionDone() hierarchy=%d, domain=0x%x"), iHierarchy.iHierarchyId, iId));
   483 	__DS_ASSERT(iTransCount == 0);
   484 	if (iHierarchy.iTraverseDirection == ETraverseChildrenFirst)
   485 		CompleteDomainTransition();
   486 	else
   487 		RequestChildrenTransition();
   488 	}
   489 
   490 void CSvrDomain::ChildrenTransitionDone()
   491 	{
   492 	__DS_TRACE((_L("CSvrDomain::ChildrenTransitionDone() hierarchy=%d, domain=0x%x"), iHierarchy.iHierarchyId, iId));
   493 	__DS_ASSERT(iTransCount == 0);
   494 	if (iHierarchy.iTraverseDirection == ETraverseChildrenFirst)
   495 		RequestMembersTransition();
   496 	else
   497 		CompleteDomainTransition();
   498 	}
   499 
   500 void CSvrDomain::CompleteMemberTransition(TInt aError)
   501 	{
   502 	__DS_TRACE((_L("CSvrDomain::CompleteMemberTransition() hierarchy=%d, domain=0x%x, aError = %d"), iHierarchy.iHierarchyId, iId, aError));
   503 	__DS_ASSERT(iTransCount);
   504 
   505 	if (aError)
   506 		{
   507 		// Add a transition failure to the array
   508 		TTransitionFailure failure(iId, aError);
   509 		iHierarchy.iTransitionFailures.Append(failure);
   510 		
   511 		if(iIsObserved)
   512 			{
   513 				if((iHierarchy.iNotifyType&EDmNotifyFail)==EDmNotifyFail)
   514 				{
   515 				TTransInfo transInfo(iId,State(),aError);
   516 				iHierarchy.iTransitions.Append(transInfo);
   517 				if(iHierarchy.OutstandingNotification())
   518 					iHierarchy.CompleteNotification(KErrNone);
   519 				}
   520 			}
   521 		// examine the failure policy to work out what to do
   522 		if (iHierarchy.iPolicy.iFailurePolicy == ETransitionFailureStop)
   523 			{
   524 			iHierarchy.CompleteTransition(aError);
   525 			return;
   526 			}
   527 		}
   528 	else if(iIsObserved)
   529 			{
   530 				if((iHierarchy.iNotifyType&EDmNotifyPass) == EDmNotifyPass)
   531 				{
   532 				TTransInfo transInfo(iId,State(),aError);
   533 				iHierarchy.iTransitions.Append(transInfo);
   534 				if(iHierarchy.OutstandingNotification())
   535 					iHierarchy.CompleteNotification(KErrNone);
   536 				}
   537 			}
   538 
   539 	if (--iTransCount == 0)
   540 		{
   541 		CTimer::Cancel();
   542 		MembersTransitionDone();
   543 		}
   544 	}
   545 
   546 void CSvrDomain::RunL()
   547 	{ // Timer expired 
   548 	__DS_TRACE((_L("CSvrDomain::RunL() Members transition timeout hierarchy=%d, domain=0x%x"), iHierarchy.iHierarchyId, iId));
   549 
   550 	// Add a transition failure to the array
   551 	TTransitionFailure failure(iId,KErrTimedOut);
   552 	iHierarchy.iTransitionFailures.Append(failure);
   553 
   554 
   555 	// examine the failure policy to work out what to do
   556 	if (iHierarchy.iPolicy.iFailurePolicy == ETransitionFailureStop)
   557 		{
   558 		iHierarchy.CompleteTransition(KErrTimedOut);
   559 		return;
   560 		}
   561 
   562 	if (iTransCount)
   563 		{ // Complete transition of all members
   564 		CDmDomainSession* session = iSessions;
   565 		while (session)
   566 			{
   567 			session->iPending = EFalse;
   568 			session = session->iNext;
   569 			}
   570 		iTransCount = 0;
   571 		MembersTransitionDone();
   572 		}
   573 	}
   574 
   575 
   576 void CSvrDomain::CompleteDomainTransition()
   577 	{
   578 	__DS_TRACE((_L("CSvrDomain::CompleteDomainTransition() hierarchy=%d, domain=0x%x"), iHierarchy.iHierarchyId, iId));
   579 	__DS_ASSERT(iTransCount == 0);
   580 	if (iHierarchy.iTransDomain == this)
   581 		{
   582 		const TInt err = (iHierarchy.iTransitionFailures.Count() > 0)? 
   583 			iHierarchy.iTransitionFailures[0].iError : KErrNone;
   584 		iHierarchy.CompleteTransition(err);
   585 		}
   586 	else
   587 		{
   588 		__DS_ASSERT(iParent);
   589 		__DS_ASSERT(iParent->iTransCount);
   590 		if (--iParent->iTransCount == 0)
   591 			iParent->ChildrenTransitionDone();
   592 		}
   593 	}
   594 
   595 void CSvrDomain::CancelTransition()
   596 	{
   597 	__DS_TRACE((_L("CSvrDomain::CancelTransition() hierarchy=%d, domain=0x%x"), iHierarchy.iHierarchyId, iId));
   598 	CTimer::Cancel();
   599 	CSvrDomain* child = iChild;
   600 	while (child)
   601 		{
   602 		child->CancelTransition();
   603 		child = child->iPeer;
   604 		}
   605 	CDmDomainSession* session = iSessions;
   606 	while (session)
   607 		{
   608 		session->iPending = EFalse;
   609 		session = session->iNext;
   610 		}
   611 	iTransCount = 0;
   612 	}
   613 
   614 void CSvrDomain::SetObserver(TBool aSet)
   615 	{
   616 	iIsObserved=aSet;
   617 	if(aSet)
   618 		{
   619 		iHierarchy.iObservedChildren++;
   620 		}
   621 	else 
   622 		{
   623 		// this should be zero at the end
   624 		iHierarchy.iObservedChildren--;
   625 		}
   626 	if(iChildrenCount!=0)
   627 		{
   628 		CSvrDomain* domain=iChild;
   629 		do	{
   630 			domain->SetObserver(aSet);
   631 			domain = domain->iPeer;
   632 			}
   633 		while(domain);
   634 		}
   635 	}
   636 
   637 TDmDomainState CSvrDomain::State()
   638 	{
   639 	TInt value;
   640 	iProperty.Get(value);
   641 	return DmStateFromPropertyValue(value);
   642 	}
   643 
   644 //*********************************************************
   645 // CDmHierarchy
   646 //*********************************************************
   647 
   648 CDmHierarchy* CDmHierarchy::New(TDmHierarchyId aHierarchyId, TDmHierarchyPolicy& aPolicy)
   649 	{
   650 	CDmHierarchy* self;
   651 	
   652 	if (aHierarchyId == KDmHierarchyIdPower)
   653 		self = CDmHierarchyPower::New(aHierarchyId, aPolicy);
   654 	else 
   655 		self = new CDmHierarchy(aHierarchyId, aPolicy);
   656 
   657 	if (!self)
   658 		__DS_PANIC(KErrNoMemory);
   659 
   660 	return self;
   661 	}
   662 
   663 CDmHierarchy::CDmHierarchy(TDmHierarchyId aHierarchyId, TDmHierarchyPolicy& aPolicy) :
   664 	iOutstandingNotification(EFalse),
   665 	iHierarchyId(aHierarchyId),
   666 	iPolicy(aPolicy)
   667 	{
   668 	iTransitionFailures.Reset();
   669 	}
   670 
   671 CSvrDomain* CDmHierarchy::LookupDomain(TDmDomainId aDomainId)
   672 	{
   673 	return iRootDomain ? iRootDomain->Lookup(aDomainId) : NULL;
   674 	}
   675 
   676 void CDmHierarchy::RequestTransition(const RMessage2* aMessage)
   677 	{
   678 	// reset the array of transition failures
   679 	iTransitionFailures.Reset();
   680 
   681 	if (aMessage)
   682 		iTransMessagePtr = *aMessage;
   683 	iTransPropValue = DmStatePropertyValue(++iTransId, iTransState);
   684 
   685 	iTransDomain->RequestDomainTransition();
   686 	}
   687 
   688 
   689 TInt CDmHierarchy::StartObserver(TDmDomainId aDomainId,TDmNotifyType aNotifyType)
   690 	{
   691 	iObservedDomain = LookupDomain(aDomainId);
   692 		
   693 	if(iObservedDomain==NULL)
   694 		return KDmErrBadDomainId;
   695 	
   696 
   697 	iObservedDomain->SetObserver(ETrue);
   698 	iNotifyType=aNotifyType;
   699 	iObserverStarted=ETrue;
   700 	return KErrNone;
   701 	}
   702 
   703 void CDmHierarchy::SetNotifyMessage(const RMessage2* aMessage)
   704 	{
   705 	if (aMessage)
   706 		{
   707 		iObsvrMessagePtr = *aMessage;
   708 		iOutstandingNotification=ETrue;
   709 		}		
   710 	}
   711 
   712 TBool CDmHierarchy::OutstandingNotification()
   713 	{
   714 	return iOutstandingNotification;
   715 	}
   716 
   717 void CDmHierarchy::CompleteNotification(TInt aError)
   718 	{
   719 	if(iOutstandingNotification)
   720 		{
   721 		iObsvrMessagePtr.Complete(aError);
   722 		iOutstandingNotification=EFalse;
   723 		}
   724 	}
   725 
   726 void CDmHierarchy::StopObserver()
   727 	{
   728 	
   729 	iObservedDomain->SetObserver(EFalse);
   730 	iTransitions.Reset();
   731 	iObserverStarted=EFalse;
   732 	}
   733 void CDmHierarchy::NotifyCompletion(TInt aReason)
   734 	{
   735 	iTransDomain = NULL;
   736 	iTransPropValue = 0;
   737 	iTransMessagePtr.Complete(aReason);
   738 	}
   739 
   740 TInt CDmHierarchy::RequestSystemTransition(TDmDomainState aTargetState, TDmTraverseDirection aTraverseDirection, const RMessage2* aMessage)
   741 	{
   742 	iTransDomain = iRootDomain;
   743 	SetState(aTargetState, aTraverseDirection);
   744 	RequestTransition(aMessage);
   745 	return KErrNone;
   746 	}
   747 
   748 
   749 TInt CDmHierarchy::RequestDomainTransition(
   750 	TDmDomainId aDomainId, 
   751 	TDmDomainState aTargetState, 
   752 	TDmTraverseDirection aTraverseDirection, 
   753 	const RMessage2* aMessage)
   754 	{
   755 	__DS_TRACE((_L("CDmHierarchy::RequestTransition() hierarchy=%d domain=0x%x state=0x%x"), iHierarchyId, aDomainId, aTargetState)); 
   756 	iTransDomain = LookupDomain(aDomainId);
   757 	if (!iTransDomain)
   758 		return KDmErrBadDomainId;
   759 	SetState(aTargetState, aTraverseDirection);
   760 	RequestTransition(aMessage);
   761 	return KErrNone;
   762 	}
   763 
   764 void CDmHierarchy::CompleteTransition(TInt aError)
   765 	{
   766 	if (!iTransDomain)
   767 		return;
   768 
   769 	__DS_TRACE((_L("CDmHierarchy::CompleteTransition() hierarchy=%d, domain=0x%x, aError=%d"), iHierarchyId, iTransDomain->iId, aError));
   770 
   771 	if (iTransDomain)
   772 		{
   773 		iTransDomain->CancelTransition();
   774 		NotifyCompletion(aError);
   775 		}
   776 	}
   777 
   778 void CDmHierarchy::SetState(TDmDomainState aTargetState, TDmTraverseDirection aTraverseDirection)
   779 	{
   780 	__DS_ASSERT(iTransDomain);
   781 
   782 
   783 	if (aTraverseDirection == ETraverseDefault)
   784 		{
   785 		TDmDomainState oldState = iTransDomain->State();
   786 
   787 		if (aTargetState >= oldState)
   788 			iTraverseDirection = iPolicy.iPositiveTransitions;
   789 		else
   790 			iTraverseDirection = iPolicy.iNegativeTransitions;
   791 		}
   792 	else
   793 		iTraverseDirection = aTraverseDirection;
   794 
   795 	__DS_ASSERT(iTraverseDirection < ETraverseMax);
   796 
   797 	iTransState = aTargetState;
   798 	}
   799 
   800 //*********************************************************
   801 // CPowerUpHandler
   802 //*********************************************************
   803 
   804 CPowerUpHandler* CPowerUpHandler::New(CDmHierarchyPower& aHierarchyPower)
   805 	{
   806 	CPowerUpHandler* self = new CPowerUpHandler(aHierarchyPower);
   807 	if (!self)
   808 		__DS_PANIC(KErrNoMemory);
   809 	self->Construct();
   810 	return self;
   811 	}
   812 
   813 CPowerUpHandler::CPowerUpHandler(CDmHierarchyPower& aHierarchyPower) : 
   814 	CActive(CActive::EPriorityStandard),
   815 	iHierarchyPower(aHierarchyPower)
   816 	{
   817 	}
   818 
   819 void CPowerUpHandler::Construct()
   820 	{
   821 	CActiveScheduler::Add(this);
   822 	}
   823 
   824 
   825 void CPowerUpHandler::RequestWakeupEventNotification()
   826 	{
   827 	Power::RequestWakeupEventNotification(iStatus);
   828 	SetActive();
   829 	}
   830 
   831 
   832 void CPowerUpHandler::Cancel()
   833 	{
   834 	CActive::Cancel();
   835 	}
   836 
   837 void CPowerUpHandler::RunL()
   838 	{ 
   839 	// power wakeup event
   840 	iHierarchyPower.PowerUp();
   841 	}
   842 
   843 
   844 void CPowerUpHandler::DoCancel()
   845 	{
   846 	Power::DisableWakeupEvents();
   847 	Power::CancelWakeupEventNotification(); 
   848 	}
   849 
   850 
   851 
   852 //*********************************************************
   853 // CDmHierarchyPower
   854 //*********************************************************
   855 CDmHierarchyPower* CDmHierarchyPower::New(TDmHierarchyId aHierarchyId, TDmHierarchyPolicy& aPolicy)
   856 	{
   857 	CDmHierarchyPower* self;
   858 
   859 	self = new CDmHierarchyPower(aHierarchyId, aPolicy);
   860 
   861 	if (!self)
   862 		__DS_PANIC(KErrNoMemory);
   863 
   864 	self->Construct();
   865 
   866 	return self;
   867 	}
   868 
   869 CDmHierarchyPower::CDmHierarchyPower(TDmHierarchyId aHierarchyId, TDmHierarchyPolicy& aPolicy) :
   870 	CDmHierarchy(aHierarchyId, aPolicy)
   871 	{
   872 	}
   873 
   874 
   875 void CDmHierarchyPower::Construct()
   876 	{
   877 	iPowerUpHandler = CPowerUpHandler::New(*this);
   878 	if (!iPowerUpHandler)
   879 		__DS_PANIC(KErrNoMemory);
   880 	}
   881 
   882 void CDmHierarchyPower::NotifyCompletion(TInt aReason)
   883 	{
   884 	iTransStatus = 0;
   885 	CDmHierarchy::NotifyCompletion(aReason);
   886 	}
   887 
   888 TInt CDmHierarchyPower::RequestSystemTransition(TDmDomainState aTargetState, TDmTraverseDirection aTraverseDirection, const RMessage2* aMessage)
   889 	{
   890 	__DS_TRACE((_L("CDmSvrManager::RequestSystemTransition() state = 0x%x"), aTargetState));
   891 	
   892 	TInt r = Power::EnableWakeupEvents((TPowerState) aTargetState);
   893 	if (r != KErrNone)
   894 		return r;
   895 	
   896 	iPowerUpHandler->RequestWakeupEventNotification();
   897 
   898 	iTransStatus |= EPoweringDown;
   899 
   900 	return CDmHierarchy::RequestSystemTransition(aTargetState, aTraverseDirection, aMessage);
   901 	}
   902 
   903 void CDmHierarchyPower::CompleteTransition(TInt aError)
   904 	{
   905 	if (!iTransDomain)
   906 		return;
   907 
   908 	__DS_TRACE((_L("CDmHierarchyPower::CompleteTransition() domain=0x%x"), iTransDomain->iId));
   909 
   910 	if (iTransDomain && aError == KErrCancel)
   911 		iPowerUpHandler->Cancel();
   912 
   913 	if (iTransStatus & EPoweringDown)
   914 		{
   915 		RFs fs;
   916 		TInt r=fs.Connect();
   917 		__DS_ASSERT(r==KErrNone);	
   918 		__DS_TRACE((_L("CDmSvrManager::CompleteTransition() Calling FinaliseDrives")));
   919 		r=fs.FinaliseDrives();
   920 		__DS_TRACE((_L("CDmSvrManager::CompleteTransition()  Finalise returned %d"),r)); 
   921 		fs.Close();
   922 
   923 		Power::PowerDown();
   924 		__DS_ASSERT(iTransState != (TDmDomainState) EPwOff);
   925 		__DS_ASSERT(iPowerUpHandler->iStatus.Int() == KErrNone);
   926 		}	
   927 	else
   928 		{
   929 		CDmHierarchy::CompleteTransition(aError);
   930 		}
   931 	}
   932 
   933 
   934 void CDmHierarchyPower::PowerUp()
   935 	{
   936 	__DS_TRACE((_L("CDmHierarchyPower::RunL() Wakeup Event")));
   937 	__DS_ASSERT(iTransDomain);
   938 
   939 	Power::DisableWakeupEvents();
   940 
   941 	iTransStatus &= ~EPoweringDown;
   942 	iTransDomain->CancelTransition();
   943 	SetState((TDmDomainState) EPwActive);
   944 	RequestTransition(NULL);
   945 	}
   946 
   947 
   948 //*********************************************************
   949 // CDmSvrManager
   950 //*********************************************************
   951 
   952 CDmSvrManager* CDmSvrManager::New()
   953 	{
   954 	CDmSvrManager* self = new CDmSvrManager();
   955 	if (!self)
   956 		__DS_PANIC(KErrNoMemory);
   957 	self->Construct();
   958 	return self;
   959 	}
   960 
   961 CDmSvrManager::CDmSvrManager()
   962 	{
   963 	}
   964 
   965 void CDmSvrManager::Construct()
   966 	{
   967 	// load the power hierarchy-  Other hieratchies need to be loaded 
   968 	// explicitly using RDmDomainManager::AddDomainHierarchy()
   969 	CDmHierarchy* hierarchy;
   970 	TInt r = BuildDomainTree(KDmHierarchyIdPower, hierarchy);
   971 	if (r != KErrNone)
   972 		__DS_PANIC(r);
   973 
   974 
   975 	RProperty prop;
   976 	r = prop.Define(KUidDmPropertyCategory, KDmPropertyKeyInit, RProperty::EInt,
   977 							KAllowAllPolicy,KPowerMgmtPolicy);
   978 	if (r != KErrNone)
   979 		__DS_PANIC(r);
   980 
   981 	prop.Set(KUidDmPropertyCategory, KDmPropertyKeyInit, ETrue);
   982 	}
   983 
   984 TInt CDmSvrManager::BuildDomainTree(TDmHierarchyId aHierarchyId, CDmHierarchy*& aHierarchy)
   985 	{
   986 
   987 	aHierarchy = NULL;
   988 
   989 	// assume we have already checked that the hierarchy doesn't already exist
   990 
   991 	// Get the name of the policy Dll
   992 	// This will be "domainPolicy.dll" for the power hierarchy
   993 	// and "domainPolicy<n>.dll" for other hierarchies where <n> is the hierarchy ID.
   994 	//
   995 	// If the hierarchy ID is less than KMaxCriticalPolicyDll, load only from ROM
   996 
   997 	TFullName dllName;
   998 
   999 	// is this policy "critical" i.e non-replaceable ?
  1000 	_LIT(KSysBin,"z:\\sys\\bin\\");	
  1001 	// const TInt KMaxCriticalPolicyDll = 1000;
  1002 	// if (aHierarchyId < KMaxCriticalPolicyDll) // <-- cannot be false while aHierarchyId is a TUint8 (typedef'd to TDmHierarchyId)
  1003 	dllName.Append(KSysBin);
  1004 
  1005 	dllName.Append(_L("domainPolicy"));
  1006 	if (aHierarchyId != KDmHierarchyIdPower)
  1007 		dllName.AppendNum(aHierarchyId);
  1008 
  1009 	dllName.Append(_L(".dll"));
  1010 	RLibrary lib;
  1011 	TInt r = lib.Load(dllName);
  1012 	if (r == KErrNotFound)
  1013 		return KErrBadHierarchyId;
  1014 	else if (r != KErrNone)
  1015 		return r;
  1016 
  1017 	TLibraryFunction ordinal1 = lib.Lookup(EDmPolicyGetDomainSpecs);
  1018 	DmPolicyGetDomainSpecs getDomainSpecs = reinterpret_cast<DmPolicyGetDomainSpecs>(ordinal1);
  1019 	if (getDomainSpecs == NULL)
  1020 		r = KErrBadHierarchyId;
  1021 
  1022 	TLibraryFunction ordinal2 = lib.Lookup(EDmPolicyRelease);
  1023 	DmPolicyRelease release = reinterpret_cast<DmPolicyRelease>(ordinal2);
  1024 	if (release == NULL)
  1025 		r = KErrBadHierarchyId;
  1026 
  1027 	TLibraryFunction ordinal3 = lib.Lookup(EDmPolicyGetPolicy);
  1028 	DmPolicyGetPolicy getPolicy = reinterpret_cast<DmPolicyGetPolicy>(ordinal3);
  1029 	if (getPolicy == NULL)
  1030 		r = KErrBadHierarchyId;
  1031 
  1032 
  1033 	// get the domain spec for this hierarchy
  1034 	const TDmDomainSpec* spec = NULL;
  1035 
  1036 	if (r == KErrNone)
  1037 		{
  1038 		spec = (*getDomainSpecs)();
  1039 		if (spec == NULL)
  1040 			r = KErrBadHierarchyId;
  1041 		}
  1042 	// get the policy
  1043 	TDmHierarchyPolicy hierarchyPolicy;
  1044 	if (r == KErrNone)
  1045 		{
  1046 		r = (*getPolicy)(hierarchyPolicy);
  1047 		if (r == KErrNone)
  1048 			{
  1049 			__DS_ASSERT(hierarchyPolicy.iPositiveTransitions < ETraverseMax);
  1050 			__DS_ASSERT(hierarchyPolicy.iNegativeTransitions < ETraverseMax);
  1051 			}
  1052 		}
  1053 
  1054 	if (r != KErrNone)
  1055 		{
  1056 		lib.Close();
  1057 		return r;
  1058 		}
  1059 
  1060 	CDmHierarchy* hierarchy = CDmHierarchy::New(aHierarchyId, hierarchyPolicy);
  1061 	if (hierarchy == NULL)
  1062 		__DS_PANIC(KErrNoMemory);
  1063 
  1064 	while (r == KErrNone && spec->iId != KDmIdNone)
  1065 		{
  1066 		// make sure the domain doesn't already exist in this hierarchy
  1067 		CSvrDomain* domain = hierarchy->LookupDomain(spec->iId);
  1068 		if (domain)
  1069 			{
  1070 			r = KErrBadHierarchyId;
  1071 			break;
  1072 			}
  1073 
  1074 		domain = CSvrDomain::New(*hierarchy, *spec);
  1075 		__DS_ASSERT(domain);
  1076 	
  1077 		if (spec->iParentId == KDmIdNone)
  1078 			{
  1079 			if (hierarchy->iRootDomain)
  1080 				{
  1081 				r = KDmErrBadDomainSpec;
  1082 				break;
  1083 				}
  1084 			hierarchy->iRootDomain = domain;
  1085 			}
  1086 		else
  1087 			{
  1088 			CSvrDomain* parent = hierarchy->LookupDomain(spec->iParentId);
  1089 			if (!parent)
  1090 				{
  1091 				r = KDmErrBadDomainSpec;
  1092 				break;
  1093 				}
  1094 			parent->AddChild(domain);
  1095 			}
  1096 		++spec;
  1097 		}
  1098 
  1099 	if (spec)
  1100 		(*release)(spec);
  1101 
  1102 
  1103 	if (r == KErrNone)
  1104 		{
  1105 		__DS_ASSERT(hierarchy->iRootDomain);
  1106 		iDomainHierarchies.Append(hierarchy);
  1107 		aHierarchy = hierarchy;
  1108 		}
  1109 	else
  1110 		{
  1111 		delete hierarchy;
  1112 		hierarchy = NULL;
  1113 		}
  1114 
  1115 	lib.Close();
  1116 
  1117 	return r;
  1118 	}
  1119 
  1120 CDmHierarchy* CDmSvrManager::LookupHierarchy(TDmHierarchyId aHierarchyId)
  1121 
  1122 	{
  1123 	// need to find the correct hierarchy first
  1124 	TInt len = iDomainHierarchies.Count();
  1125 
  1126 	CDmHierarchy* hierarchy = NULL;
  1127 	for (TInt n=0; n<len; n++)
  1128 		{
  1129 		if (iDomainHierarchies[n]->iHierarchyId == aHierarchyId)
  1130 			{
  1131 			hierarchy = iDomainHierarchies[n];
  1132 			break;
  1133 			}
  1134 		}
  1135 
  1136 	return hierarchy;
  1137 	}
  1138 	
  1139 
  1140 TInt CDmSvrManager::LookupDomain(TDmHierarchyId aHierarchyId, TDmDomainId aDomainId, CSvrDomain*& aDomain)
  1141 	{
  1142 	// need to find the correct hierarchy first
  1143 	CDmHierarchy* hierarchy = LookupHierarchy(aHierarchyId);
  1144 	if (hierarchy == NULL)
  1145 		return KErrBadHierarchyId;
  1146 
  1147 	aDomain = hierarchy->LookupDomain(aDomainId);
  1148 	if (aDomain == NULL)
  1149 		return KDmErrBadDomainId;
  1150 	
  1151 	return KErrNone;
  1152 	}
  1153 	
  1154 CSession2* CDmManagerServer::NewSessionL(const TVersion&, const RMessage2& aMessage) const
  1155 	{
  1156 
  1157     // If the client does not have ECapabilityPowerMgmt capability, then it has no
  1158     // right to make this request. Blow it up.
  1159     if (!KPowerMgmtPolicy.CheckPolicy(aMessage))
  1160 		{
  1161 
  1162         User::Leave(KErrPermissionDenied);
  1163 
  1164 		}
  1165 
  1166 	return new CDmManagerSession();
  1167 	}
  1168 
  1169 CSession2* CDmManagerServer::NewSessionL(const TVersion&) const
  1170 	{
  1171 	__DS_PANIC(KErrGeneral);
  1172 	return 0;
  1173 	}
  1174 
  1175 CDmManagerSession::CDmManagerSession()
  1176 	{}
  1177 
  1178 CDmManagerSession::~CDmManagerSession()
  1179 	{
  1180 	if (iHierarchy && iHierarchy->iControllerSession == this)
  1181 		iHierarchy->iControllerSession = NULL;
  1182 	if (iHierarchy && iHierarchy->iObserverSession == this)
  1183 		iHierarchy->iObserverSession = NULL;
  1184 	}
  1185 
  1186 class MyMessage : public RMessage2
  1187 	{
  1188 public:
  1189 	TInt* ArgRef(TInt i)
  1190 		{ return &iArgs[i]; }
  1191 	};
  1192 
  1193 void CDmManagerSession::ServiceL(const RMessage2& aMessage)
  1194 	{
  1195 	TInt r;
  1196 	CDmSvrManager* manager = ((CDmManagerServer*) Server()) -> iManager;
  1197 
  1198 	// Check client has ECapabilityPowerMgmt capability
  1199 /*	
  1200     if (!KPowerMgmtPolicy.CheckPolicy(aMessage))
  1201 		{
  1202 		aMessage.Complete(KErrPermissionDenied);
  1203 		return;
  1204 		}
  1205 */
  1206 	switch (aMessage.Function())
  1207 		{
  1208 		case EDmHierarchyAdd:
  1209 			{
  1210 			r = KErrNone;
  1211 			TDmHierarchyId hierarchyId = (TDmHierarchyId) aMessage.Int0();
  1212 
  1213 			CDmHierarchy* hierarchy = manager->LookupHierarchy(hierarchyId);
  1214 			if (hierarchy == NULL)
  1215 				r = manager->BuildDomainTree(hierarchyId, hierarchy);
  1216 			aMessage.Complete(r);
  1217 			}
  1218 			break;
  1219 
  1220 		case EDmHierarchyJoin:
  1221 			{
  1222 			r = KErrNone;
  1223 			TDmHierarchyId hierarchyId = (TDmHierarchyId) aMessage.Int0();
  1224 
  1225 			iHierarchy = manager->LookupHierarchy(hierarchyId);
  1226 			if (iHierarchy == NULL)
  1227 				r = KErrBadHierarchyId;
  1228 
  1229 			if (r == KErrNone)
  1230 				{
  1231 				// is the hierarchy already in use ?
  1232 				if (iHierarchy->iControllerSession)
  1233 					r = KErrInUse;
  1234 				else
  1235 					iHierarchy->iControllerSession = this;
  1236 				}
  1237 
  1238 			aMessage.Complete(r);
  1239 			}
  1240 			break;
  1241 
  1242 		case EDmRequestSystemTransition:
  1243 			if (iHierarchy==NULL)
  1244 				{
  1245 				aMessage.Complete(KErrBadHierarchyId);
  1246 				break;
  1247 				}
  1248 			if (iHierarchy->iTransDomain)
  1249 				{
  1250 				aMessage.Complete(KDmErrBadSequence);
  1251 				break;
  1252 				}
  1253 
  1254 			r = iHierarchy->RequestSystemTransition(
  1255 				(TDmDomainState) aMessage.Int0(),
  1256 				(TDmTraverseDirection) aMessage.Int1(),
  1257 				&aMessage);
  1258 
  1259 			if (r != KErrNone)
  1260 				aMessage.Complete(r);
  1261 			break;
  1262 
  1263 		case EDmRequestDomainTransition:
  1264 			if (iHierarchy==NULL)
  1265 				{
  1266 				aMessage.Complete(KErrBadHierarchyId);
  1267 				break;
  1268 				}
  1269 			if (iHierarchy->iTransDomain)
  1270 				{
  1271 				aMessage.Complete(KDmErrBadSequence);
  1272 				break;
  1273 				}
  1274 			r = iHierarchy->RequestDomainTransition(
  1275 				(TDmDomainId) aMessage.Int0(), 
  1276 				(TDmDomainState) aMessage.Int1(), 
  1277 				(TDmTraverseDirection) aMessage.Int2(),
  1278 				&aMessage);
  1279 
  1280 			if (r != KErrNone)
  1281 				aMessage.Complete(r);
  1282 			break;
  1283 
  1284 		case EDmGetTransitionFailureCount:
  1285 			{
  1286 			if (iHierarchy==NULL)
  1287 				{
  1288 				aMessage.Complete(KErrBadHierarchyId);
  1289 				break;
  1290 				}
  1291 			TInt failureCount = iHierarchy->iTransitionFailures.Count();
  1292 			aMessage.Complete(failureCount);
  1293 			}
  1294 			break;
  1295 		
  1296 		case EDmGetTransitionFailures:
  1297 			{
  1298 			if (iHierarchy==NULL)
  1299 				{
  1300 				aMessage.Complete(KErrBadHierarchyId);
  1301 				break;
  1302 				}
  1303 			TInt failureCount = iHierarchy->iTransitionFailures.Count();
  1304 			TInt clientFailureSize = aMessage.GetDesMaxLength(0);
  1305 			TInt clientFailureCount = clientFailureSize / sizeof(TTransitionFailure);
  1306 			__DS_ASSERT( (clientFailureSize % sizeof(TTransitionFailure)) == 0);
  1307 			__DS_ASSERT(failureCount >= clientFailureCount);
  1308 			
  1309 			HBufC8* hBuf = HBufC8::New(clientFailureSize);
  1310 			if(hBuf == NULL)
  1311 				{
  1312 				aMessage.Complete(KErrNoMemory);
  1313 				break;
  1314 				}
  1315 			TPtr8 pBuf = hBuf->Des();
  1316 			pBuf.Zero();
  1317 			for (TInt i=0; i<clientFailureCount; i++)
  1318 				{
  1319 				TPtrC8 ptr = TPtrC8((TUint8*) &iHierarchy->iTransitionFailures[i], sizeof(TTransitionFailure));
  1320 				pBuf.Append(ptr);
  1321 				}
  1322 			r = aMessage.Write(0, pBuf);
  1323 			delete hBuf;
  1324 
  1325 			aMessage.Complete(r);
  1326 			}
  1327 			break;
  1328 
  1329 		case EDmCancelTransition:
  1330 			if (iHierarchy == NULL)
  1331 				{
  1332 				aMessage.Complete(KErrBadHierarchyId);
  1333 				break;
  1334 				}
  1335 			iHierarchy->CompleteTransition(KErrCancel);
  1336 			if (iHierarchy->iObserverStarted)
  1337 				{
  1338 				iHierarchy->CompleteNotification(KErrCancel);
  1339 				iHierarchy->StopObserver();
  1340 				}
  1341 			aMessage.Complete(KErrNone);
  1342 			break;
  1343 		case EDmObserverCancel:
  1344 			if (iHierarchy == NULL)
  1345 				{
  1346 				aMessage.Complete(KErrBadHierarchyId);
  1347 				break;
  1348 				}
  1349 			if(!iHierarchy->iObserverSession)
  1350 				{
  1351 				aMessage.Complete(KDmErrBadSequence);
  1352 				break;
  1353 				}
  1354 			if (iHierarchy->iObserverStarted)
  1355 				{
  1356 				iHierarchy->CompleteNotification(KErrCancel);
  1357 				iHierarchy->StopObserver();
  1358 				}
  1359 			aMessage.Complete(KErrNone);
  1360 			break;
  1361 
  1362 		case EDmObserverJoin:
  1363 			{
  1364 			TDmHierarchyId hierarchyId = (TDmHierarchyId) aMessage.Int0();
  1365 
  1366 			iHierarchy = manager->LookupHierarchy(hierarchyId);
  1367 			if(iHierarchy==NULL)
  1368 				{
  1369 				aMessage.Complete(KErrBadHierarchyId);
  1370 				break;
  1371 				}
  1372 			if(iHierarchy->iObserverSession)
  1373 				{
  1374 				aMessage.Complete(KDmErrBadSequence);
  1375 				break;
  1376 				}
  1377 			iHierarchy->iTransitions.Reset();
  1378 			iHierarchy->iObserverSession = this;
  1379 			aMessage.Complete(KErrNone);
  1380 			}
  1381 			break;
  1382 
  1383 		case EDmObserverStart:
  1384 			{
  1385 			if (iHierarchy==NULL)
  1386 				{
  1387 				aMessage.Complete(KErrBadHierarchyId);
  1388 				break;
  1389 				}
  1390 			
  1391 			if(iHierarchy->iObserverStarted || iHierarchy->iObserverSession != this)
  1392 				{
  1393 				aMessage.Complete(KDmErrBadSequence); 
  1394 				break;
  1395 				}
  1396 			TInt ret= iHierarchy->StartObserver((TDmDomainId)aMessage.Int0(),(TDmNotifyType)aMessage.Int1());
  1397 			aMessage.Complete(ret);
  1398 			}
  1399 			break;
  1400 
  1401 		case EDmObserverNotify:
  1402 			{
  1403 			if (iHierarchy==NULL)
  1404 				{
  1405 				aMessage.Complete(KErrBadHierarchyId);
  1406 				break;
  1407 				}
  1408 			if(!iHierarchy->iObserverStarted || iHierarchy->iObserverSession != this)
  1409 				{
  1410 				aMessage.Complete(KDmErrBadSequence); 
  1411 				break;
  1412 				}
  1413 			//	Check to see if we have any events stored 
  1414 			//	If so, then notify the client
  1415 			if(iHierarchy->iTransitions.Count()>0)
  1416 				{
  1417 				aMessage.Complete(KErrNone);
  1418 				break;
  1419 				}
  1420 			//	No events are stored. complete this message later
  1421 			iHierarchy->SetNotifyMessage(&aMessage);
  1422 			}
  1423 			break;
  1424 		
  1425 		case EDmObserverEventCount:
  1426 			{
  1427 			if (iHierarchy==NULL)
  1428 				{
  1429 				aMessage.Complete(KErrBadHierarchyId);
  1430 				break;
  1431 				}
  1432 			if(!iHierarchy->iObserverStarted || iHierarchy->iObserverSession != this)
  1433 				{
  1434 				aMessage.Complete(KDmErrBadSequence);
  1435 				break;
  1436 				}
  1437 			TInt count = iHierarchy->iTransitions.Count();
  1438 			aMessage.Complete(count);
  1439 			}
  1440 			break;
  1441 		
  1442 		case EDmObserverGetEvent:
  1443 			{
  1444 			if (iHierarchy==NULL)
  1445 				{
  1446 				aMessage.Complete(KErrBadHierarchyId);
  1447 				break;
  1448 				}
  1449 			if(!iHierarchy->iObserverStarted || iHierarchy->iObserverSession != this)
  1450 				{
  1451 				aMessage.Complete(KDmErrBadSequence);
  1452 				break;
  1453 				}
  1454 			TInt transitionCount = iHierarchy->iTransitions.Count();
  1455 			TInt clientTransitionSize = aMessage.GetDesMaxLength(0);
  1456 			TInt clientTransitionCount = clientTransitionSize / sizeof(TTransInfo);
  1457 			__DS_ASSERT( (clientTransitionSize % sizeof(TTransInfo)) == 0);
  1458 			__DS_ASSERT(transitionCount >= clientTransitionCount);
  1459 			
  1460 			HBufC8* hBuf = HBufC8::New(clientTransitionSize);
  1461 			if(hBuf == NULL)
  1462 				{
  1463 				aMessage.Complete(KErrNoMemory);
  1464 				break;
  1465 				}
  1466 			TPtr8 pBuf = hBuf->Des();
  1467 			pBuf.Zero();
  1468 			for (TInt i=0; i<clientTransitionCount; i++)
  1469 				{
  1470 				TPtrC8 ptr = TPtrC8((TUint8*) &iHierarchy->iTransitions[0], sizeof(TTransInfo));
  1471 				pBuf.Append(ptr);
  1472 				iHierarchy->iTransitions.Remove(0);
  1473 				}
  1474 			r = aMessage.Write(0, pBuf);
  1475 			delete hBuf;
  1476 
  1477 			aMessage.Complete(r);
  1478 			}
  1479 			break;
  1480 		case EDmObserveredCount:
  1481 			{
  1482 			if (iHierarchy==NULL)
  1483 				{
  1484 				aMessage.Complete(KErrBadHierarchyId);
  1485 				break;
  1486 				}
  1487 			if(!iHierarchy->iObserverStarted || iHierarchy->iObserverSession != this)
  1488 				{
  1489 				aMessage.Complete(KDmErrBadSequence);
  1490 				break;
  1491 				}
  1492 			aMessage.Complete(iHierarchy->iObservedChildren);
  1493 			}
  1494 			break;
  1495 		default:
  1496 			aMessage.Complete(KDmErrBadRequest);
  1497 			break;
  1498 		}
  1499 	}
  1500 
  1501 CSession2* CDmDomainServer::NewSessionL(const TVersion&, const RMessage2&) const
  1502 	{
  1503 
  1504 	return new CDmDomainSession();
  1505 	}
  1506 
  1507 CSession2* CDmDomainServer::NewSessionL(const TVersion&) const
  1508 	{
  1509 	__DS_PANIC(KErrGeneral);
  1510 	return 0;
  1511 	}
  1512 
  1513 CDmDomainSession::~CDmDomainSession()
  1514 	{
  1515 	if (iPending)
  1516 		iDomain->CompleteMemberTransition(KErrNone);
  1517 	if (iDomain)
  1518 		iDomain->Detach(this);
  1519 	}
  1520 
  1521 void CDmDomainSession::ServiceL(const RMessage2& aMessage)
  1522 	{
  1523 	TInt r = KErrNone;
  1524 	CDmSvrManager* manager = ((CDmManagerServer*) Server()) -> iManager;
  1525 
  1526 	switch (aMessage.Function())
  1527 		{
  1528 	case EDmDomainJoin:
  1529 		{
  1530 		TDmHierarchyId hierarchyId = (TDmHierarchyId) aMessage.Int0();
  1531 		TDmDomainId domainId = (TDmDomainId) aMessage.Int1();
  1532 
  1533 		r = manager->LookupDomain(hierarchyId, domainId, iDomain);
  1534 
  1535 		if (r != KErrNone)
  1536 			break;
  1537 
  1538 		// Check client has capability to join the domain
  1539 		if (!iDomain->iJoinPolicy.CheckPolicy(aMessage))
  1540 			{
  1541 			r = KErrPermissionDenied;
  1542 			iDomain = NULL;
  1543 			break;
  1544 			}
  1545 
  1546 		iDomain->Attach(this);
  1547 		break;
  1548 		}
  1549 
  1550 	case EDmStateRequestTransitionNotification:
  1551 		iNotificationEnabled = ETrue;
  1552 		break;
  1553 
  1554 	case EDmStateCancelTransitionNotification:
  1555 		iNotificationEnabled = EFalse;
  1556 		break;
  1557 
  1558 	case EDmStateAcknowledge:
  1559 		{
  1560 		TInt propValue = aMessage.Int0();
  1561 		TInt error = aMessage.Int1();
  1562 		if (!iDomain)
  1563 			{
  1564 			r = KDmErrNotJoin;
  1565 			break;
  1566 			}
  1567 		if (iPending && iDomain->CheckPropValue(propValue))
  1568 			{
  1569 			iPending = EFalse;
  1570 			iDomain->CompleteMemberTransition(error);
  1571 			}
  1572 		}
  1573 		break;
  1574 	default:
  1575 		r = KDmErrBadRequest;
  1576 		break;
  1577 		}
  1578 	aMessage.Complete(r);
  1579 	}
  1580 
  1581 	
  1582 TInt E32Main()
  1583 	{
  1584 	CTrapCleanup* cleanupStack = CTrapCleanup::New();
  1585 	if(!cleanupStack)
  1586 		__DS_PANIC(KErrNoMemory);
  1587 
  1588 	CActiveScheduler* sched = new CActiveScheduler();
  1589 	if (!sched)
  1590 		__DS_PANIC(KErrNoMemory);
  1591 
  1592 	CActiveScheduler::Install(sched);
  1593 
  1594 	CDmSvrManager* mngr = CDmSvrManager::New();
  1595 	__DS_ASSERT(mngr);
  1596 
  1597 	CDmManagerServer* msrv = new CDmManagerServer(mngr);
  1598 	if (!msrv)
  1599 		__DS_PANIC(KErrNoMemory);
  1600 
  1601 	TInt r=msrv->Start(KDmManagerServerNameLit);
  1602 	if (r != KErrNone)
  1603 		__DS_PANIC(r);
  1604 
  1605 	CDmDomainServer* dsrv = new CDmDomainServer(mngr);
  1606 	if (!dsrv)
  1607 		__DS_PANIC(KErrNoMemory);
  1608 
  1609 	r=dsrv->Start(KDmDomainServerNameLit);
  1610 	if (r != KErrNone)
  1611 		__DS_PANIC(r);
  1612 
  1613 	CActiveScheduler::Start();
  1614 
  1615 	__DS_PANIC(0);
  1616 
  1617 	return KErrNone;
  1618 	}