實現“運行狀況”
所有 healthd
代碼均已重構爲 [email protected] 和 libhealthservice
,然後均已經過修改以實現 [email protected] HAL。這兩個庫通過 [email protected] 進行靜態關聯,這使得 [email protected] 能夠完成之前由 healthd
完成的作業(即運行 healthd_mainloop
並完成輪詢)。在 init 中,[email protected] 會將接口 IHealth
的實現註冊到 hwservicemanager
。在升級搭載 Android 8.x 供應商映像和 Android 9 框架的設備時,供應商映像可能不提供 [email protected] 服務。這項服務是按照棄用時間表強制執行的。
爲了解決此問題:
healthd
會將IHealth
註冊到hwservicemanager
(儘管它是系統守護進程)。IHealth
會被添加到系統清單中(實例名稱爲“backup”)。- 框架和
storaged
會通過healthd
(而不是hwbinder
)與binder
進行通信。 - 框架和
storaged
的代碼會進行更改,以獲取實例“default”(如果有),然後獲取“backup”。- C++ 客戶端代碼會使用
libhealthhalutils
中定義的邏輯。 - Java 客戶端代碼會使用
HealthServiceWrapper
中定義的邏輯。
- C++ 客戶端代碼會使用
- 在廣泛推出 IHealth/default 實例且棄用 Android 8.1 供應商映像後,就可以棄用 IHealth/backup 實例和
healthd
了。如需瞭解詳情,請參閱棄用 [email protected]。
針對 healthd 的板級編譯變量
BOARD_PERIODIC_CHORES_INTERVAL_*
是用於編譯 healthd
的板級變量。板級值用於分隔系統編譯部分和供應商編譯部分,無法針對系統模塊定義進行定義。在 [email protected] 中,供應商可以在 healthd_mode_ops->init
中覆蓋這兩個值(方法是棄用 [email protected].<device>
中的 libhealthservice
依賴項並重新實現此函數)。
靜態實現庫
與其他 HAL 實現庫不同,實現庫 [email protected] 是一個靜態庫,[email protected]、charger、recovery 和舊版 healthd 均關聯到此庫。
[email protected] 會實現 IHealth
(如上所述),並旨在封裝 libbatterymonitor
和 libhealthd.BOARD
。這些 [email protected] 用戶不得直接使用 BatteryMonitor
,也不得直接使用 libhealthd
中的函數;而應該將這些調用替換爲對 Health
類的調用(即實現 IHealth
接口)。爲了進一步泛化,healthd_common
代碼也會包含在 [email protected] 中。新的 healthd_common
包含 [email protected]、charger 和 healthd
之間公用代碼的剩餘部分,並會調用 IHealth 方法(而不是 BatteryMonitor)。
實現 Health 2.0 服務
在爲設備實現 [email protected] 服務時,如果默認實現:
- 足以用於設備,則直接使用
[email protected]
。 -
不足以用於設備,則創建
[email protected].(device)
可執行文件幷包括:#include <health2/service.h> int main() { return health_service_main(); }
然後:
-
如果板級
libhealthd:
- 確實存在,則與其關聯。
- 不存在,則提供針對
healthd_board_init
和healthd_board_battery_update
函數的空實現。
-
如果板級
BOARD_PERIODIC_CHORES_INTERVAL_*
變量:- 已定義,則創建設備特定的
HealthServiceCommon.cpp
(從hardware/interfaces/health/2.0/utils/libhealthservice
中複製),並在healthd_mode_service_2_0_init
中對其進行自定義。 - 未定義,則靜態關聯到
libhealthservice
。
- 已定義,則創建設備特定的
-
如果設備:
- 應該實現
getStorageInfo
和getDiskStats
API,則在get_storage_info
和get_disk_stats
函數中提供實現。 - 不應該實現這些 API,則靜態關聯到
libstoragehealthdefault
。
- 應該實現
-
更新必要的 SELinux 權限。
-
通過在恢復映像中安裝直通實現來實現恢復中的 HAL。例如:
// Android.bp cc_library_shared { name: "[email protected]<device>", recovery_available: true, relative_install_path: "hw", static_libs: [ "[email protected]", "libhealthd.<device>" // Include the following or implement device-specific storage APIs "libhealthstoragedefault", ], srcs: [ "HealthImpl.cpp", ], overrides: [ "[email protected]", ], }
// HealthImpl.cpp #include <health2/Health.h> #include <healthd/healthd.h> using android::hardware::health::V2_0::IHealth; using android::hardware::health::V2_0::implementation::Health; extern "C" IHealth* HIDL_FETCH_IHealth(const char* name) { const static std::string providedInstance{"default"}; if (providedInstance != name) return nullptr; return Health::initInstance(&gHealthdConfig).get(); }
# device.mk PRODUCT_PACKAGES += [email protected]<device>
如需瞭解詳情,請參閱 hardware/interfaces/health/2.0/README.md。
Health 客戶端
[email protected] 具有以下客戶端:
- charger。
libbatterymonitor
和healthd_common
代碼的使用情況信息封裝在 [email protected] 中。 - recovery。
libbatterymonitor
的鏈接封裝在 [email protected] 中。對Health
實現類的調用取代了對BatteryMonitor
的所有調用。 -
BatteryManager。
BatteryManager.queryProperty(int id)
是IBatteryPropertiesRegistrar.getProperty
(由healthd
提供並直接讀取/sys/class/power_supply
)的唯一客戶端。出於安全方面的考慮,不允許應用直接調用 Health HAL。在 Android 9 中,Binder 服務
IBatteryPropertiesRegistrar
由BatteryService
(而非healthd
)提供,BatteryService
會將調用委派給 Health HAL 以檢索請求的信息。 -
BatteryService。在 Android 9 中,
BatteryService
使用HealthServiceWrapper
來確定要使用的 Health 服務實例(來自供應商的“default”實例或來自 healthd 的“backup”實例)。然後,它通過IHealth.registerCallback
偵聽 Health 事件。 -
Storaged。在 Android 9 中,
storaged
使用libhealthhalutils
來確定要使用的 Health 服務實例(來自供應商的“default”實例或來自 healthd 的“backup”實例)。然後,它通過IHealth.registerCallback
偵聽 Health 事件並檢索存儲信息。
SELinux 變更
新的 [email protected] HAL 包括以下 SELinux 變更:
- 將 [email protected] 添加到
file_contexts
。 - 允許
system_server
和storaged
使用hal_health
。 - 允許
system_server
(BatteryService
) 註冊batteryproperties_service
(IBatteryPropertiesRegistrar
)。 - 允許
healthd
提供hal_health
。 - 移除允許
system_server
/storaged
通過 Binder 調用healthd
的規則。 - 移除允許
healthd
註冊batteryproperties_service
(IBatteryPropertiesRegistrar
) 的規則。
對於具有自己實現的設備,一些供應商 SELinux 變更可能是必須的。例如:
# device/<manufacturer>/<device>/sepolicy/vendor/file_contexts
/vendor/bin/hw/android\.hardware\.health@2\.0-service.<device> u:object_r:hal_health_default_exec:s0
# 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
守護進程和默認實現 [email protected]
會訪問以下內核接口以檢索電池信息:
/sys/class/power_supply/*/capacity
/sys/class/power_supply/*/charge_counter
/sys/class/power_supply/*/charge_full
/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/*/type
/sys/class/power_supply/*/voltage_max
/sys/class/power_supply/*/voltage_now
默認情況下,使用 libbatterymonitor
的任何設備特定的 Health HAL 實現都會訪問這些內核接口(除非它們在 healthd_board_init(struct healthd_config*)
中被覆蓋)。
如果這些文件缺失或者無法從 healthd
或默認服務訪問這些文件(例如,文件是一個指向供應商專用文件夾的符號鏈接,因 SELinux 政策配置錯誤而拒絕訪問),則文件無法訪問。因此,即使使用的是默認實現,也可能需要進行其他的供應商特定 SELinux 變更。
測試
Android 9 包括專門爲 [email protected] HAL 編寫的新 VTS 測試。如果設備聲明在設備清單中提供 [email protected] HAL,則該設備必須通過相應的 VTS 測試。這些測試是爲“default”實例(確保設備正確實現 HAL)和“backup”實例(確保 healthd
在被移除之前繼續正常發揮作用)編寫的。