javamanager/preinstaller/src.s60/main.cpp
author hgs
Fri, 29 Oct 2010 11:49:32 +0300
changeset 87 1627c337e51e
parent 35 85266cc22c7f
permissions -rw-r--r--
v2.2.21_1

/*
* Copyright (c) 2008 - 2010 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 preinstaller process
 *
*/


#include <e32std.h>
#include <e32base.h>
#include <f32file.h>
#include <e32property.h>
#include <javadomainpskeys.h>

#include "javauids.h"
#include "javaoslayer.h"
#include "javasymbianoslayer.h"
#include "silentmidletinstall.h"
#include "logger.h"

using namespace java::util;


_LIT_SECURE_ID(KJavaCaptainSecureID, KJavaCaptainUid);

#ifdef RD_JAVA_S60_RELEASE_5_0_IAD
// This file is used to indicate when preinstallation has been done and
// converting old S60 midlets to OMJ midlets can start.
_LIT(KConversionOngoing, "D:\\OMJConverting.dat");  // codescanner::driveletters
#endif


/**
 * The PS keys can be created from this process because javapreinstaller
 * has the same Symbian secure ID as javainstaller and so javainstaller
 * can later destroy the keys if necessary.
 */
static void createJavaInstallerPSKeys()
{
    LOG(EJavaPreinstaller, EInfo,
        "createJavaInstallerPSKeys: Going to create Java Installer PS keys");

    // any process can read the values of the PS keys
    _LIT_SECURITY_POLICY_PASS(KReadPolicy);
    // update allowed by processes with write system data capability
    _LIT_SECURITY_POLICY_C1(KWritePolicy, ECapabilityWriteDeviceData);

    TInt err = RProperty::Define(KUidSystemCategory, KPSUidJavaLatestInstallation,
                                 RProperty::EInt, KReadPolicy, KWritePolicy);
    if (KErrAlreadyExists == err)
    {
        err = KErrNone; // Ignore KErrAlreadyExists status.
    }
    if (err != KErrNone)
    {
        ELOG1(EJavaPreinstaller, "createJavaInstallerPSKeys: "
              "creating KPSUidJavaLatestInstallation failed with error %d", err);
    }

    err = RProperty::Define(KUidSystemCategory, KPSUidJavaLatestInstallationProgress,
                            RProperty::EInt, KReadPolicy, KWritePolicy);
    if (KErrAlreadyExists == err)
    {
        err = KErrNone; // Ignore KErrAlreadyExists status.
    }
    if (err != KErrNone)
    {
        ELOG1(EJavaPreinstaller, "createJavaInstallerPSKeys: "
              "creating KPSUidJavaLatestInstallationProgress failed with error %d", err);
    }

    err = RProperty::Define(KUidSystemCategory, KPSUidJavaLatestInstallationState,
                            RProperty::EInt, KReadPolicy, KWritePolicy);
    if (KErrAlreadyExists == err)
    {
        err = KErrNone; // Ignore KErrAlreadyExists status.
    }
    if (err != KErrNone)
    {
        ELOG1(EJavaPreinstaller, "createJavaInstallerPSKeys: "
              "creating KPSUidJavaLatestInstallationState failed with error %d", err);
    }
}

/**
 * Create file server connection,
 * create active scheduler,
 * add CSilentMIDletInstall active object to it and start it
 */
static void startPreinstallationL()
{
    LOG(EJavaPreinstaller, EInfo, "startPreinstallationL called");

    CActiveScheduler* as = new(ELeave) CActiveScheduler();

    // Install active scheduler
    CActiveScheduler::Install(as);
    CleanupStack::PushL(as);

    RFs fs;  // codescanner::rfs
    User::LeaveIfError(fs.Connect());
    CleanupClosePushL(fs);

    // Setup the MIDlet preinstaller and add it to the active scheduler
    CSilentMIDletInstall* si = CSilentMIDletInstall::NewLC(fs);

    LOG(EJavaPreinstaller, EInfo, "startPreinstallationL: Call CSilentMIDletInstall::Start()");

    // Initialize the MIDlet preinstaller
    si->Start();

    // Start active scheduler. Preinstallation starts.
    LOG(EJavaPreinstaller, EInfo, "startPreinstallationL: Starting CActiveScheduler");
    CActiveScheduler::Start(); // codescanner::activestart

    // Now preinstallation has been done
    LOG(EJavaPreinstaller, EInfo, "startPreinstallationL: Cleaning up");
#ifdef RD_JAVA_S60_RELEASE_5_0_IAD
    // Notify possibly waiting 'javaupdater.exe' process that preinstallation
    // has been done and that it can continue.
    TInt err = fs.Delete(KConversionOngoing);
    LOG1(EJavaPreinstaller,
         EInfo,
         "startPreinstallationL: Delete flag file returned status code %d",
         err);
#endif

    CleanupStack::PopAndDestroy(si);
    CleanupStack::PopAndDestroy(&fs); // close connection to file server
    CleanupStack::PopAndDestroy(as);
}


