FileDocCategorySizeDatePackage
AppManagerUI.javaAPI DocphoneME MR2 API (J2ME)58601Wed May 02 18:00:06 BST 2007com.sun.midp.appmanager

AppManagerUI

public class AppManagerUI extends Form implements ItemCommandListener, CommandListener
The Graphical MIDlet selector Screen.

It displays a list (or grid to be exact) of currently installed MIDlets/MIDlet suites (including the Installer MIDlet). Each MIDlet or MIDlet suite is represented by an icon with a name under it. An icon from a jad file for the MIDlet/MIDlet suite representation is used if possible, otherwise a default icon is used. There is a a set of commands per MIDlet/MIDlet suite. Note that the set of commands can change depending on the corresponding MIDlet state. For MIDlets/MIDlet suites that are not running the following commands are available:

  • Launch: Launch the MIDlet or the MIDlet Selector if it is a suite.
  • Remove: Remove the MIDlet/MIDlet suite teh user selected (with confirmation).
  • Update: Update the MIDlet/MIDlet suite the user selected.
  • Info: Show the user general information of the selected MIDlet/MIdlet suite.
  • Settings: Let the user change the manager's settings.
For MIDlets/MIDlet suites that are running the following commands are available:
  • Bring to foreground: Bring the running MIDlet to foreground
  • End: Terminate the running MIDlet
  • Remove: Remove the MIDlet/MIDlet suite teh user selected (with confirmation).
  • Update: Update the MIDlet/MIDlet suite the user selected.
  • Info: Show the user general information of the selected MIDlet/MIdlet suite.
  • Settings: Let the user change the manager's settings.
Exactly one MIDlet from a MIDlet suite could be run at the same time. Each MIDlet/MIDlet suite representation corresponds to an instance of MidletCustomItem which in turn maintains a reference to a MIDletSuiteInfo object (that contains info about this MIDlet/MIDlet suite). When a MIDlet is launched or a MIDlet form a MIDlet suite is launched the proxy instance in the corresponding MidletCustomItem is set to a running MIDletProxy value. It is set back to null when MIDlet exits. Running midlets can be distinguished from non-running MIdlets/MIDlet suites by the color of their name.

Fields Summary
private static final String
DISCOVERY_APP
Constant for the discovery application class name.
private static final String
CA_MANAGER
Constant for the certificate manager class name
private static final String
INSTALLER
Constant for the graphical installer class name.
private static final String
SUITE_SELECTOR
Constant for the graphical installer class name.
private static final Font
ICON_FONT
The font used to paint midlet names in the AppSelector. Inner class cannot have static variables thus it has to be here.
private static final Image
ICON_BG
The image used to draw background for the midlet representation. IMPL NOTE: it is assumed that background image is larger or equal than all other images that are painted over it
private static final int
bgIconW
Cashed background image width.
private static final int
bgIconH
Cashed background image height.
private static final Image
FG_REQUESTED
The icon used to display that user attention is requested and that midlet needs to brought into foreground.
private static final Image
DISABLED_IMAGE
The image used to draw disable midlet representation.
private static final int
ICON_HL_TEXT
The color used to draw midlet name for the hilighted non-running running midlet representation.
private static final int
ICON_TEXT
The color used to draw the shadow of the midlet name for the non hilighted non-running midlet representation.
private static final int
ICON_RUNNING_TEXT
The color used to draw the midlet name for the non hilighted running midlet representation.
private static final int
ICON_RUNNING_HL_TEXT
The color used to draw the midlet name for the hilighted running midlet representation.
private static final int
ITEM_PAD
Tha pad between custom item's icon and text
private static final char
truncationMark
Cashed truncation mark
private Command
exitCmd
Command object for "Exit" command for splash screen.
private Command
launchInstallCmd
Command object for "Launch" install app.
private Command
launchCaManagerCmd
Command object for "Launch" CA manager app.
private Command
launchCmd
Command object for "Launch".
private Command
infoCmd
Command object for "Info".
private Command
removeCmd
Command object for "Remove".
private Command
updateCmd
Command object for "Update".
private Command
appSettingsCmd
Command object for "Application settings".
private Command
cancelCmd
Command object for "Cancel" command for the remove form.
private Command
removeOkCmd
Command object for "Remove" command for the remove form.
Command
backCmd
Command object for "Back" command for back to the AppSelector.
private Command
fgCmd
Command object for "Bring to foreground".
private Command
endCmd
Command object for "End" midlet.
private Command
runYesCmd
Command object for "Yes" command.
private Command
runNoCmd
Command object for "No" command.
ApplicationManager
manager
Display for the Manager MIDlet.
private MIDletSuiteStorage
midletSuiteStorage
MIDlet Suite storage object.
Display
display
Display for the Manager MIDlet.
private long
lastDisplayChange
Keeps track of when the display last changed, in milliseconds.
private RunningMIDletSuiteInfo
removeMsi
MIDlet to be removed after confirmation screen was accepted
private RunningMIDletSuiteInfo
lastSelectedMsi
last Item that was selected
private MIDletProxy
appManagerMidlet
There are several Application Manager midlets from the same "internal" midlet suite that should not be running in the background. appManagerMidlet helps to destroy them (see MidletCustomItem.showNotify).
private DisplayError
displayError
UI used to display error messages.
private boolean
caManagerIncluded
True, if the CA manager is included.
private MIDletSwitcher
midletSwitcher
protected static Timer
textScrollTimer
A Timer which will handle firing repaints of the ScrollPainter
private static int
SCROLL_RATE
Text auto-scrolling parameters
private static int
SCROLL_DELAY
private static int
SCROLL_SPEED
Constructors Summary
AppManagerUI(ApplicationManager manager, Display display, DisplayError displayError, boolean first, MIDletSuiteInfo ms)
Creates and populates the Application Selector Screen.

