javamanager/javainstaller/installer/javasrc.s60/com/nokia/mj/impl/installer/applicationregistrator/SifRegistrator.java
author hgs
Fri, 29 Oct 2010 11:49:32 +0300
changeset 87 1627c337e51e
parent 50 023eef975703
permissions -rw-r--r--
v2.2.21_1

/*
* Copyright (c) 2009-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:
*
*/


package com.nokia.mj.impl.installer.applicationregistrator;

import com.nokia.mj.impl.installer.storagehandler.ApplicationInfo;
import com.nokia.mj.impl.installer.storagehandler.SuiteInfo;
import com.nokia.mj.impl.installer.utils.ComponentId;
import com.nokia.mj.impl.installer.utils.InstallerException;
import com.nokia.mj.impl.installer.utils.FileUtils;
import com.nokia.mj.impl.installer.utils.Log;
import com.nokia.mj.impl.installer.utils.PlatformUid;
import com.nokia.mj.impl.utils.Attribute;
import com.nokia.mj.impl.utils.Uid;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

/**
 * Registers (and unregisters) Java application to S60 platform's
 * software installation framework (USIF).
 */
public final class SifRegistrator
{
    /** Added application. Used with notifyAppChange() method. */
    public static final int APP_ADDED = 0;
    /** Removed application. Used with notifyAppChange() method. */
    public static final int APP_REMOVED = 1;
    /** Updated application. Used with notifyAppChange() method. */
    public static final int APP_UPDATED = 2;

    /** Native session handle. */
    private int iSessionHandle = 0;

    /*** ----------------------------- PUBLIC ------------------------------ */

    /**
     * Returns greater than zero if application registration to
     * software installation framework is enabled.
     */
    public static int getSifMode()
    {
        return _getUsifMode();
    }

    /**
     * Returns SIF specific error category from given error id.
     */
    public static int getErrorCategory(int aErrorId)
    {
        return _getErrorCategory(aErrorId);
    }

    /**
     * Launches the application view. If launching application view
     * fails this method does not throw exception but produces an
     * error log entry.
     */
    public static void launchAppView()
    {
        int err = _launchAppView();
        if (err < 0)
        {
            Log.logError("Launching AppLib failed with code " + err);
        }
    }

    /**
     * Notifies system about added/updated/removed applications.
     * This method should be called only after the changes have been
     * committed.
     *
     * @param aAppUids application uids
     * @param aAppChange change type: APP_ADDED, APP_UPDATED, or APP_REMOVED
     * @throws InstallerException if notification fails
     */
    public static void notifyAppChange(Uid[] aAppUids, int aAppChange)
    {
        if (aAppUids == null || aAppUids.length == 0)
        {
            return;
        }
        int[] appUids = new int[aAppUids.length];
        for (int i = 0; i < appUids.length; i++)
        {
            appUids[i] = ((PlatformUid)aAppUids[i]).getIntValue();
        }
        int err = _notifyAppChange(appUids, aAppChange);
        if (err < 0)
        {
            InstallerException.internalError(
                "Notifying app changes failed with code " + err);
        }
    }

    /**
     * Get component uid basing on component id.
     * This method can be called before session is created.
     *
     * @param aCid component id
     * @return uid for the component, or null if component is not found
     * @throws InstallerException if an error occurs
     */
    public static Uid getUid(int aCid)
    {
        // Use ComponentId to return int type value from native to java.
        ComponentId id = new ComponentId();
        int err = _getUid(aCid, id);
        if (err < 0)
        {
            InstallerException.internalError(
                "Getting uid for cid " + aCid + " failed with code " + err);
        }
        Uid uid = null;
        if (id.getId() != 0)
        {
            uid = PlatformUid.createUid(id.getId());
        }
        return uid;
    }