#ifdef RD_JAVA_S60_RELEASE_5_0_ROM
/**
 * If 'javaafterflashconverter.exe' is running, wait until it exits
 * so that converter and preinstaller don't try to use Java Installer
 * simultaneously.
 */
static void waitUntilAfterFlashConverterExits()
{
    LOG(EJavaPreinstaller, EInfo, "waitUntilAfterFlashConverterExits called");

    TFullName processName;
    _LIT(KJavaAFConverterProcess, "javaafterflashconverter*");
    TFindProcess finder(KJavaAFConverterProcess);

    if (finder.Next(processName) != KErrNotFound)
    {
        RProcess afConverterProcess;  // codescanner::resourcenotoncleanupstack
        TInt err = afConverterProcess.Open(finder);

        if (KErrNone != err)
        {
            WLOG1(EJavaPreinstaller,
                "waitUntilAfterFlashConverterExits: Process open err: %d", err);
        }
        else
        {
            if (EExitPending == afConverterProcess.ExitType())
            {
                // Converter is still running. Wait until it exits.
                LOG(EJavaPreinstaller, EInfo,
                    "waitUntilAfterFlashConverterExits going to wait until converter exits");
                TRequestStatus status;
                afConverterProcess.Logon(status);
                User::WaitForRequest(status);  // codescanner::userWaitForRequest
            }

            afConverterProcess.Close();
        }
    }
}
#endif


/**
 * Allow starting process only from Java Captain.
 * Execute actual preinstaller code in CSilentMIDletInstall.
 */
#ifdef RD_JAVA_S60_RELEASE_5_0_ROM
void preinstallerMainL(int argc, const char *argv[])
#else
void preinstallerMainL()
#endif
{
    // The only time that this application should be executed
    // is when Java Captain calls it.
    if (User::CreatorSecureId() != KJavaCaptainSecureID)
    {
        ELOG(EJavaPreinstaller,
             "preinstallerMainL: Mismatch in secure ID, only Java Captain can launch this exe.");
        User::Leave(KErrPermissionDenied);
    }

    // Create the PS keys that Java Installer will update already now
    // so that other processes starting during device boot can start
    // immediately listening to the keys.
    createJavaInstallerPSKeys();

#ifdef RD_JAVA_S60_RELEASE_5_0_ROM
    if (argc > 1)
    {
        // The max size of a preinstaller command line parameter is 80
        TBufC8<80> param((const TUint8 *)(argv[1]));  // codescanner::accessArrayElementWithoutCheck2
        if (param == _L8("waitafconversion"))
        {
            waitUntilAfterFlashConverterExits();
        }
   }
#endif

    startPreinstallationL();
}

/**
 * Using this kind of dllMain() allows starting preinstaller from
 * the same starter process as installer and runtime (so that they have the same
 * Symbian secure Uid and can access the same data cage).
 */
#ifdef RD_JAVA_S60_RELEASE_5_0_ROM
int dllMain(int argc, const char *argv[])
#else
int dllMain(int /* argc */, const char */*argv*/[])
#endif
{
    JavaOsLayer::startUpTrace("PREINSTALLER main() start", -1, -1);

    User::RenameProcess(_L("javapreinstaller"));
    User::RenameThread(_L("JavaPreinstallerMainThread"));

    LOG(EJavaPreinstaller, EInfo, "dllMain: Renaming process and thread done");

    // Make sure that this thread has always cleanup stack
    CTrapCleanup* cleanupStack = CTrapCleanup::New();

#ifdef RD_JAVA_S60_RELEASE_5_0_ROM
    TRAPD(err, preinstallerMainL(argc, argv));
#else
    TRAPD(err, preinstallerMainL());
#endif
    if (KErrNone != err)
    {
        ELOG1(EJavaPreinstaller, "dllMain: preinstallerMainL leaved with error %d", err);
    }

    delete cleanupStack;

    LOG1(EJavaPreinstaller, EInfo, "PREINSTALLER main() exit = %d", err);
    JavaOsLayer::startUpTrace("PREINSTALLER main() end", -1, -1);
    return err;
}

EXPORT_C FuncPtr findDllMethod(const char* funcName)
{
    FuncPtr ptr = 0;
    if (strcmp(funcName, "dllMain") == 0)
    {
        ptr = (FuncPtr)dllMain;
    }
    return ptr;
}
// eof