param
manager - The application manager that invoked it
param
displayError - The UI used to display error messages
param
display - The display instance associated with the manager
param
first - true if this is the first time AppSelector is being shown
param
ms - MidletSuiteInfo that should be selected. For the internal suites midletToRun should be set, for the other suites suiteId is enough to find the corresponding item.


                                                                                                                              
       
                    
                   
        super(null);

        try {
            caManagerIncluded = Class.forName(CA_MANAGER) != null;
        } catch (ClassNotFoundException e) {
            // keep caManagerIncluded false
        }

        this.manager = manager;
        this.display = display;
        this.displayError = displayError;

        midletSwitcher = new MIDletSwitcher(this, manager, display);

        midletSuiteStorage = MIDletSuiteStorage.getMIDletSuiteStorage();

        setTitle(Resource.getString(
                ResourceConstants.AMS_MGR_TITLE));
        updateContent();

        addCommand(exitCmd);
        setCommandListener(this);

        if (first) {
            display.setCurrent(new SplashScreen(display, this));
        } else {
            // if a MIDlet was just installed
            // getLastInstalledMidletItem() will return MidletCustomItem
            // corresponding to this suite, then we have to prompt
            // the user if he want to launch a midlet from the suite.
            MidletCustomItem mci = getLastInstalledMidletItem();
            if (mci != null) {
                askUserIfLaunchMidlet();
            } else {
                display.setCurrent(this);
                if (ms != null) {
                    // Find item to select
                    if (ms.suiteId == MIDletSuite.INTERNAL_SUITE_ID) {
                        for (int i = 0; i < size(); i++) {
                            MidletCustomItem mi = (MidletCustomItem)get(i);
                            if ((mi.msi.suiteId == MIDletSuite.INTERNAL_SUITE_ID)
                                && (mi.msi.midletToRun.equals(ms.midletToRun))) {
                                display.setCurrentItem(mi);
                                break;
                            }
                        }
                    } else {
                        for (int i = 0; i < size(); i++) {
                            MidletCustomItem mi = (MidletCustomItem)get(i);
                            if (mi.msi.suiteId == ms.suiteId) {
                                display.setCurrentItem(mi);
                                break;
                            }
                        }
                    }
                } // ms != null
            }
        }
    
Methods Summary
private voidappend(RunningMIDletSuiteInfo suiteInfo)
Appends a MidletCustomItem to the App Selector Screen

param
suiteInfo the midlet suite info of the recently started midlet


        MidletCustomItem ci = new MidletCustomItem(suiteInfo);

        if (suiteInfo.midletToRun != null &&
            suiteInfo.midletToRun.equals(DISCOVERY_APP)) {
            // setDefaultCommand will add default command first
            ci.setDefaultCommand(launchInstallCmd);
        } else if (caManagerIncluded && suiteInfo.midletToRun != null &&
            suiteInfo.midletToRun.equals(CA_MANAGER)) {
            // setDefaultCommand will add default command first
            ci.setDefaultCommand(launchCaManagerCmd);
        } else {
            ci.addCommand(infoCmd);
            ci.addCommand(removeCmd);
            ci.addCommand(updateCmd);
            ci.addCommand(appSettingsCmd);

            if (suiteInfo.enabled) {
                // setDefaultCommand will add default command first
                ci.setDefaultCommand(launchCmd);
            }
        }

        ci.setItemCommandListener(this);
        append(ci);
        ci.setOwner(this);
    
