smartinstaller/adm/inc/ADMStateMachine.h
author Santosh V Patil <santosh.v.patil@nokia.com>
Wed, 30 Jun 2010 11:01:26 +0530
branchADM
changeset 48 364021cecc90
permissions -rw-r--r--
SmartInstaller contribution based on the Nokia Qt SDK 1.0 release

/*
* Copyright (c) 2009-2010 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: 
*     State machine
*
*
*/


#ifndef ADMSTATEMACHINE_H_
#define ADMSTATEMACHINE_H_

#include <e32base.h>
#include <e32debug.h>

#include "ADMAppUi.h"
#include "ADMInstallManager.h"
#include "ADMPackageInfo.h"
#include "ADMSisParser.h"
#include "ADMXmlParser.h"

// Forward declarations
class TState;
class CStateMachine;

enum TStatePanic
	{
	EPanicStateIndexOutOfBounds = 1000,
	EPanicStateImplementationMissing,
	EPanicStateInvalidBootstrapVersion,
	EPanicStateInvalidMachineUid,
	EPanicStateFetchStatus,
	EPanicStateFetchPackageNull,
	EPanicStateUnexpectedPackage,
	EPanicStateUnexpectedRootPackage,
	EPanicStateWrapperNotInstalled
	};

const TInt KUnknownState = -40000;

// Timeout for waiting for download deletion. Default 2 s.
const TInt KDlDeletingTimeout = 2*1000*1000;

class CStateFactory : public CBase
	{
public:
	enum TAppState
		{
		EStateSetup = 0,                   // 0
		EStateSetupParsing,
		EStateBuildDepTree,
		EStateDownloadChangesFile,
		EStateParseChangesFile,
		EStateDownloadDepFile,             // 5
		EStateParseDepFile,
		EStateBuildFetchList,
		EStateVerifyAvailableDiskSpace,
		EStateConfirmDownload,
		EStateConfirmRoamingDownload,      // 10
		EStateStartDependencyDownload,
		EStateDownloadDependency,
		EStateInstallDependency,
		EStateInstallAppSis,
		EStateUninstallDependency,         // 15
		EStatePrepareExitWithError,
		EStateLaunchApp,
		EStateExit,

		EStateLast
		};

	TState& GetState(const TAppState aState) const;
	TInt StateIndex(const TState* aState) const;

	inline CStateMachine& StateMachine() const { return iStateMachine; }

	static CStateFactory* NewL(CStateMachine& aStateMachine);
	~CStateFactory();

private:
	CStateFactory(CStateMachine& aStateMachine);
	void ConstructL();

private:
	TFixedArray<TState*, EStateLast> iStates;
	CStateMachine&   iStateMachine;
	};

// Base class for a state
class TState
	{
public:
	//friend class CStateFactory;
	//friend class CStateMachine;

	TState(const CStateFactory& aFactory);

	// Change of states
	virtual void Enter() const;
	virtual void Exit() const;

	// Events from UI
	virtual void UserAccepted();
	virtual void UserRejected();
	virtual void UserCancelled();

	// Events from DownloadManager
	virtual void DownloadInProgress(const TInt aAlreadyDownloaded, const TInt aDownloadSize, const TReal32 aAvgDlSpeed);
	virtual void DownloadCompleted(const TInt aBytesDownloaded);
	virtual void DownloadFailed();
	virtual void DownloadCancelled();

	// Events from InstallManager
	virtual void InstallInProgress();
	virtual void InstallCompleted(TInt aStatus);
	virtual void InstallationCancelled();

protected:
	void DownloadFailed(const CStateFactory::TAppState aState);
	void PanicInState(TStatePanic aPanic) const;

protected:
	const CStateFactory& iFactory;
	CStateMachine& iStateMachine;
	};

// ----------------------------------------------------------------------------
class TStateSetup : public TState
	{
public:
	TStateSetup(const CStateFactory& aFactory);

	void Enter() const;
	};
// ----------------------------------------------------------------------------
class TStateSetupParsing : public TState
	{
public:
	TStateSetupParsing(const CStateFactory& aFactory);

	void Enter() const;
	};
// ----------------------------------------------------------------------------
class TStateDownloadDepFile : public TState
	{
public:
	TStateDownloadDepFile(const CStateFactory& aFactory);

	void Enter() const;

	void DownloadCompleted(const TInt aBytesDownloaded);
	void DownloadFailed();
	};
