傳感器 AIDL HAL

感測器硬體抽象層 (HAL) 是 Android 感測器框架和裝置感測器(例如加速度計或陀螺儀)之間的介面。感測器 HAL 定義了框架控制感測器必須實現的功能。

感測器 AIDL HAL 在 Android 13 及更高版本中適用於新裝置和升級裝置。 Sensors AIDL HAL 基於Sensors HAL 2.1 ,使用AIDL HAL 介面並公開頭部追蹤器和限軸 IMU 感測器類型。

AIDL HAL介面

感測器 AIDL HAL 的主要文件來源位於hardware/interfaces/sensors/aidl/android/hardware/sensors/ISensors.aidl 的HAL 定義內。

實施感測器 AIDL HAL

要實作感測器 AIDL HAL,物件必須擴展ISensors介面並實作hardware/interfaces/sensors/aidl/android/hardware/sensors/ISensors.aidl中定義的所有函數。

初始化 HAL

Sensors HAL 必須由 Android 感測器框架初始化才能使用。框架呼叫initialize()函數向感測器HAL 提供三個參數:兩個FMQ 描述子和一個指向ISensorsCallback物件的指標。

HAL 使用第一個描述符建立事件 FMQ,用於將感測器事件寫入框架。 HAL 使用第二個描述符建立喚醒鎖定 FMQ,用於在 HAL 釋放WAKE_UP感測器事件的喚醒鎖定時進行同步。 HAL 必須保存指向ISensorsCallback物件的指針,以便可以呼叫任何必要的回調函數。

初始化感測器 HAL 時, initialize()函數必須是第一個呼叫的函數。

公開可用的感測器

若要取得裝置中所有可用靜態感測器的列表,請使用getSensorsList()函數。該函數傳回一個感測器列表,每個感測器都由其句柄唯一標識。當託管感測器 HAL 的進程重新啟動時,給定感測器的句柄不得更改。句柄可能會在設備重新啟動和系統伺服器重新啟動時變更。

如果多個感測器共用相同的感測器類型和喚醒屬性,則清單中的第一個感測器稱為預設感測器,並返回到使用getDefaultSensor(int sensorType, bool wakeUp)函數的應用程式。

感測器列表穩定性

Sensors HAL 重新啟動後,如果getSensorsList()傳回的資料顯示與重新啟動先前檢索到的感測器清單相比發生了重大變化,則框架會觸發 Android 運行時的重新啟動。感測器清單的重大更改包括具有給定句柄的感測器遺失或屬性已更改,或引入新感測器的情況。儘管重新啟動 Android 運行時會對使用者造成乾擾,但這是必要的,因為 Android 框架無法再滿足靜態(非動態)感測器在應用程式的生命週期內不會更改的 Android API 約定。這也可能會阻止框架重新建立應用程式發出的活動感測器請求。因此,建議 HAL 供應商防止可避免的感測器清單變更。

為了確保穩定的感測器句柄,HAL 必須確定地將裝置中給定的實體感測器對應到其句柄。儘管感測器 HAL 介面沒有強制要求具體實現,但開發人員可以使用多種選項來滿足此要求。

例如,可以使用每個感測器的固定屬性(例如供應商、型號和感測器類型)的組合來對感測器清單進行排序。另一種選擇依賴於裝置的靜態感測器集在硬體中固定的事實,因此 HAL 需要知道所有預期感測器何時完成初始化,然後再從getSensorsList()返回。此預期感測器清單可以編譯到 HAL 二進位檔案或儲存在檔案系統中的設定檔中,並且出現的順序可用於派生穩定句柄。儘管最佳解決方案取決於 HAL 的具體實作細節,但關鍵要求是感測器句柄不會在 HAL 重新啟動時發生變化。

配置感測器

在啟動感測器之前,必須使用batch()函數為感測器配置採樣週期和最大報告延遲。

感測器必須能夠隨時使用batch()重新配置,而不會遺失感測器資料。

採樣週期

根據所配置的感測器類型,採樣週期具有不同的意義:

  • 連續:感測器事件以連續速率產生。
  • 變化時:事件的產生速度不會快於取樣週期,如果測量值不變化,事件的產生速度可能會慢於取樣週期。
  • One-shot:忽略採樣週期。
  • 特別:有關更多詳細信息,請參閱感測器類型

