javamanager/javainstaller/installer/src.s60/applicationregistrator/applicationregistrator.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Wed, 13 Oct 2010 14:23:59 +0300
branchRCL_3
changeset 83 26b2b12093af
parent 60 6c158198356e
permissions -rw-r--r--
Revision: v2.2.17 Kit: 201041

/*
* 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:  The JNI code for Java Installer component
*                ApplicationRegistrator.
*
*/


#include <apaid.h>
#include <f32file.h>
#include <apgcli.h>
#include <utf.h>
#include <s32mem.h>
#include <bautils.h>
#include <w32std.h>
#include <apgtask.h>
#include <apacmdln.h>
#include <centralrepository.h>
#include <AknUtils.h>
#include <hal.h>

#ifndef SYMBIAN_ENABLE_SPLIT_HEADERS
#include <apgicnfl.h>
#else
#include <apgicnflpartner.h>
#endif



// JNI header must be included before iconconverter.h. Latter includes some
// other header file which defines WIN32 macro, causing incorrect definitions
// to be taken from jniport.h when WINSCW compilation is made.
// This error situation can be seen from linker warnings which complain
// about not frozen exports for JNI methods.
#include "com_nokia_mj_impl_installer_applicationregistrator_ApplicationRegistrator.h"
#include "iconconverter.h"
#include "javacommonutils.h"
#include "logger.h"

// NAMESPACE DECLARATION
using namespace java;

/**
 * MIDP Stub SIS file UID. The application type Uid for MIDlets in S60
 */
const TUid KMidletApplicationTypeUid = { 0x10210E26 };

/**
 * Symbian file path separator
 */
_LIT(KPathSeperator, "\\");

/**
 * Postfix for the fake application name generated only to make AppArc happy
 */
_LIT(KAppPostfix, ".fakeapp");


#ifdef RD_JAVA_S60_RELEASE_9_2
const TInt KAppIconCount = 2;
#else
const TInt KAppIconCount = 1;
#endif

// ------------------------

/**
 * Internal wrapper method that is used to make TRAPping the leaves in the
 * native Symbian code easier.
 * Used from JNI method ...1registerApplication()
 * @see Java_com_nokia_mj_impl_installer_applicationregistrator_ApplicationRegistrator__1registerApplication
 */
jint registerApplicationL(JNIEnv *aEnv, jclass aClass, jint aSessionHandle,
                          jint aUid, HBufC16 *aGroupName, HBufC16 *aMIDletName, HBufC16 *aTargetDrive,
                          HBufC16 *aIconFileName, HBufC16 *aJarFileName, jboolean aHidden,
                          jboolean aBackground);

/**
 * Internal helper method for checking whether Application Shell is already running
 * Used JNI method ...1startAppShellUi
 *
 * @return ETrue if AppShell is running
 */
TBool isAppShellUiRunning();

/**
 * Internal helper method for checking whether this code is executing in
 * a device that has correctly working version of
 * RApaLsSession::ForceCommitNonNativeApplicationsUpdatesL()
 *
 * @return ETrue if force commit works well
 */
TBool isForceCommitSupported();

/**
 * Internal helper method for starting menu application
 *
 * @return KErrNone or Symbian error code
 */
TInt startAppShellApplicationL();

// --------------------------

/**
 * Starts native application registration session.
 *
 * @return native session handle or Symbian error code (negative number)
 */
JNIEXPORT jint JNICALL Java_com_nokia_mj_impl_installer_applicationregistrator_ApplicationRegistrator__1startSession
(JNIEnv *, jclass)
{
    TInt err;
    RApaLsSession *pApaSession = new RApaLsSession;

    if (NULL == pApaSession)
    {
        // Could not create session
        return KErrGeneral;
    }

    err = pApaSession->Connect();
    if (KErrNone != err)
    {
        // Cannot connect to AppArc server
        return err;
    }

#if 1
//#ifndef RD_JAVA_USIF_APP_REG
    // Delete any pending (un)registrations (possible if
    // e.g. device rebooted before commit).
    // This call does nothing if there is no pending registrations.
    // Ignore errors.
    (void)pApaSession->RollbackNonNativeApplicationsUpdates();

    // Prepare for Java application registrations / unregistrations
    TRAP(err, pApaSession->PrepareNonNativeApplicationsUpdatesL());
    if (KErrNone != err)
    {
        // Close session and return error
        pApaSession->Close();
        return err;
    }
#endif // RD_JAVA_USIF_APP_REG

    // Return handle to session. Utilize the fact that in Symbian
    // all pointer addresses are MOD 4 so the last 2 bits are 0
    // and can be shifted out. This way the returned handle is
    // always positive whereas Symbian error codes are always negative.
    return reinterpret_cast<TUint>(pApaSession)>>2;
}


