您的位置:首页 > 移动开发 > Android开发

Android传感器Sensor工作流程

2013-07-01 00:07 260 查看
我们使用 sensor 接口一般只要注册一下 SensorListener 像下面这样

**************************************************************

ApiDemo:

mGraphView = new GraphView(this);

mSensorManager.registerListener(mGraphView,....);

**************************************************************

这里的 listener 是因为 sensor 状态变化要产生变化的控件

然后在控件里重载 onSensorChanged 和 onAccuracyChanged 方法

public void onSensorChanged(int sensor, float[] values)

public void onAccuracyChanged(int sensor, int accuracy)

SensorManager

Sensor 主体代码和流程在 frameworks/base/core/java/android/hardware/SensorManager.java 里面

1.registerListener 其实是调用 registerLegacyListener:

public boolean registerListener(SensorListener listener, int sensors, int rate) {

...

result = registerLegacyListener(...);

...

}

2. registerLegacyListener 其实就是构造一个 LegacyListener 对象并将其加入 HashMap 中去

private boolean registerLegacyListener(int legacyType, int type,

SensorListener listener, int sensors, int rate)

{

...

legacyListener = new LegacyListener(listener);

mLegacyListenersMap.put(listener, legacyListener); //private HashMap<SensorListener,

LegacyListener> mLegacyListenersMap

...

}

3. LegacyListener 做了 2 件事 一个是调用我们重载的那 2 个接口 还有一个就是将 sensor 的

数据刷到我们的设备显示界面上去

private class LegacyListener implements SensorEventListener {

...

LegacyListener(SensorListener target) {

mTarget = target;

mSensors = 0;

}

public void onSensorChanged(SensorEvent event) {

...

mapSensorDataToWindow();

mTarget.onSensorChanged(...);//private SensorListener mTarget;

...

}

public void onAccuracyChanged(Sensor sensor, int accuracy) {

...

}

}

代码最后是一些 native 方法:

private static native void nativeClassInit();//SensorManager 构造函数里调用

private static native int sensors_module_init();//SensorManager 构造函数里调用

private static native int sensors_module_get_next_sensor(Sensor sensor, int

next);//SensorManager 构造函数里调用

// Used within this module from outside SensorManager, don't make private

static native int sensors_data_init();//SensorThread 构造里调用

static native int sensors_data_uninit();//SensorThread 析构里调用

static native int sensors_data_open(FileDescriptor fd); //SensorThread 的 run()循环调用

static native int sensors_data_close();//SensorThread 的 run()循环调用

static native int sensors_data_poll(float[] values, int[] status, long[] timestamp);//SensorThread

的 run()循环调用

SensorManager 与 IsensorService 的关系

SensorManager 调用 IsensorService 其实只是调用了 service 的方法来控制 thread 是 Lock

void startLocked(ISensorService service) {

...

ParcelFileDescriptor fd = service.getDataChanel();

...

}

或者打开

mSensorService.enableSensor(l, name, handle, delay);

IsensorService 的实例是这么获得的

mSensorService = ISensorService.Stub.asInterface(

ServiceManager.getService(Context.SENSOR_SERVICE));

IsensorService 是通过 aidl 定义的

interface ISensorService

{

ParcelFileDescriptor getDataChanel();

boolean enableSensor(IBinder listener, String name, int sensor, int enable);

}

SensorService

frameworks/base/services/java/com/android/server/SensorService.java

class SensorService extends ISensorService.Stub {

...

}

service 最终被 manager 调到走的是 android 的标准流程我们不 care,我们想知道的其实就是

enableSensor 的实现

首先,得有电

if (enable == SENSOR_DISABLE) {

mBatteryStats.noteStopSensor(uid, sensor);

} else {

mBatteryStats.noteStartSensor(uid, sensor);

}

看是不是能打开 sensor

if (enable!=SENSOR_DISABLE && !_sensors_control_activate(sensor, true)) {

Log.w(TAG, "could not enable sensor " + sensor);

return false;

}

如果 sensor 打开了 我们要监听状态还要对外面报告状态变化

if (l == null && enable!=SENSOR_DISABLE) {

l = new Listener(binder);

binder.linkToDeath(l, 0);

mListeners.add(l);

mListeners.notify();

}

如果 sensor 被关闭了 我们要取消监听并且告诉外面关闭了传感

if (enable != SENSOR_DISABLE) {

l.addSensor(sensor, enable);

} else {

l.removeSensor(sensor);

deactivateIfUnused(sensor);

if (l.mSensors == 0) {

mListeners.remove(l);

binder.unlinkToDeath(l, 0);

mListeners.notify();

}

}

另外还有一些唤醒和设置延迟的动作

if (mListeners.size() == 0) {

_sensors_control_wake();

}

if (minDelay >= 0) {

_sensors_control_set_delay(minDelay);

}

从上面可以看出来 对于底层而言只要知道上层怎么调用传感的接口就好 所以最关心的还是

我标绿的 native 方法 上层的传感流程其实比较简单 就是标准的 service 管理和 notify 流程

private static native int _sensors_control_init();

private static native ParcelFileDescriptor _sensors_control_open();

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();