    /**
     * Starts application registration session.
     * The registrations and unregistrations are done only
     * when commitSession is called.
     * If you want to discard the registrations and unregistrations
     * call rollbackSession.
     * Does nothing if session has already been successfully started
     * from this SifRegistrator instance.
     *
     * @param aTransaction true if also transaction for this session should
     * be opened, false otherwise
     * @throws InstallerException if the session cannot created
     * @see commitSession
     * @see rollbackSession
     */
    public void startSession(boolean aTransaction)
    {
        if (0 != iSessionHandle)
        {
            // Session has already been created, do nothing.
            Log.logWarning("SifRegistrator.startSession called although session is already open.");
            return;
        }

        // Native method writes error log and returns
        // negative Symbian error code if it fails.
        int ret = _startSession(aTransaction);
        if (ret < 0)
        {
            InstallerException.internalError(
                "Creating SIF session failed with code " + ret);
        }
        //Log.log("SifRegistrator session started");
        iSessionHandle = ret;
    }

    /**
     * Registers Java application suite to S60 USIF.
     *
     * @param aSuiteInfo Information needed to register the application
     * @param aIsUpdate true in case of an update, false in case of a new
     * installation
     * @throws InstallerException if registration cannot done or
     *  startSession has not been called successfully
     * @see startSession
     * @see SuiteInfo
     */
    public void registerSuite(SuiteInfo aSuiteInfo, boolean aIsUpdate)
    {
        checkSession();
        Log.log("SifRegistrator registering application suite " +
                aSuiteInfo.getGlobalId());

        // Register suite as a component.
        registerComponent(aSuiteInfo, aIsUpdate);
        registerLocalizedComponentName(aSuiteInfo, -1);
        // Register applications within the component.
        Vector apps = aSuiteInfo.getApplications();
        for (int i = 0; i < apps.size(); i++)
        {
            registerApplication(aSuiteInfo, i);
        }
        registerLocalizedProperties(aSuiteInfo);
    }

    /**
     * Unregisters Java application suite from S60 USIF.
     *
     * @param aSuiteInfo Information needed to unregister the application,
     * @throws InstallerException if unregistration cannot done or
     *  startSession has not been called successfully
     * @see startSession
     * @see SuiteInfo
     */
    public void unregisterSuite(SuiteInfo aSuiteInfo)
    {
        checkSession();
        Log.log("SifRegistrator unregistering application suite " +
                aSuiteInfo.getGlobalId());

        // Unregister suite as a component.
        unregisterComponent(aSuiteInfo);
    }

    /**
     * Commits the registrations and unregistrations.
     * Ends the current session if commit is successfull.
     * If commit fails the session is kept open so that
     * rollbackSession can be called.
     *
     * @throws InstallerException if session cannot be committed
     */
    public void commitSession()
    {
        checkSession();
        int err = _commitSession(iSessionHandle);
        if (err < 0)
        {
            InstallerException.internalError("Commiting SIF session failed with code " + err);
        }
        // Current session has been closed
        iSessionHandle = 0;
        //Log.log("SifRegistrator session committed");
    }

    /**
     * Rolls back the registrations and unregistrations.
     * Ends the current session.
     *
     * @throws InstallerException if session cannot be rolled back.
     */
    public void rollbackSession()
    {
        checkSession();
        int err = _rollbackSession(iSessionHandle);
        // Session is closed always when rollback is called
        iSessionHandle = 0;
        if (err < 0)
        {
            InstallerException.internalError("Rolling back SIF session failed with code " + err);
        }
        //Log.log("SifRegistrator session rolled back");
    }

    /**
     * Closes the current session if it still open.
     * If registerComponent or unregisterComponent has been called,
     * commitSession or rollbackSession must be called instead of this method.
     */
    public void closeSession()
    {
        if (0 == iSessionHandle)
        {
            return;
        }
        _closeSession(iSessionHandle);
        // Current session has been closed
        iSessionHandle = 0;
        //Log.log("SifRegistrator session closed");
    }

