📄 scheduler.java
字号:
/* * @(#)Scheduler.java 1.50 01/08/08 * Copyright (c) 1999,2001 Sun Microsystems, Inc. All Rights Reserved. * * This software is the confidential and proprietary information of Sun * Microsystems, Inc. ("Confidential Information"). You shall not * disclose such Confidential Information and shall use it only in * accordance with the terms of the license agreement you entered into * with Sun. * * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING * THIS SOFTWARE OR ITS DERIVATIVES. */package com.sun.midp.midlet;import javax.microedition.midlet.MIDlet;import javax.microedition.midlet.MIDletStateChangeException;import com.sun.midp.lcdui.MIDLetMap;import com.sun.midp.lcdui.DisplayAccess;import com.sun.midp.Configuration;/** * 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. * It handles transitions of the Display between foreground and background. * <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, changes * in the status of the current Displayable, 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>ACTIVE_FOREGROUND</code> - Similar to ACTIVE but also * indicates that this MIDlet has the Display (i.e. is in foreground). * <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> * Transitions in the foreground and background status are handled based * on events delivered from the Display that signal changes in the * current Displayable on the Display and on the current state of the * MIDlet. Specifically: * <UL> * <LI> Only the MIDlet in state ACTIVE_FOREGROUND is in foreground. * Any state change (paused, destroyed, etc) causes foreground to * be revoked. The current foreground MIDlet is checked on each loop. * (Another will be selected later). * <LI> If there is no foreground MIDlet a search is made for an ACTIVE * MIDlet that has set a "current" displayable (that is non-null). * There is no particular ordering or priority or cycling behavior * in the implementation. * If a MIDlet is found it is set into ACTIVE_FOREGROUND state and * given the Display. * <LI> It is possible that as far as the Scheduler is concerned * there will be no foreground 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. It is avoided by always having * the Selector be ACTIVE and able to be selected. * <LI>The notifyEnd event causes the foreground MIDlet to be * put into DestroyPending state. (Exception that the "Selector" * is never killed.) This simulates the behavior that pressing the * "end" key on the phone will return the display to the Selector. * </UL> * @see MIDlet * @see MIDletState */public class Scheduler { /** the current MIDlet suite */ private MIDletSuite midletSuite; /** the current foreground MIDlet */ private MIDletState foreground; /** 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; /** used to wait for MIDlet state changes */ private static Object mutex; /** the manager of all MIDlets */ private static Scheduler scheduler; /** * 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) { try { scheduler = (Scheduler)(Class.forName(prop)).newInstance(); } catch (Throwable ex) { throw new Error("A scheduler cannot be created from " + "the value of property " + "com.sun.midp.midlet.scheduler"); } } else { /* This is the default scheduler class */ scheduler = new Scheduler(); } } return scheduler; } /** * Register a MIDlet being constructed. * Called from the MIDlet constructor so Scheduler knows every * existing MIDlet. * @param midlet to be registered with this scheduler */ protected void register(MIDletState midlet) { synchronized (mutex) { /* * If a MIDlet of the same class is already running * Make the existing MIDlet current so that schedule() will run it */ int i = findMIDletByClass(midlet); if (i >= 0) { midlet.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++] = midlet; } } /** * 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; } /** * 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 * @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 void schedule(MIDletSuite aMidletSuite) throws ClassNotFoundException, InstantiationException, IllegalAccessException { if (midletSuite != null) { throw new RuntimeException( "There is already a MIDlet Suite scheduled."); } midletSuite = aMidletSuite; midletSuite.loadInitialMIDlet(); // Until there are no MIDlets while (nmidlets > 0) { try { MIDletState oldfg, newfg; // Check if a change in foreground is needed synchronized (mutex) { // Check if the foreground MIDlet has // changed state and should not be foreground anymore oldfg = null; if (foreground != null && foreground.getState() != MIDletState.ACTIVE_FOREGROUND) { oldfg = foreground; foreground = null; } newfg = null; if (foreground == null) { // No MIDlet as foreground // Scan the actives looking for one that needs/wants // the display foreground = selectForeground(oldfg); if (foreground != null) { // set the MIDlet in the ACTIVE_FOREGROUND state foreground.setState(MIDletState.ACTIVE_FOREGROUND); newfg = foreground; } } } // If foreground needs to be revoked do so outside of mutex if (oldfg != null) { setForeground(oldfg, false); } // If foreground needs to be invoked do so outside of mutex if (newfg != null) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -