hidl 原理分析_一个 health service 不生效问题引出的一点知识
從 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 的一些特點,其中就包括其啟動時機。如下:
# 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 做延遲啟動處理,如下:
# device//health/xxx.rc
- class hal
+ class main
經過測試,此方案可行,但是這種說不出 root cause 的解決方案難以讓人接受,所以也就拉通代碼繼續研究。
最終方案
原理分析
Framework 層
首先最大疑問就是 FW 層怎么判斷使用哪一個 health 的內容。因 health 信息最終會更新到 BatteryService.java, 嘗試在此文件中尋找答案,最終找到如下關鍵代碼:
# frameworks/base/services/core/java/com/android/server/BatteryService.java
static final class HealthServiceWrapper {
private static final String TAG = "HealthServiceWrapper";
public static final String INSTANCE_HEALTHD = "backup";
public static final String INSTANCE_VENDOR = "default";
// All interesting instances, sorted by priority high -> low.
private static final List sAllInstances =
Arrays.asList(INSTANCE_VENDOR, INSTANCE_HEALTHD);
...
}
通過這段代碼知道系統是根據 service 的實例名來決定使用哪一個 health。
service 的實例名
定制 health
通過查看如下代碼得知定制 health 的實例名為 “default”。
# device/vendor/health/HealthService.cpp
/*通過庫和如下函數引入 Google healthd 部分*/
int main(void) {
return health_service_main();
}
# hardware/interfaces/health/2.0/utils/libhealthservice/HealthServiceCommon.cpp
int health_service_main(const char* instance) {
gInstanceName = instance;
if (gInstanceName.empty()) {
gInstanceName = "default"; // 空白時實例名
}
healthd_mode_ops = &healthd_mode_service_2_0_ops;
LOG(INFO) << LOG_TAG << gInstanceName << ": Hal starting main loop...";
return healthd_main();
}
Google healthd
通過查看如下代碼得知 healthd 的實例名與定制 health 相同,所以在 Framework 層面,后加載的 service 生效。
# system/core/healthd/HealthServiceDefault.cpp
/* 此 service 實例名為 “default”*/
int main(void) {
return health_service_main();
}
# system/core/healthd/HealthServiceHealthd.cpp
/* 實例名為 “backup”*/
int main() {
return health_service_main("backup");
}
# system/core/healthd/Android.bp
/* HealthServiceDefault 重寫了 HealthServiceHealthd,所以 healthd 使用的實例名為“default”*/
cc_binary {
name: "android.hardware.health@2.0-service.override",
defaults: ["android.hardware.health@2.0-service_defaults"],
overrides: [
"healthd",
],
}
解決方案
因為我們需要使用定制的 health,所以將原生的實例名改為“backup”,這樣這個問題就得以解決了。
花絮
我也嘗試給定制 health 新建一個實例名,但是未成功,后發現似乎新添實例名需要按如下方式配置一下。但因為時間和研究的動力不足就沒有繼續了。
xxx.xxx
1.0
xxx
default
backup # 似乎可以這樣添加實例名
總結
以上是生活随笔為你收集整理的hidl 原理分析_一个 health service 不生效问题引出的一点知识的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 报错 ValueError: too m
- 下一篇: 爬虫实战学习笔记_2 网络请求urlli