    /**
     * Returns the component id of the application.
     *
     * @param aGlobalId the global id for the application.
     * @return the component id for the application, or null if the
     * application with given global id cannot be found.
     * @throws InstallerException if an error occurs
     */
    public ComponentId getComponentId(String aGlobalId)
    {
        checkSession();
        ComponentId result = new ComponentId();
        int ret = _getComponentId(iSessionHandle, aGlobalId, result);
        if (-1 == ret)
        {
            // Symbian error code KErrNotFound means that the
            // application with given global id does not exist.
            result = null;
        }
        else if (ret < -1)
        {
            InstallerException.internalError(
                "Getting component id for global id " + aGlobalId +
                " failed with code " + ret);
        }
        return result;
    }

    /**
     * Returns the component id of the application.
     *
     * @param aAppUid the uid for the application.
     * @return the component id for the application, or null if the
     * application with given uid cannot be found.
     * @throws InstallerException if an error occurs
     */
    public ComponentId getComponentId(Uid aAppUid)
    {
        checkSession();
        ComponentId result = new ComponentId();
        int ret = _getComponentIdForApp(
                      iSessionHandle, ((PlatformUid)aAppUid).getIntValue(), result);
        if (-1 == ret)
        {
            // Symbian error code KErrNotFound means that the
            // application with given uid does not exist.
            result = null;
        }
        else if (ret < -1)
        {
            InstallerException.internalError(
                "Getting component id for uid " + aAppUid +
                " failed with code " + ret);
        }
        return result;
    }

    /**
     * Writes information of the given application to JavaInstaller log.
     *
     * @param aGlobalId the global id for the application.
     */
    public void logComponent(String aGlobalId)
    {
        checkSession();
        int ret = _logComponent(iSessionHandle, aGlobalId);
        if (ret < -1)
        {
            Log.logError("SifRegistrator logComponent for " + aGlobalId +
                         " failed with code " + ret);
        }
    }

    /*** ----------------------------- PACKAGE ---------------------------- */
    /*** ----------------------------- PRIVATE ---------------------------- */

    /**
     * Checks if SifRegistrator session has been started.
     * @throws InstallerException if SifRegistrator session has not been started
     */
    private void checkSession()
    {
        if (iSessionHandle == 0)
        {
            InstallerException.internalError("No valid SIF session.");
        }
    }

    /**
     * Registers Java application suite to S60 USIF as a component.
     *
     * @param aSuiteInfo Suite information
     * @param aIsUpdate true in case of an update, false in case of a new
     * installation
     * @throws InstallerException if registration cannot done or
     *  startSession has not been called successfully
     * @see startSession
     * @see SuiteInfo
     */
    private void registerComponent(SuiteInfo aSuiteInfo, boolean aIsUpdate)
    {
        String globalId = aSuiteInfo.getGlobalId();
        String suiteName = aSuiteInfo.getName();
        String vendor = aSuiteInfo.getVendor();
        String version = aSuiteInfo.getVersion().toString();
        int uid = ((PlatformUid)aSuiteInfo.getUid()).getIntValue();
        String[] componentFiles = getComponentFiles(aSuiteInfo);
        long componentSize = aSuiteInfo.getInitialSize();
        int installState = (aSuiteInfo.isPreinstalled()? 1: 0);
        String attrValue = aSuiteInfo.getAttributeValue("Nokia-MIDlet-Block-Uninstall");
        boolean isRemovable = !(attrValue != null && attrValue.equalsIgnoreCase("true"));
        boolean isDrmProtected = (aSuiteInfo.getContentInfo() == aSuiteInfo.CONTENT_INFO_DRM);
        boolean isOriginVerified = aSuiteInfo.isTrusted();
        String midletInfoUrl = aSuiteInfo.getAttributeValue("MIDlet-Info-URL");
        String midletDescription = aSuiteInfo.getAttributeValue("MIDlet-Description");
        String downloadUrl = aSuiteInfo.getAttributeValue("Nokia-MIDlet-Download-URL");
        String updateUrl = aSuiteInfo.getAttributeValue("Nokia-Update");
        ComponentId componentId = new ComponentId();
        int err = _registerComponent(
                      iSessionHandle, uid,
                      getScrString(suiteName), getScrString(vendor),
                      getScrString(version), getScrString(globalId),
                      componentFiles, componentSize, installState,
                      isRemovable, isDrmProtected,
                      isOriginVerified, aIsUpdate,
                      aSuiteInfo.getMediaId(),
                      getScrString(midletInfoUrl),
                      getScrString(midletDescription),
                      getScrString(downloadUrl),
                      getScrString(updateUrl),
                      componentId);
        if (err < 0)
        {
            InstallerException.internalError(
                "Registering component " + globalId +
                " failed with code " + err);
        }
        else
        {
            aSuiteInfo.setComponentId(componentId);
            Log.log("SifRegistrator registered component " + globalId +
                    " with id " + componentId.getId());
        }
    }

