diff options
author | Mathias Agopian <mathias@google.com> | 2010-07-14 23:41:37 -0700 |
---|---|---|
committer | Mathias Agopian <mathias@google.com> | 2010-07-19 17:57:29 -0700 |
commit | 1bf797857e025e8a71db86fb9e79765a767ec1eb (patch) | |
tree | e8d1aabae069f2b7368be746b99667eb150363f5 | |
parent | ff7049ab2886acc73e145367118646f7741ce333 (diff) | |
download | frameworks_base-1bf797857e025e8a71db86fb9e79765a767ec1eb.zip frameworks_base-1bf797857e025e8a71db86fb9e79765a767ec1eb.tar.gz frameworks_base-1bf797857e025e8a71db86fb9e79765a767ec1eb.tar.bz2 |
new SensorService
remove old sensor service and implement SensorManager
on top of the new (native) SensorManger API.
Change-Id: Iddb77d498755da3e11646473a44d651f12f40281
28 files changed, 895 insertions, 758 deletions
@@ -113,7 +113,6 @@ LOCAL_SRC_FILES += \ 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 @@ LOCAL_C_INCLUDES := \ $(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 @@ extern "C" status_t system_init() 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.IRotationWatcher; 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 @@ public class SensorManager /*-----------------------------------------------------------------------*/ - private ISensorService mSensorService; Looper mMainLooper; @SuppressWarnings("deprecation") private HashMap<SensorListener, LegacyListener> mLegacyListenersMap = @@ -356,6 +348,7 @@ public class SensorManager /* 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 @@ public class SensorManager 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 @@ public class SensorManager 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 @@ public class SensorManager } // 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 @@ public class SensorManager /*-----------------------------------------------------------------------*/ - 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 @@ public class SensorManager * {@hide} */ public SensorManager(Looper mainLooper) { - mSensorService = ISensorService.Stub.asInterface( - ServiceManager.getService(Context.SENSOR_SERVICE)); mMainLooper = mainLooper; @@ -1051,42 +1004,37 @@ public class SensorManager return false; } - try { - synchronized (sListeners) { - ListenerDelegate l = null; - for (ListenerDelegate i : sListeners) { - if (i.getListener() == listener) { - l = i; - break; - } + 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); + 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) { - l.addSensor(sensor); + 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); + } } - } catch (RemoteException e) { - Log.e(TAG, "RemoteException in registerListener: ", e); - result = false; } return result; } @@ -1095,27 +1043,23 @@ public class SensorManager 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 @@ public class SensorManager 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 @@ public class SensorManager 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 @@ LOCAL_SHARED_LIBRARIES := \ 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 @@ struct SensorOffsets * 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 @@ sensors_module_get_next_sensor(JNIEnv *env, jobject clazz, jobject sensor, jint //---------------------------------------------------------------------------- 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; - } - } - 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); + 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); } - - // 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 @@ static JNINativeMethod gMethods[] = { {"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 @@ class ISensorServer : public IInterface 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 @@ public: 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 @@ namespace android { class ISensorEventConnection; class Sensor; +class PollLoop; // ---------------------------------------------------------------------------- @@ -56,13 +57,21 @@ public: 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..e1b1a7b 100644 --- a/include/gui/SensorManager.h +++ b/include/gui/SensorManager.h @@ -47,13 +47,13 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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() { } +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 SensorEventQueue::read(ASensorEvent* events, size_t numEvents) 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 @@ ssize_t SensorEventQueue::read(ASensorEvent* events, size_t numEvents) return size; } -status_t SensorEventQueue::enableSensor(Sensor const* sensor) const +sp<PollLoop> SensorEventQueue::getPollLoop() const { - return mSensorEventConnection->enableDisable(sensor->getHandle(), true); + Mutex::Autolock _l(mLock); + if (mPollLoop == 0) { + mPollLoop = new PollLoop(true); + mPollLoop->setCallback(getFd(), POLLIN, NULL, NULL); + } + return mPollLoop; } -status_t SensorEventQueue::disableSensor(Sensor const* sensor) const +status_t SensorEventQueue::waitForEvent() const { - return mSensorEventConnection->enableDisable(sensor->getHandle(), false); + 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::setEventRate(Sensor const* sensor, nsecs_t ns) const +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 { + return mSensorEventConnection->enableDisable(sensor->getHandle(), false); +} + +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 @@ ANDROID_SINGLETON_STATIC_INSTANCE(SensorManager) 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 @@ ASensorManager* ASensorManager_getInstance() 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 ASensorManager_destroyEventQueue(ASensorManager* manager, /*****************************************************************************/ -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 @@ ssize_t ASensorEventQueue_getEvents(ASensorEventQueue* queue, /*****************************************************************************/ -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 @@ enum { * A sensor event. */ +/* NOTE: Must match hardware/sensors.h */ typedef struct ASensorVector { union { float v[3]; @@ -95,23 +96,32 @@ typedef struct ASensorVector { 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 @@ typedef struct ASensorEventQueue ASensorEventQueue; struct ASensor; typedef struct ASensor ASensor; +typedef ASensor const* ASensorRef; +typedef ASensorRef const* ASensorList; /*****************************************************************************/ @@ -141,13 +153,13 @@ ASensorManager* ASensorManager_getInstance(); /* * 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 @@ int ASensorManager_destroyEventQueue(ASensorManager* manager, ASensorEventQueue* /* * 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 @@ int ASensorEventQueue_disableSensor(ASensorEventQueue* queue, ASensor* sensor); * 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 @@ ssize_t ASensorEventQueue_getEvents(ASensorEventQueue* queue, /* * 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 @@ class ServerThread extends Thread { 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 @@ LOCAL_SRC_FILES:= \ 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_BatteryService(JNIEnv* env); 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 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved) 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..d5e321c --- /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; +} |