android中Sensor 工作流程

來源:互聯網
上載者:User

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
先看一眼它的方法註冊
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 { 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.