传感器堆栈

下图表示 Android 传感器堆栈。虽然某些传感器可以在存在传感器 Hub 时绕过它,但每个组件仅与其正上方和正下方的组件通信。控制流从应用向下流向传感器,数据流从传感器向上流向应用。

Layers and owners of the Android sensor stack

图 1. Android 传感器堆栈的层及其各自的所有者

SDK

应用通过 传感器 SDK(软件开发工具包)API 访问传感器。SDK 包含列出可用传感器和注册传感器的函数。

注册传感器时,应用会指定其首选采样频率及其延迟要求。

  • 例如,应用可能会注册到默认加速度计,请求以 100Hz 的频率发出事件,并允许以 1 秒的延迟报告事件。
  • 应用将以至少 100Hz 的速率接收来自加速度计的事件,并且可能会延迟最多 1 秒。

如需详细了解 SDK,请参阅开发者文档

框架

该框架负责将多个应用程序链接到 HAL(硬件抽象层)。HAL 本身是单客户端的。如果没有在框架级别进行多路复用,则在任何给定时间,只有一个应用程序可以访问每个传感器。

  • 当第一个应用程序注册到传感器时,框架会向 HAL 发送请求以激活传感器。
  • 当其他应用程序注册到同一传感器时,框架会考虑每个应用程序的需求,并将更新后的请求参数发送到 HAL。
    • 采样频率将是所请求采样频率的最大值,这意味着某些应用程序将以高于其请求的频率接收事件。
    • 最大报告延迟将是所请求延迟的最小值。如果一个应用程序请求一个最大报告延迟为 0 的传感器,则所有应用程序都将以连续模式接收来自此传感器的事件,即使某些应用程序请求的传感器具有非零最大报告延迟。有关更多详细信息,请参阅 批处理
  • 当最后一个注册到某个传感器的应用程序取消注册时,框架会向 HAL 发送请求以停用传感器,从而避免不必要的功耗。

多路复用的影响

框架中对多路复用层的这种需求解释了一些设计决策。

  • 当应用程序请求特定的采样频率时,不能保证事件不会以更快的速率到达。如果另一个应用程序以更快的速率请求同一传感器,则第一个应用程序也将以更快的速率接收事件。
  • 相同的缺乏保证也适用于请求的最大报告延迟:应用程序可能会接收到延迟远低于其请求的事件。
  • 除了采样频率和最大报告延迟之外,应用程序无法配置传感器参数。
    • 例如,假设一个物理传感器可以在“高精度”和“低功耗”模式下运行。
    • 在 Android 设备上,这两种模式只能使用其中一种,因为否则,一个应用程序可能会请求高精度模式,而另一个应用程序可能会请求低功耗模式;框架将无法满足这两个应用程序的需求。框架必须始终能够满足其所有客户端的需求,因此这不是一个选项。
  • 没有从应用程序向下发送数据到传感器或其驱动程序的机制。这确保了一个应用程序无法修改传感器的行为,从而破坏其他应用程序。

传感器融合

Android 框架为某些复合传感器提供了默认实现。当设备上存在陀螺仪加速度计磁力计,但不存在旋转矢量重力线性加速度传感器时,框架会实现这些传感器,以便应用程序仍然可以使用它们。

默认实现无法访问其他实现可以访问的所有数据,并且它必须在 SoC(片上系统)上运行,因此它不如其他实现那样精确或节能。设备制造商应尽可能定义自己的融合传感器(旋转矢量、重力和线性加速度,以及更新的复合传感器,如游戏旋转矢量),而不是依赖此默认实现。设备制造商还可以请求传感器芯片供应商向他们提供实现。

默认传感器融合实现未得到维护,并且可能会导致依赖它的设备无法通过 CTS(兼容性测试套件)。

底层原理

本节作为背景信息提供给维护 Android 开源项目 (AOSP) 框架代码的人员。它与硬件制造商无关。

JNI

该框架使用与 android.hardware 关联的 Java 本地接口 (JNI),并位于 frameworks/base/core/jni/ 目录中。此代码调用较低级别的本地代码以获取对传感器硬件的访问权限。

本地框架

本地框架在 frameworks/native/ 中定义,并提供与 android.hardware 软件包等效的本地框架。本地框架调用 Binder IPC 代理以获取对特定于传感器的服务的访问权限。

Binder IPC

Binder IPC 代理有助于跨进程边界进行通信。

HAL

传感器硬件抽象层 (HAL) API 是硬件驱动程序和 Android 框架之间的接口。它由一个 HAL 接口 sensors.h 和一个我们称为 sensors.cpp 的 HAL 实现组成。

该接口由 Android 和 AOSP 贡献者定义,而实现由设备制造商提供。

传感器 HAL 接口位于 hardware/libhardware/include/hardware 中。有关更多详细信息,请参阅 sensors.h

发布周期

HAL 实现通过设置 your_poll_device.common.version 来指定它实现的 HAL 接口版本。现有的 HAL 接口版本在 sensors.h 中定义,并且功能与这些版本相关联。

Android 框架目前支持 1.0 和 1.3 版本,但 1.0 版本很快将不再受支持。本文档描述了 1.3 版本的行为,所有设备都应升级到该版本。有关如何升级到 1.3 的详细信息,请参阅 HAL 版本弃用

内核驱动程序

传感器驱动程序与物理设备交互。在某些情况下,HAL 实现和驱动程序是相同的软件实体。在其他情况下,硬件集成商请求传感器芯片制造商提供驱动程序,但他们是编写 HAL 实现的人员。

在所有情况下,HAL 实现和内核驱动程序都是硬件制造商的责任,Android 不提供编写它们的首选方法。

传感器 Hub

设备的传感器堆栈可以选择性地包含一个传感器 Hub,这有助于在 SoC 可以处于暂停模式时以低功耗执行一些低级计算。例如,步数计数或传感器融合可以在这些芯片上执行。它也是实现传感器批处理、为传感器事件添加硬件 FIFO 的好地方。有关更多信息,请参阅 批处理

注意:要开发使用新传感器或 LED 的新 ContextHub 功能,您还可以使用连接到 Hikey 或 Hikey960 开发板的 Neonkey SensorHub

传感器 Hub 的具体形式取决于架构。有时它是一个单独的芯片,有时包含在与 SoC 相同的芯片上。传感器 Hub 的重要特性是它应包含足够的内存用于批处理,并消耗非常低的功耗以实现低功耗 Android 传感器。一些传感器 Hub 包含用于通用计算的微控制器和硬件加速器,以实现低功耗传感器的极低功耗计算。

传感器 Hub 的架构以及它如何与传感器和 SoC 通信(I2C 总线、SPI 总线等)不是由 Android 指定的,但它应旨在最大限度地减少整体功耗。

一种似乎对实现简易性有重大影响的选择是让两条中断线从传感器 Hub 连接到 SoC:一条用于唤醒中断(用于唤醒传感器),另一条用于非唤醒中断(用于非唤醒传感器)。

传感器

这些是进行测量的物理 MEMs 芯片。在许多情况下,同一芯片上存在多个物理传感器。例如,一些芯片包括加速度计、陀螺仪和磁力计。(此类芯片通常称为 9 轴芯片,因为每个传感器都通过 3 个轴提供数据。)

其中一些芯片还包含一些逻辑来执行常用计算,例如运动检测、步数检测和 9 轴传感器融合。

尽管 CDD 功耗和精度要求和建议针对的是 Android 传感器而不是物理传感器,但这些要求会影响物理传感器的选择。例如,游戏旋转矢量的精度要求对物理陀螺仪的所需精度有影响。设备制造商有责任推导出物理传感器的要求。