    /**
     * Unregisters Java application suite from being S60 USIF component.
     *
     * @param aSuiteInfo suite information
     * @throws InstallerException if unregistration cannot done or
     *  startSession has not been called successfully
     * @see startSession
     * @see SuiteInfo
     */
    private void unregisterComponent(SuiteInfo aSuiteInfo)
    {
        String globalId = aSuiteInfo.getGlobalId();
        ComponentId componentId = getComponentId(globalId);
        if (componentId == null)
        {
            Log.logWarning(
                "SifRegistrator unregistration failed, application " +
                globalId + " does not exist");
            return;
        }
        // Save component id to SuiteInfo.
        aSuiteInfo.setComponentId(componentId);
        // Unregister application.
        int err = _unregisterComponent(iSessionHandle, componentId.getId());
        if (err < 0)
        {
            InstallerException.internalError(
                "Unregistering component " + globalId +
                " failed with code " + err);
        }
        else
        {
            Log.log("SifRegistrator unregistered component " + globalId +
                    " with id " + componentId.getId());
        }
    }

    /**
     * Registers one Java application to S60 USIF as an S60 application.
     * The application is registered to component whose id is taken
     * from given SuiteInfo object. The SuiteInfo must already have
     * been registered to USIF as a component with registerComponent()
     * method before this method is called.
     *
     * @param aSuiteInfo information needed to register the application
     * @param aIndex index of the application in the suite
     * @throws InstallerException if registration cannot done or
     *  startSession has not been called successfully
     * @see startSession
     * @see SuiteInfo
     */
    private void registerApplication(SuiteInfo aSuiteInfo, int aIndex)
    {
        int cid = aSuiteInfo.getComponentId().getId();
        ApplicationInfo appInfo =
            (ApplicationInfo)aSuiteInfo.getApplications().elementAt(aIndex);
        int appUid = ((PlatformUid)appInfo.getUid()).getIntValue();
        String appName = appInfo.getName();
        String appFilename = aSuiteInfo.getJarPath();
        String groupName = aSuiteInfo.getInstallationGroup();
        if (groupName == null)
        {
            groupName = ""; // default installation group
        }
        String iconFilename = null;
        if (!appInfo.getUseDefaultIcon())
        {
            iconFilename = aSuiteInfo.getRegisteredIconPath(aIndex);
        }
        Log.log("SifRegistrator iconFilename " + aIndex + ": " + iconFilename);
        int numberOfIcons = 1;
        // Initalize localized names for the application.
        LocalizedName[] localizedNames = getLocalizedNames(
                                             aSuiteInfo, "Nokia-MIDlet-" + (aIndex+1) + "-");
        int[] languages = new int[localizedNames.length];
        String[] appNames = new String[localizedNames.length];
        for (int i = 0; i < localizedNames.length; i++)
        {
            languages[i] = localizedNames[i].getLanguage();
            appNames[i] = localizedNames[i].getName();
        }
        int err = _registerApplication(
                      iSessionHandle, cid, appUid, appName, appFilename, groupName,
                      iconFilename, numberOfIcons, languages, appNames);
        if (err < 0)
        {
            InstallerException.internalError(
                "Registering application " + appUid + " to component " + cid +
                " failed with code " + err);
        }
        else
        {
            Log.log("SifRegistrator registered application " + appUid +
                    " to component " + cid);
        }
    }

