FileDocCategorySizeDatePackage
MIDletProxyList.javaAPI DocphoneME MR2 API (J2ME)43021Wed May 02 18:00:06 BST 2007com.sun.midp.main

MIDletProxyList

public class MIDletProxyList extends Object implements com.sun.midp.suspend.SuspendSystemListener, MIDletControllerEventConsumer
Manages a list of MIDlet proxies, each proxy representing a running MIDlet and tracks which MIDlet has the foreground display, the list only available to objects running in the AMS isolate.

The list is updated upon receiving events. See the process method for event processing.

Objects can listen (see MIDletProxyListListener) to the list for additions, updates to proxies, and removals as will as set foreground events and select foreground events.

This class also provides a shutdown method and processes a shutdown event to enable the method be used by native code.

Fields Summary
static final int
PROXY_ADDED
MIDletProxy added constant.
static final int
PROXY_REMOVED
MIDletProxy removed constant.
private static MIDletProxyList
midletProxyList
The one and only MIDlet proxy list.
private static boolean
shutdownFlag
True when the system is shutting down.
private Vector
listeners
What objects should get list changes.
private Vector
midletProxies
Vector to hold MIDlet proxies.
private MIDletProxy
foregroundMidlet
The foreground MIDlet.
private DisplayController
displayController
The one and only displayController.
private boolean
allPaused
True if all midlets are paused, false - otherwise
private MIDletProxy
amsProxy
MIDlet proxy whose peer application runs in the AMS isolate. Should be accessed through findAmsProxy(), may be invalid otherwise.
private static com.sun.midp.security.SecurityToken
classSecurityToken
Security token for provileged access to restricted API's.
Constructors Summary
MIDletProxyList(com.sun.midp.events.EventQueue eventQueue)
Package private constructor. Shall be called from MIDletSuiteLoader's main()

param
eventQueue reference to the event queue

        displayController = new DisplayController(this);

        /* register event listener for events processed by MIDletProxyList */
        new MIDletControllerEventListener(eventQueue, this);
    
Methods Summary
public voidaddListener(MIDletProxyListListener listener)
Add a listener for MIDlet proxy list changes.

param
listener MIDlet proxy list listener

        listeners.addElement(listener);
    
public MIDletProxyfindAmsProxy()
Retireves proxy whose peer application runs in the AMS isolate. The proxy is identified by isolate ID since only one application can run in the AMS solate.

return
the proxy or null if one cannot be found

        if (null == amsProxy) {
            for (int i = midletProxies.size() - 1; i >= 0; i--) {
                MIDletProxy current = (MIDletProxy)midletProxies.elementAt(i);

                if (current.getIsolateId() == MIDletSuiteUtils.getAmsIsolateId()) {
                    amsProxy = current;
                    break;
                }
            }
        }

        return amsProxy;
    
private MIDletProxyfindMIDletProxy(int isolateId, int displayId)
Find the MIDletProxy that has matching Isolate ID and Display ID.

param
isolateId Isolate ID
param
displayId Display ID
return
a reference to the matching MIDletProxy or null if no match

        synchronized (midletProxies) {
            for (int i = midletProxies.size() - 1; i >= 0; i--) {
                MIDletProxy current = (MIDletProxy)midletProxies.elementAt(i);

                if (current.getIsolateId() == isolateId &&
                        current.getDisplayId() == displayId) {
                    return current;
                }
            }
        }

        return null;
    
public MIDletProxyfindMIDletProxy(int suiteId, java.lang.String classname)
Find the MIDletProxy that has matching suiteId and classname.

param
suiteId the suiteId of the target application
param
classname classname of the MIDlet
return
a reference to the matching MIDletProxy or null if no match

        synchronized (midletProxies) {
            for (int i = midletProxies.size() - 1; i >= 0; i--) {
                MIDletProxy current = (MIDletProxy)midletProxies.elementAt(i);

                if (current.getSuiteId() == suiteId &&
                        current.getClassName().equals(classname)) {
                    return current;
                }
            }
        }

        return null;
    
public MIDletProxyfindMIDletProxy(int externalAppId)
Find the MIDletProxy that has matching external app ID.

param
externalAppId ID assigned by the external application manager
return
a reference to the matching MIDletProxy or null if no match

        synchronized (midletProxies) {
            for (int i = midletProxies.size() - 1; i >= 0; i--) {
                MIDletProxy current = (MIDletProxy)midletProxies.elementAt(i);

                if (current.getExternalAppId() == externalAppId) {
                    return current;
                }
            }
        }

        return null;
    
public MIDletProxygetForegroundMIDlet()
Get the foreground MIDlet.

return
proxy to the MIDlet that is in the foreground

        return foregroundMidlet;
    
public static com.sun.midp.main.MIDletProxyListgetMIDletProxyList()
Get a reference to the MIDlet proxy list in a secure way. The calling suite must have the com.sun.midp.ams permission "allowed". Should only be called in the AMS Isolate.

return
MIDP MIDlet proxy list reference

        return getMIDletProxyList(null);
    
public static com.sun.midp.main.MIDletProxyListgetMIDletProxyList(com.sun.midp.security.SecurityToken token)
Get a reference to the MIDlet proxy list in a secure way. The calling suite must have the com.sun.midp.ams permission "allowed". Should only be called in the AMS Isolate.

param
token SecurityToken with the AMS permission allowed or null to use the midletSuite permission
return
MIDP MIDlet proxy list reference

        if (token != null) {
            token.checkIfPermissionAllowed(Permissions.AMS);
        } else {
            MIDletSuite midletSuite = MIDletStateHandler.
                getMidletStateHandler().getMIDletSuite();

            midletSuite.checkIfPermissionAllowed(Permissions.AMS);
        }

        return midletProxyList;
    
public java.util.EnumerationgetMIDlets()
Get an enumeration of MIDlet proxies.

return
enumeration of midletProxys

        Vector v = new Vector();
        synchronized (midletProxies) {
            int size = midletProxies.size();
            for (int i = 0; i < size; i++) {
                v.addElement(midletProxies.elementAt(i));
            }
       }
        return v.elements();
    
public voidhandleActivateAllEvent()
Process an ACTIVATE_ALL_EVENT. MIDletControllerEventConsumer I/F method.

        SuspendSystem.getInstance(classSecurityToken).resume();

        synchronized (midletProxies) {
            MIDletProxy current;

            for (int i = midletProxies.size() - 1; i >= 0; i--) {
                current = (MIDletProxy)midletProxies.elementAt(i);

                current.activateMidlet();
            }
        }
    
public voidhandleDestroyAllEvent()
Process a SHUTDOWN_ALL_EVENT. MIDletControllerEventConsumer I/F method. It simply calls "shutdown()". In future it shall be merged with "shutdown()" and substitute it.

        shutdown();
    
public voidhandleDisplayBackgroundRequestEvent(int midletIsolateId, int midletDisplayId)
Process a background request event. MIDletControllerEventConsumer I/F method. TBD: param midletProxy proxy with information about MIDlet

param
midletIsolateId isolate ID of the sending Display
param
midletDisplayId ID of the sending Display


        MIDletProxy midletProxy = findMIDletProxy(midletIsolateId,
                                                  midletDisplayId);
        if (midletProxy == null) {
            /*
             * There is nothing we can do for the event
             * if a proxy was not found.
             *
             * Sometimes an display can send an event before
             * MIDlet. One of the cases is when
             * a MIDlet calls Display.setCurrent with a new displayable in
             * its constructor which happens before the MIDlet created
             * event.
             *
             * Sometimes an display can send an event after a
             * MIDlet's destroyApp method is called and the proxy removed
             * from this list. One of the cases is when
             * a thread the MIDlet started and is still running after
             * the destroyApp method has returned, calls display.setCurrent
             * with null while cleaning up.
             */
            return;
        }

        midletProxy.setWantsForeground(false, false);
        setForegroundMIDlet(displayController.backgroundRequest(midletProxy));
        notifyListenersOfProxyUpdate(midletProxy,
                                     MIDletProxyListListener.WANTS_FOREGROUND);
    
public voidhandleDisplayCreateNotifyEvent(int midletIsolateId, int midletDisplayId, java.lang.String midletClassName)
Process a Display created notification. MIDletControllerEventConsumer I/F method.