private voidappendMIDletsToForm(MIDletSuiteImpl midletSuite, Form form)
Appends a names of all the MIDlets in a suite to a Form, one per line.

param
midletSuite information of a suite of MIDlets
param
form form to append to

        int numberOfMidlets;
        MIDletInfo midletInfo;
        StringItem item;

        numberOfMidlets = midletSuite.getNumberOfMIDlets();
        for (int i = 1; i <= numberOfMidlets; i++) {
            midletInfo = new MIDletInfo(
                             midletSuite.getProperty("MIDlet-" + i));

            item = new StringItem(null, midletInfo.name);
            item.setLayout(Item.LAYOUT_NEWLINE_AFTER | Item.LAYOUT_2);
            form.append(item);
        }
    
private voidappendRecordStoresToForm(java.lang.String[] recordStores, Form form)
Appends names of the record stores owned by the midlet suite to a Form, one per line.

param
recordStores list of the record store names
param
form form to append to

        StringItem item;

        for (int i = 0; i < recordStores.length; i++) {
            item = new StringItem(null, recordStores[i]);
            item.setLayout(Item.LAYOUT_NEWLINE_AFTER | Item.LAYOUT_2);
            form.append(item);
        }
    
private voidaskUserIfLaunchMidlet()
Prompts the user to specify whether to launch a midlet from the midlet suite that was just installed.

        // Ask the user if he wants to run a midlet from
        // the newly installed midlet suite
        String title = Resource.getString(
            ResourceConstants.AMS_MGR_RUN_THE_NEW_SUITE_TITLE, null);
        String msg = Resource.getString(
            ResourceConstants.AMS_MGR_RUN_THE_NEW_SUITE, null);

        Alert alert = new Alert(title, msg, null, AlertType.CONFIRMATION);
        alert.addCommand(runNoCmd);
        alert.addCommand(runYesCmd);
        alert.setCommandListener(this);
        alert.setTimeout(Alert.FOREVER);

        display.setCurrent(alert);
    
public voidcommandAction(Command c, Displayable s)
Respond to a command issued on any Screen.

param
c command activated by the user
param
s the Displayable the command was on.


        if (c == exitCmd) {
            if (s == this) {
                manager.shutDown();
            }
            return;
        }

        // for the rest of the commands
        // we will have to request AppSelector to be displayed
        if (c == removeOkCmd) {

            // suite to remove was set in confirmRemove()
            try {
                remove(removeMsi);
            } catch (Throwable t) {
                if (Logging.REPORT_LEVEL <= Logging.WARNING) {
                    Logging.report(Logging.WARNING, LogChannels.LC_AMS,
                                   "Throwable in removeSuitee");
                }
            }
            return;

        } else if (c == cancelCmd) {

            // null out removeMsi in remove confirmation screen
            removeMsi = null;

        } else if (c == runYesCmd) {

            // user decided run the midlet suite after installation
            MidletCustomItem mciToRun = getLastInstalledMidletItem();
            if (mciToRun != null) {
                display.setCurrentItem(mciToRun);
                launchMidlet(mciToRun.msi);
                return;
            }

        } else if (c == runNoCmd) {

            /*
             * user decided not to run the newly installed midlet suite
             *
             * if a MIDlet was just installed
             * displayLastInstalledMidlet() will return true and
             * make "this" visible with
             * the right MIDlet icon hilighted.
             */
            if (displayLastInstalledMidlet()) {
                // Last installed midlet was set as the current item
                return;
            }

        } else if (c != backCmd) {
            return;
        }

        // for back we just need to display AppSelector
        display.setCurrent(this);
    
public voidcommandAction(Command c, Item item)
Respond to a command issued on an Item in AppSelector

