換工做在即,也有了可貴的一段空閒時間作下總結。接下來計劃分別介紹下Android的Sensor/Touch/Camera/Binder的Software架構,若是還有時間就總結下kernel。設計模式
Sensor屬於Android相對簡單的一個模塊,但麻雀雖小,五臟俱全,以此來做爲切入點對理解整個Android系統有很大幫助。必需要說的是,Android系統的總體架構並不適用於全部模塊,每一個模塊都有各自的特殊性,請不要一開始就把某些介紹看成公式。架構
不少模塊均可以稱爲Sensor,Touch是一種Sensor,Camera也能夠理解爲一種Sensor。但這裏介紹的Sensor架構並不適用於Touch和Camera,所使用的主要包含下面幾類Sensor。框架
Categorysocket |
Components函數 |
Motion Sensorsoop |
Accelerameter/ Gravity/ Gyroscope/ Rotation Vector/…優化 |
Environmental Sensorsspa |
ALS/ Pressure/…線程 |
Position Sensors設計 |
Orientation/ Mag/… |
這幾類器件有幾個類似的特色,產生的數據量少,實時性較強,構造相對簡單。
首先從總體上,Sensor的架構能夠用下圖來解釋。
有些分法把SensorService歸爲Framework的一部分,但這裏爲了凸顯出Service的重要性單獨分爲一層。
Sensor的總體邏輯很是清晰,一個控制流(藍色向下箭頭),一個數據流(紅色向上箭頭)。控制主要包括開關Sensor,設置Sensor的採樣頻率,數據流則是數據從驅動到應用的整個過程。
系統初始化過程當中,SensorService和HAL層(硬件抽象層)會進行初始化操做。SensorService鏈接着Framework和HAL,它採用動態連接加載HAL層模塊(HAL層以so共享文件的形式存在)。
//動態連接的匹配 hw_get_module(SENSORS_HARDWARE_MODULE_ID, (hw_module_t const**)&mSensorModule); //Service |
struct sensors_module_t my_hal = { common: { … id: SENSORS_HARDWARE_MODULE_ID, … }, get_sensors_list: …, }; //HAL |
一句話歸納該過程的目的就是,通過動態連接,Service能夠調用HAL層的函數,方便將控制傳遞至HAL層,也能夠從HAL獲取數據。完成該動做後,Service調用my_hal內的open函數。HAL能夠在open動做中完成初始化,如檢測系統中存在的Sensor,保存每一個Sensor的信息,維護一個全部的Sensor的列表。
HAL初始化後,Service便可調用get_sensors_list獲取系統所支持的全部Sensor。某些物理Sensor組合後,能夠虛擬出其餘Sensor,Service也會針對虛擬Sensor作處理,這部分暫不介紹。
一句話總結,與HAL創建聯繫(動態連接),HAL初始化(open),獲取Sensor信息(get_sensors_list)。
控制,一是開關,二是頻率,Android默認支持四種採樣頻率。
名稱 |
頻率 |
SENSOR_DELAY_FASTEST |
器件的最大采樣頻率 |
SENSOR_DELAY_GAME |
50HZ |
SENSOR_DELAY_UI |
30HZ |
SENSOR_DELAY_NORMAL |
5HZ |
除了這四種頻率之外,用戶也能夠指定一個特定頻率。控制的流程以下。
控制從APP註冊監聽器開始,熟悉面向對象程序設計的童鞋應該能夠猜獲得這是一個觀察者設計模式,實際上也確實如此。註冊監聽器的直接操做就是enable和setDelay兩個操做(unregisterListener則對應disable操做),Service與APP並非執行在同一個進程內的,Framework傳遞來的控制須要經過進程通訊傳遞至Service,使用的就是Binder(Binder幾乎貫穿了Android系統的各個模塊,後面介紹)。Service是惟一的,APP能夠有無限個,Service爲它們服務。這樣設計的緣由顯而易見——保證單一控制:硬件是惟一的(好比某一個加速度Sensor),對它的控制也應該是惟一的,不該該由各APP單獨控制。好比enable操做,若是已經有APP打開了設備,那麼只須要將引用計數增長1便可,並不會真正的觸發驅動的操做;disable操做,若是引用計數大於1,說明當前除了該APP,還有其餘使用者,那麼也不會觸發驅動的操做。
Service與HAL層屬於同一個進程,Service調用HAL層的函數,HAL找到對應的文件節點,根據不一樣的目的寫入不一樣的值來觸發驅動的操做。驅動根據獲得的指令,讀寫設定好的寄存器控制流就獲得了最終的落實。
一句話總結,應用開啓控制流,層層傳遞,最終讀寫寄存器。
五、數據流
數據由硬件產生,最終被應用使用,流程以下圖。
驅動負責收集數據(中斷或者輪詢模式),經過input子系統(也有部分廠商選擇使用IIO)上報數據。HAL層使用poll監控input節點,數據到來後poll返回,而後讀取數據。Service部分有一個線程,該線程能夠理解爲一個循環,不斷地poll HAL層的數據。收到數據後,Service會作一些處理(好比計算虛擬Sensor的數據),以後則經過socket將數據發送至APP進程。APP收到數據後,遍歷當前已經註冊的listener,通知它們,觀察者模式完成。
與控制流相同,數據流依然是一個Service對應多個APP,Service會將數據發送到多個APP。
說到這裏,有個地方能夠優化下。目前Service收到數據後,會通知全部的已經註冊了listener的APP,這個過程並非沒有代價的,除了正常的執行代碼外,還涉及了進程通訊。若是給APP添加一個感興趣的Sensor類型的列表(bitmap也可),只有列表內的Sensor的數據到來纔會通知該APP進程,會高效的多。
形象一點講,整個Sensor的軟件架構就像是水泵抽水灌溉。Service扮演電機的角色,它不斷的產生抽水的動力,並將水輸送至目的地(APP),驅動扮演泵的角色,它負責完成抽水的必要準備並抽水,HAL則很像是鏈接電機和泵的管道。
driver能夠邏輯上分爲三部分,以下圖。一部分支持它自己的功能,i2c讀寫,中斷或者輪詢處理。第二部分爲sysfs文件節點,接受HAL層傳遞下來的操做,經過i2c讀寫完成任務。第三部分爲input子系統(注意,該處爲Linux內核的input子系統,並非Android的input系統),負責數據上報。
一句話,driver的任務就是正常工做,完成控制操做,產生數據。
HAL層的做用一是屏蔽硬件差別,二是傳遞控制和數據。
SensorService自己就是一個線程(Thread爲其父類),不出意外它循環地執行threadLoop(Android的機制),該函數一方面負責poll數據,一方面獲得數據後處理,發送。
到了Framework,問題就簡單了,簡單的函數調用(最多涉及到jni)。
本文僅闡釋了整個框架,並未羅列出詳細的代碼,但願給出一個全局的介紹。
博客得來終覺淺,只因碼上才能見真知。如有任何疑問或者但願下一篇博客的內容介紹哪部分請直接留言或發郵件至郵箱(個人用戶名@onesixthree郵箱)。