/**
 * Registers Java Application to S60 AppArc
 *
 * @param[in] aSessionHandle
 * @param[in] aUid The Uid of the application.
 * @param[in] aGroupName  Max group name len is 16 in AppArc
 * @param[in] aMIDletName
 * @param[in] aTargetDrive Must be "C:", "E:", ..., "J:"
 * @param[in] aIconFileName The name of the icon
 * @param[in] aJarFileName The full path name of the jar file
 * @param[in] aHidden
 * @param[in] aBackground
 * @return 0 if registration succeeded or Symbian error code
 */
#if 0
//#ifdef RD_JAVA_USIF_APP_REG
JNIEXPORT jint JNICALL Java_com_nokia_mj_impl_installer_applicationregistrator_ApplicationRegistrator__1registerApplication
(JNIEnv */*aEnv*/, jclass /*aClass*/, jint /*aSessionHandle*/, jint /*aUid*/, jstring /*aGroupName*/,
 jstring /*aMIDletName*/, jstring /*aTargetDrive*/, jstring /*aIconFileName*/,
 jstring /*aJarFileName*/, jboolean /*aHidden*/, jboolean /*aBackground*/)
{
    return KErrNone;
}
#else
JNIEXPORT jint JNICALL Java_com_nokia_mj_impl_installer_applicationregistrator_ApplicationRegistrator__1registerApplication
(JNIEnv *aEnv, jclass aClass, jint aSessionHandle, jint aUid, jstring aGroupName,
 jstring aMIDletName, jstring aTargetDrive, jstring aIconFileName,
 jstring aJarFileName, jboolean aHidden, jboolean aBackground)
{
    TInt err(KErrNone);
    TBool fStayInLoop(EFalse);

    HBufC16 *unicodeIconFileName(NULL);
    HBufC16 *unicodeGroupName(NULL);
    HBufC16 *unicodeMIDletName(NULL);
    HBufC16 *unicodeTargetDrive(NULL);
    HBufC16 *unicodeJarFileName(NULL);

    // create loop that is executed only once to make error handling easier
    do
    {
        // Copy the unicode characters in jstrings to Symbian buffers so that
        // they can be used in S60 code
        const jchar *iconFileName = aEnv->GetStringChars(aIconFileName, 0);
        if (NULL == iconFileName)
        {
            ELOG(
                EJavaInstaller,
                "Cannot register application, getting icon file name as unicode failed in JNI");
            err = KErrArgument;
            break;
        }
        unicodeIconFileName = HBufC16::New(aEnv->GetStringLength(aIconFileName) + 1);
        if (NULL == unicodeIconFileName)
        {
            err = KErrNoMemory;
            break;
        }
        *unicodeIconFileName = iconFileName;
        aEnv->ReleaseStringChars(aIconFileName, iconFileName);

        const jchar *groupName = aEnv->GetStringChars(aGroupName, 0);
        if (NULL == groupName)
        {
            ELOG(
                EJavaInstaller,
                "Cannot register application, getting group name as unicode failed in JNI");
            err = KErrArgument;
            break;
        }
        unicodeGroupName = HBufC16::New(aEnv->GetStringLength(aGroupName) + 1);
        if (NULL == unicodeGroupName)
        {
            err = KErrNoMemory;
            break;
        }
        *unicodeGroupName = groupName;
        aEnv->ReleaseStringChars(aGroupName, groupName);

        const jchar *midletName = aEnv->GetStringChars(aMIDletName, 0);
        if (NULL == midletName)
        {
            ELOG(
                EJavaInstaller,
                "Cannot register application, getting midlet name as unicode failed in JNI");
            err = KErrArgument;
            break;
        }
        unicodeMIDletName = HBufC16::New(aEnv->GetStringLength(aMIDletName) + 1);
        if (NULL == unicodeMIDletName)
        {
            err = KErrNoMemory;
            break;
        }
        *unicodeMIDletName = midletName;
        aEnv->ReleaseStringChars(aMIDletName, midletName);

        const jchar *targetDrive = aEnv->GetStringChars(aTargetDrive, 0);
        if (NULL == targetDrive)
        {
            ELOG(
                EJavaInstaller,
                "Cannot register application, getting target drive as unicode failed in JNI");
            err = KErrArgument;
            break;
        }
        unicodeTargetDrive = HBufC16::New(aEnv->GetStringLength(aTargetDrive) + 1);
        if (NULL == unicodeTargetDrive)
        {
            err = KErrNoMemory;
            break;
        }
        *unicodeTargetDrive = targetDrive;
        aEnv->ReleaseStringChars(aTargetDrive, targetDrive);

        const jchar *jarFileName = aEnv->GetStringChars(aJarFileName, 0);
        if (NULL == jarFileName)
        {
            ELOG(
                EJavaInstaller,
                "Cannot register application, getting jar file name as unicode failed in JNI");
            err = KErrArgument;
            break;
        }
        unicodeJarFileName = HBufC16::New(aEnv->GetStringLength(aJarFileName) + 1);
        if (NULL == unicodeTargetDrive)
        {
            err = KErrNoMemory;
            break;
        }
        *unicodeJarFileName = jarFileName;
        aEnv->ReleaseStringChars(aJarFileName, jarFileName);
    }
    while (fStayInLoop);

    if (KErrNone != err)
    {
        delete unicodeIconFileName;
        delete unicodeGroupName;
        delete unicodeMIDletName;
        delete unicodeTargetDrive;
        delete unicodeJarFileName;

        return err;
    }

    // Call the actual register method inside TRAP harness
    TInt ret = KErrNone;
    TRAP(err,
         ret = registerApplicationL(
                   aEnv, aClass, aSessionHandle, aUid, unicodeGroupName,
                   unicodeMIDletName, unicodeTargetDrive, unicodeIconFileName,
                   unicodeJarFileName, aHidden, aBackground));

    LOG1WSTR(
        EJavaInstaller,
        EInfo,
        "Registering application, midlet name (%s)",
        (wchar_t *)(unicodeMIDletName->Des().PtrZ()));
    LOG1WSTR(
        EJavaInstaller,
        EInfo,
        "Registering application, icon file name (%s)",
        (wchar_t *)(unicodeIconFileName->Des().PtrZ()));

    if (KErrNone != err)
    {
        ELOG1(EJavaInstaller,
              "Cannot register application, err code is %d ",
              err);
    }
    if (KErrNone != ret)
    {
        // error even though the code did not leave
        err = ret;

        ELOG1(EJavaInstaller,
              "Cannot register application, non-leaving error %d",
              ret);
    }

    // Free all Symbian buffers containing copies of jstring data
    delete unicodeIconFileName;
    delete unicodeGroupName;
    delete unicodeMIDletName;
    delete unicodeTargetDrive;
    delete unicodeJarFileName;

    return err;
}
#endif // RD_JAVA_USIF_APP_REG