param
c command activated by the user
param
item the Item the command was on.

        RunningMIDletSuiteInfo msi = ((MidletCustomItem)item).msi;
        if (msi == null) {
            return;
        }

        if (c == launchInstallCmd) {

            manager.installSuite();

        } else if (c == launchCaManagerCmd) {

            manager.launchCaManager();

        } else if (c == launchCmd) {

            launchMidlet(msi);

        } else if (c == infoCmd) {

            try {
                AppInfo appInfo = new AppInfo(msi.suiteId);
                appInfo.addCommand(backCmd);
                appInfo.setCommandListener(this);
                display.setCurrent(appInfo);
            } catch (Throwable t) {
                displayError.showErrorAlert(msi.displayName, t, null, null);
            }

        } else if (c == removeCmd) {

            confirmRemove(msi);

        } else if (c == updateCmd) {

            manager.updateSuite(msi);
            display.setCurrent(this);

        } else if (c == appSettingsCmd) {

            try {
                AppSettings appSettings = new AppSettings(msi.suiteId, display,
                                                          displayError, this);
                display.setCurrent(appSettings);

            } catch (Throwable t) {
                displayError.showErrorAlert(msi.displayName, t, null, null);
            }

        } else if (c == fgCmd) {

            manager.moveToForeground(msi);
            display.setCurrent(this);

        } else if (c == endCmd) {
            manager.exitMidlet(msi);
            display.setCurrent(this);

        }
    
private voidconfirmRemove(RunningMIDletSuiteInfo suiteInfo)
Confirm the removal of a suite.

param
suiteInfo information for suite to remove

        Form confirmForm;
        StringBuffer temp = new StringBuffer(40);
        Item item;
        String extraConfirmMsg;
        String[] values = new String[1];
        MIDletSuiteImpl midletSuite = null;

        try {
            midletSuite = midletSuiteStorage.getMIDletSuite(suiteInfo.suiteId,
                                                            false);
            confirmForm = new Form(null);

            confirmForm.setTitle(Resource.getString
                                 (ResourceConstants.AMS_CONFIRMATION));

            if (suiteInfo.hasSingleMidlet()) {
                values[0] = suiteInfo.displayName;
            } else {
                values[0] =
                    midletSuite.getProperty(MIDletSuiteImpl.SUITE_NAME_PROP);
            }

            item = new StringItem(null, Resource.getString(
                       ResourceConstants.AMS_MGR_REMOVE_QUE,
                       values));
            item.setLayout(Item.LAYOUT_NEWLINE_AFTER | Item.LAYOUT_2);
            confirmForm.append(item);

            extraConfirmMsg =
                PAPICleanUp.checkMissedTransactions(midletSuite.getID());
            if (extraConfirmMsg != null) {
                temp.setLength(0);
                temp.append(" \n");
                temp.append(extraConfirmMsg);
                item = new StringItem(null, temp.toString());
                item.setLayout(Item.LAYOUT_NEWLINE_AFTER | Item.LAYOUT_2);
                confirmForm.append(item);
            }

            extraConfirmMsg = midletSuite.getProperty("MIDlet-Delete-Confirm");
            if (extraConfirmMsg != null) {
                temp.setLength(0);
                temp.append(" \n");
                temp.append(extraConfirmMsg);
                item = new StringItem(null, temp.toString());
                item.setLayout(Item.LAYOUT_NEWLINE_AFTER | Item.LAYOUT_2);
                confirmForm.append(item);
            }

            if (!suiteInfo.hasSingleMidlet()) {
                temp.setLength(0);
                temp.append(Resource.getString
                            (ResourceConstants.AMS_MGR_SUITE_CONTAINS));
                temp.append(": ");
                item = new StringItem(temp.toString(), "");
                item.setLayout(Item.LAYOUT_NEWLINE_AFTER | Item.LAYOUT_2);
                confirmForm.append(item);
                appendMIDletsToForm(midletSuite, confirmForm);
            }

            String[] recordStores =
                midletSuiteStorage.listRecordStores(suiteInfo.suiteId);
            if (recordStores != null) {
                temp.setLength(0);
                temp.append(Resource.getString
                            (ResourceConstants.AMS_MGR_SUITE_RECORD_STORES));
                temp.append(": ");
                item = new StringItem(temp.toString(), "");
                item.setLayout(Item.LAYOUT_NEWLINE_AFTER | Item.LAYOUT_2);
                confirmForm.append(item);
                appendRecordStoresToForm(recordStores, confirmForm);
            }

            temp.setLength(0);
            temp.append(" \n");
            temp.append(Resource.getString
                        (ResourceConstants.AMS_MGR_REM_REINSTALL, values));
            item = new StringItem("", temp.toString());
            confirmForm.append(item);
        } catch (Throwable t) {
            displayError.showErrorAlert(suiteInfo.displayName, t,
                                   Resource.getString
                                   (ResourceConstants.AMS_CANT_ACCESS),
                                   null);
            return;
        } finally {
            if (midletSuite != null) {
                midletSuite.close();
            }
        }

        confirmForm.addCommand(cancelCmd);
        confirmForm.addCommand(removeOkCmd);
        confirmForm.setCommandListener(this);
        removeMsi = suiteInfo;
        display.setCurrent(confirmForm);
    
