Sensors Multi-HAL 是一個框架,允許傳感器 HAL 與其他傳感器 HAL 一起運行。 Sensors Multi-HAL 動態加載存儲為供應商分區上的動態庫的傳感器子 HAL,並為它們提供一個回調對象,該對象可以處理髮布事件以及獲取和釋放喚醒鎖。傳感器子 HAL 是內置在供應商分區上的共享對像中並由多 HAL 框架使用的傳感器 HAL。這些子 HAL 不相互依賴,也不依賴於包含進程主要功能的多 HAL 代碼。
Sensors Multi-HAL 2.1 可在運行 Android 11 或更高版本的設備上使用,是 Sensors Multi-HAL 2.0 的迭代,支持加載可暴露鉸鏈角度傳感器類型的子 HAL。要支持這種傳感器類型,sub-HAL 必須使用2.1 SubHal 標頭中定義的 sub-HAL API。
Sensors Multi-HAL 2 和 Sensors HAL 2 之間的區別
Sensors Multi-HAL 2 可在運行 Android 10 或更高版本的設備上使用,它在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
。 - Sub-HAL 必須實現調試功能,以便在錯誤報告中提供調試信息。
- Sub-HAL 必須實現名稱功能,以便加載的 sub-HAL 可以與其他 sub-HAL 區分開來。
Sensors Multi-HAL 2 和 Sensors HAL 2 之間的主要區別在於初始化功能。 IHalProxyCallback
接口不提供 FMQ,而是提供了兩種方法,一種將傳感器事件發佈到傳感器框架的方法,另一種創建喚醒鎖的方法。在後台,Sensors Multi-HAL 管理與 FMQ 的所有交互,以確保及時為所有 sub-HAL 傳遞傳感器事件。強烈建議子 HAL 使用createScopedWakelock
方法將喚醒鎖超時的負擔委託給 Sensors Multi-HAL,並將喚醒鎖的使用集中到整個 Sensors Multi-HAL 的一個通用喚醒鎖上,從而最大限度地減少鎖定和解鎖來電。
Sensors Multi-HAL 2 還具有一些內置的安全功能。它處理傳感器 FMQ 已滿或 Android 傳感器框架重新啟動並且需要重置傳感器狀態的情況。此外,當事件發佈到HalProxy
類但傳感器框架無法立即接受事件時,Sensors Multi-HAL 可以將事件移動到後台線程,以允許在等待事件的同時跨所有子 HAL 繼續工作要張貼。
源代碼和參考實現
所有 Sensors Multi-HAL 代碼都在hardware/interfaces/sensors/common/default/2.X/multihal/
中可用。以下是一些資源的指針。
-
HalProxy.h
:HalProxy
對象由 Sensors 多 HAL 實例化,並處理從子 HAL 到傳感器框架的數據傳遞。 -
HalProxy.cpp
:HalProxy
的實現包含在子 HAL 和傳感器框架之間多路復用通信所需的所有邏輯。 SubHal.h
:ISensorsSubHal
接口定義了 sub-HAL 必須遵循的接口才能與HalProxy
兼容。子 HAL 實現了 initialize 方法,以便HalProxyCallback
對象可用於postEvents
和createScopedWakelock
。對於 Multi-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/
:此示例 sub-HAL 實現使用假傳感器生成假數據。用於測試多個 sub-HAL 如何在設備上交互。
執行
本節介紹如何在以下情況下實施 Sensors Multi-HAL:
- 實施傳感器 Multi-HAL 2.1
- 從 Sensors Multi-HAL 2.0 移植到 Multi-HAL 2.1
- 從 Sensors HAL 2.0 移植
- 從 Sensors HAL 1.0 移植
- 從 Sensors Multi-HAL 1.0 移植
實施傳感器 Multi-HAL 2.1
要在新設備上實施 Sensors Multi-HAL 2.1,請執行以下步驟:
- 實現
ISensorsSubHal
接口,如SubHal.h
中所述。 - 在
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
啟動,查找新實現的子 HAL,並通過調用sensorsHalGetSubHal_2_1
對其進行初始化。
從 Sensors Multi-HAL 2.0 移植到 Multi-HAL 2.1
要從 Multi-HAL 2.0 移植到 Multi-HAL 2.1,請實現SubHal
接口並重新編譯您的 sub-HAL。
這些是 2.0 和 2.1 SubHal
接口之間的區別:
-
IHalProxyCallback
使用在ISensors.hal
規範的 2.1 版中創建的類型。 -
initialize()
函數傳遞一個新的IHalProxyCallback
而不是來自 2.0SubHal
接口的那個 - Sub-HAL 必須實現
getSensorsList_2_1
和injectSensorData_2_1
而不是getSensorsList
和injectSensorData
,因為這些方法使用ISensors.hal
規範 2.1 版中添加的新類型。 - Sub-HAL 必須公開
sensorsHalGetSubHal_2_1
而不是sensorsHalGetSubHal
,以便 Multi-HAL 將它們視為 2.1 版 sub-HAL。
從 Sensors 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 事件
在 Sensors HAL 2.0 中,HAL 可以為其實現管理喚醒鎖。在 Sensors Multi-HAL 2.0 中,子 HAL 允許 Multi-HAL 實現管理喚醒鎖,並且可以通過調用createScopedWakelock
來請求獲取喚醒鎖。將喚醒事件發佈到 Multi-HAL 實現時,必須獲取鎖定範圍的喚醒鎖並將其傳遞給postEvents
。
動態傳感器
Sensors Multi-HAL 2.0 要求在動態傳感器連接發生變化時調用IHalProxyCallback
中的onDynamicSensorsConnected
和onDynamicSensorsDisconnected
。這些回調作為通過initialize()
函數提供的IHalProxyCallback
指針的一部分提供。
從 Sensors 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 實現
在 Sensors HAL 2.0 中,子 HAL 必須在傳感器事件可用時主動將傳感器事件寫入IHalProxyCallback
,而不是等待調用poll()
。
WAKE_UP 事件
在 Sensors HAL 1.0 中,HAL 可以為其實現管理喚醒鎖。在 Sensors Multi-HAL 2.0 中,子 HAL 允許 Multi-HAL 實現管理喚醒鎖,並且可以通過調用createScopedWakelock
來請求獲取喚醒鎖。將喚醒事件發佈到 Multi-HAL 實現時,必須獲取鎖定範圍的喚醒鎖並將其傳遞給postEvents
。
動態傳感器
在 Sensors HAL 1.0 中,動態傳感器通過poll()
函數返回。 Sensors Multi-HAL 2.0 要求在動態傳感器連接發生變化時調用IHalProxyCallback
中的onDynamicSensorsConnected
和onDynamicSensorsDisconnected
。這些回調作為通過initialize()
函數提供的IHalProxyCallback
指針的一部分提供。
從 Sensors 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 不支持這些引用。 - 如從 Sensors Hal 1.0 移植中所述移植sub-HAL。
- 按照實施 Sensors Mutli-HAL 2.0部分中的步驟 3 和 4 將 Sensors Multi-HAL 2.0 設置為指定的 HAL。
驗證
運行 VTS
當您將一個或多個 sub-HAL 與 Sensors Multi-Hal 2.1 集成後,請使用供應商測試套件 (VTS)確保您的 sub-HAL 實現滿足 Sensors 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
運行單元測試
HalProxy_test.cpp
中的單元測試使用在單元測試中實例化且未動態加載的假子 HAL 測試HalProxy
。創建新的 sub-HAL 時,這些測試應作為指導,指導如何添加單元測試以驗證新的 sub-HAL 是否已正確實施。
要運行測試,請執行以下命令:
cd $ANDROID_BUILD_TOP/hardware/interfaces/sensors/common/default/2.X/multihal/tests
atest
使用偽造的 sub-HAL 進行測試
假子 HAL 是ISensorsSubHal
接口的虛擬實現。 sub-HAL 公開了不同的傳感器列表。當傳感器被激活時,它們會根據給定傳感器請求中指定的間隔定期將自動生成的傳感器事件發佈到HalProxy
。
偽造的 sub-HAL 可用於測試完整的 Multi-HAL 代碼如何與加載到系統中的其他 sub-HAL 一起工作,並強調 Sensors 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 發布了大量傳感器事件。
如果喚醒鎖引用計數大於0
,這意味著HalProxy
獲得了喚醒鎖。僅當有意保持ScopedWakelock
或喚醒事件已發送到HalProxy
且傳感器框架尚未處理時,該值才應大於0
。
傳遞給HalProxy
調試方法的文件描述符會傳遞給每個子 HAL,因此開發人員必須將調試方法實現為ISensorsSubHal
接口的一部分。