messagingfw/msgtest/targetautomation/TechviewStart/Starter.cpp
changeset 0 8e480a14352b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/messagingfw/msgtest/targetautomation/TechviewStart/Starter.cpp	Mon Jan 18 20:36:02 2010 +0200
@@ -0,0 +1,445 @@
+// 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:
+//
+			  
+#include "Starter.h"
+#include "AppStarter.h"
+#include "ThreadWatch.h"
+#include <e32property.h>
+#include "MsvTestUtils.h"
+#include <Start.rsg>
+#include "Start.hrh"
+
+typedef TInt (*ShellEntryPoint)(TAny *);
+#if defined(__WINS__)
+LOCAL_D const TUint KHeapSize=0x10000;
+LOCAL_D const TUint KMaxHeapSize=0x400000;
+#endif
+
+
+_LIT(KStubRunResourceFileName, "Z:\\SYSTEM\\PROGRAMS\\Start.RSC");
+_LIT(KGlobalSemaphore, "SPLASH");
+_LIT(KStartChunkName,"Start");
+
+const TInt KRetryTime = 100000;
+
+/**
+@internalComponent
+*/
+TBool definedPhonePwrValue = EFalse;
+
+
+/**
+* Contructor
+*/
+CStarter::CStarter() :	CActive(EPriorityStandard), iNrSemaphore(0)
+	{}
+
+/**
+* Destructor.
+*/
+CStarter::~CStarter()
+	{
+	if (iQueHeader)
+		{
+		while (!(iQueHeader->IsEmpty()))
+			{
+			CThreadWatcher* threadWatcher = iQueHeader->First();
+			iQueHeader->Remove(*threadWatcher);
+			delete threadWatcher;
+			}
+		delete iQueHeader;
+		}
+
+	iLsSess.Close();
+#if defined (__WINS__)
+	iAppUiSession.Close();
+#endif
+	delete iStartupList;
+	delete iExtrasList;
+	delete iSplashExe;
+	iCmdLineArgs.Close();
+	iResourceFile.Close();
+	iFsSession.Close();
+	}
+
+/**
+* Creates an instance of a CStarter object.
+* @return			a pointer to this object
+*/
+CStarter* CStarter::NewL()
+	{
+	CStarter* self = new (ELeave) CStarter;
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop();
+	return self;
+	}
+
+/**
+* Handles the actual initialization of this object.
+*/
+void CStarter::ConstructL()
+	{
+	// Connect to the File Server
+	while (iFsSession.Connect() != KErrNone)
+		{
+		User::After(KRetryTime);
+		}
+
+	//Connected to File Server
+	iResourceFile.OpenL(iFsSession, KStubRunResourceFileName);
+
+	// read the first one
+    HBufC8* res = iResourceFile.AllocReadLC(R_APP_START_PARAMS);
+    TResourceReader theReader;
+    theReader.SetBuffer(res);
+	//Main configuration resource read
+
+	// get data from it
+	iSplashExe = theReader.ReadHBufCL();
+
+	TUint32 applicationsListId = theReader.ReadInt32();
+	TUint32 exeListId = theReader.ReadInt32();
+
+	// free up memory
+	CleanupStack::PopAndDestroy();	// res
+
+	// prepare the data for the active object
+	iStartupList = iResourceFile.AllocReadL(applicationsListId);
+    iStartupListReader.SetBuffer(iStartupList);
+	iStartupCount = iStartupListReader.ReadUint16();	//The size of the resource array
+
+	iExtrasList= iResourceFile.AllocReadL(exeListId);
+    iExtrasListReader.SetBuffer(iExtrasList);
+	iExtrasCount = iExtrasListReader.ReadUint16();	//The size of the resource array
+
+	iQueHeader = new (ELeave) TSglQue<CThreadWatcher>(_FOFF(CThreadWatcher,iLink));
+
+	// Tell system agent the phone is on.
+	// This is only appropriate for 2-box solutions, and is needed for SMS sending and receiving.
+	// Also, at some point, this should probably be moved to a separate component that startup launches.
+	TInt testState;
+	if(KErrNone != RProperty::Get(KUidSystemCategory, KMsvTestUidPhonePwrValue, testState))
+		{
+		User::LeaveIfError(RProperty::Define(KUidSystemCategory, KMsvTestUidPhonePwrValue, RProperty::EInt));
+		definedPhonePwrValue = ETrue;
+		}
+	User::LeaveIfError(RProperty::Set(KUidSystemCategory, KMsvTestUidPhonePwrValue, EMsvTestPhoneOn));
+
+	if(definedPhonePwrValue)
+		{
+		User::LeaveIfError(RProperty::Delete(KUidSystemCategory, KMsvTestUidPhonePwrValue));
+		}
+
+	RChunk chunk;
+	TUint8 finish=0;
+	if(	chunk.CreateGlobal(KStartChunkName,1,1)== KErrNone)
+		{
+		if(	chunk.OpenGlobal(KStartChunkName,EFalse)== KErrNone)
+			{
+			TUint8* base=chunk.Base();
+			*base=finish;
+			chunk.Close();
+			}
+		}
+	}
+
+/**
+* Actually launch the splash screen exe
+*/
+void CStarter::StartSplashScreenL()
+	{
+	if (iSplashExe == NULL || iSplashExe->Length() == 0)
+		{
+		return;
+		}
+
+	// launch the splash screen
+	TPtrC splashCmd;
+	splashCmd.Set(*iSplashExe);
+
+#if defined(__WINS__)
+	TParse fileName;
+	User::LeaveIfError(fileName.Set(_L(".DLL"),&splashCmd,NULL));
+	User::LeaveIfError(iLib.Load(fileName.FullName()));
+	ShellEntryPoint libFunc=(ShellEntryPoint)iLib.Lookup(1);
+	if (!libFunc)
+		{
+		User::Leave(KErrGeneral);
+		}
+	TBuf<256> name;
+	TInt num=0;
+	TInt ret=KErrNone;
+	do
+		{
+		name.Format(TRefByValue<const TDesC>(_L("Splash%d")),num++);
+		ret=iSplash.Create(name,libFunc,KDefaultStackSize,&splashCmd,&iLib,NULL,/*NULL,*/KHeapSize,KMaxHeapSize,EOwnerProcess);
+		} while(ret==KErrAlreadyExists);
+	User::LeaveIfError(ret);
+#else
+	TFindFile findShell(iFsSession);
+	User::LeaveIfError(findShell.FindByDir(splashCmd,_L("\\System\\Programs\\.EXE")));
+	//User::LeaveIfError(iSplash.Create(findShell.File(),splashCmd));
+	TInt err1 = 0;
+	TRAPD(err,(err1 = iSplash.Create(findShell.File(),splashCmd)));	//Change back to commented out line when E32 bug is fixed ###
+	if (err!=KErrNone && err1 != KErrNone)
+		{
+		iSplash.SetHandle(KNullHandle);
+		User::Leave(err);
+		}
+#endif
+	iSplash.Resume();
+
+	}
+
+/**
+* Method to be called to procced the startup
+*/
+void CStarter::Start()
+	{
+	iStage = ESplashScreen;
+	RequestNotify();
+	}
+
+/**
+* Start then connect the Eikon server
+*/
+void CStarter::Connect()
+	{
+	// Connect to the AppUi session, effective starting it.
+	while(iAppUiSession.Connect() != KErrNone)
+		{
+		User::After(KRetryTime);
+		}
+
+	// Connect to the AppLsServer
+	while(iLsSess.Connect() != KErrNone)
+		{
+		User::After(KRetryTime);
+		}
+
+	TInt count=0;
+	while(iLsSess.GetAllApps() != KErrNone) //collect data
+		{
+		}
+  	while(iLsSess.AppCount(count) != KErrNone) //collect data
+		{
+		}
+	RequestNotify();
+	}
+
+/**
+* Proceed the next application to be launched
+*/
+void CStarter::LaunchNextStartupAppL()
+	{
+	TUint32 applicationUid = iStartupListReader.ReadUint32();
+	TFullName exeFilePath = iStartupListReader.ReadTPtrC();
+	TFullName dllFilePath = iStartupListReader.ReadTPtrC();
+	iCmdLineArgs.Append( iStartupListReader.ReadTPtrC());
+	TDesC *commandLineArgs = &iCmdLineArgs[ iCmdLineArgs.Count()-1];
+
+	TUint32 stackSize = iStartupListReader.ReadUint32();
+	stackSize = stackSize ? stackSize : KDefaultStackSize;
+	TUint32 minHeapSize = iStartupListReader.ReadUint32();
+	minHeapSize = minHeapSize ? minHeapSize : KMinHeapSize;
+	TUint32 maxHeapSize = iStartupListReader.ReadUint32();
+
+	TBool monitored = (TUint16)iStartupListReader.ReadUint16();
+	TBool semaphore = (TUint16)iStartupListReader.ReadUint16();
+	TBool viewless = (TUint16)iStartupListReader.ReadUint16();
+	TInt bootType  = (TUint16)iStartupListReader.ReadUint16();
+			
+	if(semaphore)
+		{
+		iNrSemaphore++; //increase with one.
+		iWaiting++;
+		}
+
+	iStartupCount--; // next app
+	CAppStarter::NewLD(bootType, applicationUid, exeFilePath, dllFilePath, commandLineArgs,
+						stackSize, minHeapSize, maxHeapSize, monitored, viewless,
+						semaphore, iQueHeader, iLsSess, this);
+	}
+
+/**
+* Proceed the next extra app to be launched
+*/
+void CStarter::LaunchNextExtrasL()
+	{
+	TUint32 applicationUid = iExtrasListReader.ReadUint32();
+	TFullName exeFilePath = iExtrasListReader.ReadTPtrC();
+	TFullName dllFilePath = iExtrasListReader.ReadTPtrC();
+	iCmdLineArgs.Append( iExtrasListReader.ReadTPtrC());
+	TDesC *commandLineArgs = &iCmdLineArgs[ iCmdLineArgs.Count()-1];
+
+	TUint32 stackSize = iExtrasListReader.ReadUint32();
+	stackSize = stackSize ? stackSize : KDefaultStackSize;
+	TUint32 minHeapSize = iExtrasListReader.ReadUint32();
+	minHeapSize = minHeapSize ? minHeapSize : KMinHeapSize;
+	TUint32 maxHeapSize = iExtrasListReader.ReadUint32();
+	
+	TBool monitored = (TUint16)iExtrasListReader.ReadUint16();
+	TBool viewless = (TUint16)iExtrasListReader.ReadUint16();
+	TInt bootType  = (TUint16)iExtrasListReader.ReadUint16();
+
+	iExtrasCount--; // next app
+	CAppStarter::NewLD(bootType, applicationUid, exeFilePath, dllFilePath, commandLineArgs,
+						stackSize, minHeapSize, maxHeapSize, monitored, viewless,
+						EFalse, iQueHeader, iLsSess, this);
+	}
+
+void CStarter::RestartMonitoredThreadL(TInt appType, TThreadId& aThreadId, TDesC& aExeFileName, TUint32 aAppUid, TBool aViewless)
+  	{
+  	if(appType == EExecutableType) 
+  		{
+  		User::LeaveIfError(iLsSess.StartDocument(aExeFileName, TUid::Uid(0), aThreadId));
+  		} 
+  	else if(aViewless)
+  		{
+  		TApaAppInfo info;
+  		User::LeaveIfError(iLsSess.GetAppInfo(info,TUid::Uid(aAppUid)));
+  		CApaCommandLine* cmdLine=CApaCommandLine::NewLC();	
+  		cmdLine->SetLibraryNameL(info.iFullName);
+  		cmdLine->SetCommandL(EApaCommandRunWithoutViews);
+  		User::LeaveIfError(iLsSess.StartApp(*cmdLine, aThreadId));
+  		CleanupStack::PopAndDestroy();	// cmdLine
+		}
+  	else
+  		{
+  		TApaAppInfo info;
+  		User::LeaveIfError(iLsSess.GetAppInfo(info,TUid::Uid(aAppUid)));
+  		TFileName fName;
+  		if (info.iUid!=KNullUid)
+  			{
+  			User::LeaveIfError(iLsSess.StartDocument(fName, TUid::Uid(aAppUid), aThreadId));
+  			}
+  		}
+   	}
+
+/**
+* Method called when the requested step have been procced
+*/
+void CStarter::RunL()
+	{
+	switch (iStage)
+		{
+		case ESplashScreen:
+			{
+			iStage =  EStarting;
+			// don't care about the error - for now
+			TRAPD(err, StartSplashScreenL());
+			iSplashStarted = (err == KErrNone);
+			RequestNotify();		
+			}
+			break;
+		case EStarting:
+			iStage = EConnected;
+			Connect();
+			break;
+		case EConnected:
+			{
+			iStage = EStart;
+			iSema.CreateGlobal(KGlobalSemaphore, EOwnerProcess); //For Shell
+			RequestNotify();
+			}
+			break;
+		case EStart:
+			{
+			iStage = EStart;
+			if (iStartupCount)
+				{
+				LaunchNextStartupAppL();
+				RequestNotify();
+				}
+			break;
+		case EWait:
+ 			iStage = EStartExtras;
+			if(iSema.OpenGlobal(KGlobalSemaphore, EOwnerProcess) == KErrNone)
+				{
+				while(iNrSemaphore > 0) //Defined in the resourcefile for apps that has to be started before the splash screen is removed
+					{
+					iSema.Wait();
+					iNrSemaphore--;
+					}
+				iSema.Close();
+				}
+
+			if(iSplashStarted)
+				{
+				//use chunk to tell splash screen to stop by setting to 1
+				RChunk chunk;
+				TUint8 finish=1;
+				if(	chunk.OpenGlobal(KStartChunkName,EFalse)== KErrNone)
+					{
+					TUint8* base=chunk.Base();
+					*base=finish;
+					chunk.Close();
+					}
+				}
+
+			RequestNotify();
+			}
+			break;
+		case EStartExtras:
+			if(iExtrasCount)
+				{
+				LaunchNextExtrasL();
+				RequestNotify();
+				}
+			break;
+		default: 
+			iStage = ESplashScreen;
+			break;
+		}
+	}
+
+TInt CStarter::RunError(TInt /*aError*/)
+	{
+	return KErrNone;
+	}
+
+void CStarter::Done(TBool aSuccess)
+	{
+	if(aSuccess)
+		{
+		iWaiting--;
+		}
+	else
+		{
+		iWaiting--;
+		iNrSemaphore--;
+		}
+	if(iWaiting <= 0)
+		{
+		iStage = EWait;
+		RequestNotify();
+		}
+	}
+/**
+* Cancel the execution
+*/
+void CStarter::DoCancel()
+	{
+	TRequestStatus* status = &iStatus;
+	User::RequestComplete(status, KErrCancel);
+	}
+
+void CStarter::RequestNotify()
+	{
+	TRequestStatus* status = &iStatus;
+	User::RequestComplete(status, KErrNone);
+	SetActive();
+	}