private booleandisplayLastInstalledMidlet()
Displayas AppManagerUI with a recently installed midlet hilighted.

return
true if display.setCurrentItem() was called, false - otherwise

        MidletCustomItem ci = getLastInstalledMidletItem();

        if (ci != null) {
            display.setCurrentItem(ci);
            return true;
        }

        return false;
    
private voiddisplaySuccessMessage(java.lang.String successMessage)
Alert the user that an action was successful.

param
successMessage message to display to user

        Image icon;
        Alert successAlert;

        icon = GraphicalInstaller.getImageFromInternalStorage("_dukeok8");

        successAlert = new Alert(null, successMessage, icon, null);

        successAlert.setTimeout(GraphicalInstaller.ALERT_TIMEOUT);

        // We need to prevent "flashing" on fast development platforms.
        while (System.currentTimeMillis() - lastDisplayChange <
               GraphicalInstaller.ALERT_TIMEOUT);

        display.setCurrent(successAlert, this);
        lastDisplayChange = System.currentTimeMillis();
    
private intgetLastInstalledMIDlet()
Open the settings database and retreive an id of the midlet suite that was installed last.

return
ID of the midlet suite that was installed last or MIDletSuite.UNUSED_SUITE_ID.

        ByteArrayInputStream bas;
        DataInputStream dis;
        byte[] data;
        RecordStore settings = null;
        int ret = MIDletSuite.UNUSED_SUITE_ID;

        try {
            settings = RecordStore.
                       openRecordStore(GraphicalInstaller.SETTINGS_STORE,
                                       false);

            /** we should be guaranteed that this is always the case! */
            if (settings.getNumRecords() > 0) {

                data = settings.getRecord(
                           GraphicalInstaller.SELECTED_MIDLET_RECORD_ID);

                if (data != null) {
                    bas = new ByteArrayInputStream(data);
                    dis = new DataInputStream(bas);
                    ret = dis.readInt();
                }
            }

        } catch (RecordStoreException e) {
            // ignore
        } catch (IOException e) {
            // ignore
        } finally {
            if (settings != null) {
                try {
                    settings.closeRecordStore();
                } catch (RecordStoreException e) {
                    // ignore
                }
            }
        }

        return ret;
    
private com.sun.midp.appmanager.AppManagerUI$MidletCustomItemgetLastInstalledMidletItem()
Finds a MidletCustomItem corresponding to the last installed midlet suite.

return
the midlet custom item if it was found, null otherwise

        int installedMidlet = getLastInstalledMIDlet();

        if (installedMidlet != MIDletSuite.UNUSED_SUITE_ID &&
                installedMidlet != MIDletSuite.INTERNAL_SUITE_ID) {
            for (int i = 0; i < size(); i++) {
                MidletCustomItem ci = (MidletCustomItem)get(i);
                if (ci.msi.suiteId == installedMidlet) {
                    return ci;
                }
            }
        }

        return null;
    
public RunningMIDletSuiteInfogetSelectedMIDletSuiteInfo()
Called to determine MidletSuiteInfo of the last selected Item.

return
last selected MidletSuiteInfo

        return lastSelectedMsi;
    
private voidlaunchMidlet(RunningMIDletSuiteInfo msi)
Launches the midlet suite described by the given MIDletSuiteInfo.

param
msi a structure with information about the midlet suite that must be launched

        if (msi.hasSingleMidlet()) {
            manager.launchSuite(msi, msi.midletToRun);
            display.setCurrent(this);
        } else {
            try {
                new MIDletSelector(msi, display, this, manager);
            } catch (Throwable t) {
                displayError.showErrorAlert(msi.displayName, t,
                                            null, null);
            }
        }
    
voidnotifyMidletExited(MIDletProxy midlet)
Called when a running midlet exited.