param
midletIsolateId isolate ID of the sending Display
param
midletDisplayId ID of the sending Display
param
midletClassName Class name of the MIDlet that owns the display


        MIDletProxy midletProxy = null;

        synchronized (midletProxies) {
            for (int i = midletProxies.size() - 1; i >= 0; i--) {
                MIDletProxy current = (MIDletProxy)midletProxies.elementAt(i);
                if (current.getIsolateId() == midletIsolateId &&
                        current.getClassName().equals(midletClassName)) {
                    midletProxy = current;
                    break;
                }
            }
        }

        if (midletProxy == null) {
            /**
             * The isolate is create a display without a MIDlet to display
             * a fatal error loading the suite in SVM mode.
             * So just do nothing, a preempt event will follow.
             */
            return;
        }

        /* Just set the display ID of the proxy. */
        midletProxy.setDisplayId(midletDisplayId);
    
public voidhandleDisplayForegroundRequestEvent(int midletIsolateId, int midletDisplayId, boolean isAlert)
Process a foreground request event. MIDletControllerEventConsumer I/F method. TBD: param midletProxy proxy with information about MIDlet

param
midletIsolateId isolate ID of the sending Display
param
midletDisplayId ID of the sending Display
param
isAlert true if the current displayable is an Alert


        MIDletProxy midletProxy = findMIDletProxy(midletIsolateId,
                                                  midletDisplayId);
        if (midletProxy == null) {
            /*
             * There is nothing we can do for the event
             * if a proxy was not found. See midletActiveNotification().
             */
            return;
        }

        if (midletProxy == foregroundMidlet) {
            // force alert waiting to false, since it can't be waiting
            midletProxy.setWantsForeground(true, false);
        } else {
            midletProxy.setWantsForeground(true, isAlert);
            setForegroundMIDlet(
                displayController.foregroundRequest(midletProxy));
        }

        /**
         * The internal calls to  notifyListenersOfProxyChange() within
         * setForegroundMIDlet() should not override the behaviour of
         * listener which is an IndicatorManager in this case. So,
         * notifyListenersOfProxyChange() should be called after
         * setForegroundMIDlet().
         */
        notifyListenersOfProxyUpdate(midletProxy,
                                     MIDletProxyListListener.WANTS_FOREGROUND);
    
public voidhandleDisplayPreemptStartEvent(int midletIsolateId, int midletDisplayId)
Process a "display preempt start" event.

Set the foreground to a given display if a certain display has the foreground. Used to start preempting. MIDletControllerEventConsumer I/F method.

param
midletIsolateId isolate ID of the sending Display
param
midletDisplayId ID of the sending Display


        MIDletProxy preempting = new MIDletProxy(this, 0,
            midletIsolateId, MIDletSuite.UNUSED_SUITE_ID,
                null, null, MIDletProxy.MIDLET_ACTIVE);
        preempting.setDisplayId(midletDisplayId);

        MIDletProxy nextForeground =
            displayController.startPreempting(preempting);

        if (nextForeground != null) {
            setForegroundMIDlet(nextForeground);
        }
    
public voidhandleDisplayPreemptStopEvent(int midletIsolateId, int midletDisplayId)
Process a "display preempt stop" event.

Set the foreground to a given display if a certain display has the foreground. Used to end preempting. MIDletControllerEventConsumer I/F method.

param
midletIsolateId isolate ID of the sending Display
param
midletDisplayId ID of the sending Display


        MIDletProxy nextForeground =
            displayController.endPreempting(
                midletIsolateId,
                midletDisplayId);

        if (nextForeground != null) {
            setForegroundMIDlet(nextForeground);
        }
    
public voidhandleFatalErrorNotifyEvent(int midletIsolateId, int midletDisplayId)
Processes FATAL_ERROR_NOTIFICATION. MIDletControllerEventConsumer I/F method.

param
midletIsolateId isolate ID of the sending isolate
param
midletDisplayId ID of the sending Display


        removeIsolateProxies(midletIsolateId);
        AmsUtil.terminateIsolate(midletIsolateId);
    
public voidhandleMIDletActiveNotifyEvent(int midletSuiteId, java.lang.String midletClassName)
Process a MIDlet active notification MIDletControllerEventConsumer I/F method. TBD: param midletProxy proxy with information about MIDlet

param
midletSuiteId ID of the MIDlet suite
param
midletClassName Class name of the MIDlet


        MIDletProxy midletProxy = findMIDletProxy(midletSuiteId,
                                                  midletClassName);
        if (midletProxy == null) {
            /*
             * There is nothing we can do for the other events
             * if a proxy was not found.
             *
             * Sometimes an display can send an event after a
             * MIDlet's destroyApp method is called and the proxy removed
             * from this list. One of the cases is when
             * a thread the MIDlet started and is still running after
             * the destroyApp method has returned, calls display.setCurrent
             * with null while cleaning up.
             */
            return;
        }

        midletProxy.setMidletState(MIDletProxy.MIDLET_ACTIVE);
        notifyListenersOfProxyUpdate(midletProxy,
                                     MIDletProxyListListener.MIDLET_STATE);
        setForegroundMIDlet(displayController.midletActive(midletProxy));
        notifyIfMidletActive();
    
public voidhandleMIDletCreateNotifyEvent(int midletSuiteId, java.lang.String midletClassName, int midletIsolateId, int midletExternalAppId, java.lang.String midletDisplayName)
Process a MIDlet created notification. MIDletControllerEventConsumer I/F method.

param
midletSuiteId ID of the MIDlet suite
param
midletClassName Class name of the MIDlet
param
midletIsolateId isolate ID of the sending MIDlet
param
midletExternalAppId ID of given by an external application manager
param
midletDisplayName name to show the user


        MIDletProxy midletProxy = findMIDletProxy(midletSuiteId,
                                                  midletClassName);
        if (midletProxy != null) {
            /**
             * The isolate this MIDlet was last run in, died because the
             * event proccessing encountered a fatal error, which ends
             * the isolate without notifing the proxy list.
             * So just remove the MIDlet's proxy now.
             * So we can add the new midlet proxy.
             */
            removeMidletProxy(midletProxy);
        }

        /* MIDlet's are constructed in PAUSED state. */
        midletProxy = new MIDletProxy(this,
            midletExternalAppId,
            midletIsolateId,
            midletSuiteId,
            midletClassName,
            midletDisplayName,
            MIDletProxy.MIDLET_PAUSED);

        int suspendResumeState =
                SuspendSystem.getInstance(classSecurityToken).getState();

        if ((suspendResumeState == SuspendSystem.SUSPENDED) ||
                (suspendResumeState == SuspendSystem.SUSPENDING)) {
            MIDletProxyUtils.terminateMIDletIsolate(midletProxy, this);
            midletProxy = null;
            return;
        }

        midletProxies.addElement(midletProxy);

        notifyListenersOfProxyListChange(midletProxy, PROXY_ADDED);

        displayController.midletCreated(midletProxy);
    
public voidhandleMIDletDestroyNotifyEvent(int midletSuiteId, java.lang.String midletClassName)
Process a MIDlet destroyed event. MIDletControllerEventConsumer I/F method. TBD: param midletProxy proxy with information about MIDlet

param
midletSuiteId ID of the MIDlet suite
param
midletClassName Class name of the MIDlet


        MIDletProxy midletProxy = findMIDletProxy(midletSuiteId,
                                                  midletClassName);
        if (midletProxy == null) {
            /*
             * There is nothing we can do for the event
             * if a proxy was not found. See midletActiveNotification().
             */
            return;
        }

        midletProxy.destroyedNotification();
        removeMidletProxy(midletProxy);
    
public voidhandleMIDletDestroyRequestEvent(int midletIsolateId, int midletDisplayId)
Process a MIDlet destroy request event. MIDletControllerEventConsumer I/F method. TBD: param midletProxy proxy with information about MIDlet

param
midletIsolateId isolate ID of the sending Display
param
midletDisplayId ID of the sending Display


        MIDletProxy midletProxy = findMIDletProxy(midletIsolateId,
                                                  midletDisplayId);
        if (midletProxy == null) {
            return;
        }

        midletProxy.destroyMidlet();
    
public voidhandleMIDletForegroundSelectEvent(int onlyFromLaunched)
Process a select foreground event by putting the foreground selector MIDlet in the foreground. MIDletControllerEventConsumer I/F method.

        MIDletProxy nextForeground =
            displayController.selectForeground(onlyFromLaunched == 1);

        if (nextForeground == foregroundMidlet) {
            return;
        }

        setForegroundMIDlet(nextForeground);
    
public voidhandleMIDletForegroundTransferEvent(int originMIDletSuiteId, java.lang.String originMIDletClassName, int targetMIDletSuiteId, java.lang.String targetMIDletClassName)
Process an event to transition the foreground from a current display to a target MIDlet by ID and classname. If the source display does not currently own the foreground the request is ignored. If the target MIDlet is found in the active list then it it set as the foreground. If not found, then it should be added as the next display to get the foreground (when it asks). MIDletControllerEventConsumer I/F method.

param
originMIDletSuiteId ID of MIDlet from which to take forefround ownership away,
param
originMIDletClassName Name of MIDlet from which to take forefround ownership away
param
targetMIDletSuiteId ID of MIDlet to give forefround ownership to,
param
targetMIDletClassName Name of MIDlet to give forefround ownership to


        MIDletProxy origin = findMIDletProxy(originMIDletSuiteId,
                                             originMIDletClassName);
        if (origin == null) {
            return;
        }
        // See if the foreground can be handed to the target MIDlet
        MIDletProxy target = findMIDletProxy(targetMIDletSuiteId,
                                             targetMIDletClassName);
        if (target != null) {
            target.setWantsForeground(true, false);
            // Let the DisplayController make the UE policy choice
            setForegroundMIDlet(displayController.transferRequest(origin,
                                                                  target));

            /**
            * The internal calls to  notifyListenersOfProxyChange() within
            * setForegroundMIDlet() should not override the behaviour of a
            * listener which is an IndicatorManager in this case. So,
            * notifyListenersOfProxyChange() should be called after
            * setForegroundMIDlet().
            */
            notifyListenersOfProxyUpdate(target,
                MIDletProxyListListener.WANTS_FOREGROUND);
        }
    
public voidhandleMIDletPauseNotifyEvent(int midletSuiteId, java.lang.String midletClassName)
Process a MIDlet paused notification. MIDletControllerEventConsumer I/F method. TBD: param midletProxy proxy with information about MIDlet

param
midletSuiteId ID of the MIDlet suite
param
midletClassName Class name of the MIDlet


        MIDletProxy midletProxy = findMIDletProxy(midletSuiteId,
                                                  midletClassName);
        if (midletProxy == null) {
            /*
             * There is nothing we can do for the other events
             * if a proxy was not found. See midletActiveNotification().
             */
            return;
        }

        midletProxy.setMidletState(MIDletProxy.MIDLET_PAUSED);
        notifyListenersOfProxyUpdate(midletProxy,
                                     MIDletProxyListListener.MIDLET_STATE);

        setForegroundMIDlet(displayController.midletPaused(midletProxy));
    
public voidhandleMIDletResumeRequestEvent(int midletSuiteId, java.lang.String midletClassName)
Processes a MIDLET_RESUME_REQUEST event. MIDletControllerEventConsumer I/F method.

param
midletSuiteId ID of the MIDlet suite
param
midletClassName Class name of the MIDlet

        MIDletProxy midletProxy = findMIDletProxy(midletSuiteId,
                                                  midletClassName);
        if (midletProxy == null) {
            /*
             * There is nothing we can do for the event
             * if a proxy was not found. See midletActiveNotification().
             */
            return;
        }

        // Just grant the request.
        midletProxy.activateMidlet();
    
public voidhandleMIDletRsPauseNotifyEvent(int midletSuiteId, java.lang.String midletClassName)
Handles notification event of MIDlet resources pause. MIDletControllerEventConsumer I/F method.

param
midletSuiteId ID of the MIDlet suite
param
midletClassName Class name of the MIDlet


        MIDletProxy midletProxy = findMIDletProxy(midletSuiteId,
                                                  midletClassName);
        if (midletProxy == null) {
            /*
             * There is nothing we can do for the other events
             * if a proxy was not found.
             */
            return;
        }

        notifyListenersOfProxyUpdate(midletProxy,
                MIDletProxyListListener.RESOURCES_SUSPENDED);
    