/**
 * See JNI method __1registerApplication.
 * This method makes all calls that may leave (the actual registering)
 */
jint registerApplicationL(
    JNIEnv *, jclass, jint aSessionHandle, jint aUid, HBufC16 *aGroupName,
    HBufC16 *aMIDletName, HBufC16 *aTargetDrive, HBufC16 *aIconFileName,
    HBufC16 * /*aJarFileName*/, jboolean aHidden, jboolean aBackground)
{
    RFs         fileServ;
    RFile       appArcIcon;
    TUid        midletUid;
    TInt        err;
    TInt        numberOfIcons = KAppIconCount; // number of icons stored in MBM
    // Also default mbm has one icon.

    midletUid.iUid = aUid;

    // AppArc requires open RFile handle
    err = fileServ.Connect();
    if (KErrNone != err)
    {
        // Will not register application without icon
        ELOG1(EJavaInstaller,
              "Cannot open RFs connection, err code is %d ", err);
        return err;
    }
    CleanupClosePushL(fileServ);

    // The session must be shared so that AppArc can
    // use the same icon file handle
    err = fileServ.ShareProtected();
    if (KErrNone != err)
    {
        ELOG1(EJavaInstaller,
              "Cannot share file server session, err code is %d ", err);
        User::Leave(err);
    }

    // Default icon has been copied from ROM, so the icon may have ReadOnly
    // flag on. Must remove that flag.
    fileServ.SetAtt(*aIconFileName, 0, KEntryAttReadOnly);

    // open the icon
    err = appArcIcon.Open(
              fileServ,
              *aIconFileName,
              (EFileShareReadersOrWriters | EFileWrite));
    if (KErrNone != err)
    {
        ELOG1(EJavaInstaller,
              "registerApplicationL: Cannot open icon, err code is %d ", err);
        User::Leave(err);
    }

    // Now icon is open
    CleanupClosePushL(appArcIcon);

    // Generate the executable name name using the same
    // algorithm as used earlier in S60 platform
    // in case some external S60 application
    // needs to parse the Uid from the executable name.
    TFileName appName;
    appName.Copy(KPathSeperator);
    appName.AppendNum(midletUid.iUid);
    appName.Append(KAppPostfix);

    // Create writer needed for actual registration
    CApaRegistrationResourceFileWriter *writer = NULL;
    writer = CApaRegistrationResourceFileWriter::NewL(
                 midletUid,
                 appName,
                 TApaAppCapability::ENonNative);
    CleanupStack::PushL(writer);

    writer->SetGroupNameL(*aGroupName);
    if (aBackground)
    {
        // By default this is false, so the value needs to be set
        // only if it is true
        writer->SetLaunchInBackgroundL(ETrue);
    }
    if (aHidden)
    {
        // By default this is false, so the value needs to be set
        // only if it is true
        writer->SetAppIsHiddenL(ETrue);
    }

    // write application Uid to opaque data   (needed by MIDlet launcher)
    TBuf8<4>         opaqueData;     // opaque data will contain one signed 32-bit int
    RDesWriteStream  writeStream(opaqueData);
    writeStream.WriteInt32L(midletUid.iUid);
    writeStream.CommitL();
    writer->SetOpaqueDataL(opaqueData);

    CApaLocalisableResourceFileWriter*  lWriter = NULL;
    lWriter =
        CApaLocalisableResourceFileWriter::NewL(
            KNullDesC,  // short caption
            *aMIDletName,  // caption
            numberOfIcons,
            KNullDesC);
    CleanupStack::PushL(lWriter);

    TDriveUnit targetDrive(*aTargetDrive);

    // Convert session handle to pointer.
    RApaLsSession *pApaSession =
        reinterpret_cast<RApaLsSession*>(aSessionHandle<<2);

    // Register application to AppArc
    pApaSession->RegisterNonNativeApplicationL(
        KMidletApplicationTypeUid,
        targetDrive,
        *writer,
        lWriter,
        &appArcIcon);

    CleanupStack::PopAndDestroy(lWriter);
    CleanupStack::PopAndDestroy(writer);
    // close icon file handle
    CleanupStack::PopAndDestroy(&appArcIcon);

    // close file server connection
    CleanupStack::PopAndDestroy(&fileServ);

    return err;
}