    private static String[] getComponentFiles(SuiteInfo aSuite)
    {
        Vector componentFiles = new Vector();
        if (!aSuite.isPreinstalled())
        {
            // Add component jad and jar files only when the
            // application is not preinstalled.
            String path = aSuite.getJadPath();
            if (path != null)
            {
                componentFiles.addElement(getScrString(path));
            }
            path = aSuite.getJarPath();
            if (path != null)
            {
                componentFiles.addElement(getScrString(path));
            }
        }
        boolean addRootPath = true;
        int rootDrive = FileUtils.getDrive(aSuite.getRootDir());
        for (int i = 0; i < componentFiles.size(); i++)
        {
            if (FileUtils.getDrive((String)componentFiles.elementAt(i)) ==
                    rootDrive)
            {
                // File from the root path drive already exists in
                // component files vector, no need to add root path
                // separately.
                addRootPath = false;
                break;
            }
        }
        if (addRootPath)
        {
            componentFiles.addElement(
                getScrString(aSuite.getRootDir() + "nofile.txt"));
        }
        String[] result = new String[componentFiles.size()];
        componentFiles.copyInto(result);
        for (int i = 0; i < result.length; i++)
        {
            Log.log("SifRegistrator componentFiles[" + i + "]: " + result[i]);
        }
        return result;
    }

    /**
     * Registers localized names for given application from given suite.
     * This method can be called only after registerComponent method has
     * been called.
     *
     * @param aSuite suite info
     * @param aIndex index of the application within the suite, if -1 then
     * localized names for the suite itself is registered
     */
    private void registerLocalizedComponentName(SuiteInfo aSuite, int aIndex)
    {
        LocalizedName[] localizedNames = null;
        int cid = 0;
        if (aIndex == -1)
        {
            if (aSuite.getComponentId() == null)
            {
                Log.log(
                    "SifRegistrator.registerLocalizedComponentName: cid not present in suite");
                return;
            }
            cid = aSuite.getComponentId().getId();
            localizedNames = getLocalizedNames(aSuite, "Nokia-MIDlet-Name-");
        }
        else
        {
            ApplicationInfo app =
                (ApplicationInfo)aSuite.getApplications().elementAt(aIndex);
            if (app.getComponentId() == null)
            {
                Log.log(
                    "SifRegistrator.registerLocalizedComponentName: cid not present in app");
                return;
            }
            cid = app.getComponentId().getId();
            localizedNames = getLocalizedNames(
                                 aSuite, "Nokia-MIDlet-" + (aIndex+1) + "-");
        }
        for (int i = 0; i < localizedNames.length; i++)
        {
            int err = _registerLocalizedComponentName(
                          iSessionHandle, cid,
                          getScrString(localizedNames[i].getName()),
                          getScrString(aSuite.getVendor()),
                          localizedNames[i].getLanguage());
            if (err < 0)
            {
                InstallerException.internalError(
                    "Adding localized name for component " + cid +
                    " failed with code " + err +
                    " (" + localizedNames[i] + ")");
            }
        }
    }

