感應器 HAL 2.0

感應器硬體抽象層 (HAL) 是 Android 感應器架構與裝置感應器 (例如加速計或陀螺儀) 之間的介面。感應器 HAL 會定義必須實作的功能,才能讓架構控制感應器。

新裝置和升級裝置可在 Android 10 以上版本使用 Sensors HAL 2.0。Sensors HAL 2.0 是以 Sensors HAL 1.0 為基礎,但有幾個主要差異,因此無法回溯相容。Sensors HAL 2.0 會使用快速訊息佇列 (FMQ),將 HAL 中的感應器事件傳送至 Android 感應器架構。

新裝置和升級裝置可在 Android 11 以上版本中使用 Sensors HAL 2.1。Sensors HAL 2.1 是 Sensors HAL 2.0 的迭代版本,可公開 HINGE_ANGLE 感應器類型,並更新各種方法以接受 HINGE_ANGLE 類型。

HAL 2.1 介面

Sensors HAL 2.1 的主要說明文件來源位於 hardware/interfaces/sensors/2.1/ISensors.hal 中的 HAL 定義。如果本頁面與 ISensors.hal 之間的規定有所衝突,請使用 ISensors.hal 中的規定。

HAL 2.0 介面

Sensors HAL 2.0 的主要說明文件來源位於 hardware/interfaces/sensors/2.0/ISensors.hal 中的 HAL 定義。如果本頁面與 ISensors.hal 之間的規定有所衝突,請使用 ISensors.hal 中的規定。

實作 Sensors HAL 2.0 和 HAL 2.1

如要實作感應器 HAL 2.0 或 2.1,物件必須擴充 ISensors 介面,並實作 2.0/ISensors.hal2.1/ISensors.hal 中定義的所有函式。

初始化 HAL

必須由 Android 感應器架構初始化 Sensors HAL,才能使用該架構。架構會呼叫 HAL 2.0 的 initialize() 函式,以及 HAL 2.1 的 initialize_2_1() 函式,為 Sensors HAL 提供三個參數:兩個 FMQ 描述元和一個指向 ISensorsCallback 物件的指標。

HAL 會使用第一個描述元建立事件 FMQ,用於將感應器事件寫入架構。HAL 會使用第二個描述項建立 Wake Lock FMQ,用於在 HAL 釋出 WAKE_UP 感應器事件的喚醒鎖時進行同步。HAL 必須儲存指向 ISensorsCallback 物件的指標,以便叫用任何必要的回呼函式。

initialize()initialize_2_1() 函式必須是初始化 Sensors HAL 時呼叫的第一個函式。

公開可用感應器

如要取得裝置中所有可用的靜態感應器清單,請在 HAL 2.0 上使用 getSensorsList() 函式,在 HAL 2.1 上使用 getSensorsList_2_1() 函式。這個函式會傳回感應器清單,每個感應器都有專屬的控點。代管 Sensors HAL 的程序重新啟動時,指定感應器的句柄不得變更。在裝置重新啟動和系統伺服器重新啟動時,句柄可能會變更。

如果多個感應器共用相同的感應器類型和喚醒屬性,清單中的第一個感應器就會稱為「預設」感應器,並傳回給使用 getDefaultSensor(int sensorType, bool wakeUp) 函式的應用程式。

感應器清單的穩定性

在 Sensors HAL 重新啟動後,如果 getSensorsList()getSensorsList_2_1() 傳回的資料與重新啟動前擷取的傳感器清單有顯著差異,架構就會觸發 Android 執行階段的重新啟動程序。感應器清單的重大變更包括:特定句柄的缺少或屬性變更,或是新增感應器的情況。雖然重新啟動 Android 執行階段會對使用者造成干擾,但這是必要的,因為 Android 架構無法再符合 Android API 合約,即在應用程式生命週期內,靜態 (非動態) 感應器不會變更。這也可能會導致架構無法重新建立應用程式提出的有效感應器要求。因此,建議 HAL 供應商避免感應器清單發生變更。

為確保感應器句柄穩定,HAL 必須以確定方式將裝置中的特定實體感應器對應至其句柄。雖然 Sensors HAL 介面並未強制實作特定實作方式,但開發人員可以透過多種方式滿足這項要求。

舉例來說,您可以使用各個感應器的固定屬性組合 (例如供應商、型號和感應器類型) 來排序感應器清單。另一個選項則是依據裝置的靜態感應器組在硬體中固定的事實,因此 HAL 需要知道所有預期的感應器何時完成初始化,才能從 getSensorsList()getSensorsList_2_1() 返回。這個預期感應器清單可編譯為 HAL 二進位檔,或儲存在檔案系統中的設定檔中,而顯示順序可用於衍生穩定的句柄。雖然最佳解決方案取決於 HAL 的具體實作細節,但主要要求是感應器句柄在 HAL 重新啟動時不會變更。

設定感應器

啟用感應器前,您必須使用 batch() 函式,為感應器設定取樣週期和最大回報延遲時間。

感應器必須能夠隨時使用 batch() 重新設定,且不會遺失感應器資料。

取樣週期

取樣期間的意義會因所設定的感應器類型而異:

  • 連續:感應器事件會以連續速率產生。
  • 變更時:事件產生頻率不得高於取樣週期,如果測量值沒有變更,產生事件的頻率可能會低於取樣週期。
  • 單一:略過取樣期間。
  • 特殊:詳情請參閱「感應器類型」。

如要瞭解取樣期間與感應器回報模式之間的互動關係,請參閱「回報模式」。

回報延遲時間上限