public voidhandleMIDletStartErrorEvent(int midletSuiteId, java.lang.String midletClassName, int midletExternalAppId, int errorCode, java.lang.String errorDetails)
Process a MIDlet start error event. Notify from last to first added to allow the listener to remove itself without causing a missed notification. MIDletControllerEventConsumer I/F method.

param
midletSuiteId ID of the MIDlet suite
param
midletClassName Class name of the MIDlet
param
midletExternalAppId ID of given by an external application manager
param
errorCode start error code
param
errorDetails start error details


        for (int i = listeners.size() - 1; i >= 0; i--) {
            MIDletProxyListListener listener =
                (MIDletProxyListListener)listeners.elementAt(i);

            listener.midletStartError(midletExternalAppId, midletSuiteId,
                                      midletClassName, errorCode, errorDetails);
        }
    
public voidhandlePauseAllEvent()
Process a PAUSE_ALL_EVENT. MIDletControllerEventConsumer I/F method.

        synchronized (midletProxies) {
            MIDletProxy current;

            for (int i = midletProxies.size() - 1; i >= 0; i--) {
                current = (MIDletProxy)midletProxies.elementAt(i);
                if (!current.wasNotActive) {
                    SuspendSystem.getInstance(classSecurityToken).
                            addSuspendDependency(current);
                    current.pauseMidlet();
                } else {
                    MIDletProxyUtils.terminateMIDletIsolate(current, this);
                }
            }
        }

        SuspendSystem.getInstance(classSecurityToken).suspend();

    
public voidhandleSetForegroundByNameRequestEvent(int suiteId, java.lang.String className)
Processes SET_FOREGROUND_BY_NAME_REQUEST event.

Set specified MIDlet to foreground.

param
suiteId MIDlet's suite ID
param
className MIDlet's class name


        MIDletProxy midletProxy = findMIDletProxy(suiteId, className);
        if (midletProxy != null) {
            setForegroundMIDlet(midletProxy);
        }
    
static voidinitClass(com.sun.midp.main.MIDletProxyList theMIDletProxyList)
Called by the MIDlet suite loader in AMS Isolate to intialize the midletProxy list. Shall be called only by MIDletSuiteLoader's main().

param
theMIDletProxyList proxy list instance to be used as MIDlet controller container Should only be called in the AMS Isolate.


                                                                            
        

        /*
        TBD: the code below is commented until
        the issue with non-static Logging.assertTrue
        will be fixed !

        Logging.assertTrue(theMIDletProxyList != null,
                           "theMIDletProxyList must be non-null");
        Logging.assertTrue(midletProxyList == null,
                           "midletProxyList must be initialized only once");
        */
        midletProxyList = theMIDletProxyList;
    
public booleanisAlertWaitingInBackground()
Return true if home indicator needs to be turned on

return
true if any MIDlet has set an Alert as the current displayable while in the background, otherwise false

        synchronized (midletProxies) {
            for (int i = midletProxies.size() - 1; i >= 0; i--) {
                MIDletProxy current = (MIDletProxy)midletProxies.elementAt(i);

                if (current.isAlertWaiting()) {
                    return true;
                }
            }
        }

        return false;
    
public booleanisMidletInList(int id, java.lang.String className)
Check to see if the MIDlet is already started.

param
id Suite ID of the MIDlet
param
className Class name of the MIDlet
return
true if the MIDlet has been started

        synchronized (midletProxies) {
            for (int i = midletProxies.size() - 1; i >= 0; i--) {
                MIDletProxy current = (MIDletProxy)midletProxies.elementAt(i);

                if (current.getSuiteId() == id &&
                    current.getClassName().equals(className)) {
                    return true;
                }
            }
        }

        return false;
    
public voidmidpResumed()
Called to notify that java side of MIDP system has been resumed.

public voidmidpSuspended()
Called to notify that java side of MIDP system has been suspended.

        notifyIfAllPaused();
    
