實作健康狀態 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 和輪詢。在初始化中,health@2.1-service 會將介面 IHealth 的實作項目註冊至 hwservicemanager。升級搭載 Android 8.x 或 9 供應商映像檔和 Android 11 架構的裝置時,供應商映像檔可能不會提供 health@2.1 服務。淘汰時間表會強制執行與舊版供應商映像檔的回溯相容性。

為確保回溯相容性:

  1. healthd 雖然是系統守護程式,但會將 IHealth 註冊至 hwservicemanagerIHealth 會加入系統資訊清單,並使用「backup」做為例項名稱。
  2. 架構和 storaged 會透過 hwbinderhealthd 通訊,而非 binder
  3. 架構和 storaged 的程式碼會變更為擷取「預設」例項 (如果可用),然後擷取「備用」例項。
    • C++ 用戶端程式碼會使用 libhealthhalutils 中定義的邏輯。
    • Java 用戶端程式碼會使用 HealthServiceWrapper 中定義的邏輯。
  4. 在 IHealth/預設廣泛提供,且 Android 8.1 供應商映像檔已淘汰後,IHealth/備份和 healthd 也將淘汰。詳情請參閱 Deprecating health@1.0

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 中包裝。
  • recovery。libbatterymonitor 的連結已包裝在 health@2.0-impl 中。所有對 BatteryMonitor 的呼叫都會由對 Health 實作類別的呼叫取代。
  • BatteryManager. BatteryManager.queryProperty(int id)IBatteryPropertiesRegistrar.getProperty 的唯一用戶端。IBatteryPropertiesRegistrar.getProperty 是由 healthd 提供,並直接讀取 /sys/class/power_supply

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

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

  • 已保存。在 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 (新增於 Health 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 (新增於 Health 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 (新增於 Health 2.1)
  • /sys/class/power_supply/*/type
  • /sys/class/power_supply/*/voltage_max
  • /sys/class/power_supply/*/voltage_now

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

如果 healthd 或預設服務無法存取這些檔案 (例如檔案本身是供應商專屬資料夾的符號連結,而該資料夾因 SELinux 政策設定錯誤而拒絕存取),這些檔案可能無法正常運作。因此,即使使用了預設實作,您可能還是需要變更供應商專屬的 SELinux。

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

測試

Android 11 包含專為 health@2.1 HAL 所撰寫的全新 VTS 測試。如果裝置在裝置資訊清單中宣告了 health@2.1 HAL,就必須通過對應的 VTS 測試。我們會為預設例項 (確保裝置正確實作 HAL) 和備份例項 (確保 healthd 在移除前繼續正常運作) 撰寫測試。

電池資訊規定

Health 2.0 HAL 會針對 HAL 介面列出一系列要求,但相應的 VTS 測試在執行時會相對寬鬆。我們在 Android 11 中加入了新的 VTS 測試,針對搭載 Android 11 以上版本的裝置強制執行下列規定:

  • 即時和平均電池電流的單位必須為微安 (μA)。
  • 瞬時和平均電池電流的符號必須正確。具體情況如下:
    • 目前電量為 UNKNOWN 時 == 0
    • 目前電量為 CHARGING 時 > 0
    • 電池狀態為 NOT_CHARGING 時,電流 <= 0
    • 電池狀態為 DISCHARGING 時,電流 < 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 電源供應類別」。