--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/installationservices/swi/source/daemon/daemonbehaviour.cpp Wed Sep 01 12:22:02 2010 +0100
@@ -0,0 +1,435 @@
+/*
+* Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "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 "daemonbehaviour.h"
+#include "swispubsubdefs.h"
+#include "recsisx.h"
+#include "sisregistrywritablesession.h"
+#include "sisregistryentry.h"
+#include "filesisdataprovider.h"
+#include "swi/sisparser.h"
+#include "swi/siscontents.h"
+#include "swi/siscontroller.h"
+#include "sisinfo.h"
+#include "cleanuputils.h"
+#include "sisregistrypackage.h"
+#include "log.h"
+
+void ScanDirectoryL(TInt aDrive);
+
+using namespace Swi;
+
+CDaemonBehaviour* CDaemonBehaviour::NewL()
+ {
+ CDaemonBehaviour* self = NewLC();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+CDaemonBehaviour* CDaemonBehaviour::NewLC()
+ {
+ CDaemonBehaviour* self = new (ELeave) CDaemonBehaviour;
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ return self;
+ }
+
+void CDaemonBehaviour::ConstructL()
+ {
+ User::LeaveIfError(iFs.Connect());
+ User::LeaveIfError(iFs.ShareProtected());
+ User::LeaveIfError(iApaSession.Connect());
+ iSisInstaller = CSisInstaller::NewL(this);
+ TRAP_IGNORE(iSwiDaemonPlugin = CSwiDaemonPlugin::NewL());
+ }
+
+CDaemonBehaviour::~CDaemonBehaviour()
+ {
+ if(iSwiDaemonPlugin)
+ {
+ delete iSwiDaemonPlugin;
+ REComSession::FinalClose();
+ }
+ delete iSisInstaller;
+ iFs.Close();
+ iApaSession.Close();
+ }
+
+ // from MDaemonBehaviour
+TBool CDaemonBehaviour::StartupL()
+ {
+ // Return state of Startup
+ return ETrue;
+ }
+
+void CDaemonBehaviour::MediaChangeL(TInt aDrive, TChangeType aChangeType)
+ {
+ DEBUG_PRINTF3(_L8("SWI Daemon - Media change detected. Drive: %d, Change Type: %d."),
+ aDrive, aChangeType);
+
+ RSisRegistryWritableSession registrySession;
+
+ User::LeaveIfError(registrySession.Connect());
+ CleanupClosePushL(registrySession);
+
+ if (aChangeType==EMediaInserted)
+ {
+ // notify IAR
+ registrySession.AddDriveL(aDrive);
+
+ // Scan directory on the card and run pre-installed through SWIS
+ // nb. will leave if no SIS files to install.
+ ProcessPreinstalledFilesL(aDrive);
+ }
+ else if (aChangeType==EMediaRemoved)
+ {
+ // Cancel all requests for install
+ iSisInstaller->Reset();
+
+ // Notify plugin
+ if(iSwiDaemonPlugin)
+ {
+ iSwiDaemonPlugin->MediaRemoved(aDrive);
+ }
+
+#ifndef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+ // notify IAR
+ registrySession.RemoveDriveL(aDrive);
+#endif
+ }
+ CleanupStack::PopAndDestroy(®istrySession);
+ }
+
+void CDaemonBehaviour::ProcessPreinstalledFilesL(TInt aDrive)
+ {
+ _LIT(KDaemonPrivatePath,":\\private\\10202dce\\");
+
+ iSisInstaller->Reset();
+ ProcessPreinstalledFilesL(aDrive, KDaemonPrivatePath);
+ iStartNotified = EFalse;
+ iDrive = aDrive;
+ iSisInstaller->StartInstallingL();
+ }
+
+void CDaemonBehaviour::ProcessPreinstalledFilesL(TInt aDrive, const TDesC& aDirectory)
+ {
+ TPath preInstalledPath;
+ TChar drive;
+ RFs::DriveToChar(aDrive, drive);
+ preInstalledPath.Append(drive);
+ preInstalledPath.Append(aDirectory);
+
+ CDir* dir = NULL;
+ TInt err = iFs.GetDir(preInstalledPath, KEntryAttNormal, ESortByName, dir);
+ if (err != KErrNone && err != KErrPathNotFound)
+ {
+ User::Leave(err);
+ }
+ if(dir)
+ {
+ // dir will only exist if GetDir succeeded
+ CleanupStack::PushL(dir);
+ for(TInt i = 0; i < dir->Count(); i++)
+ {
+ const TEntry &entry = (*dir)[i];
+ if(!entry.IsDir())
+ {
+ TFileName fileName(preInstalledPath);
+ fileName.Append(entry.iName);
+ iSisInstaller->AddFileToInstallL(fileName);
+ }
+ }
+ CleanupStack::PopAndDestroy(dir);
+ }
+ }
+
+
+// From MDaemonInstallBehaviour
+
+MDaemonInstallBehaviour::TSisInstallState CDaemonBehaviour::VerifyAppCacheListL()
+ {
+ MDaemonInstallBehaviour::TSisInstallState returnState = MDaemonInstallBehaviour::EStateVerifyAppCacheList;
+
+ // What is really desired is notification that the Application Architecture cached List
+ // is valid, but as this cannot be done simply.
+ // Is is simulated by a call to two member functions.
+
+ TApaAppInfo appInfo;
+ User::LeaveIfError(iApaSession.GetAllApps());
+ TInt err(iApaSession.GetNextApp(appInfo)); // Call member function that can report an EAppListInvalid
+
+ if (err == RApaLsSession::EAppListInvalid)
+ {
+ returnState = MDaemonInstallBehaviour::EStateVerifyAppCacheList;
+ }
+ else if (err == KErrNone) // cached list of apps is ready
+ {
+ returnState = MDaemonInstallBehaviour::EStateVerifySwisProperty;
+ }
+ else
+ {
+ User::Leave(err);
+ }
+ return returnState;
+ }
+
+MDaemonInstallBehaviour::TSisInstallState CDaemonBehaviour::VerifySwisPropertyL()
+ {
+ MDaemonInstallBehaviour::TSisInstallState returnState = MDaemonInstallBehaviour::EStateVerifySwisProperty;
+ TInt swisState;
+ TInt err(RProperty::Get(KUidSystemCategory,KUidSoftwareInstallKey,swisState));
+
+ if (err == KErrNotFound)
+ {
+ returnState = (MDaemonInstallBehaviour::EStateInstall);
+ }
+ else if (err == KErrNone)
+ {
+ if (swisState == ESwisNone)
+ {
+ // SWIS is idle
+ returnState = (MDaemonInstallBehaviour::EStateInstall);
+ }
+ else
+ {
+ // SWIS is performing an operation
+ returnState = (MDaemonInstallBehaviour::EStateVerifySwisIdle);
+ }
+ }
+ else
+ {
+ User::Leave(err);
+ }
+ return returnState;
+ }
+
+MDaemonInstallBehaviour::TSisInstallState CDaemonBehaviour::VerifySwisIdleL()
+ {
+ MDaemonInstallBehaviour::TSisInstallState returnState = MDaemonInstallBehaviour::EStateVerifySwisIdle;
+ TInt swisState;
+
+ // Obtain the state of the software installer
+ User::LeaveIfError(RProperty::Get(KUidSystemCategory,KUidSoftwareInstallKey,swisState));
+
+ if (swisState == ESwisNone) // Swis is idle
+ {
+ returnState = (MDaemonInstallBehaviour::EStateInstall);
+ }
+ else // Software installer is currently installing/uinstalling
+ {
+ returnState = (MDaemonInstallBehaviour::EStateVerifySwisIdle);
+ }
+ return returnState;
+ }
+
+void CDaemonBehaviour::ReadSymbianHeaderL(RFile& aFile, TUid& aUid1, TUid& aUid2, TUid& aUid3)
+ {
+
+ TInt uidLen = sizeof(TInt32);
+
+ TPckg<TInt32> uid1(aUid1.iUid);
+ User::LeaveIfError(aFile.Read(uid1, uidLen));
+ if (uid1.Length() != uidLen)
+ {
+ User::Leave(KErrUnderflow);
+ }
+
+ TPckg<TInt32> uid2(aUid2.iUid);
+ User::LeaveIfError(aFile.Read(uid2, uidLen));
+ if (uid1.Length() != uidLen)
+ {
+ User::Leave(KErrUnderflow);
+ }
+
+ TPckg<TInt32> uid3(aUid3.iUid);
+ User::LeaveIfError(aFile.Read(uid3, uidLen));
+ if (uid1.Length() != uidLen)
+ {
+ User::Leave(KErrUnderflow);
+ }
+
+ }
+
+void CDaemonBehaviour::DoInstallRequestL(const TDesC& aFileName)
+ {
+ DEBUG_PRINTF2(_L("SWI Daemon - Processing presinstalled SIS file '%S'"),
+ &aFileName);
+
+ TUid appUid;
+ TDataType dataType;
+
+ User::LeaveIfError(iFs.ShareProtected());
+
+ // have to pass the file using the file handle
+ // otherwise SisHelper won't be able to read the
+ // daemon private directory
+ RFile file;
+ User::LeaveIfError(file.Open(iFs, aFileName, EFileRead | EFileStream | EFileShareReadersOnly));
+ CleanupClosePushL(file);
+ User::LeaveIfError(iApaSession.AppForDocument(file,appUid,dataType));
+
+ // Start installing the file only if it is a sisx file
+ if (dataType.Des8() == KDataTypeSisx)
+ {
+
+ // Check if this is already installed, by extracting the package UID and
+ // asking the registry.
+
+ TUid uid1, uid2, uid3;
+ ReadSymbianHeaderL(file, uid1, uid2, uid3);
+
+
+ // UID 3 will be the package UID, query the registry about it.
+ RSisRegistrySession session;
+ User::LeaveIfError(session.Connect());
+ CleanupClosePushL(session);
+
+ // temporary work around while we decide what IsInstalled should be policed by.
+
+ RSisRegistryEntry entry;
+ TInt entryOpenResult = entry.Open(session, uid3);
+ CleanupClosePushL(entry);
+
+ // Get the types and other details from the stub
+ CFileSisDataProvider* fileProvider = CFileSisDataProvider::NewLC(iFs, aFileName, EFileRead | EFileShareReadersOnly);
+ TInt64 pos( 0 );
+ fileProvider->Seek( ESeekStart, pos );
+ Swi::Sis::CContents* content = Swi::Sis::Parser::ContentsL(*fileProvider);
+ CleanupStack::PushL( content );
+ HBufC8* controllerdata = content->ReadControllerL();
+ CleanupStack::PushL( controllerdata );
+ TPtrProvider provider(controllerdata->Des());
+ Sis::CController *siscontroller = Swi::Sis::CController::NewLC(provider);
+
+ switch(siscontroller->Info().InstallType())
+ {
+ /* For SA/PA, If UID is found in registry, Don't install otherwise Install */
+ case EInstInstallation:
+ case EInstPreInstalledApp:
+ {
+ if(entryOpenResult != KErrNone)
+ {
+ DoInstallL(file,appUid);
+ }
+
+ break;
+ }
+ /*
+ For PP/SP, If patch name is found already in registry, Don't install
+ otherwise Install
+ */
+ case EInstPreInstalledPatch:
+ case EInstAugmentation:
+ {
+ TBool shouldInstall = ETrue;
+ const RPointerArray<CString>& names = siscontroller->Info().Names();
+ RPointerArray<CSisRegistryPackage> augmentations;
+
+ // If Base package is not available then don't do anything and break the case.
+ if (entryOpenResult != KErrNone)
+ {
+ break;
+ }
+
+ //Get the Augmentation and Install if augmentation doesn't match
+ CleanupResetAndDestroy<RPointerArray<CSisRegistryPackage> >::PushL(augmentations);
+ entry.AugmentationsL(augmentations);
+ for (TInt i = 0; i < augmentations.Count(); ++i)
+ {
+ for (TInt j =0; j < names.Count(); ++j)
+ {
+ if ((uid3 == augmentations[i]->Uid()) &&
+ (augmentations[i]->Name() == names[j]->Data()))
+ {
+ shouldInstall=EFalse;
+ break;
+ }
+ }
+ }
+
+ if(shouldInstall)
+ {
+ DoInstallL(file,appUid);
+ }
+
+ CleanupStack::PopAndDestroy(&augmentations);
+ break;
+ }
+
+ default:
+ /*
+ If SA/PA/SP/PP is not the case we can't handle because
+ PU has never been supported for SwiDaemon according to FS.
+ */
+ ASSERT(EFalse);
+
+ }
+
+ CleanupStack::PopAndDestroy(6, &session);
+
+ } // End of SISX file condition
+
+ CleanupStack::PopAndDestroy(&file); // close
+ }
+
+void CDaemonBehaviour::DoNotifyMediaProcessingComplete()
+ {
+ if(iSwiDaemonPlugin && iStartNotified)
+ {
+ iSwiDaemonPlugin->MediaProcessingComplete();
+ }
+ }
+
+void CDaemonBehaviour::DoInstallL(RFile &file, const TUid &appUid)
+ {
+
+ // Rewind file
+ TInt pos = 0;
+ file.Seek(ESeekStart, pos);
+
+ if(iSwiDaemonPlugin)
+ {
+ DEBUG_PRINTF(_L8("SWI Daemon - Using external plugin to process install"));
+
+ if(!iStartNotified)
+ {
+ iSwiDaemonPlugin->MediaProcessingStart(iDrive);
+ iStartNotified = ETrue;
+ }
+ iSwiDaemonPlugin->RequestInstall(file);
+ }
+
+ else
+ {
+ DEBUG_PRINTF(_L8("SWI Daemon - Using internal logic to process install"));
+
+ TThreadId threadId;
+ User::LeaveIfError(iApaSession.StartDocument(file,appUid,threadId));
+
+ RThread thread;
+ User::LeaveIfError(thread.Open(threadId));
+ CleanupClosePushL(thread);
+
+ // Wait for the installer to terminate before launching another install.
+
+ TRequestStatus status;
+ thread.Logon(status);
+ User::WaitForRequest(status);
+ CleanupStack::PopAndDestroy(&thread);
+ }
+ }