private voidnotifyIfAllPaused()
Notifies the device if all MIDlets considered to be paused, that is at least one MIDlet is paused and others are either paused or destroyed. The notification is produced only once when the system runs to that state.

        boolean  allMidletsPaused = false;
        int midletState;

        synchronized (midletProxies) {
            if (!allPaused) {
                for (int i = midletProxies.size() - 1; i >= 0; i--) {
                    midletState = ((MIDletProxy) midletProxies.elementAt(i)).
                            getMidletState();

                    if (MIDletProxy.MIDLET_PAUSED == midletState) {
                        allMidletsPaused = true;
                    } else if (MIDletProxy.MIDLET_DESTROYED != midletState) {
                        allMidletsPaused = false;
                        break;
                    }
                }

                if (allMidletsPaused) {
                    allPaused = true;
                    notifySuspendAll0();
                }
            }
        }
    
private voidnotifyIfMidletActive()
Notifies the device if an active MIDlet appeared in the system. The notification is produced only once when the system runs out of the state with all the MIDlets being either paused or destroyed.

        MIDletProxy midletProxy;

        synchronized (midletProxies) {
            if (allPaused) {
                for (int i = midletProxies.size() - 1; i >= 0; i--) {
                    midletProxy = (MIDletProxy)midletProxies.elementAt(i);
                    if (midletProxy.getMidletState() ==
                            MIDletProxy.MIDLET_ACTIVE) {
                        allPaused = false;
                        notifyResumeAll0();
                        break;
                    }
                }
            }
        }
    
voidnotifyListenersOfProxyListChange(MIDletProxy midletProxy, int notificationType)
Notify the listeners of change in the size of the proxy list. Notify from last to first added to allow the listener to remove itself without causing a missed notification.

param
midletProxy midletProxy that was added or removed in the list
param
notificationType type of change, added or removed


        for (int i = listeners.size() - 1; i >= 0; i--) {
            MIDletProxyListListener listener =
                (MIDletProxyListListener)listeners.elementAt(i);

            switch (notificationType) {
            case PROXY_ADDED:
                listener.midletAdded(midletProxy);
                break;

            case PROXY_REMOVED:
                listener.midletRemoved(midletProxy);
                break;
            }
        }
    
voidnotifyListenersOfProxyUpdate(MIDletProxy midletProxy, int reason)
Notify the listeners of the midletProxy list that a proxy has been updated. Notify from last to first added to allow the listener to remove itself without causing a missed notification.

param
midletProxy midletProxy that changed in the list
param
reason reason for the change


        for (int i = listeners.size() - 1; i >= 0; i--) {
            MIDletProxyListListener listener =
                (MIDletProxyListListener)listeners.elementAt(i);

            listener.midletUpdated(midletProxy, reason);
        }
    
private native voidnotifyResumeAll0()
Notify native code that an active MIDlet appeared in the system.

private native voidnotifySuspendAll0()
Notify native code that all MIDlets have been paused.

voidremoveIsolateProxies(int id)
Removes the MIDletproxies that belong to the isolate id

param
id IsolateId

        // We are removing multiple items from the list we
        // have to remove from the enumeration.
        Enumeration e = getMIDlets();
        while (e.hasMoreElements()) {
            MIDletProxy mp = (MIDletProxy)e.nextElement();
            if (mp.getIsolateId() == id) {
                removeMidletProxy(mp);
            }
        }
    
public voidremoveListener(MIDletProxyListListener listener)
Remove a listener for MIDlet proxy list changes.

param
listener MIDlet proxy list listener

        listeners.removeElement(listener);
    
voidremoveMidletProxy(MIDletProxy midletProxy)
Removes a MidletProxy from the MidletProxyList

param
midletProxy the MIDletProxy to be removed.

        MIDletProxy preempting;

        /*
         * Remove the proxy before notifying the display controller,
         * so that new foreground search will not find MIDlet, but
         * don't notify the listener until after new foreground, since
         * the old foreground will generate a update notification.
         */
        midletProxies.removeElement(midletProxy);

        preempting = midletProxy.getPreemptingDisplay();
        if (preempting != null) {
            setForegroundMIDlet(displayController.midletDestroyed(preempting));
        } else {
            setForegroundMIDlet(
                displayController.midletDestroyed(midletProxy));
        }

        notifyListenersOfProxyListChange(midletProxy, PROXY_REMOVED);

        // An object may be waiting for the shutdown to complete
        if (shutdownFlag) {
            synchronized (midletProxies) {
                if (midletProxies.size() == 0) {
                    midletProxies.notifyAll();
                }
            }
        }
    