若要了解採樣週期和感測器報告模式之間的交互作用,請參閱報告模式

最大報告延遲

最大報告延遲設定事件在 SoC 喚醒時透過 HAL 寫入事件 FMQ 之前可以延遲並儲存在硬體 FIFO 中的最大時間(以奈秒為單位)。

值為零表示必須在測量事件後立即報告事件,要么完全跳過 FIFO,要么一旦來自感測器的一個事件出現在 FIFO 中就清空 FIFO。

例如,當 SoC 喚醒時,以 50 Hz 啟動、最大報告延遲為零的加速計每秒觸發中斷 50 次。

當最大報告延遲大於零時,感測器事件不需要在偵測到後立即報告。事件可以暫時儲存在硬體 FIFO 中並批次報告,只要沒有事件延遲超過最大報告延遲即可。自上一批以來的所有事件都會立即記錄並返回。這減少了發送到 SoC 的中斷數量,並允許 SoC 在感測器捕獲和批次資料時切換到較低功耗模式。

每個事件都有一個與之關聯的時間戳記。延遲報告事件的時間不得影響事件時間戳。時間戳必須準確,並且對應於事件實際發生的時間,而不是報告的時間。

有關以非零最大報告延遲報告感測器事件的更多資訊和要求,請參閱批次

啟動感應器

該框架使用activate()函數啟用和停用感測器。在啟動感測器之前,框架必須先使用batch()配置感測器。

停用感測器後,不得將來自該感測器的其他感測器事件寫入事件 FMQ。

沖洗感測器

如果感測器配置為批次感測器數據,框架可以透過呼叫flush()強制立即刷新批次的感測器事件。這會導致指定感測器句柄的批次感測器事件立即寫入事件 FMQ。感測器 HAL 必須將刷新完成事件附加到由於呼叫flush()而寫入的感測器事件的末端。

刷新是異步發生的(也就是說,該函數必須立即返回)。如果實作對多個感測器使用單一 FIFO,則該 FIFO 將被刷新,並且僅為指定感測器添加刷新完成事件。

如果指定的感測器沒有 FIFO(不可能進行緩衝),或者調用時 FIFO 為空,則flush()仍必須成功並為該感測器發送刷新完成事件。這適用於除一次性感測器之外的所有感測器。

如果為一次性感測器呼叫了flush() ,則flush()必須傳回BAD_VALUE且不產生刷新完成事件。

將感測器事件寫入 FMQ

感測器 HAL 使用事件 FMQ 將感測器事件推送到 Android 感測器框架中。

事件 FMQ 是同步 FMQ,這意味著任何向 FMQ 寫入超出可用空間允許的事件的嘗試都會導致寫入失敗。在這種情況下,HAL 應確定是將當前事件集寫入兩個較小的事件群組,還是在有足夠空間可用時將所有事件寫入在一起。

當感測器 HAL 將所需數量的感測器事件寫入事件 FMQ 時,感測器 HAL 必須透過將EventQueueFlagBits::READ_AND_PROCESS位元寫入事件 FMQ 的EventFlag::wake函數來通知框架事件已準備就緒。可以使用EventFlag::createEventFlag和事件 FMQ 的getEventFlagWord()函數從事件 FMQ 建立 EventFlag。

感測器 AIDL HAL 支援事件 FMQ 上的writewriteBlocking 。預設實作提供了使用write的參考。如果使用writeBlocking函數,則readNotification標誌必須設定為EventQueueFlagBits::EVENTS_READ ,該標誌由框架在從 Event FMQ 讀取事件時設定。寫入通知標誌必須設定為EventQueueFlagBits::READ_AND_PROCESS ,它通知框架事件已寫入事件 FMQ。

WAKE_UP 事件

WAKE_UP事件是導致應用處理器 (AP) 喚醒並立即處理該事件的感測器事件。每當WAKE_UP事件寫入事件 FMQ 時,感測器 HAL 必須確保喚醒鎖定,以確保系統保持喚醒狀態,直到框架可以處理該事件。收到WAKE_UP事件後,框架會保護自己的喚醒鎖定,從而允許感測器 HAL 釋放其喚醒鎖定。若要在感測器 HAL 釋放其喚醒鎖定時進行同步,請使用喚醒鎖定 FMQ。

