diff -r f5050f1da672 -r 04becd199f91 javatools/javaappbackconverter/src.s60/main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javatools/javaappbackconverter/src.s60/main.cpp Tue Apr 27 16:30:29 2010 +0300 @@ -0,0 +1,406 @@ +/* +* Copyright (c) 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: Java platform 2.0 javaappbackconverter process +* +*/ + + +#include +#include +#include +#include +#include +#include +#include + +#include "javacommonutils.h" +#include "javauids.h" +#include "backconverter.h" +#include "noarmlogs.h" + +_LIT_SECURE_ID(KAppInstUiSecureID, 0x101F875A); +_LIT_SECURE_ID(KAppSisLauncherSecureID, 0x1020473F); + + +/** + * Create file server connection. + * If no data storage file exists, exit. + * Create active scheduler and start it to execute actual back converter. + */ +static void ExecuteBackConverterL(RFs &aFs) +{ + LOG(EJavaConverters, EInfo, "javaappbackconverter: ExecuteBackConverterL called"); + + CActiveScheduler* as = new(ELeave) CActiveScheduler(); + + // Install active scheduler + CActiveScheduler::Install(as); + CleanupStack::PushL(as); + + // The file server session must be shared so that that AppArc can + // use the icon file handle opened in back converter + TInt err = aFs.ShareProtected(); + if (KErrNone != err) + { + ELOG1(EJavaConverters, + "javaappbackconverter: ExecuteBackConverterL: " + "Cannot share file server session, err code is %d ", err); + User::Leave(err); + } + + // Setup and start the back conversion + CBackConverter* back = CBackConverter::NewLC(aFs); + + LOG(EJavaConverters, + EInfo, "javaappbackconverter: ExecuteBackConverterL: Call CBackConverter::Start()"); + + back->Start(); + + // Start active scheduler + LOG(EJavaConverters, EInfo, "ExecuteBackConverterL: Starting CActiveScheduler"); + CActiveScheduler::Start(); + + LOG(EJavaConverters, EInfo, "javaappbackconverter: ExecuteBackConverterL: Cleaning up"); + + CleanupStack::PopAndDestroy(back); + CleanupStack::PopAndDestroy(as); +} + +/** + * Menu application has a central repository key that can be used in + * devices belonging to Nokia 5800 XpressMusic device family to request + * that the Menu application would rescan all applications it contains. + */ +static void UseCRKeyToUpdateAppShellDataL() +{ + const TUid KCRUidMenu = { 0x101F8847 }; + const TUint32 KMenuUpdateData = 0x00000001; + + // Update Central Rep + CRepository *pCenRep = CRepository::NewL(KCRUidMenu); + + TInt value = 1; + TInt err = pCenRep->Set(KMenuUpdateData, value); + if (KErrNone != err) + { + ELOG1(EJavaConverters, + "javaappbackconverter: UseCRKeyToUpdateAppShellDataL: " + "setting cenrep value failed, error %d ", + err); + } + + delete pCenRep; +} + +/** + * After OMJ has been uninstalled the menu application of the device + * does not display the icons of the old, restored java applications. + * The icons are shown after the device is booted. + * Tell menu application to scan again all applications so that the icons + * will be shown. + */ +static void AddOldJavaAppIconsToMenuApp() +{ + LOG(EJavaConverters, EInfo, "javaappbackconverter: AddOldJavaAppIconsToMenuApp called."); + + TRAPD(err, UseCRKeyToUpdateAppShellDataL()); + if (KErrNotFound == err) + { + // Only Nokia XPressMusic 5800 device family supports this feature, + // N97 and later devices no longer support it but they have new Menu + // application that shows all Java application icons anyway. + LOG(EJavaConverters, EInfo, + "javaappbackconverter: AddOldJavaAppIconsToMenuApp: This device does not " + "support refreshing Menu using CR keys."); + } + else if (KErrNone != err) + { + ELOG1(EJavaConverters, + "javaappbackconverter: AddOldJavaAppIconsToMenuApp: Error: %d", err); + } +} + +/** + * Kill the running OMJ javaregistry.exe. After killing next call to + * Registry API restarts the old S60 server process. + */ +static void KillRegistry() +{ + LOG(EJavaConverters, EInfo, "javaappbackconverter: KillRegistry called."); + + TFullName processName; + _LIT(KJavaRegistryProcess, "javaregistry*"); + TFindProcess finder(KJavaRegistryProcess); + + if (finder.Next(processName) != KErrNotFound) + { + RProcess processToKill; + TInt err = processToKill.Open(finder); + + if (KErrNone != err) + { + WLOG1(EJavaConverters, "javaappbackconverter: Process open: %d", err); + } + else + { + processToKill.Kill(KErrNone); + processToKill.Close(); + } + } + else + { + WLOG(EJavaConverters, "javaappbackconverter: Registry process not found"); + } +} + +/** + * Unregister OMJ MIDlet starter, reregister old S60 MIDlet starter + */ +static void ReregisterOldMidletStarter() +{ + LOG(EJavaConverters, EInfo, "javaappbackconverter: ReregisterOldMidletStarter called"); + + _LIT(KStubMIDP2RecogExe, "StubMIDP2RecogExe.exe"); + + RApaLsSession appLstSession; + + TInt error = appLstSession.Connect(); + if (error != KErrNone) + { + ELOG1(EJavaConverters, "javaappbackconverter: ReregisterOldMidletStarter: " + "RApaLsSession.Connect failed with error %d", error); + return; + } + TRAP(error, appLstSession.RegisterNonNativeApplicationTypeL( + TUid::Uid(KMidletApplicationTypeUid), KStubMIDP2RecogExe())); + if (error == KErrNone) + { + LOG(EJavaConverters, EInfo, "javaappbackconverter: ReregisterOldMidletStarter: " + "Registered MIDlet application type for S60 Java."); + } + else if (error != KErrAlreadyExists) + { + ELOG1(EJavaConverters, "javaappbackconverter: ReregisterOldMidletStarter: " + "RegisterNonNativeApplicationTypeL failed with error %d", error); + } + else + { + // OMJ Java has registered MIDlet application type so that it is handled by + // OMJ binary 'javalauncher.exe', must change that registration + WLOG(EJavaConverters, "javaappbackconverter: ReregisterOldMidletStarter: " + "MIDlet application type was registered (by OMJ Java)."); + // Ignore possible error in deregistration + TRAP(error, appLstSession.DeregisterNonNativeApplicationTypeL( + TUid::Uid(KMidletApplicationTypeUid))); + TRAP(error, appLstSession.RegisterNonNativeApplicationTypeL( + TUid::Uid(KMidletApplicationTypeUid), KStubMIDP2RecogExe())); + if (KErrNone != error) + { + ELOG1(EJavaConverters, "javaappbackconverter: ReregisterOldMidletStarter: " + "RegisterNonNativeApplicationTypeL failed with error %d", error); + } + else + { + LOG(EJavaConverters, EInfo, "javaappbackconverter: ReregisterOldMidletStarter: " + "Registered MIDlet application type again (for S60 Java)."); + } + } + + appLstSession.Close(); +} + + +/** + * Show dialog telling that the device must be rebooted + */ +static void showMustRebootDialog() +{ + LOG(EJavaConverters, EInfo, "javaappbackconverter: showMustRebootDialog() Called"); + + // Wait for 2 seconds before showing dialog + User::After(2000000); + + TRAPD(err, + TRequestStatus status; + CAknGlobalMsgQuery* globalMsg = CAknGlobalMsgQuery::NewLC(); + + // In OMJ 2.x beta .sis uninstallation it is enough to + // show the text always in english (non-localized) + _LIT(KJavaPleaseReboot, "To complete the uninstallation process, \ + the phone must be restarted. Until then some applications may not function properly."); + + // tell that device will be rebooted + globalMsg->ShowMsgQueryL( + status, + KJavaPleaseReboot, + R_AVKON_SOFTKEYS_OK_EMPTY__OK, + KNullDesC(), + KNullDesC(), + 0, + -1, + CAknQueryDialog::EWarningTone); + + User::WaitForRequest(status); + + CleanupStack::PopAndDestroy(globalMsg); + ); + if (KErrNone != err) + { + ELOG1(EJavaConverters, + "javaappbackconverter: showMustRebootDialog() TRAP_IGNORE exited with err %d", err); + } +} + + +/** + * Create cleanup stack and run the javaappbackconverter code inside TRAP + * harness to log unexpected leaves. + */ +TInt E32Main() +{ + CTrapCleanup* pCleanupStack = CTrapCleanup::New(); + if (NULL == pCleanupStack) + { + ELOG(EJavaConverters, "javaappbackconverter: Could not create cleanup stack!"); + return KErrNoMemory; + } + + LOG(EJavaConverters, EInfo, "javaappbackconverter: Starting backconverter"); + + // Create file server session + RFs fs; + TInt err = fs.Connect(); + if (KErrNone != err) + { + ELOG1(EJavaConverters, + "javaappbackconverter: Cannot open RFs connection. Error %d", err); + return err; + } + + // Determine whether backconversion should be done or not. + // It should be done + // - if this process has been started when java_2_0.sis is uninstalled + // OR + // - if this process has been started when s60_omj_restore_midlets.sis is installed + + // The path name of the loaded executable on which this process is based is + // 'javaappbackconverter.exe' if this process has been started from java_2_0.sis and + // 'javaapprestorer.exe' if this process has been started from s60_omj_restore_midlets.sis + _LIT(KJavaRestorerFileName, "javaapprestorer.exe"); + TBool fStartedFromOmjSis(ETrue); + RProcess thisProcess; + TFileName filename = thisProcess.FileName(); + if (filename.Find(KJavaRestorerFileName) > 0) + { + LOG(EJavaConverters, EInfo, + "javaappbackconverter: Started from s60_omj_restore_midlets.sis"); + fStartedFromOmjSis = EFalse; + } + LOG1WSTR(EJavaConverters, EInfo, + "javaappbackconverter: Process file name is %s", (wchar_t *)(filename.PtrZ())); + + // Check whether uninstalling or (installing/upgrading) + TBool fUninstallingSisPackage(EFalse); + TInt value(0); + // Ignore errors, if the value cannot be read, assume 'installing .sis' + RProperty::Get(KPSUidSWInstallerUiNotification, KSWInstallerUninstallation, value); + if (0 == value) + { + // Native installer is installing (or upgrading) a .sis package + LOG(EJavaConverters, EInfo, "javaappbackconverter: native installer is installing .sis"); + } + else + { + // Native installer is uninstalling a .sis package + fUninstallingSisPackage = ETrue; + LOG(EJavaConverters, EInfo, "javaappbackconverter: native installer is uninstalling .sis"); + } + + if (fUninstallingSisPackage && fStartedFromOmjSis) + { + // backconversion must be done + LOG(EJavaConverters, EInfo, "javaappbackconverter: Going to do backconversion."); + } + else if ((!fUninstallingSisPackage) && (!fStartedFromOmjSis)) + { + // backconversion must be done + LOG(EJavaConverters, EInfo, "javaappbackconverter: Going to restore midlets."); + } + else + { + LOG(EJavaConverters, EInfo, + "javaappbackconverter: Back conversion / restoration is not needed."); + fs.Close(); + return KErrNone; + } + + // The only time that this application should be executed + // is when native installer starts it + if ((User::CreatorSecureId() != KAppInstUiSecureID) && + (User::CreatorSecureId() != KAppSisLauncherSecureID)) + { + ELOG(EJavaConverters, + "javaappbackconverter: Mismatch in secure ID, only AppInstUi " + "or SisLauncher can launch this exe."); + ELOG1(EJavaConverters, + "javaappbackconverter: Starter has SID %x ", User::CreatorSecureId().iId); + fs.Close(); + return KErrPermissionDenied; + } + else + { + LOG(EJavaConverters, EInfo, "javaappbackconverter: Starter SID was OK."); + } + + ReregisterOldMidletStarter(); + + TInt ret = KErrNone; + TRAP(ret, ExecuteBackConverterL(fs)); + if (ret != KErrNone) + { + ELOG1(EJavaConverters, "javaappbackconverter: ExecuteBackConverterL: Main error %d", ret); + } + + // Kill OMJ Java Registry process. Next call to Java Registry API starts + // old S60 Java Registry server + KillRegistry(); + + // Start also old SystemAMS.exe to restore old S60 Java environment to functional state + RProcess rSystemAms; + _LIT(KSystemAmsProcess, "SystemAMS.exe"); + _LIT(KEmptyCommandLine, ""); + err = rSystemAms.Create(KSystemAmsProcess, KEmptyCommandLine); + if (KErrNone == err) + { + rSystemAms.Resume(); + } + else + { + WLOG1(EJavaConverters, + "javaappbackconverter: Starting SystemAMS.exe failed, err %d", err); + } + rSystemAms.Close(); + + AddOldJavaAppIconsToMenuApp(); + + fs.Close(); + + if (fUninstallingSisPackage) + { + showMustRebootDialog(); + } + + delete pCleanupStack; + return ret; +}