001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package com.sun.midp.suspend;
028:
029: import com.sun.midp.main.*;
030: import com.sun.midp.security.SecurityToken;
031: import com.sun.midp.security.Permissions;
032:
033: import java.util.Vector;
034:
035: /**
036: * Main system of the current isolate that contains all
037: * suspendable subsystems in current isolate.
038: * There is a singleton instance in each isolate. The
039: * instance kept in the AMS isolate is a special one and
040: * belongs to <code>MIDPSystem</code> subtype.
041: */
042: public class SuspendSystem extends AbstractSubsystem {
043: /**
044: * Listeners interested in suspend/resume operations.
045: */
046: private final Vector listeners = new Vector(1, 2);
047:
048: /**
049: * Main subsystem that implements suspend actions for
050: * whole MIDP system. It works in the AMS Isolate. There
051: * is the only instance for all isolates.
052: */
053: private static class MIDPSystem extends SuspendSystem implements
054: MIDletProxyListListener {
055: /**
056: * A flag to determine if at least one MIDlet has been
057: * destroyed during last suspend processing.
058: */
059: private boolean midletKilled = false;
060:
061: /**
062: * A flag to determine if at least one MIDlet has been
063: * successfully paused during last suspend processing.
064: */
065: private boolean midletPaused = false;
066:
067: /**
068: * Stored foreground MIDlet.
069: */
070: private MIDletProxy lastForeground;
071:
072: /**
073: * The MIDlet proxy list.
074: */
075: MIDletProxyList mpl = MIDletProxyList
076: .getMIDletProxyList(classSecurityToken);
077:
078: /**
079: * Constructs the only instance.
080: */
081: private MIDPSystem() {
082: state = ACTIVE;
083:
084: mpl.addListener(this );
085: addListener(mpl);
086: }
087:
088: /**
089: * Initiates MIDPSystem suspend operations.
090: */
091: public synchronized void suspend() {
092: if (ACTIVE == state) {
093: SuspendTimer.start(mpl);
094: lastForeground = mpl.getForegroundMIDlet();
095: SuspendResumeUI.showSuspendAlert(classSecurityToken);
096: super .suspend();
097: }
098: }
099:
100: /**
101: * Performs MIDPSystem-specific suspend operations.
102: */
103: protected synchronized void suspendImpl() {
104: SuspendTimer.stop();
105: }
106:
107: /**
108: * Performs MIDPSystem-specific resume operations.
109: */
110: protected synchronized void resumeImpl() {
111: midletKilled = false;
112: midletPaused = false;
113:
114: SuspendResumeUI.dismissSuspendAlert();
115: alertIfAllMidletsKilled();
116:
117: if (null != lastForeground) {
118: mpl.setForegroundMIDlet(lastForeground);
119: lastForeground = null;
120: }
121: }
122:
123: /**
124: * Shows proper alert if all user midlets were killed by a preceding
125: * suspend operation, and the event is not reported yet.
126: */
127: private synchronized void alertIfAllMidletsKilled() {
128: if (allMidletsKilled()) {
129: SuspendResumeUI.showAllKilledAlert(classSecurityToken);
130: }
131: }
132:
133: /**
134: * Notifies of system suspend.
135: */
136: protected void suspended() {
137: super .suspended();
138: suspended0(!midletPaused && midletKilled);
139: }
140:
141: /**
142: * Notifies native functionality that MIDP activities in java
143: * have been suspended.
144: * @param allMidletsKilled true to indicate that all user MIDlets
145: * were killed by suspend routines.
146: */
147: protected native void suspended0(boolean allMidletsKilled);
148:
149: /**
150: * Determines if at least one of preceding suspension operations
151: * killed all user MIDlets and the condition has not been checked
152: * since that time.
153: * @return true if a suspension operation killed all user MIDlets
154: * and the condition has not been checked yet, false
155: * otherwise. This method returns true only once for one
156: * event.
157: */
158: protected native boolean allMidletsKilled();
159:
160: /**
161: * Receives notifications on MIDlet updates and removes corresponding
162: * MIDlet proxy from suspend dependencies if required.
163: * @param midlet MIDletProxy that represents the MIDlet updated
164: * @param reason kind of changes that took place, see
165: */
166: public void midletUpdated(MIDletProxy midlet, int reason) {
167: boolean amsMidlet = (MIDletSuiteUtils.getAmsIsolateId() == midlet
168: .getIsolateId());
169:
170: if (reason == MIDletProxyListListener.RESOURCES_SUSPENDED) {
171: if (!amsMidlet) {
172: midletPaused = true;
173: }
174: removeSuspendDependency(midlet);
175: } else if (reason == MIDletProxyListListener.MIDLET_STATE
176: && amsMidlet
177: && midlet.getMidletState() == MIDletProxy.MIDLET_ACTIVE) {
178: /* An AMS midlet has been activated, checking if it is a
179: * result of abnormal midlet termination during suspend.
180: */
181: alertIfAllMidletsKilled();
182: }
183: }
184:
185: /**
186: * Receives MIDlet removal notification and removes corresponding
187: * MIDlet proxy from suspend dependencies.
188: * @param midlet MIDletProxy that represents the MIDlet removed
189: */
190: public synchronized void midletRemoved(MIDletProxy midlet) {
191: midletKilled = true;
192: removeSuspendDependency(midlet);
193: if (midlet == lastForeground) {
194: lastForeground = null;
195: }
196: }
197:
198: /**
199: * Not used. MIDletProxyListListener interface method.
200: */
201: public void midletAdded(MIDletProxy midlet) {
202: }
203:
204: /**
205: * Not used. MIDletProxyListListener interface method.
206: */
207: public void midletStartError(int externalAppId, int suiteId,
208: String className, int errorCode, String errorDetails) {
209: }
210: }
211:
212: /**
213: * The singleton instance.
214: */
215: private static SuspendSystem instance = MIDletSuiteUtils
216: .getIsolateId() == MIDletSuiteUtils.getAmsIsolateId() ? new MIDPSystem()
217: : new SuspendSystem();
218:
219: /**
220: * Retrieves the singleton instance.
221: * @param token security token that identifies caller permissions for
222: * accessing this API
223: * @return the singleton instance
224: */
225: public static SuspendSystem getInstance(SecurityToken token) {
226: token.checkIfPermissionAllowed(Permissions.MIDP);
227: return instance;
228: }
229:
230: /**
231: * Retrieves the singleton instance. The method is only available from
232: * this restricted package.
233: * @return the singleton instance
234: */
235: static SuspendSystem getInstance() {
236: return instance;
237: }
238:
239: /**
240: * Constructs an instance.
241: */
242: private SuspendSystem() {
243: }
244:
245: /**
246: * Registers a listener interested in system suspend/resume operations.
247: * IMPL_NOTE: method for removing listeners is not needed currently.
248: *
249: * @param listener the listener to be added
250: */
251: public void addListener(SuspendSystemListener listener) {
252: synchronized (listeners) {
253: listeners.addElement(listener);
254: }
255: }
256:
257: /**
258: * Notifies listeners of system suspend.
259: */
260: protected void suspended() {
261: synchronized (listeners) {
262: for (int i = listeners.size() - 1; i >= 0; i--) {
263: SuspendSystemListener listener = (SuspendSystemListener) listeners
264: .elementAt(i);
265: listener.midpSuspended();
266: }
267: }
268: }
269:
270: /**
271: * Notifies listeners of system resume.
272: */
273: protected void resumed() {
274: synchronized (listeners) {
275: for (int i = listeners.size() - 1; i >= 0; i--) {
276: SuspendSystemListener listener = (SuspendSystemListener) listeners
277: .elementAt(i);
278: listener.midpResumed();
279: }
280: }
281: }
282: }
|