/*
* 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.javame.sensor;
import java.util.Hashtable;
import javax.microedition.sensor.SensorInfo;
import javax.microedition.sensor.DataListener;
import com.sun.midp.events.Event;
import com.sun.midp.events.EventListener;
import com.sun.midp.events.EventQueue;
import com.sun.midp.events.EventTypes;
import com.sun.midp.events.NativeEvent;
import com.sun.midp.security.*;
/**
* This class is a bridge between native event callbacks and
* {@link AvailabilityListener} callbacks. The current implementation of
* SensorDevice does not know anything about SensorInfo to which it belongs to,
* so we must register them in the {@link Configurator} factory.
*/
final class NativeSensorRegistry {
/** Maps native sensor id to the SensorInfo. */
private static final Hashtable ID_INFO_MAP = new Hashtable();
/** Maps native sensor id to the AvailabilityListener. */
private static final Hashtable ID_LISTENER_MAP = new Hashtable();
/** Event queue instance. */
private static final EventQueue eventQueue;
/** Code operation table: smallest code. */
static final int EVENT_SMALLEST_CODE = 1;
/** Code operation table: aviability listener code. */
static final int EVENT_AV_LISTENER_CODE = EVENT_SMALLEST_CODE;
/** Code operation table: data collect code. */
static final int EVENT_DATA_COLLECT_CODE = EVENT_SMALLEST_CODE + 1;
/** Code operation table: highest code. */
static final int EVENT_HIGHEST_CODE = EVENT_DATA_COLLECT_CODE;
/** Native event listener. */
private static final EventListener EVENT_LISTENER = new EventListener() {
public boolean preprocess(Event evtNew, Event evtOld) {
boolean retV = (evtNew instanceof NativeEvent);
if (retV) {
int codeOp = ((NativeEvent)evtNew).intParam1;
retV = (EVENT_SMALLEST_CODE <= codeOp && codeOp <= EVENT_HIGHEST_CODE);
}
return retV;
}
public void process(Event evt) {
if (evt instanceof NativeEvent) {
NativeEvent nativeEvt = (NativeEvent) evt;
int codeOp = nativeEvt.intParam1;
switch(codeOp) {
case EVENT_AV_LISTENER_CODE: // aviability listener
processAvListEvent(nativeEvt);
break;
case EVENT_DATA_COLLECT_CODE: // start collecting data
processDataCollectEvent(nativeEvt);
break;
}
}
}
private void processAvListEvent(NativeEvent nativeEvt) {
Integer sensorType = new Integer(nativeEvt.intParam2);
boolean available = (nativeEvt.intParam3 == 1);
AvailabilityListener listener;
synchronized (ID_LISTENER_MAP) {
listener = (AvailabilityListener) ID_LISTENER_MAP
.get(sensorType);
}
if (listener != null) {
SensorInfo info;
synchronized (ID_INFO_MAP) {
info = (SensorInfo) ID_INFO_MAP.get(sensorType);
}
listener.notifyAvailability(info, available);
}
}
private void processDataCollectEvent(NativeEvent nativeEvt) {
Sensor sensor = SensorRegistry.getSensor(nativeEvt.intParam2);
if (sensor != null) {
ChannelDevice device = sensor.getChannelDevice(nativeEvt.intParam3);
if (device != null) {
ValueListener listener;
if ((listener = device.getListener()) != null) {
new Thread(new RunGetData(device, listener, nativeEvt.intParam3)).start();
}
}
}
}
};
/**
* Inner class to request security token from SecurityInitializer.
* SecurityInitializer should be able to check this inner class name.
*/
static private class SecurityTrusted
implements ImplicitlyTrustedClass {};
static {
/** Security token to allow access to implementation APIs */
SecurityToken classSecurityToken =
SecurityInitializer.requestToken(new SecurityTrusted());
eventQueue = EventQueue.getEventQueue(classSecurityToken);
// Register EVENT_LISTENER with SENSOR_EVENT type
eventQueue.registerEventListener(
EventTypes.SENSOR_EVENT, EVENT_LISTENER);
}
/** Prevents instantiation. */
private NativeSensorRegistry() {
}
/**
* Register the {@link SensorDevice} with {@link SensorInfo}.
*
* @param device SensorDevice instance
* @param info SensorInfo instance
*/
static void register(SensorDevice device, SensorInfo info) {
synchronized (ID_INFO_MAP) {
ID_INFO_MAP.put(new Integer(device.numberSensor), info);
}
}
/**
* Posts an event to queue.
*
* @param codeOp code operation
* @param param1 parameter 1
* @param param2 parameter 2
* @param param3 parameter 3
*/
static void postSensorEvent(int codeOp, int param1, int param2, int param3) {
NativeEvent event = new NativeEvent(EventTypes.SENSOR_EVENT);
event.intParam1 = codeOp;
event.intParam2 = param1;
event.intParam3 = param2;
event.intParam4 = param3;
eventQueue.post(event);
}
/**
* Start monitoring the activity change callbacks from native layer.
*
* @param sensorType id of the native sensor
* @param listener AvailabilityListener callback listener
*/
static void startMonitoringAvailability(int sensorType,
AvailabilityListener listener) {
synchronized (ID_LISTENER_MAP) {
ID_LISTENER_MAP.put(new Integer(sensorType), listener);
}
doStartMonitoringAvailability(sensorType);
}
/**
* Stop monitoring the activity change callbacks from native layer.
*
* @param sensorType the native sensor id
*/
static void stopMonitoringAvailability(int sensorType) {
doStopMonitoringAvailability(sensorType);
synchronized (ID_LISTENER_MAP) {
ID_LISTENER_MAP.remove(new Integer(sensorType));
}
}
/**
* Start monitoring the activity change events in native layer.
* <p>
* <i>calls javacall_sensor_start_monitor_availability(sensor)</i>
*
* @param sensorType the native sensor id
* @return true on success false otherwise
*/
private static native boolean doStartMonitoringAvailability(int sensorType);
/**
* Stop monitoring the activity change events in native layer.
* <p>
* <i>calls javacall_sensor_stop_monitor_availability(sensor)</i>
*
* @param sensorType the native sensor id
* @return true on success false otherwise
*/
private static native boolean doStopMonitoringAvailability(int sensorType);
}
class RunGetData implements Runnable {
ChannelDevice device;
ValueListener listener;
int numChannel;
RunGetData(ChannelDevice device, ValueListener listener, int numChannel) {
this.device = device;
this.listener = listener;
this.numChannel = numChannel;
}
public void run() {
int errorCode = device.measureData();
if (errorCode == ValueListener.DATA_READ_OK) {
//Data listener
listener.valueReceived(numChannel,
device.getData(), device.getUncertainty(),
device.getValidity());
} else {
listener.dataReadError(numChannel, errorCode);
}
}
}