javatools/javapostupdater/src/main.cpp
changeset 21 2a9601315dfc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javatools/javapostupdater/src/main.cpp	Mon May 03 12:27:20 2010 +0300
@@ -0,0 +1,427 @@
+/*
+* 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:  OMJ S60 environment post updater process.
+*               This process is executed when OMJ is installed, after
+*               the native installer exits.
+*               Register new Java 2.0 midlet starter to AppArc.
+*               Execute javaappconverter.exe and javausersettingsconfigurator.exe.
+*               Destroy one PS key owned by the native installer.
+*               Create new PS keys used by new Java Installer.
+*               Refresh midlet icons shown in menu application.
+*
+*/
+
+
+#include <e32std.h>
+#include <e32base.h>
+#include <f32file.h>
+#include <w32std.h>
+#include <centralrepository.h>
+#include <swinstapi.h>
+#include <apgcli.h> // for RApaLsSession
+
+#include <javadomainpskeys.h>
+
+#include "javaprocessconstants.h"
+#include "javauids.h"
+#include "logger.h"
+
+
+_LIT8(KAppJavaType, "application/java");
+
+
+/**
+ * Ask javainstaller to create the new PS keys
+ * that other processes can later use to get information of
+ * the progress of the installation of Java applications.
+ */
+static void CreateNewJavaInstallerPSKeys()
+{
+    LOG(EJavaConverters, EInfo, "javapostupdater: CreateNewJavaInstallerPSKeys() was called");
+
+    RProcess rJavaInstaller;
+    TFileName fileName;
+    // Pass just 'register' command
+    TBuf<128> commandLine;
+
+    // Build command line used to pass all necessary info to Java Installer
+    TInt len = strlen(java::runtime::JAVA_INSTALLER_STARTER_DLL);
+    TPtr8 ptr8InstallerDll((TUint8 *)java::runtime::JAVA_INSTALLER_STARTER_DLL, len, len);
+    commandLine.Copy(ptr8InstallerDll);
+
+    commandLine.Append(_L(" register"));
+
+    LOG(EJavaConverters, EInfo,
+        "javapostupdater: CreateNewJavaInstallerPSKeys() starting Java "
+        "Installer for registering PS keys");
+
+    // start JavaInstaller
+    TBuf<64> installerProcess;  // Actual len of the process name is 9
+    len = strlen(java::runtime::JAVA_PROCESS);
+    TPtr8 ptr8Process((TUint8 *)java::runtime::JAVA_PROCESS, len, len);
+    installerProcess.Copy(ptr8Process);
+
+    TInt err = rJavaInstaller.Create(installerProcess, commandLine);
+    if (KErrNone == err)
+    {
+        LOG(EJavaConverters, EInfo,
+            "javapostupdater: CreateNewJavaInstallerPSKeys() calling Resume");
+        rJavaInstaller.Resume();
+    }
+
+    LOG(EJavaConverters, EInfo,
+        "javapostupdater: CreateNewJavaInstallerPSKeys() calling RProcess::Close");
+    // free resources before returning
+    rJavaInstaller.Close();
+}
+
+
+/**
+ * Make a dummy call to Installer using SwiUI::RSWInstSilentLauncher
+ * so that OMJ appinstuiplugin gets called from AppInstUi process
+ * and can remove one conflicting P&S key created by old S60 Java Installer
+ */
+static void DeleteOldJavaInstallerPSKeyL()
+{
+    SwiUI::RSWInstSilentLauncher   installer;
+    SwiUI::TUninstallOptions       options;
+    SwiUI::TUninstallOptionsPckg   pckg;
+
+    // use default options
+    pckg = options;
+
+    LOG(EJavaConverters, EInfo, "javapostupdater: DeleteOldJavaInstallerPSKey() called");
+
+    TInt err = installer.Connect();
+    if (KErrNone != err)
+    {
+        ELOG1(EJavaConverters,
+              "javapostupdater: DeleteOldJavaInstallerPSKey: RSWInstSilentLauncher "
+              "connect error %d", err);
+        return;
+    }
+
+    CleanupClosePushL(installer);
+
+    // Calling AppInstUi silent install API immediately after OMJ has been
+    // installed may fail because the AppInstUI has not yet exited or new OMJ
+    // ECOM plugin is not yet in use.
+    // Make the calls in a loop and wait a couple of seconds between
+    const TUid illegalAppUid = {KRandomIllegalAppUid};
+    TInt nRetries = 7;
+    do
+    {
+        // This call returns KErrCancel even if the PS key was destroyed
+        err = installer.SilentUninstall(illegalAppUid, pckg, KAppJavaType);
+        if ((KErrNone != err) && (KErrCancel != err))
+        {
+            WLOG1(EJavaConverters,
+                  "javapostupdater: DeleteOldJavaInstallerPSKey: SilentUninstall error %d", err);
+        }
+
+        // Wait 3 sec so that AppInstUi has time to finish previous operation
+        // and exit so that new ECom OMJ specific plugin will be loaded
+        User::After(3000000);
+        nRetries--;
+    }
+    while ((KErrCancel != err) && (KErrNone != err) && (nRetries > 0));
+
+    if (nRetries == 0)
+    {
+        ELOG1(EJavaConverters,
+              "javapostupdater: DeleteOldJavaInstallerPSKey: Could not delete PS key, error %d",
+              err);
+    }
+    else
+    {
+        LOG(EJavaConverters,
+            EInfo, "javapostupdater: DeleteOldJavaInstallerPSKey() PS Key was deleted");
+    }
+
+
+    CleanupStack::PopAndDestroy(&installer);
+}
+
+
+/**
+ * Start javaappconverter.exe process and wait until it exits. After that
+ * start javausersettingsconfigurator.exe process and wait until it exits.
+ */
+static void runConverters()
+{
+    JELOG2(EJavaPreinstaller);
+
+    // Start converter process
+    RProcess converter;
+    TInt err = converter.Create(_L("javaappconverter.exe"), KNullDesC);
+    if (KErrNone == err)
+    {
+        // Process has been created
+        LOG(EJavaConverters, EInfo,
+            "runConverter: created javaappconverter process");
+
+        // Get ready to wait until the process ends
+        TRequestStatus status;
+        converter.Logon(status);
+
+        // Make the main thread of the process runnable
+        converter.Resume();
+        LOG(EJavaConverters, EInfo,
+            "runConverter: started javaappconverter");
+
+        // Wait until the process ends.
+        User::WaitForRequest(status);
+        converter.Close();
+
+        if (status.Int() == KErrAlreadyExists)
+        {
+            // Old S60 midlets have already been converted.
+            // This is an OMJ upgrade installation.
+            LOG(EJavaConverters, EInfo,
+                "runConverter: no need to execute javausersettingsconfigurator process");
+            return;
+        }
+        else
+        {
+            LOG1(EJavaConverters, EInfo,
+                 "runConverter: javaappconverter ended with status %d", status.Int());
+        }
+    }
+    else
+    {
+        ELOG1(
+            EJavaConverters,
+            "runConverter: starting javaappconverter failed, err %d",
+            err);
+        return;
+    }
+
+    // Configure the user settings of the newly installed applications
+    // (based on how they were configured in the legacy java)
+    RProcess userSettingsTool;
+    err = userSettingsTool.Create(_L("javausersettingsconfigurator.exe"), KNullDesC);
+    if (err == KErrNone)
+    {
+        // Process has been created
+        LOG(EJavaConverters, EInfo,
+            "runConverter: created javausersettingsconfigurator process");
+
+        // Get ready to wait until the process ends
+        TRequestStatus status;
+        userSettingsTool.Logon(status);
+
+        // Make the main thread of the process runnable
+        userSettingsTool.Resume();
+        LOG(EJavaConverters, EInfo,
+            "runConverter: started javausersettingsconfigurator");
+
+        // Wait until the process ends.
+        User::WaitForRequest(status);
+
+        LOG1(EJavaConverters, EInfo,
+             "runConverter: javausersettingsconfigurator ended with status %d", status.Int());
+
+        userSettingsTool.Close();
+    }
+    else
+    {
+        ELOG1(
+            EJavaConverters,
+            "startConverter: starting javausersettingsconfigurator failed, err %d",
+            err);
+    }
+}
+
+/**
+ * Register 'javalauncher.exe' as the midlet application type handler
+ * in AppArc. If necessary unregister old handler first.
+ */
+static void registerMidletApplicationTypeHandler()
+{
+    _LIT(KMidpAppArcPlugin, "javalauncher.exe");
+
+    RApaLsSession appLstSession;
+    TInt err = appLstSession.Connect();
+    if (KErrNone == err)
+    {
+        TRAP(err, appLstSession.RegisterNonNativeApplicationTypeL(
+                 TUid::Uid(KMidletApplicationTypeUid), KMidpAppArcPlugin()));
+        if (KErrNone == err)
+        {
+            // All is well
+            LOG(EJavaConverters, EInfo,
+                "registerMidletApplicationTypeHandler: Registered MIDlet application "
+                "type for Java 2.x");
+        }
+        else if (KErrAlreadyExists == err)
+        {
+            // Java 1.x has registered MIDlet application type handler StubMIDP2RecogExe.exe,
+            // must change that registration
+            LOG(EJavaConverters, EInfo,
+                "registerMidletApplicationTypeHandler: MIDlet application type was already "
+                "registered by Java 1.x");
+            TRAP_IGNORE(appLstSession.DeregisterNonNativeApplicationTypeL(
+                            TUid::Uid(KMidletApplicationTypeUid)));
+            TRAP(err, appLstSession.RegisterNonNativeApplicationTypeL(
+                     TUid::Uid(KMidletApplicationTypeUid), KMidpAppArcPlugin()));
+            if (KErrNone == err)
+            {
+                LOG(EJavaConverters, EInfo,
+                    "registerMidletApplicationTypeHandler: Registered MIDlet application "
+                    "type again (for Java 2.x).");
+            }
+            else
+            {
+                ELOG1(EJavaConverters,
+                      "registerMidletApplicationTypeHandler: Reregistering MIDlet application "
+                      "type failed with err %d",
+                      err);
+            }
+        }
+        else
+        {
+            ELOG1(EJavaConverters,
+                  "registerMidletApplicationTypeHandler: Registering MIDlet "
+                  "application type failed with err %d",
+                  err);
+        }
+
+        // Launch rescan of all applications so that all java applications
+        // will be shown in Menu
+        TRAP(err, appLstSession.PrepareNonNativeApplicationsUpdatesL());
+        if (KErrNone != err)
+        {
+            ELOG1(EJavaConverters,
+                  "registerMidletApplicationTypeHandler: PrepareNonNativeApplicationsUpdatesL error %d",
+                  err);
+        }
+        else
+        {
+            LOG(EJavaConverters, EInfo,
+                "registerMidletApplicationTypeHandler: PrepareNonNativeApplicationsUpdatesL OK");
+        }
+
+        TRAP(err, appLstSession.CommitNonNativeApplicationsUpdatesL());
+        if (KErrNone != err)
+        {
+            ELOG1(EJavaConverters,
+                  "registerMidletApplicationTypeHandler: CommitNonNativeApplicationsUpdatesL error %d",
+                  err);
+        }
+        else
+        {
+            LOG(EJavaConverters, EInfo,
+                "registerMidletApplicationTypeHandler: CommitNonNativeApplicationsUpdatesL OK");
+        }
+
+        appLstSession.Close();
+    }
+    else
+    {
+        ELOG1(EJavaConverters,
+              "registerMidletApplicationTypeHandler: Connecting to AppArc failed with error %d",
+              err);
+    }
+}
+
+/**
+ * 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,
+              "javapostupdater: UseCRKeyToUpdateAppShellDataL: "
+              "setting cenrep value failed, error %d ",
+              err);
+    }
+
+    delete pCenRep;
+}
+
+/**
+ * If OMJ is upgraded the Application Shell (menu application) of the
+ * Nokia 5800 XpressMusic device family does not
+ * display the icons of the java applications that have been installed to
+ * only OMJ environment. 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 AddAllJavaAppIconsToMenuApp()
+{
+    LOG(EJavaConverters, EInfo, "javapostupdater: AddAllJavaAppIconsToMenuApp 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,
+            "javapostupdater: AddAllJavaAppIconsToMenuApp: This device does not "
+            "support refreshing Menu using CR keys.");
+    }
+    else if (KErrNone != err)
+    {
+        ELOG1(EJavaConverters,
+              "javapostupdater: AddAllJavaAppIconsToMenuApp: Error: %d", err);
+    }
+}
+
+/**
+ * Create cleanup stack and run the post updater code inside TRAP harness
+ * to log unexpected leaves.
+ */
+TInt E32Main()
+{
+    __UHEAP_MARK;
+    CTrapCleanup* cleanupStack = CTrapCleanup::New();
+
+    LOG(EJavaConverters, EInfo, "javapostupdater process starts");
+
+    // Java 2.0 midlet starter handles midlet application type
+    registerMidletApplicationTypeHandler();
+
+    // Convert existing midlets to Java 2.0 midlets
+    runConverters();
+
+    // Delete one old PS key owned by native installer (appinstui)
+    TRAPD(error, DeleteOldJavaInstallerPSKeyL());
+    if (KErrNone != error)
+    {
+        ELOG1(EJavaConverters,
+              "javapostupdater: DeleteOldJavaInstallerPSKeyL() leaved with %d", error);
+    }
+
+    // Create new PS keys that Java 2.0 Java Installer will use
+    CreateNewJavaInstallerPSKeys();
+
+    // Make sure all Java application icons are shown in menu.
+    AddAllJavaAppIconsToMenuApp();
+
+    delete cleanupStack;
+    __UHEAP_MARKEND;
+    return error;
+}