    /**
     * Registers localized property values for given suite.
     * This method can be called only after registerComponent
     * method has been called.
     *
     * @param aSuite suite info
     */
    private void registerLocalizedProperties(SuiteInfo aSuite)
    {
        if (aSuite.getComponentId() == null)
        {
            Log.log(
                "SifRegistrator.registerLocalizedProperties: cid not present in suite");
            return;
        }
        int cid = aSuite.getComponentId().getId();
        final int UNSPECIFIED_LOCALE = -1; // KUnspecifiedLocale

        // Register MIDlet-Delete-Confirm attribute values.
        final String attrName = "MIDlet-Delete-Confirm";
        String nonlocalizedAttrValue = aSuite.getAttributeValue(attrName);
        int err = _setLocalizedComponentProperty(
                      iSessionHandle, cid, getScrString(attrName),
                      getScrString(nonlocalizedAttrValue), UNSPECIFIED_LOCALE);
        if (err < 0)
        {
            InstallerException.internalError(
                "Adding property " + attrName + " for component " + cid +
                " failed with code " + err + " (" + nonlocalizedAttrValue + ")");
        }
        LocalizedName[] localizedAttrValues =
            getLocalizedNames(aSuite, "Nokia-" + attrName + "-");
        for (int i = 0; i < localizedAttrValues.length; i++)
        {
            err = _setLocalizedComponentProperty(
                      iSessionHandle, cid, getScrString(attrName),
                      getScrString(localizedAttrValues[i].getName()),
                      localizedAttrValues[i].getLanguage());
            if (err < 0)
            {
                InstallerException.internalError(
                    "Adding localized property " + attrName +
                    " for component " + cid + " failed with code " + err +
                    " (" + localizedAttrValues[i] + ")");
            }
        }

        // Register Domain-Category property.
        String protectionDomainProperty = "Domain-Category";
        String protectionDomainName = aSuite.getProtectionDomainName();
        err = _setLocalizedComponentProperty(
            iSessionHandle, cid, protectionDomainProperty,
            getProtectionDomainPropertyValue(protectionDomainName),
            UNSPECIFIED_LOCALE);
        if (err < 0)
        {
            InstallerException.internalError(
                "Adding property " + protectionDomainProperty +
                " value " + protectionDomainName + " for component " +
                cid + " failed with code " + err);
        }
    }

    /**
     * Returns the "Domain-Category" property value which contains
     * the text id and text file name for the localized domain category
     * text. This method must never return null.
     */
    private String getProtectionDomainPropertyValue(String aProtectionDomain)
    {
        String textId = "txt_java_inst_setlabel_cert_domain_val_untrusted_third_party";
        if (aProtectionDomain != null)
        {
            if (aProtectionDomain.equals("Manufacturer"))
            {
                textId = "txt_java_inst_setlabel_cert_domain_val_manufacturer";
            }
            else if (aProtectionDomain.equals("Operator"))
            {
                textId = "txt_java_inst_setlabel_cert_domain_val_operator";
            }
            else if (aProtectionDomain.equals("IdentifiedThirdParty"))
            {
                textId = "txt_java_inst_setlabel_cert_domain_val_trusted_third_party";
            }
        }
        return textId + ",javaapplicationinstaller";
    }

    /**
     * Returns array of localized names from the specified
     * attributes of given suite. Assumes that aAttrPrefix
     * is an attribute name prefix that is followed by locale.
     * If the same locale is found more than once, localized
     * name for only the last occurrence is returned.
     */
    private LocalizedName[] getLocalizedNames(
        SuiteInfo aSuite, String aAttrPrefix)
    {
        Hashtable localizedNames = new Hashtable();
        Enumeration e = aSuite.getAttributes().elements();
        while (e.hasMoreElements())
        {
            Attribute attr = (Attribute)e.nextElement();
            String name = attr.getName();
            if (name.startsWith(aAttrPrefix))
            {
                String locale = name.substring(aAttrPrefix.length());
                if (isValidLocale(locale))
                {
                    LocalizedName localizedName =
                        new LocalizedName(attr.getValue(), locale);
                    if (localizedName.getLanguage() == -1)
                    {
                        Log.logWarning(
                            "SifRegistrator ignored unknown locale: " +
                            name + ": " + localizedName);
                    }
                    else if (localizedName.getName() == null ||
                             localizedName.getName().length() == 0)
                    {
                        Log.logWarning(
                            "SifRegistrator ignored empty localized text: " +
                            name + ": " + localizedName);
                    }
                    else
                    {
                        Log.log("SifRegistrator found localized text " +
                                name + ": " + localizedName);
                        localizedNames.put(
                            new Integer(localizedName.getLanguage()),
                            localizedName);
                    }
                }
            }
        }
        LocalizedName[] result = new LocalizedName[localizedNames.size()];
        e = localizedNames.elements();
        for (int i = 0; e.hasMoreElements(); i++)
        {
            result[i] = (LocalizedName)e.nextElement();
        }
        return result;
    }

