传感器 AIDL HAL

传感器硬件抽象层 (HAL) 是 Android 传感器框架与设备的传感器(如加速度计或陀螺仪)之间的接口。传感器 HAL 定义了必须实现的功能,以允许框架控制传感器。

传感器 AIDL HAL 在 Android 13 及更高版本中可用于新的和升级的设备。传感器 AIDL HAL 基于 Sensors HAL 2.1,使用 AIDL HAL 接口,并公开头部跟踪器和有限轴 IMU 传感器类型。

AIDL HAL 接口

传感器 AIDL HAL 的主要文档来源位于 hardware/interfaces/sensors/aidl/android/hardware/sensors/ISensors.aidl 的 HAL 定义中。

实现传感器 AIDL HAL

要实现传感器 AIDL HAL,对象必须扩展 ISensors 接口并实现 hardware/interfaces/sensors/aidl/android/hardware/sensors/ISensors.aidl 中定义的所有函数。

初始化 HAL

传感器 HAL 必须先由 Android 传感器框架初始化,然后才能使用。框架调用 initialize() 函数以向传感器 HAL 提供三个参数:两个 FMQ 描述符和一个指向 ISensorsCallback 对象的指针。

HAL 使用第一个描述符创建事件 FMQ,用于将传感器事件写入框架。HAL 使用第二个描述符创建唤醒锁定 FMQ,用于同步 HAL 何时释放其针对 WAKE_UP 传感器事件的唤醒锁定。HAL 必须保存指向 ISensorsCallback 对象的指针,以便可以调用任何必要的回调函数。

initialize() 函数必须是初始化传感器 HAL 时调用的第一个函数。

公开可用传感器

要获取设备中所有可用静态传感器的列表,请使用 getSensorsList() 函数。此函数返回传感器列表,每个传感器都由其句柄唯一标识。当托管传感器 HAL 的进程重启时,给定传感器的句柄不得更改。句柄可能会在设备重启和系统服务器重启之间发生变化。

如果多个传感器共享相同的传感器类型和唤醒属性,则列表中的第一个传感器称为默认传感器,并返回给使用 getDefaultSensor(int sensorType, bool wakeUp) 函数的应用。

传感器列表的稳定性

在传感器 HAL 重启后,如果 getSensorsList() 返回的数据表明与重启前检索到的传感器列表相比发生了重大变化,则框架会触发 Android 运行时的重启。传感器列表的重大更改包括具有给定句柄的传感器丢失或属性已更改,或者引入了新传感器的情况。虽然重启 Android 运行时会对用户造成干扰,但这是必需的,因为 Android 框架无法再满足 Android API 合约,即静态(非动态)传感器在应用的生命周期内不会更改。这也可能会阻止框架重新建立应用发出的活动传感器请求。因此,建议 HAL 供应商防止可避免的传感器列表更改。

为了确保传感器句柄的稳定性,HAL 必须确定性地将设备中的给定物理传感器映射到其句柄。虽然传感器 HAL 接口未强制规定任何特定的实现方式,但开发者可以使用多种选项来满足此要求。

例如,可以使用每个传感器的固定属性(例如供应商、型号和传感器类型)的组合对传感器列表进行排序。另一种选择依赖于设备的一组静态传感器在硬件中是固定的这一事实,因此 HAL 需要知道所有预期的传感器何时完成初始化,然后才能从 getSensorsList() 返回。此预期传感器列表可以编译到 HAL 二进制文件中或存储在文件系统中的配置文件中,并且可以使用出现的顺序来派生稳定的句柄。虽然最佳解决方案取决于您的 HAL 的具体实现细节,但关键要求是传感器句柄在 HAL 重启后不会更改。

配置传感器

在传感器激活之前,必须使用 batch() 函数配置传感器的采样周期和最大报告延迟。

传感器必须能够在任何时候使用 batch() 重新配置,而不会丢失传感器数据。

采样周期

采样周期根据配置的传感器类型而具有不同的含义

  • 连续:传感器事件以连续速率生成。
  • On-change(变化时):事件的生成速度不快于采样周期,并且如果测量值没有变化,则事件的生成速度可能慢于采样周期。
  • One-shot(单次):采样周期被忽略。
  • 特殊:有关更多详细信息,请参阅传感器类型

要了解采样周期和传感器的报告模式之间的交互,请参阅报告模式

最大报告延迟

最大报告延迟设置了事件在写入到通过 HAL 的 Event FMQ 之前,可以在硬件 FIFO 中延迟和存储的最长时间(以纳秒为单位),前提是 SoC 处于唤醒状态。

零值表示事件必须在测量后立即报告,要么完全跳过 FIFO,要么在 FIFO 中存在来自传感器的事件时立即清空 FIFO。

例如,当 SoC 处于唤醒状态时,以 50 Hz 激活的加速度计在最大报告延迟为零的情况下,每秒触发 50 次中断。

当最大报告延迟大于零时,传感器事件不需要在检测到后立即报告。事件可以临时存储在硬件 FIFO 中并批量报告,前提是没有事件延迟超过最大报告延迟。自上一批次以来的所有事件都会被记录并一次性返回。这减少了发送到 SoC 的中断次数,并允许 SoC 在传感器捕获和批量处理数据时切换到低功耗模式。

每个事件都有一个与其关联的时间戳。延迟事件的报告时间不得影响事件时间戳。时间戳必须准确,并且对应于事件实际发生的时间,而不是报告时间。

有关使用非零最大报告延迟报告传感器事件的其他信息和要求,请参阅批量处理

激活传感器

框架使用 activate() 函数启用和停用传感器。在激活传感器之前,框架必须首先使用 batch() 配置传感器。

传感器停用后,不得将来自该传感器的其他传感器事件写入 Event FMQ。

刷新传感器

如果传感器配置为批量处理传感器数据,则框架可以通过调用 flush() 强制立即刷新批量处理的传感器事件。这会导致指定传感器句柄的批量传感器事件立即写入 Event FMQ。Sensors HAL 必须将刷新完成事件附加到作为调用 flush() 的结果而写入的传感器事件的末尾。

刷新是异步发生的(即,此函数必须立即返回)。如果实现对多个传感器使用单个 FIFO,则会刷新该 FIFO,并且仅为指定的传感器添加刷新完成事件。

如果指定的传感器没有 FIFO(无法缓冲),或者如果在调用时 FIFO 为空,则 flush() 仍然必须成功并为该传感器发送刷新完成事件。这适用于除 one-shot(单次)传感器之外的所有传感器。

如果为 one-shot(单次)传感器调用 flush(),则 flush() 必须返回 BAD_VALUE,并且不生成刷新完成事件。

将传感器事件写入 FMQ

Sensors HAL 使用 Event FMQ 将传感器事件推送到 Android 传感器框架中。

Event FMQ 是一个同步 FMQ,这意味着任何尝试向 FMQ 写入比可用空间允许的事件更多的事件都会导致写入失败。在这种情况下,HAL 应确定是将当前事件集分成两个较小的事件组写入,还是在有足够的空间可用时将所有事件一起写入。

当 Sensors HAL 已将所需数量的传感器事件写入 Event FMQ 后,Sensors HAL 必须通过将 EventQueueFlagBits::READ_AND_PROCESS 位写入 Event FMQ 的 EventFlag::wake 函数来通知框架事件已准备就绪。可以使用 EventFlag::createEventFlag 和 Event FMQ 的 getEventFlagWord() 函数从 Event FMQ 创建 EventFlag。

Sensors AIDL HAL 同时支持 Event FMQ 上的 writewriteBlocking。默认实现提供了使用 write 的参考。如果使用 writeBlocking 函数,则 readNotification 标志必须设置为 EventQueueFlagBits::EVENTS_READ,这是框架在从 Event FMQ 读取事件时设置的。写入通知标志必须设置为 EventQueueFlagBits::READ_AND_PROCESS,这会通知框架事件已写入 Event FMQ。

WAKE_UP 事件

WAKE_UP 事件是传感器事件,它会导致应用处理器 (AP) 唤醒并立即处理事件。每当 WAKE_UP 事件写入 Event FMQ 时,Sensors HAL 必须获得唤醒锁,以确保系统保持唤醒状态,直到框架可以处理该事件为止。收到 WAKE_UP 事件后,框架会获得自己的唤醒锁,从而允许 Sensors HAL 释放其唤醒锁。要同步 Sensors HAL 何时释放其唤醒锁,请使用 Wake Lock FMQ。

Sensors HAL 必须读取 Wake Lock FMQ 以确定框架已处理的 WAKE_UP 事件的数量。如果未处理的 WAKE_UP 事件的总数为零,则 HAL 应仅释放其 WAKE_UP 事件的唤醒锁。处理传感器事件后,框架会计算标记为 WAKE_UP 事件的事件数量,并将此数量写回 Wake Lock FMQ。

每当框架将数据写入 Wake Lock FMQ 时,框架都会在 Wake Lock FMQ 上设置 WakeLockQueueFlagBits::DATA_WRITTEN 写入通知。

动态传感器

动态传感器是指不是设备物理组成部分,但可以用作设备输入的传感器,例如带有加速度计的游戏手柄。

当动态传感器连接时,必须从 Sensors HAL 调用 ISensorsCallback 中的 onDynamicSensorConnected 函数。这会通知框架新的动态传感器,并允许通过框架控制该传感器,并使客户端使用该传感器的事件。

同样,当动态传感器断开连接时,必须调用 ISensorsCallback 中的 onDynamicSensorDisconnected 函数,以便框架可以删除任何不再可用的传感器。

直接通道

直接通道是一种操作方法,其中传感器事件被写入特定内存,而不是写入 Event FMQ,从而绕过 Android 传感器框架。注册直接通道的客户端必须直接从用于创建直接通道的内存中读取传感器事件,并且不会通过框架接收传感器事件。configDirectReport() 函数类似于正常操作的 batch(),并配置直接报告通道。

registerDirectChannel()unregisterDirectChannel() 函数创建或销毁新的直接通道。

操作模式

setOperationMode() 函数允许框架配置传感器,以便框架可以将传感器数据注入到传感器中。这对于测试非常有用,尤其适用于框架下层存在的算法。

injectSensorData() 函数通常用于将操作参数推送到 Sensors HAL 中。该函数还可以用于将传感器事件注入到特定传感器中。

验证

要验证 Sensors HAL 的实现,请运行传感器 CTS 和 VTS 测试。

CTS 测试

传感器 CTS 测试存在于自动化 CTS 测试和手动 CTS Verifier 应用中。

自动化测试位于 cts/tests/sensor/src/android/hardware/cts。这些测试验证传感器的标准功能,例如激活传感器、批量处理和传感器事件速率。

CTS Verifier 测试位于 cts/apps/CtsVerifier/src/com/android/cts/verifier/sensors。这些测试需要测试操作员的手动输入,并确保传感器报告准确的值。

通过 CTS 测试对于确保被测设备满足所有 CDD 要求至关重要。

VTS 测试

Sensors AIDL HAL 的 VTS 测试位于 hardware/interfaces/sensors/aidl/vts/。这些测试确保 Sensors HAL 已正确实现,并且 ISensors.aidlISensorsCallback.aidl 中的所有要求都已得到适当满足。

初始化 HAL

必须支持 initialize() 函数,以在框架和 HAL 之间建立 FMQ。

公开可用传感器

在 Sensors AIDL HAL 中,getSensorsList() 函数必须在单个设备启动期间返回相同的值,即使跨 Sensors HAL 重启也是如此。getSensorsList() 函数的新要求是,它必须在单个设备启动期间返回相同的值,即使跨 Sensors HAL 重启也是如此。这允许框架在系统服务器重启时尝试重新建立传感器连接。getSensorsList() 返回的值可以在设备执行重启后更改。

将传感器事件写入 FMQ

在 Sensors AIDL HAL 中,Sensors HAL 必须主动将传感器事件写入 Event FMQ,而不是等待调用 poll() 时才写入传感器事件,只要传感器事件可用即可。HAL 还负责将正确的位写入 EventFlag,以在框架内引起 FMQ 读取。

WAKE_UP 事件

在 Sensors HAL 1.0 中,HAL 能够在 WAKE_UP 发布到 poll() 之后的任何后续 poll() 调用中,为任何 WAKE_UP 事件释放其唤醒锁,因为这表明框架已处理所有传感器事件并已获得唤醒锁(如果需要)。由于在 Sensors AIDL HAL 中,当框架处理了写入 FMQ 的事件时,HAL 不再收到通知,因此 Wake Lock FMQ 允许框架在处理 WAKE_UP 事件时与 HAL 进行通信。

在 Sensors AIDL HAL 中,Sensors HAL 为 WAKE_UP 事件获取的唤醒锁必须以 SensorsHAL_WAKEUP 开头。

动态传感器

动态传感器在 Sensors HAL 1.0 中使用 poll() 函数返回。Sensors AIDL HAL 要求,每当动态传感器连接发生更改时,都必须调用 ISensorsCallback 中的 onDynamicSensorsConnectedonDynamicSensorsDisconnected。这些回调作为通过 initialize() 函数提供的 ISensorsCallback 指针的一部分提供。

操作模式

必须支持 WAKE_UP 传感器的 DATA_INJECTION 模式。

多 HAL 支持

Sensors AIDL HAL 使用 Sensors Multi-HAL 框架支持多 HAL。有关实现详细信息,请参阅从 Sensors HAL 2.1 移植