FileDocCategorySizeDatePackage
NativeAppManagerPeer.javaAPI DocphoneME MR2 API (J2ME)19126Wed May 02 18:00:04 BST 2007com.sun.midp.main

NativeAppManagerPeer

public class NativeAppManagerPeer extends Object implements com.sun.midp.suspend.SuspendSystemListener, MIDletProxyListListener, EventListener, IsolateMonitorListener
This is an implementation of the native application manager peer for the MVM mode of VM capable of running with more than 1 midlet concurrently. It notifies it peer of MIDlet state changes, but not this MIDlet.

Fields Summary
static boolean
alreadyCalled
If true, the main of this class has already been called.
static final int
MAIN_EXIT
return value from Main, so we know that Main exited normally
private static NativeAppManagerPeer
singleton
Singleton native app manager peer reference.
private SecurityToken
internalSecurityToken
Security token for using protected APIs.
private MIDletProxyList
midletProxyList
MIDlet proxy list reference.
private EventQueue
eventQueue
Event queue reference.
Constructors Summary
private NativeAppManagerPeer()
Create and initialize a new native app manager peer MIDlet.

        /*
         * WARNING: Don't add any calls before this !
         *
         * Register AMS Isolate ID in native global variable.
         * Since native functions rely on this value to distinguish
         * whether Java AMS is running, this MUST be called before any
         * other native functions from this Isolate. I.E. This call
         * must be the first thing this main class makes.
         */
        registerAmsIsolateId();

        internalSecurityToken =
            SecurityInitializer.requestToken(new SecurityTrusted());
        eventQueue = EventQueue.getEventQueue(internalSecurityToken);

        // current isolate & AMS isolate is the same object
        int amsIsolateId = MIDletSuiteUtils.getAmsIsolateId();
        int currentIsolateId = MIDletSuiteUtils.getIsolateId();

        // init AMS task resources needed for all tasks
        MIDletSuiteUtils.initAmsResources();

        // create all needed event-related objects but not initialize ...
        MIDletEventProducer midletEventProducer =
            new MIDletEventProducer(eventQueue);

        MIDletControllerEventProducer midletControllerEventProducer =
            new MIDletControllerEventProducer(eventQueue,
                                              amsIsolateId,
                                              currentIsolateId);

        ForegroundEventProducer foregroundEventProducer =
            new ForegroundEventProducer(eventQueue);

        midletProxyList = new MIDletProxyList(eventQueue);

        // do all initialization for already created event-related objects ...
        MIDletProxy.initClass(foregroundEventProducer, midletEventProducer);
        MIDletProxyList.initClass(midletProxyList);

        AmsUtil.initClass(midletProxyList, midletControllerEventProducer);

        midletProxyList.addListener(this);
        midletProxyList.setDisplayController(
            new NativeDisplayControllerPeer(midletProxyList));

        IsolateMonitor.addListener(this);

        SuspendSystem.getInstance(internalSecurityToken).addListener(this);

        eventQueue.registerEventListener(
            EventTypes.NATIVE_MIDLET_EXECUTE_REQUEST, this);
        eventQueue.registerEventListener(
            EventTypes.NATIVE_MIDLET_RESUME_REQUEST, this);
        eventQueue.registerEventListener(
            EventTypes.NATIVE_MIDLET_PAUSE_REQUEST, this);
        eventQueue.registerEventListener(
            EventTypes.NATIVE_MIDLET_DESTROY_REQUEST, this);
        eventQueue.registerEventListener(
            EventTypes.NATIVE_MIDLET_GETINFO_REQUEST, this);
        eventQueue.registerEventListener(
            EventTypes.NATIVE_SET_FOREGROUND_REQUEST, this);

        IndicatorManager.init(midletProxyList);

        NamsTestService.init(internalSecurityToken, eventQueue);
    
Methods Summary
private static native voidexitInternal(int status)
Exit the VM with an error code. Our private version of Runtime.exit.

This is needed because the MIDP version of Runtime.exit cannot tell if it is being called from a MIDlet or not, so it always throws an exception.

param
status Status code to return.

public static voidmain(java.lang.String[] args)
Called at the initial start of the VM. Initializes internal security and any other AMS classes related classes before starting the MIDlet.

