實作 Health 2.1

在 Android 11 中,所有 healthd 程式碼都會重構為 libhealthlooplibhealth2impl,然後修改為實作 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 會向 hwservicemanager 註冊介面 IHealth 的實作項目。使用 Android 8.x 或 9 供應商映像檔和 Android 11 架構升級裝置時,供應商映像檔可能不會提供 health@2.1 服務。淘汰時間表會強制執行舊版供應商圖片的回溯相容性。

如要確保回溯相容性,請採取下列做法:

  1. healthd 會向 hwservicemanager 註冊 IHealth,即使是系統精靈也一樣。系統資訊清單會新增 IHealth,執行個體名稱為「backup」。
  2. 架構和 storaged 會透過 hwbinderhealthd 通訊,而不是 binder
  3. 架構和 storaged 的程式碼會變更為擷取「default」例項 (如有),然後擷取「backup」。
    • C++ 用戶端程式碼會使用 libhealthhalutils 中定義的邏輯。
    • Java 用戶端程式碼會使用 HealthServiceWrapper 中定義的邏輯。
  4. IHealth/default 廣泛推出後,Android 8.1 供應商映像檔就會遭到淘汰,屆時 IHealth/backup 和 healthd 也會淘汰。

適用於健康狀態檢查工具的開發板專屬建構變數

BOARD_PERIODIC_CHORES_INTERVAL_* 是用來建構 healthd 的板級變數。在系統/供應商建構作業分割期間,無法為系統模組定義主機板專屬值。這些值過去會在已淘汰的 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@2.x 具有下列用戶端:

  • 充電器。libbatterymonitorhealthd_common 程式碼的使用方式會包裝在 health@2.0-impl 中。
  • 復原。libbatterymonitor 的連結會包裝在 health@2.0-impl 中。所有對 BatteryMonitor 的呼叫都會替換為對 Health 實作類別的呼叫。
  • BatteryManager。BatteryManager.queryProperty(int id)IBatteryPropertiesRegistrar.getProperty 的唯一用戶端。IBatteryPropertiesRegistrar.getProperty 是由healthd提供,並直接讀取 /sys/class/power_supply

    基於安全考量,應用程式不得直接呼叫健康 HAL。在 Android 9 以上版本中,繫結器服務 IBatteryPropertiesRegistrarBatteryService 提供,而非 healthdBatteryService 會將呼叫委派給健康 HAL,以擷取所要求的資訊。

  • BatteryService. 在 Android 9 以上版本中,BatteryService 會使用 HealthServiceWrapper 判斷要使用 vendor 中的預設健康狀態服務執行個體,還是 healthd 中的備份健康狀態服務執行個體。BatteryService 接著會透過 IHealth.registerCallback 監聽健康狀態事件。

  • Storaged。在 Android 9 以上版本中,storaged 會使用 libhealthhalutils 判斷要使用 vendor 中的預設健康狀態服務執行個體,還是 healthd 中的備份健康狀態服務執行個體。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 (在「健康」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 (在「健康」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 (在「健康」2.1 中新增)
  • /sys/class/power_supply/*/type
  • /sys/class/power_supply/*/voltage_max
  • /sys/class/power_supply/*/voltage_now

使用 libbatterymonitor 的任何裝置專屬健康狀態 HAL 實作都會預設存取這些核心介面,除非在健康狀態實作類別建構函式中覆寫。

如果這些檔案遺失或無法從 healthd 或預設服務存取 (例如,檔案是供應商專屬資料夾的符號連結,但因 SELinux 政策設定錯誤而拒絕存取),檔案可能無法正常運作。因此即使使用預設實作方式,可能仍需進行額外的供應商專屬 SELinux 變更。

健康 2.1 中使用的部分核心介面 (例如 /sys/class/power_supply/*/capacity_level/sys/class/power_supply/*/time_to_full_now) 可能為選用介面。不過,為避免因缺少核心介面而導致架構行為不正確,建議您先挑選 CL 1398913,再建構 Health HAL 2.1 服務。

測試

Android 11 包含專為 health@2.1 HAL 編寫的全新 VTS 測試。如果裝置在裝置資訊清單中聲明 health@2.1 HAL,就必須通過對應的 VTS 測試。測試是針對預設執行個體 (確保裝置正確實作 HAL) 和備份執行個體 (確保 healthd 在移除前持續正常運作) 編寫。

電池資訊規定

健康 2.0 HAL 會在 HAL 介面上聲明一組需求,但相應的 VTS 測試在強制執行這些需求時相對寬鬆。在 Android 11 中,我們新增了 VTS 測試,以確保搭載 Android 11 以上版本的裝置符合下列規定:

  • 瞬間和平均電池電流的單位必須是微安培 (μA)。
  • 即時和平均電池電流的正負號必須正確。 具體來說:
    • 電池狀態為 UNKNOWN 時,current == 0
    • 電池狀態為 CHARGING 時,current > 0
    • 電池狀態為 NOT_CHARGING 時,電流 <= 0
    • 電池狀態為 DISCHARGING 時,current < 0
    • 電池狀態為 FULL 時不會強制執行
  • 電池狀態必須與電源是否已連接相符。具體來說:
    • 如果已接上電源,電池狀態必須是 CHARGINGNOT_CHARGINGFULL
    • 只有在電源中斷時,電池狀態才必須為 DISCHARGING

如果您在實作中使用 libbatterymonitor,並透過核心介面傳遞值,請確保 sysfs 節點回報的值正確無誤:

  • 請確認回報的電池電流採用正確的符號和單位。這包括下列 sysfs 節點:
    • /sys/class/power_supply/*/current_avg
    • /sys/class/power_supply/*/current_max
    • /sys/class/power_supply/*/current_now
    • 正值表示電池的輸入電流。
    • 值應以微安培 (μA) 為單位。
  • 請確認電池電壓是以微伏特 (μV) 為單位回報。包括下列 sysfs 節點:
    • /sys/class/power_supply/*/voltage_max
    • /sys/class/power_supply/*/voltage_now
    • 請注意,預設 HAL 實作會將 voltage_now 除以 1000,並以毫伏特 (mV) 回報值。請參閱 @1.0::HealthInfo

詳情請參閱「Linux 電源供應器類別」。