Batching

什么是批处理?

批处理是指在传感器中枢和/或硬件 FIFO 中缓冲传感器事件,然后通过 Sensors HAL 报告这些事件。在本页中,缓冲传感器事件的位置(传感器中枢和/或硬件 FIFO)称为“FIFO”。完成传感器事件批处理后,系统会立即向 Sensors HAL(如有)报告传感器事件。

实施批处理,系统会在多个传感器事件准备好处理时仅唤醒搭载 Android 系统的主应用处理器 (AP),而不是唤醒每个事件的应用处理器,从而显著节省电量。可能节省的电量与传感器中枢和/或 FIFO 可以缓冲的事件数直接相关:可批处理的事件越多,节省电量的可能性越大。批处理利用低能耗内存来减少高能耗 AP 唤醒次数。

只有当传感器配有硬件 FIFO 和/或可在传感器中枢内缓冲事件时才会进行批处理。无论是哪种情况,传感器都必须通过 SensorInfo.fifoMaxEventCount 报告一次可以批处理的最大事件数。

如果在一个 FIFO 中为某个传感器预留了空间,则该传感器必须通过 SensorInfo.fifoReservedEventCount 报告预留的事件数。如果该 FIFO 为此传感器专有,则 SensorInfo.fifoReservedEventCount 是该 FIFO 的大小。如果该 FIFO 在多个传感器之间共用,则此值可能为零。一个常见的使用情形是,如果某个传感器是唯一的活跃传感器,则应允许该传感器使用整个 FIFO。如果多个传感器处于活跃状态,则保证在 FIFO 中为每个传感器预留至少 SensorInfo.fifoReservedEventCount 个事件的空间。如果使用传感器中枢,则必须通过软件强制执行保证。

在以下情况下对传感器事件进行批处理:

  • 传感器的当前最大报告延迟大于零,这意味着传感器事件最长可延迟到最大报告延迟,再通过 HAL 进行报告。
  • AP 处于挂起模式且传感器为非唤醒传感器。在这种情况下,事件不得唤醒 AP 且必须一直存储起来,直到唤醒 AP。

如果传感器不支持批处理且 AP 处于睡眠状态,则仅向 AP 报告唤醒传感器事件,不得报告非唤醒事件。

批处理参数

用于约束批处理行为的两个参数分别为 sampling_period_nsmax_report_latency_nssampling_period_ns 用于确定生成新传感器事件的频率,而 max_report_latency_ns 用于确定还要多久才必须向 Sensors HAL 报告事件。

sampling_period_ns

sampling_period_ns 参数的含义取决于指定传感器的报告模式:

  • 连续模式:sampling_period_ns 是采样率,表示生成事件的频率。
  • 变化时触发模式:sampling_period_ns 限制事件的采样率,表示事件的生成频率不会高于每 sampling_period_ns 纳秒一次。如果没有生成事件且测量值长时间保持不变,则周期可能超过 sampling_period_ns。如需了解详情,请参阅变化时触发报告模式。
  • 单次模式:sampling_period_ns 会被忽略。该参数没有任何作用。
  • 特殊模式:如需详细了解如何将 sampling_period_ns 用于特殊的传感器,请参阅传感器类型

如需详细了解 sampling_period_ns 在不同模式下的影响,请参阅报告模式

对于采用连续模式和变化时触发模式的传感器:

  • 如果 sampling_period_ns 小于 SensorInfo.minDelay,则 HAL 实现必须静默地将其限制为 max(SensorInfo.minDelay, 1ms)。Android 不支持以高于 1000Hz 的频率生成事件。
  • 如果 sampling_period_ns 大于 SensorInfo.maxDelay,则 HAL 实现必须静默地将其截断为 SensorInfo.maxDelay

物理传感器的运行速率和时钟精度有时会受到限制。因此,实际采样频率与请求的频率可以不同,只要它满足下表中的要求即可。

如果请求的频率

那么实际频率必须

低于最小频率 (<1/maxDelay)

在最小频率的 90%-110% 之间

在最小和最大频率之间

在请求频率的 90%-220% 之间

高于最大频率 (>1/minDelay)

在最大频率的 90%-110% 之间,且低于 1100Hz

max_report_latency_ns

max_report_latency_ns 设置了一个最长时间值(以纳秒为单位),该值是指在 AP 唤醒期间,通过 HAL 报告之前,事件可以延迟并存储在硬件 FIFO 中的最长时间。

值为零表示事件必须在测量完成后立即报告,即完全跳过 FIFO,或者在传感器发出的事件出现时立即清空 FIFO。