/**
 * Unregisters Java Application from S60 AppArc
 *
 * @param[in] aSessionHandle
 * @param[in] aUid The Uid of the application to be unregistered..
 * @return 0 if unregistration succeeded or Symbian error code
 */
#if 0
//#ifdef RD_JAVA_USIF_APP_REG
JNIEXPORT jint JNICALL Java_com_nokia_mj_impl_installer_applicationregistrator_ApplicationRegistrator__1unregisterApplication
(JNIEnv *, jclass, jint /*aSessionHandle*/, jint /*aUid*/)
{
    return KErrNone;
}
#else
JNIEXPORT jint JNICALL Java_com_nokia_mj_impl_installer_applicationregistrator_ApplicationRegistrator__1unregisterApplication
(JNIEnv *, jclass, jint aSessionHandle, jint aUid)
{
    // Convert session handle to pointer.
    RApaLsSession *pApaSession =
        reinterpret_cast<RApaLsSession*>(aSessionHandle<<2);

    TUid appUid;
    appUid.iUid = aUid;
    TRAPD(err, pApaSession->DeregisterNonNativeApplicationL(appUid));
    return err;
}
#endif // RD_JAVA_USIF_APP_REG


/**
 * Commits native application registration session.
 * If commit succeeds the native session is closed.
 *
 * @param[in] aSessionHandle
 * @param[in] aSynchronous if true, makes synchronous commit
 * @return 0 or Symbian error code (negative number)
 */
