From 1bf797857e025e8a71db86fb9e79765a767ec1eb Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Wed, 14 Jul 2010 23:41:37 -0700 Subject: new SensorService remove old sensor service and implement SensorManager on top of the new (native) SensorManger API. Change-Id: Iddb77d498755da3e11646473a44d651f12f40281 --- Android.mk | 1 - cmds/system_server/library/Android.mk | 2 + cmds/system_server/library/system_init.cpp | 4 + core/java/android/hardware/ISensorService.aidl | 29 -- core/java/android/hardware/SensorManager.java | 203 ++++-------- core/jni/Android.mk | 1 + core/jni/android_hardware_SensorManager.cpp | 152 ++++----- include/gui/ISensorServer.h | 2 +- include/gui/Sensor.h | 3 +- include/gui/SensorEventQueue.h | 9 + include/gui/SensorManager.h | 6 +- libs/gui/ISensorEventConnection.cpp | 3 + libs/gui/ISensorServer.cpp | 2 + libs/gui/Sensor.cpp | 12 + libs/gui/SensorEventQueue.cpp | 46 ++- libs/gui/SensorManager.cpp | 31 +- native/android/sensor.cpp | 37 +-- native/include/android/sensor.h | 34 +- .../java/com/android/server/SensorService.java | 282 ---------------- services/java/com/android/server/SystemServer.java | 4 - services/jni/Android.mk | 1 - services/jni/com_android_server_SensorService.cpp | 177 ---------- services/jni/onload.cpp | 2 - services/sensorservice/Android.mk | 28 ++ services/sensorservice/SensorService.cpp | 359 +++++++++++++++++++++ services/sensorservice/SensorService.h | 119 +++++++ services/sensorservice/tests/Android.mk | 14 + services/sensorservice/tests/sensorservicetest.cpp | 90 ++++++ 28 files changed, 895 insertions(+), 758 deletions(-) delete mode 100644 core/java/android/hardware/ISensorService.aidl delete mode 100644 services/java/com/android/server/SensorService.java delete mode 100644 services/jni/com_android_server_SensorService.cpp create mode 100644 services/sensorservice/Android.mk create mode 100644 services/sensorservice/SensorService.cpp create mode 100644 services/sensorservice/SensorService.h create mode 100644 services/sensorservice/tests/Android.mk create mode 100644 services/sensorservice/tests/sensorservicetest.cpp diff --git a/Android.mk b/Android.mk index 69a40c1..5db6610 100644 --- a/Android.mk +++ b/Android.mk @@ -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 #include #include +#include #include @@ -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 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 sHandleToSensor = new SparseArray(); @@ -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 mSensorList = new ArrayList(); 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 -#include +#include +#include +#include #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 nextcommon, &sSensorDevice); - return err; + SensorManager& mgr(SensorManager::getInstance()); + sp queue(mgr.createEventQueue()); + queue->incStrong(clazz); + return reinterpret_cast(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 queue(reinterpret_cast(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 queue(reinterpret_cast(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 queue(reinterpret_cast(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 getSensorList()= 0; + virtual Vector getSensorList() = 0; virtual sp 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 getPollLoop() const; sp mSensorEventConnection; sp mSensorChannel; + mutable Mutex mLock; + mutable sp 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 createEventQueue(); private: sp mSensorServer; - Sensor* mSensorList; + Sensor const** mSensorList; Vector 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 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 getSensorList() { Parcel data, reply; + data.writeInterfaceToken(ISensorServer::getInterfaceDescriptor()); remote()->transact(GET_SENSOR_LIST, data, &reply); Sensor s; Vector v; @@ -63,6 +64,7 @@ public: virtual sp createSensorEventConnection() { Parcel data, reply; + data.writeInterfaceToken(ISensorServer::getInterfaceDescriptor()); remote()->transact(CREATE_SENSOR_EVENT_CONNECTION, data, &reply); return interface_cast(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 #include #include #include +#include #include #include @@ -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 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(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(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 #include @@ -21,6 +23,8 @@ #include #include +#include + #include #include #include @@ -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 ; igetType() == type) + return mSensorList[i]; + } + return NULL; } sp 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(manager)->getSensorList(&l); if (list) { - *list = l; + *list = reinterpret_cast(l); } return c; } -ASensor* ASensorManager_getDefaultSensor(ASensorManager* manager, int type) +ASensor const* ASensorManager_getDefaultSensor(ASensorManager* manager, int type) { return static_cast(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(queue)->enableSensor( - static_cast(sensor)); + static_cast(sensor)); } -int ASensorEventQueue_disableSensor(ASensorEventQueue* queue, ASensor* sensor) +int ASensorEventQueue_disableSensor(ASensorEventQueue* queue, ASensor const* sensor) { return static_cast(queue)->disableSensor( - static_cast(sensor)); + static_cast(sensor)); } -int ASensorEventQueue_setEventRate(ASensorEventQueue* queue, ASensor* sensor, +int ASensorEventQueue_setEventRate(ASensorEventQueue* queue, ASensor const* sensor, int32_t usec) { return static_cast(queue)->setEventRate( - static_cast(sensor), us2ns(usec)); + static_cast(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)->getName().string(); + return static_cast(sensor)->getName().string(); } -const char* ASensor_getVendor(ASensor* sensor) +const char* ASensor_getVendor(ASensor const* sensor) { - return static_cast(sensor)->getVendor().string(); + return static_cast(sensor)->getVendor().string(); } -int ASensor_getType(ASensor* sensor) +int ASensor_getType(ASensor const* sensor) { - return static_cast(sensor)->getType(); + return static_cast(sensor)->getType(); } -float ASensor_getResolution(ASensor* sensor) +float ASensor_getResolution(ASensor const* sensor) { - return static_cast(sensor)->getResolution(); + return static_cast(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< mListeners = new ArrayList(); - - 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 - -#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, "", "()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, "", - "(Ljava/io/FileDescriptor;)V"); - - clazz = env->FindClass("android/os/Bundle"); - gBundleOffsets.mClass = (jclass) env->NewGlobalRef(clazz); - gBundleOffsets.mConstructor = env->GetMethodID(clazz, "", "()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 +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include + +#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 ; iactivate(mSensorDevice, sensor.getHandle(), 0); + } + + run("SensorService", PRIORITY_URGENT_DISPLAY); +} + +SensorService::~SensorService() +{ +} + +status_t SensorService::dump(int fd, const Vector& 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 ; igetNumConnections()); + 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 > activeConnections( + getActiveConnections()); + + size_t numConnections = activeConnections.size(); + if (numConnections) { + for (size_t i=0 ; i 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::getActiveConnections() const +{ + Mutex::Autolock _l(mLock); + return mActiveConnections; +} + +Vector SensorService::getSensorList() +{ + return mSensorList; +} + +sp SensorService::createSensorEventConnection() +{ + sp result(new SensorEventConnection(this)); + Mutex::Autolock _l(mLock); + mConnections.add(result); + return result; +} + +void SensorService::cleanupConnection(const wp& connection) +{ + Mutex::Autolock _l(mLock); + ssize_t index = mConnections.indexOf(connection); + if (index >= 0) { + + size_t size = mActiveSensors.size(); + for (size_t i=0 ; iremoveConnection(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& 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& 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& 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& connection) +{ + mConnections.add(connection); +} + +status_t SensorService::SensorRecord::addConnection( + const sp& connection) +{ + if (mConnections.indexOf(connection) < 0) { + mConnections.add(connection); + } + return NO_ERROR; +} + +bool SensorService::SensorRecord::removeConnection( + const wp& connection) +{ + ssize_t index = mConnections.indexOf(connection); + if (index >= 0) { + mConnections.removeItemsAt(index, 1); + } + return mConnections.size() ? false : true; +} + +// --------------------------------------------------------------------------- + +SensorService::SensorEventConnection::SensorEventConnection( + const sp& 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 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 +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +// --------------------------------------------------------------------------- + +struct sensors_poll_device_t; +struct sensors_module_t; + +namespace android { +// --------------------------------------------------------------------------- + +class SensorService : + public BinderService, + public BnSensorServer, + protected Thread +{ + friend class BinderService; + + SensorService(); + virtual ~SensorService(); + + virtual void onFirstRef(); + + // Thread interface + virtual bool threadLoop(); + + // ISensorServer interface + virtual Vector getSensorList(); + virtual sp createSensorEventConnection(); + virtual status_t dump(int fd, const Vector& args); + + + class SensorEventConnection : public BnSensorEventConnection { + virtual sp getSensorChannel() const; + virtual status_t enableDisable(int handle, bool enabled); + virtual status_t setEventRate(int handle, nsecs_t ns); + sp const mService; + sp const mChannel; + SortedVector mSensorList; + public: + SensorEventConnection(const sp& 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 > mConnections; + public: + SensorRecord(const sp& connection); + status_t addConnection(const sp& connection); + bool removeConnection(const wp& connection); + size_t getNumConnections() const { return mConnections.size(); } + }; + + SortedVector< wp > getActiveConnections() const; + + // constants + Vector mSensorList; + struct sensors_poll_device_t* mSensorDevice; + struct sensors_module_t* mSensorModule; + Permission mDump; + + // protected by mLock + mutable Mutex mLock; + SortedVector< wp > mConnections; + DefaultKeyedVector mActiveSensors; + SortedVector< wp > mActiveConnections; + +public: + static char const* getServiceName() { return "sensorservice"; } + + void cleanupConnection(const wp& connection); + status_t enable(const sp& connection, int handle); + status_t disable(const sp& connection, int handle); + status_t setRate(const sp& 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 +#include +#include +#include +#include + +using namespace android; + +bool receiver(int fd, int events, void* data) +{ + sp q((SensorEventQueue*)data); + ssize_t n; + ASensorEvent buffer[8]; + while ((n = q->read(buffer, 8)) > 0) { + for (int i=0 ; i\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 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 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; +} -- cgit v1.1