电源统计信息 HAL

设备子系统功耗通常在实验室环境中针对各种稳态条件进行测量和记录,例如当屏幕开启时或设备处于闲置功耗状态时。这适用于具有恒定功耗或在实验室环境中易于测量的条件下的子系统,但不适用于某些用例,例如屏幕显示视频时。

IPower.hal 1.0 提供了一个接口,用于传递 电源提示 并报告有关子系统休眠状态指标的累积数据。在 Android 10 及更高版本中,累积统计信息报告功能位于 IPowerStats.hal 电源统计信息收集 API 中,并提供了一种检索设备上能耗数据的方法。这取代了 IPower.hal 接口的累积统计信息收集部分,从而更清晰地划分了功能。

IPowerStats 服务读数不是周期性的。它们发生在关键时刻,例如电池电量下降 1% 时。当电池耗电量低时,读数频率较低;当电池耗电量高时,读数频率较高。数据可能会发送回服务器,并可能在错误报告中用于分析和分类。这为不断降低功耗和延长电池续航时间的工作提供支持。

IPower.hal 和 IPowerStats.hal

在 Android 10 上,IPower.halIPowerStats.hal 接口均可用,但 IPower.halstats 收集功能仅通过 IPowerStats.hal 接口提供。IPowerStats.hal 功能包括用于获取和使用从受支持设备的设备上功耗测量中收集的数据的 API。

  • 为低频率(getRailInfo)和高频率(streamEnergyData)客户端执行轨级能量测量,并报告自启动以来累积的能量。
  • 报告与每个受支持的 PowerEntity 相关的信息,这些信息是数据可用的。PowerEntity 是一个平台子系统、外围设备或电源域,它们会影响设备的总功耗。
  • 报告功率实体状态集(getPowerEntityStateInfo),指定实体为此提供驻留数据,然后报告每个指定的 PowerEntity 的累积数据。

IPowerStats.hal API 由以下客户端使用

  • Statsd,用于收集每轨功耗指标。
  • Perfetto,用于将功耗与 CPU 活动相关联。
  • Batterystats,通过使用测量数据而不是从 power_profile.xml. 中的预定义常量估算电池功耗来改进电池归因。

在 Android 10 及更高版本中,设备制造商可以在 IPower.halIPowerStats.hal 功能之间进行选择,但如果未实现 IPowerStats.hal,则所有客户端都必须回退到 IPower.hal

IPowerStats.hal 实现选项

只有 IPower.hal 功能在 Android 7 到 Android 9 上可用。已升级到 Android 10 的设备必须具有硬件功耗监控子系统,或可用于监控和记录功耗统计信息的其他方法。某些 SoC 会为您收集功耗统计信息,或者您可以通过软件获得功率实体状态驻留信息。功耗监控硬件仅对于支持 getRailInfo()getEnergyData()streamEnergyData() 是必需的。

如果您在没有功耗监控硬件的情况下实现 IPowerStats.hal,则 getRailInfo()、getEnergyData()streamEnergyData() 会返回 NOT_SUPPORTED。同样,如果不想使用 getPowerEntityInfo()、getPowerEntityStateInfo()getPowerEntityStateResidencyData(),它们也可能返回 NOT_SUPPORTED

轨级监控 API 返回的数据示例包括

  • 显示器的电源轨消耗了 X µW。
  • 调制解调器的电源轨消耗了 Y µW。

子系统睡眠状态 API 返回的数据示例包括

  • 调制解调器处于睡眠状态 X 毫秒。
  • SoC 处于断电状态 Y 毫秒。
  • GPU 处于挂起状态 Z 毫秒。

使用硬件功耗监控子系统

如果您的设备设计具有硬件功耗监控子系统,请通过创建一个从中 PowerStats.hal 可以解析数据的单个 sysfs 节点,或通过进行一系列 ioctl 类型系统调用来实现 IPowerStats.hal

您必须以防止累加器溢出的方式实现内核驱动程序。使用的算法取决于您独特的硬件功耗监控子系统设计,该设计必须提供瞬时和平均总线电压和电流测量值。内核驱动程序必须以不清除能量累加器的方式捕获此数据,并且必须以 64 位变量的形式维护自启动以来每个子轨的累积能量数据,该变量会随着每次累加器查询的能量读数而递增。

给定组件(或可选的,多个组件)的统计信息必须位于单个节点中。虽然这不是 sysfs 的常规用法(通常将每个节点限制为单个值),但它可以确保所有数据的一致性。

设计指南

  • sysfs 节点读取或进行系统调用时,保持低延迟(最大 1 毫秒)。
  • 确保支持统计信息功能不会显着增加功耗
    • 不要增加接入点 (AP) 和/或子系统唤醒次数来跟踪参数,例如睡眠模式下花费的时间。
    • 在可能的情况下,利用其他流量在应用处理器和固件之间机会性地传输统计信息。
  • 如有必要,子系统可以使用以下驱动程序功能
    • 在内部缓存数据以避免延迟/唤醒,但代价是数据略微陈旧。
    • 当子系统处于睡眠状态时执行外推,以提供更新的睡眠时间,而无需唤醒子系统。

选择组件、子系统和统计信息

在选择要从中收集 IPowerStats.hal 数据的组件或子系统时,请选择设备上消耗大量电流(5 毫安或更多)或支持多种功耗模式的任何组件或子系统,例如以下各项

  • 各个 SoC 子系统。
  • 部分或完全在 SoC 外部的子系统,例如 WiFi、图像处理器或安全处理器。
  • 外围设备,例如高功率 LED 和摄像头。
  • 使用不同模式的电源域(例如整个 SoC 的电源域)。

自定义

此可选功能适用于自定义。设计用例并自定义您的使用

  • 决定要测量哪些轨,以及测量频率。
  • 决定何时读取数据,以及如何解释数据。
  • 根据您的数据,决定要采取什么操作以及何时采取操作。

验证

VTS 测试确保满足 Android 要求。IPowerStats.hal 中的注释用于验证设备是否符合规范。

例如,如果您调用 getRailInfo() 但它不返回任何内容,则 VTS 测试失败,因为您没有收到有关受监控轨的信息,或者返回 SUCCESS 状态。同样,如果您收到轨信息,但它伴随有 NON_SUPPORTEDFILE_SYSTEM_ERROR 响应,这也是失败。VTS 使用 IPower.hal 和 IPowerStats.hal 注释中的要求,验证 HAL 文件中是否遵守设备制造商规范。下面显示了 VTS 测试中使用的注释示例

/**
* Rail information:
* Reports information related to the rails being monitored.
*
* @return rails Information about monitored rails.
* @return status SUCCESS on success or NOT_SUPPORTED if
* feature is not enabled or FILESYSTEM_ERROR on filesystem nodes
* access error.
*/
getRailInfo()
generates(vec<e;RailInfo>e; rails, Status status);