在 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”实例(确保 healthd
healthd 在被移除之前继续正常发挥作用)编写的。
电池信息要求
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 电源类。