传感器多 HAL

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/中可用。以下是一些资源的指针。

执行

本节介绍如何在以下情况下实施 Sensors Multi-HAL:

实施传感器 Multi-HAL 2.1

要在新设备上实施 Sensors Multi-HAL 2.1,请执行以下步骤:

  1. 实现ISensorsSubHal接口,如SubHal.h中所述。
  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启动,查找新实现的子 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.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。

从 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中的onDynamicSensorsConnectedonDynamicSensorsDisconnected 。这些回调作为通过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中的onDynamicSensorsConnectedonDynamicSensorsDisconnected 。这些回调作为通过initialize()函数提供的IHalProxyCallback指针的一部分提供。

从 Sensors 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. 从 Sensors Hal 1.0 移植中所述移植sub-HAL。
  4. 按照实施 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 并将其推送到设备,请执行以下步骤:

  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命令调试框架。要请求 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接口的一部分。