    /**
     * Returns true if given locale is a valid one. Valid locales
     * use two letter ISO language and optionally country codes.
     */
    private boolean isValidLocale(String aLocale)
    {
        boolean result = false;
        if (aLocale.length() == 2)
        {
            // Assume that locale has only language code.
            result = true;
        }
        if (aLocale.length() == 5)
        {
            // Assume that locale has language and country codes.
            char separator = aLocale.charAt(2);
            if (separator == '-' || separator == '_')
            {
                result = true;
            }
        }
        return result;
    }

    /**
     * Returns a string which can be stored to S60 SCR. This method ensures
     * that the length of the returned string does not exceed the maximum
     * length limit set by SCR (512 characters).
     */
    private static String getScrString(String aStr)
    {
        final int maxLen = 512;
        if (aStr != null && aStr.length() > maxLen)
        {
            return aStr.substring(0, maxLen);
        }
        return aStr;
    }

    /*** ----------------------------- NATIVE ----------------------------- */

    /**
     * Notifies system about added/updated/removed applications.
     * This method should be called only after the changes have been
     * committed.
     *
     * @param aAppUids application uids
     * @param aAppChange change type: APP_ADDED, APP_UPDATED, or APP_REMOVED
     * @return 0 or Symbian error code (negative number)
     */
    private static native int _notifyAppChange(int[] aAppUids, int aAppChange);

    /**
     * Launches the applications view.
     *
     * @return 0 or Symbian error code (negative number)
     */
    private static native int _launchAppView();

    /**
     * Starts native application registration session.
     *
     * @param aTransaction true if also transaction for this session should
     * be opened, false otherwise
     * @return native session handle or Symbian error code (negative number)
     */
    private static native int _startSession(boolean aTransaction);

    /**
     * Commits native application registration session.
     * If commit succeeds the native session is closed.
     *
     * @param aSessionHandle
     * @param aSynchronous if true, makes synchronous commit
     * @return 0 or Symbian error code (negative number)
     */
    private static native int _commitSession(int aSessionHandle);

    /**
     * Rolls back and closes native application registration session.
     *
     * @param aSessionHandle
     * @return 0 or Symbian error code (negative number)
     */
    private static native int _rollbackSession(int aSessionHandle);

    /**
     * Closes native application registration session.
     *
     * @param aSessionHandle the session to be closed
     */
    private static native void _closeSession(int aSessionHandle);

    /**
     * Registers Java application to S60 USIF as a component.
     *
     * @param aSessionHandle
     * @param aUid
     * @param aSuiteName
     * @param aVendor
     * @param aVersion
     * @param aGlobalId
     * @param aComponentFiles
     * @param aComponentSize
     * @param aInstallState
     * @param aIsRemovable
     * @param aIsDrmProtected
     * @param aIsOriginVerified
     * @param aIsUpdate
     * @param aMediaId
     * @param aMidletInfoUrl
     * @param aMidletDescription
     * @param aDownloadUrl
     * @param aUpdateUrl
     * @param aComponentId upon successful execution contains the
     * component id for the registered component
     * @return 0 if registration succeeded or Symbian error code
     */
    private static native int _registerComponent(
        int aSessionHandle, int aUid, String aSuiteName, String aVendor,
        String aVersion, String aGlobalId,
        String[] aComponentFiles, long aComponentSize, int aInstallState,
        boolean aIsRemovable, boolean aIsDrmProtected,
        boolean aIsOriginVerified, boolean aIsUpdate, int aMediaId,
        String aMidletInfoUrl, String aMidletDescription,
        String aDownloadUrl, String aUpdateUrl,
        ComponentId aComponentId);

