genericservices/taskscheduler/SCHSVR/SchSSAMan.cpp
changeset 0 e4d67989cc36
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/genericservices/taskscheduler/SCHSVR/SchSSAMan.cpp	Tue Feb 02 02:01:42 2010 +0200
@@ -0,0 +1,232 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "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:
+// Implementation of CSchStartupStateMgr class which connects to
+// the Domain manager to keep aware of the current start-up
+// state and distributes the state changes to registered observers.
+// 
+//
+
+/**
+ @file
+ @internalComponent
+*/
+
+#include "SchSSAMan.h"
+#include "SchLogger.h"
+
+/**
+constructor of CSchStartupStateMgr
+@internalComponent
+*/
+CSchStartupStateMgr::CSchStartupStateMgr(TDmHierarchyId aHierarchyId, TDmDomainId aDomainId) :
+	CDmDomain(aHierarchyId,aDomainId),
+	iCurrentStartupState(EStartupStateUndefined)
+	 {
+	 }
+	 
+/**
+destructor of CSchStartupStateMgr
+@internalComponent
+*/
+CSchStartupStateMgr::~CSchStartupStateMgr()
+	{
+	Cancel();
+	iObserverList.Reset();
+	}
+	
+/**
+Getter
+@internalComponent
+@return the current startup state
+*/
+TStartupStateIdentifier CSchStartupStateMgr::CurrentStartupState()
+	{
+	return iCurrentStartupState;
+	}
+	
+/**
+updates the MSchStartupStateObserver objects.
+@internalComponent
+*/
+void CSchStartupStateMgr::UpdateStateAwareObjectsL(TStartupStateIdentifier aKnownState)
+	{
+	for (TInt i = 0; i < iObserverList.Count(); i++)
+		{
+		iObserverList[i]->ProcessSSAEventL(aKnownState);
+		}
+	}
+	
+/**
+This method takes a a startup state which can be user defined
+state and maps it to a known startup state (KSS). KSS are
+Symbian defined states: undefined, critical static, critical dynamic,
+and non-critical.
+User defined states are refered to as USS - unknown startup state.
+
+@internalComponent
+*/
+TStartupStateIdentifier CSchStartupStateMgr::GetKnownStartupState(TDmDomainState aStartupState)
+	{
+	TStartupStateIdentifier knownStartupState = iCurrentStartupState;
+	
+	if (aStartupState >= EStartupStateNonCritical)
+		{
+		knownStartupState = EStartupStateNonCritical;
+		}
+	else if(aStartupState >= EStartupStateCriticalDynamic)
+		{
+		knownStartupState = EStartupStateCriticalDynamic;
+		}
+	else if(aStartupState >= EStartupStateCriticalStatic)
+		{
+		knownStartupState = EStartupStateCriticalStatic;
+		}
+	else 
+		{
+		knownStartupState = EStartupStateUndefined;
+		}
+	
+	return knownStartupState;
+	}
+
+/**
+Register the MSchStartupStateObserver object with the CServerStartupMgr.
+@internalComponent
+@param aObs the pointer to the MStartupStateObserver object to be registered with CServerStartupMgr.
+*/
+void CSchStartupStateMgr::RegisterObserverL(const MSchStartupStateObserver* aObs)
+	{
+	User::LeaveIfError(iObserverList.Append(aObs));
+	}
+
+/**
+Handle the error if RunL leaves. Just tell the observers that
+we have reached the final state.
+
+@internalComponent
+@param aError error code generated by the RunL(), not used here.
+@return KErrNone to avoid CActiveScheduler to panic.
+*/
+TInt CSchStartupStateMgr::RunError(TInt /*aError*/)
+	{
+	LOGSTRING("CSchStartupStateMgr::RunL() leaves, set SS to final state.");
+	TRAP_IGNORE(UpdateStateAwareObjectsL(KSchFinalStartupState));
+	return KErrNone;
+	}
+	
+/**
+Finsish constructing the CSchStartupStateMgr and start
+interacting with Domain Manager to receive startup state
+changes. 
+All observers should have been registered before calling this method
+
+@internalComponent
+*/
+void CSchStartupStateMgr::InitialiseL()
+	{
+	TRAPD(err, CDmDomain::ConstructL());
+	if (err != KErrNone)
+		{
+		// the ConstructL leaves, go to final state
+		LOGSTRING2("CDmDomain::ConstructL leaves with %d. Goto final state", err);
+		UpdateStateAwareObjectsL(KSchFinalStartupState);
+		iCurrentStartupState = KSchFinalStartupState;
+		return;
+		}
+			
+	// Typical pattern of using P&S is to subscribe first then get
+	// current state. Example implementation given
+	// in SSA Adaptation How-to also does it this way.
+	RequestTransitionNotification();
+	
+	// get the start up state from the Domain Manager.
+	TDmDomainState rawstate = GetState();
+
+	// rawstate may be user defined. Map to known states.
+	TStartupStateIdentifier nextKnownState = GetKnownStartupState(rawstate);
+		
+	// NB: nextKnownState can be KStartupStateUndefined for 2 reasons.
+	// One is rawstate == 0 which we must check first. Second:
+	// rawstate is user defined values lower than critical static. In
+	// the second case we must wait for next state change.
+	if (rawstate == EStartupStateUndefined || 
+		nextKnownState == KSchFinalStartupState)
+		{
+		// If either something wrong with DM or final state is reached,
+		// go to final state
+		iCurrentStartupState = KSchFinalStartupState;
+		UpdateStateAwareObjectsL(KSchFinalStartupState);
+		Cancel();
+		return;
+		}
+			
+	iCurrentStartupState = nextKnownState;
+	}
+
+/**
+Executed when the startup state change is done, it does the 
+same thing as the method InitialiseL() does
+@internalComponent
+*/
+void CSchStartupStateMgr::RunL()
+	{
+	if(iStatus != KErrNone) // something wrong with the RequestTransitionNotification().
+		{
+		AcknowledgeLastState(iStatus.Int()); //Acknowledge the domainmanager in case of leaving, this to avoid the acknowledgement in RunError()
+		User::LeaveIfError(iStatus.Int()); //RunError will handle this.
+		}
+
+	RequestTransitionNotification();
+
+	TDmDomainState rawstate = GetState();
+
+	// Must first check the case rawstate == undefined and deal with it here.
+	// GetKnowStartupState maps 1 to 15 to EStartupStateUndefined
+	// which means a SS before critical static. It does not mean go
+	// to final state.
+
+	//If the rawstate is EStartupStateUndefined there must be sth wrong.
+	if(rawstate == EStartupStateUndefined) 
+		{
+		Cancel();
+		AcknowledgeLastState(KErrBadHandle);
+		User::Leave(KErrBadHandle); //RunError will handle this.
+		}
+
+	// get the known state			
+	TStartupStateIdentifier nextKnownState = GetKnownStartupState(rawstate);
+	
+	//Tell domain manager that we have processed the last state change before starting any time consuming work.
+	AcknowledgeLastState(KErrNone);
+	
+	//Sleep 2 tickperiods this allows the acknowledgement reach the domain manager.
+	TTimeIntervalMicroSeconds32 tickPeriod;
+	UserHal::TickPeriod(tickPeriod);	
+	User::After(2*tickPeriod.Int()); 
+
+	// Schsvr only want to know transition to non-critical.
+	// Ignore all states below that level.
+	if (iCurrentStartupState < KSchFinalStartupState && nextKnownState == KSchFinalStartupState)
+		{
+		UpdateStateAwareObjectsL(nextKnownState);
+		}
+	
+	iCurrentStartupState = nextKnownState;	
+	
+	//do not request transition notification if we have reached the last state
+	if(iCurrentStartupState == KSchFinalStartupState)
+		{
+		Cancel();
+		}
+	}