param
midlet proxy of a newly added MIDlet

        String midletClassName = midlet.getClassName();

        if (midlet.getSuiteId() == MIDletSuite.INTERNAL_SUITE_ID &&
                !midletClassName.equals(DISCOVERY_APP) &&
                !midletClassName.equals(INSTALLER) &&
                !midletClassName.equals(CA_MANAGER)) {
            appManagerMidlet = null;
        } else {
            MidletCustomItem ci;

            for (int i = 0; i < size(); i++) {
                ci = (MidletCustomItem)get(i);

                if (ci.msi.equals(midlet)) {
                    ci.removeCommand(fgCmd);
                    ci.removeCommand(endCmd);

                    if (ci.msi.midletToRun != null &&
                            ci.msi.midletToRun.equals(DISCOVERY_APP)) {
                        ci.setDefaultCommand(launchInstallCmd);
                    } else if (caManagerIncluded &&
                            ci.msi.midletToRun != null &&
                            ci.msi.midletToRun.equals(CA_MANAGER)) {
                        ci.setDefaultCommand(launchCaManagerCmd);
                    } else {
                        if (ci.msi.enabled) {
                            ci.setDefaultCommand(launchCmd);
                        }
                    }

                    midletSwitcher.remove(ci.msi);
                    ci.msi.proxy = null;

                    if (removeMsi != null && removeMsi.equals(midlet)) {
                        remove(removeMsi);
                    }

                    /*
                     * When the Installer midlet quites
                     * (it is removed from the running apps list)
                     * this is a good time to see if any new MIDlet suites
                     * where added
                     * Also the CA manager could have disabled a MIDlet.
                     */
                    if (INSTALLER.equals(midletClassName)) {
                        updateContent();
                        /*
                        * After a MIDlet suite is successfully installed on the
                        * device, ask the user whether or not to launch
                        * a MIDlet from the suite.
                        */
                        MidletCustomItem mci = getLastInstalledMidletItem();
                        if (mci != null) {
                            askUserIfLaunchMidlet();
                            return;
                        }
                    } else {
                        if (CA_MANAGER.equals(midletClassName)) {
                            updateContent();
                        }
                        ci.update();
                    }

                    return;
                }
            }
        }

        // Midlet quited; display the application Selector
        display.setCurrent(this);
    
voidnotifyMidletStartError(int suiteId, java.lang.String className, int errorCode, java.lang.String errorDetails)
Called when a midlet could not be launched.

param
suiteId suite ID of the MIDlet
param
className class name of the MIDlet
param
errorCode error code
param
errorDetails error code details

        Alert a;
        String errorMsg;

        switch (errorCode) {
        case Constants.MIDLET_SUITE_NOT_FOUND:
            errorMsg = Resource.getString(
                ResourceConstants.AMS_MIDLETSUITELDR_MIDLETSUITE_NOTFOUND);
            break;

        case Constants.MIDLET_CLASS_NOT_FOUND:
            errorMsg = Resource.getString(
              ResourceConstants.AMS_MIDLETSUITELDR_CANT_LAUNCH_MISSING_CLASS);
            break;

        case Constants.MIDLET_INSTANTIATION_EXCEPTION:
            errorMsg = Resource.getString(
              ResourceConstants.AMS_MIDLETSUITELDR_CANT_LAUNCH_ILL_OPERATION);
            break;

        case Constants.MIDLET_ILLEGAL_ACCESS_EXCEPTION:
            errorMsg = Resource.getString(
              ResourceConstants.AMS_MIDLETSUITELDR_CANT_LAUNCH_ILL_OPERATION);
            break;

        case Constants.MIDLET_OUT_OF_MEM_ERROR:
            errorMsg = Resource.getString(
                ResourceConstants.AMS_MIDLETSUITELDR_QUIT_OUT_OF_MEMORY);
            break;

        case Constants.MIDLET_RESOURCE_LIMIT:
        case Constants.MIDLET_ISOLATE_RESOURCE_LIMIT:
            errorMsg = Resource.getString(
                ResourceConstants.AMS_MIDLETSUITELDR_RESOURCE_LIMIT_ERROR);
            break;

        case Constants.MIDLET_ISOLATE_CONSTRUCTOR_FAILED:
            errorMsg = Resource.getString(
                ResourceConstants.AMS_MIDLETSUITELDR_CANT_EXE_NEXT_MIDLET);
            break;

        case Constants.MIDLET_SUITE_DISABLED:
            errorMsg = Resource.getString(
                ResourceConstants.AMS_MIDLETSUITELDR_MIDLETSUITE_DISABLED);
            break;

        case Constants.MIDLET_INSTALLER_RUNNING:
            String[] values = new String[1];
            values[0] = className;
            errorMsg = Resource.getString(
                           ResourceConstants.AMS_MGR_UPDATE_IS_RUNNING,
                           values);
            break;

        default:
            errorMsg = Resource.getString(
                ResourceConstants.AMS_MIDLETSUITELDR_UNEXPECTEDLY_QUIT);
        }

        if (errorDetails != null) {
             errorMsg += "\n\n" + errorDetails;
        }

        displayError.showErrorAlert(null, null,
                                    Resource.getString
                                    (ResourceConstants.EXCEPTION),
                                    errorMsg);
    