JNIEXPORT jint JNICALL Java_com_nokia_mj_impl_installer_applicationregistrator_ApplicationRegistrator__1commitSession
(JNIEnv *, jclass, jint aSessionHandle, jboolean aSynchronous)
{
    (void)aSynchronous; // suppress compilation warning about unused argument
    // Convert session handle to pointer.
    RApaLsSession *pApaSession =
        reinterpret_cast<RApaLsSession*>(aSessionHandle<<2);

    TInt err = KErrNone;

#if 1
//#ifndef RD_JAVA_USIF_APP_REG
    if (aSynchronous)
    {
        // Make synchronous commit
        TRAP(err, pApaSession->CommitNonNativeApplicationsUpdatesL());
        if (KErrNone == err)
        {
            pApaSession->Close();
            delete pApaSession;
        }
        return err;
    }

    // Otherwise check whether the device supports asynchronous commit
    // (has a working version of new AppArc method ForceCommitNonNativeApplicationsUpdatesL)
    // Latest S60 5.0 builds contain fix for Symbian
    // defect PDEF129466 (PDEF129467 for Symbian OS 9.5).
    if (!isForceCommitSupported())
    {
        // Use old API
        TRAP(err, pApaSession->CommitNonNativeApplicationsUpdatesL());
    }
    else
    {
#ifdef __WINS__
        // Use always this synchronous commit when running in emulator
        // to make writing autotest cases easier.
        TRAP(err, pApaSession->CommitNonNativeApplicationsUpdatesL());
#else
        // asynchronous commit
        TRAP(err, pApaSession->ForceCommitNonNativeApplicationsUpdatesL());
#endif // __WINS__
    }
#endif // RD_JAVA_USIF_APP_REG

    if (KErrNone == err)
    {
        pApaSession->Close();
        delete pApaSession;
    }
    return err;
}


/**
 * Rolls back and closes native application registration session.
 *
 * @param[in] aSessionHandle
 * @return 0 or Symbian error code (negative number)
 */
JNIEXPORT jint JNICALL Java_com_nokia_mj_impl_installer_applicationregistrator_ApplicationRegistrator__1rollbackSession
(JNIEnv *, jclass, jint aSessionHandle)
{
    // Convert session handle to pointer.
    RApaLsSession *pApaSession =
        reinterpret_cast<RApaLsSession*>(aSessionHandle<<2);

    TInt err = KErrNone;
#if 1
//#ifndef RD_JAVA_USIF_APP_REG
    err = pApaSession->RollbackNonNativeApplicationsUpdates();
#endif // RD_JAVA_USIF_APP_REG
    pApaSession->Close();
    delete pApaSession;

    return err;
}


/**
 * Tells whether the uid is in use in AppArc.
 * Calls AppArc RApaLsSession::GetAppType
 *
 * @param[in] aSessionHandle
 * @param[in] aUid
 * @return 0 if the uid is not in use,
 *  1 if the uid is in use
 */