感測器 HAL 必須讀取喚醒鎖定 FMQ 以確定框架已處理的WAKE_UP事件的數量。僅當未處理的WAKE_UP事件總數為零時,HAL 才應釋放WAKE_UP事件的喚醒鎖定。處理感測器事件後,框架會計算標記為WAKE_UP事件的事件數量,並將該數字寫回喚醒鎖定 FMQ。

每當框架將資料寫入喚醒鎖定 FMQ 時,框架都會在喚醒鎖定 FMQ 上設定WakeLockQueueFlagBits::DATA_WRITTEN寫入通知。

動態感測器

動態感測器是物理上不屬於裝置一部分但可用作裝置輸入的感測器,例如帶有加速計的遊戲手把。

連接動態感測器時,必須從感測器 HAL 呼叫ISensorsCallback中的onDynamicSensorConnected函數。這會向框架通知新的動態感測器,並允許透過框架控制感測器並使客戶端使用感測器的事件。

同樣,當動態感測器斷開連接時,必須呼叫ISensorsCallback中的onDynamicSensorDisconnected函數,以便框架可以刪除不再可用的任何感測器。

直接管道

直接通道是一種操作方法,其中感測器事件被寫入特定內存,而不是繞過 Android 感測器框架寫入事件 FMQ。註冊直接通道的用戶端必須直接從用於建立直接通道的記憶體讀取感測器事件,並且不會透過框架接收感測器事件。 configDirectReport()函數與正常操作的batch()類似,設定直接報告通道。

registerDirectChannel()unregisterDirectChannel()函數創建或銷毀新的直接通道。

操作模式

setOperationMode()函數允許框架配置感測器,以便框架可以將感測器資料注入感測器。這對於測試很有用,特別是對於框架下方存在的演算法。

injectSensorData()函數通常用於將操作參數推送到感測器 HAL 中。此函數也可用於將感測器事件注入特定感測器。

驗證

若要驗證感測器 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 測試

感測器 AIDL HAL 的 VTS 測試位於hardware/interfaces/sensors/aidl/vts/中。這些測試可確保感測器 HAL 正確實現,並且ISensors.aidlISensorsCallback.aidl中的所有要求均得到正確滿足。

初始化 HAL

必須支援initialize()函數才能在框架和HAL之間建立FMQ。

公開可用的感測器

在 Sensors AIDL HAL 中, getSensorsList()函數必須在單一裝置啟動期間傳回相同的值,即使在 Sensors HAL 重新啟動期間也是如此。 getSensorsList()函數的一個新要求是,它必須在單一裝置啟動期間傳回相同的值,即使感測器 HAL 重新啟動也是如此。這允許框架在系統伺服器重新啟動時嘗試重新建立感測器連接。設備重新啟動後, getSensorsList()傳回的值可能會改變。

將感測器事件寫入 FMQ

在感測器 AIDL HAL 中,感測器 HAL 必須在感測器事件可用時主動將感測器事件寫入事件 FMQ,而不是等待調用poll() 。 HAL 也負責將正確的位元寫入EventFlag以引發框架內的 FMQ 讀取。

WAKE_UP 事件

在感測器 HAL 1.0 中,在將WAKE_UP發佈到poll()後,HAL 能夠在任何後續呼叫poll()時釋放其對任何WAKE_UP事件的喚醒鎖,因為這表示框架已處理所有感測器事件並已獲得喚醒鎖(如有必要)。因為,在 Sensors AIDL HAL 中,當框架處理了寫入 FMQ 的事件時,HAL 不再收到通知,因此喚醒鎖定 FMQ 允許框架在處理WAKE_UP事件時與 HAL 進行通訊。

在感測器 AIDL HAL 中,感測器 HAL 為WAKE_UP事件保護的喚醒鎖定必須以SensorsHAL_WAKEUP開頭。

動態感測器

使用 Sensors HAL 1.0 中的poll()函數傳回動態感測器。感測器 AIDL HAL 要求每當動態感測器連接發生變化時就呼叫ISensorsCallback中的onDynamicSensorsConnectedonDynamicSensorsDisconnected 。這些回呼可作為透過initialize()函數提供的ISensorsCallback指標的一部分來使用。

操作模式

必須支援WAKE_UP感測器的DATA_INJECTION模式。

多 HAL 支持

Sensors AIDL HAL 使用Sensors Multi-HAL 框架支援多 HAL。有關實現詳細信息,請參閱從感測器 HAL 2.1 移植