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
接口的一部分。