Sensors Multi-HAL 是一種架構,可讓感應器 HAL 與其他感應器 HAL 一併執行。Multi-HAL 感應器會動態載入儲存在供應商分區上以動態程式庫形式儲存的感應器子 HAL,並提供回呼物件,以處理發布事件及取得並釋出 Wake Lock。感應器 sub-HAL 是一種感應器 HAL,內建於供應商分區上的共用物件中,由 Multi-HAL 架構使用。這些子 HAL 不會彼此依賴,也不會依賴包含處理程序主要函式的多 HAL 程式碼。
Sensors Multi-HAL 2.1 適用於搭載 Android 11 以上版本的裝置,是 Sensors Multi-HAL 2.0 的迭代版本,可支援載入可公開鉸鏈角度感應器類型的子 HAL。如要支援此感應器類型,子 HAL 必須使用 2.1 子 HAL 標頭中定義的子 HAL API。
如果裝置搭載 Android 13 以上版本,且使用 Sensors AIDL HAL,您可以使用多 HAL 修補層,啟用多 HAL 功能。如需實作詳細資訊,請參閱「使用 Sensors Multi-HAL 搭配 Sensors AIDL HAL」。
Sensors Multi-HAL 2 和 Sensors HAL 2 的差異
在搭載 Android 10 以上版本的裝置上,可使用 Sensors Multi-HAL 2,這項技術在 Sensors HAL 2 之上引入多個抽象概念,可讓您更輕鬆地與 HAL API 互動。Sensors Multi-HAL 2 會導入 HalProxy 類別,用於處理 Sensors HAL 2 介面和 V2_1/SubHal
(或 V2_0/SubHal
) 介面,讓 HalProxy
與子 HAL 互動。
ISensorsSubHal
介面與 2.1/ISensors.hal
(或 2.0/ISensors.hal
) 介面有以下差異:
- 初始化方法會傳遞
IHalProxyCallback
類別,而非兩個 FMQ 和ISensorsCallback
。 - 子 HAL 必須實作偵錯函式,才能在錯誤報告中提供偵錯資訊。
- Sub-HAL 必須實作名稱函式,以便區分載入的 sub-HAL 和其他子 HAL。
感應器 Multi-HAL 2 與感應器 HAL 2 之間的主要差異在於初始化函式。IHalProxyCallback
介面不會提供 FMQ,而是提供兩種方法:一種將感應器事件發布至感應器架構的方法,另一種則是建立 Wake Lock 的方法。在幕後,Sensors Multi-HAL 會管理與 FMQ 的所有互動,確保所有子 HAL 都能及時收到感應器事件。強烈建議您使用 createScopedWakelock
方法,將 Wake Lock 逾時的負擔委派給感應器 Multi-HAL,並將 Wake Lock 使用情形集中化為整個感應器的 Multi-HAL 所有 Wake Lock,進而盡量減少鎖定和解鎖呼叫。
Sensors Multi-HAL 2 也內建了一些安全功能。它會處理感應器 FMQ 已滿的情況,或是 Android 感應器架構重新啟動且需要重設感應器狀態的情況。此外,當事件發布至 HalProxy
類別,但感應器架構無法立即接受事件時,感應器 Multi-HAL 可以將事件移至背景執行緒,讓工作在等待事件發布期間,持續處理所有子 HAL。
原始碼和參考實作
hardware/interfaces/sensors/common/default/2.X/multihal/
提供所有 Sensors Multi-HAL 程式碼。以下是部分資源的指標。
HalProxy.h
:HalProxy
物件由 Sensors 多重 HAL 例項化,並處理從子 HAL 傳遞至感應器架構的資料。HalProxy.cpp
:HalProxy
的實作包含在子 HAL 和感應器架構之間進行多工通訊所需的所有邏輯。SubHal.h
:ISensorsSubHal
介面會定義子 HAL 必須遵循的介面,才能與HalProxy
相容。Sub-HAL 會實作初始化方法,讓HalProxyCallback
物件可用於postEvents
和createScopedWakelock
。如果是多 HAL 2.0 實作項目,請使用
SubHal.h
的 2.0 版。hardware/interfaces/sensors/common/default/2.X/multihal/tests/
:這些單元測試會驗證HalProxy
實作。hardware/interfaces/sensors/common/default/2.X/multihal/tests/fake_subhal/
:這個子 HAL 實作範例使用假感應器產生假資料。適用於測試多部子 HAL 在裝置上的互動方式。
實作
本節說明如何在下列情況下實作感應器 Multi-HAL:
- 將感應器多 HAL 與感應器 AIDL HAL 搭配使用
- 實作感應器 Multi-HAL 2.1
- 從感應器多 HAL 2.0 移植至多 HAL 2.1
- 從感應器 HAL 2.0 移植
- 從 Sensors HAL 1.0 移植
- 從感應器移植 Multi-HAL 1.0
將感應器多 HAL 與感應器 AIDL HAL 搭配使用
如要讓 Sensors AIDL HAL 支援多 HAL 功能,請匯入 AIDL Multi-HAL 墊片層模組,位於 hardware/interfaces/sensors/aidl/default/multihal/。這個模組會處理 AIDL 和 HIDL 感應器 HAL 定義類型之間的轉換,並在 實作 Sensors Multi-HAL 2.1 中所述的多 HAL 介面周圍定義包裝函式。AIDL 多重 HAL 墊片層與實作 Sensors Multi-HAL 2.1 的裝置相容。
AIDL 多 HAL 輔助程式層可讓您在感應器 AIDL HAL 中公開頭戴式追蹤器和有限軸 IMU 感應器類型。如要使用 AIDL HAL 介面定義的這些感應器類型,請在 getSensorsList_2_1()
實作中設定 SensorInfo
結構體中的 type
欄位。這是安全的,因為 AIDL 和 HIDL 感應器的整數支援感應器類型欄位不會重疊。
實作 Sensors Multi-HAL 2.1
如要在新裝置上實作 Sensors Multi-HAL 2.1,請按照下列步驟操作:
- 按照
SubHal.h
所述,實作ISensorsSubHal
介面。 - 在
SubHal.h
中實作sensorsHalGetSubHal_2_1
方法。 新增
cc_library_shared
目標,建構新實作的子 HAL。新增目標時,請注意下列事項:- 確保目標推送至裝置的廠商分區。
- 在位於
/vendor/etc/sensors/hals.conf
的設定檔中,在新行中新增程式庫的路徑。視需要建立hals.conf
檔案。
如需建構子 HAL 程式庫的
Android.bp
項目範例,請參閱hardware/interfaces/sensors/common/default/2.X/multihal/tests/Android.bp
。從
manifest.xml
檔案中移除所有android.hardware.sensors
項目,該檔案包含裝置支援的 HAL 清單。從
device.mk
檔案中移除所有android.hardware.sensors
服務和service.rc
檔案,並將android.hardware.sensors@2.1-service.multihal
和android.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.0SubHal
介面中的SubHal
- Sub-HAL 必須實作
getSensorsList_2_1
和injectSensorData_2_1
,而非getSensorsList
和injectSensorData
,因為這些方法使用的是ISensors.hal
規格 2.1 版中新增的新類型。 - 子 HAL 必須公開
sensorsHalGetSubHal_2_1
,而非sensorsHalGetSubHal
,才能讓 Multi-HAL 將其視為 2.1 版子 HAL。
來自感應器 HAL 2.0 的連接埠
從 Sensors HAL 2.0 升級至 Sensors Multi-HAL 2.0 時,請確認 HAL 實作符合下列規定。
初始化 HAL
Sensors HAL 2.0 提供初始化函式,可讓感應器服務傳遞 FMQ 和動態感應器回呼。在 Sensors Multi-HAL 2.0 中,initialize()
函式會傳遞單一回呼,該回呼必須用於發布感應器事件、取得喚醒鎖定,以及通知動態感應器連線和中斷連線。
將感應器事件發布至 Multi-HAL 實作項目
子 HAL 必須在感應器事件可用時,將感應器事件寫入 IHalProxyCallback
,而非透過 FMQ 發布感應器事件。
WAKE_UP 事件
在感應器 HAL 2.0 中,HAL 可管理用於實作的 Wake Lock。在 Sensors Multi-HAL 2.0 中,子 HAL 可讓 Multi-HAL 實作項目管理喚醒鎖定,並可要求喚醒鎖定,藉此叫用 createScopedWakelock
。將喚醒事件發布至多重 HAL 實作時,必須取得並傳遞鎖定的喚醒鎖定機制至 postEvents
。
動態感應器
根據 Sensors Multi-HAL 2.0 的規定,每當動態感應器連線發生變更時,就會呼叫 IHalProxyCallback
中的 onDynamicSensorsConnected
和 onDynamicSensorsDisconnected
。這些回呼可用於透過 initialize()
函式提供的 IHalProxyCallback
指標。
來自感應器 HAL 1.0 的連接埠
從 Sensors HAL 1.0 升級至 Sensors Multi-HAL 2.0 時,請確認 HAL 實作符合下列規定。
初始化 HAL
您必須支援 initialize()
函式,才能在 sub-HAL 和 Multi-HAL 實作之間建立回呼。
公開可用感應器
在 Sensors Multi-HAL 2.0 中,getSensorsList()
函式必須在單一裝置啟動期間傳回相同的值,即使在重新啟動感應器 HAL 的情況下也是如此。如此一來,系統伺服器重新啟動時,架構就能嘗試重新建立感應器連線。裝置重新啟動後,getSensorsList()
傳回的值可能會變更。
將感應器事件張貼至 Multi-HAL 實作
在感應器 HAL 2.0 中,只要有感應器事件,子 HAL 就必須主動將感應器事件寫入 IHalProxyCallback
,而不必等待呼叫 poll()
。
WAKE_UP 事件
在 Sensors HAL 1.0 中,HAL 可以管理喚醒鎖定功能的實作方式。在感應器 Multi-HAL 2.0 中,子 HAL 可讓實作 Multi-HAL 管理管理 Wake Lock,並可透過叫用 createScopedWakelock
要求取得 Wake Lock。將喚醒事件發布至多重 HAL 實作時,必須取得並傳遞鎖定的喚醒鎖定機制至 postEvents
。
動態感應器
在 Sensors HAL 1.0 中,動態感應器會透過 poll()
函式傳回。如要使用感應器 Multi-HAL 2.0,每當動態感應器連線變更時,系統就會呼叫 IHalProxyCallback
中的 onDynamicSensorsConnected
和 onDynamicSensorsDisconnected
。這些回呼可用於透過 initialize()
函式提供的 IHalProxyCallback
指標。
感應器連接埠 Multi-HAL 1.0
如要從 Sensors Multi-HAL 1.0 移植現有實作,請按照下列步驟操作。
- 確認感應器 HAL 設定位於
/vendor/etc/sensors/hals.conf
。這可能會涉及移動位於/system/etc/sensors/hals.conf
的檔案。 - 請移除
hardware/hardware.h
和hardware/sensors.h
的所有參照,因為 HAL 2.0 不支援這些參照。 - 從感應器的 Hal 1.0 移植到通訊埠子 HAL。
- 按照「實作感應器 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
中的單元測試會使用假的子 HAL 測試 HalProxy
,這些假的子 HAL 會在單元測試中例項化,且不會動態載入。建立新的子 HAL 時,這些測試應可做為指南,說明如何新增單元測試,驗證新子 HAL 是否已正確實作。
如要執行測試,請執行下列指令:
cd $ANDROID_BUILD_TOP/hardware/interfaces/sensors/common/default/2.X/multihal/tests
atest
使用假的子 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 推送至裝置,請執行下列步驟:
執行下列指令,建構三個不同的假子 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
使用假子 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
重新啟動
HalProxy
,並載入設定中列出的新的子 HAL。adb shell stop
adb shell start
偵錯
開發人員可以使用 lshal
指令對架構進行偵錯。如要要求 Sensors 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 或以上),表示有許多事件尚待寫入感應器架構。這表示感應器服務發生死結或已停止運作,因此無法處理感應器事件,或是最近從子 HAL 發布大量感應器事件。
如果 Wake Lock 參照計數大於 0
,表示 HalProxy
已取得 Wake Lock。只有在 ScopedWakelock
有意保留,或是喚醒事件已傳送至 HalProxy
,但未經由感應器架構處理的情況下,才應大於 0
。
傳遞至 HalProxy
偵錯方法的檔案描述元會傳遞到每個 sub-HAL,因此開發人員必須在 ISensorsSubHal
介面中實作偵錯方法。