javatools/javaappbackconverter/src.s60/main.cpp
branchRCL_3
changeset 14 04becd199f91
--- /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 <e32std.h>
+#include <e32base.h>
+#include <e32property.h>
+#include <f32file.h>
+#include <centralrepository.h>
+#include <swinstallerinternalpskeys.h>
+#include <AknGlobalMsgQuery.h>
+
+#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;
+}