public voidsetDisplayController(DisplayController newController)
Enables the display controller to be replaced by an application manager.

param
newController new display controller

        displayController = newController;
    
private native voidsetForegroundInNativeState(int isolateId, int displayId)
Set foreground midletProxy in the native midletProxy list state.

param
isolateId Isolate ID
param
displayId Display ID

public voidsetForegroundMIDlet(MIDletProxy newForeground)
Sets the foreground MIDlet. If the given midletProxy is paused, then it will be activated before given the foreground. the internal system property "pause_app_in_background" is true, then previous foreground MIDlet will be paused.

The follow steps are performed when changed:

1. Send an event to notify the old foreground Display it has lost the foreground

2. Change the foreground field in this object and in the native code.

3. Send an event to notify the new foreground Display is has gained the foreground

param
newForeground Proxy of the MIDlet to be put in the foreground

        if (newForeground != null &&
            (newForeground.getMidletState() == MIDletProxy.MIDLET_DESTROYED ||
            newForeground == foregroundMidlet ||
            newForeground.noDisplay())) {
            return;
        }

        if (foregroundMidlet != null &&
            (foregroundMidlet.getMidletState() !=
            MIDletProxy.MIDLET_DESTROYED)) {
            /*
             * Background MIDlet will run with a lower priority
             */
            MIDletProxyUtils.minPriority(foregroundMidlet);
            foregroundMidlet.notifyMIDletHasForeground(false);
        }

        foregroundMidlet =
            displayController.foregroundMidletChanging(newForeground);

        /*
         * When there are no more midletProxys the foreground midletProxy
         * will be null again.
         */

        if (foregroundMidlet != null) {
            setForegroundInNativeState(foregroundMidlet.getIsolateId(),
                                       foregroundMidlet.getDisplayId());
            // This call with a true parameter will set the alertWaiting field.
            foregroundMidlet.notifyMIDletHasForeground(true);

           /*
            * Foreground MIDlet will run with a normal priority
            */
            MIDletProxyUtils.normalPriority(foregroundMidlet);

            notifyListenersOfProxyUpdate(foregroundMidlet,
                MIDletProxyListListener.ALERT_WAITING);
        } else {
            setForegroundInNativeState(MIDletSuiteUtils.getAmsIsolateId(),
                                       -1);
        }
    
public voidshutdown()
Shutdown the system by asynchronously destroying all MIDlets.

        synchronized (midletProxies) {
            if (shutdownFlag) {
                return;
            }

            shutdownFlag = true;

            if (midletProxies.size() == 0) {
                /*
                 * We are done if no proxyies are in the list.
                 * Notify any objects waiting for shutdown.
                 */
                midletProxies.notifyAll();
                return;
            }

            for (int i = midletProxies.size() - 1; i >= 0; i--) {
                MIDletProxy current = (MIDletProxy)midletProxies.elementAt(i);

                current.destroyMidlet();
            }
        }
    
static booleanshutdownInProgress()
Returns shutdown status

return
true if shutdown is in progress, else false

        return shutdownFlag;
    
public voidterminatePauseAll()
Finalizes PAUSE_ALL_EVENT processing after timeout for pausing MIDlets expires.

        synchronized (midletProxies) {
            MIDletProxy current;

            for (int i = midletProxies.size() - 1; i >= 0; i--) {
                current = (MIDletProxy)midletProxies.elementAt(i);

                current.terminateNotPausedMidlet();
            }

        }
    
public voidwaitForShutdownToComplete()
Wait for the system to asynchronously destroy all MIDlets.

        synchronized (midletProxies) {
            // Wait for shutdown to be called.
            while (!shutdownFlag) {
                try {
                    midletProxies.wait();
                } catch (InterruptedException ie) {
                    return;
                }
            }

            // Wait for all MIDlets to be destroyed.
            while (midletProxies.size() > 0) {
                try {
                    midletProxies.wait();
                } catch (InterruptedException ie) {
                    return;
                }
            }
        }