JNIEXPORT jint JNICALL Java_com_nokia_mj_impl_installer_applicationregistrator_ApplicationRegistrator__1uidInUse
(JNIEnv *, jclass, jint aSessionHandle, jint aUid)
{
    // Convert session handle to pointer.
    RApaLsSession *pApaSession =
        reinterpret_cast<RApaLsSession*>(aSessionHandle<<2);

    TUid typeUid;
    TUid appUid;
    appUid.iUid = aUid;
    TInt err = pApaSession->GetAppType(typeUid, appUid);
    if (KErrNone == err)
    {
        // AppArc knows the app type -> the uid is in use
        return 1;
    }
    else
    {
        return 0;
    }
}


/**
 * Returns the logical group name of the application.
 * Calls AppArc RApaLsSession::GetAppCapability
 *
 * @param[in] aSessionHandle
 * @param[in] aUid
 * @param[out] aGroupName should be "" when called, will contain group name
 *  when function returns if call was successfull.
 *  Note that max group name len is 16.
 * @return Symbian error code (negative number) if fails, otherwise 0
 */
JNIEXPORT jint JNICALL Java_com_nokia_mj_impl_installer_applicationregistrator_ApplicationRegistrator__1getGroupName
(JNIEnv *aEnv, jclass aClass, jint aSessionHandle, jint aUid, jobject aGroupName)
{
    if (0 == aGroupName)
    {
        // Cannot return logical group name because StringBuffer param is null
        return KErrArgument;
    }

    // Convert session handle to pointer.
    RApaLsSession *pApaSession =
        reinterpret_cast<RApaLsSession*>(aSessionHandle<<2);

    TInt    err;
    TUid    midletUid;
    TApaAppCapabilityBuf cap;

    midletUid.iUid = aUid;

    err = pApaSession->GetAppCapability(cap, midletUid);
    if (KErrNone != err)
    {
        return err;
    }

    // The name is available in Unicode format from cap, convert it to UTF8
    // Then lenght of the buffer has '+1' to reserve space for zero terminator
    // needed to convert string to Java string
    TBuf8<KApaMaxAppGroupName+1> nameBuf;   // max group name len is 16
    err = CnvUtfConverter::ConvertFromUnicodeToUtf8(nameBuf, cap().iGroupName);
    if (KErrNone != err)
    {
        return err;
    }

    // Get class handle to StringBuffer
    aClass = aEnv->GetObjectClass(aGroupName);

    // Get method ID to StringBuffer StringBuffer.append(String)
    jmethodID methodID = aEnv->GetMethodID(
                             aClass,
                             "append",
                             "(Ljava/lang/String;)Ljava/lang/StringBuffer;");
    if (0 == methodID)
    {
        return KErrGeneral;
    }

    // Create new Java String
    jstring logicalName = aEnv->NewStringUTF((const char*)(nameBuf.PtrZ()));

    // Append it to aGroupName parameter
    aEnv->CallObjectMethod(aGroupName, methodID, logicalName);

    return 0;
}


/**
 * Closes native application registration session.
 *
 * @param[in] aSessionHandle the session to be closed
 */
JNIEXPORT void JNICALL Java_com_nokia_mj_impl_installer_applicationregistrator_ApplicationRegistrator__1closeSession
(JNIEnv *, jclass, jint aSessionHandle)
{
    // Convert session handle to pointer.
    RApaLsSession *pApaSession =
        reinterpret_cast<RApaLsSession*>(aSessionHandle<<2);

    pApaSession->Close();
    delete pApaSession;
}


/**
 * Converts icon to S60 specific format. SVG icons are converted to MIF,
 * other icons to MBM.
 *
 * @param[in] aInputIconFilename file name of the original icon inside .jar
 * @param[in] aOutputIconFilename file name for converted (output) icon
 * @param[in] aJarFilename jar file name. In S60 the icon is always
 *   inside the .jar file
 * @param[out] aIconSuffix the correct suffix of the icon is returned through
 *    this parameter, will contain '.mbm' or '.mif' when function returns
 * @return true if the conversion succeeds
 */