native 方法

1. manager 部分

frameworks/base/core/jni/android_hardware_SensorManager.cpp

先看一眼它的方法注册

static JNINativeMethod gMethods[] = {

{"nativeClassInit", "()V", (void*)nativeClassInit },

{"sensors_module_init","()I", (void*)sensors_module_init },

{"sensors_module_get_next_sensor","(Landroid/hardware/Sensor;I)I",

(void*)sensors_module_get_next_sensor },

{"sensors_data_init", "()I", (void*)sensors_data_init },

{"sensors_data_uninit", "()I", (void*)sensors_data_uninit },

{"sensors_data_open", "(Ljava/io/FileDescriptor;)I", (void*)sensors_data_open },

{"sensors_data_close", "()I", (void*)sensors_data_close },

{"sensors_data_poll", "([F[I[J)I", (void*)sensors_data_poll },

};

小贴一个例子作为代表

static jint

sensors_data_open(JNIEnv *env, jclass clazz, jobject fdo)

{

jclass FileDescriptor = env->FindClass("java/io/FileDescriptor");

jfieldID offset = env->GetFieldID(FileDescriptor, "descriptor", "I");

int fd = env->GetIntField(fdo, offset);

return sSensorDevice->data_open(sSensorDevice, fd); // doesn't take ownership of fd

}

调用到最后其实都是用的 sSensorDevice 的方法

/*

* The method below are not thread-safe and not intended to be

*/

static sensors_data_device_t* sSensorDevice = 0;

2.service 部分

frameworks/base/services/jni/com_android_server_SensorService.cpp

先看一眼它的方法注册

static JNINativeMethod gMethods[] = {

{"_sensors_control_init", "()I", (void*) android_init },

{"_sensors_control_open", "()Landroid/os/ParcelFileDescriptor;", (void*) android_open },

{"_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 },

};

然后上面的那些方法我就不一一贴了 给出一个例子 其实这么实现的

static jboolean

android_activate(JNIEnv *env, jclass clazz, jint sensor, jboolean activate)

{

int active = sSensorDevice->activate(sSensorDevice, sensor, activate);

return (active<0) ? false : true;

}

所以最后调用的其实都是 sSensorDevice 的方法 其他的几个也是这样 sSensorDevice 是这个

(不是线程安全的)

/*

* The method below are not thread-safe and not intended to be

*/

static sensors_control_device_t* sSensorDevice = 0;

3.继续追 终于到了硬件层了 最后一切的方法其实就在这里了

hardware/libhardware/include/hardware/sensor.h

struct sensors_control_device_t {

struct hw_device_t common;

/**

* Returns the fd which will be the parameter to

* sensors_data_device_t::open_data().

* The caller takes ownership of this fd. This is intended to be

* passed cross processes.

*

* @return a fd if successful, < 0 on error

*/

int (*open_data_source)(struct sensors_control_device_t *dev);

/** Activate/deactivate one sensor.

*

* @param handle is the handle of the sensor to change.

* @param enabled set to 1 to enable, or 0 to disable the sensor.

*

* @return 0 on success, negative errno code otherwise

*/

int (*activate)(struct sensors_control_device_t *dev,

int handle, int enabled);

/**

* Set the delay between sensor events in ms

*

* @return 0 if successful, < 0 on error

*/

int (*set_delay)(struct sensors_control_device_t *dev, int32_t ms);

/**

* Causes sensors_data_device_t.poll() to return -EWOULDBLOCK immediately.

*/

int (*wake)(struct sensors_control_device_t *dev);

};

struct sensors_data_device_t {

struct hw_device_t common;

/**

* Prepare to read sensor data.

*

* This routine does NOT take ownership of the fd

* and must not close it. Typically this routine would

* use a duplicate of the fd parameter.

*

* @param fd from sensors_control_open.

*

* @return 0 if successful, < 0 on error

*/

int (*data_open)(struct sensors_data_device_t *dev, int fd);

/**

* Caller has completed using the sensor data.

* The caller will not be blocked in sensors_data_poll

* when this routine is called.

*

* @return 0 if successful, < 0 on error

*/

int (*data_close)(struct sensors_data_device_t *dev);

/**

* Return sensor data for one of the enabled sensors.

*

* @return sensor handle for the returned data, 0x7FFFFFFF when

* sensors_control_device_t.wake() is called and -errno on error

*

*/

int (*poll)(struct sensors_data_device_t *dev,

sensors_data_t* data);

};

最后一组函数

/** convenience API for opening and closing a device */

static inline int sensors_control_open(const struct hw_module_t* module,

struct sensors_control_device_t** device) {

return module->methods->open(module,

SENSORS_HARDWARE_CONTROL, (struct hw_device_t**)device);

}

static inline int sensors_control_close(struct sensors_control_device_t* device) {

return device->common.close(&device->common);

}

static inline int sensors_data_open(const struct hw_module_t* module,

struct sensors_data_device_t** device) {

return module->methods->open(module,

SENSORS_HARDWARE_DATA, (struct hw_device_t**)device);

}

static inline int sensors_data_close(struct sensors_data_device_t* device) {

return device->common.close(&device->common);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: