javamanager/javacaptain/extensionplugins/scrupdater/src/scrupdater.cpp
changeset 49 35baca0e7a2e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javamanager/javacaptain/extensionplugins/scrupdater/src/scrupdater.cpp	Tue Jul 06 20:36:19 2010 +0300
@@ -0,0 +1,666 @@
+/*
+* Copyright (c) 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:  ScrUpdater is Java Captain Symbian plugin that updates
+*               presence information of Java Applications in USIF SCR
+*               when removable drive is added or removed to the device.
+*
+*/
+
+#include <apgcli.h>
+#include <e32base.h>
+#include <f32file.h>
+
+#include "javaprocessconstants.h"
+#include "javasymbianoslayer.h"
+#include "javauids.h"
+#include "logger.h"
+#include "coreinterface.h"
+#include "booteventprovidermessages.h"
+#include "mmceventprovidermessages.h"
+
+#include "scrupdater.h"
+
+using namespace Usif;
+
+_LIT(KMediaId, "Media-Id");
+
+/**
+ * Return pointer to ExtensionPluginInterface implementation for this
+ * extension dll
+ */
+java::captain::ExtensionPluginInterface* getExtensionPlugin()
+{
+    return new java::captain::ScrUpdater();
+}
+
+namespace java  // codescanner::namespace
+{
+namespace captain  // codescanner::namespace
+{
+
+using java::fileutils::driveInfo;
+using java::fileutils::DriveListenerInterface;
+
+/**
+ * Empty contructor
+ */
+ScrUpdater::ScrUpdater()
+{
+}
+
+/**
+ * Empty destructor
+ */
+ScrUpdater::~ScrUpdater()
+{
+}
+
+/**
+ * Implement PluginInterface method
+ */
+void ScrUpdater::startPlugin(CoreInterface* /* aCore */)
+{
+    LOG(EJavaCaptain, EInfo, "ScrUpdater plugin started");
+}
+
+/**
+ * Implement PluginInterface method
+ */
+void ScrUpdater::stopPlugin()
+{
+}
+
+/**
+ * Implement ExtensionPluginInterface method
+ */
+EventConsumerInterface* ScrUpdater::getEventConsumer()
+{
+    return this;
+}
+
+/**
+ * Handle Java Captain events sent by Boot event provider or
+ * MMC event provider.
+ *
+ * Implement EventConsumerInterface method
+ */
+void ScrUpdater::event(const std::string& aEventProvider,
+                       java::comms::CommsMessage& aMsg)
+{
+    if (aEventProvider == BOOT_EVENT_PROVIDER)
+    {
+        int bootType = NORMAL_BOOT_C;
+        getBootMessageParams(aMsg, bootType);
+        LOG1(
+            EJavaCaptain,
+            EInfo,
+            "ScrUpdater::event() boot event received (type=%d)",
+            bootType);
+        switch (bootType)
+        {
+            case IAD_BOOT_C:
+            case FIRST_DEVICE_BOOT_C:
+            case NORMAL_BOOT_C:
+            {
+                // Update presence information
+                TRAPD(err, initializeScrPresenceInfoL())
+                if (KErrNone != err)
+                {
+                    ELOG1(EJavaCaptain, "initializeScrPresenceInfoL: leaved (%d)", err);
+                }
+            }
+            break;
+
+            default:
+            {
+                WLOG1(EJavaCaptain,
+                    "DriveListenerInterface: event() unknown boot event (type=%d)", bootType);
+            }
+            break;
+        }
+    }
+    else if (aEventProvider == MMC_EVENT_PROVIDER)
+    {
+        int operation = 0;
+        driveInfo di;
+        getMmcChangedMessageParams(aMsg, operation, di);
+        LOG1(
+            EJavaCaptain,
+            EInfo,
+            "ScrUpdater::event() mmc event received (operation=%d)",
+            operation);
+
+        switch (operation)
+        {
+            case DriveListenerInterface::REMOVABLE_MEDIA_REMOVED_C:
+            {
+                // All Java applications in the removed drive are set
+                // to 'not present' state
+                TRAPD(err, removeScrPresencesL(&di));
+                if (KErrNone != err)
+                {
+                    ELOG1(EJavaCaptain, "removeScrPresencesL leaved (%d)", err);
+                }
+            }
+            break;
+
+            case DriveListenerInterface::REMOVABLE_MEDIA_INSERTED_C:
+            {
+                // Those Java applications in the drive to where the media
+                // (e.g. memory card) was added are set to 'present' state
+                // IF the media id is correct (in other words if the same
+                // memory card that they have been installed to is added
+                // to the drive).
+                TRAPD(err, addScrPresencesL(&di));
+                if (KErrNone != err)
+                {
+                    ELOG1(EJavaCaptain, "addScrPresencesL leaved (%d)", err);
+                }
+            }
+            break;
+        }
+    }
+}
+
+/**
+ * Set the presence state of all Java applications installed
+ * to the removable drive specified in aInfo to not present
+ */
+void ScrUpdater::removeScrPresencesL(driveInfo *aInfo)
+{
+    __UHEAP_MARK;
+    LOG1WSTR(EJavaCaptain, EInfo,
+        "removeScrPresencesL: driveInfo root path is %s", aInfo->iRootPath);
+
+    RSoftwareComponentRegistry *pScr = createScrL();
+    CleanupStack::PushL(pScr);
+
+    // Get ids of all Java components in scr
+    RArray<TComponentId> componentIdList;
+    CleanupClosePushL(componentIdList);
+
+    CComponentFilter *pJavaSwTypeFilter = CComponentFilter::NewLC();
+    pJavaSwTypeFilter->SetSoftwareTypeL(Usif::KSoftwareTypeJava);
+
+    pScr->GetComponentIdsL(componentIdList, pJavaSwTypeFilter);
+    CleanupStack::PopAndDestroy(pJavaSwTypeFilter);
+
+    // For each component check whether it has been installed
+    // to the removed drive
+    TInt  nComponents = componentIdList.Count();
+    TUint removedDrive = (TUint)(aInfo->iRootPath[0]);
+    // Now removedDrive contains the drive letter, convert it to drive number 0-25
+    if ((removedDrive > 64) && (removedDrive < 91))  // codescanner::magicnumbers
+    {
+        // 'A' - 'Z'
+        removedDrive -= 65;  // codescanner::magicnumbers
+    }
+    else if ((removedDrive > 96) && (removedDrive < 123))  // codescanner::magicnumbers
+    {
+        // 'a' - 'z'
+        removedDrive -= 97;  // codescanner::magicnumbers
+    }
+    else
+    {
+        ELOG1WSTR(EJavaCaptain,
+            "removeScrPresencesL: Unexpected root path in remove drive info %s",
+            aInfo->iRootPath);
+        CleanupStack::PopAndDestroy(pScr);
+        return;
+    }
+
+    LOG2(EJavaCaptain, EInfo, "Number of Java components is %d, removed drive is %d",
+        nComponents, removedDrive);
+
+    RArray<TApaAppUpdateInfo> removedApps;
+    CleanupClosePushL(removedApps);
+
+    for (TInt nInd = 0; nInd < nComponents; nInd++)
+    {
+        CComponentEntry *pEntry = CComponentEntry::NewLC();
+        if (!(pScr->GetComponentL(componentIdList[nInd], *pEntry)))
+        {
+            ELOG1(EJavaCaptain,
+                "removeScrPresencesL: SCR GetComponentIdsL returned id %d "
+                "but GetComponentL does not find it", componentIdList[nInd]);
+            CleanupStack::PopAndDestroy(pEntry);
+            continue;
+        }
+
+        TInt nInstalledDrives = pEntry->InstalledDrives().Length();
+        if (nInstalledDrives <= removedDrive)
+        {
+            // SCR InstalledDrives should be array of 26 elements (value 0 or 1)
+            ELOG2(EJavaCaptain,
+                "removeScrPresencesL: The length of InstalledDrives array (%d) "
+                "is smaller than removedDrive (%d)", nInstalledDrives, removedDrive);
+            CleanupStack::PopAndDestroy(pEntry);
+            continue;
+        }
+
+        LOG1(EJavaCaptain, EInfo, "Java component id %d", componentIdList[nInd]);
+
+        if (pEntry->InstalledDrives()[removedDrive])
+        {
+            // This component has been installed to the drive
+            // that has just been removed
+            pScr->SetIsComponentPresentL(componentIdList[nInd], EFalse);
+
+            LOG1(EJavaCaptain, EInfo,
+                "removeScrPresencesL: set component %d to not present",
+                componentIdList[nInd]);
+
+            // Gather the Uids of all applications that are no longer present
+            RArray<TUid> appsInComponent;
+            CleanupClosePushL(appsInComponent);
+            pScr->GetAppUidsForComponentL(
+                componentIdList[nInd], appsInComponent);
+            for (TInt nInd2 = 0; nInd2 < appsInComponent.Count(); nInd2++)
+            {
+                TApaAppUpdateInfo appInfo;
+                appInfo.iAppUid = appsInComponent[nInd2];
+                appInfo.iAction = TApaAppUpdateInfo::EAppNotPresent;
+                removedApps.AppendL(appInfo);
+            }
+            CleanupStack::PopAndDestroy(&appsInComponent);
+        }
+
+        CleanupStack::PopAndDestroy(pEntry);
+    }
+
+    // Tell AppArc which applications are no longer present
+    if (removedApps.Count() > 0)
+    {
+        RApaLsSession apaSession;
+        TInt err = apaSession.Connect();
+        if (KErrNone != err)
+        {
+            ELOG1(EJavaCaptain, "removeScrPresencesL: Error %d when connecting AppArc", err);
+        }
+        else
+        {
+            CleanupClosePushL(apaSession);
+            apaSession.UpdateAppListL(removedApps);
+            CleanupStack::PopAndDestroy(); // closes apaSession
+        }
+    }
+
+    CleanupStack::PopAndDestroy(); // Close removedApps
+    CleanupStack::PopAndDestroy(); // Close componentIdList
+    CleanupStack::PopAndDestroy(pScr);
+    __UHEAP_MARKEND;
+}
+
+
+/**
+ * Set the presence state of all Java applications installed
+ * to the removable drive specified in aInfo to present
+ */
+void ScrUpdater::addScrPresencesL(driveInfo *aInfo)
+{
+    __UHEAP_MARK;
+    LOG1WSTR(EJavaCaptain, EInfo,
+        "addScrPresencesL: driveInfo root path is %s", aInfo->iRootPath);
+
+    RSoftwareComponentRegistry *pScr = createScrL();
+    CleanupStack::PushL(pScr);
+
+    // Get ids of all Java components in scr
+    RArray<TComponentId> componentIdList;
+    CleanupClosePushL(componentIdList);
+
+    CComponentFilter *pJavaSwTypeFilter = CComponentFilter::NewLC();
+    pJavaSwTypeFilter->SetSoftwareTypeL(Usif::KSoftwareTypeJava);
+
+    pScr->GetComponentIdsL(componentIdList, pJavaSwTypeFilter);
+    CleanupStack::PopAndDestroy(pJavaSwTypeFilter);
+
+    // For each component check whether it has been installed
+    // to the added drive AND whether the media id is correct
+    // (in other words if the actual memory card where the component
+    // has been installed to is added to the drive).
+    TInt  nComponents  = componentIdList.Count();
+    TUint addedMediaId = (TUint)(aInfo->iId);
+    TUint addedDrive   = (TUint)(aInfo->iRootPath[0]);
+    // Now addedDrive contains the drive letter, convert it to drive number 0-25
+    if ((addedDrive > 64) && (addedDrive < 91))  // codescanner::magicnumbers
+    {
+        // 'A' - 'Z'
+        addedDrive -= 65;  // codescanner::magicnumbers
+    }
+    else if ((addedDrive > 96) && (addedDrive < 123))  // codescanner::magicnumbers
+    {
+        // 'a' - 'z'
+        addedDrive -= 97;  // codescanner::magicnumbers
+    }
+    else
+    {
+        ELOG1WSTR(EJavaCaptain,
+            "addScrPresencesL: Unexpected root path in add drive info %s",
+            aInfo->iRootPath);
+        CleanupStack::PopAndDestroy(pScr);
+        return;
+    }
+
+    LOG2(EJavaCaptain, EInfo, "Number of Java components is %d, added drive is %d",
+        nComponents, addedDrive);
+
+    RArray<TApaAppUpdateInfo> addedApps;
+    CleanupClosePushL(addedApps);
+
+    for (TInt nInd = 0; nInd < nComponents; nInd++)
+    {
+        CComponentEntry *pEntry = CComponentEntry::NewLC();
+        if (!(pScr->GetComponentL(componentIdList[nInd], *pEntry)))
+        {
+            ELOG1(EJavaCaptain,
+                "addScrPresencesL: SCR GetComponentIdsL returned id %d "
+                "but GetComponentL does not find it", componentIdList[nInd]);
+            CleanupStack::PopAndDestroy(pEntry);
+            continue;
+        }
+
+        // When Java Installer registers Java app to SCR it stores also
+        // the media id using SetComponentPropertyL(TComponentId aComponentId,
+        // _L("Media-Id"), TInt64 aValue);  (aValue is actually 32 bit int)
+        CIntPropertyEntry* pMediaIdProperty = (CIntPropertyEntry *)
+            pScr->GetComponentPropertyL(componentIdList[nInd], KMediaId);
+        if (NULL == pMediaIdProperty)
+        {
+            ELOG1(EJavaCaptain,
+                "addScrPresencesL: media_id property not found for component %d",
+                componentIdList[nInd]);
+            CleanupStack::PopAndDestroy(pEntry);
+            continue;
+        }
+        CleanupStack::PushL(pMediaIdProperty);
+
+        TInt nInstalledDrives = pEntry->InstalledDrives().Length();
+        if (nInstalledDrives <= addedDrive)
+        {
+            // SCR InstalledDrives should be array of 26 elements (value 0 or 1)
+            ELOG2(EJavaCaptain,
+                "addScrPresencesL: The length of InstalledDrives array (%d) "
+                "is smaller than addedDrive (%d)", nInstalledDrives, addedDrive);
+            CleanupStack::PopAndDestroy(pEntry);
+            continue;
+        }
+
+        LOG1(EJavaCaptain, EInfo, "Java component id %d", componentIdList[nInd]);
+
+        if (pEntry->InstalledDrives()[addedDrive])
+        {
+            // This component has been installed to the drive
+            // that has just been added.
+            // Now check whether the media id of the added media
+            // is OK for this component.
+            if (addedMediaId == pMediaIdProperty->IntValue())
+            {
+                pScr->SetIsComponentPresentL(componentIdList[nInd], ETrue);
+
+                LOG1(EJavaCaptain, EInfo,
+                    "addScrPresencesL: set component %d to present",
+                    componentIdList[nInd]);
+
+                // Gather the Uids of all 'new' applications that are now present
+                RArray<TUid> appsInComponent;
+                CleanupClosePushL(appsInComponent);
+                pScr->GetAppUidsForComponentL(
+                    componentIdList[nInd], appsInComponent);
+                for (TInt nInd2 = 0; nInd2 < appsInComponent.Count(); nInd2++)
+                {
+                    TApaAppUpdateInfo appInfo;
+                    appInfo.iAppUid = appsInComponent[nInd2];
+                    appInfo.iAction = TApaAppUpdateInfo::EAppPresent;
+                    addedApps.AppendL(appInfo);
+                }
+                CleanupStack::PopAndDestroy(&appsInComponent);
+            }
+        }
+
+        CleanupStack::PopAndDestroy(pMediaIdProperty);
+        CleanupStack::PopAndDestroy(pEntry);
+    }
+
+    // Tell AppArc which 'new' applications are now present
+    if (addedApps.Count() > 0)
+    {
+        RApaLsSession apaSession;
+        TInt err = apaSession.Connect();
+        if (KErrNone != err)
+        {
+            ELOG1(EJavaCaptain, "addScrPresencesL: Error %d when connecting AppArc", err);
+        }
+        else
+        {
+            CleanupClosePushL(apaSession);
+            apaSession.UpdateAppListL(addedApps);
+            CleanupStack::PopAndDestroy(); // closes apaSession
+        }
+    }
+
+    CleanupStack::PopAndDestroy(); // Close addedApps
+    CleanupStack::PopAndDestroy(); // Close componentIdList
+    CleanupStack::PopAndDestroy(pScr);
+    __UHEAP_MARKEND;
+}
+
+
+/**
+ * Loop through all removable drives and get the media id of
+ * the memory card or other removable media in the drive and update
+ * presence information of all Java applications installed
+ * to removable drives accordingly.
+ */
+void ScrUpdater::initializeScrPresenceInfoL()
+{
+    __UHEAP_MARK;
+    RFs fs;  // codescanner::rfs
+    User::LeaveIfError(fs.Connect());
+    CleanupClosePushL(fs);
+
+    // Which drives are present and what is the media id of
+    // each removable volume
+    TInt  err = KErrNone;
+    TInt  err2 = KErrNone;
+    TBool drivePresent[EDriveZ + 1];
+    TUint driveMediaId[EDriveZ + 1];
+    TVolumeInfo volumeInfo;
+    TDriveInfo  driveInfo;
+
+    for (TInt nInd = EDriveA; nInd < EDriveZ; nInd++)
+    {
+        err = fs.Volume(volumeInfo, nInd);
+        if (KErrNone == err)
+        {
+            drivePresent[nInd] = ETrue;  // codescanner::accessArrayElementWithoutCheck2
+            driveMediaId[nInd] = volumeInfo.iUniqueID;  // codescanner::accessArrayElementWithoutCheck2
+            // If the media is not removable, media id is not checked
+            err2 = fs.Drive(driveInfo, nInd);
+            if (KErrNone != err2)
+            {
+                ELOG1(EJavaCaptain,
+                    "initializeScrPresenceInfoL: error (%d) when trying to get drive info",
+                    err2);
+                User::Leave(err2);
+            }
+            else
+            {
+                if (!(driveInfo.iDriveAtt & KDriveAttRemovable))
+                {
+                    driveMediaId[nInd] = 0;  // codescanner::accessArrayElementWithoutCheck2
+                }
+            }
+        }
+        else if (KErrNotReady == err)
+        {
+            // no volume in this drive
+            drivePresent[nInd] = EFalse;  // codescanner::accessArrayElementWithoutCheck2
+            driveMediaId[nInd] = 0;  // codescanner::accessArrayElementWithoutCheck2
+        }
+        else
+        {
+            ELOG1(EJavaCaptain,
+                "initializeScrPresenceInfoL: error (%d) when trying to get volume info",
+                err);
+            User::Leave(err);
+        }
+    }
+    CleanupStack::PopAndDestroy(); // close RFs
+
+
+    RSoftwareComponentRegistry *pScr = createScrL();
+    CleanupStack::PushL(pScr);
+
+    // Get ids of all Java components in scr
+    RArray<TComponentId> componentIdList;
+    CComponentFilter *pJavaSwTypeFilter = CComponentFilter::NewLC();
+    pJavaSwTypeFilter->SetSoftwareTypeL(Usif::KSoftwareTypeJava);
+
+    pScr->GetComponentIdsL(componentIdList, pJavaSwTypeFilter);
+    CleanupStack::PopAndDestroy(pJavaSwTypeFilter);
+    CleanupClosePushL(componentIdList);
+
+    // For each component check whether the drive it has been installed
+    // to is present AND whether the media id is correct
+    TInt  nComponents  = componentIdList.Count();
+
+    LOG1(EJavaCaptain, EInfo, "initializeScrPresenceInfoL: Number of Java components is %d",
+        nComponents);
+
+    for (TInt nInd = 0; nInd < nComponents; nInd++)
+    {
+        CComponentEntry *pEntry = CComponentEntry::NewLC();
+        if (!(pScr->GetComponentL(componentIdList[nInd], *pEntry)))
+        {
+            ELOG1(EJavaCaptain,
+                "initializeScrPresenceInfoL: SCR GetComponentIdsL returned id %d "
+                "but GetComponentL does not find it", componentIdList[nInd]);
+            CleanupStack::PopAndDestroy(pEntry);
+            continue;
+        }
+
+        CIntPropertyEntry* pMediaIdProperty = (CIntPropertyEntry *)
+            pScr->GetComponentPropertyL(componentIdList[nInd], KMediaId);
+        if (NULL == pMediaIdProperty)
+        {
+            ELOG1(EJavaCaptain,
+                "initializeScrPresenceInfoL: media_id property not found for component %d",
+                componentIdList[nInd]);
+            CleanupStack::PopAndDestroy(pEntry);
+            continue;
+        }
+        CleanupStack::PushL(pMediaIdProperty);
+
+        TInt nInstalledDrives = pEntry->InstalledDrives().Length();
+        if (nInstalledDrives > (EDriveZ + 1))
+        {
+            WLOG2(EJavaCaptain,
+                "initializeScrPresenceInfoL: too big (%d) installed drives array for "
+                "component %d", nInstalledDrives, componentIdList[nInd]);
+            nInstalledDrives = EDriveZ;
+        }
+        // When Java components are installed, only one installed drive
+        // and corresponding media id are registered.
+        TInt installationDrive = -1;
+
+        for (TInt driveNumber = EDriveA; driveNumber < nInstalledDrives; driveNumber++)
+        {
+            if (pEntry->InstalledDrives()[driveNumber])
+            {
+                installationDrive = driveNumber;
+                break;
+            }
+        }
+
+        if (installationDrive == -1)
+        {
+            ELOG1(EJavaCaptain,
+                "initializeScrPresenceInfoL: component (id %d) did not have installed drive info",
+                componentIdList[nInd]);
+            CleanupStack::PopAndDestroy(pMediaIdProperty);
+            CleanupStack::PopAndDestroy(pEntry);
+            continue;
+        }
+
+        if (drivePresent[installationDrive])  // codescanner::accessArrayElementWithoutCheck2
+        {
+            // Check also the media id
+            if (driveMediaId[installationDrive] == pMediaIdProperty->IntValue())  // codescanner::accessArrayElementWithoutCheck2
+            {
+                LOG1(EJavaCaptain, EInfo,
+                    "initializeScrPresenceInfoL: set component %d to present",
+                    componentIdList[nInd]);
+
+                pScr->SetIsComponentPresentL(componentIdList[nInd], ETrue);
+            }
+            else
+            {
+                LOG1(EJavaCaptain, EInfo,
+                    "initializeScrPresenceInfoL: set component %d to NOT present",
+                    componentIdList[nInd]);
+
+                pScr->SetIsComponentPresentL(componentIdList[nInd], EFalse);
+            }
+        }
+        else
+        {
+            LOG1(EJavaCaptain, EInfo,
+                "initializeScrPresenceInfoL: set component %d to NOT present",
+                componentIdList[nInd]);
+
+            // drive is not present -> Java component installed to that
+            // drive is not present
+            pScr->SetIsComponentPresentL(componentIdList[nInd], EFalse);
+        }
+
+        CleanupStack::PopAndDestroy(pMediaIdProperty);
+        CleanupStack::PopAndDestroy(pEntry);
+    }
+
+    CleanupStack::PopAndDestroy(); // Close componentIdList
+    CleanupStack::PopAndDestroy(pScr); // Also closes RSoftwareComponentRegistry
+
+    __UHEAP_MARKEND;
+}
+
+
+/**
+ * Creates an instance of RSoftwareComponentRegistry and connects to it.
+ */
+RSoftwareComponentRegistry *ScrUpdater::createScrL()
+{
+    RSoftwareComponentRegistry *pScr = new RSoftwareComponentRegistry;  // codescanner::nonleavenew
+    if (NULL == pScr)
+    {
+        ELOG(EJavaInstaller,
+            "CreateScrL: Creating RSoftwareComponentRegistry failed");
+        User::Leave(KErrGeneral);
+    }
+    TInt err = pScr->Connect();
+    if (KErrNone != err)
+    {
+        ELOG1(EJavaInstaller,
+            "CreateScrL: Connecting to RSoftwareComponentRegistry failed, error %d",
+            err);
+        delete pScr;
+        User::Leave(err);
+    }
+
+    return pScr;
+}
+
+
+} // namespace captain
+} // namespace java