在 Android 11 中,所有 healthd 代码都被重构为 libhealthloop 和 libhealth2impl,然后进行了修改以实现 health@2.1 HAL。这两个库通过 health@2.0-impl-2.1(Health 2.1 的直通实现)静态关联。通过静态链接库,health@2.0-impl-2.1 可以执行与 healthd 相同的工作,例如运行 healthd_mainloop 和轮询。在 init 中,health@2.1-service 会将接口 IHealth 的实现注册到 hwservicemanager。在使用 Android 8.x 或 9 供应商映像和 Android 11 框架升级设备时,供应商映像可能不会提供 health@2.1 服务。与旧版供应商映像的向后兼容性按照废弃时间表强制执行。
要确保向后兼容性,请执行以下操作:
- 尽管这是一个系统守护进程,
healthd会将IHealth注册到hwservicemanager。将IHealth添加到系统清单中(实例名称为“backup”)。 - 框架和
storaged通过hwbinder(而不是binder)与healthd通信。 - 框架和
storaged的代码会更改为获取实例“default”(如果有),然后获取“backup”实例。- C++ 客户端代码会使用
libhealthhalutils中定义的逻辑。 - Java 客户端代码使用
HealthServiceWrapper中定义的逻辑。
- C++ 客户端代码会使用
- 在广泛推出 IHealth/default 实例且弃用 Android 8.1 供应商映像后,就可以弃用 IHealth/backup 实例和
healthd。如需了解详情,请参阅弃用 health@1.0。
针对 healthd 的板级编译变量
BOARD_PERIODIC_CHORES_INTERVAL_* 是用于构建 healthd 的板级变量。在系统/供应商 build 拆分过程中,无法为系统模块定义板级值。这些值会在已废弃的函数 healthd_board_init 中替换。
在 health@2.1 中,供应商可以在传递到运行状况实现类构造函数之前替换 healthd_config 结构体中的这两个周期性间隔值。运行状况实现类应继承自 android::hardware::health::V2_1::implementation::Health。
实现 Health 2.1 服务
如需了解如何实现 Health 2.1 服务,请参阅 hardware/interfaces/health/2.1/README.md。
Health 客户端
health@2.0 具有以下客户端:
- charger。
libbatterymonitor和healthd_common代码的使用在health@2.0-impl中封装。 - recovery:
libbatterymonitor的链接封装在health@2.0-impl中。对BatteryMonitor的所有调用都会替换为对Health实现类的调用。 BatteryManager。
BatteryManager.queryProperty(int id)是IBatteryPropertiesRegistrar.getProperty的唯一客户端。IBatteryPropertiesRegistrar.getProperty由healthd提供,并直接读取/sys/class/power_supply。出于安全方面的考虑,不允许应用直接调用 Health HAL。在 Android 9 及更高版本中,Binder 服务
IBatteryPropertiesRegistrar由BatteryService(而非healthd)提供。BatteryService将调用委派给 Health HAL 以检索请求的信息。BatteryService。在 Android 9 及更高版本中,
BatteryService使用HealthServiceWrapper来决定是使用来自vendor的默认 Health 服务实例还是使用来自healthd的备用 Health 服务实例。然后,BatteryService通过IHealth.registerCallback监听健康事件。Storaged。在 Android 9 及更高版本中,
storaged使用libhealthhalutils来决定是使用来自vendor的默认 Health 服务实例还是使用来自healthd的备用 Health 服务实例。然后,storaged通过IHealth.registerCallback监听健康事件,并检索存储信息。
SELinux 更改
health@2.1 HAL 在平台中包含以下 SELinux 变更:
- 将
android.hardware.health@2.1-service添加到file_contexts。
对于具有自己实现的设备,一些供应商 SELinux 变更可能是必须的。示例:
# device/<manufacturer>/<device>/sepolicy/vendor/hal_health_default.te
# Add device specific permissions to hal_health_default domain, especially
# if it links to board-specific libhealthd or implements storage APIs.
内核接口
healthd 守护进程和默认实现 android.hardware.health@2.0-impl-2.1 会访问以下内核接口以检索电池信息:
/sys/class/power_supply/*/capacity_level(在 Health 2.1 中添加)/sys/class/power_supply/*/capacity/sys/class/power_supply/*/charge_counter/sys/class/power_supply/*/charge_full/sys/class/power_supply/*/charge_full_design(在 Health 2.1 中添加)/sys/class/power_supply/*/current_avg/sys/class/power_supply/*/current_max/sys/class/power_supply/*/current_now/sys/class/power_supply/*/cycle_count/sys/class/power_supply/*/health/sys/class/power_supply/*/online/sys/class/power_supply/*/present/sys/class/power_supply/*/status/sys/class/power_supply/*/technology/sys/class/power_supply/*/temp/sys/class/power_supply/*/time_to_full_now(在 Health 2.1 中添加)/sys/class/power_supply/*/type/sys/class/power_supply/*/voltage_max/sys/class/power_supply/*/voltage_now
默认情况下,使用 libbatterymonitor 的任何设备特定的 Health HAL 实现都会访问这些内核接口,除非它们在运行状况实现类构造函数中被替换。
如果这些文件缺失或者无法从 healthd 或默认服务访问这些文件(例如,文件是一个指向供应商专用文件夹的符号链接,因 SELinux 政策配置错误而拒绝访问),这些文件可能无法正常运行。因此,即使使用的是默认实现,也可能需要进行其他的供应商特定 SELinux 变更。
Health 2.1 中使用的某些内核接口(如 /sys/class/power_supply/*/capacity_level 和 /sys/class/power_supply/*/time_to_full_now)可能是可选的。不过,为了防止因缺少内核接口而导致错误的框架行为,建议您在构建 Health HAL 2.1 服务之前择优挑选 CL 1398913。
测试
Android 11 包含专门为 health@2.1 HAL 编写的新 VTS 测试。如果设备在设备清单中声明了 health@2.1 HAL,则该设备必须通过相应的 VTS 测试。这些测试是为“default”实例(确保设备正确实现 HAL)和“backup”实例(确保 healthdhealthd 在被移除之前继续正常发挥作用)编写的。
电池信息要求
Health 2.0 HAL 对 HAL 接口提出了一组要求,但相应的 VTS 测试在强制执行这些要求方面相对较为宽松。 在 Android 11 中,添加了新的 VTS 测试,以便在搭载 Android 11 及更高版本的设备上强制执行以下要求:
- 当前的电池和平均电池状况必须为微单位 (~A)。
- 当前电量和平均电池电量的符号必须正确无误。具体而言:
- 当电池状态为
UNKNOWN时,电流 == 0 - 当电池状态为
CHARGING时,电流 > 0 - 当电池电量为
NOT_CHARGING时,电流 <= 0 - 当前电量状态低于
DISCHARGING - 电池状态为
FULL时不强制执行
- 当电池状态为
- 电池状态必须正确无误,才能连接电源。具体而言:
- 当且仅当连接电源时,电池状态必须是
CHARGING、NOT_CHARGING或FULL之一; - 当且仅当电源源断开连接时,电池状态必须为
DISCHARGING。
- 当且仅当连接电源时,电池状态必须是
如果您在实现中使用 libbatterymonitor 并从内核接口传递值,请确保 sysfs 节点报告正确的值:
- 确保使用正确的电量和单位对电池进行报告。这包括以下 sysfs 节点:
/sys/class/power_supply/*/current_avg/sys/class/power_supply/*/current_max/sys/class/power_supply/*/current_now- 正值表示传入电池的当前电量。
- 值应以微单位 ($A) 表示。
- 确保以微量 (VV) 为单位报告电池电压。这包括以下 sysfs 节点:
/sys/class/power_supply/*/voltage_max/sys/class/power_supply/*/voltage_now- 请注意,默认 HAL 实现将
voltage_now除以 1000,并报告以毫安 (mV) 为单位的值。请参阅 @1.0::HealthInfo。
如需了解详情,请参阅 Linux 电源类。