resourcemgmt/powerandmemorynotificationservice/src/shutdownsrv.cpp
changeset 0 4e1aa6a622a0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/resourcemgmt/powerandmemorynotificationservice/src/shutdownsrv.cpp	Tue Feb 02 00:53:00 2010 +0200
@@ -0,0 +1,760 @@
+// Copyright (c) 1997-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:
+//
+
+#ifndef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include "shutdownsrv.h"
+#else //SYMBIAN_ENABLE_SPLIT_HEADERS
+#include "shutdownsess.h"
+#endif //SYMBIAN_ENABLE_SPLIT_HEADERS
+#include "savenotf.h"
+#include "savepriv.h"
+#include "shutdowntimer.h"
+#include <hal.h>
+#include <f32file.h>
+#include <bautils.h>
+
+#ifdef SYMBIAN_SSM_GRACEFUL_SHUTDOWN
+#include <s32mem.h>
+#include <ssm/ssmpatchableconstants.h>
+#endif
+
+//The function used to start the profiler, while profiling the shutdown.
+#ifdef __PROFILE_SHUTDOWN
+_LIT(KProfilerCmd,"start -noui");
+void StartProfiler()
+	{
+	RProcess p;
+	TInt r=p.Create(KProfilerName,KProfilerCmd);
+	if (r==KErrNone)
+		{
+		p.Resume();
+		p.Close();
+		}
+	}
+#endif
+
+//The function used to unload the profiler, while profiling the shutdown.
+#ifdef __PROFILE_SHUTDOWN
+void UnloadProfiler()
+	{
+	TFullName name;
+	TFindServer findSvr(KProfilerName);
+	Profiler::Unload();
+	while(findSvr.Next(name) == KErrNone)
+		{
+		User::After(1000000);
+		findSvr.Find(KProfilerName);
+		}
+	}
+#endif
+
+//
+// class CServShutdownServer
+//
+
+/**
+Standard phase-one factory method for creating CServShutdownServer instances.
+@return A newly-constructed shutdown server object.
+@leave Some system-wide error codes including KErrNoMemory.
+*/
+EXPORT_C CServShutdownServer* CServShutdownServer::NewL()
+	{ // static
+	CServShutdownServer* self=new(ELeave) CServShutdownServer(CActive::EPriorityStandard);
+	return self;
+	}
+
+/**
+Destructor.
+Releases CShutdownTimer object if it has been allocated.
+*/
+EXPORT_C CServShutdownServer::~CServShutdownServer()
+	{
+	delete iShutdownTimer;
+	}
+
+/**
+This method iterates through all session instances and checks that all they have pending
+requests (which means that all clients have completed their powerdown related processing
+and re-registered itself back to the shutdown server).. If that's true (all sessions have
+pending requests) and iPowerOff flag is nonzero, the method will call SwitchOff() - the
+power will be switched off. 
+@see CServShutdownServer::SwitchOff()
+@see CServShutdownSession::HasPendingRequest()
+*/
+EXPORT_C void CServShutdownServer::HandlePowerNotifRequest(const RThread& /*aClient*/)
+	{
+	// if all sessions have a pending request then they've all saved their data and we can switch off
+	TBool completed=ETrue;
+	TDblQueIter<CSession2> iter(iSessionIter);
+	iter.SetToFirst();
+
+	for (CSession2* session=iter++; session!=NULL; session=iter++)
+		{
+		if (!static_cast<CServShutdownSession*>(session)->HasPendingRequest())
+			{
+			completed=EFalse;
+			break;
+			}
+		}
+	if (completed && iPowerOff)
+		{
+		SwitchOff();
+		}
+	}
+
+/**
+This method will call SwitchOff(), if there are no sessions, so - no clients.
+If there are registered clients (sessions), the method will call CServShutdownSession::NotifySave()
+for each of them.
+If the timer object has been initialised, it calculates the shutdown timeout value 
+and adds the timer to the active scheduler.
+@param aSaveType The action, which will be given to the clients, when calling their 
+                 MSaveObserver::SaveL() implementations.
+@see CServShutdownServer::SwitchOff()
+@see CServShutdownSession::NotifySave()
+*/
+EXPORT_C void CServShutdownServer::NotifySave(MSaveObserver::TSaveType aSaveType)
+	{
+	TDblQueIter<CSession2> iter(iSessionIter);
+	iter.SetToFirst();
+	CSession2* p=iter++;
+	if (p==NULL)
+		{
+		if (iPowerOff)
+			{
+			SwitchOff();
+			}
+		}
+	else
+		{
+		TInt numClients = 0;
+
+		iter.SetToFirst();
+	    for (CSession2* session=iter++; session!=NULL; session=iter++)
+			{
+			static_cast<CServShutdownSession*>(session)->NotifySave(aSaveType);
+			numClients++;  
+			}
+			
+		if(iShutdownTimer && !iShutdownTimer->IsActive())
+			{
+			iShutdownTimer->Start(numClients);
+			}
+		}
+	}
+
+/**
+@return Non-zero If the powerdown sequence has been initiated.
+*/
+EXPORT_C TBool CServShutdownServer::IsPowerOff() const
+	{
+	return iPowerOff;
+	}
+
+/**
+Cancels any power off request.
+*/
+EXPORT_C void CServShutdownServer::CancelPowerOff()
+	{
+	iPowerOff=EFalse;
+	
+	// Cancel the timer.
+	if (iShutdownTimer)
+		{
+		iShutdownTimer->Cancel();
+		}
+	}
+
+/**
+@param aPriority The active object priority.
+*/
+EXPORT_C CServShutdownServer::CServShutdownServer(TInt aPriority):
+	CServer2(aPriority), iShutdownTimer(0)
+	{
+    }
+
+/**
+Completes the server construction by adding the server to the active scheduler and initializing the
+CShutdownTimer object if applicable.
+@leave See CServer2::StartL() leave error codes.
+@see CServer2::StartL()
+@panic KErrNotSupported Incorrect patchable variables configuration.
+*/
+EXPORT_C void CServShutdownServer::ConstructL()
+	{
+	iShutdownTimer = CShutdownTimer::NewL(*this);
+	#ifdef TEST_SHUTDOWN_SERVER 
+	StartL(__TEST_SHUTDOWN_SERVER_NAME);
+	#else
+	StartL(__SHUTDOWN_SERVER_NAME);
+	#endif
+	}
+
+/**
+This method switches off the power using the Power API.
+If there is a defined SYSLIBS_TEST macro, the method does nothing.
+*/
+void CServShutdownServer::DoSwitchOff()
+	{
+	//Finalize the drives before shutting down
+	RFs fs;
+	TInt r=fs.Connect(); 
+	if (r==KErrNone) 
+		{
+		//Ignore the error code, as it is not a critical call
+		r=fs.FinaliseDrives();
+		fs.Close();
+		}
+#ifdef 	SYSLIBS_TEST 
+		// Test mode, only prints debug message.
+		RDebug::Printf("CServShutdownServer::SwitchOff() gets run in SYSLIBS_TEST mode.\n");
+#else 	//SYSLIBS_TEST
+	// restart or standby/shutdown using Power API 
+	if (Power::EnableWakeupEvents(iPowerEvent) == KErrNone)
+		{
+		// Prepare to wake up if power event is standby
+		TRequestStatus s;
+		Power::RequestWakeupEventNotification(s);
+		Power::PowerDown(); // if event is Restart, this function should never return
+		User::WaitForRequest(s);
+		}
+#endif //SYSLIBS_TEST
+	} 
+void CServShutdownServer::SwitchOff()
+	{
+	// If the timer has applied, cancel any outstanding requests, 
+	// no matter SwitchOff() has been triggered by the timer or the shutdown server.
+	if (iShutdownTimer)
+		{
+		iShutdownTimer->Cancel();
+		}
+
+	if (iPowerOff)
+		{
+#ifdef __PROFILE_SHUTDOWN
+		UnloadProfiler();
+#endif //__PROFILE_SHUTDOWN
+		}
+	//SSM shutdown is used only when patchable constant KSsmGracefulShutdown is true 
+#ifdef SYMBIAN_SSM_GRACEFUL_SHUTDOWN
+	if (iPowerOff && !IsSsmGracefulShutdown())
+#else
+	if (iPowerOff)
+#endif
+		{
+		//Shutdown using old shutdownsrv, not SSM
+		DoSwitchOff();
+		}
+	iPowerOff = EFalse;
+	}
+
+/**
+This method creates a new server side session object.
+@param aVersion Shutdown server version number.
+@return A pointer to the created session object.
+@leave KErrNotSupported Unknown shutdown server version
+@leave Some system-wide error codes including KErrNoMemory.
+*/
+CSession2* CServShutdownServer::NewSessionL(const TVersion& aVersion,const RMessage2& /*aMessage*/) const
+	{
+	TVersion v(KShutdownMajorVN,KShutdownMinorVN,KShutdownBuildVN);
+	if (!User::QueryVersionSupported(v,aVersion))
+		User::Leave(KErrNotSupported);
+
+	CSession2* pSession = CServShutdownSession::NewL();
+	return pSession;
+	}
+
+/**
+This method has to be called, when the registered clients have to be notified that a 
+particular action has to be done, such as MSaveObserver::ESaveData, MSaveObserver::ESaveAll, 
+MSaveObserver::EReleaseRAM,...
+If this is a beginning of a powerdown sequence, the method will store the locales and the HAL
+properties.
+If the requested action is not MSaveObserver::ESaveNone, the method will call 
+CServShutdownServer::NotifySave().
+@param aAction The type of the requested action
+@param aPowerOff If it is non-zero, this is the beginning of a powerdown sequence.
+@param aEvent The type of the powerdown event (power off or restart)
+@leave KErrNotSupported Leaves if aEvent is invalid  
+@see CServShutdownServer::NotifySave()
+@see TPowerState
+*/
+EXPORT_C void CServShutdownServer::HandleShutdownEventL(MSaveObserver::TSaveType aAction,TBool aPowerOff, TPowerState aEvent)
+	{
+	if( aPowerOff )
+		{
+		__ASSERT_ALWAYS((aEvent>EPwActive)&&(aEvent<EPwLimit), User::Leave(KErrNotSupported));
+#ifdef __PROFILE_SHUTDOWN
+		StartProfiler();
+#endif
+
+#ifdef SYMBIAN_SSM_GRACEFUL_SHUTDOWN
+		if (!IsSsmGracefulShutdown())
+			{
+			// Save the state of the HAL
+			// The state of the locale should be saved before the HAL
+			BaflUtils::PersistLocale();
+			BaflUtils::PersistHAL();
+			}
+#else
+		// Save the state of the HAL
+		// The state of the locale should be saved before the HAL
+		BaflUtils::PersistLocale();
+		BaflUtils::PersistHAL();
+#endif
+		}
+
+	iPowerOff=aPowerOff;
+	iPowerEvent = aEvent;
+	// add LAF setting for powering down screen (& keyboard??)
+	if (aAction != MSaveObserver::ESaveNone)
+		{
+		NotifySave(aAction);
+		}
+	}
+
+/**
+This method returns an information about the shutdown status.
+@param aPowerOff An output parameter, where iPowerOff value will be stored. 
+                 It will be non-zero, if a powerdown sequence has been initiated.
+@param aAllSessionsHavePendingRequest An output parameter. It will be non-zero, if
+                 all clients has pending requests.
+*/
+EXPORT_C void CServShutdownServer::GetShutdownState(TBool& aPowerOff, TBool& aAllSessionsHavePendingRequest) const
+	{
+	aAllSessionsHavePendingRequest = AllSessionsHavePendingRequest();
+	aPowerOff = iPowerOff;
+	}
+
+/**
+This method creates an array of CArrayFix<TThreadId> type and appends to it the
+thread id-s of the all registered clients.
+The created CArrayFix<TThreadId> instance will be pushed on the cleanup stack.
+@return A pointer to a CArrayFix<TThreadId> array with the client thread id-s.
+@leave Some system-wide error codes including KErrNoMemory.
+*/
+EXPORT_C CArrayFix<TThreadId>* CServShutdownServer::ClientArrayLC()
+	{
+	CArrayFix<TThreadId>* clientArray=new(ELeave) CArrayFixFlat<TThreadId>(2);
+	CleanupStack::PushL(clientArray);
+	TDblQueIter<CSession2> iter(iSessionIter);
+	iter.SetToFirst();
+	TKeyArrayFix key(0,ECmpTInt);
+    for (CSession2* session=iter++; session!=NULL; session=iter++)
+		{
+		TThreadId id=static_cast<CServShutdownSession*>(session)->ClientThreadId();
+		TInt pos;
+		if (clientArray->Find(id,key,pos)!=0)
+			{
+			clientArray->AppendL(id);
+			}
+		}
+	return clientArray;
+	
+	
+	}
+
+#ifdef SYMBIAN_SSM_GRACEFUL_SHUTDOWN
+/**
+This method will write thread id-s of all clients that are registered for shutdown notification in to a streem.
+@param aMessage consists of buffer, clientside array count and server side array count 
+*/
+void CServShutdownServer::ClientArrayL(const RMessage2& aMessage)
+	{
+	const TInt arrayItemCount = ClientArrayCount();
+	//write all registered client array in a buffer only when client side 
+	//array count is equal to server side array count
+	if(arrayItemCount == aMessage.Int1())
+		{
+		const TInt sizeRequired = arrayItemCount * sizeof(TThreadId);
+		CBufFlat* const buf=CBufFlat::NewL(sizeRequired);
+		CleanupStack::PushL(buf);
+		RBufWriteStream writeStream(*buf);
+		CleanupClosePushL(writeStream); 
+		TDblQueIter<CSession2> iter(iSessionIter);
+		iter.SetToFirst();
+    	for (CSession2* session=iter++; session!=NULL; session=iter++)
+			{
+			TThreadId id=static_cast<CServShutdownSession*>(session)->ClientThreadId();
+			//Thread id (which is TUint64) is broken in to two TUint32 and written as RWriteStream doesnt 
+			//support TUint64. Client API will recreate TUint64 value from these TUint32 values.
+			if(id.Id())
+				{
+				//RWriteStream there is no API to writes a TUint64 value as a 64 bit value to stream
+				writeStream.WriteUint32L(I64HIGH(id.Id()));
+				writeStream.WriteUint32L(I64LOW(id.Id()));
+				}
+			}
+		writeStream.CommitL();
+		aMessage.WriteL(0, buf->Ptr(0));
+		CleanupStack::PopAndDestroy(2,buf);	//writeStream, buf 
+		}
+	else
+		{
+		aMessage.Write(2, TPckg<TInt>(arrayItemCount));
+		}	
+	
+	}
+		
+/**
+This method will return the number of client that are registered for Shutdown notification with ShutDown server.
+@return Number of registered clients.
+*/
+TInt CServShutdownServer::ClientArrayCount()
+	{
+	TDblQueIter<CSession2> iter(iSessionIter);
+	iter.SetToFirst();
+	TInt count =0;
+    for (CSession2* session=iter++; session!=NULL; session=iter++)
+		{
+		TThreadId id=static_cast<CServShutdownSession*>(session)->ClientThreadId();
+		//Clients which are not registered for notification will not have RMessage in the session and hence 
+		//thread id will be NULL(e.g.CLafShutdownEventObserverAdaptor). Avoid such clients. 		
+		if(id.Id())
+			{
+			++count;
+			}
+		}
+	return count;
+	}
+#endif	//SYMBIAN_SSM_GRACEFUL_SHUTDOWN	
+/**
+@return Non-zero, if all registered clients have pending requests.
+*/
+TBool CServShutdownServer::AllSessionsHavePendingRequest() const
+	{
+	TBool ret=ETrue;
+	TDblQueIter<CSession2> iter(iSessionIter);
+	iter.SetToFirst();
+	for (CSession2* session=iter++; session!=NULL; session=iter++)
+		{
+		const CServShutdownSession* mySession=static_cast<CServShutdownSession*>(session);
+		if (!mySession->HasPendingRequest())
+			{
+			ret=EFalse;
+			break;
+			}
+		}
+	return ret;
+	}
+
+
+/**
+@param aId Client's thread id.
+@return Non-zero if the client with this thread id has no pending request.
+*/
+EXPORT_C TBool CServShutdownServer::IsClientHung(TThreadId aId) const
+	{
+	TBool ret=EFalse;
+	TDblQueIter<CSession2> iter(iSessionIter);
+	iter.SetToFirst();
+	for (CSession2* session=iter++; session!=NULL; session=iter++)
+		{
+		const CServShutdownSession* mySession=static_cast<CServShutdownSession*>(session);
+
+		if (mySession->ClientThreadId()==aId)
+			{
+			if (!mySession->HasPendingRequest())
+				{
+				ret=ETrue;
+				break;
+				}
+			}
+		}
+	return ret;
+	}
+
+//
+// class CServShutdownSession
+//
+
+/**
+*/
+EXPORT_C CServShutdownSession::CServShutdownSession()
+	: CSession2(),
+	iCurrentEvent(-1), iOutstandingEvent(-1)
+	{}
+
+/**
+*/
+EXPORT_C CServShutdownSession::~CServShutdownSession()
+	{
+	}
+
+/**
+Standard phase-one factor method for creating CServShutdownSession instances.
+@return A pointer to the created CServShutdownSession instance.
+@leave KErrNoMemory Not enough memory to complete the operation.
+*/
+CServShutdownSession* CServShutdownSession::NewL()
+	{
+	return new (ELeave) CServShutdownSession;
+	}
+
+/**
+@return Non-zero, if the client has a pending request.
+*/
+TBool CServShutdownSession::HasPendingRequest() const
+	{
+	return !iPtr.IsNull();
+	}
+
+/**
+This method will complete the pending asychronous client request, effectivelly notifying it
+about the action, which the client has to do.
+@param aSaveType The type of the requested save action.
+*/
+void CServShutdownSession::NotifySave(MSaveObserver::TSaveType aSaveType)
+	{
+	const TInt saveType=(TInt)aSaveType;
+	if (HasPendingRequest())
+		{
+		iPtr.Complete(saveType);
+		iCurrentEvent=saveType;
+		}
+	else
+		{
+		if (iCurrentEvent==(TInt)MSaveObserver::ESaveAll || 
+			(iCurrentEvent==(TInt)MSaveObserver::ESaveQuick && 
+			 aSaveType==MSaveObserver::ESaveData))
+            {
+			iOutstandingEvent=saveType;
+			}
+		}
+	}
+
+/**
+This method dispatches all client requests to the appropriate method calls.
+@param aMessage The client's message
+@param aCompleteRequest An output parameter. If zero, the client request
+                will be completed later.
+*/
+void CServShutdownSession::DoServiceL(const RMessage2& aMessage, TBool& aCompleteRequest)
+	{
+	switch (aMessage.Function())
+		{
+	case TSaveOpCodeNotify:
+		RequestNotifyPowerDown(aMessage);
+		// don't complete async message yet
+		aCompleteRequest=EFalse;
+		break;
+	case TSaveOpCodeNotifyCancel:
+		RequestNotifyPowerDownCancel();
+		break;
+	case TSaveOpCodeHandleError:
+		User::Leave(KErrNotSupported);
+		break;
+	case TSaveOpCodePowerOff:
+		PowerOffL(aMessage);
+		break;
+	case TSaveOpCodeQueryPowerState:
+		PowerStateL(aMessage);
+		break;
+#ifdef SYMBIAN_SSM_GRACEFUL_SHUTDOWN
+	case EEventObsAdaptHandleShutdown:
+	case EEventObsAdaptClientArrayCount:
+	case EEventObsAdaptClientArray:
+	case EEventObsAdaptIsClientHung:
+	case EEventObsAdaptGetShutdownState:
+		{
+		if (IsSsmGracefulShutdown())	// SSM should be used for device shutdown
+			{
+			switch(aMessage.Function())
+				{
+				case EEventObsAdaptHandleShutdown:
+					HandleShutdownEventL(aMessage);
+					break;
+				case EEventObsAdaptClientArrayCount:
+					ClientArrayCount(aMessage);
+					break;
+				case EEventObsAdaptClientArray:
+					ClientArrayL(aMessage);
+					break;
+				case EEventObsAdaptIsClientHung:
+					IsClientHung(aMessage);
+					break;
+				case EEventObsAdaptGetShutdownState:
+					GetShutdownState(aMessage);
+					break;			
+				}
+			}
+		break;	
+		}
+#endif // SYMBIAN_SSM_GRACEFUL_SHUTDOWN
+	default:
+		User::Leave(KErrNotSupported);
+		break;
+		}
+	}
+
+#ifdef SYMBIAN_SSM_GRACEFUL_SHUTDOWN
+
+void CServShutdownSession::HandleShutdownEventL(const RMessage2& aMessage)
+	{
+	MSaveObserver::TSaveType action = static_cast <MSaveObserver::TSaveType> (aMessage.Int0());
+	TBool powerOff = static_cast <TBool> (aMessage.Int1());
+	TPowerState powerEvent = static_cast <TPowerState> (aMessage.Int2());
+
+	CServShutdownServer* server = static_cast<CServShutdownServer*>(const_cast<CServer2*>(Server()));
+	server->HandleShutdownEventL(action, powerOff, powerEvent);
+	}
+
+void CServShutdownSession::ClientArrayCount(const RMessage2& aMessage) const
+	{
+	CServShutdownServer* server = static_cast<CServShutdownServer*>(const_cast<CServer2*>(Server()));
+	const TInt count = server->ClientArrayCount();
+	aMessage.Write(0, TPckg<TInt>(count));
+	}
+/*
+This function will write all registered client array in a buffer only when client side array count is equal to server side array count
+else aMessage will contain an empty buffer and server side array count .
+@param aMessage consists of buffer, clientside array count and server side array count 
+*/
+void CServShutdownSession::ClientArrayL(const RMessage2& aMessage)
+	{
+	CServShutdownServer* server = static_cast<CServShutdownServer*>(const_cast<CServer2*>(Server()));
+	server->ClientArrayL(aMessage);
+	}
+
+void CServShutdownSession::IsClientHung(const RMessage2& aMessage) const
+	{
+	CServShutdownServer* server = static_cast<CServShutdownServer*>(const_cast<CServer2*>(Server()));
+	TThreadId threadId = static_cast <TThreadId>(aMessage.Int0());
+	TBool clientHung = server->IsClientHung(threadId);
+
+	aMessage.Write(1, TPckg<TBool>(clientHung));
+	}
+
+void CServShutdownSession::GetShutdownState(const RMessage2& aMessage) const
+	{
+	TBool powerOff;
+	TBool allSessionsHavePendingRequest;
+
+	CServShutdownServer* server = static_cast<CServShutdownServer*>(const_cast<CServer2*>(Server()));
+	server->GetShutdownState(powerOff, allSessionsHavePendingRequest);
+	aMessage.Write(0, TPckg<TBool>(powerOff));
+	aMessage.Write(1, TPckg<TBool>(allSessionsHavePendingRequest));
+	}
+
+#endif 	//SYMBIAN_SSM_GRACEFUL_SHUTDOWN
+
+/**
+Handles the servicing of client requests passed to the shutdown server.
+@param	aMessage The message containing the client request.
+*/
+EXPORT_C void CServShutdownSession::ServiceL(const RMessage2& aMessage)
+	{
+	TBool aCompleteRequest=ETrue;
+	TRAPD(error, DoServiceL(aMessage, aCompleteRequest));
+	if (aCompleteRequest)
+		{
+		aMessage.Complete(error);
+		}
+	}
+
+/**
+This method processes a client-side registration request. It is an asynchronous request,
+which will be completed later, when powerdown/low memory event occurs.
+@param	aMessage The message containing the client request.
+*/
+void CServShutdownSession::RequestNotifyPowerDown(const RMessage2& aMessage)
+	{
+	iCurrentEvent=-1;
+	iPtr = aMessage;
+
+	if (iOutstandingEvent!=-1)
+		{
+		NotifySave((MSaveObserver::TSaveType)iOutstandingEvent);
+		iOutstandingEvent=-1;
+		}
+	//The thread variable is just a dummy variable(input for CServShutdownServer::HandlePowerNotifRequest)
+	//and is not used inside the function at all, it is there to preserve BC.
+	RThread thread;
+	static_cast<CServShutdownServer*>(const_cast<CServer2*>(Server()))->HandlePowerNotifRequest(thread);
+	}
+
+/**
+This method cancels the client registration, completing the requests with 
+KErrCancel error code.
+*/
+void CServShutdownSession::RequestNotifyPowerDownCancel()
+	{
+	if (HasPendingRequest())
+		iPtr.Complete(KErrCancel);
+	}
+
+/**
+@return The client's thread id.
+*/
+TThreadId CServShutdownSession::ClientThreadId() const
+    {
+    TThreadId id = NULL;
+    RThread clientThread;
+    //Clients which are not registered for notification will not have RMessage in the session and hence 
+	//thread id will be NULL(e.g.CLafShutdownEventObserverAdaptor). Avoid such clients. 
+    if(!iPtr.IsNull() && KErrNone == iPtr.Client(clientThread))
+    	{	
+		id = clientThread.Id();	
+    	}
+    clientThread.Close();	
+    return id;
+    }
+
+
+/**
+This method should be used only with  SYSLIBS_TEST macro defined and can be used to 
+initiate a powerdown sequence.
+Without SYSLIBS_TEST macro defined the method will panic the client with 
+KErrNotSupported error code.
+@param	aMessage The message containing the client request.
+*/
+#ifdef SYSLIBS_TEST
+void CServShutdownSession::PowerOffL(const RMessage2& aMessage)
+    {
+	MSaveObserver::TSaveType action = static_cast <MSaveObserver::TSaveType> (aMessage.Int0());
+    TBool powerOff = static_cast <TBool> (aMessage.Int1());
+	CServShutdownServer* server = static_cast<CServShutdownServer*>(const_cast<CServer2*>(Server()));
+    server->HandleShutdownEventL(action, powerOff);
+    }
+#else
+void CServShutdownSession::PowerOffL(const RMessage2& aMessage)
+    {
+    aMessage.Panic(__SHUTDOWN_SERVER_NAME, KErrNotSupported);
+    }
+#endif//SYSLIBS_TEST
+
+/**
+This method should be used only with SYSLIBS_TEST macro defined and can be used to 
+get the power state of the server.
+Without SYSLIBS_TEST macro defined the method will panic the client with 
+KErrNotSupported error code.
+@param	aMessage The message containing the client request.
+*/
+#ifdef SYSLIBS_TEST
+void CServShutdownSession::PowerStateL(const RMessage2& aMessage) const
+    {
+    CServShutdownServer* server = static_cast<CServShutdownServer*>(const_cast<CServer2*>(Server()));
+    TBool powerOff = server->IsPowerOff();
+    TPckg<TBool> powerOffPckg(powerOff);
+    aMessage.WriteL(0,powerOffPckg);
+    }
+#else
+void CServShutdownSession::PowerStateL(const RMessage2& aMessage) const
+    {
+    aMessage.Panic(__SHUTDOWN_SERVER_NAME, KErrNotSupported);
+    }
+#endif//SYSLIBS_TEST
+