Android之感測器系統(Gsensor)
最近在解關於Gsensor的Bug,Bug還沒解掉,反而把Android的Gsensor流程走了一遍。好久不寫部落格了,不能偷懶啊,學了東西還是得總結一下,好讓後來人不要費多少工夫,同時拋磚引玉,大家一起討論一下,有什麼錯誤我好糾正一下,對自己也是一種激勵。言歸正傳,本文主要從上層的Activity一直分析到kernel的driver,路比較長,不過我喜歡搞清楚架構。
目錄:
一、應用層的API;
二、Framwork中的處理;
三、C++中的JNI;
四、Kernel的Gsensor-driver;
一、應用層的API
先看一個例子,這個例子是Gsensor的最簡單應用,只是用來列印x,y,z的三個值:
- publicclass main extends Activity {
- privatefloat x, y, z;
- protectedvoid onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- SensorManager mSensorManager= (SensorManager) getSystemService(SENSOR_SERVICE);
-
Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);
- SensorEventListener lsn = new SensorEventListener() {
- publicvoid onSensorChanged(SensorEvent e) {
- System.out.println(e.value[0]);
- System.out.println(e.value[1]);
-
System.out.println(e.value[2
- }
- publicvoid onAccuracyChanged(Sensor s, int accuracy) {
- }
- };
- mSensorManager.registerListener(lsn, sensor, SensorManager.SENSOR_DELAY_GAME);
- }
這段程式碼中我們重點關注這幾個類: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方法:
- 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 },
- };
從這裡我們可以看出,SensorService這個類主要是負責控制Sensor裝置的。這些JNI函式最終都會呼叫到我們Sensor.cpp裡面的實現。對比我們的SensorManager中JNI的註冊:
- 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)I", (void*)sensors_data_open },
- {"sensors_data_close", "()I", (void*)sensors_data_close },
- {"sensors_data_poll", "([F[I[J)I", (void*)sensors_data_poll },
- };
不難看出,SensorManager主要負責的是資料的傳輸;
OK,到這裡Sensor基本就分析完了。其中WindowManager跟Sensor打交道,實現轉屏等操作,這裡就先不做分析了。本人水平有限,接觸android也就兩個月的時間,有什麼不對或者欠妥的地方歡迎指正。