感應器多 HAL

感應器 Multi-HAL 是一種架構,可讓感應器 HAL 與其他感應器 HAL 一起執行。Multi-HAL 感應器會動態載入儲存在供應商分區上以動態程式庫形式儲存的感應器子 HAL,並提供回呼物件,以處理發布事件及取得並釋出 Wake Lock。感應器 sub-HAL 是一種感應器 HAL,內建於供應商分區上的共用物件中,由 Multi-HAL 架構使用。這些子 HAL 不會依附,也不會依賴包含程序主要函式的多重 HAL 程式碼。

感應器 Multi-HAL 2.1 (適用於搭載 Android 11 以上版本的裝置) 是 Sensors Multi-HAL 2.0 的疊代,可支援載入具有轉軸角度感應器類型的子 HAL。為了支援這種感應器類型,子 HAL 必須使用 2.1 SubHal 標頭中定義的 sub-HAL API。

如果裝置搭載 Android 13 以上版本且使用 Sensors AIDL HAL,可以使用多 HAL 輔助層來允許多 HAL 功能。如要進一步瞭解實作詳情,請參閱「將感應器 Multi-HAL 與 Sensors AIDL HAL 搭配使用」。

多 HAL 2 感應器與感應器 HAL 2 之間的差異

感應器 Multi-HAL 2 適用於搭載 Android 10 以上版本的裝置,在感應器 HAL 2 之外導入了幾種抽象化機制,讓您能夠更輕鬆地與 HAL API 互動。感應器 Multi-HAL 2 引進 HalProxy 類別,可處理感應器的 HAL 2 介面實作作業,以及透過 V2_1/SubHal (或 V2_0/SubHal) 介面讓 HalProxy 與子 HAL 互動。

ISensorsSubHal 介面與 2.1/ISensors.hal (或 2.0/ISensors.hal) 介面有以下差異:

  • 初始化方法會傳送 IHalProxyCallback 類別,而不是兩個 FMQ 和 ISensorsCallback
  • Sub-HAL 必須實作偵錯函式,才能在錯誤報告中提供偵錯資訊。
  • Sub-HAL 必須實作名稱函式,以便區分載入的 sub-HAL 和其他子 HAL。

感應器 Multi-HAL 2 與感應器 HAL 2 之間的主要差異在於初始化函式。IHalProxyCallback 介面不會提供 FMQ,而是提供兩種方法:一種將感應器事件發布至感應器架構的方法,另一種則是建立 Wake Lock 的方法。實際上,感應器 Multi-HAL 會管理與 FMQ 的所有互動,確保所有子 HAL 的感應器事件及時提交。強烈建議您使用 createScopedWakelock 方法,將 Wake Lock 逾時的負擔委派給感應器 Multi-HAL,並將 Wake Lock 使用情形集中化為整個感應器的 Multi-HAL 所有 Wake Lock,進而盡量減少鎖定和解鎖呼叫。

此外,若感應器搭載 Multi-HAL 2,還內建部分安全功能,它可處理感應器 FMQ 已滿或 Android 感應器架構重新啟動,以及需要重設感應器狀態的情況。此外,如果事件發布至 HalProxy 類別,但感應器架構無法立即接受事件,感應器 Multi-HAL 可以將事件移至背景執行緒,讓工作在等待事件發布時,在子 HAL 中繼續運作。

原始碼和參考實作

所有感應器多 HAL 程式碼都位於 hardware/interfaces/sensors/common/default/2.X/multihal/ 中。以下是部分資源的指標。

導入作業

本節說明如何在下列情況下實作感應器 Multi-HAL:

將感應器多 HAL 與感應器 AIDL HAL 搭配使用

如要允許使用感應器 AIDL HAL 的多 HAL 功能,請匯入 AIDL Multi-HAL Shim 層模組,位於 hardware/interfaces/sensors/aidl/default/multihal/。這個模組會處理 AIDL 和 HIDL 感應器 HAL 定義類型之間的轉換作業,並定義多重 HAL 介面之間的包裝函式,如「實作感應器 Multi-HAL 2.1」一文所述。AIDL 多 HAL 輔助程式層與實作感應器 Multi-HAL 2.1 的裝置相容。