JNIEXPORT jboolean JNICALL Java_com_nokia_mj_impl_installer_applicationregistrator_ApplicationRegistrator__1convertIcon
(JNIEnv *aEnv, jclass aClass, jstring aInputIconFilename,
 jstring aOutputIconFilename, jstring aJarFilename, jobject aIconSuffix)
{
    jboolean conversionSucceeded = JNI_TRUE;
    RFs      fileServ;

    // IconConverter requires open RFile handle
    TInt err = fileServ.Connect();
    if (KErrNone != err)
    {
        // Cannot convert icons without file server connection
        ELOG1(EJavaInstaller,
              "_1convertIcon: Cannot open RFs connection, err code is %d ", err);
        return err;
    }

    // Copy the unicode characters in jstrings to Symbian buffers so that
    // they can be used in S60 code
    const jchar *iconFileName = aEnv->GetStringChars(aInputIconFilename, 0);
    if (NULL == iconFileName)
    {
        ELOG(
            EJavaInstaller,
            "Cannot convert icon, getting icon file name as unicode failed in JNI");
        fileServ.Close();
        return JNI_FALSE;
    }
    HBufC16 *unicodeIconFileName = HBufC16::New(aEnv->GetStringLength(aInputIconFilename) + 1);
    if (NULL == unicodeIconFileName)
    {
        fileServ.Close();
        return JNI_FALSE;
    }
    *unicodeIconFileName = iconFileName;
    aEnv->ReleaseStringChars(aInputIconFilename, iconFileName);

    const jchar *jarFileName = aEnv->GetStringChars(aJarFilename, 0);
    if (NULL == jarFileName)
    {
        ELOG(
            EJavaInstaller,
            "Cannot convert icon, getting jar file name as unicode failed in JNI");
        delete unicodeIconFileName;
        fileServ.Close();
        return JNI_FALSE;
    }
    HBufC16 *unicodeJarFileName = HBufC16::New(aEnv->GetStringLength(aJarFilename) + 1);
    if (NULL == unicodeJarFileName)
    {
        delete unicodeIconFileName;
        fileServ.Close();
        return JNI_FALSE;
    }
    *unicodeJarFileName = jarFileName;
    aEnv->ReleaseStringChars(aJarFilename, jarFileName);

    const jchar *outputFileName = aEnv->GetStringChars(aOutputIconFilename, 0);
    if (NULL == outputFileName)
    {
        ELOG(
            EJavaInstaller,
            "Cannot convert icon, getting output file name as unicode failed in JNI");
        delete unicodeIconFileName;
        delete unicodeJarFileName;
        fileServ.Close();
        return JNI_FALSE;
    }
    HBufC16 *unicodeOutputFileName = HBufC16::New(aEnv->GetStringLength(aOutputIconFilename) + 1);
    if (NULL == unicodeOutputFileName)
    {
        delete unicodeIconFileName;
        delete unicodeJarFileName;
        fileServ.Close();
        return JNI_FALSE;
    }
    *unicodeOutputFileName = outputFileName;
    aEnv->ReleaseStringChars(aOutputIconFilename, outputFileName);

    CIconConverter *pConv = NULL;
    TRAP(err, pConv= CIconConverter::NewL(fileServ));
    if (KErrNone != err)
    {
        ELOG1(EJavaInstaller, "Cannot create icon converter, error %d ", err);
        delete unicodeIconFileName;
        delete unicodeJarFileName;
        delete unicodeOutputFileName;
        fileServ.Close();
        return JNI_FALSE;
    }

    // read icon from .jar file, convert it to MIF/MBM and store to file
    TBool isMbmIcon = EFalse;
    err = pConv->Convert(*unicodeJarFileName, *unicodeIconFileName,
                         *unicodeOutputFileName, &isMbmIcon);
    delete pConv;
    if (KErrNone != err)
    {
        WLOG1(EJavaInstaller,
              "Cannot convert icon, err code is %d.",
              err);
        conversionSucceeded = JNI_FALSE;
    }

    // Free all Symbian buffers containing copies of jstring data
    delete unicodeIconFileName;
    delete unicodeJarFileName;
    delete unicodeOutputFileName;
    fileServ.Close();

    // set the value of aIconSuffix to '.mbm' or '.mif'
    if (0 == aIconSuffix)
    {
        // Cannot return icon suffix name because StringBuffer param is null
        WLOG(EJavaInstaller,
             "_1convertIcon cannot return the correct icon suffix because param is null");
        return JNI_FALSE;
    }

    // Get class handle to StringBuffer
    aClass = aEnv->GetObjectClass(aIconSuffix);

    // Get method ID to StringBuffer StringBuffer.append(String)
    jmethodID methodID = aEnv->GetMethodID(
                             aClass,
                             "append",
                             "(Ljava/lang/String;)Ljava/lang/StringBuffer;");
    if (0 == methodID)
    {
        WLOG(EJavaInstaller, "_1convertIcon: JNI: getting append method failed.");
        return JNI_FALSE;
    }

    // Create new Java String, Multibitmap file name suffix is '.mbm',
    // suffix for mif wrapped svg is '.mif'
    jstring suffix;
    if (isMbmIcon)
    {
        suffix = aEnv->NewStringUTF(".mbm");
    }
    else
    {
        suffix = aEnv->NewStringUTF(".mif");
    }

    // Append it to aIconSuffix parameter
    aEnv->CallObjectMethod(aIconSuffix, methodID, suffix);

    return conversionSucceeded;
}


