📄 scheduler.java
字号:
/* * @(#)Scheduler.java 1.65 02/10/15 @(#) * * Copyright (c) 1999-2002 Sun Microsystems, Inc. All rights reserved. * PROPRIETARY/CONFIDENTIAL * Use is subject to license terms. */package com.sun.midp.midlet;import javax.microedition.midlet.MIDlet;import javax.microedition.midlet.MIDletStateChangeException;import com.sun.midp.lcdui.DisplayManager;import com.sun.midp.lcdui.DisplayManagerFactory;import com.sun.midp.lcdui.SystemEventListener;import com.sun.midp.lcdui.MIDletEventListener;import com.sun.midp.main.Configuration;import com.sun.midp.security.Permissions;/** * The Scheduler starts and controls MIDlets through the lifecycle states. * MIDlets are created using its no-arg Constructor. Once created * it is sequenced through the start, paused, and destroy states. * <p> * The Scheduler is a singleton. The Scheduler is retrieved with * getScheduler(). The Scheduler can be replaced by subclassing. * Events that affect MIDlet scheduling should notify the Scheduler. * Typical events are MIDlet creation, changing of MIDlet states, etc. * <p> * To replace the Scheduler, subclass it and then set the * "com.sun.midp.midlet.scheduler" property to the name of the subclass. * When the Scheduler is first retrieved, the property is checked and the * instance created. If left unset the Scheduler class is used unchanged. * <p> * The MIDlet methods are protected in the javax.microedition.midlet package * so the Scheduler can not call them directly. The MIDletState object and * MIDletProxy subclass class allow the Scheduler to hold the state of the * MIDlet and to invoke methods on it. The MIDletState instance is created * by the MIDlet when it is constructed. * <p> * This default implementation of the Scheduler introduces a couple * of extra internally only visible states to allow processing of MIDlet * requested state changes in the control thread and serialized with * other state changes. The additional states are: * <UL> * <LI> <code>PAUSED_RESUME</code> - Similar to PAUSED but also indicates * that this MIDlet has requested to be resumed. * <LI> <code>DESTROY_PENDING</code> - Indicates that the MIDlet needs * to be DESTROYED. The MIDlet's destroyApp has not yet been called. * </UL> * The Scheduler loops, looking for MIDlets that require state changes * and making the requested changes including calling methods in * the MIDlet to make the change. * <p> * When a MIDlet is started, put in <code>ACTIVE</code> state, its display * is activated by the scheduler using the display manager. When a MIDlet is * destroyed its display is deactivated. When MIDlet is paused by the MIDlet * itself, its display is deactivated and it will not be restarted unless the * MIDlet requests itself to be restarted. When a MIDlet is paused by a UI * event from the display manager the display of the MIDlet is * not deactivated but suspended, which means it can be resumed by * system event such as a user selection. * <p> * It is possible that as far as the Scheduler is concerned * there is no <code>ACTIVE</code> MIDlet. The only case in which this should * arise is when all MIDlets are PAUSED or DESTROYED. From the user * point of view this is quite bad. This case is the same as all off the * active MIDlets not have a current displayable. So display manager will * need to "default screen". Later when multiple MIDlet suites can be run, * the VM will run in the background and the the application selector will * run. * <p> * For the specific handling of events received from the display manager * see the documenation for implemenation each of listener methods. * * @see MIDlet * @see MIDletState * @see DisplayManager */public class Scheduler implements SystemEventListener, MIDletEventListener { /** the current MIDlet suite */ private MIDletSuite midletSuite; /** array of MIDlets */ private MIDletState[] midlets; /** current number of MIDlets [0..n-1] */ private int nmidlets; /** next index to be scanned by selectForeground */ private int scanIndex; /** display manager */ private DisplayManager displayManager; /** Flag to indicate if the system was shutdown. */ private boolean systemShutdown; /** used to wait for MIDlet state changes */ private static Object mutex; /** the manager of all MIDlets */ private static Scheduler scheduler; /** the thread on which the scheduler is active */ private Thread schedulerThread; /** * Construct a new Scheduler object. */ protected Scheduler() { /* * The fact that there is only one scheduler is a security feature. * Multiple schedulers are allow in the future, the constructor * should require security domain parameter and it should be * checked. */ if (scheduler != null) { throw new Error("Only one scheduler instance allowed"); } mutex = new Object(); nmidlets = 0; // start with 5 empty slots, we will add more if needed midlets = new MIDletState[5]; } /** * Get the Scheduler that manages the lifecycle states MIDlets. * If the instance of the Scheduler has already been created * it is returned. If not it is created from the value of * the "com.sun.midp.midlet.scheduler" property. If that property * is null the default scheduler (this class) is instantiated. * The instance becomes the Scheduler for this process * * @return the MIDlet management software scheduler */ public static synchronized Scheduler getScheduler() { /* * If not scheduler has been created, create one now. * If the scheduler class has been overridden use it. */ if (scheduler == null) { String prop = Configuration.getProperty("com.sun.midp.midlet.scheduler"); if (prop != null) { Class c; try { c = Class.forName(prop); } catch (Throwable ex) { throw new Error("A scheduler class cannot be loaded " + "from the value of property " + "com.sun.midp.midlet.scheduler"); } try { scheduler = (Scheduler)c.newInstance(); } catch (Throwable ex) { throw new Error("The construction of " + prop + " instance failed"); } } else { /* This is the default scheduler class */ scheduler = new Scheduler(); } } return scheduler; } /** * Get the display manager. * * @return the display manager */ private DisplayManager getDisplayManager() { if (displayManager == null) { displayManager = DisplayManagerFactory.getDisplayManager(); } return displayManager; } /** * Schedule a MIDlet from outside of the package. * * @param midlet to be registered with this scheduler * * @exception SecurityException if the suite does not have the * AMS permission. */ public void scheduleMIDlet(MIDlet midlet) { midletSuite.checkIfPermissionAllowed(Permissions.AMS); register(midlet); } /** * Register a MIDlet being constructed. * * @param midlet to be registered with this scheduler */ protected void register(MIDlet midlet) { synchronized (mutex) { MIDletState state = MIDletStateMap.getState(midlet); /* * If a MIDlet of the same class is already running * Make the existing MIDlet current so that schedule() will run it */ int i = findMIDletByClass(state); if (i >= 0) { state.setState(MIDletState.DESTROY_PENDING); // Fall into adding it to the list so destroyApp // can be called at a reasonable time. } // Grow the list if necessary if (nmidlets >= midlets.length) { MIDletState[] n = new MIDletState[nmidlets+5]; System.arraycopy(midlets, 0, n, 0, nmidlets); midlets = n; } // Add it to the end of the list midlets[nmidlets++] = state; mutex.notify(); } } /** * Return the mutex for synchronization and notification of changes * to a MIDlets state. * It is used by MIDlets when they are changing states. * It is the mutex used for all state changes. * @return mutex object for synchronizing this scheduler */ protected Object getMutex() { return mutex; } /** * Provides a <code>MIDletProxy</code> with a mechanism to retrieve * <code>MIDletSuite</code> being scheduled. * * @return MIDletSuite being scheduled */ public MIDletSuite getMIDletSuite() { return midletSuite; } /** * Returns true if the current thread is the Scheduler's thread. * * @return true if the current thread is this Scheduler's thread */ public boolean isDispatchThread() { // NOTE: This will have to be removed when Display // changes queued in the event handler return (Thread.currentThread() == schedulerThread); } /** * Run MIDlets until there are none. * Handle any pending state transitions of any MIDlet. * If there are none, wait for transitions. * If there is no foreground MIDlet select one that is ACTIVE and * has setCurrent != null. * <p> * If the foreground MIDlet changes from the ACTIVE_FOREGROUND state * it automatically looses the foreground and and new one is selected. * * @param aMidletSuite the current midlet suite * * @return true if a method ended because the last MIDlet was destroyed * normally, false if the system is shutting down. * * @exception ClassNotFoundException is thrown, if the MIDlet main class is * not found * @exception InstantiationException is thrown, if the MIDlet can not be * created * @exception IllegalAccessException is thrown, if the MIDlet is not * permitted to perform a specific operation */ public boolean schedule(MIDletSuite aMidletSuite) throws ClassNotFoundException, InstantiationException, IllegalAccessException { if (midletSuite != null) { throw new RuntimeException( "There is already a MIDlet Suite scheduled."); } // NOTE: This will have to be removed when Display // changes queued in the event handler schedulerThread = Thread.currentThread();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -