从 Android P 开始,Google 开始推荐厂家再定制一个 health 。前不久遇到一个定制 health 中的信息未成功反应到 Framework 的问题,在分析解决问题的过程中,学习到了一点新知识,所以就在这篇文章里根据解决问题的流程做一个小小的记录。
问题:定制 health service 中的一些 health 信息未成功反应到 Framework。
已知:定制 health 和 Google healthd 进程都运行于设备中,定制 health 主要重写 healthd_board_battery_update 函数,会通过库文件引用原生代码(system/core/healthd/)中的实现。
初步方案
简单介绍
服务创建时都编写了一个 x.rc 文件,用来描述 health service 的一些特点,其中就包括其启动时机。如下:
1 2 3 4 5 6 7 8
# system/core/healthd/android.hardware.health@2.0-service.rc /* sevice 类型的 setction 表示一个可执行程序(进程) */ service health-hal-2-0 /vendor/bin/hw/android.hardware.health@2.0-service or healthd.rc class hal user system group system file /dev/kmsg w
启动顺序: hal-> core-> main -> later
尝试性修改 health service 启动时机
因为对 Framework 层的处理不熟悉,就根据经验判断定制 health 与 Google healthd 可能有时序冲突,对定制 health 做延迟启动处理,如下:
1 2 3
# device/<vendor>/health/xxx.rc - class hal + class main
经过测试,此方案可行,但是这种说不出 root cause 的解决方案难以让人接受,所以也就拉通代码继续研究。
最终方案
原理分析
Framework 层
首先最大疑问就是 FW 层怎么判断使用哪一个 health 的内容。因 health 信息最终会更新到 BatteryService.java, 尝试在此文件中寻找答案,最终找到如下关键代码:
1 2 3 4 5 6 7 8 9 10
# frameworks/base/services/core/java/com/android/server/BatteryService.java staticfinalclassHealthServiceWrapper { privatestaticfinalStringTAG="HealthServiceWrapper"; publicstaticfinalStringINSTANCE_HEALTHD="backup"; publicstaticfinalStringINSTANCE_VENDOR="default"; // All interesting instances, sorted by priority high -> low. privatestaticfinal List<String> sAllInstances = Arrays.asList(INSTANCE_VENDOR, INSTANCE_HEALTHD); ... }