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。為了支援此感測器類型,子 HAL 必須使用2.1 SubHal 標頭中定義的子 HAL API。
對於運行 Android 13 或更高版本並使用Sensors AIDL HAL 的設備,您可以使用多 HAL shim 層來允許多 HAL 功能。有關實現詳細信息,請參閱將感測器 Multi-HAL 與感測器 AIDL HAL 結合使用。
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
。 - 子 HAL 必須實作偵錯功能,以便在錯誤報告中提供偵錯資訊。
- 子 HAL 必須實作名稱函數,以便載入的子 HAL 可以與其他子 HAL 區分開。
Sensors Multi-HAL 2 和 Sensors HAL 2 之間的主要差異在於初始化函數。 IHalProxyCallback
介面不提供 FMQ,而是提供兩種方法,一種將感測器事件發佈到感測器框架的方法,一種創建喚醒鎖定的方法。在底層,Sensors Multi-HAL 管理與 FMQ 的所有交互,以確保及時傳遞所有子 HAL 的感測器事件。強烈建議子 HAL 使用createScopedWakelock
方法將超時喚醒鎖的負擔委託給 Sensors Multi-HAL,並將喚醒鎖的使用集中到整個 Sensors Multi-HAL 的一個公共喚醒鎖,從而最大限度地減少鎖定和解鎖來電。
Sensors Multi-HAL 2 還具有一些內建安全功能。它處理感測器 FMQ 已滿或 Android 感測器框架重新啟動且需要重置感測器狀態的情況。此外,當事件發佈到HalProxy
類別但感測器框架無法立即接受事件時,Sensors Multi-HAL 可以將事件移至後台線程,以便在等待事件時允許所有子 HAL 繼續工作待發布。
源碼及參考實現
所有感測器 Multi-HAL 程式碼可在hardware/interfaces/sensors/common/default/2.X/multihal/
中找到。以下是一些資源的指標。
-
HalProxy.h
:HalProxy
物件由感測器多 HAL 實例化,並處理從子 HAL 到感測器框架的資料傳遞。 -
HalProxy.cpp
:HalProxy
的實作包含子 HAL 和感測器框架之間多路復用通訊所需的所有邏輯。 SubHal.h
:ISensorsSubHal
介面定義子 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/
:此範例子 HAL 實作使用假感測器產生假資料。對於測試多個子 HAL 如何在裝置上互動非常有用。
執行
本節介紹如何在以下情況下實現 Sensors Multi-HAL:
- 將感測器 Multi-HAL 與感測器 AIDL HAL 結合使用
- 實施感測器 Multi-HAL 2.1
- 從感測器 Multi-HAL 2.0 移植到 Multi-HAL 2.1
- 從感測器 HAL 2.0 移植
- 從感測器 HAL 1.0 移植
- 從感測器 Multi-HAL 1.0 移植
將感測器 Multi-HAL 與感測器 AIDL HAL 結合使用
若要允許感測器 AIDL HAL 具有多 HAL 功能,請匯入 AIDL Multi-HAL shim 層模組,該模組位於hardware/interfaces/sensors/aidl/default/multihal/中。此模組處理 AIDL 和 HIDL 感測器 HAL 定義類型之間的轉換,並定義圍繞實現感測器 Multi-HAL 2.1中所述的 multi-HAL 介面的包裝器。 AIDL multi-HAL shim 層與實作 Sensors Multi-HAL 2.1 的裝置相容。
AIDL 多 HAL 墊片層可讓您在感測器 AIDL HAL 中公開頭部追蹤器和限軸 IMU 感測器類型。若要使用 AIDL HAL 介面定義的這些感測器類型,請在getSensorsList_2_1()
實作的SensorInfo
結構中設定type
欄位。這是安全的,因為 AIDL 和 HIDL 感測器 HAL 的支援整數的感測器類型欄位不會重疊。
實施感測器 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
對其進行初始化。
從感測器 Multi-HAL 2.0 到 Multi-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
介面中的 IHalProxyCallback - 子 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 事件
在 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
指標的一部分來使用。
感測器 HAL 1.0 的端口
從Sensors HAL 1.0升級到 Sensors Multi-HAL 2.0 時,請確保 HAL 實現符合下列要求。
初始化 HAL
必須支援initialize()
函數才能在子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 可以管理其實現的喚醒鎖定。在 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
指標的一部分來使用。
感測器 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。
- 依照實作 Sensors Mutli-HAL 2.0部分中的步驟 3 和 4,將 Sensors Multi-HAL 2.0 設定為指定的 HAL。
驗證
運行VTS
當您將一個或多個子 HAL 與 Sensors Multi-Hal 2.1 整合後,請使用供應商測試套件 (VTS)確保您的子 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
如果您正在執行 AIDL Multi-HAL shim 層,請執行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 是否正確實現。
若要執行測試,請執行以下命令:
cd $ANDROID_BUILD_TOP/hardware/interfaces/sensors/common/default/2.X/multihal/tests
atest
使用假子 HAL 進行測試
假子 HAL 是ISensorsSubHal
介面的虛擬實作。子 HAL 公開不同的感測器清單。當感測器啟動時,它們會根據給定感測器請求中指定的時間間隔定期將自動產生的感測器事件發佈到HalProxy
。
假子 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
指令來除錯框架。若要請求感測器 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
的 debug 方法的檔案描述子會傳遞給每個子 HAL,因此開發人員必須將 debug 方法實作為ISensorsSubHal
介面的一部分。