os/kernelhwsrv/userlibandfileserver/domainmgr/src/domaincli.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\domaincli.cpp
    15 // 
    16 //
    17 
    18 #include <e32base.h>
    19 #include <e32base_private.h>
    20 #include <e32property.h>
    21 
    22 #include <domainmember.h>
    23 #include <domainmanager.h>
    24 #include "domainobserver.h"
    25 #include "domainsrv.h"
    26 
    27 #define __DM_PANIC(aError) User::Panic(_L("domainCli.cpp"), (-(aError)) | (__LINE__ << 16))
    28 #define __DM_ASSERT(aCond) __ASSERT_DEBUG(aCond,User::Panic(_L("domainCli.cpp; assertion failed"), __LINE__))
    29 
    30 TInt RDmDomainSession::Connect(TDmHierarchyId aHierarchyId, TDmDomainId aDomainId, TUint* aKey)
    31 	{
    32 	TInt r = RSessionBase::CreateSession(KDmDomainServerNameLit, KDmDomainServerVersion, 1);
    33 	if (r != KErrNone)
    34 		return r;
    35 	TIpcArgs a( (TInt)aHierarchyId, (TInt)aDomainId );
    36 	r = RSessionBase::SendReceive(EDmDomainJoin, a);
    37 	if (r != KErrNone)
    38 		{
    39 		RSessionBase::Close();
    40 		return r;
    41 		}
    42 	*aKey = DmStatePropertyKey(
    43 		aHierarchyId, 
    44 		aDomainId);
    45 
    46 	return KErrNone;
    47 	}
    48 
    49 void RDmDomainSession::Acknowledge(TInt aValue, TInt aError)
    50 	{
    51 	__DM_ASSERT(Handle() != KNullHandle);
    52 
    53 	TIpcArgs a(aValue, aError);
    54 	TInt r = RSessionBase::SendReceive(EDmStateAcknowledge, a);
    55 	if (r != KErrNone)
    56 		__DM_PANIC(r);
    57 	}
    58 
    59 void RDmDomainSession::RequestTransitionNotification()
    60 	{
    61 	__DM_ASSERT(Handle() != KNullHandle);
    62 	TInt r = RSessionBase::SendReceive(EDmStateRequestTransitionNotification);
    63 	if (r != KErrNone)
    64 		__DM_PANIC(r);
    65 	}
    66 
    67 void RDmDomainSession::CancelTransitionNotification()
    68 	{
    69 	if (Handle() != KNullHandle)
    70 		{
    71 		TInt r = RSessionBase::SendReceive(EDmStateCancelTransitionNotification);
    72 		if (r != KErrNone)
    73 			__DM_PANIC(r);
    74 		}
    75 	}
    76 
    77 
    78 
    79 /**
    80 Connects to the domain identified by the specified domain Id.
    81 
    82 To connect to the root domain, which has the Id KDmIdRoot,
    83 the capability WriteDeviceData is required.
    84 
    85 Once connected, an  application can use this RDmDomain object to read
    86 the domain's power state and to request notification
    87 when the power state changes.
    88 
    89 @param aDomainId The identifier of the domain to be connected to.
    90 
    91 @return KErrNone, if successful; otherwise one of the other system-wide
    92         or domain manager specific error codes.
    93 
    94 @capability WriteDeviceData If aDomainId==KDmIdRoot
    95 */
    96 EXPORT_C TInt RDmDomain::Connect(TDmDomainId aDomainId)
    97 	{
    98 	TUint key;
    99 	TInt r = iSession.Connect(KDmHierarchyIdPower, aDomainId, &key);
   100 	if (r != KErrNone)
   101 		return r;
   102 	r = iStateProperty.Attach(KUidDmPropertyCategory, key);
   103 	if (r != KErrNone)
   104 		{
   105 		iSession.Close();
   106 		return r;
   107 		}
   108 	return KErrNone;
   109 	}
   110 	
   111 
   112 
   113 
   114 /**
   115 Connects to the domain identified by the specified domain Id.
   116 
   117 To connect to the root domain, which has the Id KDmIdRoot,
   118 the capability WriteDeviceData is required.
   119 
   120 Once connected, an  application can use this RDmDomain object to read
   121 the domain's state and to request notification
   122 when the state changes.
   123 
   124 @param aHierarchyId	The Id of the domain hierarchy to connect to.
   125 @param aDomainId    The identifier of the domain to be connected to.
   126 
   127 @return KErrNone, if successful; otherwise one of the other system-wide
   128         or domain manager specific error codes.
   129 
   130 @capability WriteDeviceData If aDomainId==KDmIdRoot
   131 */
   132 EXPORT_C TInt RDmDomain::Connect(TDmHierarchyId aHierarchyId, TDmDomainId aDomainId)
   133 	{
   134 	TUint key;
   135 	TInt r = iSession.Connect(aHierarchyId, aDomainId, &key);
   136 	if (r != KErrNone)
   137 		return r;
   138 	r = iStateProperty.Attach(KUidDmPropertyCategory, key);
   139 	if (r != KErrNone)
   140 		{
   141 		iSession.Close();
   142 		return r;
   143 		}
   144 	return KErrNone;
   145 	}
   146 	
   147 
   148 	
   149 	
   150 /**
   151 Disconnects from the associated domain.
   152 	
   153 If this object is not connected to any domain, then it returns silently.
   154 */
   155 EXPORT_C void RDmDomain::Close()
   156 	{
   157 	iSession.Close();
   158 	iStateProperty.Close();
   159 	}
   160 
   161 
   162 
   163 
   164 /**
   165 Requests notification when the domain's state changes.
   166 
   167 This is an asynchronous request that completes when
   168 the domain's state changes.
   169 
   170 @param aStatus The request status object for this asynchronous request.
   171 
   172 @see RDmDomain::CancelTransitionNotification()
   173 */
   174 EXPORT_C void RDmDomain::RequestTransitionNotification(TRequestStatus& aStatus)
   175 	{
   176 	iStateProperty.Subscribe(aStatus);
   177 	iSession.RequestTransitionNotification();
   178 	}
   179 
   180 
   181 
   182 
   183 /**
   184 Cancels an outstanding notification request.
   185 
   186 Any outstanding notification request completes with KErrCancel.
   187 */
   188 EXPORT_C void RDmDomain::CancelTransitionNotification()
   189 	{
   190 	iSession.CancelTransitionNotification();
   191 	iStateProperty.Cancel();
   192 	}
   193 
   194 
   195 
   196 
   197 /**
   198 Gets the domain's power state.
   199 	
   200 An application normally calls this function after a notification request
   201 has completed. It then performs any application-dependent action demanded by
   202 the power state, and then acknowledges the state transition.
   203 
   204 Note that the domain manager requires any domain power state change to be
   205 acknowledged by all applications connected to the domain.
   206 
   207 @return The connected domain's power state.
   208 
   209 @see RDmDomain::AcknowledgeLastState()
   210 */
   211 EXPORT_C TPowerState RDmDomain::GetPowerState()
   212 	{
   213 	TInt value;
   214 	TInt r = iStateProperty.Get(value);
   215 	if (r != KErrNone)
   216 		__DM_PANIC(r);
   217 	iLastStatePropertyValue = value;
   218 	return (TPowerState) DmStateFromPropertyValue(value);
   219 	}
   220 
   221 
   222 
   223 
   224 /**
   225 Acknowledges the state change.
   226 	
   227 An application must acknowledge that it has performed all actions required
   228 by the last known state of the domain.
   229 */
   230 EXPORT_C void RDmDomain::AcknowledgeLastState()
   231 	{
   232 	iSession.Acknowledge(iLastStatePropertyValue, KErrNone);
   233 	}
   234 
   235 
   236 /**
   237 Acknowledges the state change with the specified error
   238 	
   239 An application must acknowledge that it has performed all actions required
   240 by the last known state of the domain.
   241 
   242 @param aError KDmErrNotJoin if domain is not part of the hierarhcy or a 
   243 	system wide error value associated with the state change.
   244 */
   245 EXPORT_C void RDmDomain::AcknowledgeLastState(TInt aError)
   246 	{
   247 	iSession.Acknowledge(iLastStatePropertyValue, aError);
   248 	}
   249 
   250 
   251 
   252 /**
   253 Gets the domain's state.
   254 	
   255 An application normally calls this function after a notification request
   256 has completed. It then performs any application-dependent action demanded by
   257 the state, and then acknowledges the state transition.
   258 
   259 Note, that the domain manager requires any domain state change to be
   260 acknowledged by all applications connected to the domain.
   261 
   262 @return The connected domain's state.
   263 */
   264 EXPORT_C TDmDomainState RDmDomain::GetState()
   265 	{
   266 	TInt value;
   267 	TInt r = iStateProperty.Get(value);
   268 	if (r != KErrNone)
   269 		__DM_PANIC(r);
   270 	iLastStatePropertyValue = value;
   271 	return DmStateFromPropertyValue(value);
   272 	}
   273 
   274 TInt RDmManagerSession::Connect()
   275 	{
   276 	__DM_ASSERT(Handle() == KNullHandle);
   277 
   278 	return RSessionBase::CreateSession(
   279 				KDmManagerServerNameLit, 
   280 				KDmManagerServerVersion, 
   281 				2);
   282 	}
   283 
   284 TInt RDmManagerSession::ConnectObserver(TDmHierarchyId aHierarchyId)
   285 	{
   286 	TInt r = Connect();
   287 	if (r != KErrNone)
   288 		return r;
   289 
   290 	TIpcArgs a( (TInt)aHierarchyId);
   291 	r = RSessionBase::SendReceive(EDmObserverJoin, a);
   292 	if (r != KErrNone)
   293 		{
   294 		RSessionBase::Close();
   295 		return r;
   296 		}
   297 	return KErrNone;
   298 	}
   299 
   300 TInt RDmManagerSession::Connect(TDmHierarchyId aHierarchyId)
   301 	{
   302 	TInt r = Connect();
   303 	if (r != KErrNone)
   304 		return r;
   305 
   306 	TIpcArgs a( (TInt)aHierarchyId);
   307 	r = RSessionBase::SendReceive(EDmHierarchyJoin, a);
   308 	if (r != KErrNone)
   309 		{
   310 		RSessionBase::Close();
   311 		return r;
   312 		}
   313 	return KErrNone;
   314 	}
   315 
   316 void RDmManagerSession::RequestDomainTransition(
   317 	TDmDomainId aDomainId, 
   318 	TDmDomainState aState,
   319 	TDmTraverseDirection aDirection,
   320 	TRequestStatus& aStatus)
   321 	{
   322 	__DM_ASSERT(Handle() != KNullHandle);
   323 	
   324 	if(aDirection < 0 || aDirection > ETraverseMax)
   325 		__DM_PANIC(KErrArgument);
   326 
   327 	TIpcArgs a(aDomainId, aState, aDirection);
   328 	RSessionBase::SendReceive(EDmRequestDomainTransition, a, aStatus);
   329 	}
   330 
   331 void RDmManagerSession::CancelTransition()
   332 	{
   333 	if (Handle() != KNullHandle)
   334 		{
   335 		TInt r = RSessionBase::SendReceive(EDmCancelTransition);
   336 		if (r != KErrNone)
   337 			__DM_PANIC(r);
   338 		}
   339 	}
   340 
   341 void RDmManagerSession::CancelObserver()
   342 	{
   343 	if (Handle() != KNullHandle)
   344 		{
   345 		TInt r = RSessionBase::SendReceive(EDmObserverCancel);
   346 		if (r != KErrNone)
   347 			__DM_PANIC(r);
   348 		}
   349 	}
   350 
   351 void RDmManagerSession::RequestSystemTransition(
   352 	TDmDomainState aState,
   353 	TDmTraverseDirection aDirection,
   354 	TRequestStatus& aStatus)
   355 	{
   356 	__DM_ASSERT(Handle() != KNullHandle);
   357 
   358 	TIpcArgs a(aState, aDirection);
   359 	RSessionBase::SendReceive(EDmRequestSystemTransition, a, aStatus);
   360 	}
   361 
   362 TInt RDmManagerSession::AddDomainHierarchy(TDmHierarchyId aHierarchyId)
   363 	{
   364 	__DM_ASSERT(Handle() != KNullHandle);
   365 
   366 	TIpcArgs a( (TInt)aHierarchyId);
   367 	TInt r = RSessionBase::SendReceive(EDmHierarchyAdd, a);
   368 
   369 	return r;
   370 	}
   371 
   372 TInt RDmManagerSession::GetTransitionFailureCount()
   373 	{
   374 	__DM_ASSERT(Handle() != KNullHandle);
   375 
   376 	return RSessionBase::SendReceive(EDmGetTransitionFailureCount);
   377 	}
   378 
   379 TInt RDmManagerSession::GetTransitionFailures(RArray<const TTransitionFailure>& aTransitionFailures)
   380 	{
   381 	__DM_ASSERT(Handle() != KNullHandle);
   382 
   383 	aTransitionFailures.Reset();
   384 
   385 	TInt err = KErrNone;
   386 
   387 	TInt failureCount = GetTransitionFailureCount();
   388 	if (failureCount <= 0)
   389 		return failureCount;
   390 
   391 	TTransitionFailure* failures = new TTransitionFailure[failureCount];
   392 	if(failures == NULL)
   393 		return(KErrNoMemory);
   394 	TPtr8 dataPtr(reinterpret_cast<TUint8*>(failures), failureCount * sizeof(TTransitionFailure));
   395 
   396 	TIpcArgs a(&dataPtr);
   397 	err = RSessionBase::SendReceive(EDmGetTransitionFailures, a);
   398 	
   399 	if (err == KErrNone)
   400 		{
   401 		for (TInt i=0; i<failureCount; i++)
   402 			aTransitionFailures.Append(failures[i]);
   403 		}
   404 
   405 	delete [] failures;
   406 
   407 	return err;
   408 	}
   409 
   410 TInt RDmManagerSession::StartObserver(TDmDomainId aDomainId, TDmNotifyType aNotifyType)
   411 	{
   412 	__DM_ASSERT(Handle() != KNullHandle);
   413 	
   414 	TIpcArgs a(aDomainId,aNotifyType);
   415 	return(RSessionBase::SendReceive(EDmObserverStart,a));
   416 	}
   417 
   418 void RDmManagerSession::GetNotification(TRequestStatus& aStatus)
   419 	{
   420 	__DM_ASSERT(Handle() != KNullHandle);
   421 	RSessionBase::SendReceive(EDmObserverNotify,aStatus);
   422 	}
   423 	
   424 TInt RDmManagerSession::GetEventCount()
   425 	{
   426 	__DM_ASSERT(Handle() != KNullHandle);
   427 	return(RSessionBase::SendReceive(EDmObserverEventCount));
   428 	}
   429 
   430 TInt RDmManagerSession::GetEvents(RArray<const TTransInfo>& aTransitions)
   431 	{
   432 	__DM_ASSERT(Handle() != KNullHandle);
   433 
   434 	aTransitions.Reset();
   435 
   436 
   437 	TInt count = GetEventCount();
   438 	// This shouldn't happen unless something gone terribly wrong
   439 	if (count <= 0)
   440 		return KErrGeneral;
   441 
   442 	TTransInfo* trans = new TTransInfo[count];
   443 	if(trans == NULL)
   444 		return(KErrNoMemory);
   445 	
   446 	TPtr8 dataPtr(reinterpret_cast<TUint8*>(trans), count * sizeof(TTransInfo));
   447 
   448 	TIpcArgs a(&dataPtr);
   449 	TInt ret=RSessionBase::SendReceive(EDmObserverGetEvent, a);
   450 	
   451 	if(ret==KErrNone)
   452 		{
   453 		for (TInt i=0; i<count; i++)
   454 			aTransitions.Append(trans[i]);
   455 		}
   456 	
   457 	delete [] trans;
   458 	return ret;
   459 	
   460 	}
   461 
   462 TInt RDmManagerSession::ObserverDomainCount()
   463 	{
   464 	__DM_ASSERT(Handle() != KNullHandle);
   465 	return(RSessionBase::SendReceive(EDmObserveredCount));
   466 	}
   467 
   468 /**
   469 @internalAll
   470 @released
   471 */
   472 EXPORT_C TInt RDmDomainManager::WaitForInitialization()
   473 	{
   474 	RProperty prop;
   475 	TInt r = prop.Attach(KUidDmPropertyCategory, KDmPropertyKeyInit);
   476 	if (r != KErrNone)
   477 		return r;
   478 
   479 #ifdef _DEBUG
   480 	TInt count = RThread().RequestCount();
   481 #endif
   482 
   483 	TRequestStatus status;
   484 	for (;;)
   485 		{
   486 		prop.Subscribe(status);
   487 		TInt value;
   488 		r = prop.Get(value);
   489 		if (r == KErrNone)
   490 			{
   491 			if (value) break; // initialized
   492 			// property exists but the server is not intialized yet
   493 			}
   494 		else
   495 			{
   496 			if (r != KErrNotFound) break; // error
   497 			// property doesn't exist yet
   498 			}
   499 		User::WaitForRequest(status);
   500 		if (status.Int() != KErrNone)
   501 			break;	// error
   502 		}
   503 
   504 	if (status.Int() == KRequestPending)
   505 		{
   506 		prop.Cancel();
   507 		User::WaitForRequest(status);
   508 		}
   509 	prop.Close();
   510 
   511 	__DM_ASSERT(RThread().RequestCount() == count);
   512 
   513 	return r;
   514 	}
   515 
   516 
   517 
   518 
   519 /**
   520 Opens a controlling connection to the standard power domain hierarchy
   521 in the domain manager.
   522 
   523 The domain manger allows only one open connection at any one time to the 
   524 power domain hierarchy.
   525 Connection is usually made by the power policy entity.
   526 
   527 @return KErrNone, if successful; otherwise one of the other system-wide
   528         or the domain manager specific error codes.
   529         
   530 @see KDmErrAlreadyJoin   
   531 */
   532 EXPORT_C TInt RDmDomainManager::Connect()
   533 	{
   534 	return iSession.Connect(KDmHierarchyIdPower);
   535 	}
   536 
   537 
   538 
   539 
   540 /**
   541 Opens a controlling connection to a specific domain hieararchy owned 
   542 by the domain manager.
   543 
   544 The domain manger allows only one open connection at any one time to a 
   545 particular hierarchy.
   546 
   547 @param	aHierarchyId	The Id of the domain hierarchy to connect to.
   548 
   549 @return KErrNone, if successful; otherwise one of the other system-wide
   550         or domain manager specific error codes.
   551         
   552 @see KDmErrAlreadyJoin
   553 @see KErrBadHierarchyId       
   554 */
   555 EXPORT_C TInt RDmDomainManager::Connect(TDmHierarchyId aHierarchyId)
   556 
   557 	{
   558 	return iSession.Connect(aHierarchyId);
   559 	}
   560 
   561 
   562 
   563 
   564 /**
   565 Closes this connection to the domain manager.
   566 	
   567 If there is no existing connection, then it returns silently.
   568 */
   569 EXPORT_C void RDmDomainManager::Close()
   570 	{
   571 	iSession.Close();
   572 	}
   573 
   574 
   575 
   576 
   577 /**
   578 Requests a system-wide power state transition.
   579 
   580 The domain hierarchy is traversed in the default direction
   581 		
   582 @param aState   The target power state.
   583 @param aStatus  The request status object for this asynchronous request.
   584 
   585 @see RDmDomainManager::CancelTransition()
   586 */
   587 EXPORT_C void RDmDomainManager::RequestSystemTransition(TPowerState aState, TRequestStatus& aStatus)
   588 	{
   589 	if (aState == EPwActive)
   590 		{
   591 		TRequestStatus* status = &aStatus;
   592 		User::RequestComplete(status, KErrArgument);
   593 		return;
   594 		}
   595 	RequestSystemTransition((TDmDomainState) aState, ETraverseDefault, aStatus);
   596 	}
   597 
   598 
   599 
   600 
   601 /**
   602 Requests a system-wide power shutdown.
   603 
   604 This is a request to change the system's power state to EPwOff.
   605 This call does not return; the system can only return by rebooting.
   606 */
   607 EXPORT_C void RDmDomainManager::SystemShutdown()
   608 	{
   609 	TRequestStatus status;
   610 	RequestSystemTransition((TDmDomainState) EPwOff, ETraverseDefault, status);
   611 	User::WaitForRequest(status);
   612 	__DM_ASSERT(0);
   613 	}
   614 
   615 
   616 
   617 
   618 /**
   619 Requests a domain state transition.
   620 
   621 The domain hierarchy is traversed in the default direction.
   622 
   623 @param aDomainId The Id of the domain for which the state transition
   624                  is being requested.
   625 @param aState    The target state.
   626 @param aStatus   The request status object for this asynchronous request.
   627 
   628 @see RDmDomainManager::CancelTransition()
   629 */
   630 EXPORT_C void RDmDomainManager::RequestDomainTransition(
   631 	TDmDomainId aDomainId, 
   632 	TPowerState aState, 
   633 	TRequestStatus& aStatus)
   634 	{
   635 	RequestDomainTransition(aDomainId,(TDmDomainState)  aState, ETraverseDefault, aStatus);
   636 	}
   637 
   638 
   639 
   640 
   641 /**
   642 Cancels a state transition, whether initiated by a call
   643 to RequestSystemTransition() or RequestDomainTransition().
   644 
   645 An outstanding state transition request completes with KErrCancel.
   646 */
   647 EXPORT_C void RDmDomainManager::CancelTransition()
   648 	{
   649 	iSession.CancelTransition();
   650 	}
   651 
   652 
   653 
   654 
   655 /**
   656 Requests a system-wide state transition.
   657 
   658 The domain hierarchy is traversed in the specified direction.
   659 		
   660 @param aState   The target state.
   661 @param aDirection The direction in which to traverse the hierarchy
   662 @param aStatus  The request status object for this asynchronous request.
   663 
   664 @see RDmDomainManager::CancelTransition()
   665 
   666 @panic domainCli.cpp; assertion failed VARNUM if the numerical value of aDirection
   667        is greater than the value of ETraverseMax. NOTE: VARNUM is the line number
   668        in the source code and may change if the implementation changes.
   669 */
   670 EXPORT_C void RDmDomainManager::RequestSystemTransition(
   671 	TDmDomainState aState, 
   672 	TDmTraverseDirection aDirection, 
   673 	TRequestStatus& aStatus)
   674 	{
   675 	__DM_ASSERT(aDirection <= ETraverseMax);
   676 	iSession.RequestSystemTransition(aState, aDirection, aStatus);
   677 	}
   678 
   679 
   680 
   681 
   682 /**
   683 Requests a domain state transition.
   684 
   685 The domain hierarchy is traversed in the specified direction
   686 
   687 @param aDomainId The Id of the domain for which the state transition
   688                  is being requested.
   689 @param aState    The target state.
   690 @param aDirection The direction in which to traverse the hierarchy.
   691 @param aStatus   The request status object for this asynchronous request.
   692 
   693 @see RDmDomainManager::CancelTransition()
   694 
   695 @panic domainCli.cpp; assertion failed VARNUM if the numerical value of aDirection
   696        is greater than the value of ETraverseMax. NOTE: VARNUM is the line number
   697        in the source code and may change if the implementation changes.
   698 */
   699 EXPORT_C void RDmDomainManager::RequestDomainTransition(
   700 	TDmDomainId aDomainId, 
   701 	TDmDomainState aState, 
   702 	TDmTraverseDirection aDirection,
   703 	TRequestStatus& aStatus)
   704 	{
   705 	__DM_ASSERT(aDirection <= ETraverseMax);
   706 	iSession.RequestDomainTransition(aDomainId, aState, aDirection, aStatus);
   707 	}
   708 
   709 
   710 
   711 
   712 /**
   713 Adds a domain hierarchy to the domain manager.
   714 
   715 @param aHierarchyId The Id of the domain hierarchy to be added.
   716 
   717 @return	KErrNone if successful; otherwise one of the other system-wide
   718         or domain manager specific error codes.
   719 */
   720 EXPORT_C TInt RDmDomainManager::AddDomainHierarchy(TDmHierarchyId aHierarchyId)
   721 	{
   722 	RDmManagerSession	session;
   723 	TInt r = session.Connect();
   724 	if (r != KErrNone)
   725 		return r;
   726 	r = session.AddDomainHierarchy(aHierarchyId);
   727 	session.Close();
   728 	return r;
   729 	}
   730 
   731 
   732 
   733 /**
   734 Requests a list of transition failures since the last transition request.
   735 
   736 @param aTransitionFailures A client-supplied array of TTransitionFailure objects which 
   737 		on exit will contain the failures that have occurred since the last transition 
   738 		request. 
   739 @pre	The session must be connected.
   740 
   741 @return KErrNone, if successful; otherwise one of the other system-wide
   742         or domain manager specific error codes.
   743 */
   744 EXPORT_C TInt RDmDomainManager::GetTransitionFailures(RArray<const TTransitionFailure>& aTransitionFailures)
   745 	{
   746 	return iSession.GetTransitionFailures(aTransitionFailures);
   747 	}
   748 
   749 
   750 
   751 /**
   752 Gets the number of transition failures since the last transition request.
   753 
   754 @return	The number of failures, if successful; otherwise one of the other system-wide
   755         or domain manager specific error codes.
   756 */
   757 EXPORT_C TInt RDmDomainManager::GetTransitionFailureCount()
   758 	{
   759 	return iSession.GetTransitionFailureCount();
   760 	}
   761 
   762 
   763 
   764 // CDmDomain
   765 
   766 /**
   767 Constructor.
   768 
   769 Adds this active object to the active scheduler. The priority of the active object
   770 is the standard value, i.e. CActive::EPriorityStandard.
   771 
   772 @param aHierarchyId The Id of the domain hierarchy to connect to.
   773 @param aDomainId	The Id of the domain to connect to.
   774 
   775 @see CActive
   776 @see CActive::TPriority
   777 */
   778 EXPORT_C CDmDomain::CDmDomain(TDmHierarchyId aHierarchyId, TDmDomainId aDomainId) : 
   779 	CActive(CActive::EPriorityStandard), 
   780 	iHierarchyId(aHierarchyId), 
   781 	iDomainId(aDomainId)
   782 	{
   783 	CActiveScheduler::Add(this);
   784 	}
   785 
   786 
   787 
   788 
   789 /**
   790 Destructor.
   791 
   792 Closes the session to the domain manager.
   793 */
   794 EXPORT_C CDmDomain::~CDmDomain()
   795 	{
   796 	Cancel();
   797 	iDomain.Close();
   798 	}
   799 
   800 
   801 
   802 
   803 /**
   804 Second-phase constructor.
   805 
   806 The function attempts to connect to the domain specified in the constructor.
   807 
   808 @leave One of the system-wide error codes
   809 */
   810 EXPORT_C void CDmDomain::ConstructL()
   811 	{
   812 	User::LeaveIfError(iDomain.Connect(iHierarchyId, iDomainId));
   813 	}
   814 
   815 
   816 
   817 
   818 /**
   819 Requests notification when the domain's state changes.
   820 
   821 RunL() will be called when this happens.
   822 */
   823 EXPORT_C void CDmDomain::RequestTransitionNotification()
   824 	{
   825 	__DM_ASSERT(!IsActive());
   826 	iDomain.RequestTransitionNotification(iStatus);
   827 	SetActive();
   828 	}
   829 
   830 
   831 
   832 
   833 /**
   834 Cancels an outstanding notification request.
   835 
   836 Any outstanding notification request completes with KErrCancel.
   837 */
   838 EXPORT_C void CDmDomain::DoCancel()
   839 	{
   840 	iDomain.CancelTransitionNotification();
   841 	}
   842 
   843 
   844 
   845 
   846 /**
   847 Acknowledges the last state change.
   848 	
   849 An application must acknowledge that it has performed all actions required
   850 by the last known state of the domain.
   851 
   852 @param aError	The error to return to the domain manager. The client should
   853 				set this to KErrNone if it successfully transitioned to the 
   854 				new state or to one of the system-wide error codes.
   855 */
   856 EXPORT_C void CDmDomain::AcknowledgeLastState(TInt aError)
   857 	{
   858 	iDomain.AcknowledgeLastState(aError);
   859 	}
   860 
   861 
   862 
   863 
   864 /**
   865 Gets the domain's state.
   866 	
   867 An application normally calls this function after a notification request
   868 has completed. It then performs any application-dependent action demanded by
   869 the state, and then acknowledges the state transition.
   870 
   871 @return The connected domain's state.
   872 */
   873 EXPORT_C TDmDomainState CDmDomain::GetState()
   874 	{
   875 	return iDomain.GetState();
   876 	}
   877 
   878 // CDmDomainManager
   879 
   880 /**
   881 Constructor.
   882 
   883 Adds this active object to the active scheduler.
   884 
   885 @param aHierarchyId The Id of the domain hierarchy to connect to
   886 */
   887 EXPORT_C CDmDomainManager::CDmDomainManager(TDmHierarchyId aHierarchyId) : 
   888 	CActive(CActive::EPriorityStandard), 
   889 	iHierarchyId(aHierarchyId)
   890 	{
   891 	CActiveScheduler::Add(this);
   892 	}
   893 
   894 
   895 
   896 
   897 /**
   898 Destructor.
   899 
   900 Closes the session to the domain manager.
   901 */
   902 EXPORT_C CDmDomainManager::~CDmDomainManager()
   903 	{
   904 	Cancel();
   905 	iManager.Close();
   906 	}
   907 
   908 
   909 
   910 
   911 /**
   912 The second-phase constructor.
   913 
   914 This function attempts to connect to the hierarchy 
   915 specified in the constructor.
   916 
   917 @leave One of the system-wide error codes.
   918 */
   919 EXPORT_C void CDmDomainManager::ConstructL()
   920 	{
   921 	User::LeaveIfError(iManager.Connect(iHierarchyId));
   922 	}
   923 
   924 
   925 
   926 
   927 /**
   928 Requests a system-wide state transition.
   929 
   930 The domain hierarchy is traversed in the specified direction
   931 		
   932 @param aState   The target state.
   933 @param aDirection The direction in which to traverse the hierarchy.
   934 */
   935 EXPORT_C void CDmDomainManager::RequestSystemTransition(TDmDomainState aState, TDmTraverseDirection aDirection)
   936 	{
   937 	__DM_ASSERT(!IsActive());
   938 	iStatus = KRequestPending;
   939 	iManager.RequestSystemTransition(aState, aDirection, iStatus);
   940 	SetActive();
   941 	}
   942 
   943 
   944 
   945 
   946 /**
   947 Requests a domain state transition.
   948 
   949 The domain hierarchy is traversed in the specified direction.
   950 
   951 @param aDomain The Id of the domain for which the state transition
   952                  is being requested.
   953 @param aState    The target state.
   954 @param aDirection The direction in which to traverse the hierarchy.
   955 */
   956 EXPORT_C void CDmDomainManager::RequestDomainTransition(TDmDomainId aDomain, TDmDomainState aState, TDmTraverseDirection aDirection)
   957 	{
   958 	__DM_ASSERT(!IsActive());
   959 	iStatus = KRequestPending;
   960 	iManager.RequestDomainTransition(aDomain, aState, aDirection, iStatus);
   961 	SetActive();
   962 	}
   963 
   964 
   965 
   966 
   967 /**
   968 Adds a domain hierarchy to the domain manager.
   969 
   970 @param aHierarchyId The Id of the domain hierarchy to add
   971 
   972 @return	KErrNone if successful; otherwise one of the other system-wide
   973         or domain manager specific error codes.
   974 */
   975 EXPORT_C TInt CDmDomainManager::AddDomainHierarchy(TDmHierarchyId aHierarchyId)
   976 	{
   977 	RDmManagerSession	session;
   978 	TInt r = session.Connect();
   979 	if (r != KErrNone)
   980 		return r;
   981 	r = session.AddDomainHierarchy(aHierarchyId);
   982 	session.Close();
   983 	return r;
   984 
   985 	}
   986 
   987 
   988 
   989 
   990 /**
   991 Cancels a pending event.
   992 */
   993 EXPORT_C void CDmDomainManager::DoCancel()
   994 	{
   995 	iManager.CancelTransition();
   996 	}
   997 
   998 
   999 
  1000 
  1001 /**
  1002 Requests a list of transition failures since the last transition request.
  1003 
  1004 @param aTransitionFailures A client-supplied array of TTransitionFailure objects which 
  1005 		on exit will contain the failures that have occurred since the last transition 
  1006 		request. 
  1007 @pre	The session must be connected.
  1008 
  1009 @return KErrNone, if successful; otherwise one of the other system-wide
  1010         or domain manager specific error codes.
  1011 */
  1012 EXPORT_C TInt CDmDomainManager::GetTransitionFailures(RArray<const TTransitionFailure>& aTransitionFailures)
  1013 	{
  1014 	return iManager.GetTransitionFailures(aTransitionFailures);
  1015 	}
  1016 
  1017 
  1018 
  1019 
  1020 /**
  1021 Gets the number of transition failures since the last transition request.
  1022 
  1023 @return	The number of failures if successful, otherwise one of the other system-wide
  1024         or domain manager specific error codes.
  1025 */
  1026 EXPORT_C TInt CDmDomainManager::GetTransitionFailureCount()
  1027 	{
  1028 	return iManager.GetTransitionFailureCount();
  1029 	}
  1030 
  1031 
  1032 
  1033 
  1034 CHierarchyObserver::CHierarchyObserver(MHierarchyObserver& aHierarchyObserver, TDmHierarchyId aHierarchyId):
  1035 	CActive(CActive::EPriorityStandard), 
  1036 	iHierarchyId(aHierarchyId),
  1037 	iObserver(aHierarchyObserver)
  1038 	{
  1039 	iTransitionEvents.Reset();
  1040 	CActiveScheduler::Add(this);
  1041 	}
  1042 
  1043 
  1044 
  1045 
  1046 /**
  1047 Constructs a new observer on the domain hierarchy.
  1048 
  1049 Note that only one observer per domain hierarchy is allowed.
  1050 
  1051 @param	aHierarchyObserver	The implementation of the interface to the domain manager.
  1052 @param	aHierarchyId		The Id of the domain hierarchy.
  1053 
  1054 @return The newly created CHierarchyObserver object.
  1055 */
  1056 EXPORT_C CHierarchyObserver* CHierarchyObserver::NewL(MHierarchyObserver& aHierarchyObserver,TDmHierarchyId aHierarchyId)
  1057 	{
  1058 	CHierarchyObserver* observer=new(ELeave)CHierarchyObserver(aHierarchyObserver,aHierarchyId);
  1059 
  1060 	CleanupStack::PushL(observer);
  1061 	User::LeaveIfError(observer->iSession.ConnectObserver(aHierarchyId));
  1062 	CleanupStack::Pop();
  1063 	
  1064 	return(observer);
  1065 	}
  1066 
  1067 
  1068 
  1069 
  1070 /**
  1071 Destructor.
  1072 
  1073 Frees resources prior to destruction of the object.
  1074 */
  1075 EXPORT_C CHierarchyObserver::~CHierarchyObserver()
  1076 	{
  1077 	Cancel();
  1078 	iSession.Close();
  1079 	iTransitionEvents.Reset();
  1080 	}
  1081 
  1082 void CHierarchyObserver::DoCancel()
  1083 	{
  1084 	iObserverStarted=EFalse;
  1085 	iSession.CancelObserver();
  1086 	}
  1087 
  1088 void CHierarchyObserver::RunL()
  1089 //
  1090 // Process the reply to client's request for domain transition/failure
  1091 //
  1092 	{
  1093 
  1094 	TInt ret= iSession.GetEvents(iTransitionEvents);
  1095 	
  1096 	User::LeaveIfError(ret);
  1097 	
  1098 	TInt count = iTransitionEvents.Count();
  1099 
  1100 	for(TInt i=0;i<count;i++)
  1101 		{
  1102 		if(iTransitionEvents[i].iError==KErrNone)
  1103 			iObserver.TransProgEvent(iTransitionEvents[i].iDomainId,iTransitionEvents[i].iState);
  1104 		else if(iTransitionEvents[i].iError==KDmErrOutstanding)
  1105 			iObserver.TransReqEvent(iTransitionEvents[i].iDomainId,iTransitionEvents[i].iState);
  1106 		else
  1107 			iObserver.TransFailEvent(iTransitionEvents[i].iDomainId,iTransitionEvents[i].iState,iTransitionEvents[i].iError);
  1108 		}
  1109 
  1110 	GetNotification();
  1111 	}
  1112 
  1113 
  1114 
  1115 
  1116 /**
  1117 Starts the observer. 
  1118 
  1119 @param	aDomainId		The Id of the domain to which the obsever is attached.
  1120 @param	aNotifyType		The type of notifications of interest to the observer.
  1121 
  1122 @return KErrNone on successful start, otherwise one of the other system wide error codes.
  1123 */
  1124 EXPORT_C TInt CHierarchyObserver::StartObserver(TDmDomainId aDomainId, TDmNotifyType aNotifyType)
  1125 	{
  1126 	iNotifyType=aNotifyType;
  1127 	iDomainId=aDomainId;
  1128 	
  1129 	TInt ret=iSession.StartObserver(iDomainId, iNotifyType);
  1130 	if(ret!=KErrNone)
  1131 		return ret;
  1132 	iObserverStarted=ETrue;
  1133 	GetNotification();
  1134 	return KErrNone;
  1135 	}
  1136 
  1137 
  1138 
  1139 
  1140 /**
  1141 Stops the observer. 
  1142 
  1143 @return KErrNone if successful; KDmErrBadSequence, if the observer 
  1144         has not already started.
  1145 */
  1146 EXPORT_C TInt CHierarchyObserver::StopObserver()
  1147 	{
  1148 	if(!iObserverStarted)
  1149 		return(KDmErrBadSequence);
  1150 	Cancel();
  1151 	return(KErrNone);
  1152 	}
  1153 
  1154 void CHierarchyObserver::GetNotification()
  1155 	{
  1156 	iSession.GetNotification(iStatus);
  1157 	SetActive();
  1158 	}
  1159 
  1160 /**
  1161 Gets the number of domains that are being observed.
  1162 
  1163 This value is the number of children of the domain member to which the observer
  1164 is attached, including itself. 
  1165 
  1166 @return The number of observed domain members.
  1167         One of the other system wide error codes may be returned on failure;
  1168         specifically KErrNotFound if the observer is not already started.
  1169 */
  1170 EXPORT_C TInt CHierarchyObserver::ObserverDomainCount()
  1171 	{
  1172 	if(!iObserverStarted)
  1173 		return KErrNotFound;
  1174 	return(iSession.ObserverDomainCount());	
  1175 	}