感應器硬體抽象層 (HAL) 是 Android 感應器架構與裝置感應器 (例如加速計或陀螺儀) 之間的介面。Sensors HAL 會定義必須實作的函式,以便讓架構控制感應器。
新裝置和升級裝置可在 Android 13 以上版本使用 Sensors AIDL HAL。感應器 AIDL HAL 以感應器 HAL 2.1 為基礎,並採用 AIDL HAL 介面,並公開頭戴式追蹤器和有限軸 IMU 感應器類型。
AIDL HAL 介面
Sensors AIDL HAL 的主要說明文件來源位於 HAL 定義中,位址為 hardware/interfaces/sensors/aidl/android/hardware/sensors/ISensors.aidl。
實作 Sensors AIDL HAL
如要實作 Sensors AIDL HAL,物件必須擴充 ISensors
介面,並實作 hardware/interfaces/sensors/aidl/android/hardware/sensors/ISensors.aidl 中定義的所有函式。
初始化 HAL
必須由 Android 感應器架構初始化 Sensors HAL,才能使用該架構。架構會呼叫 initialize()
函式,為 Sensors HAL 提供三個參數:兩個 FMQ 描述元和一個指向 ISensorsCallback
物件的指標。
HAL 會使用第一個描述元建立事件 FMQ,用於將感應器事件寫入架構。HAL 會使用第二個描述項建立 Wake Lock FMQ,用於在 HAL 釋出 WAKE_UP
感應器事件的喚醒鎖時進行同步。HAL 必須儲存指向 ISensorsCallback
物件的指標,以便叫用任何必要的回呼函式。
initialize()
函式必須是初始化 Sensors HAL 時呼叫的第一個函式。
公開可用感應器
如要取得裝置中所有可用的靜態感應器清單,請使用 getSensorsList()
函式。這個函式會傳回感應器清單,每個感應器都會透過其處理常式進行唯一識別。代管 Sensors HAL 的程序重新啟動時,特定感應器的句柄不得變更。裝置重新啟動和系統伺服器重新啟動時,帳號代碼可能會變更。
如果多個感應器共用相同的感應器類型和喚醒屬性,清單中的第一個感應器就會稱為「預設」感應器,並傳回給使用 getDefaultSensor(int sensorType, bool wakeUp)
函式的應用程式。
感應器清單的穩定性
在 Sensors HAL 重新啟動後,如果 getSensorsList()
傳回的資料與重新啟動前擷取的感應器清單相比有重大變化,架構會觸發 Android 執行階段的重新啟動程序。感應器清單的重大變更包括:特定句柄的缺少或屬性變更,或是新增感應器的情況。雖然重新啟動 Android 執行階段會對使用者造成干擾,但這是必要的,因為 Android 架構無法再符合 Android API 合約,即在應用程式生命週期內,靜態 (非動態) 感應器不會變更。這也可能會導致架構無法重新建立應用程式提出的有效感應器要求。因此,建議 HAL 供應商避免變更感應器清單。
為確保感應器能穩定運作,HAL 必須以確定性的方式將裝置中的特定物理感應器對應到其控制代碼。雖然感應器 HAL 介面不需要特定實作,但開發人員有很多選項可以滿足這項需求。
舉例來說,您可以使用各個感應器的固定屬性組合 (例如供應商、型號和感應器類型) 來排序感應器清單。另一個選項則是依據裝置的靜態感應器組在硬體中固定的事實,因此 HAL 需要知道所有預期的感應器何時完成初始化,才能從 getSensorsList()
返回。這份清單的預期感應器清單可以編譯為 HAL 二進位檔,或儲存在檔案系統的設定檔中。外觀順序可用來衍生穩定的控點。雖然最佳解決方案取決於 HAL 的具體實作細節,但主要要求是感應器句柄在 HAL 重新啟動時不會變更。
設定感應器
在啟用感應器之前,您必須使用 batch()
函式,為感應器設定取樣週期和最大回報延遲時間。
感應器必須能夠隨時使用 batch()
重新設定,且不會遺失感應器資料。
取樣期間
取樣週期會因所設定的感應器類型而有所不同:
- 連續:感應器事件會以連續速率產生。
- 變更時:事件產生頻率不得高於取樣週期,如果測量值沒有變更,產生事件的頻率可能會低於取樣週期。
- 單一:略過取樣期間。
- 特殊:詳情請參閱「感應器類型」。
如要瞭解取樣週期與感應器回報模式之間的互動關係,請參閱「回報模式」。
回報延遲時間上限
報表延遲時間上限決定事件在 SoC 處於喚醒狀態時,事件在硬體 FIFO 寫入事件 FMQ 前,最多可以延遲 (以奈秒為單位) 進行設定。
值為零表示事件必須在測量後立即回報,也就是說,要麼完全略過 FIFO,要麼在 FIFO 中出現感應器事件後立即清空 FIFO。
舉例來說,如果加速計以 50 Hz 的頻率啟用,且最大回報延遲為零,則在 SoC 喚醒時,會觸發每秒 50 次的中斷。
當最大回報延遲時間大於零時,感應器事件就不需要在偵測到後立即回報。只要事件無法延遲超過報表延遲時間上限,事件就可以暫時儲存在硬體 FIFO 中並分批回報。系統會記錄並一次傳回上一個批次以來的所有事件。這麼做可減少傳送至 SoC 的中斷數量,並讓 SoC 在感應器擷取及批次處理資料時,切換至低功耗模式。
每個事件都會與時間戳記相關聯。延遲回報事件的時間,不得影響事件時間戳記。時間戳記必須準確,且必須對應實際發生事件的時間,而非回報事件的時間。
如要進一步瞭解如何以非零值的最大回報延遲時間回報感應器事件,以及相關規定,請參閱「批次處理」一文。
啟用感應器
這個架構會使用 activate()
函式啟用及停用感應器。啟用感應器前,架構必須先使用 batch()
設定感應器。
感應器停用後,該感應器的其他感應器事件不得寫入事件 FMQ。
沖洗感應器
如果將感應器設為批次處理感應器資料,架構可以呼叫 flush()
,強制立即清除批次感應器事件。這會導致指定感應器句柄的批次感應器事件立即寫入事件 FMQ。Sensors HAL 必須在呼叫 flush()
後寫入的感應器事件結尾處,附加一個刷新完成事件。
清除作業會以非同步方式執行 (也就是說,這個函式必須立即傳回)。如果實作項目針對多個感應器使用單一 FIFO,該 FIFO 就會清除,且只會針對指定的感應器新增清除完成事件。
如果指定的感應器沒有 FIFO (可能沒有緩衝處理),或 FIFO 在呼叫時為空白,則 flush()
仍必須成功,並針對該感應器傳送清除完成事件。除了一次性感應器以外,所有感應器都適用這項做法。
如果 flush()
是針對一次性感應器呼叫,則 flush()
必須傳回 BAD_VALUE
,且不得產生刷新完成事件。
將感應器事件寫入 FMQ
Sensors HAL 會使用事件 FMQ,將感應器事件推送至 Android 感應器架構。
事件 FMQ 是同步的 FMQ,也就是說,如果嘗試將比可用空間還多的事件寫入 FMQ,寫入作業就會失敗。在這種情況下,HAL 應判斷是否要將目前的事件組寫入兩個較小的事件組,或是在有足夠空間時將所有事件一起寫入。
當 Sensors HAL 將所需數量的感應器事件寫入 Event FMQ 時,Sensors HAL 必須將 EventQueueFlagBits::READ_AND_PROCESS
位元寫入 Event FMQ 的 EventFlag::wake
函式,通知架構事件已就緒。您可以使用 EventFlag::createEventFlag
和 Event FMQ 的 getEventFlagWord()
函式,從 Event FMQ 建立 EventFlag。
感應器 AIDL HAL 可支援事件 FMQ 的 write
和 writeBlocking
。
預設實作會提供 write
使用參照。如果使用 writeBlocking
函式,readNotification
旗標必須設為 EventQueueFlagBits::EVENTS_READ
;此旗標會從架構讀取事件 FMQ 事件時設定。寫入通知標記必須設為 EventQueueFlagBits::READ_AND_PROCESS
,以便通知架構已將事件寫入事件 FMQ。
WAKE_UP 事件
WAKE_UP
事件是感應器事件,會導致應用程式處理器 (AP) 喚醒並立即處理事件。每當 WAKE_UP
事件寫入 Event FMQ 時,Sensors HAL 必須確保喚醒鎖定,確保系統保持喚醒狀態,直到架構可以處理事件為止。收到 WAKE_UP
事件後,架構會保護自己的喚醒鎖定,讓 Sensors HAL 釋放喚醒鎖定。如要同步處理感應器 HAL 釋出其 Wake Lock 的時機,請使用 Wake Lock FMQ。
Sensors HAL 必須讀取 Wake Lock FMQ,才能判斷架構已處理的 WAKE_UP
事件數量。只有在未處理的 WAKE_UP
事件總數為零時,HAL 才應釋放 WAKE_UP
事件的喚醒鎖定。處理感應器事件後,架構會計算標示為 WAKE_UP
事件的事件數,並將這個數字寫回 Wake Lock FMQ。
每當架構將資料寫入 Wake Lock FMQ 時,就會在 Wake Lock FMQ 上設定 WakeLockQueueFlagBits::DATA_WRITTEN
寫入通知。
動態感應器
動態感應器並非裝置的實體元件,但可用於裝置的輸入,例如具有加速計的遊戲控制器。
連接動態感應器時,必須透過 Sensors HAL 呼叫 ISensorsCallback
中的 onDynamicSensorConnected
函式。這會通知架構新的動態感應器,並允許透過架構控制感應器,讓客戶使用感應器事件。
同樣地,當動態感應器中斷連線時,必須呼叫 ISensorsCallback
中的 onDynamicSensorDisconnected
函式,讓架構移除任何不再可用的感應器。
直接管道
直接管道是一種運作方式,可將感應器事件寫入特定記憶體,而非寫入 Event FMQ,藉此略過 Android 感應器架構。註冊直接管道的用戶端必須直接從用於建立直接管道的記憶體讀取感應器事件,且不會透過架構接收感應器事件。configDirectReport()
函式與 batch()
的正常運作類似,可設定直接回報管道。
registerDirectChannel()
和 unregisterDirectChannel()
函式會建立或刪除新的直接管道。
作業模式
setOperationMode()
函式可讓架構設定感應器,以便架構將感應器資料注入感應器。這很適合用於測試,尤其是存在於架構下的演算法。
injectSensorData()
函式通常用於將作業參數推送至 Sensors HAL。這個函式也可以用來將感應器事件插入特定感應器。
驗證
如要驗證 Sensors HAL 的導入方式,請執行感應器 CTS 和 VTS 測試。
CTS 測試
感應器 CTS 測試會出現在自動 CTS 測試和手動 CTS Verifier 應用程式中。
自動化測試位於 cts/tests/sensor/src/android/hardware/cts。這些測試會驗證感應器的標準功能,例如啟用感應器、批次處理和感應器事件速率。
CTS Verifier 測試位於 cts/apps/CtsVerifier/src/com/android/cts/verifier/sensors。這些測試需要測試操作員手動輸入資料,並確保感應器回報的值正確無誤。
通過 CTS 測試非常重要,因為這可確保測試中的裝置符合所有 CDD 要求。
VTS 測試
Sensors AIDL HAL 的 VTS 測試位於 hardware/interfaces/sensors/aidl/vts/。這些測試可確保 Sensors HAL 正確實作,且 ISensors.aidl
和 ISensorsCallback.aidl
內的所有需求都正確滿足。
初始化 HAL
必須支援 initialize()
函式,才能在架構和 HAL 之間建立 FMQ。
公開可用的感應器
在 Sensors AIDL HAL 中,getSensorsList()
函式必須在單一裝置啟動期間傳回相同的值,即使在 Sensors HAL 重新啟動時也是如此。getSensorsList()
函式的一項新規定是,即使在感應器 HAL 重新啟動的情況下,它必須在單一裝置啟動期間傳回相同的值。這樣一來,如果系統伺服器重新啟動,架構就能嘗試重新建立感應器連線。裝置重新啟動後,getSensorsList()
傳回的值可能會變更。
將感應器事件寫入 FMQ
在 Sensors AIDL HAL 中,Sensors HAL 必須在感應器事件可用時主動將感應器事件寫入 Event FMQ,而非等待 poll()
呼叫。HAL 也負責將正確的位元寫入 EventFlag
,以便在架構中讀取 FMQ。
WAKE_UP 事件
在 Sensors HAL 1.0 中,HAL 可在 WAKE_UP
發布至 poll()
後,針對任何後續對 poll()
的呼叫,釋放任何 WAKE_UP
事件的喚醒鎖定,因為這表示架構已處理所有感應器事件,並在必要時取得喚醒鎖定。由於在 Sensors AIDL HAL 中,當架構處理寫入 FMQ 的事件時,HAL 不會再收到通知,因此 Wake Lock FMQ 可讓架構在處理 WAKE_UP
事件時與 HAL 通訊。
在 Sensors AIDL HAL 中,Sensors HAL 為 WAKE_UP
事件提供的喚醒鎖定機制,開頭必須是 SensorsHAL_WAKEUP
。
動態感應器
系統使用感應器 HAL 1.0 中的 poll()
函式傳回動態感應器。每當動態感應器連線發生變更時,Sensors AIDL HAL 就會要求呼叫 ISensorsCallback
中的 onDynamicSensorsConnected
和 onDynamicSensorsDisconnected
。這些回呼會做為透過 initialize()
函式提供的 ISensorsCallback
指標的一部分提供。
運作模式
必須支援 WAKE_UP
感應器的 DATA_INJECTION
模式。
支援多種 HAL
Sensors AIDL HAL 支援使用 Sensors Multi-HAL 架構的多 HAL。如需實作詳細資訊,請參閱「從 Sensors HAL 2.1 移植」。