1. 程式人生 > >Android之感測器系統(Gsensor)

Android之感測器系統(Gsensor)

最近在解關於Gsensor的Bug,Bug還沒解掉,反而把Android的Gsensor流程走了一遍。好久不寫部落格了,不能偷懶啊,學了東西還是得總結一下,好讓後來人不要費多少工夫,同時拋磚引玉,大家一起討論一下,有什麼錯誤我好糾正一下,對自己也是一種激勵。言歸正傳,本文主要從上層的Activity一直分析到kernel的driver,路比較長,不過我喜歡搞清楚架構。

目錄:

一、應用層的API;

二、Framwork中的處理;

三、C++中的JNI;

四、Kernel的Gsensor-driver;

一、應用層的API

先看一個例子,這個例子是Gsensor的最簡單應用,只是用來列印x,y,z的三個值:

  1. publicclass main extends Activity {    
  2.     privatefloat x, y, z;    
  3.     protectedvoid onCreate(Bundle savedInstanceState) {    
  4.         super.onCreate(savedInstanceState);   
  5.         SensorManager mSensorManager= (SensorManager) getSystemService(SENSOR_SERVICE);   
  6.         Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);  
  7.         SensorEventListener lsn = new SensorEventListener() {  
  8.                     publicvoid onSensorChanged(SensorEvent e) {  
  9.                             System.out.println(e.value[0]);  
  10.                             System.out.println(e.value[1]);  
  11.                             System.out.println(e.value[2
    ]);  
  12.                      }  
  13.                     publicvoid onAccuracyChanged(Sensor s, int accuracy) {  
  14.                     }      
  15.                };  
  16.                mSensorManager.registerListener(lsn, sensor, SensorManager.SENSOR_DELAY_GAME);  
  17. }  
  

    這段程式碼中我們重點關注這幾個類:SensorManager,SensorEvent;然後我們進入到Framework中看看這兩個類是如何實現,它們都做了什麼操作。

二、Framework中的處理

    相關檔案:/frameworks/base/core/java/android/hardware/SensorManager.java;

    這個SensorManager主要負責返回感測器型別,從底層獲得資料。getSystemService(String name)是根據名字返回相應的Manager,這個機制也比較重要,網上有相關資料,在此不展開討論了;mSensorManager.getDefaultSensor(type)就是獲取指定型別的感測器。這些型別在API手冊中都能查到,包括溫度感測器,重力感應器等。registerListener註冊監聽器,這是為了能讓ManagerSensor回撥正確的介面函式,註冊的時候我們可以指定sensor的靈敏度,分四個等級,API手冊中有相應介紹。我們來看一下SensorManager的建構函式:

     1.獲取windowManager例項,監控螢幕旋轉狀態;

     2.初始化sensorList感測器列表;呼叫了sensors_module_init()和sensors_module_get_next_sensor()兩個本地JNI方法;

     3.構造SensorThread執行緒(這裡執行緒並沒有開啟);

      系統中只維護了一個SensorManager,應用層的呼叫只是往SensorManager裡面註冊了一個監聽介面,然後使能相應的Sensor,設定Sensor的引數;SensorManager的獲取是通過呼叫getSystemService方法,這個方法會檢測SensorManager是否已經存在了,如果存在了一個例項就直接返回這個例項。

     下面重點分析一下SensorThread執行緒,這個執行緒的開啟是在registerListener裡面,SensorThread是一個死迴圈,他通過呼叫native方法sensors_data_poll方法來輪詢下層發來的感測器資料。每次接受到一個數據就會呼叫代理listener中的onSensorChangedLocked方法,把它封裝成一個訊息發給自己的messagerHandler,在這裡面最終呼叫註冊的onSensorChanged方法,也就是我們上面應用程式介面的中方法。

三、C++中的JNI

     相關檔案:/frameworks/base/core/jni/android_hardware_SensorManager.cpp;

     sensors_module_init()模組初始化-->hw_get_module()-->load(),其實就是把sensor.so的連結庫載入進來;

     sensor.so是與機器相關的hardware層來實現的,要在hardware下實現相應的sensor.cpp;這個檔案就是跟kernel打交道的最底層的檔案了。裡面主要完成了開啟裝置檔案,讀取裝置節點的資料。比如我們的Gsensor是走的輸入輸出子系統,就開啟相應的event檔案來讀取驅動上報的座標資料。

四、Kernel中的驅動

     這個我們的實現比較簡單,是走的input子系統。你可以選擇用中斷模式或者輪詢模式來讀取裝置發來的資料。

五、SensorService(對比SensorManager)

     其實還有一個非常重要的類沒有說,就是SensorService;現在有必要把整個Sensor總結分析一下了。

     系統開啟之後會依次啟動各種系統服務;原始碼在SystemServer.java中,在這裡系統會new一個SensorService,SensorService中會呼叫JNI方法_sensors_control_init,對應com_android_server_SersorService.cpp中的android_init();這個主要是初始化SensorDevice的控制代碼供以後呼叫;下面是com_android_server_SersorService.cpp註冊的JNI方法:

  1. static JNINativeMethod gMethods[] = {  
  2.     {"_sensors_control_init",     "()I",   (void*) android_init },  
  3.     {"_sensors_control_open",     "()Landroid/os/Bundle;",  (void*) android_open },  
  4.     {"_sensors_control_close",     "()I",  (void*) android_close },  
  5.     {"_sensors_control_activate""(IZ)Z", (void*) android_activate },  
  6.     {"_sensors_control_wake",     "()I", (void*) android_data_wake },  
  7.     {"_sensors_control_set_delay","(I)I", (void*) android_set_delay },  
  8. };  

    從這裡我們可以看出,SensorService這個類主要是負責控制Sensor裝置的。這些JNI函式最終都會呼叫到我們Sensor.cpp裡面的實現。對比我們的SensorManager中JNI的註冊:

  1. static JNINativeMethod gMethods[] = {  
  2.     {"nativeClassInit""()V",              (void*)nativeClassInit },  
  3.     {"sensors_module_init","()I",           (void*)sensors_module_init },  
  4.     {"sensors_module_get_next_sensor","(Landroid/hardware/Sensor;I)I",  
  5.                                             (void*)sensors_module_get_next_sensor },  
  6.     {"sensors_data_init""()I",            (void*)sensors_data_init },  
  7.     {"sensors_data_uninit""()I",          (void*)sensors_data_uninit },  
  8.     {"sensors_data_open",  "([Ljava/io/FileDescriptor;[I)I",  (void*)sensors_data_open },  
  9.     {"sensors_data_close""()I",           (void*)sensors_data_close },  
  10.     {"sensors_data_poll",  "([F[I[J)I",     (void*)sensors_data_poll },  
  11. };  

    不難看出,SensorManager主要負責的是資料的傳輸;

    OK,到這裡Sensor基本就分析完了。其中WindowManager跟Sensor打交道,實現轉屏等操作,這裡就先不做分析了。本人水平有限,接觸android也就兩個月的時間,有什麼不對或者欠妥的地方歡迎指正。