例如,以 50Hz 激活的加速度计,如果 max_report_latency_ns=0,则在 AP 唤醒期间,每秒会触发 50 次中断。

如果 max_report_latency_ns>0,则在检测到传感器事件后无需立即进行报告。只要所有事件的延迟均不超过 max_report_latency_ns 纳秒,就可以将事件临时存储在 FIFO 中并以批量方式进行报告。这意味着,自上一批报告的事件之后产生的所有事件,都将一次性记录并返回。这样就可以减少发送到 AP 的中断数量,并且在传感器捕获数据并进行批量处理时,AP 可以切换到低能耗模式(闲置)。

每个事件都具有相关联的时间戳。推迟事件的报告时间并不影响事件的时间戳。时间戳必须准确,并与事件的实际发生时间而非报告时间相对应。

允许传感器事件临时存储在 FIFO 中不会修改向 HAL 提交事件的行为:来自于不同传感器的事件可交错存储,并且来自于同一传感器的所有事件按时间排序。

唤醒和非唤醒事件

来自唤醒传感器的传感器事件必须存储在一个或多个唤醒 FIFO 中。一种常见的设计是,使用一个较大的共用唤醒 FIFO,来自所有唤醒传感器的事件交错存储于该 FIFO 中。或者,您可以为每个传感器配备一个唤醒 FIFO,或者为特定唤醒传感器配备专有 FIFO 并为其余唤醒传感器配备一个共用 FIFO。

类似地,来自非唤醒传感器的传感器事件必须存储在一个或多个非唤醒 FIFO 中。

在所有情况下,唤醒传感器事件和非唤醒传感器事件都不能交错存储在同一个 FIFO 中。唤醒事件必须存储在唤醒 FIFO 中,非唤醒事件必须存储在非唤醒 FIFO 中。

对于唤醒 FIFO,一个较大的共用 FIFO 设计可带来最佳的能耗效益。对于非唤醒 FIFO,一个较大的共用 FIFO 和几个较小的预留 FIFO 设计的能耗特征类似。 如需了解有关如何配置每个 FIFO 的更多建议,请参阅 FIFO 分配优先级

非挂起模式下的行为

当 AP 处于唤醒状态(未处于挂起模式)时,只要事件延迟不超过 max_report_latency,则可将事件临时存储在 FIFO 中。

只要 AP 不进入挂起模式,事件就不应被丢弃或丢失。如果在 max_report_latency 过去之前内部 FIFO 已满,则系统会在这个时候报告事件以确保不会丢失任何事件。

当多个传感器共用一个 FIFO 时,如果其中一个传感器已达到 max_report_latency,系统会立即报告来自该 FIFO 的所有事件,即使其他传感器尚未达到 max_report_latency 也是如此。这样可减少报告事件的批次。当有一个事件必须报告时,就可以报告来自所有传感器的所有事件。

例如,如果以下传感器处于启用状态:

  • max_report_latency = 20 秒时进行批处理的加速度计
  • max_report_latency = 5 秒时进行批处理的陀螺仪

可以在报告陀螺仪批次的同时报告加速度计批次(每 5 秒钟报告一次),即使加速度计和陀螺仪未共用同一个 FIFO 也可以报告。

挂起模式下的行为

如果您希望在不使 AP 保持唤醒状态的情况下从后台收集传感器数据,则采用批处理特别有用。由于传感器驱动程序和 HAL 实现被禁止持有唤醒锁*,因此 AP 可在收集传感器数据时进入挂起模式。

AP 挂起时的传感器行为取决于传感器是否为唤醒传感器。如需了解详情,请参阅唤醒传感器

当非唤醒 FIFO 存满时,它必须环绕并像环形缓冲区一样运作,覆盖较旧的事件:即新事件替换旧事件。在挂起模式下,max_report_latency 对非唤醒 FIFO 没有影响。

当唤醒 FIFO 已装满时,或者当其中一个唤醒传感器达到 max_report_latency 时,硬件必须唤醒 AP 并报告数据。

在这两种情况下(唤醒和非唤醒),只要 AP 退出挂起模式,即使一些传感器未达到 max_report_latency,也会产生一个包含所有 FIFO 内容的批处理。这样可最大限度地降低在 AP 再次进入挂起模式后却很快又要被唤醒的风险,进而最大限度地降低能耗。

*不允许驱动程序持有唤醒锁的一个值得注意的例外情况是,在 max_report_latency 小于 1 秒的情况下启用处于连续报告模式的唤醒传感器。在此情况下,驱动程序可以持有唤醒锁,这是因为 AP 在进入挂起模式前会被唤醒事件唤醒,因此没有机会进入挂起模式。

