--- /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;
+}