javatools/javaappbackconverter/src.s60/main.cpp
branchRCL_3
changeset 14 04becd199f91
equal deleted inserted replaced
13:f5050f1da672 14:04becd199f91
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: Java platform 2.0 javaappbackconverter process
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <e32std.h>
       
    20 #include <e32base.h>
       
    21 #include <e32property.h>
       
    22 #include <f32file.h>
       
    23 #include <centralrepository.h>
       
    24 #include <swinstallerinternalpskeys.h>
       
    25 #include <AknGlobalMsgQuery.h>
       
    26 
       
    27 #include "javacommonutils.h"
       
    28 #include "javauids.h"
       
    29 #include "backconverter.h"
       
    30 #include "noarmlogs.h"
       
    31 
       
    32 _LIT_SECURE_ID(KAppInstUiSecureID, 0x101F875A);
       
    33 _LIT_SECURE_ID(KAppSisLauncherSecureID, 0x1020473F);
       
    34 
       
    35 
       
    36 /**
       
    37  * Create file server connection.
       
    38  * If no data storage file exists, exit.
       
    39  * Create active scheduler and start it to execute actual back converter.
       
    40  */
       
    41 static void ExecuteBackConverterL(RFs &aFs)
       
    42 {
       
    43     LOG(EJavaConverters, EInfo, "javaappbackconverter: ExecuteBackConverterL called");
       
    44 
       
    45     CActiveScheduler* as = new(ELeave) CActiveScheduler();
       
    46 
       
    47     // Install active scheduler
       
    48     CActiveScheduler::Install(as);
       
    49     CleanupStack::PushL(as);
       
    50 
       
    51     // The file server session must be shared so that that AppArc can
       
    52     // use the icon file handle opened in back converter
       
    53     TInt err = aFs.ShareProtected();
       
    54     if (KErrNone != err)
       
    55     {
       
    56         ELOG1(EJavaConverters,
       
    57               "javaappbackconverter: ExecuteBackConverterL: "
       
    58               "Cannot share file server session, err code is %d ", err);
       
    59         User::Leave(err);
       
    60     }
       
    61 
       
    62     // Setup and start the back conversion
       
    63     CBackConverter* back = CBackConverter::NewLC(aFs);
       
    64 
       
    65     LOG(EJavaConverters,
       
    66         EInfo, "javaappbackconverter: ExecuteBackConverterL: Call CBackConverter::Start()");
       
    67 
       
    68     back->Start();
       
    69 
       
    70     // Start active scheduler
       
    71     LOG(EJavaConverters, EInfo, "ExecuteBackConverterL: Starting CActiveScheduler");
       
    72     CActiveScheduler::Start();
       
    73 
       
    74     LOG(EJavaConverters, EInfo, "javaappbackconverter: ExecuteBackConverterL: Cleaning up");
       
    75 
       
    76     CleanupStack::PopAndDestroy(back);
       
    77     CleanupStack::PopAndDestroy(as);
       
    78 }
       
    79 
       
    80 /**
       
    81  * Menu application has a central repository key that can be used in
       
    82  * devices belonging to Nokia 5800 XpressMusic device family to request
       
    83  * that the Menu application would rescan all applications it contains.
       
    84  */
       
    85 static void UseCRKeyToUpdateAppShellDataL()
       
    86 {
       
    87     const TUid KCRUidMenu = { 0x101F8847 };
       
    88     const TUint32 KMenuUpdateData = 0x00000001;
       
    89 
       
    90     // Update Central Rep
       
    91     CRepository *pCenRep = CRepository::NewL(KCRUidMenu);
       
    92 
       
    93     TInt value = 1;
       
    94     TInt err = pCenRep->Set(KMenuUpdateData, value);
       
    95     if (KErrNone != err)
       
    96     {
       
    97         ELOG1(EJavaConverters,
       
    98               "javaappbackconverter: UseCRKeyToUpdateAppShellDataL: "
       
    99               "setting cenrep value failed, error %d ",
       
   100               err);
       
   101     }
       
   102 
       
   103     delete pCenRep;
       
   104 }
       
   105 
       
   106 /**
       
   107  * After OMJ has been uninstalled the menu application of the device
       
   108  * does not display the icons of the old, restored java applications.
       
   109  * The icons are shown after the device is booted.
       
   110  * Tell menu application to scan again all applications so that the icons
       
   111  * will be shown.
       
   112  */
       
   113 static void AddOldJavaAppIconsToMenuApp()
       
   114 {
       
   115     LOG(EJavaConverters, EInfo, "javaappbackconverter: AddOldJavaAppIconsToMenuApp called.");
       
   116 
       
   117     TRAPD(err, UseCRKeyToUpdateAppShellDataL());
       
   118     if (KErrNotFound == err)
       
   119     {
       
   120         // Only Nokia XPressMusic 5800 device family supports this feature,
       
   121         // N97 and later devices no longer support it but they have new Menu
       
   122         // application that shows all Java application icons anyway.
       
   123         LOG(EJavaConverters, EInfo,
       
   124             "javaappbackconverter: AddOldJavaAppIconsToMenuApp: This device does not "
       
   125             "support refreshing Menu using CR keys.");
       
   126     }
       
   127     else if (KErrNone != err)
       
   128     {
       
   129         ELOG1(EJavaConverters,
       
   130               "javaappbackconverter: AddOldJavaAppIconsToMenuApp: Error: %d", err);
       
   131     }
       
   132 }
       
   133 
       
   134 /**
       
   135  * Kill the running OMJ javaregistry.exe. After killing next call to
       
   136  * Registry API restarts the old S60 server process.
       
   137  */
       
   138 static void KillRegistry()
       
   139 {
       
   140     LOG(EJavaConverters, EInfo, "javaappbackconverter: KillRegistry called.");
       
   141 
       
   142     TFullName processName;
       
   143     _LIT(KJavaRegistryProcess, "javaregistry*");
       
   144     TFindProcess finder(KJavaRegistryProcess);
       
   145 
       
   146     if (finder.Next(processName) != KErrNotFound)
       
   147     {
       
   148         RProcess processToKill;
       
   149         TInt err = processToKill.Open(finder);
       
   150 
       
   151         if (KErrNone != err)
       
   152         {
       
   153             WLOG1(EJavaConverters, "javaappbackconverter: Process open: %d", err);
       
   154         }
       
   155         else
       
   156         {
       
   157             processToKill.Kill(KErrNone);
       
   158             processToKill.Close();
       
   159         }
       
   160     }
       
   161     else
       
   162     {
       
   163         WLOG(EJavaConverters, "javaappbackconverter: Registry process not found");
       
   164     }
       
   165 }
       
   166 
       
   167 /**
       
   168  * Unregister OMJ MIDlet starter, reregister old S60 MIDlet starter
       
   169  */
       
   170 static void ReregisterOldMidletStarter()
       
   171 {
       
   172     LOG(EJavaConverters, EInfo, "javaappbackconverter: ReregisterOldMidletStarter called");
       
   173 
       
   174     _LIT(KStubMIDP2RecogExe, "StubMIDP2RecogExe.exe");
       
   175 
       
   176     RApaLsSession appLstSession;
       
   177 
       
   178     TInt error = appLstSession.Connect();
       
   179     if (error != KErrNone)
       
   180     {
       
   181         ELOG1(EJavaConverters, "javaappbackconverter: ReregisterOldMidletStarter: "
       
   182               "RApaLsSession.Connect failed with error %d", error);
       
   183         return;
       
   184     }
       
   185     TRAP(error, appLstSession.RegisterNonNativeApplicationTypeL(
       
   186              TUid::Uid(KMidletApplicationTypeUid), KStubMIDP2RecogExe()));
       
   187     if (error == KErrNone)
       
   188     {
       
   189         LOG(EJavaConverters, EInfo, "javaappbackconverter: ReregisterOldMidletStarter: "
       
   190             "Registered MIDlet application type for S60 Java.");
       
   191     }
       
   192     else if (error != KErrAlreadyExists)
       
   193     {
       
   194         ELOG1(EJavaConverters, "javaappbackconverter: ReregisterOldMidletStarter: "
       
   195               "RegisterNonNativeApplicationTypeL failed with error %d", error);
       
   196     }
       
   197     else
       
   198     {
       
   199         // OMJ Java has registered MIDlet application type so that it is handled by
       
   200         // OMJ binary 'javalauncher.exe', must change that registration
       
   201         WLOG(EJavaConverters, "javaappbackconverter: ReregisterOldMidletStarter: "
       
   202              "MIDlet application type was registered (by OMJ Java).");
       
   203         // Ignore possible error in deregistration
       
   204         TRAP(error, appLstSession.DeregisterNonNativeApplicationTypeL(
       
   205                  TUid::Uid(KMidletApplicationTypeUid)));
       
   206         TRAP(error, appLstSession.RegisterNonNativeApplicationTypeL(
       
   207                  TUid::Uid(KMidletApplicationTypeUid), KStubMIDP2RecogExe()));
       
   208         if (KErrNone != error)
       
   209         {
       
   210             ELOG1(EJavaConverters, "javaappbackconverter: ReregisterOldMidletStarter: "
       
   211                   "RegisterNonNativeApplicationTypeL failed with error %d", error);
       
   212         }
       
   213         else
       
   214         {
       
   215             LOG(EJavaConverters, EInfo, "javaappbackconverter: ReregisterOldMidletStarter: "
       
   216                 "Registered MIDlet application type again (for S60 Java).");
       
   217         }
       
   218     }
       
   219 
       
   220     appLstSession.Close();
       
   221 }
       
   222 
       
   223 
       
   224 /**
       
   225  * Show dialog telling that the device must be rebooted
       
   226  */
       
   227 static void showMustRebootDialog()
       
   228 {
       
   229     LOG(EJavaConverters, EInfo, "javaappbackconverter: showMustRebootDialog() Called");
       
   230 
       
   231     // Wait for 2 seconds before showing dialog
       
   232     User::After(2000000);
       
   233 
       
   234     TRAPD(err,
       
   235           TRequestStatus status;
       
   236           CAknGlobalMsgQuery* globalMsg = CAknGlobalMsgQuery::NewLC();
       
   237 
       
   238           // In OMJ 2.x beta .sis uninstallation it is enough to
       
   239           // show the text always in english (non-localized)
       
   240           _LIT(KJavaPleaseReboot, "To complete the uninstallation process, \
       
   241  the phone must be restarted. Until then some applications may not function properly.");
       
   242 
       
   243           // tell that device will be rebooted
       
   244           globalMsg->ShowMsgQueryL(
       
   245               status,
       
   246               KJavaPleaseReboot,
       
   247               R_AVKON_SOFTKEYS_OK_EMPTY__OK,
       
   248               KNullDesC(),
       
   249               KNullDesC(),
       
   250               0,
       
   251               -1,
       
   252               CAknQueryDialog::EWarningTone);
       
   253 
       
   254           User::WaitForRequest(status);
       
   255 
       
   256           CleanupStack::PopAndDestroy(globalMsg);
       
   257          );
       
   258     if (KErrNone != err)
       
   259     {
       
   260         ELOG1(EJavaConverters,
       
   261               "javaappbackconverter: showMustRebootDialog() TRAP_IGNORE exited with err %d", err);
       
   262     }
       
   263 }
       
   264 
       
   265 
       
   266 /**
       
   267  * Create cleanup stack and run the javaappbackconverter code inside TRAP
       
   268  * harness to log unexpected leaves.
       
   269  */
       
   270 TInt E32Main()
       
   271 {
       
   272     CTrapCleanup* pCleanupStack = CTrapCleanup::New();
       
   273     if (NULL == pCleanupStack)
       
   274     {
       
   275         ELOG(EJavaConverters, "javaappbackconverter: Could not create cleanup stack!");
       
   276         return KErrNoMemory;
       
   277     }
       
   278 
       
   279     LOG(EJavaConverters, EInfo, "javaappbackconverter: Starting backconverter");
       
   280 
       
   281     // Create file server session
       
   282     RFs fs;
       
   283     TInt err = fs.Connect();
       
   284     if (KErrNone != err)
       
   285     {
       
   286         ELOG1(EJavaConverters,
       
   287               "javaappbackconverter: Cannot open RFs connection. Error %d", err);
       
   288         return err;
       
   289     }
       
   290 
       
   291     // Determine whether backconversion should be done or not.
       
   292     // It should be done
       
   293     // - if this process has been started when java_2_0.sis is uninstalled
       
   294     // OR
       
   295     // - if this process has been started when s60_omj_restore_midlets.sis is installed
       
   296 
       
   297     // The path name of the loaded executable on which this process is based is
       
   298     // 'javaappbackconverter.exe' if this process has been started from java_2_0.sis and
       
   299     // 'javaapprestorer.exe' if this process has been started from s60_omj_restore_midlets.sis
       
   300     _LIT(KJavaRestorerFileName, "javaapprestorer.exe");
       
   301     TBool fStartedFromOmjSis(ETrue);
       
   302     RProcess thisProcess;
       
   303     TFileName filename = thisProcess.FileName();
       
   304     if (filename.Find(KJavaRestorerFileName) > 0)
       
   305     {
       
   306         LOG(EJavaConverters, EInfo,
       
   307             "javaappbackconverter: Started from s60_omj_restore_midlets.sis");
       
   308         fStartedFromOmjSis = EFalse;
       
   309     }
       
   310     LOG1WSTR(EJavaConverters, EInfo,
       
   311              "javaappbackconverter: Process file name is %s", (wchar_t *)(filename.PtrZ()));
       
   312 
       
   313     // Check whether uninstalling or (installing/upgrading)
       
   314     TBool fUninstallingSisPackage(EFalse);
       
   315     TInt value(0);
       
   316     // Ignore errors, if the value cannot be read, assume 'installing .sis'
       
   317     RProperty::Get(KPSUidSWInstallerUiNotification, KSWInstallerUninstallation, value);
       
   318     if (0 == value)
       
   319     {
       
   320         // Native installer is installing (or upgrading) a .sis package
       
   321         LOG(EJavaConverters, EInfo, "javaappbackconverter: native installer is installing .sis");
       
   322     }
       
   323     else
       
   324     {
       
   325         // Native installer is uninstalling a .sis package
       
   326         fUninstallingSisPackage = ETrue;
       
   327         LOG(EJavaConverters, EInfo, "javaappbackconverter: native installer is uninstalling .sis");
       
   328     }
       
   329 
       
   330     if (fUninstallingSisPackage && fStartedFromOmjSis)
       
   331     {
       
   332         // backconversion must be done
       
   333         LOG(EJavaConverters, EInfo, "javaappbackconverter: Going to do backconversion.");
       
   334     }
       
   335     else if ((!fUninstallingSisPackage) && (!fStartedFromOmjSis))
       
   336     {
       
   337         // backconversion must be done
       
   338         LOG(EJavaConverters, EInfo, "javaappbackconverter: Going to restore midlets.");
       
   339     }
       
   340     else
       
   341     {
       
   342         LOG(EJavaConverters, EInfo,
       
   343             "javaappbackconverter: Back conversion / restoration is not needed.");
       
   344         fs.Close();
       
   345         return KErrNone;
       
   346     }
       
   347 
       
   348     // The only time that this application should be executed
       
   349     // is when native installer starts it
       
   350     if ((User::CreatorSecureId() != KAppInstUiSecureID) &&
       
   351             (User::CreatorSecureId() != KAppSisLauncherSecureID))
       
   352     {
       
   353         ELOG(EJavaConverters,
       
   354              "javaappbackconverter: Mismatch in secure ID, only AppInstUi "
       
   355              "or SisLauncher can launch this exe.");
       
   356         ELOG1(EJavaConverters,
       
   357               "javaappbackconverter: Starter has SID %x ", User::CreatorSecureId().iId);
       
   358         fs.Close();
       
   359         return KErrPermissionDenied;
       
   360     }
       
   361     else
       
   362     {
       
   363         LOG(EJavaConverters, EInfo, "javaappbackconverter: Starter SID was OK.");
       
   364     }
       
   365 
       
   366     ReregisterOldMidletStarter();
       
   367 
       
   368     TInt ret = KErrNone;
       
   369     TRAP(ret, ExecuteBackConverterL(fs));
       
   370     if (ret != KErrNone)
       
   371     {
       
   372         ELOG1(EJavaConverters, "javaappbackconverter: ExecuteBackConverterL: Main error %d", ret);
       
   373     }
       
   374 
       
   375     // Kill OMJ Java Registry process. Next call to Java Registry API starts
       
   376     // old S60 Java Registry server
       
   377     KillRegistry();
       
   378 
       
   379     // Start also old SystemAMS.exe to restore old S60 Java environment to functional state
       
   380     RProcess rSystemAms;
       
   381     _LIT(KSystemAmsProcess, "SystemAMS.exe");
       
   382     _LIT(KEmptyCommandLine, "");
       
   383     err = rSystemAms.Create(KSystemAmsProcess, KEmptyCommandLine);
       
   384     if (KErrNone == err)
       
   385     {
       
   386         rSystemAms.Resume();
       
   387     }
       
   388     else
       
   389     {
       
   390         WLOG1(EJavaConverters,
       
   391               "javaappbackconverter: Starting SystemAMS.exe failed, err %d", err);
       
   392     }
       
   393     rSystemAms.Close();
       
   394 
       
   395     AddOldJavaAppIconsToMenuApp();
       
   396 
       
   397     fs.Close();
       
   398 
       
   399     if (fUninstallingSisPackage)
       
   400     {
       
   401         showMustRebootDialog();
       
   402     }
       
   403 
       
   404     delete pCleanupStack;
       
   405     return ret;
       
   406 }