| <html devsite><head> |
| <title>传感器堆栈</title> |
| <meta name="project_path" value="/_project.yaml"/> |
| <meta name="book_path" value="/_book.yaml"/> |
| </head> |
| <body> |
| <!-- |
| Copyright 2017 The Android Open Source Project |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| |
| <p>下图显示的是 Android 传感器堆栈。尽管某些传感器可以绕过传感器中枢(如果存在)进行通信,但各个组件仅可与其上方和下方紧邻的组件通信。控制系统从应用向下流向传感器,数据从传感器向上流向应用。</p> |
| <img src="images/ape_fwk_sensors.png" alt="Android 传感器堆栈的层级和所有者"/> |
| <p class="img-caption"><strong>图 1. </strong> Android 传感器堆栈层级以及各自的所有者</p> |
| |
| <h2 id="sdk">SDK</h2> |
| <p>应用通过 <a href="http://developer.android.com/reference/android/hardware/SensorManager.html">Sensors SDK(软件开发套件)API</a> 访问传感器。SDK 包含用以列示可用传感器和注册到传感器的函数。</p> |
| <p>在注册到传感器时,应用可指定自己的首选采样率和延迟要求。</p> |
| <ul> |
| <li>例如,应用可注册到默认加速度计,以 100Hz 的频率请求事件,并允许事件报告有 1 秒延迟。</li> |
| <li>应用将以至少 100Hz 的频率从加速度计接收事件,且最多会延迟 1 秒。</li> |
| </ul> |
| <p>请参阅<a href="index.html#targeted_at_developers">开发者文档</a>,详细了解 SDK。</p> |
| <h2 id="framework">框架</h2> |
| <p>框架负责将多个应用关联到 <a href="hal-interface.html">HAL</a>。HAL 本身是单一客户端。如果框架级别没有发生这种多路复用,则在任何指定时间内只有一个应用可以访问各个传感器。</p> |
| <ul> |
| <li>当第一个应用注册到传感器时,框架会向 HAL 发送请求以激活传感器。</li> |
| <li>当其他应用注册到相同的传感器时,框架会考虑每个应用的要求,并将更新的已请求参数发送到 HAL。<ul> |
| <li><a href="hal-interface.html#sampling_period_ns">采样率</a>将是请求的采样率的最大值,这意味着一些应用接收事件的频率会高于所请求的频率。</li> |
| <li><a href="hal-interface.html#max_report_latency_ns">最大报告延迟</a>将是请求的延迟的最小值。如果某个应用以 0 为最大报告延迟请求传感器,则所有应用将以连续模式从该传感器接收事件,即使某些应用以非零值的最大报告延迟请求传感器也是如此。请参阅<a href="batching.html">批处理</a>,了解详情。</li> |
| </ul> |
| </li> |
| <li>当注册到某个传感器的最后一个应用取消注册之后,框架会向 HAL 发送请求以停用该传感器,从而避免不必要的功耗。</li> |
| </ul> |
| <h3 id="impact_of_multiplexing">多路复用的影响</h3> |
| <p>在框架中实现多路复用层的这一需求解释了一些设计决策。</p> |
| <ul> |
| <li>当应用请求特定采样率时,不能保证事件不会以更快的频率到达。如果另一个应用以更快的频率请求同一传感器,则第一个应用也将以较快频率接收事件。</li> |
| <li>请求的最大报告延迟同样无法得到保证:应用可能以比请求的延迟短的多的延迟接收事件。</li> |
| <li>除了采样率和最大报告延迟之外,应用还无法配置传感器参数。 |
| <ul> |
| <li>例如,假设某个物理传感器可同时在“高精确度”和“低电耗”模式下运行。</li> |
| <li>这两种模式中只有一种可以在 Android 设备上使用,因为否则一个应用可能请求高精确度模式,而另一个可能请求低电耗模式;框架根本无法同时满足这两个应用的要求。框架必须始终能够满足所有客户端的需要,因此同时使用两种模式是不可行的。</li> |
| </ul> |
| </li> |
| <li>没有将数据从应用向下发送至传感器或其驱动程序的机制。这样可以确保某个应用无法修改传感器的行为,从而不会对其他应用造成破坏。</li> |
| </ul> |
| <h3 id="sensor_fusion">传感器融合</h3> |
| <p>Android 框架为部分复合传感器提供默认实现。如果一个设备上有<a href="sensor-types.html#gyroscope">陀螺仪</a>、<a href="sensor-types.html#accelerometer">加速度计</a>和<a href="sensor-types.html#magnetic_field_sensor">磁力计</a>,但没有<a href="sensor-types.html#rotation_vector">旋转矢量</a>、<a href="sensor-types.html#gravity">重力</a>和<a href="sensor-types.html#linear_acceleration">线性加速度</a>传感器,则框架会实现这些传感器,以便应用仍然可以使用它们。</p> |
| <p>默认实现无法访问其他实现可以访问的所有数据,并且必须在 SoC 上运行,因此它不像其他实现那样精准和省电。设备制造商应尽可能定义自己的融合传感器(旋转矢量传感器、重力传感器和线性加速度传感器,以及<a href="sensor-types.html#game_rotation_vector">游戏旋转矢量</a>传感器等较新的复合传感器),而非依赖该默认实现。此外,设备制造商也可以要求传感器芯片供应商为其提供实现。</p> |
| <p>默认的传感器融合实现没有相关的维护,且可能导致依赖它的设备无法通过 CTS 验证。</p> |
| <h3 id="under_the_hood">深入了解</h3> |
| <p>本部分作为背景信息提供,适用于 Android 开放源代码项目 (AOSP) 框架代码的维护人员,与硬件制造商无关。</p> |
| <h4 id="jni">JNI</h4> |
| <p>框架使用的是与 <a href="http://developer.android.com/reference/android/hardware/package-summary.html">android.hardware</a> 相关联的 Java 本机接口 (JNI)(位于 <code>frameworks/base/core/jni/</code> 目录中)。该代码会调用较低级别的原生代码,以获取对相应传感器硬件的访问权限。</p> |
| <h4 id="native_framework">原生框架</h4> |
| <p>原生框架在 <code>frameworks/native/</code> 中定义,提供相当于 <a href="http://developer.android.com/reference/android/hardware/package-summary.html">android.hardware</a> 文件包的原生内容。原生框架会调用 Binder IPC 代理,以获取对传感器专属服务的访问权限。</p> |
| <h4 id="binder_ipc">Binder IPC</h4> |
| <p>Binder IPC 代理用于促进跨越进程边界的通信。</p> |
| <h2 id="hal">HAL</h2> |
| <p>Sensors Hardware Abstraction Layer (HAL) API 是硬件驱动程序和 Android 框架之间的接口。它包含一个 HAL 接口 sensors.h 和一个我们称之为 sensors.cpp 的 HAL 实现。</p> |
| <p>接口由 Android 和 AOSP 贡献者定义,并由设备制造商提供实现。</p> |
| <p>传感器 HAL 接口位于 <code>hardware/libhardware/include/hardware</code> 中。请参阅 <a href="https://android.googlesource.com/platform/hardware/libhardware/+/master/include/hardware/sensors.h">sensors.h</a>,了解详情。</p> |
| <h3 id="release_cycle">版本周期</h3> |
| <p>HAL 实现通过设置 <code>your_poll_device.common.version</code> 指定实现的 HAL 接口版本。现有 HAL 接口版本在 sensors.h 中定义,相应功能与这些版本绑定在一起。</p> |
| <p>Android 框架目前支持版本 1.0 和 1.3,不过版本 1.0 很快将不再受支持。本文档介绍了版本 1.3(所有设备均应升级到该版本)的行为。要详细了解如何升级到版本 1.3,请参阅 <a href="versioning.html">HAL 版本弃用</a>。</p> |
| <h2 id="kernel_driver">内核驱动程序</h2> |
| <p>传感器驱动程序可与物理设备进行交互。在某些情况下,HAL 实现和驱动程序是同一软件实体。在其他情况下,硬件集成者会要求传感器芯片制造商提供相应驱动程序,但是它们是用于编写 HAL 实现的驱动程序。</p> |
| <p>在所有情况下,HAL 实现和内核驱动程序都由硬件制造商负责提供,Android 不提供首选编写方式。</p> |
| <h2 id="sensor_hub">传感器中枢</h2> |
| <p>设备的传感器堆栈可视需要添加传感器中枢。在 SoC 可以处于暂停模式时,传感器中枢对执行一些低功耗的低级计算任务非常有用。例如,计步功能或传感器融合功能可以在这些芯片上执行。此外,它也是实施传感器批处理以及为传感器事件添加硬件 FIFO 的理想位置。请参阅<a href="batching.html">批处理</a>,了解详情。</p> |
| <p>传感器中枢的具体化方式取决于架构。它有时是一个单独的芯片,有时包含在与 SoC 相同的芯片上。传感器中枢的重要特征是,应该包含足够的内存来进行批处理,并消耗极少的电量以便能实现低功耗 Android 传感器。部分传感器中枢包含一个微控制器(用于通用计算)和硬件加速器(用于针对低电耗传感器实现极低功耗计算)。</p> |
| <p>传感器中枢的架构方式以及与传感器和 SoC(I2C 总线、SPI 总线等)的通信方式并非由 Android 指定,但应该以最大程度减少整体功耗为目标。</p> |
| <p>有一种方案似乎会对实现的简单性产生重大影响,即从传感器中枢到 SoC 设置两个中断行:一个用于唤醒中断(适用于唤醒传感器),另一个用于非唤醒中断(适用于非唤醒传感器)。</p> |
| <h2 id="sensors">传感器</h2> |
| <p>传感器是进行测量操作的物理 MEM 芯片。在很多情况下,同一个芯片上会有多个物理传感器。例如,一些芯片中包含加速度计、陀螺仪和磁力计(此类芯片通常称为 9 轴芯片,因为每个传感器基于 3 个轴提供数据)。</p> |
| <p>此外,其中的部分芯片还包含用于执行常见计算任务(例如运动状态检测、步数检测以及 9 轴传感器融合)的逻辑。</p> |
| <p>尽管 CDD 功率和精确度的要求与建议针对的是 Android 传感器而非物理传感器,但这些要求会影响物理传感器的选择。例如,游戏旋转矢量传感器的精确度要求会影响物理陀螺仪的精确度要求。设备制造商负责推算物理传感器的相关要求。</p> |
| |
| </body></html> |