// ----------------------------------------------------------------------------
class TStateParseDepFile : public TState
	{
public:
	TStateParseDepFile(const CStateFactory& aFactory);

	void Enter() const;
	};
// ----------------------------------------------------------------------------
class TStateBuildDepTree : public TState
	{
public:
	TStateBuildDepTree(const CStateFactory& aFactory);

	void Enter() const;
	};
// ----------------------------------------------------------------------------
class TStateDownloadChangesFile : public TState
	{
public:
	TStateDownloadChangesFile(const CStateFactory& aFactory);

	void Enter() const;

	void DownloadCompleted(const TInt aBytesDownloaded);
	void DownloadFailed();
	};
// ----------------------------------------------------------------------------
class TStateParseChangesFile : public TState
	{
public:
	TStateParseChangesFile(const CStateFactory& aFactory);

	void Enter() const;
	};
// ----------------------------------------------------------------------------
class TStateBuildFetchList : public TState
	{
public:
	TStateBuildFetchList(const CStateFactory& aFactory);

	void Enter() const;
	};
// ----------------------------------------------------------------------------
class TStateVerifyAvailableDiskSpace : public TState
	{
public:
	TStateVerifyAvailableDiskSpace(const CStateFactory& aFactory);

	void Enter() const;
	};
// ----------------------------------------------------------------------------
class TStateConfirmDownload : public TState
	{
public:
	TStateConfirmDownload(const CStateFactory& aFactory);

	void Enter() const;
	void UserAccepted();
	};
// ----------------------------------------------------------------------------
class TStateConfirmRoamingDownload : public TState
	{
public:
	TStateConfirmRoamingDownload(const CStateFactory& aFactory);

	void Enter() const;
	void UserAccepted();
	};
// ----------------------------------------------------------------------------
class TStateStartDependencyDownload : public TState
	{
public:
	TStateStartDependencyDownload(const CStateFactory& aFactory);

	void Enter() const;
	};
// ----------------------------------------------------------------------------
class TStateDownloadDependency : public TState
	{
public:
	TStateDownloadDependency(const CStateFactory& aFactory);

	void Enter() const;

	void DownloadCompleted(const TInt aBytesDownloaded);
	void DownloadInProgress(const TInt aAlreadyDownloaded, const TInt aDownloadSize, const TReal32 aAvgDlSpeed);
	void DownloadFailed();

private:
	TBool iRetryDownload; // Set to true, if we're retrying download
	};
// ----------------------------------------------------------------------------
class TStateInstallDependency : public TState
	{
public:
	TStateInstallDependency(const CStateFactory& aFactory);

	void Enter() const;
	void Exit() const;
	void InstallCompleted(TInt aStatus);
	};
// ----------------------------------------------------------------------------
class TStateInstallAppSis : public TState
	{
public:
	TStateInstallAppSis(const CStateFactory& aFactory);

	void Enter() const;
	void InstallCompleted(TInt aStatus);
	};
// ----------------------------------------------------------------------------
class TStateUninstallDependency : public TState
	{
public:
	TStateUninstallDependency(const CStateFactory& aFactory);

	void Enter() const;
	void InstallCompleted(TInt aStatus);
	};
// ----------------------------------------------------------------------------
class TStatePrepareExitWithError : public TState
	{
public:
	TStatePrepareExitWithError(const CStateFactory& aFactory);

	void Enter() const;

private:
	TInt CreateInstallationResumeInfo() const;
	void BackupFilesL() const;
	};
// ----------------------------------------------------------------------------
class TStateLaunchApp : public TState
	{
public:
	TStateLaunchApp(const CStateFactory& aFactory);

	void Enter() const;
	void UserAccepted();
	void UserRejected();
};
// ----------------------------------------------------------------------------
class TStateExit : public TState
	{
public:
	TStateExit(const CStateFactory& aFactory);

	void Enter() const;

private:
	void RemoveResumeFiles() const;

#ifdef FEATURE_REPORTING
	void Report() const;

public:
	void DownloadInProgress(const TInt /* aAlreadyDownloaded */, const TInt /* aDownloadSize */, const TReal32 /* aAvgDlSpeed */);
	void DownloadCompleted(const TInt /* aBytesDownloaded */);
	void DownloadFailed();
	void DownloadCancelled();
#endif
	};

