/*
*
*
* Copyright 1990-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 only, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License version 2 for more details (a copy is
* included at /legal/license.txt).
*
* You should have received a copy of the GNU General Public License
* version 2 along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 or visit www.sun.com if you need additional
* information or have any questions.
*/
package com.sun.midp.main;
import com.sun.midp.events.EventTypes;
import com.sun.midp.events.NativeEvent;
import com.sun.midp.events.EventQueue;
/**
* This class provides methods to send events of types
* handled by MIDletControllerEventConsumer I/F implementors.
* This class completely hide event construction & sending in its methods.
*
* This class is intended to be used by MIDletStateHandler & MIDletPeer
* classes in Allication Isolate.
* So in some of its sendXXXEvent()methods we can change int IDs to
* MIDletPeer references.
*
* Generic comments for all XXXEventProducers:
*
* For each supported event type there is a separate sendXXXEvent() method,
* that gets all needed parameters to construct an event of an approprate class.
* The method also performs event sending itself.
*
* If a given event type merges a set of logically different subtypes,
* this class shall provide separate methods for these subtypes.
*
* It is assumed that only one object instance of this class
* is initialized with the system event that is created at (isolate) startup.
*
* This class only operates on the event queue given to it during
* construction, the class does not obtain any restricted object itself,
* so it does not need protection.
*
* All MIDP stack subsystems that need to send events of supported types,
* must get a reference to an already created istance of this class.
* Typically, this instance should be passed as a constructor parameter.
*
* Class is NOT final to allow debug/profile/test/automation subsystems
* to change, substitute, complement default "event sending" functionality :
* Ex.
* class LogXXXEventProducer
* extends XXXEventProducer {
* ...
* void sendXXXEvent(parameters) {
* LOG("Event of type XXX is about to be sent ...")
* super.sendXXXEvent(parameters);
* LOG("Event of type XXX has been sent successfully !")
* }
* ...
* }
*/
public class MIDletControllerEventProducer {
/** Cached reference to the MIDP event queue. */
protected EventQueue eventQueue;
/** Cached reference to AMS isolate ID. */
protected int amsIsolateId;
/** Cached reference to current isolate ID. */
protected int currentIsolateId;
/** Preallocate start error event to work in case of out of memory */
final NativeEvent startErrorEvent;
/** Preallocate MIDlet created event to work in case of out of memory */
final NativeEvent midletCreatedEvent;
/** Preallocate MIDlet active event to work in case of out of memory */
final NativeEvent midletActiveEvent;
/** Preallocate MIDlet paused event to work in case of out of memory */
final NativeEvent midletPausedEvent;
/** Preallocate MIDlet destroyed event to work in case of out of memory */
final NativeEvent midletDestroyedEvent;
/**
* Preallocate MIDlet resources paused event to work in case of out
* of memory
*/
final NativeEvent midletRsPausedEvent;
/**
* Construct a new MIDletControllerEventProducer.
*
* @param theEventQueue An event queue where new events will be posted.
* @param theAmsIsolateId AMS Isolate Id
* @param theCurrentIsolateId Current Isolate Id
*/
public MIDletControllerEventProducer(
EventQueue theEventQueue,
int theAmsIsolateId,
int theCurrentIsolateId) {
eventQueue = theEventQueue;
amsIsolateId = theAmsIsolateId;
currentIsolateId = theCurrentIsolateId;
/* Cache all of the notification events. */
startErrorEvent =
new NativeEvent(EventTypes.MIDLET_START_ERROR_EVENT);
midletCreatedEvent =
new NativeEvent(EventTypes.MIDLET_CREATED_NOTIFICATION);
midletActiveEvent =
new NativeEvent(EventTypes.MIDLET_ACTIVE_NOTIFICATION);
midletPausedEvent =
new NativeEvent(EventTypes.MIDLET_PAUSED_NOTIFICATION);
midletDestroyedEvent =
new NativeEvent(EventTypes.MIDLET_DESTROYED_NOTIFICATION);
midletRsPausedEvent =
new NativeEvent(EventTypes.MIDLET_RS_PAUSED_NOTIFICATION);
}
/*
* MIDlet Startup Events:
*
* MIDLET_START_ERROR
* MIDLET_CREATED_NOTIFICATION
*/
/**
* Notifies AMS that MIDlet creation failed
* NEW: earlier it has been explicitely generated by
* void static AppIsolateMIDletSuiteLoader.main(...)
*
* @param midletExternalAppId ID of given by an external application
* manager
* @param midletSuiteId ID of the MIDlet suite
* @param midletClassName Class name of the MIDlet
* @param errorCode start error code
*/
public void sendMIDletStartErrorEvent(
int midletSuiteId,
String midletClassName,
int midletExternalAppId,
int errorCode,
String errorDetails) {
synchronized (startErrorEvent) {
// use pre-created event to work in case of handling out of memory
startErrorEvent.intParam1 = midletSuiteId;
startErrorEvent.intParam2 = midletExternalAppId;
startErrorEvent.intParam3 = errorCode;
startErrorEvent.stringParam1 = midletClassName;
startErrorEvent.stringParam2 = errorDetails;
eventQueue.sendNativeEventToIsolate(startErrorEvent, amsIsolateId);
}
}
/**
* Called to send a MIDlet created notification to the AMS isolate.
*
* @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 midletDisplayName name to show the user
*/
public void sendMIDletCreateNotifyEvent(
int midletSuiteId,
String midletClassName,
int midletExternalAppId,
String midletDisplayName) {
synchronized (midletCreatedEvent) {
midletCreatedEvent.intParam1 = midletSuiteId;
midletCreatedEvent.intParam2 = currentIsolateId;
midletCreatedEvent.intParam3 = midletExternalAppId;
midletCreatedEvent.stringParam1 = midletClassName;
midletCreatedEvent.stringParam2 = midletDisplayName;
eventQueue.sendNativeEventToIsolate(midletCreatedEvent,
amsIsolateId);
}
}
/*
* MIDlet State Management (Lifecycle) Events:
*
* MIDLET_ACTIVE_NOTIFICATION
* MIDLET_PAUSE_NOTIFICATION
* MIDLET_DESTROY_NOTIFICATION
*
* MIDLET_DESTROY_REQUEST
*
* ACTIVATE_ALL - produced by native code
* PAUSE_ALL -produced by native code
* SHUTDOWN/DESTROY_ALL - produced by native code
*
* FATAL_ERROR_NOTIFICATION - produced by native code
*
*/
/**
* Called to send a MIDlet active notification to the AMS isolate.
*
* @param midletSuiteId ID of the MIDlet suite
* @param midletClassName Class name of the MIDlet
*/
public void sendMIDletActiveNotifyEvent(int midletSuiteId,
String midletClassName) {
sendEvent(midletActiveEvent, midletSuiteId, midletClassName);
}
/**
* Called to send a MIDlet paused notification to the AMS isolate.
*
* @param midletSuiteId ID of the MIDlet suite
* @param midletClassName Class name of the MIDlet
*/
public void sendMIDletPauseNotifyEvent(int midletSuiteId,
String midletClassName) {
sendEvent(midletPausedEvent, midletSuiteId, midletClassName);
}
/**
* Called to send a MIDlet destroyed notification to the AMS isolate.
*
* @param midletSuiteId ID of the MIDlet suite
* @param midletClassName Class name of the MIDlet
*/
public void sendMIDletDestroyNotifyEvent(int midletSuiteId,
String midletClassName) {
sendEvent(midletDestroyedEvent, midletSuiteId, midletClassName);
}
/**
* Called to send a MIDlet resume request to the AMS isolate.
*
* @param midletSuiteId ID of the MIDlet suite
* @param midletClassName Class name of the MIDlet
*/
public void sendMIDletResumeRequest(int midletSuiteId,
String midletClassName) {
sendEvent(new NativeEvent(EventTypes.MIDLET_RESUME_REQUEST),
midletSuiteId, midletClassName);
}
/**
* Sends notification for MIDlet resources pause to the AMS isolate.
*
* @param midletSuiteId ID of the MIDlet suite
* @param midletClassName Class name of the MIDlet
*/
public void sendMIDletRsPauseNotifyEvent(int midletSuiteId,
String midletClassName) {
sendEvent(midletRsPausedEvent, midletSuiteId, midletClassName);
}
/**
* Called by the display to request the central AMS to destroy the owning
* MIDlet.
*
* @param midletDisplayId ID of the sending Display
*/
public void sendMIDletDestroyRequestEvent(int midletDisplayId) {
sendEvent(new NativeEvent(EventTypes.MIDLET_DESTROY_REQUEST_EVENT),
midletDisplayId);
}
/*
* Foreground MIDlet Management Events:
*
* SELECT_FOREGROUND - produced by native code
* FOREGROUND_TRANSFER
* SET_FOREGROUND_BY_NAME_REQUEST
*
*/
/**
* Called to send a foreground MIDlet transfer event to the AMS isolate.
* Former: NEW method, originally sent from CHAPI
*
* @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
*/
public void sendMIDletForegroundTransferEvent(
int originMIDletSuiteId,
String originMIDletClassName,
int targetMIDletSuiteId,
String targetMIDletClassName) {
NativeEvent event =
new NativeEvent(EventTypes.FOREGROUND_TRANSFER_EVENT);
event.intParam1 = originMIDletSuiteId;
event.intParam2 = targetMIDletSuiteId;
event.stringParam1 = originMIDletClassName;
event.stringParam2 = targetMIDletClassName;
eventQueue.sendNativeEventToIsolate(event, amsIsolateId);
}
/**
* Called to send a request to AMS isolate for a MIDlet be in
* the foreground.
*
* @param suiteId MIDlet's suite ID
* @param className MIDlet's class name
*/
public void sendSetForegroundByNameRequestEvent(int suiteId,
String className) {
NativeEvent event =
new NativeEvent(EventTypes.SET_FOREGROUND_BY_NAME_REQUEST);
event.intParam1 = suiteId;
event.stringParam1 = className;
eventQueue.sendNativeEventToIsolate(event, amsIsolateId);
}
/**
* Called to send a Display created notification to the AMS isolate.
*
* @param midletDisplayId ID of the sending Display
* @param midletClassName Class name of the MIDlet that owns the display
*/
public void sendDisplayCreateNotifyEvent(int midletDisplayId,
String midletClassName) {
NativeEvent event =
new NativeEvent(EventTypes.DISPLAY_CREATED_NOTIFICATION);
event.intParam1 = currentIsolateId;
event.intParam2 = midletDisplayId;
event.stringParam1 = midletClassName;
eventQueue.sendNativeEventToIsolate(event, amsIsolateId);
}
/*
* Foreground Display Management Events:
*
* FOREGROUND_REQUEST
* BACKGROUND_REQUEST
*
*/
/**
* Called to send a foreground request event to the AMS isolate.
*
* @param midletDisplayId ID of the sending Display
* @param isAlert true if the current displayable is an Alert
*/
public void sendDisplayForegroundRequestEvent(int midletDisplayId,
boolean isAlert) {
NativeEvent event =
new NativeEvent(EventTypes.FOREGROUND_REQUEST_EVENT);
if (isAlert) {
event.intParam2 = 1;
} else {
event.intParam2 = 0;
}
sendEvent(event, midletDisplayId);
}
/**
* Called to send a background request event to the AMS isolate.
*
* @param midletDisplayId ID of the sending Display
*/
public void sendDisplayBackgroundRequestEvent(int midletDisplayId) {
sendEvent(new NativeEvent(EventTypes.BACKGROUND_REQUEST_EVENT),
midletDisplayId);
}
/*
* Display Preemption Management Events:
*
* PREEMPT
*
*/
/**
* Called to start preempting and end preempting.
* Probably: will need more parameters, ex. MIDlet ID
*
* @param midletDisplayId ID of the sending Display
*/
public void sendDisplayPreemptStartEvent(int midletDisplayId) {
NativeEvent event =
new NativeEvent(EventTypes.PREEMPT_EVENT);
event.intParam2 = -1; /* start = true */
sendEvent(event, midletDisplayId);
}
/**
* Called to start preempting and end preempting.
* Probably: will need more parameters, ex. MIDlet ID
*
* @param midletDisplayId ID of the sending Display
*/
public void sendDisplayPreemptStopEvent(int midletDisplayId) {
NativeEvent event =
new NativeEvent(EventTypes.PREEMPT_EVENT);
event.intParam2 = 0; /* start = false */
sendEvent(event, midletDisplayId);
}
/**
* Sends standard MIDlet controller event setting two integer parameters
* for display ID and isolate ID. It is synchronized by the event to be
* sent to avoid inconsistent parameters setting.
*
* @param event event to be sent
* @param midletDisplayId ID of the sending Display
*/
private void sendEvent(NativeEvent event, int midletDisplayId) {
synchronized (event) {
event.intParam1 = currentIsolateId;
event.intParam4 = midletDisplayId;
eventQueue.sendNativeEventToIsolate(event, amsIsolateId);
}
}
/**
* Sends standard MIDlet controller event setting two parameters
* for suite ID and class name. It is synchronized by the event to be
* sent to avoid inconsistent parameters setting.
*
* @param event event to be sent
* @param midletSuiteId ID of the MIDlet suite
* @param midletClassName Class name of the MIDlet
*/
private void sendEvent(NativeEvent event, int midletSuiteId,
String midletClassName) {
synchronized (event) {
event.intParam1 = midletSuiteId;
event.stringParam1 = midletClassName;
eventQueue.sendNativeEventToIsolate(event, amsIsolateId);
}
}
}