am e4764521
: Merge "new SensorService" into gingerbread
Merge commit 'e4764521353e898554931a557460fc49209fb0a9' into gingerbread-plus-aosp * commit 'e4764521353e898554931a557460fc49209fb0a9': new SensorService
This commit is contained in:
@ -113,7 +113,6 @@ LOCAL_SRC_FILES += \
|
|||||||
core/java/android/content/pm/IPackageMoveObserver.aidl \
|
core/java/android/content/pm/IPackageMoveObserver.aidl \
|
||||||
core/java/android/content/pm/IPackageStatsObserver.aidl \
|
core/java/android/content/pm/IPackageStatsObserver.aidl \
|
||||||
core/java/android/database/IContentObserver.aidl \
|
core/java/android/database/IContentObserver.aidl \
|
||||||
core/java/android/hardware/ISensorService.aidl \
|
|
||||||
core/java/android/net/IConnectivityManager.aidl \
|
core/java/android/net/IConnectivityManager.aidl \
|
||||||
core/java/android/net/INetworkManagementEventObserver.aidl \
|
core/java/android/net/INetworkManagementEventObserver.aidl \
|
||||||
core/java/android/net/IThrottleManager.aidl \
|
core/java/android/net/IThrottleManager.aidl \
|
||||||
|
@ -10,11 +10,13 @@ LOCAL_C_INCLUDES := \
|
|||||||
$(base)/services/camera/libcameraservice \
|
$(base)/services/camera/libcameraservice \
|
||||||
$(base)/services/audioflinger \
|
$(base)/services/audioflinger \
|
||||||
$(base)/services/surfaceflinger \
|
$(base)/services/surfaceflinger \
|
||||||
|
$(base)/services/sensorservice \
|
||||||
$(base)/media/libmediaplayerservice \
|
$(base)/media/libmediaplayerservice \
|
||||||
$(JNI_H_INCLUDE)
|
$(JNI_H_INCLUDE)
|
||||||
|
|
||||||
LOCAL_SHARED_LIBRARIES := \
|
LOCAL_SHARED_LIBRARIES := \
|
||||||
libandroid_runtime \
|
libandroid_runtime \
|
||||||
|
libsensorservice \
|
||||||
libsurfaceflinger \
|
libsurfaceflinger \
|
||||||
libaudioflinger \
|
libaudioflinger \
|
||||||
libcameraservice \
|
libcameraservice \
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include <CameraService.h>
|
#include <CameraService.h>
|
||||||
#include <AudioPolicyService.h>
|
#include <AudioPolicyService.h>
|
||||||
#include <MediaPlayerService.h>
|
#include <MediaPlayerService.h>
|
||||||
|
#include <SensorService.h>
|
||||||
|
|
||||||
#include <android_runtime/AndroidRuntime.h>
|
#include <android_runtime/AndroidRuntime.h>
|
||||||
|
|
||||||
@ -69,6 +70,9 @@ extern "C" status_t system_init()
|
|||||||
SurfaceFlinger::instantiate();
|
SurfaceFlinger::instantiate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Start the sensor service
|
||||||
|
SensorService::instantiate();
|
||||||
|
|
||||||
// On the simulator, audioflinger et al don't get started the
|
// On the simulator, audioflinger et al don't get started the
|
||||||
// same way as on the device, and we need to start them here
|
// same way as on the device, and we need to start them here
|
||||||
if (!proc->supportsProcesses()) {
|
if (!proc->supportsProcesses()) {
|
||||||
|
@ -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);
|
|
||||||
}
|
|
@ -16,12 +16,7 @@
|
|||||||
|
|
||||||
package android.hardware;
|
package android.hardware;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.os.Binder;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.os.Parcelable;
|
|
||||||
import android.os.ParcelFileDescriptor;
|
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
@ -33,8 +28,6 @@ import android.view.IRotationWatcher;
|
|||||||
import android.view.IWindowManager;
|
import android.view.IWindowManager;
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
|
|
||||||
import java.io.FileDescriptor;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -339,7 +332,6 @@ public class SensorManager
|
|||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
private ISensorService mSensorService;
|
|
||||||
Looper mMainLooper;
|
Looper mMainLooper;
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
private HashMap<SensorListener, LegacyListener> mLegacyListenersMap =
|
private HashMap<SensorListener, LegacyListener> mLegacyListenersMap =
|
||||||
@ -356,6 +348,7 @@ public class SensorManager
|
|||||||
/* The thread and the sensor list are global to the process
|
/* The thread and the sensor list are global to the process
|
||||||
* but the actual thread is spawned on demand */
|
* but the actual thread is spawned on demand */
|
||||||
private static SensorThread sSensorThread;
|
private static SensorThread sSensorThread;
|
||||||
|
private static int sQueue;
|
||||||
|
|
||||||
// Used within this module from outside SensorManager, don't make private
|
// Used within this module from outside SensorManager, don't make private
|
||||||
static SparseArray<Sensor> sHandleToSensor = new SparseArray<Sensor>();
|
static SparseArray<Sensor> sHandleToSensor = new SparseArray<Sensor>();
|
||||||
@ -370,80 +363,41 @@ public class SensorManager
|
|||||||
boolean mSensorsReady;
|
boolean mSensorsReady;
|
||||||
|
|
||||||
SensorThread() {
|
SensorThread() {
|
||||||
// this gets to the sensor module. We can have only one per process.
|
|
||||||
sensors_data_init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void finalize() {
|
protected void finalize() {
|
||||||
sensors_data_uninit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// must be called with sListeners lock
|
// must be called with sListeners lock
|
||||||
boolean startLocked(ISensorService service) {
|
boolean startLocked() {
|
||||||
try {
|
try {
|
||||||
if (mThread == null) {
|
if (mThread == null) {
|
||||||
Bundle dataChannel = service.getDataChannel();
|
mSensorsReady = false;
|
||||||
if (dataChannel != null) {
|
SensorThreadRunnable runnable = new SensorThreadRunnable();
|
||||||
mSensorsReady = false;
|
Thread thread = new Thread(runnable, SensorThread.class.getName());
|
||||||
SensorThreadRunnable runnable = new SensorThreadRunnable(dataChannel);
|
thread.start();
|
||||||
Thread thread = new Thread(runnable, SensorThread.class.getName());
|
synchronized (runnable) {
|
||||||
thread.start();
|
while (mSensorsReady == false) {
|
||||||
synchronized (runnable) {
|
runnable.wait();
|
||||||
while (mSensorsReady == false) {
|
|
||||||
runnable.wait();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
mThread = thread;
|
|
||||||
}
|
}
|
||||||
|
mThread = thread;
|
||||||
}
|
}
|
||||||
} catch (RemoteException e) {
|
|
||||||
Log.e(TAG, "RemoteException in startLocked: ", e);
|
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
}
|
}
|
||||||
return mThread == null ? false : true;
|
return mThread == null ? false : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class SensorThreadRunnable implements Runnable {
|
private class SensorThreadRunnable implements Runnable {
|
||||||
private Bundle mDataChannel;
|
SensorThreadRunnable() {
|
||||||
SensorThreadRunnable(Bundle dataChannel) {
|
|
||||||
mDataChannel = dataChannel;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean open() {
|
private boolean open() {
|
||||||
// NOTE: this cannot synchronize on sListeners, since
|
// NOTE: this cannot synchronize on sListeners, since
|
||||||
// it's held in the main thread at least until we
|
// it's held in the main thread at least until we
|
||||||
// return from here.
|
// return from here.
|
||||||
|
sQueue = sensors_create_queue();
|
||||||
// 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;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -466,7 +420,7 @@ public class SensorManager
|
|||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
// wait for an event
|
// 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];
|
int accuracy = status[0];
|
||||||
synchronized (sListeners) {
|
synchronized (sListeners) {
|
||||||
@ -478,7 +432,8 @@ public class SensorManager
|
|||||||
}
|
}
|
||||||
|
|
||||||
// we have no more listeners or polling failed, terminate the thread
|
// we have no more listeners or polling failed, terminate the thread
|
||||||
sensors_data_close();
|
sensors_destroy_queue(sQueue);
|
||||||
|
sQueue = 0;
|
||||||
mThread = null;
|
mThread = null;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -506,7 +461,7 @@ public class SensorManager
|
|||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
private class ListenerDelegate extends Binder {
|
private class ListenerDelegate {
|
||||||
final SensorEventListener mSensorEventListener;
|
final SensorEventListener mSensorEventListener;
|
||||||
private final ArrayList<Sensor> mSensorList = new ArrayList<Sensor>();
|
private final ArrayList<Sensor> mSensorList = new ArrayList<Sensor>();
|
||||||
private final Handler mHandler;
|
private final Handler mHandler;
|
||||||
@ -602,8 +557,6 @@ public class SensorManager
|
|||||||
* {@hide}
|
* {@hide}
|
||||||
*/
|
*/
|
||||||
public SensorManager(Looper mainLooper) {
|
public SensorManager(Looper mainLooper) {
|
||||||
mSensorService = ISensorService.Stub.asInterface(
|
|
||||||
ServiceManager.getService(Context.SENSOR_SERVICE));
|
|
||||||
mMainLooper = mainLooper;
|
mMainLooper = mainLooper;
|
||||||
|
|
||||||
|
|
||||||
@ -1051,42 +1004,37 @@ public class SensorManager
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
synchronized (sListeners) {
|
||||||
synchronized (sListeners) {
|
ListenerDelegate l = null;
|
||||||
ListenerDelegate l = null;
|
for (ListenerDelegate i : sListeners) {
|
||||||
for (ListenerDelegate i : sListeners) {
|
if (i.getListener() == listener) {
|
||||||
if (i.getListener() == listener) {
|
l = i;
|
||||||
l = i;
|
break;
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
String name = sensor.getName();
|
||||||
String name = sensor.getName();
|
int handle = sensor.getHandle();
|
||||||
int handle = sensor.getHandle();
|
if (l == null) {
|
||||||
if (l == null) {
|
result = false;
|
||||||
result = false;
|
l = new ListenerDelegate(listener, sensor, handler);
|
||||||
l = new ListenerDelegate(listener, sensor, handler);
|
sListeners.add(l);
|
||||||
sListeners.add(l);
|
if (!sListeners.isEmpty()) {
|
||||||
if (!sListeners.isEmpty()) {
|
result = sSensorThread.startLocked();
|
||||||
result = sSensorThread.startLocked(mSensorService);
|
if (result) {
|
||||||
if (result) {
|
result = sensors_enable_sensor(sQueue, name, handle, delay);
|
||||||
result = mSensorService.enableSensor(l, name, handle, delay);
|
if (!result) {
|
||||||
if (!result) {
|
// there was an error, remove the listeners
|
||||||
// there was an error, remove the listeners
|
sListeners.remove(l);
|
||||||
sListeners.remove(l);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
} else {
|
result = sensors_enable_sensor(sQueue, name, handle, delay);
|
||||||
result = mSensorService.enableSensor(l, name, handle, delay);
|
if (result) {
|
||||||
if (result) {
|
l.addSensor(sensor);
|
||||||
l.addSensor(sensor);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (RemoteException e) {
|
|
||||||
Log.e(TAG, "RemoteException in registerListener: ", e);
|
|
||||||
result = false;
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -1095,27 +1043,23 @@ public class SensorManager
|
|||||||
if (listener == null || sensor == null) {
|
if (listener == null || sensor == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
synchronized (sListeners) {
|
||||||
synchronized (sListeners) {
|
final int size = sListeners.size();
|
||||||
final int size = sListeners.size();
|
for (int i=0 ; i<size ; i++) {
|
||||||
for (int i=0 ; i<size ; i++) {
|
ListenerDelegate l = sListeners.get(i);
|
||||||
ListenerDelegate l = sListeners.get(i);
|
if (l.getListener() == listener) {
|
||||||
if (l.getListener() == listener) {
|
// disable these sensors
|
||||||
// disable these sensors
|
String name = sensor.getName();
|
||||||
String name = sensor.getName();
|
int handle = sensor.getHandle();
|
||||||
int handle = sensor.getHandle();
|
sensors_enable_sensor(sQueue, name, handle, SENSOR_DISABLE);
|
||||||
mSensorService.enableSensor(l, name, handle, SENSOR_DISABLE);
|
// if we have no more sensors enabled on this listener,
|
||||||
// if we have no more sensors enabled on this listener,
|
// take it off the list.
|
||||||
// take it off the list.
|
if (l.removeSensor(sensor) == 0) {
|
||||||
if (l.removeSensor(sensor) == 0) {
|
sListeners.remove(i);
|
||||||
sListeners.remove(i);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (RemoteException e) {
|
|
||||||
Log.e(TAG, "RemoteException in unregisterListener: ", e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1123,25 +1067,21 @@ public class SensorManager
|
|||||||
if (listener == null) {
|
if (listener == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
synchronized (sListeners) {
|
||||||
synchronized (sListeners) {
|
final int size = sListeners.size();
|
||||||
final int size = sListeners.size();
|
for (int i=0 ; i<size ; i++) {
|
||||||
for (int i=0 ; i<size ; i++) {
|
ListenerDelegate l = sListeners.get(i);
|
||||||
ListenerDelegate l = sListeners.get(i);
|
if (l.getListener() == listener) {
|
||||||
if (l.getListener() == listener) {
|
// disable all sensors for this listener
|
||||||
// disable all sensors for this listener
|
for (Sensor sensor : l.getSensors()) {
|
||||||
for (Sensor sensor : l.getSensors()) {
|
String name = sensor.getName();
|
||||||
String name = sensor.getName();
|
int handle = sensor.getHandle();
|
||||||
int handle = sensor.getHandle();
|
sensors_enable_sensor(sQueue, name, handle, SENSOR_DISABLE);
|
||||||
mSensorService.enableSensor(l, name, handle, SENSOR_DISABLE);
|
|
||||||
}
|
|
||||||
sListeners.remove(i);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
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);
|
private static native int sensors_module_get_next_sensor(Sensor sensor, int next);
|
||||||
|
|
||||||
// Used within this module from outside SensorManager, don't make private
|
// Used within this module from outside SensorManager, don't make private
|
||||||
static native int sensors_data_init();
|
static native int sensors_create_queue();
|
||||||
static native int sensors_data_uninit();
|
static native void sensors_destroy_queue(int queue);
|
||||||
static native int sensors_data_open(FileDescriptor[] fds, int[] ints);
|
static native boolean sensors_enable_sensor(int queue, String name, int sensor, int enable);
|
||||||
static native int sensors_data_close();
|
static native int sensors_data_poll(int queue, float[] values, int[] status, long[] timestamp);
|
||||||
static native int sensors_data_poll(float[] values, int[] status, long[] timestamp);
|
|
||||||
}
|
}
|
||||||
|
@ -168,6 +168,7 @@ LOCAL_SHARED_LIBRARIES := \
|
|||||||
libbinder \
|
libbinder \
|
||||||
libnetutils \
|
libnetutils \
|
||||||
libui \
|
libui \
|
||||||
|
libgui \
|
||||||
libsurfaceflinger_client \
|
libsurfaceflinger_client \
|
||||||
libcamera_client \
|
libcamera_client \
|
||||||
libskiagl \
|
libskiagl \
|
||||||
|
@ -18,8 +18,9 @@
|
|||||||
|
|
||||||
#include "utils/Log.h"
|
#include "utils/Log.h"
|
||||||
|
|
||||||
#include <hardware/sensors.h>
|
#include <gui/Sensor.h>
|
||||||
#include <cutils/native_handle.h>
|
#include <gui/SensorManager.h>
|
||||||
|
#include <gui/SensorEventQueue.h>
|
||||||
|
|
||||||
#include "jni.h"
|
#include "jni.h"
|
||||||
#include "JNIHelp.h"
|
#include "JNIHelp.h"
|
||||||
@ -43,44 +44,36 @@ struct SensorOffsets
|
|||||||
* The method below are not thread-safe and not intended to be
|
* 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
|
static jint
|
||||||
sensors_module_init(JNIEnv *env, jclass clazz)
|
sensors_module_init(JNIEnv *env, jclass clazz)
|
||||||
{
|
{
|
||||||
int err = 0;
|
SensorManager::getInstance();
|
||||||
sensors_module_t const* module;
|
return 0;
|
||||||
err = hw_get_module(SENSORS_HARDWARE_MODULE_ID, (const hw_module_t **)&module);
|
|
||||||
if (err == 0)
|
|
||||||
sSensorModule = (sensors_module_t*)module;
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static jint
|
static jint
|
||||||
sensors_module_get_next_sensor(JNIEnv *env, jobject clazz, jobject sensor, jint next)
|
sensors_module_get_next_sensor(JNIEnv *env, jobject clazz, jobject sensor, jint next)
|
||||||
{
|
{
|
||||||
if (sSensorModule == NULL)
|
SensorManager& mgr(SensorManager::getInstance());
|
||||||
return 0;
|
|
||||||
|
|
||||||
SensorOffsets& sensorOffsets = gSensorOffsets;
|
Sensor const* const* sensorList;
|
||||||
const struct sensor_t* list;
|
size_t count = mgr.getSensorList(&sensorList);
|
||||||
int count = sSensorModule->get_sensors_list(sSensorModule, &list);
|
|
||||||
if (next >= count)
|
if (next >= count)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
list += next;
|
Sensor const* const list = sensorList[next];
|
||||||
|
const SensorOffsets& sensorOffsets(gSensorOffsets);
|
||||||
jstring name = env->NewStringUTF(list->name);
|
jstring name = env->NewStringUTF(list->getName().string());
|
||||||
jstring vendor = env->NewStringUTF(list->vendor);
|
jstring vendor = env->NewStringUTF(list->getVendor().string());
|
||||||
env->SetObjectField(sensor, sensorOffsets.name, name);
|
env->SetObjectField(sensor, sensorOffsets.name, name);
|
||||||
env->SetObjectField(sensor, sensorOffsets.vendor, vendor);
|
env->SetObjectField(sensor, sensorOffsets.vendor, vendor);
|
||||||
env->SetIntField(sensor, sensorOffsets.version, list->version);
|
env->SetIntField(sensor, sensorOffsets.version, 1);
|
||||||
env->SetIntField(sensor, sensorOffsets.handle, list->handle);
|
env->SetIntField(sensor, sensorOffsets.handle, list->getHandle());
|
||||||
env->SetIntField(sensor, sensorOffsets.type, list->type);
|
env->SetIntField(sensor, sensorOffsets.type, list->getType());
|
||||||
env->SetFloatField(sensor, sensorOffsets.range, list->maxRange);
|
env->SetFloatField(sensor, sensorOffsets.range, list->getMaxValue());
|
||||||
env->SetFloatField(sensor, sensorOffsets.resolution, list->resolution);
|
env->SetFloatField(sensor, sensorOffsets.resolution, list->getResolution());
|
||||||
env->SetFloatField(sensor, sensorOffsets.power, list->power);
|
env->SetFloatField(sensor, sensorOffsets.power, list->getPowerUsage());
|
||||||
|
|
||||||
next++;
|
next++;
|
||||||
return next<count ? next : 0;
|
return next<count ? next : 0;
|
||||||
@ -88,75 +81,64 @@ sensors_module_get_next_sensor(JNIEnv *env, jobject clazz, jobject sensor, jint
|
|||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
static jint
|
static jint
|
||||||
sensors_data_init(JNIEnv *env, jclass clazz)
|
sensors_create_queue(JNIEnv *env, jclass clazz)
|
||||||
{
|
{
|
||||||
if (sSensorModule == NULL)
|
SensorManager& mgr(SensorManager::getInstance());
|
||||||
return -1;
|
sp<SensorEventQueue> queue(mgr.createEventQueue());
|
||||||
int err = sensors_data_open(&sSensorModule->common, &sSensorDevice);
|
queue->incStrong(clazz);
|
||||||
return err;
|
return reinterpret_cast<int>(queue.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
static jint
|
static void
|
||||||
sensors_data_uninit(JNIEnv *env, jclass clazz)
|
sensors_destroy_queue(JNIEnv *env, jclass clazz, jint nativeQueue)
|
||||||
{
|
{
|
||||||
int err = 0;
|
sp<SensorEventQueue> queue(reinterpret_cast<SensorEventQueue *>(nativeQueue));
|
||||||
if (sSensorDevice) {
|
if (queue != 0) {
|
||||||
err = sensors_data_close(sSensorDevice);
|
queue->decStrong(clazz);
|
||||||
if (err == 0)
|
|
||||||
sSensorDevice = 0;
|
|
||||||
}
|
}
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static jint
|
static jboolean
|
||||||
sensors_data_open(JNIEnv *env, jclass clazz, jobjectArray fdArray, jintArray intArray)
|
sensors_enable_sensor(JNIEnv *env, jclass clazz,
|
||||||
|
jint nativeQueue, jstring name, jint sensor, jint enable)
|
||||||
{
|
{
|
||||||
jclass FileDescriptor = env->FindClass("java/io/FileDescriptor");
|
sp<SensorEventQueue> queue(reinterpret_cast<SensorEventQueue *>(nativeQueue));
|
||||||
jfieldID fieldOffset = env->GetFieldID(FileDescriptor, "descriptor", "I");
|
if (queue == 0) return JNI_FALSE;
|
||||||
int numFds = (fdArray ? env->GetArrayLength(fdArray) : 0);
|
status_t res;
|
||||||
int numInts = (intArray ? env->GetArrayLength(intArray) : 0);
|
if (enable) {
|
||||||
native_handle_t* handle = native_handle_create(numFds, numInts);
|
res = queue->enableSensor(sensor);
|
||||||
int offset = 0;
|
} else {
|
||||||
|
res = queue->disableSensor(sensor);
|
||||||
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) {
|
return res == NO_ERROR ? true : false;
|
||||||
jint* ints = env->GetIntArrayElements(intArray, 0);
|
|
||||||
for (int i = 0; i < numInts; i++) {
|
|
||||||
handle->data[offset++] = ints[i];
|
|
||||||
}
|
|
||||||
env->ReleaseIntArrayElements(intArray, ints, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// doesn't take ownership of the native handle
|
|
||||||
return sSensorDevice->data_open(sSensorDevice, handle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static jint
|
static jint
|
||||||
sensors_data_close(JNIEnv *env, jclass clazz)
|
sensors_data_poll(JNIEnv *env, jclass clazz, jint nativeQueue,
|
||||||
{
|
|
||||||
return sSensorDevice->data_close(sSensorDevice);
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint
|
|
||||||
sensors_data_poll(JNIEnv *env, jclass clazz,
|
|
||||||
jfloatArray values, jintArray status, jlongArray timestamp)
|
jfloatArray values, jintArray status, jlongArray timestamp)
|
||||||
{
|
{
|
||||||
sensors_data_t data;
|
sp<SensorEventQueue> queue(reinterpret_cast<SensorEventQueue *>(nativeQueue));
|
||||||
int res = sSensorDevice->poll(sSensorDevice, &data);
|
if (queue == 0) return -1;
|
||||||
if (res >= 0) {
|
|
||||||
jint accuracy = data.vector.status;
|
status_t res;
|
||||||
env->SetFloatArrayRegion(values, 0, 3, data.vector.v);
|
ASensorEvent event;
|
||||||
env->SetIntArrayRegion(status, 0, 1, &accuracy);
|
|
||||||
env->SetLongArrayRegion(timestamp, 0, 1, &data.time);
|
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
|
static void
|
||||||
@ -179,11 +161,13 @@ static JNINativeMethod gMethods[] = {
|
|||||||
{"sensors_module_init","()I", (void*)sensors_module_init },
|
{"sensors_module_init","()I", (void*)sensors_module_init },
|
||||||
{"sensors_module_get_next_sensor","(Landroid/hardware/Sensor;I)I",
|
{"sensors_module_get_next_sensor","(Landroid/hardware/Sensor;I)I",
|
||||||
(void*)sensors_module_get_next_sensor },
|
(void*)sensors_module_get_next_sensor },
|
||||||
{"sensors_data_init", "()I", (void*)sensors_data_init },
|
|
||||||
{"sensors_data_uninit", "()I", (void*)sensors_data_uninit },
|
{"sensors_create_queue", "()I", (void*)sensors_create_queue },
|
||||||
{"sensors_data_open", "([Ljava/io/FileDescriptor;[I)I", (void*)sensors_data_open },
|
{"sensors_destroy_queue", "(I)V", (void*)sensors_destroy_queue },
|
||||||
{"sensors_data_close", "()I", (void*)sensors_data_close },
|
{"sensors_enable_sensor", "(ILjava/lang/String;II)Z",
|
||||||
{"sensors_data_poll", "([F[I[J)I", (void*)sensors_data_poll },
|
(void*)sensors_enable_sensor },
|
||||||
|
|
||||||
|
{"sensors_data_poll", "(I[F[I[J)I", (void*)sensors_data_poll },
|
||||||
};
|
};
|
||||||
|
|
||||||
}; // namespace android
|
}; // namespace android
|
||||||
|
@ -36,7 +36,7 @@ class ISensorServer : public IInterface
|
|||||||
public:
|
public:
|
||||||
DECLARE_META_INTERFACE(SensorServer);
|
DECLARE_META_INTERFACE(SensorServer);
|
||||||
|
|
||||||
virtual Vector<Sensor> getSensorList()= 0;
|
virtual Vector<Sensor> getSensorList() = 0;
|
||||||
virtual sp<ISensorEventConnection> createSensorEventConnection() = 0;
|
virtual sp<ISensorEventConnection> createSensorEventConnection() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -51,7 +51,8 @@ public:
|
|||||||
TYPE_PROXIMITY = ASENSOR_TYPE_PROXIMITY
|
TYPE_PROXIMITY = ASENSOR_TYPE_PROXIMITY
|
||||||
};
|
};
|
||||||
|
|
||||||
Sensor();
|
Sensor();
|
||||||
|
Sensor(struct sensor_t const* hwSensor);
|
||||||
virtual ~Sensor();
|
virtual ~Sensor();
|
||||||
|
|
||||||
const String8& getName() const;
|
const String8& getName() const;
|
||||||
|
@ -42,6 +42,7 @@ namespace android {
|
|||||||
|
|
||||||
class ISensorEventConnection;
|
class ISensorEventConnection;
|
||||||
class Sensor;
|
class Sensor;
|
||||||
|
class PollLoop;
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -56,13 +57,21 @@ public:
|
|||||||
ssize_t write(ASensorEvent const* events, size_t numEvents);
|
ssize_t write(ASensorEvent const* events, size_t numEvents);
|
||||||
ssize_t read(ASensorEvent* 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 enableSensor(Sensor const* sensor) const;
|
||||||
status_t disableSensor(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;
|
status_t setEventRate(Sensor const* sensor, nsecs_t ns) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
sp<PollLoop> getPollLoop() const;
|
||||||
sp<ISensorEventConnection> mSensorEventConnection;
|
sp<ISensorEventConnection> mSensorEventConnection;
|
||||||
sp<SensorChannel> mSensorChannel;
|
sp<SensorChannel> mSensorChannel;
|
||||||
|
mutable Mutex mLock;
|
||||||
|
mutable sp<PollLoop> mPollLoop;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@ -47,13 +47,13 @@ public:
|
|||||||
SensorManager();
|
SensorManager();
|
||||||
~SensorManager();
|
~SensorManager();
|
||||||
|
|
||||||
ssize_t getSensorList(Sensor**) const;
|
ssize_t getSensorList(Sensor const* const** list) const;
|
||||||
Sensor* getDefaultSensor(int type);
|
Sensor const* getDefaultSensor(int type);
|
||||||
sp<SensorEventQueue> createEventQueue();
|
sp<SensorEventQueue> createEventQueue();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sp<ISensorServer> mSensorServer;
|
sp<ISensorServer> mSensorServer;
|
||||||
Sensor* mSensorList;
|
Sensor const** mSensorList;
|
||||||
Vector<Sensor> mSensors;
|
Vector<Sensor> mSensors;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -47,6 +47,7 @@ public:
|
|||||||
virtual sp<SensorChannel> getSensorChannel() const
|
virtual sp<SensorChannel> getSensorChannel() const
|
||||||
{
|
{
|
||||||
Parcel data, reply;
|
Parcel data, reply;
|
||||||
|
data.writeInterfaceToken(ISensorEventConnection::getInterfaceDescriptor());
|
||||||
remote()->transact(GET_SENSOR_CHANNEL, data, &reply);
|
remote()->transact(GET_SENSOR_CHANNEL, data, &reply);
|
||||||
return new SensorChannel(reply);
|
return new SensorChannel(reply);
|
||||||
}
|
}
|
||||||
@ -54,6 +55,7 @@ public:
|
|||||||
virtual status_t enableDisable(int handle, bool enabled)
|
virtual status_t enableDisable(int handle, bool enabled)
|
||||||
{
|
{
|
||||||
Parcel data, reply;
|
Parcel data, reply;
|
||||||
|
data.writeInterfaceToken(ISensorEventConnection::getInterfaceDescriptor());
|
||||||
data.writeInt32(handle);
|
data.writeInt32(handle);
|
||||||
data.writeInt32(enabled);
|
data.writeInt32(enabled);
|
||||||
remote()->transact(ENABLE_DISABLE, data, &reply);
|
remote()->transact(ENABLE_DISABLE, data, &reply);
|
||||||
@ -63,6 +65,7 @@ public:
|
|||||||
virtual status_t setEventRate(int handle, nsecs_t ns)
|
virtual status_t setEventRate(int handle, nsecs_t ns)
|
||||||
{
|
{
|
||||||
Parcel data, reply;
|
Parcel data, reply;
|
||||||
|
data.writeInterfaceToken(ISensorEventConnection::getInterfaceDescriptor());
|
||||||
data.writeInt32(handle);
|
data.writeInt32(handle);
|
||||||
data.writeInt64(ns);
|
data.writeInt64(ns);
|
||||||
remote()->transact(SET_EVENT_RATE, data, &reply);
|
remote()->transact(SET_EVENT_RATE, data, &reply);
|
||||||
|
@ -48,6 +48,7 @@ public:
|
|||||||
virtual Vector<Sensor> getSensorList()
|
virtual Vector<Sensor> getSensorList()
|
||||||
{
|
{
|
||||||
Parcel data, reply;
|
Parcel data, reply;
|
||||||
|
data.writeInterfaceToken(ISensorServer::getInterfaceDescriptor());
|
||||||
remote()->transact(GET_SENSOR_LIST, data, &reply);
|
remote()->transact(GET_SENSOR_LIST, data, &reply);
|
||||||
Sensor s;
|
Sensor s;
|
||||||
Vector<Sensor> v;
|
Vector<Sensor> v;
|
||||||
@ -63,6 +64,7 @@ public:
|
|||||||
virtual sp<ISensorEventConnection> createSensorEventConnection()
|
virtual sp<ISensorEventConnection> createSensorEventConnection()
|
||||||
{
|
{
|
||||||
Parcel data, reply;
|
Parcel data, reply;
|
||||||
|
data.writeInterfaceToken(ISensorServer::getInterfaceDescriptor());
|
||||||
remote()->transact(CREATE_SENSOR_EVENT_CONNECTION, data, &reply);
|
remote()->transact(CREATE_SENSOR_EVENT_CONNECTION, data, &reply);
|
||||||
return interface_cast<ISensorEventConnection>(reply.readStrongBinder());
|
return interface_cast<ISensorEventConnection>(reply.readStrongBinder());
|
||||||
}
|
}
|
||||||
|
@ -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()
|
Sensor::~Sensor()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -13,11 +13,15 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define LOG_TAG "Sensors"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <utils/Errors.h>
|
#include <utils/Errors.h>
|
||||||
#include <utils/RefBase.h>
|
#include <utils/RefBase.h>
|
||||||
|
#include <utils/PollLoop.h>
|
||||||
|
|
||||||
#include <gui/Sensor.h>
|
#include <gui/Sensor.h>
|
||||||
#include <gui/SensorChannel.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]));
|
ssize_t size = mSensorChannel->read(events, numEvents*sizeof(events[0]));
|
||||||
if (size >= 0) {
|
if (size >= 0) {
|
||||||
if (size % sizeof(events[0])) {
|
if (size % sizeof(events[0])) {
|
||||||
// partial write!!! should never happen.
|
// partial read!!! should never happen.
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
// returns number of events read
|
// returns number of events read
|
||||||
@ -77,18 +81,48 @@ ssize_t SensorEventQueue::read(ASensorEvent* events, size_t numEvents)
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t SensorEventQueue::enableSensor(Sensor const* sensor) const
|
sp<PollLoop> SensorEventQueue::getPollLoop() const
|
||||||
{
|
{
|
||||||
|
Mutex::Autolock _l(mLock);
|
||||||
|
if (mPollLoop == 0) {
|
||||||
|
mPollLoop = new PollLoop(true);
|
||||||
|
mPollLoop->setCallback(getFd(), POLLIN, NULL, NULL);
|
||||||
|
}
|
||||||
|
return mPollLoop;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t SensorEventQueue::waitForEvent() const
|
||||||
|
{
|
||||||
|
const int fd = getFd();
|
||||||
|
sp<PollLoop> pollLoop(getPollLoop());
|
||||||
|
int32_t result = pollLoop->pollOnce(-1, NULL, NULL);
|
||||||
|
return (result == fd) ? NO_ERROR : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t SensorEventQueue::wake() const
|
||||||
|
{
|
||||||
|
sp<PollLoop> pollLoop(getPollLoop());
|
||||||
|
pollLoop->wake();
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t SensorEventQueue::enableSensor(Sensor const* sensor) const {
|
||||||
return mSensorEventConnection->enableDisable(sensor->getHandle(), true);
|
return mSensorEventConnection->enableDisable(sensor->getHandle(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t SensorEventQueue::disableSensor(Sensor const* sensor) const
|
status_t SensorEventQueue::disableSensor(Sensor const* sensor) const {
|
||||||
{
|
|
||||||
return mSensorEventConnection->enableDisable(sensor->getHandle(), false);
|
return mSensorEventConnection->enableDisable(sensor->getHandle(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t SensorEventQueue::setEventRate(Sensor const* sensor, nsecs_t ns) const
|
status_t SensorEventQueue::enableSensor(int32_t handle) const {
|
||||||
{
|
return mSensorEventConnection->enableDisable(handle, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t SensorEventQueue::disableSensor(int32_t handle) const {
|
||||||
|
return mSensorEventConnection->enableDisable(handle, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t SensorEventQueue::setEventRate(Sensor const* sensor, nsecs_t ns) const {
|
||||||
return mSensorEventConnection->setEventRate(sensor->getHandle(), ns);
|
return mSensorEventConnection->setEventRate(sensor->getHandle(), ns);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define LOG_TAG "Sensors"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
@ -21,6 +23,8 @@
|
|||||||
#include <utils/RefBase.h>
|
#include <utils/RefBase.h>
|
||||||
#include <utils/Singleton.h>
|
#include <utils/Singleton.h>
|
||||||
|
|
||||||
|
#include <binder/IServiceManager.h>
|
||||||
|
|
||||||
#include <gui/ISensorServer.h>
|
#include <gui/ISensorServer.h>
|
||||||
#include <gui/ISensorEventConnection.h>
|
#include <gui/ISensorEventConnection.h>
|
||||||
#include <gui/Sensor.h>
|
#include <gui/Sensor.h>
|
||||||
@ -36,25 +40,40 @@ ANDROID_SINGLETON_STATIC_INSTANCE(SensorManager)
|
|||||||
SensorManager::SensorManager()
|
SensorManager::SensorManager()
|
||||||
: mSensorList(0)
|
: mSensorList(0)
|
||||||
{
|
{
|
||||||
|
const String16 name("sensorservice");
|
||||||
|
while (getService(name, &mSensorServer) != NO_ERROR) {
|
||||||
|
usleep(250000);
|
||||||
|
}
|
||||||
|
|
||||||
mSensors = mSensorServer->getSensorList();
|
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()
|
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;
|
*list = mSensorList;
|
||||||
return mSensors.size();
|
return mSensors.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
Sensor* SensorManager::getDefaultSensor(int type)
|
Sensor const* SensorManager::getDefaultSensor(int type)
|
||||||
{
|
{
|
||||||
// TODO: needs implementation
|
// For now we just return the first sensor of that type we find.
|
||||||
return mSensorList;
|
// 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()
|
sp<SensorEventQueue> SensorManager::createEventQueue()
|
||||||
|
@ -43,17 +43,18 @@ ASensorManager* ASensorManager_getInstance()
|
|||||||
return &SensorManager::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);
|
int c = static_cast<SensorManager*>(manager)->getSensorList(&l);
|
||||||
if (list) {
|
if (list) {
|
||||||
*list = l;
|
*list = reinterpret_cast<ASensorList>(l);
|
||||||
}
|
}
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASensor* ASensorManager_getDefaultSensor(ASensorManager* manager, int type)
|
ASensor const* ASensorManager_getDefaultSensor(ASensorManager* manager, int type)
|
||||||
{
|
{
|
||||||
return static_cast<SensorManager*>(manager)->getDefaultSensor(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(
|
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(
|
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)
|
int32_t usec)
|
||||||
{
|
{
|
||||||
return static_cast<SensorEventQueue*>(queue)->setEventRate(
|
return static_cast<SensorEventQueue*>(queue)->setEventRate(
|
||||||
static_cast<Sensor*>(sensor), us2ns(usec));
|
static_cast<Sensor const*>(sensor), us2ns(usec));
|
||||||
}
|
}
|
||||||
|
|
||||||
int ASensorEventQueue_hasEvents(ASensorEventQueue* queue)
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,6 +87,7 @@ enum {
|
|||||||
* A sensor event.
|
* A sensor event.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* NOTE: Must match hardware/sensors.h */
|
||||||
typedef struct ASensorVector {
|
typedef struct ASensorVector {
|
||||||
union {
|
union {
|
||||||
float v[3];
|
float v[3];
|
||||||
@ -95,23 +96,32 @@ typedef struct ASensorVector {
|
|||||||
float y;
|
float y;
|
||||||
float z;
|
float z;
|
||||||
};
|
};
|
||||||
|
struct {
|
||||||
|
float azimuth;
|
||||||
|
float pitch;
|
||||||
|
float roll;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
int8_t status;
|
int8_t status;
|
||||||
uint8_t reserved[3];
|
uint8_t reserved[3];
|
||||||
} ASensorVector;
|
} ASensorVector;
|
||||||
|
|
||||||
|
/* NOTE: Must match hardware/sensors.h */
|
||||||
typedef struct ASensorEvent {
|
typedef struct ASensorEvent {
|
||||||
int sensor;
|
int32_t version; /* sizeof(struct ASensorEvent) */
|
||||||
|
int32_t sensor;
|
||||||
|
int32_t type;
|
||||||
int32_t reserved0;
|
int32_t reserved0;
|
||||||
|
int64_t timestamp;
|
||||||
union {
|
union {
|
||||||
float data[16];
|
float data[16];
|
||||||
|
ASensorVector vector;
|
||||||
ASensorVector acceleration;
|
ASensorVector acceleration;
|
||||||
ASensorVector magnetic;
|
ASensorVector magnetic;
|
||||||
float temperature;
|
float temperature;
|
||||||
float distance;
|
float distance;
|
||||||
float light;
|
float light;
|
||||||
};
|
};
|
||||||
int64_t timestamp;
|
|
||||||
int32_t reserved1[4];
|
int32_t reserved1[4];
|
||||||
} ASensorEvent;
|
} ASensorEvent;
|
||||||
|
|
||||||
@ -124,6 +134,8 @@ typedef struct ASensorEventQueue ASensorEventQueue;
|
|||||||
|
|
||||||
struct ASensor;
|
struct ASensor;
|
||||||
typedef struct ASensor 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.
|
* 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
|
* Returns the default sensor for the given type, or NULL if no sensor
|
||||||
* of that type exist.
|
* 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.
|
* 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.
|
* 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.
|
* 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.
|
* Sets the delivery rate of events in microseconds for the given sensor.
|
||||||
@ -179,7 +191,7 @@ int ASensorEventQueue_disableSensor(ASensorEventQueue* queue, ASensor* sensor);
|
|||||||
* rate.
|
* rate.
|
||||||
* Returns a negative error code on failure.
|
* 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
|
* 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)
|
* 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)
|
* 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
|
* Return this sensor's type
|
||||||
*/
|
*/
|
||||||
int ASensor_getType(ASensor* sensor);
|
int ASensor_getType(ASensor const* sensor);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns this sensors's resolution
|
* Returns this sensors's resolution
|
||||||
*/
|
*/
|
||||||
float ASensor_getResolution(ASensor* sensor);
|
float ASensor_getResolution(ASensor const* sensor);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -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();
|
|
||||||
}
|
|
@ -165,10 +165,6 @@ class ServerThread extends Thread {
|
|||||||
Watchdog.getInstance().init(context, battery, power, alarm,
|
Watchdog.getInstance().init(context, battery, power, alarm,
|
||||||
ActivityManagerService.self());
|
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");
|
Slog.i(TAG, "Window Manager");
|
||||||
wm = WindowManagerService.main(context, power,
|
wm = WindowManagerService.main(context, power,
|
||||||
factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL);
|
factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL);
|
||||||
|
@ -7,7 +7,6 @@ LOCAL_SRC_FILES:= \
|
|||||||
com_android_server_InputManager.cpp \
|
com_android_server_InputManager.cpp \
|
||||||
com_android_server_LightsService.cpp \
|
com_android_server_LightsService.cpp \
|
||||||
com_android_server_PowerManagerService.cpp \
|
com_android_server_PowerManagerService.cpp \
|
||||||
com_android_server_SensorService.cpp \
|
|
||||||
com_android_server_SystemServer.cpp \
|
com_android_server_SystemServer.cpp \
|
||||||
com_android_server_VibratorService.cpp \
|
com_android_server_VibratorService.cpp \
|
||||||
com_android_server_location_GpsLocationProvider.cpp \
|
com_android_server_location_GpsLocationProvider.cpp \
|
||||||
|
@ -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
|
|
@ -9,7 +9,6 @@ int register_android_server_BatteryService(JNIEnv* env);
|
|||||||
int register_android_server_InputManager(JNIEnv* env);
|
int register_android_server_InputManager(JNIEnv* env);
|
||||||
int register_android_server_LightsService(JNIEnv* env);
|
int register_android_server_LightsService(JNIEnv* env);
|
||||||
int register_android_server_PowerManagerService(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_VibratorService(JNIEnv* env);
|
||||||
int register_android_server_SystemServer(JNIEnv* env);
|
int register_android_server_SystemServer(JNIEnv* env);
|
||||||
int register_android_server_location_GpsLocationProvider(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_LightsService(env);
|
||||||
register_android_server_AlarmManagerService(env);
|
register_android_server_AlarmManagerService(env);
|
||||||
register_android_server_BatteryService(env);
|
register_android_server_BatteryService(env);
|
||||||
register_android_server_SensorService(env);
|
|
||||||
register_android_server_VibratorService(env);
|
register_android_server_VibratorService(env);
|
||||||
register_android_server_SystemServer(env);
|
register_android_server_SystemServer(env);
|
||||||
register_android_server_location_GpsLocationProvider(env);
|
register_android_server_location_GpsLocationProvider(env);
|
||||||
|
28
services/sensorservice/Android.mk
Normal file
28
services/sensorservice/Android.mk
Normal file
@ -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)
|
359
services/sensorservice/SensorService.cpp
Normal file
359
services/sensorservice/SensorService.cpp
Normal file
@ -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
|
||||||
|
|
119
services/sensorservice/SensorService.h
Normal file
119
services/sensorservice/SensorService.h
Normal file
@ -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
|
14
services/sensorservice/tests/Android.mk
Normal file
14
services/sensorservice/tests/Android.mk
Normal file
@ -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)
|
90
services/sensorservice/tests/sensorservicetest.cpp
Normal file
90
services/sensorservice/tests/sensorservicetest.cpp
Normal file
@ -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;
|
||||||
|
}
|
Reference in New Issue
Block a user