voidnotifyMidletStarted(MIDletProxy midlet)
Called when a new midlet was launched.

param
midlet proxy of a newly added MIDlet

        String midletClassName = midlet.getClassName();

        if (midletClassName.equals(manager.getClass().getName())) {
            return;
        }

        if (midlet.getSuiteId() == MIDletSuite.INTERNAL_SUITE_ID &&
                !midletClassName.equals(DISCOVERY_APP) &&
                !midletClassName.equals(INSTALLER) &&
                !midletClassName.equals(CA_MANAGER)) {
            appManagerMidlet = midlet;
        } else {
            MidletCustomItem ci;
            for (int i = 0; i < size(); i++) {
                ci = (MidletCustomItem)get(i);

                if (ci.msi.equals(midlet)) {
                    ci.removeCommand(launchCmd);
                    ci.removeCommand(launchInstallCmd);

                    if (caManagerIncluded) {
                        ci.removeCommand(launchCaManagerCmd);
                    }

                    ci.setDefaultCommand(fgCmd);
                    ci.addCommand(endCmd);
                    if (ci.msi.proxy == null) {
                        // add item to midlet switcher
                        midletSwitcher.append(ci.msi);
                    }
                    ci.msi.proxy = midlet;
                    return;
                }
            }
        }
    
voidnotifyMidletStateChanged(MIDletProxy midlet)
Called when state of a running midlet was changed.

param
midlet proxy of a newly added MIDlet

        MidletCustomItem mci = null;

        for (int i = 0; i < size(); i++) {
            mci = (MidletCustomItem)get(i);
            if (mci.msi.proxy == midlet) {
                mci.update();
            }
        }
    
private voidremove(RunningMIDletSuiteInfo suiteInfo)
Removes a midlet from the App Selector Screen

param
suiteInfo the midlet suite info of a recently removed MIDlet

        RunningMIDletSuiteInfo msi;

        if (suiteInfo == null) {
            // Invalid parameter, should not happen.
            return;
        }

        // the last item in AppSelector is time
        for (int i = 0; i < size(); i++) {
            msi = (RunningMIDletSuiteInfo)((MidletCustomItem)get(i)).msi;
            if (msi == suiteInfo) {
                PAPICleanUp.removeMissedTransaction(suiteInfo.suiteId);

                if (msi.proxy != null) {
                    msi.proxy.destroyMidlet();
                }

                try {
                    midletSuiteStorage.remove(suiteInfo.suiteId);
                } catch (Throwable t) {
                    if (t instanceof MIDletSuiteLockedException) {
                        String[] val = new String[1];
                        val[0] = suiteInfo.displayName;
                        displayError.showErrorAlert(suiteInfo.displayName,
                            null,
                            Resource.getString(ResourceConstants.ERROR),
                            Resource.getString(
                                ResourceConstants.AMS_MGR_REMOVE_LOCKED_SUITE,
                                    val),
                            this);
                    } else {
                        displayError.showErrorAlert(suiteInfo.displayName,
                            t,
                            Resource.getString(ResourceConstants.ERROR),
                            null, this);
                    }

                    return;
                }

                try {
                    PushRegistryInternal.unregisterConnections(
                        suiteInfo.suiteId);
                } catch (Throwable t) {
                    // Intentionally ignored: suite has been removed already,
                    // we can't do anything meaningful at this point.
                }

                delete(i);
                removeMsi = null;
                break;
            }
        }

        display.setCurrent(this);
    
public voidshowMidletSwitcher(boolean onlyFromLaunchedList)
Called when midlet selector needed.

param
onlyFromLaunchedList true if midlet should be selected from the list of already launched midlets, if false then possibility to launch midlet is needed.

        if (onlyFromLaunchedList && midletSwitcher.hasItems()) {
            display.setCurrent(midletSwitcher);
        } else {
            display.setCurrent(this);
        }
    