/**
 * Returns true if the current device is touch screen
 * device without physical LSK and RSK
 *
 * @return true if virtual on screen keypad is needed
 */
JNIEXPORT jboolean JNICALL Java_com_nokia_mj_impl_installer_applicationregistrator_ApplicationRegistrator__1isOnDeviceKeypadNeeded
(JNIEnv *, jclass)
{
    // Return TRUE -> OnScreenKeypad attribute will be given
    // default value if the attribute has not been defined in
    // .jad file or manifest.
    // The runtime code will check whether the device has touch
    // screen using AknLayoutUtils::PenEnabled() and show the
    // keypad only if needed.
    return JNI_TRUE;
}


/**
 * Sends a process to process notification to the parent process
 * of Java Installer telling that Installer is about to start
 * displaying UI dialogs.
 */
JNIEXPORT void JNICALL Java_com_nokia_mj_impl_installer_applicationregistrator_ApplicationRegistrator__1notifyLauncherThatUiIsReady
(JNIEnv *, jclass)
{
    RProcess currentProcess;
    currentProcess.Rendezvous(EJavaInstaller);

    return;
}


/**
 * Returns true if the code is executed in Symbian 9.2
 * emulator environment.
 *
 * @return if Symbian 9.2 emulator environment
 */
JNIEXPORT jboolean JNICALL Java_com_nokia_mj_impl_installer_applicationregistrator_ApplicationRegistrator__1runningIn92Emulator
(JNIEnv *, jclass)
{
#if !defined(RD_JAVA_S60_RELEASE_5_0_IAD) && defined(__WINS__)
    return JNI_TRUE;
#else
    return JNI_FALSE;
#endif
}


/**
 * Internal helper method for checking whether this code is executing in
 * a device that has correctly working version of
 * RApaLsSession::ForceCommitNonNativeApplicationsUpdatesL()
 *
 * The device family based on Nokia XpressMusic5800 did not have
 * working version of force commit
 *
 * @return ETrue if current device does not belong to Nokia XpressMusic5800
 *  device family
 */
TBool isForceCommitSupported()
{
    TInt err;
    TInt value;

    err = HAL::Get(HAL::EModel, value);
    if (KErrNone == err)
    {
        LOG1(EJavaInstaller, EInfo, "Device model is %d", value);
    }
    else
    {
        WLOG1(EJavaInstaller, "Cannot get device model id, error %d", err);
        // It is safest to assume that force commit is not supported
        return EFalse;
    }

    // Check against all current (28. Aug 2009) members of the device family.
    // Note that several closely related devices share the same model id.
    if ((0x2000DA56 != value) &&
            (0x2001DE9D != value) &&
            (0x2000DA60 != value) &&
            (0x20023765 != value))
    {
        // The device does not belong to Nokia 5800 XpressMusic device family,
        // so it supports foce commit
        return ETrue;
    }
    else
    {
        return EFalse;
    }
}