Merge "new SensorService" into gingerbread
diff --git a/Android.mk b/Android.mk
index 69a40c1..5db6610 100644
--- a/Android.mk
+++ b/Android.mk
@@ -113,7 +113,6 @@
core/java/android/content/pm/IPackageMoveObserver.aidl \
core/java/android/content/pm/IPackageStatsObserver.aidl \
core/java/android/database/IContentObserver.aidl \
- core/java/android/hardware/ISensorService.aidl \
core/java/android/net/IConnectivityManager.aidl \
core/java/android/net/INetworkManagementEventObserver.aidl \
core/java/android/net/IThrottleManager.aidl \
diff --git a/cmds/system_server/library/Android.mk b/cmds/system_server/library/Android.mk
index a880a91..457cbd4 100644
--- a/cmds/system_server/library/Android.mk
+++ b/cmds/system_server/library/Android.mk
@@ -10,11 +10,13 @@
$(base)/services/camera/libcameraservice \
$(base)/services/audioflinger \
$(base)/services/surfaceflinger \
+ $(base)/services/sensorservice \
$(base)/media/libmediaplayerservice \
$(JNI_H_INCLUDE)
LOCAL_SHARED_LIBRARIES := \
libandroid_runtime \
+ libsensorservice \
libsurfaceflinger \
libaudioflinger \
libcameraservice \
diff --git a/cmds/system_server/library/system_init.cpp b/cmds/system_server/library/system_init.cpp
index 1d57fdc..a29ba73 100644
--- a/cmds/system_server/library/system_init.cpp
+++ b/cmds/system_server/library/system_init.cpp
@@ -19,6 +19,7 @@
#include <CameraService.h>
#include <AudioPolicyService.h>
#include <MediaPlayerService.h>
+#include <SensorService.h>
#include <android_runtime/AndroidRuntime.h>
@@ -69,6 +70,9 @@
SurfaceFlinger::instantiate();
}
+ // Start the sensor service
+ SensorService::instantiate();
+
// On the simulator, audioflinger et al don't get started the
// same way as on the device, and we need to start them here
if (!proc->supportsProcesses()) {
diff --git a/core/java/android/hardware/ISensorService.aidl b/core/java/android/hardware/ISensorService.aidl
deleted file mode 100644
index 67180bd..0000000
--- a/core/java/android/hardware/ISensorService.aidl
+++ /dev/null
@@ -1,29 +0,0 @@
-/* //device/java/android/android/hardware/ISensorService.aidl
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.hardware;
-
-import android.os.Bundle;
-
-/**
- * {@hide}
- */
-interface ISensorService
-{
- Bundle getDataChannel();
- boolean enableSensor(IBinder listener, String name, int sensor, int enable);
-}
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index 492f8cc..e6750e6 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -16,12 +16,7 @@
package android.hardware;
-import android.content.Context;
-import android.os.Binder;
-import android.os.Bundle;
import android.os.Looper;
-import android.os.Parcelable;
-import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
import android.os.Handler;
@@ -33,8 +28,6 @@
import android.view.IWindowManager;
import android.view.Surface;
-import java.io.FileDescriptor;
-import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -339,7 +332,6 @@
/*-----------------------------------------------------------------------*/
- private ISensorService mSensorService;
Looper mMainLooper;
@SuppressWarnings("deprecation")
private HashMap<SensorListener, LegacyListener> mLegacyListenersMap =
@@ -356,6 +348,7 @@
/* The thread and the sensor list are global to the process
* but the actual thread is spawned on demand */
private static SensorThread sSensorThread;
+ private static int sQueue;
// Used within this module from outside SensorManager, don't make private
static SparseArray<Sensor> sHandleToSensor = new SparseArray<Sensor>();
@@ -370,80 +363,41 @@
boolean mSensorsReady;
SensorThread() {
- // this gets to the sensor module. We can have only one per process.
- sensors_data_init();
}
@Override
protected void finalize() {
- sensors_data_uninit();
}
// must be called with sListeners lock
- boolean startLocked(ISensorService service) {
+ boolean startLocked() {
try {
if (mThread == null) {
- Bundle dataChannel = service.getDataChannel();
- if (dataChannel != null) {
- mSensorsReady = false;
- SensorThreadRunnable runnable = new SensorThreadRunnable(dataChannel);
- Thread thread = new Thread(runnable, SensorThread.class.getName());
- thread.start();
- synchronized (runnable) {
- while (mSensorsReady == false) {
- runnable.wait();
- }
+ mSensorsReady = false;
+ SensorThreadRunnable runnable = new SensorThreadRunnable();
+ Thread thread = new Thread(runnable, SensorThread.class.getName());
+ thread.start();
+ synchronized (runnable) {
+ while (mSensorsReady == false) {
+ runnable.wait();
}
- mThread = thread;
}
+ mThread = thread;
}
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException in startLocked: ", e);
} catch (InterruptedException e) {
}
return mThread == null ? false : true;
}
private class SensorThreadRunnable implements Runnable {
- private Bundle mDataChannel;
- SensorThreadRunnable(Bundle dataChannel) {
- mDataChannel = dataChannel;
+ SensorThreadRunnable() {
}
private boolean open() {
// NOTE: this cannot synchronize on sListeners, since
// it's held in the main thread at least until we
// return from here.
-
- // this thread is guaranteed to be unique
- Parcelable[] pfds = mDataChannel.getParcelableArray("fds");
- FileDescriptor[] fds;
- if (pfds != null) {
- int length = pfds.length;
- fds = new FileDescriptor[length];
- for (int i = 0; i < length; i++) {
- ParcelFileDescriptor pfd = (ParcelFileDescriptor)pfds[i];
- fds[i] = pfd.getFileDescriptor();
- }
- } else {
- fds = null;
- }
- int[] ints = mDataChannel.getIntArray("ints");
- sensors_data_open(fds, ints);
- if (pfds != null) {
- try {
- // close our copies of the file descriptors,
- // since we are just passing these to the JNI code and not using them here.
- for (int i = pfds.length - 1; i >= 0; i--) {
- ParcelFileDescriptor pfd = (ParcelFileDescriptor)pfds[i];
- pfd.close();
- }
- } catch (IOException e) {
- // *shrug*
- Log.e(TAG, "IOException: ", e);
- }
- }
- mDataChannel = null;
+ sQueue = sensors_create_queue();
return true;
}
@@ -466,7 +420,7 @@
while (true) {
// wait for an event
- final int sensor = sensors_data_poll(values, status, timestamp);
+ final int sensor = sensors_data_poll(sQueue, values, status, timestamp);
int accuracy = status[0];
synchronized (sListeners) {
@@ -478,7 +432,8 @@
}
// we have no more listeners or polling failed, terminate the thread
- sensors_data_close();
+ sensors_destroy_queue(sQueue);
+ sQueue = 0;
mThread = null;
break;
}
@@ -506,7 +461,7 @@
/*-----------------------------------------------------------------------*/
- private class ListenerDelegate extends Binder {
+ private class ListenerDelegate {
final SensorEventListener mSensorEventListener;
private final ArrayList<Sensor> mSensorList = new ArrayList<Sensor>();
private final Handler mHandler;
@@ -602,8 +557,6 @@
* {@hide}
*/
public SensorManager(Looper mainLooper) {
- mSensorService = ISensorService.Stub.asInterface(
- ServiceManager.getService(Context.SENSOR_SERVICE));
mMainLooper = mainLooper;
@@ -1051,42 +1004,37 @@
return false;
}
- try {
- synchronized (sListeners) {
- ListenerDelegate l = null;
- for (ListenerDelegate i : sListeners) {
- if (i.getListener() == listener) {
- l = i;
- break;
- }
- }
-
- String name = sensor.getName();
- int handle = sensor.getHandle();
- if (l == null) {
- result = false;
- l = new ListenerDelegate(listener, sensor, handler);
- sListeners.add(l);
- if (!sListeners.isEmpty()) {
- result = sSensorThread.startLocked(mSensorService);
- if (result) {
- result = mSensorService.enableSensor(l, name, handle, delay);
- if (!result) {
- // there was an error, remove the listeners
- sListeners.remove(l);
- }
- }
- }
- } else {
- result = mSensorService.enableSensor(l, name, handle, delay);
- if (result) {
- l.addSensor(sensor);
- }
+ synchronized (sListeners) {
+ ListenerDelegate l = null;
+ for (ListenerDelegate i : sListeners) {
+ if (i.getListener() == listener) {
+ l = i;
+ break;
}
}
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException in registerListener: ", e);
- result = false;
+
+ String name = sensor.getName();
+ int handle = sensor.getHandle();
+ if (l == null) {
+ result = false;
+ l = new ListenerDelegate(listener, sensor, handler);
+ sListeners.add(l);
+ if (!sListeners.isEmpty()) {
+ result = sSensorThread.startLocked();
+ if (result) {
+ result = sensors_enable_sensor(sQueue, name, handle, delay);
+ if (!result) {
+ // there was an error, remove the listeners
+ sListeners.remove(l);
+ }
+ }
+ }
+ } else {
+ result = sensors_enable_sensor(sQueue, name, handle, delay);
+ if (result) {
+ l.addSensor(sensor);
+ }
+ }
}
return result;
}
@@ -1095,27 +1043,23 @@
if (listener == null || sensor == null) {
return;
}
- try {
- synchronized (sListeners) {
- final int size = sListeners.size();
- for (int i=0 ; i<size ; i++) {
- ListenerDelegate l = sListeners.get(i);
- if (l.getListener() == listener) {
- // disable these sensors
- String name = sensor.getName();
- int handle = sensor.getHandle();
- mSensorService.enableSensor(l, name, handle, SENSOR_DISABLE);
- // if we have no more sensors enabled on this listener,
- // take it off the list.
- if (l.removeSensor(sensor) == 0) {
- sListeners.remove(i);
- }
- break;
+ synchronized (sListeners) {
+ final int size = sListeners.size();
+ for (int i=0 ; i<size ; i++) {
+ ListenerDelegate l = sListeners.get(i);
+ if (l.getListener() == listener) {
+ // disable these sensors
+ String name = sensor.getName();
+ int handle = sensor.getHandle();
+ sensors_enable_sensor(sQueue, name, handle, SENSOR_DISABLE);
+ // if we have no more sensors enabled on this listener,
+ // take it off the list.
+ if (l.removeSensor(sensor) == 0) {
+ sListeners.remove(i);
}
+ break;
}
}
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException in unregisterListener: ", e);
}
}
@@ -1123,25 +1067,21 @@
if (listener == null) {
return;
}
- try {
- synchronized (sListeners) {
- final int size = sListeners.size();
- for (int i=0 ; i<size ; i++) {
- ListenerDelegate l = sListeners.get(i);
- if (l.getListener() == listener) {
- // disable all sensors for this listener
- for (Sensor sensor : l.getSensors()) {
- String name = sensor.getName();
- int handle = sensor.getHandle();
- mSensorService.enableSensor(l, name, handle, SENSOR_DISABLE);
- }
- sListeners.remove(i);
- break;
+ synchronized (sListeners) {
+ final int size = sListeners.size();
+ for (int i=0 ; i<size ; i++) {
+ ListenerDelegate l = sListeners.get(i);
+ if (l.getListener() == listener) {
+ // disable all sensors for this listener
+ for (Sensor sensor : l.getSensors()) {
+ String name = sensor.getName();
+ int handle = sensor.getHandle();
+ sensors_enable_sensor(sQueue, name, handle, SENSOR_DISABLE);
}
+ sListeners.remove(i);
+ break;
}
}
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException in unregisterListener: ", e);
}
}
@@ -1794,9 +1734,8 @@
private static native int sensors_module_get_next_sensor(Sensor sensor, int next);
// Used within this module from outside SensorManager, don't make private
- static native int sensors_data_init();
- static native int sensors_data_uninit();
- static native int sensors_data_open(FileDescriptor[] fds, int[] ints);
- static native int sensors_data_close();
- static native int sensors_data_poll(float[] values, int[] status, long[] timestamp);
+ static native int sensors_create_queue();
+ static native void sensors_destroy_queue(int queue);
+ static native boolean sensors_enable_sensor(int queue, String name, int sensor, int enable);
+ static native int sensors_data_poll(int queue, float[] values, int[] status, long[] timestamp);
}
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 89fea41..5c37c7c 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -168,6 +168,7 @@
libbinder \
libnetutils \
libui \
+ libgui \
libsurfaceflinger_client \
libcamera_client \
libskiagl \
diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp
index 9a90b72..232c8af 100644
--- a/core/jni/android_hardware_SensorManager.cpp
+++ b/core/jni/android_hardware_SensorManager.cpp
@@ -18,8 +18,9 @@
#include "utils/Log.h"
-#include <hardware/sensors.h>
-#include <cutils/native_handle.h>
+#include <gui/Sensor.h>
+#include <gui/SensorManager.h>
+#include <gui/SensorEventQueue.h>
#include "jni.h"
#include "JNIHelp.h"
@@ -43,44 +44,36 @@
* The method below are not thread-safe and not intended to be
*/
-static sensors_module_t* sSensorModule = 0;
-static sensors_data_device_t* sSensorDevice = 0;
static jint
sensors_module_init(JNIEnv *env, jclass clazz)
{
- int err = 0;
- sensors_module_t const* module;
- err = hw_get_module(SENSORS_HARDWARE_MODULE_ID, (const hw_module_t **)&module);
- if (err == 0)
- sSensorModule = (sensors_module_t*)module;
- return err;
+ SensorManager::getInstance();
+ return 0;
}
static jint
sensors_module_get_next_sensor(JNIEnv *env, jobject clazz, jobject sensor, jint next)
{
- if (sSensorModule == NULL)
- return 0;
+ SensorManager& mgr(SensorManager::getInstance());
- SensorOffsets& sensorOffsets = gSensorOffsets;
- const struct sensor_t* list;
- int count = sSensorModule->get_sensors_list(sSensorModule, &list);
+ Sensor const* const* sensorList;
+ size_t count = mgr.getSensorList(&sensorList);
if (next >= count)
return -1;
- list += next;
-
- jstring name = env->NewStringUTF(list->name);
- jstring vendor = env->NewStringUTF(list->vendor);
+ Sensor const* const list = sensorList[next];
+ const SensorOffsets& sensorOffsets(gSensorOffsets);
+ jstring name = env->NewStringUTF(list->getName().string());
+ jstring vendor = env->NewStringUTF(list->getVendor().string());
env->SetObjectField(sensor, sensorOffsets.name, name);
env->SetObjectField(sensor, sensorOffsets.vendor, vendor);
- env->SetIntField(sensor, sensorOffsets.version, list->version);
- env->SetIntField(sensor, sensorOffsets.handle, list->handle);
- env->SetIntField(sensor, sensorOffsets.type, list->type);
- env->SetFloatField(sensor, sensorOffsets.range, list->maxRange);
- env->SetFloatField(sensor, sensorOffsets.resolution, list->resolution);
- env->SetFloatField(sensor, sensorOffsets.power, list->power);
+ env->SetIntField(sensor, sensorOffsets.version, 1);
+ env->SetIntField(sensor, sensorOffsets.handle, list->getHandle());
+ env->SetIntField(sensor, sensorOffsets.type, list->getType());
+ env->SetFloatField(sensor, sensorOffsets.range, list->getMaxValue());
+ env->SetFloatField(sensor, sensorOffsets.resolution, list->getResolution());
+ env->SetFloatField(sensor, sensorOffsets.power, list->getPowerUsage());
next++;
return next<count ? next : 0;
@@ -88,75 +81,64 @@
//----------------------------------------------------------------------------
static jint
-sensors_data_init(JNIEnv *env, jclass clazz)
+sensors_create_queue(JNIEnv *env, jclass clazz)
{
- if (sSensorModule == NULL)
- return -1;
- int err = sensors_data_open(&sSensorModule->common, &sSensorDevice);
- return err;
+ SensorManager& mgr(SensorManager::getInstance());
+ sp<SensorEventQueue> queue(mgr.createEventQueue());
+ queue->incStrong(clazz);
+ return reinterpret_cast<int>(queue.get());
}
-static jint
-sensors_data_uninit(JNIEnv *env, jclass clazz)
+static void
+sensors_destroy_queue(JNIEnv *env, jclass clazz, jint nativeQueue)
{
- int err = 0;
- if (sSensorDevice) {
- err = sensors_data_close(sSensorDevice);
- if (err == 0)
- sSensorDevice = 0;
+ sp<SensorEventQueue> queue(reinterpret_cast<SensorEventQueue *>(nativeQueue));
+ if (queue != 0) {
+ queue->decStrong(clazz);
}
- return err;
}
-static jint
-sensors_data_open(JNIEnv *env, jclass clazz, jobjectArray fdArray, jintArray intArray)
+static jboolean
+sensors_enable_sensor(JNIEnv *env, jclass clazz,
+ jint nativeQueue, jstring name, jint sensor, jint enable)
{
- jclass FileDescriptor = env->FindClass("java/io/FileDescriptor");
- jfieldID fieldOffset = env->GetFieldID(FileDescriptor, "descriptor", "I");
- int numFds = (fdArray ? env->GetArrayLength(fdArray) : 0);
- int numInts = (intArray ? env->GetArrayLength(intArray) : 0);
- native_handle_t* handle = native_handle_create(numFds, numInts);
- int offset = 0;
-
- for (int i = 0; i < numFds; i++) {
- jobject fdo = env->GetObjectArrayElement(fdArray, i);
- if (fdo) {
- handle->data[offset++] = env->GetIntField(fdo, fieldOffset);
- } else {
- handle->data[offset++] = -1;
- }
+ sp<SensorEventQueue> queue(reinterpret_cast<SensorEventQueue *>(nativeQueue));
+ if (queue == 0) return JNI_FALSE;
+ status_t res;
+ if (enable) {
+ res = queue->enableSensor(sensor);
+ } else {
+ res = queue->disableSensor(sensor);
}
- if (numInts > 0) {
- jint* ints = env->GetIntArrayElements(intArray, 0);
- for (int i = 0; i < numInts; i++) {
- handle->data[offset++] = ints[i];
- }
- env->ReleaseIntArrayElements(intArray, ints, 0);
- }
-
- // doesn't take ownership of the native handle
- return sSensorDevice->data_open(sSensorDevice, handle);
+ return res == NO_ERROR ? true : false;
}
static jint
-sensors_data_close(JNIEnv *env, jclass clazz)
-{
- return sSensorDevice->data_close(sSensorDevice);
-}
-
-static jint
-sensors_data_poll(JNIEnv *env, jclass clazz,
+sensors_data_poll(JNIEnv *env, jclass clazz, jint nativeQueue,
jfloatArray values, jintArray status, jlongArray timestamp)
{
- sensors_data_t data;
- int res = sSensorDevice->poll(sSensorDevice, &data);
- if (res >= 0) {
- jint accuracy = data.vector.status;
- env->SetFloatArrayRegion(values, 0, 3, data.vector.v);
- env->SetIntArrayRegion(status, 0, 1, &accuracy);
- env->SetLongArrayRegion(timestamp, 0, 1, &data.time);
+ sp<SensorEventQueue> queue(reinterpret_cast<SensorEventQueue *>(nativeQueue));
+ if (queue == 0) return -1;
+
+ status_t res;
+ ASensorEvent event;
+
+ res = queue->read(&event, 1);
+ if (res == -EAGAIN) {
+ res = queue->waitForEvent();
+ if (res != NO_ERROR)
+ return -1;
+ res = queue->read(&event, 1);
}
- return res;
+ if (res < 0)
+ return -1;
+
+ jint accuracy = event.vector.status;
+ env->SetFloatArrayRegion(values, 0, 3, event.vector.v);
+ env->SetIntArrayRegion(status, 0, 1, &accuracy);
+ env->SetLongArrayRegion(timestamp, 0, 1, &event.timestamp);
+
+ return event.sensor;
}
static void
@@ -179,11 +161,13 @@
{"sensors_module_init","()I", (void*)sensors_module_init },
{"sensors_module_get_next_sensor","(Landroid/hardware/Sensor;I)I",
(void*)sensors_module_get_next_sensor },
- {"sensors_data_init", "()I", (void*)sensors_data_init },
- {"sensors_data_uninit", "()I", (void*)sensors_data_uninit },
- {"sensors_data_open", "([Ljava/io/FileDescriptor;[I)I", (void*)sensors_data_open },
- {"sensors_data_close", "()I", (void*)sensors_data_close },
- {"sensors_data_poll", "([F[I[J)I", (void*)sensors_data_poll },
+
+ {"sensors_create_queue", "()I", (void*)sensors_create_queue },
+ {"sensors_destroy_queue", "(I)V", (void*)sensors_destroy_queue },
+ {"sensors_enable_sensor", "(ILjava/lang/String;II)Z",
+ (void*)sensors_enable_sensor },
+
+ {"sensors_data_poll", "(I[F[I[J)I", (void*)sensors_data_poll },
};
}; // namespace android
diff --git a/include/gui/ISensorServer.h b/include/gui/ISensorServer.h
index 3e05076..9c8afc5 100644
--- a/include/gui/ISensorServer.h
+++ b/include/gui/ISensorServer.h
@@ -36,7 +36,7 @@
public:
DECLARE_META_INTERFACE(SensorServer);
- virtual Vector<Sensor> getSensorList()= 0;
+ virtual Vector<Sensor> getSensorList() = 0;
virtual sp<ISensorEventConnection> createSensorEventConnection() = 0;
};
diff --git a/include/gui/Sensor.h b/include/gui/Sensor.h
index 86a16f1..e696d63 100644
--- a/include/gui/Sensor.h
+++ b/include/gui/Sensor.h
@@ -51,7 +51,8 @@
TYPE_PROXIMITY = ASENSOR_TYPE_PROXIMITY
};
- Sensor();
+ Sensor();
+ Sensor(struct sensor_t const* hwSensor);
virtual ~Sensor();
const String8& getName() const;
diff --git a/include/gui/SensorEventQueue.h b/include/gui/SensorEventQueue.h
index d8d8128..bb03c12 100644
--- a/include/gui/SensorEventQueue.h
+++ b/include/gui/SensorEventQueue.h
@@ -42,6 +42,7 @@
class ISensorEventConnection;
class Sensor;
+class PollLoop;
// ----------------------------------------------------------------------------
@@ -56,13 +57,21 @@
ssize_t write(ASensorEvent const* events, size_t numEvents);
ssize_t read(ASensorEvent* events, size_t numEvents);
+ status_t waitForEvent() const;
+ status_t wake() const;
+
status_t enableSensor(Sensor const* sensor) const;
status_t disableSensor(Sensor const* sensor) const;
+ status_t enableSensor(int32_t handle) const;
+ status_t disableSensor(int32_t handle) const;
status_t setEventRate(Sensor const* sensor, nsecs_t ns) const;
private:
+ sp<PollLoop> getPollLoop() const;
sp<ISensorEventConnection> mSensorEventConnection;
sp<SensorChannel> mSensorChannel;
+ mutable Mutex mLock;
+ mutable sp<PollLoop> mPollLoop;
};
// ----------------------------------------------------------------------------
diff --git a/include/gui/SensorManager.h b/include/gui/SensorManager.h
index 0d65334..e1b1a7be 100644
--- a/include/gui/SensorManager.h
+++ b/include/gui/SensorManager.h
@@ -47,13 +47,13 @@
SensorManager();
~SensorManager();
- ssize_t getSensorList(Sensor**) const;
- Sensor* getDefaultSensor(int type);
+ ssize_t getSensorList(Sensor const* const** list) const;
+ Sensor const* getDefaultSensor(int type);
sp<SensorEventQueue> createEventQueue();
private:
sp<ISensorServer> mSensorServer;
- Sensor* mSensorList;
+ Sensor const** mSensorList;
Vector<Sensor> mSensors;
};
diff --git a/libs/gui/ISensorEventConnection.cpp b/libs/gui/ISensorEventConnection.cpp
index 3e9d456..a5083fe 100644
--- a/libs/gui/ISensorEventConnection.cpp
+++ b/libs/gui/ISensorEventConnection.cpp
@@ -47,6 +47,7 @@
virtual sp<SensorChannel> getSensorChannel() const
{
Parcel data, reply;
+ data.writeInterfaceToken(ISensorEventConnection::getInterfaceDescriptor());
remote()->transact(GET_SENSOR_CHANNEL, data, &reply);
return new SensorChannel(reply);
}
@@ -54,6 +55,7 @@
virtual status_t enableDisable(int handle, bool enabled)
{
Parcel data, reply;
+ data.writeInterfaceToken(ISensorEventConnection::getInterfaceDescriptor());
data.writeInt32(handle);
data.writeInt32(enabled);
remote()->transact(ENABLE_DISABLE, data, &reply);
@@ -63,6 +65,7 @@
virtual status_t setEventRate(int handle, nsecs_t ns)
{
Parcel data, reply;
+ data.writeInterfaceToken(ISensorEventConnection::getInterfaceDescriptor());
data.writeInt32(handle);
data.writeInt64(ns);
remote()->transact(SET_EVENT_RATE, data, &reply);
diff --git a/libs/gui/ISensorServer.cpp b/libs/gui/ISensorServer.cpp
index c6177bc..7111092 100644
--- a/libs/gui/ISensorServer.cpp
+++ b/libs/gui/ISensorServer.cpp
@@ -48,6 +48,7 @@
virtual Vector<Sensor> getSensorList()
{
Parcel data, reply;
+ data.writeInterfaceToken(ISensorServer::getInterfaceDescriptor());
remote()->transact(GET_SENSOR_LIST, data, &reply);
Sensor s;
Vector<Sensor> v;
@@ -63,6 +64,7 @@
virtual sp<ISensorEventConnection> createSensorEventConnection()
{
Parcel data, reply;
+ data.writeInterfaceToken(ISensorServer::getInterfaceDescriptor());
remote()->transact(CREATE_SENSOR_EVENT_CONNECTION, data, &reply);
return interface_cast<ISensorEventConnection>(reply.readStrongBinder());
}
diff --git a/libs/gui/Sensor.cpp b/libs/gui/Sensor.cpp
index 1fdd285..48e1cb7 100644
--- a/libs/gui/Sensor.cpp
+++ b/libs/gui/Sensor.cpp
@@ -36,6 +36,18 @@
{
}
+Sensor::Sensor(struct sensor_t const* hwSensor)
+{
+ mName = hwSensor->name;
+ mVendor = hwSensor->vendor;
+ mHandle = hwSensor->handle;
+ mType = hwSensor->type;
+ mMinValue = 0; // FIXME: minValue
+ mMaxValue = hwSensor->maxRange; // FIXME: maxValue
+ mResolution = hwSensor->resolution;
+ mPower = hwSensor->power;
+}
+
Sensor::~Sensor()
{
}
diff --git a/libs/gui/SensorEventQueue.cpp b/libs/gui/SensorEventQueue.cpp
index f922ac4..cc98656 100644
--- a/libs/gui/SensorEventQueue.cpp
+++ b/libs/gui/SensorEventQueue.cpp
@@ -13,11 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
+#define LOG_TAG "Sensors"
+
#include <stdint.h>
#include <sys/types.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
+#include <utils/PollLoop.h>
#include <gui/Sensor.h>
#include <gui/SensorChannel.h>
@@ -68,7 +72,7 @@
ssize_t size = mSensorChannel->read(events, numEvents*sizeof(events[0]));
if (size >= 0) {
if (size % sizeof(events[0])) {
- // partial write!!! should never happen.
+ // partial read!!! should never happen.
return -EINVAL;
}
// returns number of events read
@@ -77,18 +81,48 @@
return size;
}
-status_t SensorEventQueue::enableSensor(Sensor const* sensor) const
+sp<PollLoop> SensorEventQueue::getPollLoop() const
{
+ Mutex::Autolock _l(mLock);
+ if (mPollLoop == 0) {
+ mPollLoop = new PollLoop(true);
+ mPollLoop->setCallback(getFd(), POLLIN, NULL, NULL);
+ }
+ return mPollLoop;
+}
+
+status_t SensorEventQueue::waitForEvent() const
+{
+ const int fd = getFd();
+ sp<PollLoop> pollLoop(getPollLoop());
+ int32_t result = pollLoop->pollOnce(-1, NULL, NULL);
+ return (result == fd) ? NO_ERROR : -1;
+}
+
+status_t SensorEventQueue::wake() const
+{
+ sp<PollLoop> pollLoop(getPollLoop());
+ pollLoop->wake();
+ return NO_ERROR;
+}
+
+status_t SensorEventQueue::enableSensor(Sensor const* sensor) const {
return mSensorEventConnection->enableDisable(sensor->getHandle(), true);
}
-status_t SensorEventQueue::disableSensor(Sensor const* sensor) const
-{
+status_t SensorEventQueue::disableSensor(Sensor const* sensor) const {
return mSensorEventConnection->enableDisable(sensor->getHandle(), false);
}
-status_t SensorEventQueue::setEventRate(Sensor const* sensor, nsecs_t ns) const
-{
+status_t SensorEventQueue::enableSensor(int32_t handle) const {
+ return mSensorEventConnection->enableDisable(handle, true);
+}
+
+status_t SensorEventQueue::disableSensor(int32_t handle) const {
+ return mSensorEventConnection->enableDisable(handle, false);
+}
+
+status_t SensorEventQueue::setEventRate(Sensor const* sensor, nsecs_t ns) const {
return mSensorEventConnection->setEventRate(sensor->getHandle(), ns);
}
diff --git a/libs/gui/SensorManager.cpp b/libs/gui/SensorManager.cpp
index cd89285..d719efb 100644
--- a/libs/gui/SensorManager.cpp
+++ b/libs/gui/SensorManager.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#define LOG_TAG "Sensors"
+
#include <stdint.h>
#include <sys/types.h>
@@ -21,6 +23,8 @@
#include <utils/RefBase.h>
#include <utils/Singleton.h>
+#include <binder/IServiceManager.h>
+
#include <gui/ISensorServer.h>
#include <gui/ISensorEventConnection.h>
#include <gui/Sensor.h>
@@ -36,25 +40,40 @@
SensorManager::SensorManager()
: mSensorList(0)
{
+ const String16 name("sensorservice");
+ while (getService(name, &mSensorServer) != NO_ERROR) {
+ usleep(250000);
+ }
+
mSensors = mSensorServer->getSensorList();
- // TODO: needs implementation
+ size_t count = mSensors.size();
+ mSensorList = (Sensor const**)malloc(count * sizeof(Sensor*));
+ for (size_t i=0 ; i<count ; i++) {
+ mSensorList[i] = mSensors.array() + i;
+ }
}
SensorManager::~SensorManager()
{
- // TODO: needs implementation
+ free(mSensorList);
}
-ssize_t SensorManager::getSensorList(Sensor** list) const
+ssize_t SensorManager::getSensorList(Sensor const* const** list) const
{
*list = mSensorList;
return mSensors.size();
}
-Sensor* SensorManager::getDefaultSensor(int type)
+Sensor const* SensorManager::getDefaultSensor(int type)
{
- // TODO: needs implementation
- return mSensorList;
+ // For now we just return the first sensor of that type we find.
+ // in the future it will make sense to let the SensorService make
+ // that decision.
+ for (size_t i=0 ; i<mSensors.size() ; i++) {
+ if (mSensorList[i]->getType() == type)
+ return mSensorList[i];
+ }
+ return NULL;
}
sp<SensorEventQueue> SensorManager::createEventQueue()
diff --git a/native/android/sensor.cpp b/native/android/sensor.cpp
index 7a3907e..e1fc4e7 100644
--- a/native/android/sensor.cpp
+++ b/native/android/sensor.cpp
@@ -43,17 +43,18 @@
return &SensorManager::getInstance();
}
-int ASensorManager_getSensorList(ASensorManager* manager, ASensor** list)
+int ASensorManager_getSensorList(ASensorManager* manager,
+ ASensorList* list)
{
- Sensor* l;
+ Sensor const* const* l;
int c = static_cast<SensorManager*>(manager)->getSensorList(&l);
if (list) {
- *list = l;
+ *list = reinterpret_cast<ASensorList>(l);
}
return c;
}
-ASensor* ASensorManager_getDefaultSensor(ASensorManager* manager, int type)
+ASensor const* ASensorManager_getDefaultSensor(ASensorManager* manager, int type)
{
return static_cast<SensorManager*>(manager)->getDefaultSensor(type);
}
@@ -82,23 +83,23 @@
/*****************************************************************************/
-int ASensorEventQueue_enableSensor(ASensorEventQueue* queue, ASensor* sensor)
+int ASensorEventQueue_enableSensor(ASensorEventQueue* queue, ASensor const* sensor)
{
return static_cast<SensorEventQueue*>(queue)->enableSensor(
- static_cast<Sensor*>(sensor));
+ static_cast<Sensor const*>(sensor));
}
-int ASensorEventQueue_disableSensor(ASensorEventQueue* queue, ASensor* sensor)
+int ASensorEventQueue_disableSensor(ASensorEventQueue* queue, ASensor const* sensor)
{
return static_cast<SensorEventQueue*>(queue)->disableSensor(
- static_cast<Sensor*>(sensor));
+ static_cast<Sensor const*>(sensor));
}
-int ASensorEventQueue_setEventRate(ASensorEventQueue* queue, ASensor* sensor,
+int ASensorEventQueue_setEventRate(ASensorEventQueue* queue, ASensor const* sensor,
int32_t usec)
{
return static_cast<SensorEventQueue*>(queue)->setEventRate(
- static_cast<Sensor*>(sensor), us2ns(usec));
+ static_cast<Sensor const*>(sensor), us2ns(usec));
}
int ASensorEventQueue_hasEvents(ASensorEventQueue* queue)
@@ -128,23 +129,23 @@
/*****************************************************************************/
-const char* ASensor_getName(ASensor* sensor)
+const char* ASensor_getName(ASensor const* sensor)
{
- return static_cast<Sensor*>(sensor)->getName().string();
+ return static_cast<Sensor const*>(sensor)->getName().string();
}
-const char* ASensor_getVendor(ASensor* sensor)
+const char* ASensor_getVendor(ASensor const* sensor)
{
- return static_cast<Sensor*>(sensor)->getVendor().string();
+ return static_cast<Sensor const*>(sensor)->getVendor().string();
}
-int ASensor_getType(ASensor* sensor)
+int ASensor_getType(ASensor const* sensor)
{
- return static_cast<Sensor*>(sensor)->getType();
+ return static_cast<Sensor const*>(sensor)->getType();
}
-float ASensor_getResolution(ASensor* sensor)
+float ASensor_getResolution(ASensor const* sensor)
{
- return static_cast<Sensor*>(sensor)->getResolution();
+ return static_cast<Sensor const*>(sensor)->getResolution();
}
diff --git a/native/include/android/sensor.h b/native/include/android/sensor.h
index 4291d3e..00d95d8 100644
--- a/native/include/android/sensor.h
+++ b/native/include/android/sensor.h
@@ -87,6 +87,7 @@
* A sensor event.
*/
+/* NOTE: Must match hardware/sensors.h */
typedef struct ASensorVector {
union {
float v[3];
@@ -95,23 +96,32 @@
float y;
float z;
};
+ struct {
+ float azimuth;
+ float pitch;
+ float roll;
+ };
};
int8_t status;
uint8_t reserved[3];
} ASensorVector;
+/* NOTE: Must match hardware/sensors.h */
typedef struct ASensorEvent {
- int sensor;
+ int32_t version; /* sizeof(struct ASensorEvent) */
+ int32_t sensor;
+ int32_t type;
int32_t reserved0;
+ int64_t timestamp;
union {
float data[16];
+ ASensorVector vector;
ASensorVector acceleration;
ASensorVector magnetic;
float temperature;
float distance;
float light;
};
- int64_t timestamp;
int32_t reserved1[4];
} ASensorEvent;
@@ -124,6 +134,8 @@
struct ASensor;
typedef struct ASensor ASensor;
+typedef ASensor const* ASensorRef;
+typedef ASensorRef const* ASensorList;
/*****************************************************************************/
@@ -141,13 +153,13 @@
/*
* Returns the list of available sensors.
*/
-int ASensorManager_getSensorList(ASensorManager* manager, ASensor** list);
+int ASensorManager_getSensorList(ASensorManager* manager, ASensorList* list);
/*
* Returns the default sensor for the given type, or NULL if no sensor
* of that type exist.
*/
-ASensor* ASensorManager_getDefaultSensor(ASensorManager* manager, int type);
+ASensor const* ASensorManager_getDefaultSensor(ASensorManager* manager, int type);
/*
* Creates a new sensor event queue and associate it with a looper.
@@ -166,12 +178,12 @@
/*
* Enable the selected sensor. Returns a negative error code on failure.
*/
-int ASensorEventQueue_enableSensor(ASensorEventQueue* queue, ASensor* sensor);
+int ASensorEventQueue_enableSensor(ASensorEventQueue* queue, ASensor const* sensor);
/*
* Disable the selected sensor. Returns a negative error code on failure.
*/
-int ASensorEventQueue_disableSensor(ASensorEventQueue* queue, ASensor* sensor);
+int ASensorEventQueue_disableSensor(ASensorEventQueue* queue, ASensor const* sensor);
/*
* Sets the delivery rate of events in microseconds for the given sensor.
@@ -179,7 +191,7 @@
* rate.
* Returns a negative error code on failure.
*/
-int ASensorEventQueue_setEventRate(ASensorEventQueue* queue, ASensor* sensor, int32_t usec);
+int ASensorEventQueue_setEventRate(ASensorEventQueue* queue, ASensor const* sensor, int32_t usec);
/*
* Returns true if there are one or more events available in the
@@ -210,22 +222,22 @@
/*
* Returns this sensor's name (non localized)
*/
-const char* ASensor_getName(ASensor* sensor);
+const char* ASensor_getName(ASensor const* sensor);
/*
* Returns this sensor's vendor's name (non localized)
*/
-const char* ASensor_getVendor(ASensor* sensor);
+const char* ASensor_getVendor(ASensor const* sensor);
/*
* Return this sensor's type
*/
-int ASensor_getType(ASensor* sensor);
+int ASensor_getType(ASensor const* sensor);
/*
* Returns this sensors's resolution
*/
-float ASensor_getResolution(ASensor* sensor);
+float ASensor_getResolution(ASensor const* sensor);
#ifdef __cplusplus
diff --git a/services/java/com/android/server/SensorService.java b/services/java/com/android/server/SensorService.java
deleted file mode 100644
index 9f5718f..0000000
--- a/services/java/com/android/server/SensorService.java
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server;
-
-import android.content.Context;
-import android.hardware.ISensorService;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.os.IBinder;
-import android.util.Config;
-import android.util.Slog;
-import android.util.PrintWriterPrinter;
-import android.util.Printer;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-
-import com.android.internal.app.IBatteryStats;
-import com.android.server.am.BatteryStatsService;
-
-
-/**
- * Class that manages the device's sensors. It register clients and activate
- * the needed sensors. The sensor events themselves are not broadcasted from
- * this service, instead, a file descriptor is provided to each client they
- * can read events from.
- */
-
-class SensorService extends ISensorService.Stub {
- static final String TAG = SensorService.class.getSimpleName();
- private static final boolean DEBUG = false;
- private static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
- private static final int SENSOR_DISABLE = -1;
- private int mCurrentDelay = 0;
-
- /**
- * Battery statistics to be updated when sensors are enabled and disabled.
- */
- final IBatteryStats mBatteryStats = BatteryStatsService.getService();
-
- private final class Listener implements IBinder.DeathRecipient {
- final IBinder mToken;
- final int mUid;
-
- int mSensors = 0;
- int mDelay = 0x7FFFFFFF;
-
- Listener(IBinder token, int uid) {
- mToken = token;
- mUid = uid;
- }
-
- void addSensor(int sensor, int delay) {
- mSensors |= (1<<sensor);
- if (delay < mDelay)
- mDelay = delay;
- }
-
- void removeSensor(int sensor) {
- mSensors &= ~(1<<sensor);
- }
-
- boolean hasSensor(int sensor) {
- return ((mSensors & (1<<sensor)) != 0);
- }
-
- public void binderDied() {
- if (localLOGV) Slog.d(TAG, "sensor listener died");
- synchronized(mListeners) {
- mListeners.remove(this);
- mToken.unlinkToDeath(this, 0);
- // go through the lists of sensors used by the listener that
- // died and deactivate them.
- for (int sensor=0 ; sensor<32 && mSensors!=0 ; sensor++) {
- if (hasSensor(sensor)) {
- removeSensor(sensor);
- deactivateIfUnusedLocked(sensor);
- try {
- mBatteryStats.noteStopSensor(mUid, sensor);
- } catch (RemoteException e) {
- // oops. not a big deal.
- }
- }
- }
- if (mListeners.size() == 0) {
- _sensors_control_wake();
- _sensors_control_close();
- } else {
- // TODO: we should recalculate the delay, since removing
- // a listener may increase the overall rate.
- }
- mListeners.notify();
- }
- }
- }
-
- @SuppressWarnings("unused")
- public SensorService(Context context) {
- if (localLOGV) Slog.d(TAG, "SensorService startup");
- _sensors_control_init();
- }
-
- public Bundle getDataChannel() throws RemoteException {
- // synchronize so we do not require sensor HAL to be thread-safe.
- synchronized(mListeners) {
- return _sensors_control_open();
- }
- }
-
- public boolean enableSensor(IBinder binder, String name, int sensor, int enable)
- throws RemoteException {
-
- if (localLOGV) Slog.d(TAG, "enableSensor " + name + "(#" + sensor + ") " + enable);
-
- if (binder == null) {
- Slog.e(TAG, "listener is null (sensor=" + name + ", id=" + sensor + ")");
- return false;
- }
-
- if (enable < 0 && (enable != SENSOR_DISABLE)) {
- Slog.e(TAG, "invalid enable parameter (enable=" + enable +
- ", sensor=" + name + ", id=" + sensor + ")");
- return false;
- }
-
- boolean res;
- int uid = Binder.getCallingUid();
- synchronized(mListeners) {
- res = enableSensorInternalLocked(binder, uid, name, sensor, enable);
- if (res == true) {
- // Inform battery statistics service of status change
- long identity = Binder.clearCallingIdentity();
- if (enable == SENSOR_DISABLE) {
- mBatteryStats.noteStopSensor(uid, sensor);
- } else {
- mBatteryStats.noteStartSensor(uid, sensor);
- }
- Binder.restoreCallingIdentity(identity);
- }
- }
- return res;
- }
-
- private boolean enableSensorInternalLocked(IBinder binder, int uid,
- String name, int sensor, int enable) throws RemoteException {
-
- // check if we have this listener
- Listener l = null;
- for (Listener listener : mListeners) {
- if (binder == listener.mToken) {
- l = listener;
- break;
- }
- }
-
- if (enable != SENSOR_DISABLE) {
- // Activate the requested sensor
- if (_sensors_control_activate(sensor, true) == false) {
- Slog.w(TAG, "could not enable sensor " + sensor);
- return false;
- }
-
- if (l == null) {
- /*
- * we don't have a listener for this binder yet, so
- * create a new one and add it to the list.
- */
- l = new Listener(binder, uid);
- binder.linkToDeath(l, 0);
- mListeners.add(l);
- mListeners.notify();
- }
-
- // take note that this sensor is now used by this client
- l.addSensor(sensor, enable);
-
- } else {
-
- if (l == null) {
- /*
- * This client isn't in the list, this usually happens
- * when enabling the sensor failed, but the client
- * didn't handle the error and later tries to shut that
- * sensor off.
- */
- Slog.w(TAG, "listener with binder " + binder +
- ", doesn't exist (sensor=" + name +
- ", id=" + sensor + ")");
- return false;
- }
-
- // remove this sensor from this client
- l.removeSensor(sensor);
-
- // see if we need to deactivate this sensors=
- deactivateIfUnusedLocked(sensor);
-
- // if the listener doesn't have any more sensors active
- // we can get rid of it
- if (l.mSensors == 0) {
- // we won't need this death notification anymore
- binder.unlinkToDeath(l, 0);
- // remove the listener from the list
- mListeners.remove(l);
- // and if the list is empty, turn off the whole sensor h/w
- if (mListeners.size() == 0) {
- _sensors_control_wake();
- _sensors_control_close();
- }
- mListeners.notify();
- }
- }
-
- // calculate and set the new delay
- int minDelay = 0x7FFFFFFF;
- for (Listener listener : mListeners) {
- if (listener.mDelay < minDelay)
- minDelay = listener.mDelay;
- }
- if (minDelay != 0x7FFFFFFF) {
- mCurrentDelay = minDelay;
- _sensors_control_set_delay(minDelay);
- }
-
- return true;
- }
-
- private void deactivateIfUnusedLocked(int sensor) {
- int size = mListeners.size();
- for (int i=0 ; i<size ; i++) {
- if (mListeners.get(i).hasSensor(sensor)) {
- // this sensor is still in use, don't turn it off
- return;
- }
- }
- if (_sensors_control_activate(sensor, false) == false) {
- Slog.w(TAG, "could not disable sensor " + sensor);
- }
- }
-
- @Override
- protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- synchronized (mListeners) {
- Printer pr = new PrintWriterPrinter(pw);
- int c = 0;
- pr.println(mListeners.size() + " listener(s), delay=" + mCurrentDelay + " ms");
- for (Listener l : mListeners) {
- pr.println("listener[" + c + "] " +
- "sensors=0x" + Integer.toString(l.mSensors, 16) +
- ", uid=" + l.mUid +
- ", delay=" +
- l.mDelay + " ms");
- c++;
- }
- }
- }
-
- private ArrayList<Listener> mListeners = new ArrayList<Listener>();
-
- private static native int _sensors_control_init();
- private static native Bundle _sensors_control_open();
- private static native int _sensors_control_close();
- private static native boolean _sensors_control_activate(int sensor, boolean activate);
- private static native int _sensors_control_set_delay(int ms);
- private static native int _sensors_control_wake();
-}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index c01680e..ab869bb 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -165,10 +165,6 @@
Watchdog.getInstance().init(context, battery, power, alarm,
ActivityManagerService.self());
- // Sensor Service is needed by Window Manager, so this goes first
- Slog.i(TAG, "Sensor Service");
- ServiceManager.addService(Context.SENSOR_SERVICE, new SensorService(context));
-
Slog.i(TAG, "Window Manager");
wm = WindowManagerService.main(context, power,
factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL);
diff --git a/services/jni/Android.mk b/services/jni/Android.mk
index 0cf36b3..cdc0a6f 100644
--- a/services/jni/Android.mk
+++ b/services/jni/Android.mk
@@ -7,7 +7,6 @@
com_android_server_InputManager.cpp \
com_android_server_LightsService.cpp \
com_android_server_PowerManagerService.cpp \
- com_android_server_SensorService.cpp \
com_android_server_SystemServer.cpp \
com_android_server_VibratorService.cpp \
com_android_server_location_GpsLocationProvider.cpp \
diff --git a/services/jni/com_android_server_SensorService.cpp b/services/jni/com_android_server_SensorService.cpp
deleted file mode 100644
index 77db6da..0000000
--- a/services/jni/com_android_server_SensorService.cpp
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright 2008, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "SensorService"
-
-#include "utils/Log.h"
-
-#include <hardware/sensors.h>
-
-#include "jni.h"
-#include "JNIHelp.h"
-
-namespace android {
-
-static struct file_descriptor_offsets_t
-{
- jclass mClass;
- jmethodID mConstructor;
- jfieldID mDescriptor;
-} gFileDescriptorOffsets;
-
-static struct parcel_file_descriptor_offsets_t
-{
- jclass mClass;
- jmethodID mConstructor;
-} gParcelFileDescriptorOffsets;
-
-static struct bundle_descriptor_offsets_t
-{
- jclass mClass;
- jmethodID mConstructor;
- jmethodID mPutIntArray;
- jmethodID mPutParcelableArray;
-} gBundleOffsets;
-
-/*
- * The method below are not thread-safe and not intended to be
- */
-
-static sensors_control_device_t* sSensorDevice = 0;
-
-static jint
-android_init(JNIEnv *env, jclass clazz)
-{
- sensors_module_t* module;
- if (hw_get_module(SENSORS_HARDWARE_MODULE_ID, (const hw_module_t**)&module) == 0) {
- if (sensors_control_open(&module->common, &sSensorDevice) == 0) {
- const struct sensor_t* list;
- int count = module->get_sensors_list(module, &list);
- return count;
- }
- }
- return 0;
-}
-
-static jobject
-android_open(JNIEnv *env, jclass clazz)
-{
- native_handle_t* handle = sSensorDevice->open_data_source(sSensorDevice);
- if (!handle) {
- return NULL;
- }
-
- // new Bundle()
- jobject bundle = env->NewObject(
- gBundleOffsets.mClass,
- gBundleOffsets.mConstructor);
-
- if (handle->numFds > 0) {
- jobjectArray fdArray = env->NewObjectArray(handle->numFds,
- gParcelFileDescriptorOffsets.mClass, NULL);
- for (int i = 0; i < handle->numFds; i++) {
- // new FileDescriptor()
- jobject fd = env->NewObject(gFileDescriptorOffsets.mClass,
- gFileDescriptorOffsets.mConstructor);
- env->SetIntField(fd, gFileDescriptorOffsets.mDescriptor, handle->data[i]);
- // new ParcelFileDescriptor()
- jobject pfd = env->NewObject(gParcelFileDescriptorOffsets.mClass,
- gParcelFileDescriptorOffsets.mConstructor, fd);
- env->SetObjectArrayElement(fdArray, i, pfd);
- }
- // bundle.putParcelableArray("fds", fdArray);
- env->CallVoidMethod(bundle, gBundleOffsets.mPutParcelableArray,
- env->NewStringUTF("fds"), fdArray);
- }
-
- if (handle->numInts > 0) {
- jintArray intArray = env->NewIntArray(handle->numInts);
- env->SetIntArrayRegion(intArray, 0, handle->numInts, &handle->data[handle->numInts]);
- // bundle.putIntArray("ints", intArray);
- env->CallVoidMethod(bundle, gBundleOffsets.mPutIntArray,
- env->NewStringUTF("ints"), intArray);
- }
-
- // delete the file handle, but don't close any file descriptors
- native_handle_delete(handle);
- return bundle;
-}
-
-static jint
-android_close(JNIEnv *env, jclass clazz)
-{
- if (sSensorDevice->close_data_source)
- return sSensorDevice->close_data_source(sSensorDevice);
- else
- return 0;
-}
-
-static jboolean
-android_activate(JNIEnv *env, jclass clazz, jint sensor, jboolean activate)
-{
- int active = sSensorDevice->activate(sSensorDevice, sensor, activate);
- return (active<0) ? false : true;
-}
-
-static jint
-android_set_delay(JNIEnv *env, jclass clazz, jint ms)
-{
- return sSensorDevice->set_delay(sSensorDevice, ms);
-}
-
-static jint
-android_data_wake(JNIEnv *env, jclass clazz)
-{
- int res = sSensorDevice->wake(sSensorDevice);
- return res;
-}
-
-
-static JNINativeMethod gMethods[] = {
- {"_sensors_control_init", "()I", (void*) android_init },
- {"_sensors_control_open", "()Landroid/os/Bundle;", (void*) android_open },
- {"_sensors_control_close", "()I", (void*) android_close },
- {"_sensors_control_activate", "(IZ)Z", (void*) android_activate },
- {"_sensors_control_wake", "()I", (void*) android_data_wake },
- {"_sensors_control_set_delay","(I)I", (void*) android_set_delay },
-};
-
-int register_android_server_SensorService(JNIEnv *env)
-{
- jclass clazz;
-
- clazz = env->FindClass("java/io/FileDescriptor");
- gFileDescriptorOffsets.mClass = (jclass)env->NewGlobalRef(clazz);
- gFileDescriptorOffsets.mConstructor = env->GetMethodID(clazz, "<init>", "()V");
- gFileDescriptorOffsets.mDescriptor = env->GetFieldID(clazz, "descriptor", "I");
-
- clazz = env->FindClass("android/os/ParcelFileDescriptor");
- gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
- gParcelFileDescriptorOffsets.mConstructor = env->GetMethodID(clazz, "<init>",
- "(Ljava/io/FileDescriptor;)V");
-
- clazz = env->FindClass("android/os/Bundle");
- gBundleOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
- gBundleOffsets.mConstructor = env->GetMethodID(clazz, "<init>", "()V");
- gBundleOffsets.mPutIntArray = env->GetMethodID(clazz, "putIntArray", "(Ljava/lang/String;[I)V");
- gBundleOffsets.mPutParcelableArray = env->GetMethodID(clazz, "putParcelableArray",
- "(Ljava/lang/String;[Landroid/os/Parcelable;)V");
-
- return jniRegisterNativeMethods(env, "com/android/server/SensorService",
- gMethods, NELEM(gMethods));
-}
-
-}; // namespace android
diff --git a/services/jni/onload.cpp b/services/jni/onload.cpp
index 1a2d8b6..cd4f0a4 100644
--- a/services/jni/onload.cpp
+++ b/services/jni/onload.cpp
@@ -9,7 +9,6 @@
int register_android_server_InputManager(JNIEnv* env);
int register_android_server_LightsService(JNIEnv* env);
int register_android_server_PowerManagerService(JNIEnv* env);
-int register_android_server_SensorService(JNIEnv* env);
int register_android_server_VibratorService(JNIEnv* env);
int register_android_server_SystemServer(JNIEnv* env);
int register_android_server_location_GpsLocationProvider(JNIEnv* env);
@@ -33,7 +32,6 @@
register_android_server_LightsService(env);
register_android_server_AlarmManagerService(env);
register_android_server_BatteryService(env);
- register_android_server_SensorService(env);
register_android_server_VibratorService(env);
register_android_server_SystemServer(env);
register_android_server_location_GpsLocationProvider(env);
diff --git a/services/sensorservice/Android.mk b/services/sensorservice/Android.mk
new file mode 100644
index 0000000..75f690f
--- /dev/null
+++ b/services/sensorservice/Android.mk
@@ -0,0 +1,28 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ SensorService.cpp
+
+LOCAL_CFLAGS:= -DLOG_TAG=\"SensorService\"
+
+# need "-lrt" on Linux simulator to pick up clock_gettime
+ifeq ($(TARGET_SIMULATOR),true)
+ ifeq ($(HOST_OS),linux)
+ LOCAL_LDLIBS += -lrt -lpthread
+ endif
+endif
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils \
+ libhardware \
+ libutils \
+ libbinder \
+ libui \
+ libgui
+
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_MODULE:= libsensorservice
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
new file mode 100644
index 0000000..5410cbc
--- /dev/null
+++ b/services/sensorservice/SensorService.cpp
@@ -0,0 +1,359 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/SortedVector.h>
+#include <utils/KeyedVector.h>
+#include <utils/threads.h>
+#include <utils/Atomic.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+
+#include <binder/BinderService.h>
+
+#include <gui/ISensorServer.h>
+#include <gui/ISensorEventConnection.h>
+
+#include <hardware/sensors.h>
+
+#include "SensorService.h"
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+/*
+ * TODO:
+ * - handle per-connection event rate
+ * - filter events per connection
+ * - make sure to keep the last value of each event type so we can quickly
+ * send something to application when they enable a sensor that is already
+ * active (the issue here is that it can take time before a value is
+ * produced by the h/w if the rate is low or if it's a one-shot sensor).
+ */
+
+SensorService::SensorService()
+ : Thread(false),
+ mDump("android.permission.DUMP")
+{
+}
+
+void SensorService::onFirstRef()
+{
+ status_t err = hw_get_module(SENSORS_HARDWARE_MODULE_ID,
+ (hw_module_t const**)&mSensorModule);
+
+ LOGE_IF(err, "couldn't load %s module (%s)",
+ SENSORS_HARDWARE_MODULE_ID, strerror(-err));
+
+ err = sensors_open(&mSensorModule->common, &mSensorDevice);
+
+ LOGE_IF(err, "couldn't open device for module %s (%s)",
+ SENSORS_HARDWARE_MODULE_ID, strerror(-err));
+
+ LOGD("nuSensorService starting...");
+
+ struct sensor_t const* list;
+ int count = mSensorModule->get_sensors_list(mSensorModule, &list);
+ for (int i=0 ; i<count ; i++) {
+ Sensor sensor(list + i);
+ LOGI("%s", sensor.getName().string());
+ mSensorList.add(sensor);
+ mSensorDevice->activate(mSensorDevice, sensor.getHandle(), 0);
+ }
+
+ run("SensorService", PRIORITY_URGENT_DISPLAY);
+}
+
+SensorService::~SensorService()
+{
+}
+
+status_t SensorService::dump(int fd, const Vector<String16>& args)
+{
+ const size_t SIZE = 1024;
+ char buffer[SIZE];
+ String8 result;
+ if (!mDump.checkCalling()) {
+ snprintf(buffer, SIZE, "Permission Denial: "
+ "can't dump SurfaceFlinger from pid=%d, uid=%d\n",
+ IPCThreadState::self()->getCallingPid(),
+ IPCThreadState::self()->getCallingUid());
+ result.append(buffer);
+ } else {
+ Mutex::Autolock _l(mLock);
+ snprintf(buffer, SIZE, "%d connections / %d active\n",
+ mConnections.size(), mActiveConnections.size());
+ result.append(buffer);
+ snprintf(buffer, SIZE, "Active sensors:\n");
+ result.append(buffer);
+ for (size_t i=0 ; i<mActiveSensors.size() ; i++) {
+ snprintf(buffer, SIZE, "handle=%d, connections=%d\n",
+ mActiveSensors.keyAt(i),
+ mActiveSensors.valueAt(i)->getNumConnections());
+ result.append(buffer);
+ }
+ }
+ write(fd, result.string(), result.size());
+ return NO_ERROR;
+}
+
+bool SensorService::threadLoop()
+{
+ LOGD("nuSensorService thread starting...");
+
+ sensors_event_t buffer[16];
+ struct sensors_poll_device_t* device = mSensorDevice;
+ ssize_t count;
+
+ do {
+ count = device->poll(device, buffer, sizeof(buffer)/sizeof(*buffer));
+ if (count<0) {
+ LOGE("sensor poll failed (%s)", strerror(-count));
+ break;
+ }
+
+ const SortedVector< wp<SensorEventConnection> > activeConnections(
+ getActiveConnections());
+
+ size_t numConnections = activeConnections.size();
+ if (numConnections) {
+ for (size_t i=0 ; i<numConnections ; i++) {
+ sp<SensorEventConnection> connection(activeConnections[i].promote());
+ if (connection != 0) {
+ connection->sendEvents(buffer, count);
+ }
+ }
+ }
+
+ } while (count >= 0 || Thread::exitPending());
+
+ LOGW("Exiting SensorService::threadLoop!");
+ return false;
+}
+
+SortedVector< wp<SensorService::SensorEventConnection> >
+SensorService::getActiveConnections() const
+{
+ Mutex::Autolock _l(mLock);
+ return mActiveConnections;
+}
+
+Vector<Sensor> SensorService::getSensorList()
+{
+ return mSensorList;
+}
+
+sp<ISensorEventConnection> SensorService::createSensorEventConnection()
+{
+ sp<SensorEventConnection> result(new SensorEventConnection(this));
+ Mutex::Autolock _l(mLock);
+ mConnections.add(result);
+ return result;
+}
+
+void SensorService::cleanupConnection(const wp<SensorEventConnection>& connection)
+{
+ Mutex::Autolock _l(mLock);
+ ssize_t index = mConnections.indexOf(connection);
+ if (index >= 0) {
+
+ size_t size = mActiveSensors.size();
+ for (size_t i=0 ; i<size ; ) {
+ SensorRecord* rec = mActiveSensors.valueAt(i);
+ if (rec && rec->removeConnection(connection)) {
+ mSensorDevice->activate(mSensorDevice, mActiveSensors.keyAt(i), 0);
+ mActiveSensors.removeItemsAt(i, 1);
+ delete rec;
+ size--;
+ } else {
+ i++;
+ }
+ }
+
+ mActiveConnections.remove(connection);
+ mConnections.removeItemsAt(index, 1);
+ }
+}
+
+status_t SensorService::enable(const sp<SensorEventConnection>& connection,
+ int handle)
+{
+ status_t err = NO_ERROR;
+ Mutex::Autolock _l(mLock);
+ SensorRecord* rec = mActiveSensors.valueFor(handle);
+ if (rec == 0) {
+ rec = new SensorRecord(connection);
+ mActiveSensors.add(handle, rec);
+ err = mSensorDevice->activate(mSensorDevice, handle, 1);
+ LOGE_IF(err, "Error activating sensor %d (%s)", handle, strerror(-err));
+ } else {
+ err = rec->addConnection(connection);
+ }
+ if (err == NO_ERROR) {
+ // connection now active
+ connection->addSensor(handle);
+ if (mActiveConnections.indexOf(connection) < 0) {
+ mActiveConnections.add(connection);
+ }
+ }
+ return err;
+}
+
+status_t SensorService::disable(const sp<SensorEventConnection>& connection,
+ int handle)
+{
+ status_t err = NO_ERROR;
+ Mutex::Autolock _l(mLock);
+ SensorRecord* rec = mActiveSensors.valueFor(handle);
+ LOGW("sensor (handle=%d) is not enabled", handle);
+ if (rec) {
+ // see if this connection becomes inactive
+ connection->removeSensor(handle);
+ if (connection->hasAnySensor() == false) {
+ mActiveConnections.remove(connection);
+ }
+ // see if this sensor becomes inactive
+ if (rec->removeConnection(connection)) {
+ mActiveSensors.removeItem(handle);
+ delete rec;
+ err = mSensorDevice->activate(mSensorDevice, handle, 0);
+ }
+ }
+ return err;
+}
+
+status_t SensorService::setRate(const sp<SensorEventConnection>& connection,
+ int handle, nsecs_t ns)
+{
+ status_t err = NO_ERROR;
+ Mutex::Autolock _l(mLock);
+
+ err = mSensorDevice->setDelay(mSensorDevice, handle, ns);
+
+ // TODO: handle rate per connection
+ return err;
+}
+
+// ---------------------------------------------------------------------------
+
+SensorService::SensorRecord::SensorRecord(
+ const sp<SensorEventConnection>& connection)
+{
+ mConnections.add(connection);
+}
+
+status_t SensorService::SensorRecord::addConnection(
+ const sp<SensorEventConnection>& connection)
+{
+ if (mConnections.indexOf(connection) < 0) {
+ mConnections.add(connection);
+ }
+ return NO_ERROR;
+}
+
+bool SensorService::SensorRecord::removeConnection(
+ const wp<SensorEventConnection>& connection)
+{
+ ssize_t index = mConnections.indexOf(connection);
+ if (index >= 0) {
+ mConnections.removeItemsAt(index, 1);
+ }
+ return mConnections.size() ? false : true;
+}
+
+// ---------------------------------------------------------------------------
+
+SensorService::SensorEventConnection::SensorEventConnection(
+ const sp<SensorService>& service)
+ : mService(service), mChannel(new SensorChannel())
+{
+}
+
+SensorService::SensorEventConnection::~SensorEventConnection()
+{
+ mService->cleanupConnection(this);
+}
+
+void SensorService::SensorEventConnection::onFirstRef()
+{
+}
+
+void SensorService::SensorEventConnection::addSensor(int32_t handle) {
+ if (mSensorList.indexOf(handle) <= 0) {
+ mSensorList.add(handle);
+ }
+}
+
+void SensorService::SensorEventConnection::removeSensor(int32_t handle) {
+ mSensorList.remove(handle);
+}
+
+bool SensorService::SensorEventConnection::hasSensor(int32_t handle) const {
+ return mSensorList.indexOf(handle) >= 0;
+}
+
+bool SensorService::SensorEventConnection::hasAnySensor() const {
+ return mSensorList.size() ? true : false;
+}
+
+status_t SensorService::SensorEventConnection::sendEvents(
+ sensors_event_t const* buffer, size_t count)
+{
+ // TODO: we should only send the events for the sensors this connection
+ // is registered for.
+
+ ssize_t size = mChannel->write(buffer, count*sizeof(sensors_event_t));
+ if (size == -EAGAIN) {
+ // the destination doesn't accept events anymore, it's probably
+ // full. For now, we just drop the events on the floor.
+ LOGW("dropping %d events on the floor", count);
+ return size;
+ }
+
+ LOGE_IF(size<0, "dropping %d events on the floor (%s)",
+ count, strerror(-size));
+
+ return size < 0 ? size : NO_ERROR;
+}
+
+sp<SensorChannel> SensorService::SensorEventConnection::getSensorChannel() const
+{
+ return mChannel;
+}
+
+status_t SensorService::SensorEventConnection::enableDisable(
+ int handle, bool enabled)
+{
+ status_t err;
+ if (enabled) {
+ err = mService->enable(this, handle);
+ } else {
+ err = mService->disable(this, handle);
+ }
+ return err;
+}
+
+status_t SensorService::SensorEventConnection::setEventRate(
+ int handle, nsecs_t ns)
+{
+ return mService->setRate(this, handle, ns);
+}
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
new file mode 100644
index 0000000..d5e321ce
--- /dev/null
+++ b/services/sensorservice/SensorService.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SENSOR_SERVICE_H
+#define ANDROID_SENSOR_SERVICE_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Vector.h>
+#include <utils/SortedVector.h>
+#include <utils/KeyedVector.h>
+#include <utils/threads.h>
+#include <utils/RefBase.h>
+
+#include <binder/BinderService.h>
+#include <binder/Permission.h>
+
+#include <gui/Sensor.h>
+#include <gui/SensorChannel.h>
+#include <gui/ISensorServer.h>
+#include <gui/ISensorEventConnection.h>
+
+// ---------------------------------------------------------------------------
+
+struct sensors_poll_device_t;
+struct sensors_module_t;
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+class SensorService :
+ public BinderService<SensorService>,
+ public BnSensorServer,
+ protected Thread
+{
+ friend class BinderService<SensorService>;
+
+ SensorService();
+ virtual ~SensorService();
+
+ virtual void onFirstRef();
+
+ // Thread interface
+ virtual bool threadLoop();
+
+ // ISensorServer interface
+ virtual Vector<Sensor> getSensorList();
+ virtual sp<ISensorEventConnection> createSensorEventConnection();
+ virtual status_t dump(int fd, const Vector<String16>& args);
+
+
+ class SensorEventConnection : public BnSensorEventConnection {
+ virtual sp<SensorChannel> getSensorChannel() const;
+ virtual status_t enableDisable(int handle, bool enabled);
+ virtual status_t setEventRate(int handle, nsecs_t ns);
+ sp<SensorService> const mService;
+ sp<SensorChannel> const mChannel;
+ SortedVector<int32_t> mSensorList;
+ public:
+ SensorEventConnection(const sp<SensorService>& service);
+ virtual ~SensorEventConnection();
+ virtual void onFirstRef();
+ status_t sendEvents(sensors_event_t const* buffer, size_t count);
+ bool hasSensor(int32_t handle) const;
+ bool hasAnySensor() const;
+ void addSensor(int32_t handle);
+ void removeSensor(int32_t handle);
+ };
+
+ class SensorRecord {
+ SortedVector< wp<SensorEventConnection> > mConnections;
+ public:
+ SensorRecord(const sp<SensorEventConnection>& connection);
+ status_t addConnection(const sp<SensorEventConnection>& connection);
+ bool removeConnection(const wp<SensorEventConnection>& connection);
+ size_t getNumConnections() const { return mConnections.size(); }
+ };
+
+ SortedVector< wp<SensorEventConnection> > getActiveConnections() const;
+
+ // constants
+ Vector<Sensor> mSensorList;
+ struct sensors_poll_device_t* mSensorDevice;
+ struct sensors_module_t* mSensorModule;
+ Permission mDump;
+
+ // protected by mLock
+ mutable Mutex mLock;
+ SortedVector< wp<SensorEventConnection> > mConnections;
+ DefaultKeyedVector<int, SensorRecord*> mActiveSensors;
+ SortedVector< wp<SensorEventConnection> > mActiveConnections;
+
+public:
+ static char const* getServiceName() { return "sensorservice"; }
+
+ void cleanupConnection(const wp<SensorEventConnection>& connection);
+ status_t enable(const sp<SensorEventConnection>& connection, int handle);
+ status_t disable(const sp<SensorEventConnection>& connection, int handle);
+ status_t setRate(const sp<SensorEventConnection>& connection, int handle, nsecs_t ns);
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_SENSOR_SERVICE_H
diff --git a/services/sensorservice/tests/Android.mk b/services/sensorservice/tests/Android.mk
new file mode 100644
index 0000000..45296dd
--- /dev/null
+++ b/services/sensorservice/tests/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ sensorservicetest.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils libutils libui libgui
+
+LOCAL_MODULE:= test-sensorservice
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_EXECUTABLE)
diff --git a/services/sensorservice/tests/sensorservicetest.cpp b/services/sensorservice/tests/sensorservicetest.cpp
new file mode 100644
index 0000000..e464713
--- /dev/null
+++ b/services/sensorservice/tests/sensorservicetest.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/sensor.h>
+#include <gui/Sensor.h>
+#include <gui/SensorManager.h>
+#include <gui/SensorEventQueue.h>
+#include <utils/PollLoop.h>
+
+using namespace android;
+
+bool receiver(int fd, int events, void* data)
+{
+ sp<SensorEventQueue> q((SensorEventQueue*)data);
+ ssize_t n;
+ ASensorEvent buffer[8];
+ while ((n = q->read(buffer, 8)) > 0) {
+ for (int i=0 ; i<n ; i++) {
+ if (buffer[i].type == Sensor::TYPE_ACCELEROMETER) {
+ printf("time=%lld, value=<%5.1f,%5.1f,%5.1f>\n",
+ buffer[i].timestamp,
+ buffer[i].acceleration.x,
+ buffer[i].acceleration.y,
+ buffer[i].acceleration.z);
+ }
+ }
+ }
+ if (n<0 && n != -EAGAIN) {
+ printf("error reading events (%s)\n", strerror(-n));
+ }
+ return true;
+}
+
+
+int main(int argc, char** argv)
+{
+ SensorManager& mgr(SensorManager::getInstance());
+
+ Sensor const* const* list;
+ ssize_t count = mgr.getSensorList(&list);
+ printf("numSensors=%d\n", count);
+
+ sp<SensorEventQueue> q = mgr.createEventQueue();
+ printf("queue=%p\n", q.get());
+
+ Sensor const* accelerometer = mgr.getDefaultSensor(Sensor::TYPE_ACCELEROMETER);
+ printf("accelerometer=%p (%s)\n",
+ accelerometer, accelerometer->getName().string());
+ q->enableSensor(accelerometer);
+
+ q->setEventRate(accelerometer, ms2ns(10));
+
+ sp<PollLoop> loop = new PollLoop(false);
+ loop->setCallback(q->getFd(), POLLIN, receiver, q.get());
+
+ do {
+ //printf("about to poll...\n");
+ int32_t ret = loop->pollOnce(-1, 0, 0);
+ switch (ret) {
+ case ALOOPER_POLL_CALLBACK:
+ //("ALOOPER_POLL_CALLBACK\n");
+ break;
+ case ALOOPER_POLL_TIMEOUT:
+ printf("ALOOPER_POLL_TIMEOUT\n");
+ break;
+ case ALOOPER_POLL_ERROR:
+ printf("ALOOPER_POLL_TIMEOUT\n");
+ break;
+ default:
+ printf("ugh? poll returned %d\n", ret);
+ break;
+ }
+ } while (1);
+
+
+ return 0;
+}