private voidupdateContent()
Read in and create a MIDletInfo for newly added MIDlet suite and check enabled state of currently added MIDlet suites.

        int[] suiteIds;
        RunningMIDletSuiteInfo msi = null;
        boolean newlyAdded;

        suiteIds = midletSuiteStorage.getListOfSuites();

        // Add the Installer as the first installed midlet
        if (size() > 0) {
            msi = ((MidletCustomItem)get(0)).msi;
        }

        if (msi == null || msi.midletToRun == null ||
            !msi.midletToRun.equals(DISCOVERY_APP)) {

            msi = new RunningMIDletSuiteInfo(MIDletSuite.INTERNAL_SUITE_ID,
                DISCOVERY_APP,
                Resource.getString(ResourceConstants.INSTALL_APPLICATION),
                true) {
                    public boolean equals(MIDletProxy midlet) {
                        if (super.equals(midlet)) {
                            return true;
                        }

                        // there is one exception when 2 midlets belong to the
                        // same icon: Discovery app & Graphical installer.
                        // Graphical Installer can be launched by Discover app
                        // or when MIdlet update is needed.
                        // In such cases we simply need to set the proxy on
                        // corresponding icon (MidletCustomItem).
                        // Note that when Discovery app exits and
                        // Installer is launched
                        // notifyMidletExited() will not find corresponding
                        // icon in the list of MidletCustomItems.
                        // (that midlet exit will be ignored).
                        return (INSTALLER.equals(midlet.getClassName()));
                    }
                };

            append(msi);
        }

        if (caManagerIncluded) {
            // Add the CA manager as the second installed midlet
            if (size() > 1) {
                msi = ((MidletCustomItem)get(1)).msi;
            }

            if (msi == null || msi.midletToRun == null ||
                !msi.midletToRun.equals(CA_MANAGER)) {
                msi = new RunningMIDletSuiteInfo(MIDletSuite.INTERNAL_SUITE_ID,
                  CA_MANAGER,
                  Resource.getString(ResourceConstants.CA_MANAGER_APP), true);
                append(msi);
            }
        }

        // Add the rest of the installed midlets
        for (int lowest, i = 0; i < suiteIds.length; i++) {

            lowest = i;

            for (int k = i + 1; k < suiteIds.length; k++) {
                if (suiteIds[k] < suiteIds[lowest]) {
                    lowest = k;
                }
            }

            try {
                MIDletSuiteInfo temp =
                    midletSuiteStorage.getMIDletSuiteInfo(suiteIds[lowest]);

                RunningMIDletSuiteInfo suiteInfo =
                    new RunningMIDletSuiteInfo(temp, midletSuiteStorage);

                newlyAdded = true;
                for (int k = 0; k < size(); k++) {
                    MidletCustomItem mci = (MidletCustomItem)get(k);

                    if (suiteIds[lowest] == mci.msi.suiteId) {
                        newlyAdded = false;
                        boolean isEnabled = suiteInfo.enabled;

                        if (mci.msi.enabled != isEnabled) {
                            mci.msi.enabled = isEnabled;

                            // MIDlet suite being enabled
                            if (isEnabled) {
                                mci.setDefaultCommand(launchCmd);
                            } else { // MIDlet suite is being disabled

                                if (mci.msi.proxy == null) { // Not running
                                    mci.removeCommand(launchCmd);

                                }

                                // running MIDlets will continue to run
                                // even when disabled
                            }
                        }

                        // Update all information about the suite;
                        // if the suite's icon was changed, reload it.
                        String oldIconName = mci.msi.iconName;
                        int oldNumberOfMidlets = mci.msi.numberOfMidlets;
                        MIDletProxy oldProxy = mci.msi.proxy;

                        mci.msi = suiteInfo;
                        mci.msi.proxy = oldProxy;

                        if ((suiteInfo.iconName != null &&
                                !suiteInfo.iconName.equals(oldIconName)) ||
                            (suiteInfo.iconName == null &&
                                suiteInfo.numberOfMidlets != oldNumberOfMidlets)
                        ) {
                            mci.msi.icon = null;
                            mci.msi.loadIcon(midletSuiteStorage);
                            mci.icon = mci.msi.icon;
                        }

                        break;
                    }
                }

                if (newlyAdded) {
                    append(suiteInfo);
                }

            } catch (Exception e) {
                // move on to the next suite
            }

            suiteIds[lowest] = suiteIds[i];
        }