对唤醒传感器进行批处理时的注意事项

根据设备,AP 可能需要几毫秒才能完全退出挂起模式并开始刷写 FIFO。因此必须在 FIFO 中分配足够的头空间,才能让设备完全退出挂起状态,而不造成唤醒 FIFO 溢出。不得丢失任何事件,并且必须遵照 max_report_latency

对采用变化时触发模式的非唤醒传感器进行批处理时的注意事项

采用变化时触发模式的传感器仅在其所测量的值发生变化时才会生成事件。如果所测量的值在 AP 处于挂起模式时发生变化,则应用预计会在 AP 唤醒时立即收到事件。因此,如果采用变化时触发模式的非唤醒传感器与其他传感器共用 FIFO,则必须谨慎执行该传感器事件的批处理操作。每个采用变化时触发模式的传感器所生成的最后一个事件都必须始终保存在共用 FIFO 之外,使其永远不会被其他事件覆盖。当 AP 唤醒时,在报告 FIFO 中的所有事件后,还必须报告最后一个采用变化时触发模式的传感器事件。

以下是要避免的情况:

  1. 应用同时注册到共用同一个 FIFO 的非唤醒计步器(变化时触发模式)和非唤醒加速度计(连续模式)。
  2. 应用收到一个计步器事件 step_count=1000 steps 代码>。
  3. AP 转到挂起模式。
  4. 用户步行 20 步,导致计步器和加速度计事件交错存储,最后的计步器事件为 step_count = 1020 steps
  5. 用户长时间不动,导致加速度计事件在 FIFO 中继续累积,最终覆盖共享 FIFO 中的各 step_count 事件。
  6. AP 唤醒并将 FIFO 中的所有事件发送到应用。
  7. 应用只收到了加速度计事件,并认为用户没有走步。

通过将最后的计步器事件保存在 FIFO 之外的存储区,即使所有其他计步器事件都被加速度计事件覆盖,HAL 仍可以在 AP 唤醒时报告最后的事件。这样,当 AP 唤醒时,应用就会收到 step_count = 1020 steps

实现批处理

为节省电量,批处理必须在不借助 AP 的情况下实现。在批处理期间必须允许 AP 处于挂起模式。

如果在传感器中枢内执行批处理,则应尽量降低传感器中枢的耗电量。

可随时修改最大报告延迟,特别是在已启用指定传感器的情况下;该操作不应导致事件丢失。

FIFO 分配优先级

在硬件 FIFO 和/或传感器中枢缓冲区空间有限的平台上,系统设计人员可能必须选择为各传感器预留多少 FIFO 空间。为了帮助实现这一选择,下面列出了在不同传感器上实现批处理时可能有帮助的应用。

高值:低能耗行人航位推算

目标批处理时间:1 到 10 分钟

待批处理的传感器:

  • 唤醒步测器
  • 唤醒游戏旋转向量传感器(频率 5Hz)
  • 唤醒气压计(频率 5Hz)
  • 唤醒未校准磁力计(频率 5Hz)

批处理此类数据,可在 AP 处于挂起模式时执行行人航位推算。

高值:中等能耗间歇性动作/手势识别

目标批处理时间:3 秒

待批处理的传感器:非唤醒加速度计(频率 50Hz)

批处理此类数据,可定期识别任意动作和手势,而无需在收集数据时让 AP 保持唤醒状态。

中等值:中等能耗连续动作/手势识别

目标批处理时间:1 到 3 分钟

待批处理的传感器:唤醒加速度计(频率 50Hz)

批处理此类数据,可持续识别任意动作和手势,而无需在收集数据时让 AP 保持唤醒状态。

中高值:减少中断负载

目标批处理时间:小于 1 秒

待批处理的传感器:任意高频传感器(通常为非唤醒传感器)。

如果陀螺仪设置为 240Hz,仅仅批处理 10 个陀螺仪事件就可以将每秒的中断次数从 240 次减少到 24 次。

中等值:连续低频数据采集

目标批处理时间:1 到 10 分钟

待批处理的传感器:

  • 唤醒气压计(频率 1Hz)
  • 唤醒湿度传感器(频率 1Hz)
  • 其他类似频率的低频唤醒传感器

可创建低能耗的监控应用。

中低值:连续全传感器采集

目标批处理时间:1 到 10 分钟

待批处理的传感器:所有唤醒传感器(在高频下运行)

允许在 AP 处于挂起模式的情况下,完整收集传感器数据。 仅当 FIFO 空间不构成问题时,才会考虑这种方式。