傳感器 AIDL HAL

傳感器硬件抽象層 (HAL) 是 Android 傳感器框架和設備傳感器(例如加速度計或陀螺儀)之間的接口。 Sensors HAL 定義了必須實現的功能以允許框架控制傳感器。

傳感器 AIDL HAL 適用於 Android 13 及更高版本,適用於新設備和升級設備。 Sensors AIDL HAL 基於Sensors HAL 2.1 ,使用AIDL HAL 接口並公開頭部跟踪器和受限軸 IMU 傳感器類型。

AIDL HAL 接口

Sensors AIDL HAL 的主要文檔來源位於hardware/interfaces/sensors/aidl/android/hardware/sensors/ISensors.aidl的 HAL 定義中。

實現傳感器 AIDL HAL

要實現 Sensors AIDL HAL,對象必須擴展ISensors接口並實現hardware/interfaces/sensors/aidl/android/hardware/sensors/ISensors.aidl中定義的所有功能。

初始化 HAL

Sensors HAL 必須先由 Android 傳感器框架初始化,然後才能使用。框架調用initialize()函數為 Sensors HAL 提供三個參數:兩個 FMQ 描述符和一個指向ISensorsCallback對象的指針。

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

initialize()函數必須是初始化 Sensors HAL 時調用的第一個函數。

暴露可用的傳感器

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

如果多個傳感器共享相同的傳感器類型和喚醒屬性,則列表中的第一個傳感器稱為默認傳感器,並返回給使用getDefaultSensor(int sensorType, bool wakeUp)函數的應用程序。

傳感器列表的穩定性

在 Sensors HAL 重啟後,如果getSensorsList()返回的數據表明與重啟前檢索到的傳感器列表相比發生了重大變化,則框架會觸發 Android 運行時的重啟。傳感器列表的重大變化包括缺少具有給定句柄的傳感器或已更改屬性或引入新傳感器的情況。儘管重新啟動 Android 運行時會對用戶造成乾擾,但它是必需的,因為 Android 框架無法再滿足靜態(非動態)傳感器在應用程序生命週期內不會發生變化的 Android API 合同。這也可能會阻止框架重新建立應用程序發出的活動傳感器請求。因此,建議 HAL 供應商防止可避免的傳感器列表更改。

為了確保穩定的傳感器句柄,HAL 必須確定性地將設備中的給定物理傳感器映射到其句柄。儘管 Sensors HAL 接口沒有強制要求特定的實現,但開發人員有許多可用的選項來滿足這一要求。

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

配置傳感器

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

傳感器必須能夠隨時使用batch()重新配置,而不會丟失傳感器數據。

採樣期

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

  • 連續:傳感器事件以連續速率生成。
  • On-change:事件的生成速度不快於採樣週期,並且如果測量值沒有變化,則事件的生成速度可能低於採樣週期。
  • 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

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

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

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

Sensors 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事件後,框架會保護自己的喚醒鎖,從而允許 Sensors HAL 釋放其喚醒鎖。要在傳感器 HAL 釋放其喚醒鎖定時進行同步,請使用喚醒鎖定 FMQ。

Sensors HAL 必須讀取 Wake Lock FMQ 以確定框架已處理的WAKE_UP事件的數量。如果未處理的WAKE_UP事件的總數為零,HAL 應該只為WAKE_UP事件釋放喚醒鎖。處理傳感器事件後,框架計算標記為WAKE_UP事件的事件數,並將此數寫回喚醒鎖 FMQ。

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

動態傳感器

動態傳感器是物理上不是設備的一部分但可用作設備輸入的傳感器,例如帶有加速度計的遊戲手柄。

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

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

直銷渠道

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

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

操作模式

setOperationMode()函數允許框架配置傳感器,以便框架可以將傳感器數據注入傳感器。這對於測試很有用,尤其是對於框架下存在的算法。

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

驗證

要驗證傳感器 HAL 的實施,請運行傳感器 CTS 和 VTS 測試。

CTS 測試

傳感器 CTS 測試存在於自動 CTS 測試和手動 CTS Verifier 應用程序中。

自動化測試位於cts/tests/sensor/src/android/hardware/cts中。這些測試驗證傳感器的標準功能,例如激活傳感器、批處理和傳感器事件率。

CTS 驗證程序測試位於cts/apps/CtsVerifier/src/com/android/cts/verifier/sensors中。這些測試需要測試操作員手動輸入,並確保傳感器報告準確的值。

通過 CTS 測試對於確保被測設備滿足所有 CDD 要求至關重要。

VTS 測試

Sensors AIDL HAL 的 VTS 測試位於hardware/interfaces/sensors/aidl/vts/中。這些測試可確保正確實施 Sensors HAL 並正確滿足ISensors.aidlISensorsCallback.aidl中的所有要求。

初始化 HAL

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

暴露可用的傳感器

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

將傳感器事件寫入 FMQ

在傳感器 AIDL HAL 中,無需等待調用poll() ,只要傳感器事件可用,傳感器 HAL 就必須主動將傳感器事件寫入事件 FMQ。 HAL 還負責將正確的位寫入EventFlag以在框架內進行 FMQ 讀取。

WAKE_UP 事件

在 Sensors HAL 1.0 中,在WAKE_UP發佈到poll() poll()之後,HAL 能夠在任何後續調用 poll() 時為任何WAKE_UP事件釋放喚醒鎖,因為這表明框架已經處理了所有傳感器事件並獲得了如有必要,喚醒鎖。因為在 Sensors AIDL HAL 中,當框架處理寫入 FMQ 的事件時,HAL 不再收到通知,Wake Lock FMQ 允許框架在處理WAKE_UP事件後與 HAL 進行通信。

在 Sensors AIDL HAL 中,由 Sensors HAL 針對WAKE_UP事件保護的喚醒鎖必須以SensorsHAL_WAKEUP

動態傳感器

動態傳感器是使用 Sensors HAL 1.0 中的poll()函數返回的。 Sensors AIDL HAL 要求在動態傳感器連接發生變化時調用ISensorsCallback中的onDynamicSensorsConnectedonDynamicSensorsDisconnected 。這些回調作為通過initialize()函數提供的ISensorsCallback指針的一部分提供。

操作模式

必須支持WAKE_UP傳感器的DATA_INJECTION模式。

多 HAL 支持

Sensors AIDL HAL 使用Sensors Multi-HAL 框架支持多 HAL。有關實現細節,請參閱從 Sensors HAL 2.1 移植