Health 2.1 の実装

Android 11 では、すべての healthd コードが libhealthlooplibhealth2impl にリファクタリングされ、health@2.1 HAL を実装するように変更されました。これら 2 つのライブラリは、Health 2.1 のパススルー実装である health@2.0-impl-2.1 によって静的にリンクされています。静的にリンクされたライブラリにより、health@2.0-impl-2.1 は、healthd_mainloop の実行やポーリングなど、healthd と同じ処理を実行できます。init では、health@2.1-service がインターフェース IHealth の実装を hwservicemanager に登録します。Android 8.x または 9 ベンダーのイメージと Android 11 フレームワークを使用してデバイスをアップグレードする場合、ベンダー イメージは health@2.1 サービスを提供できない可能性があります。古いベンダー イメージとの下位互換性は、サポート終了予定によって決まります。

下位互換性を確保するには:

  1. healthdIHealthhwservicemanager に登録します(システムデーモンであるにもかかわらず)。IHealth が、インスタンス名「backup」でシステム マニフェストに追加されます。
  2. フレームワークと storaged は、binder ではなく hwbinder を介して healthd と通信します。
  3. フレームワークと storaged のコードが、インスタンス「default」と、可能であれば「backup」を取得するように変更されます。
    • C++ クライアント コードでは、libhealthhalutils で定義されたロジックが使用されます。
    • Java クライアント コードでは、HealthServiceWrapper で定義されたロジックが使用されます。
  4. IHealth / default が広く使用可能になり、Android 8.1 ベンダー イメージのサポートが終了したら、IHealth / backup と healthd のサポートが終了する可能性があります。詳しくは、health@1.0 のサポート終了をご覧ください。

healthd のボード固有のビルド変数

BOARD_PERIODIC_CHORES_INTERVAL_* は、healthd のビルドに使用されるボード固有の変数です。システム/ベンダーのビルド分割の一環として、ボード固有の値はシステム モジュールに定義できません。これらの値は、サポートが終了した関数 healthd_board_init でオーバーライドされていました。

health@2.1 では、ベンダーは、ヘルス実装クラス コンストラクタに渡す前に、healthd_config 構造体内でこの 2 つの周期区間の値をオーバーライドできます。ヘルス実装クラスは android::hardware::health::V2_1::implementation::Health から継承します。

Health 2.1 サービスの実装

Health 2.1 サービスの実装については、hardware/interfaces/health/2.1/README.md をご覧ください。

Health クライアント

health@2.x には次のクライアントがあります。

  • chargerlibbatterymonitorhealthd_common コードは、health@2.0-impl でラップされます。
  • recoverylibbatterymonitor へのリンクは health@2.0-impl にラップされます。BatteryMonitor への呼び出しはすべて、Health 実装クラスへの呼び出しに置き換えられます。
  • BatteryManagerBatteryManager.queryProperty(int id)IBatteryPropertiesRegistrar.getProperty の唯一のクライアントでした。healthd によって IBatteryPropertiesRegistrar.getProperty が提供され、/sys/class/power_supply を直接読み取ります。

    セキュリティ上の考慮事項として、アプリは Health HAL を直接呼び出すことができません。Android 9 以降では、バインダー サービス IBatteryPropertiesRegistrarhealthd ではなく BatteryService によって提供されます。BatteryService は、呼び出しをヘルス HAL に委任して、必要な情報を取得します。

  • BatteryService。Android 9 以降では、BatteryServiceHealthServiceWrapper を使用して、vendor のデフォルトのヘルスサービス インスタンスを使用するのか、healthd のバックアップ ヘルスサービス インスタンスを使用するのかを決定します。それから、BatteryServiceIHealth.registerCallback を介してヘルスイベントをリッスンします。

  • Storaged。Android 9 以降では、storagedlibhealthhalutils を使用して、vendor のデフォルトのヘルスサービス インスタンスを使用するのか、healthd のバックアップ ヘルスサービス インスタンスを使用するのかを決定します。それから、storagedIHealth.registerCallback を介してヘルスイベントをリッスンし、ストレージ情報を取得します。

SELinux の変更点

health@2.1 HAL には、プラットフォームにおける次の SELinux の変更が含まれています。

  • android.hardware.health@2.1-servicefile_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 を使用するデバイス固有の Health HAL 実装は、health_implementation クラス コンストラクタでオーバーライドしない限り、デフォルトでこれらのカーネル インターフェースにアクセスします。

これらのファイルが見つからないか、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 では、Android 11 以降でリリースするデバイスに対して次の要件を強制する新しい VTS テストが追加されています。

  • 瞬時および平均のバッテリー電流の単位は、マイクロアンペア(μA)である必要があります。
  • 瞬時および平均のバッテリー電流には正しい符号を使用する必要があります。詳細は以下のとおりです。
    • current == 0(バッテリーのステータスが UNKNOWN の場合)
    • current > 0(バッテリーのステータスが CHARGING の場合)
    • current <= 0(バッテリーのステータスが NOT_CHARGING の場合)
    • current < 0(バッテリーのステータスが DISCHARGING の場合)
    • バッテリーのステータスが 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 を 1,000 で割り、値をミリボルト(mV)で報告します。@1.0::HealthInfo をご覧ください。

詳細については、Linux 電源クラスをご覧ください。