// ----------------------------------------------------------------------------
class CStateMachine : public CActive,
	public CInstallManager::MInstallClient,
	public CDownloadHandler::MDownloadClient
	{
public:
	friend class TState;
	friend class TStateBuildDepTree;
	friend class TStateBuildFetchList;
	friend class TStateConfirmDownload;
	friend class TStateConfirmRoaming;
	friend class TStateDownloadChangesFile;
	friend class TStateDownloadDepFile;
	friend class TStateDownloadDependency;
	friend class TStateExit;
	friend class TStateInstallAppSis;
	friend class TStateInstallDependency;
	friend class TStateLaunchApp;
	friend class TStateParseChangesFile;
	friend class TStateParseDepFile;
	friend class TStateParseSisFile;
	friend class TStatePrepareExitWithError;
	friend class TStateSetup;
	friend class TStateSetupParsing;
	friend class TStateStartDependencyDownload;
	friend class TStateUninstallDependency;
	friend class TStateVerifyAvailableDiskSpace;
	friend class TStateWaitForUserConfirmation;

	static CStateMachine* NewL(CADMAppUi& aAppUi, const TDesC& aDownloadPath);
	~CStateMachine();

	void Start();
	void Stop();
	void SetStartState(const CStateFactory::TAppState aState);
	void SetState(const CStateFactory::TAppState aState);
	TInt StateIndex() const;

	// Interfacing for ADM
	// Called when user has made a selection in a query dialog
	void SetIAP(TUint32 aIAP);
	void HandleUserResponse(TInt aResponse);
	CStateFactory::TAppState FailedState() const { return iFailedState; }
	inline TInt32 TotalDownloadSize() const { return iDepTree->GetTotalDownloadSize(); }
	inline HBufC* LaunchCaption() const
		{
			CPackageInfo* root = iDepTree->GetRootNode();
			if (root)
				return root->GetPackageName();
			else
				return NULL;
		}

#ifdef USE_LOGFILE
	RFileLogger& Log() const { return iAppUi.iLog; }
#endif

	// Interface to ADM
	inline TBool ResumeRequired() const { return iAppUi.iIsResumeRequired; }
	inline TInt MachineUid() const { return iAppUi.iMachineUid; }
	inline TInt BootstrapVersion() const { return iAppUi.iBootstrapVersion; }
	inline TBool RegisteredRoaming() const { return iAppUi.RegisteredRoaming(); }
	inline TBool UsingWLAN() const { return iAppUi.UsingWLAN(); }
	inline TBool OviStoreRunning() const { return iAppUi.iOviStoreRunning; }
	inline TBool ResumingInstallation() const { return iAppUi.iResumingInstallation; }
	inline HBufC* DepFilename() const { return iAppUi.iDepFileName; }
	inline HBufC* SisFilename() const { return iAppUi.iSisFileName; }
	inline HBufC8* ConfigUrl() const { return iAppUi.iConfigUrl; }
	inline TUid& WrapperPackageUid() const { return (TUid&)iAppUi.iWrapperPackageUid; }
	inline RFs& FsSession() const { return iAppUi.EikonEnv()->FsSession(); }
	inline void SetSilentInstallationOk(const TBool aOk) { iAppUi.iSilentInstallationOk = aOk; }
	inline void SetNonSilentInstallation(const TBool aVal) { iAppUi.iNonSilentInstallation = aVal; }
	inline void SetAppLaunch(const TBool aSuccess) { iAppUi.iAppLaunch = aSuccess; }
	inline TBool AppLaunch() const { return iAppUi.iAppLaunch; }
	inline TInt ExitReason() const { return iAppUi.iExitReason; }
	void UpdateProgressBar(const TInt aStartValue, const TInt aEndValue);
	void StopProgressBar() const;
	void SetFailureReason(TExitReason aReason);
	void ShowDownloadQueryL(const TInt aResourceId, const TInt aInfoResourceId = -1);
	void ShowWaitNoteL(const TInt aResourceId);
	void ShowInstallingWaitNoteL(const TInt aCurrent, const TInt aLast);
	void ShowProgressBarL(const TInt aStartValue, const TInt aEndValue, const TInt aCurrent = -1, const TInt aLast = -1);
	void StopWaitNote();

protected:
	void RunL();
	void DoCancel();
	TInt RunError(const TInt aError);

	void SetState(TState& aState);

	//From MInstallClient
	void HandleInstallCompletedL(TInt aStatus);

	//From MDownloadClient
	/**
	 * Called by Download Manager when IAP has changed.
	 * @param aIAP IAP ID
	 */
	void HandleIapChanged(const TUint32 aIAP);
	/**
	 * Called by Download Manager when downloading of a packet is completed.
	 * @param aDlFileName Name of the downloaded file.
	 * @param aResponseType Download type.
	 * @param aDownloadSize Total number of bytes downloaded.
	 */
	void HandleHttpFetchCompleted( const TDesC& aDlFilename, const TInt aDownloadType, const TInt32 aBytesDownloaded, const TReal32 aAvgDlSpeed, const TInt64 aDlTime );

	/**
	 * Called when download manager has retrieved a packet from the network.
	 * Required for updating the progress bar.
	 */
	void HandleHttpFetchInProgress(const TInt32 aAlreadyDownloaded, const TInt32 aDownloadSize, const TReal32 aAvgDlSpeed);

	/**
	 * Called when download manager encounters a problem while downloading
	 */
	void HandleHttpFetchFailure( const TDesC& aDlFilename, const TInt aGlobalErrorId, const TInt aErrorId, const TInt aFetchType );

	/**
	 * Called when download manager is deleting the download.
	 */
	void HandleDownloadDeleting();

	// State machine required functions
	//void HandleFailure();
	//TBool VerifyAvailableDiskSpace();
	//void SilentInstallDownloadedPackageL();

private:
	CStateMachine(CADMAppUi& aAppUi);
	void ConstructL(const TDesC& aDownloadPath);

private:
	CADMAppUi&			iAppUi;
	CStateFactory*		iStateFactory;     //< owns
	CInstallManager*	iInstallManager;   //< owns
	CDownloadHandler*	iDownloadHandler;  //< owns

	CXmlParser*			iXmlParser; //< owns
	CSisParser*			iSisParser; //< owns
	CDepTree*			iDepTree;   //< owns
	CPackageInfo*		iCurrentPackage;

	/**
	 * Path to the downloaded file. Updated after each finishing each
	 * download (completed or failed).
	 */
	HBufC*              iDownloadedFile;   //< owns

	/**
	 * Current state.
	 */
	TState*             iState;

	/**
	 * The state that experienced failure that causes ADM to exit.
	 */
	CStateFactory::TAppState    iFailedState;

	/**
	 * Number of dependency tree nodes processed so far.
	 */
	TInt   iNodesProcessed;

	/**
	 * Progress bar current value.
	 */
	TInt32 iProgressCurrentValue;

	/**
	 * Progress bar maximum value. Stays constant after being set.
	 */
	TInt32 iProgressMaxValue;

	/**
	 * Current package # being downloaded/installed.
	 */
	TInt iCounterCurrent;

	/**
	 * Total number of packages being downloaded/installed.
	 */
	TInt iCounterMax;

	/**
	 * Total size of the packages to be downloaded in bytes.
	 * Used in progress bar update.
	 */
	TInt32 iDownloadSize;

	/**
	 * Downloaded bytes so far.
	 * Used in progress bar update.
	 */
	TInt32 iCumulativeDepDownloaded;

	/**
	 * Total number of bytes downloaded during session. Includes all
	 * dependency XML file downloads and .sis file downloads.
	 */
	TInt32 iCumulativeDownloaded;

	/**
	 * Time in microseconds used in downloading, used for calculating average download speed.
	 */
	TInt64 iDownloadTime;

	/**
	 * Drive in which wrapper is installed.
	 */
	TChar iWrapperInstalledDrive;

	/**
	 * Restart Attempt for Download Failure
	 */
	TInt iRestartAttempt;

#ifdef FEATURE_LAUNCH_INSTALLED_APP
	/**
	 * App Launch name
	 */
	TFileName iLaunchName;
	TFileName iLaunchIconFilename;
	TApaAppCaption iLaunchCaption;
#endif

	/**
	 * Semaphore for signalling download deleting.
	 */
	RSemaphore iDlDeletingSemaphore;
	};

#endif /* ADMSTATEMACHINE_H_ */