天天看點

android中Sensor 工作流程

JAVA 程式

我們使用 sensor 接口一般隻要注冊一下 SensorListener 像下面這樣

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

ApiDemo:

     mGraphView = new GraphView(this);

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

這裡的 listener 是因為 sensor 狀态變化要産生變化的控件

然後在控件裡重載 on

SensorChanged 和 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

       {"_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.

     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.

     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) {

                 SENSORS_HARDWARE_DATA, (struct hw_device_t**)device);

static inline int sensors_data_close(struct sensors_data_device_t* device) {

轉載于http://yueguc.iteye.com/blog/855450

繼續閱讀