param
args not used


                           
       
          

                                   
         

        // Since this is public method, guard against multiple calls

        if (alreadyCalled) {
            throw new SecurityException();
        }

        alreadyCalled = true;

        try {
            try {
                singleton = new NativeAppManagerPeer();
            } catch (Throwable exception) {
                notifySystemStartError();
                throw exception;
            }

            notifySystemStart();
            singleton.processNativeAppManagerRequests();
        } catch (Throwable exception) {
            if (Logging.TRACE_ENABLED) {
                Logging.trace(exception,
                             "Exception caught in NativeManagerPeer");
            }
        } finally {
            exitInternal(MAIN_EXIT);
        }
    
public voidmidletAdded(MIDletProxy midlet)
Called when a MIDlet is added to the list.

param
midlet The proxy of the MIDlet being added

        notifyMidletCreated(midlet.getExternalAppId());
    
public voidmidletRemoved(MIDletProxy midlet)
Called when a MIDlet is removed from the list.

param
midlet The proxy of the removed MIDlet

        notifyMidletDestroyed(midlet.getExternalAppId());
    
public voidmidletStartError(int externalAppId, int suiteId, java.lang.String className, int errorCode, java.lang.String errorDetails)
Called when error occurred while starting a MIDlet object.

param
externalAppId ID assigned by the external application manager
param
suiteId Suite ID of the MIDlet
param
className Class name of the MIDlet
param
errorCode start error code
param
errorDetails start error details

        notifyMidletStartError(externalAppId, errorCode);
    
public voidmidletUpdated(MIDletProxy midlet, int fieldId)
Called when the state of a MIDlet in the list is updated.

param
midlet The proxy of the MIDlet that was updated
param
fieldId code for which field of the proxy was updated

        if (fieldId == MIDLET_STATE) {
            if (midlet.getMidletState() == MIDletProxy.MIDLET_ACTIVE) {
                notifyMidletActive(midlet.getExternalAppId());
                return;
            }

            if (midlet.getMidletState() == MIDletProxy.MIDLET_PAUSED) {
                notifyMidletPaused(midlet.getExternalAppId());
                return;
            }
        }
    
public voidmidpResumed()
Called if MIDP system has been resumed.

        notifySystemStart();
    
public voidmidpSuspended()
Called if MIDP system has been suspended.

        notifySystemSuspended();
    
private static native voidnotifyMidletActive(int externalAppId)
Notify the native application manager that the MIDlet is active.

param
externalAppId ID assigned by the external application manager

private static native voidnotifyMidletCreated(int externalAppId)
Notify the native application manager of the MIDlet creation.

param
externalAppId ID assigned by the external application manager

private static native voidnotifyMidletDestroyed(int externalAppId)
Notify the native application manager that the MIDlet is destroyed.

param
externalAppId ID assigned by the external application manager

private static native voidnotifyMidletPaused(int externalAppId)
Notify the native application manager that the MIDlet is paused.

param
externalAppId ID assigned by the external application manager

private static native voidnotifyMidletStartError(int externalAppId, int error)
Notify the native application manager of the MIDlet creation.

param
externalAppId ID assigned by the external application manager
param
error error code

private static native voidnotifyOperationCompleted(int operation, int externalAppId, int retCode)
Notify the native application manager that the system has completed the requested operation and the result (if any) is available.

param
operation code of the operation that has completed
param
externalAppId ID assigned by the external application manager
param
retCode completion code (0 if OK)

private static native voidnotifySuiteTerminated(int suiteId)
Notify the native application manager that the suite is terminated.

param
suiteId ID of the MIDlet suite

private static native voidnotifySystemStart()
Notify the native application manager of the system start up.

private static native voidnotifySystemStartError()
Notify the native application manager that the system had an error starting.

private static native voidnotifySystemSuspended()
Notifies native application manager on MIDP suspension.

public booleanpreprocess(Event event, Event waitingEvent)
Preprocess an event that is being posted to the event queue. This method will get called in the thread that posted the event.

param
event event being posted
param
waitingEvent previous event of this type waiting in the queue to be processed
return
true to allow the post to continue, false to not post the event to the queue

        return true;
    
public voidprocess(Event event)
Process an event. This method will get called in the event queue processing thread.

param
event event to process

        String errorMsg = null;

        NativeEvent nativeEvent = (NativeEvent)event;
        MIDletProxy midlet = midletProxyList.findMIDletProxy(
                                 nativeEvent.intParam1);

        switch (nativeEvent.getType()) {

        case EventTypes.NATIVE_MIDLET_EXECUTE_REQUEST:
            if (midlet == null) {
                if (nativeEvent.intParam2 == MIDletSuite.UNUSED_SUITE_ID) {
                    notifyMidletStartError(nativeEvent.intParam1,
                                           Constants.MIDLET_ID_NOT_GIVEN);
                } else if (nativeEvent.stringParam1 == null) {
                    notifyMidletStartError(nativeEvent.intParam1,
                                           Constants.MIDLET_CLASS_NOT_GIVEN);
                } else {
                    MIDletSuiteUtils.executeWithArgs(internalSecurityToken,
                        nativeEvent.intParam1, nativeEvent.intParam2,
                        nativeEvent.stringParam1, nativeEvent.stringParam2,
                        nativeEvent.stringParam3, nativeEvent.stringParam4,
                        nativeEvent.stringParam5, nativeEvent.intParam3,
                        nativeEvent.intParam4, nativeEvent.intParam5,
                        nativeEvent.stringParam6);
                }
            } else {
                errorMsg = "Only one instance of a MIDlet can be launched";
            }
            break;

        case EventTypes.NATIVE_MIDLET_RESUME_REQUEST:
            if (midlet != null) {
                midlet.activateMidlet();
            } else {
                errorMsg = "Invalid App Id";
            }
            break;

        case EventTypes.NATIVE_MIDLET_PAUSE_REQUEST:
            if (midlet != null) {
                midlet.pauseMidlet();
            } else {
                errorMsg = "Invalid App Id";
            }
            break;

        case EventTypes.NATIVE_MIDLET_DESTROY_REQUEST:
            /*
             * IMPL_NOTE: nativeEvent.intParam2 is a timeout value which
             *            should be passed to MIDletProxy.destroyMidlet().
             *
             */
            if (midlet != null) {
                midlet.destroyMidlet();
            } else {
                errorMsg = "Invalid App Id";
            }
            break;

        case EventTypes.NATIVE_MIDLET_GETINFO_REQUEST:
            int isolateId = midlet.getIsolateId();
            Isolate task = null;
            Isolate[] allTasks = Isolate.getIsolates();

            for (int i = 0; i < allTasks.length; i++) {
                if (allTasks[i].id() == isolateId) {
                    task = allTasks[i];
                    break;
                }
            }

            if (task != null) {
                /* Structure to hold run time information about a midlet. */
                RuntimeInfo runtimeInfo = new RuntimeInfo();

                runtimeInfo.memoryTotal    = task.totalMemory();
                runtimeInfo.memoryReserved = task.reservedMemory();
                runtimeInfo.usedMemory     = task.usedMemory();
                runtimeInfo.priority       = task.getPriority();
                // there is no Isolate API now
                runtimeInfo.profileName    = null;

                saveRuntimeInfoInNative(runtimeInfo);
            }

            notifyOperationCompleted(EventTypes.NATIVE_MIDLET_GETINFO_REQUEST,
                nativeEvent.intParam1, (task == null) ? 1 : 0);
            break;

        case EventTypes.NATIVE_SET_FOREGROUND_REQUEST:
            // Allow Nams to explicitly set nothing to be in the foreground
            // with special AppId 0
            if (midlet != null ||
                nativeEvent.intParam1 == Constants.MIDLET_APPID_NO_FOREGROUND) {
                if (midletProxyList.getForegroundMIDlet() == midlet &&
                        midlet != null) {
                    // send the notification even if the midlet already has
                    // the foreground
                    NativeDisplayControllerPeer.notifyMidletHasForeground(
                        midlet.getExternalAppId());
                } else {
                    midletProxyList.setForegroundMIDlet(midlet);
                }
            } else {
                errorMsg = "Invalid App Id";
            }
            break;

        default:
            errorMsg = "Unknown event type "+event.getType();
            break;
        }

        if (Logging.REPORT_LEVEL <= Logging.ERROR && errorMsg != null) {
            Logging.report(Logging.ERROR, LogChannels.LC_AMS, errorMsg);
        }
    
private voidprocessNativeAppManagerRequests()
Called in the main VM thread to keep the thread alive to until shutdown completes.

        midletProxyList.waitForShutdownToComplete();

        /*
         * Shutdown the event queue gracefully to process any events
         * that may be in the queue currently.
         */
        eventQueue.shutdown();
    
private static native voidregisterAmsIsolateId()
Register the Isolate ID of the AMS Isolate by making a native method call that will call JVM_CurrentIsolateId and set it in the proper native variable.

private static native voidsaveRuntimeInfoInNative(RuntimeInfo runtimeInfo)
Saves runtime information from the given structure into the native buffer.

param
runtimeInfo structure holding the information to save

public voidsuiteTerminated(int suiteId)
Called when a suite isolate is terminated.

param
suiteId ID of the suite

        notifySuiteTerminated(suiteId);