Android P Implementing Health

實現“運行狀況”

所有 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] 服務。這項服務是按照棄用時間表強制執行的。

爲了解決此問題:

  1. healthd 會將 IHealth 註冊到 hwservicemanager(儘管它是系統守護進程)。IHealth 會被添加到系統清單中(實例名稱爲“backup”)。
  2. 框架和 storaged 會通過 healthd(而不是 hwbinder)與 binder 進行通信。
  3. 框架和 storaged 的代碼會進行更改,以獲取實例“default”(如果有),然後獲取“backup”。
    • C++ 客戶端代碼會使用 libhealthhalutils 中定義的邏輯。
    • Java 客戶端代碼會使用 HealthServiceWrapper 中定義的邏輯。
  4. 在廣泛推出 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] 具有以下客戶端:

  • chargerlibbatterymonitor 和 healthd_common 代碼的使用情況信息封裝在 [email protected] 中。
  • recoverylibbatterymonitor 的鏈接封裝在 [email protected] 中。對 Health 實現類的調用取代了對 BatteryMonitor 的所有調用。
  • BatteryManagerBatteryManager.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 在被移除之前繼續正常發揮作用)編寫的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章