    /**
     * Unregisters Java application from S60 USIF.
     *
     * @param aSessionHandle
     * @param aComponentId The component id of the application
     * @return 0 if unregistration succeeded or Symbian error code
     */
    private static native int _unregisterComponent(
        int aSessionHandle, int aComponentId);

    /**
     * Registers Java application to S60 USIF as an application
     * inside specified component.
     *
     * @param aSessionHandle
     * @param aCid
     * @param aAppUid
     * @param aAppName
     * @param aAppFilename
     * @param aGroupName
     * @param aIconFilename
     * @param aNumberOfIcons
     * @param aLanguages
     * @param aAppNames
     * @return 0 if registration succeeded or Symbian error code
     */
    private static native int _registerApplication(
        int aSessionHandle, int aCid, int aAppUid, String aAppName,
        String aAppFilename, String aGroupName, String aIconFilename,
        int aNumberOfIcons, int[] aLanguages, String[] aAppNames);

    /**
     * Registers localized name and vendor for specified component.
     *
     * @param aSessionHandle
     * @param aCid component id
     * @param aName localized component name
     * @param aVendor localized component vendor (can be null)
     * @param aLanguage S60 language code
     * @return 0 if unregistration succeeded or Symbian error code
     */
    private static native int _registerLocalizedComponentName(
        int aSessionHandle, int aCid, String aName, String aVendor, int aLanguage);

    /**
     * Sets localized property value for specified component.
     *
     * @param aSessionHandle
     * @param aCid component id
     * @param aName property name
     * @param aValue localized property value
     * @param aLanguage S60 language code
     * @return 0 if unregistration succeeded or Symbian error code
     */
    private static native int _setLocalizedComponentProperty(
        int aSessionHandle, int aCid, String aName, String aValue, int aLanguage);

    /**
     * Returns the component id of the application.
     *
     * @param aSessionHandle
     * @param aGlobalId
     * @param aComponentId contains component id after successful function call
     * @return Symbian error code (negative number) if fails, otherwise 0
     */
    private static native int _getComponentId(
        int aSessionHandle, String aGlobalId, ComponentId aComponentId);

    /**
     * Returns the component id of the application.
     *
     * @param aSessionHandle
     * @param aAppUid
     * @param aComponentId contains component id after successful function call
     * @return Symbian error code (negative number) if fails, otherwise 0
     */
    private static native int _getComponentIdForApp(
        int aSessionHandle, int aAppUid, ComponentId aComponentId);

    /**
     * Returns the uid of the component.
     *
     * @param aSessionHandle
     * @param aCid component id
     * @param aUid contains uid after successful function call
     * @return Symbian error code (negative number) if fails, otherwise 0
     */
    private static native int _getUid(int aCid, ComponentId aUid);

    /**
     * Writes information of the given application to JavaInstaller log.
     *
     * @param aSessionHandle
     * @param aGlobalId the global id for the application
     * @return Symbian error code (negative number) if fails, otherwise 0
     */
    private static native int _logComponent(
        int aSessionHandle, String aGlobalId);

    /**
     * Checks if USIF is enabled.
     *
     * @return 1 if application data should be registered to USIF, 0 otherwise
     */
    private static native int _getUsifMode();

    /**
     * Returns SIF specific error category from given error id.
     */
    private static native int _getErrorCategory(int aErrorId);
}