報告延遲時間上限會設定事件可延遲的最大時間 (以奈秒為單位),在 SoC 喚醒時,事件會先延遲並儲存在硬體 FIFO 中,再透過 HAL 寫入事件 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 應判斷是否要將目前的事件組寫入兩個較小的事件組,或是在有足夠空間時將所有事件一起寫入。

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

Sensors HAL 2.0/2.1 支援事件 FMQ 上的 writewriteBlocking。預設實作會提供 write 使用參照。如果使用 writeBlocking 函式,readNotification 旗標必須設為 EventQueueFlagBits::EVENTS_READ,這是架構在讀取 Event FMQ 中的事件時所設定的值。寫入通知標記必須設為 EventQueueFlagBits::READ_AND_PROCESS,以通知架構,事件已寫入事件 FMQ。

WAKE_UP 事件

WAKE_UP 事件是感應器事件,會導致應用程式處理器 (AP) 喚醒並立即處理事件。每當 WAKE_UP 事件寫入 Event FMQ 時,Sensors HAL 必須確保喚醒鎖定,確保系統保持喚醒狀態,直到架構可以處理事件為止。收到 WAKE_UP 事件後,架構會保護自己的喚醒鎖定,讓 Sensors HAL 釋放喚醒鎖定。如要同步處理 Sensors HAL 釋放喚醒鎖定時的情況,請使用 Wake Lock FMQ。

Sensors HAL 必須讀取 Wake Lock FMQ,才能判斷架構已處理的 WAKE_UP 事件數量。HAL 應只有在未處理的 WAKE_UP 事件總數為零時,才會釋出 WAKE_UP 事件的 Wake Lock。處理感應器事件後,架構會計算標示為 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() 函式可讓架構設定感應器,以便架構將感應器資料注入感應器。這對於測試特別有用,尤其是用於架構下方的演算法。

HAL 2.0 中的 injectSensorData() 函式和 HAL 2.0 中的 injectSensorsData_2_1() 函式通常用於將作業參數推送至 Sensors HAL。這個函式也可以用於將感應器事件插入特定感應器。

驗證

如要驗證 Sensors 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 測試

感應器 HAL 2.0 的 VTS 測試位於 hardware/interfaces/sensors/2.0/vts。Sensors HAL 2.1 的 VTS 測試位於 hardware/interfaces/sensors/2.1/vts。這些測試可確保 Sensors HAL 正確實作,且 ISensors.halISensorsCallback.hal 內的所有需求都正確滿足。

從 Sensors HAL 2.0 升級至 2.1

從 Sensors HAL 2.0 升級至 2.1 時,HAL 實作必須包含 initialize_2_1()getSensorsList_2_1()injectSensorsData_2_1() 方法,以及 HAL 2.1 類型。這些方法必須符合上述 HAL 2.0 的相同要求。

由於次要版本 HAL 必須支援先前 HAL 的所有函式,因此 2.1 HAL 必須支援以 2.0 HAL 的形式初始化。為了避免同時支援 HAL 版本複雜,強烈建議您使用 Multi-HAL 2.1。

如需實作專屬 Sensors 2.1 HAL 的範例,請參閱 Sensors.h

從 Sensors HAL 1.0 升級至 2.0

從 Sensors HAL 1.0 升級至 2.0 時,請確認 HAL 實作符合下列規定。

初始化 HAL

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

公開可用感應器

在 Sensors HAL 2.0 中,getSensorsList() 函式必須在單一裝置啟動期間傳回相同的值,即使在 Sensors HAL 重新啟動時也是如此。getSensorsList() 函式的新要求是,即使在 Sensors HAL 重新啟動時,它也必須在單一裝置啟動期間傳回相同的值。這樣一來,如果系統伺服器重新啟動,架構就能嘗試重新建立感應器連線。裝置重新啟動後,getSensorsList() 傳回的值可能會變更。

將感應器事件寫入 FMQ

在 Sensors HAL 2.0 中,Sensors HAL 必須主動將感應器事件寫入事件 FMQ,而非等待 poll() 呼叫。HAL 也負責將正確的位元寫入 EventFlag,以便在架構中讀取 FMQ。

WAKE_UP 事件

在 Sensors HAL 1.0 中,HAL 可在 WAKE_UP 發布至 poll() 後,針對任何後續對 poll() 的呼叫,釋放任何 WAKE_UP 事件的喚醒鎖定,因為這表示架構已處理所有感應器事件,並在必要時取得喚醒鎖定。因為在 Sensors HAL 2.0 中,HAL 不再知道架構何時處理寫入 FMQ 的事件,因此 Wake Lock FMQ 可讓架構在處理 WAKE_UP 事件時與 HAL 通訊。

在 Sensors HAL 2.0 中,Sensors HAL 為 WAKE_UP 事件提供的喚醒鎖定機制,開頭必須是 SensorsHAL_WAKEUP

動態感應器

在 Sensors HAL 1.0 中,系統會使用 poll() 函式傳回動態感應器。Sensors HAL 2.0 規定,每當動態感應器連線變更時,就必須呼叫 ISensorsCallback 中的 onDynamicSensorsConnectedonDynamicSensorsDisconnected。這些回呼會做為透過 initialize() 函式提供的 ISensorsCallback 指標的一部分提供。

運作模式

Sensors HAL 2.0 必須支援 WAKE_UP 感應器的 DATA_INJECTION 模式。

支援多個 HAL

感應器 HAL 2.0 和 2.1 支援使用感應器 Multi-HAL 架構的多 HAL。如需實作詳細資訊,請參閱「從 Sensors HAL 1.0 移植」。