diff -r e5618cc85d74 -r 6c158198356e javamanager/javacaptain/extensionplugins/scrupdater/src/scrupdater.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javamanager/javacaptain/extensionplugins/scrupdater/src/scrupdater.cpp Thu Aug 19 09:48:13 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 +#include +#include + +#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 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 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 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 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 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 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 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