AIDL 多 HAL 輔助程式層可讓您在感應器 AIDL HAL 中公開頭戴式追蹤器和有限軸 IMU 感應器類型。如要使用 AIDL HAL 介面定義的這些感應器類型,請在 getSensorsList_2_1() 實作的 SensorInfo 結構中設定 type 欄位。這是安全的,因為 AIDL 和 HIDL 感應器的整數支援感應器類型欄位不會重疊。

實作感應器 Multi-HAL 2.1

如要在新裝置上實作感應器 Multi-HAL 2.1,請按照下列步驟操作:

  1. 按照 SubHal.h 的說明實作 ISensorsSubHal 介面。
  2. SubHal.h 中實作 sensorsHalGetSubHal_2_1 方法。
  3. 新增 cc_library_shared 目標,建構新實作的子 HAL。新增目標時,請注意下列事項:

    1. 確保目標推送至裝置的廠商分區。
    2. 在位於 /vendor/etc/sensors/hals.conf 的設定檔中,新增一行程式庫的路徑。如有需要,請建立 hals.conf 檔案。

    如需建構子 HAL 程式庫的 Android.bp 項目範例,請參閱 hardware/interfaces/sensors/common/default/2.X/multihal/tests/Android.bp

  4. manifest.xml 檔案移除所有 android.hardware.sensors 項目,該檔案包含裝置支援的 HAL 清單。

  5. device.mk 檔案中移除所有 android.hardware.sensors 服務和 service.rc 檔案,然後將 android.hardware.sensors@2.1-service.multihalandroid.hardware.sensors@2.1-service.multihal.rc 新增至 PRODUCT_PACKAGES

啟動時,HalProxy 會啟動,尋找新實作的 sub-HAL,並透過呼叫 sensorsHalGetSubHal_2_1 將其初始化。

從感應器多 HAL 2.0 到多 HAL 2.1 連接埠

如要從 Multi-HAL 2.0 攜至 Multi-HAL 2.1,請實作 SubHal 介面並重新編譯子 HAL。

下列是 2.0 和 2.1 SubHal 介面之間的差異:

  • IHalProxyCallback 會使用在 ISensors.hal 規格 2.1 版中建立的類型。
  • initialize() 函式會傳遞新的 IHalProxyCallback,而不是 2.0 SubHal 介面的介面。
  • Sub-HAL 必須實作 getSensorsList_2_1injectSensorData_2_1,而非 getSensorsListinjectSensorData,因為這些方法使用的是 ISensors.hal 規格 2.1 版中新增的新類型。
  • Sub-HAL 必須公開 sensorsHalGetSubHal_2_1 (而非 sensorsHalGetSubHal),才能讓 Multi-HAL 將其視為 2.1 Sub-HAL 版本。

來自感應器 HAL 2.0 的連接埠

感應器 HAL 2.0 升級至 Multi-HAL 2.0 時,請確保 HAL 實作符合下列規定。

初始化 HAL

感應器 HAL 2.0 有初始化函式,可讓感應器服務傳遞 FMQ 和動態感應器回呼。在感應器多 HAL 2.0 中,initialize() 函式會傳遞單一回呼,此回呼必須用於發布感應器事件、取得 Wake Lock,以及通知動態感應器連線和中斷連線。

將感應器事件發布至 Multi-HAL 實作項目

子 HAL 必須在感應器事件可用時,將感應器事件寫入 IHalProxyCallback,而非透過 FMQ 發布感應器事件。

WAKE_UP 事件

在感應器 HAL 2.0 中,HAL 可管理用於實作的 Wake Lock。在感應器 Multi-HAL 2.0 中,子 HAL 可讓實作 Multi-HAL 管理管理 Wake Lock,並可透過叫用 createScopedWakelock 要求取得 Wake Lock。將喚醒事件發布至 Multi-HAL 實作後,必須取得鎖定範圍的 Wake Lock,並傳遞至 postEvents

動態感應器

如要使用感應器 Multi-HAL 2.0,每當動態感應器連線變更時,系統就會呼叫 IHalProxyCallback 中的 onDynamicSensorsConnectedonDynamicSensorsDisconnected。這些回呼屬於 IHalProxyCallback 指標的一部分,透過 initialize() 函式提供。

來自感應器 HAL 1.0 的連接埠

Sensors HAL 1.0 升級至感應器 Multi-HAL 2.0 時,請確保 HAL 實作符合下列規定。

初始化 HAL

您必須支援 initialize() 函式,才能在 sub-HAL 和 Multi-HAL 實作之間建立回呼。

公開可用的感應器

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

將感應器事件發布至 Multi-HAL 實作項目

在感應器 HAL 2.0 中,只要有感應器事件,子 HAL 就必須主動將感應器事件寫入 IHalProxyCallback,而不必等待呼叫 poll()

WAKE_UP 事件

在感應器 HAL 1.0 中,HAL 可管理用於實作的 Wake Lock。在感應器 Multi-HAL 2.0 中,子 HAL 可讓實作 Multi-HAL 管理管理 Wake Lock,並可透過叫用 createScopedWakelock 要求取得 Wake Lock。將喚醒事件發布至 Multi-HAL 實作後,必須取得鎖定範圍的 Wake Lock,並傳遞至 postEvents

動態感應器

在感應器 HAL 1.0 中,動態感應器會透過 poll() 函式傳回。如要使用感應器 Multi-HAL 2.0,每當動態感應器連線變更時,系統就會呼叫 IHalProxyCallback 中的 onDynamicSensorsConnectedonDynamicSensorsDisconnected。這些回呼屬於 IHalProxyCallback 指標的一部分,透過 initialize() 函式提供。

感應器連接埠 Multi-HAL 1.0

如要從 Sensors Multi-HAL 1.0 移植現有實作,請按照下列步驟操作。

  1. 確認感應器 HAL 設定位於 /vendor/etc/sensors/hals.conf。這可能涉及移動位於 /system/etc/sensors/hals.conf 的檔案。
  2. 請移除 hardware/hardware.hhardware/sensors.h 的所有參照,因為 HAL 2.0 不支援這些參照。
  3. 從感應器的 Hal 1.0 移植到通訊埠子 HAL
  4. 按照「實作感應器 Mutli-HAL 2.0」一節的步驟 3 和 4,將感應器 Multi-HAL 2.0 設為指定的 HAL。

驗證

執行 VTS

整合一或多個子 HAL 與感應器 Multi-Hal 2.1 後,請使用供應商測試套件 (VTS) 確保子 HAL 實作符合感應器 HAL 介面設定的所有要求。

如要在主機機器設定 VTS 時只執行感應器 VTS 測試,請執行下列指令:

vts-tradefed run commandAndExit vts \
    --skip-all-system-status-check \
    --primary-abi-only \
    --skip-preconditions \
    --module VtsHalSensorsV2_0Target && \
  vts-tradefed run commandAndExit vts \
    --skip-all-system-status-check \
    --primary-abi-only \
    --skip-preconditions \
    --module VtsHalSensorsV2_1Target

如果您執行 AIDL Multi-HAL 輔助程式層,請執行 VtsAidlHalSensorsTargetTest

vts-tradefed run commandAndExit vts \
    --skip-all-system-status-check \
    --primary-abi-only \
    --skip-preconditions \
    --module VtsAidlHalSensorsTargetTest

執行單元測試

HalProxy_test.cpp測試 HalProxy 中的單元測試使用在單元測試中執行個體化的假子 HAL,不會動態載入。建立新的 sub-HAL 時,這些測試應可做為如何新增單元測試的指引,用於驗證新的 sub-HAL 已正確實作。

如要執行測試,請執行下列指令:

cd $ANDROID_BUILD_TOP/hardware/interfaces/sensors/common/default/2.X/multihal/tests
atest

使用假的 sub-HAL 進行測試

假 sub-HAL 是 ISensorsSubHal 介面的虛擬實作。子 HAL 會顯示不同的感應器清單。感應器啟用後,會根據指定感應器要求中指定的間隔時間,定期將自動產生的感應器事件發布至 HalProxy

假的 sub-HAL 可用來測試完整的 Multi-HAL 程式碼如何與已載入系統中的其他子 HAL 搭配運作,以及對感應器 Multi-HAL 程式碼的各個方面帶來壓力。

hardware/interfaces/sensors/common/default/2.X/multihal/tests/fake_subhal/ 提供兩個假的子 HAL。

如要建構假的子 HAL 並推送到裝置上,請按照下列步驟操作:

  1. 執行下列指令,建構三個不同的假子 HAL,並推送至裝置:

    $ANDROID_BUILD_TOP/hardware/interfaces/sensors/common/default/2.X/multihal/tests/
    mma
    adb push \
      $ANDROID_BUILD_TOP/out/target/product/<device>/symbols/vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config1.so \
      /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config1.so
    adb push \
      $ANDROID_BUILD_TOP/out/target/product/<device>/symbols/vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config2.so \
      /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config2.so
    adb push \
      $ANDROID_BUILD_TOP/out/target/product/<device>/symbols/vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config3.so \
      /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config3.so
    
  2. 使用假子 HAL 的路徑更新 /vendor/etc/sensors/hals.conf 的感應器 HAL 設定。

    /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config1.so
    /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config2.so
    /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config3.so
    
  3. 重新啟動 HalProxy,並載入設定中列出的新的子 HAL。

    adb shell stop
    adb shell start
    

偵錯

開發人員可以使用 lshal 指令對架構進行偵錯。如要要求感應器 HAL 的偵錯輸出內容,請執行下列指令:

adb root
adb shell lshal debug android.hardware.sensors@2.1::ISensors/default

接著,系統會將 HalProxy 目前狀態及其子 HAL 的相關資訊輸出至終端機。以下為 HalProxy 物件和假子 HAL 的指令輸出範例。

Internal values:
  Threads are running: true
  Wakelock timeout start time: 200 ms ago
  Wakelock timeout reset time: 73208 ms ago
  Wakelock ref count: 0
  # of events on pending write queue: 0
  # of non-dynamic sensors across all subhals: 8
  # of dynamic sensors across all subhals: 0
SubHals (2):
  Name: FakeSubHal-OnChange
  Debug dump:
Available sensors:
Name: Ambient Temp Sensor
Min delay: 40000
Flags: 2
Name: Light Sensor
Min delay: 200000
Flags: 2
Name: Proximity Sensor
Min delay: 200000
Flags: 3
Name: Relative Humidity Sensor
Min delay: 40000
Flags: 2
  Name: FakeSubHal-OnChange
  Debug dump:
Available sensors:
Name: Ambient Temp Sensor
Min delay: 40000
Flags: 2
Name: Light Sensor
Min delay: 200000
Flags: 2
Name: Proximity Sensor
Min delay: 200000
Flags: 3
Name: Relative Humidity Sensor
Min delay: 40000
Flags: 2

如果 # of events on pending write queue 指定的數字是較大的數字 (1000 或以上),表示有許多事件尚待寫入感應器架構。這表示感應器服務已死結或當機,且未處理感應器事件,或者近期有大量感應器事件從 sub-HAL 發布。

如果 Wake Lock 遭拒次數大於 0,表示 HalProxy 已取得 Wake Lock。只有在 ScopedWakelock 刻意保留,或喚醒事件傳送至 HalProxy 且尚未由感應器架構處理時,這個值才應大於 0

傳遞至 HalProxy 偵錯方法的檔案描述元會傳遞到每個 sub-HAL,因此開發人員必須在 ISensorsSubHal 介面中實作偵錯方法。