Health 2.1 implementieren

In Android 11 wird der gesamte healthd-Code in libhealthloop und libhealth2impl refaktoriert und dann so geändert, dass die health@2.1-HAL implementiert wird. Diese beiden Bibliotheken werden von health@2.0-impl-2.1, der Passthrough-Implementierung von Health 2.1, statisch verknüpft. Die statisch verknüpften Bibliotheken ermöglichen es health@2.0-impl-2.1, dieselben Aufgaben wie healthd auszuführen, z. B. healthd_mainloop und Polling. In „init“ registriert health@2.1-service eine Implementierung der Schnittstelle IHealth für hwservicemanager. Beim Upgrade von Geräten mit einem Anbieter-Image für Android 8.x oder 9 und einem Android 11-Framework wird der Dienst „health@2.1“ möglicherweise nicht vom Anbieter-Image bereitgestellt. Die Abwärtskompatibilität mit alten Anbieter-Images wird durch den Einstellungszeitplan erzwungen.

So sorgen Sie für Abwärtskompatibilität:

  1. healthd registriert IHealth bei hwservicemanager, obwohl es sich um einen System-Daemon handelt. IHealth wird dem Systemmanifest mit dem Instanznamen „backup“ hinzugefügt.
  2. Das Framework und storaged kommunizieren über hwbinder anstelle von binder mit healthd.
  3. Der Code für das Framework und storaged wurde geändert, um die Instanz „default“ (falls verfügbar) und dann „backup“ abzurufen.
    • Der C++-Clientcode verwendet die in libhealthhalutils definierte Logik.
    • Im Java-Clientcode wird die in HealthServiceWrapper definierte Logik verwendet.
  4. Sobald IHealth/default allgemein verfügbar ist und Vendor-Images für Android 8.1 eingestellt werden, können IHealth/backup und healthd eingestellt werden.

Board-spezifische Build-Variablen für healthd

BOARD_PERIODIC_CHORES_INTERVAL_* sind boardspezifische Variablen, die zum Erstellen von healthd verwendet werden. Im Rahmen der Aufteilung von System- und Anbieter-Builds können keine boardspezifischen Werte für Systemmodule definiert werden. Diese Werte wurden in der verworfenen Funktion healthd_board_init überschrieben.

In health@2.1 können Anbieter diese beiden Werte für das Intervall für regelmäßige Aufgaben in der healthd_config-Struktur überschreiben, bevor sie an den Konstruktor der Health-Implementierungsklasse übergeben werden. Die Klasse für die Gesundheitsimplementierung sollte von android::hardware::health::V2_1::implementation::Health abgeleitet werden.

Health 2.1-Dienst implementieren

Informationen zur Implementierung des Health 2.1-Dienstes finden Sie unter hardware/interfaces/health/2.1/README.md.

Gesundheits-Clients

health@2.x hat die folgenden Clients:

  • Ladegerät Die Verwendung von libbatterymonitor- und healthd_common-Code ist in health@2.0-impl eingeschlossen.
  • recovery. Die Verknüpfung mit libbatterymonitor ist in health@2.0-impl enthalten. Alle Aufrufe von BatteryMonitor werden durch Aufrufe der Implementierungsklasse Health ersetzt.
  • BatteryManager BatteryManager.queryProperty(int id) war der einzige Client von IBatteryPropertiesRegistrar.getProperty. IBatteryPropertiesRegistrar.getProperty wurde von healthd bereitgestellt und direkt von /sys/class/power_supply gelesen.

    Aus Sicherheitsgründen dürfen Apps nicht direkt in den Health HAL aufrufen. In Android 9 und höher wird der Binder-Dienst IBatteryPropertiesRegistrar von BatteryService anstelle von healthd bereitgestellt. BatteryService delegiert den Aufruf an die Health-HAL, um die angeforderten Informationen abzurufen.

  • BatteryService Unter Android 9 und höher verwendet BatteryService HealthServiceWrapper, um zu bestimmen, ob die Standard-Health-Service-Instanz von vendor oder die Backup-Health-Service-Instanz von healthd verwendet werden soll. BatteryService wartet dann über IHealth.registerCallback auf Gesundheitsereignisse.

  • Storaged Unter Android 9 und höher verwendet storaged libhealthhalutils, um zu bestimmen, ob die Standard-Health-Service-Instanz von vendor oder die Backup-Health-Service-Instanz von healthd verwendet werden soll. storaged wartet dann über IHealth.registerCallback auf Gesundheitsereignisse und ruft Speicherinformationen ab.

SELinux-Änderungen

Der health@2.1-HAL enthält die folgenden SELinux-Änderungen auf der Plattform:

  • Fügt android.hardware.health@2.1-service zu file_contexts hinzu.

Bei Geräten mit eigener Implementierung sind möglicherweise einige SELinux-Änderungen des Anbieters erforderlich. Beispiel:

# 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.

Kernelschnittstellen

Der healthd-Daemon und die Standardimplementierung android.hardware.health@2.0-impl-2.1 greifen auf die folgenden Kernelschnittstellen zu, um Akkuinformationen abzurufen:

  • /sys/class/power_supply/*/capacity_level (in Health 2.1 hinzugefügt)
  • /sys/class/power_supply/*/capacity
  • /sys/class/power_supply/*/charge_counter
  • /sys/class/power_supply/*/charge_full
  • /sys/class/power_supply/*/charge_full_design (in Health 2.1 hinzugefügt)
  • /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 (in Health 2.1 hinzugefügt)
  • /sys/class/power_supply/*/type
  • /sys/class/power_supply/*/voltage_max
  • /sys/class/power_supply/*/voltage_now

Jede gerätespezifische Health-HAL-Implementierung, die libbatterymonitor verwendet, greift standardmäßig auf diese Kernelschnittstellen zu, sofern dies nicht im Konstruktor der Health-Implementierungsklasse überschrieben wird.

Wenn diese Dateien fehlen oder nicht über healthd oder den Standarddienst zugänglich sind (z. B. wenn die Datei ein Symlink zu einem anbieterspezifischen Ordner ist, der aufgrund einer falsch konfigurierten SELinux-Richtlinie den Zugriff verweigert), funktionieren sie möglicherweise nicht richtig. Daher können zusätzliche anbieterspezifische SELinux-Änderungen erforderlich sein, auch wenn die Standardimplementierung verwendet wird.

Einige in Health 2.1 verwendete Kernelschnittstellen, z. B. /sys/class/power_supply/*/capacity_level und /sys/class/power_supply/*/time_to_full_now, sind möglicherweise optional. Um jedoch falsches Framework-Verhalten aufgrund fehlender Kernelschnittstellen zu verhindern, wird empfohlen, CL 1398913 vor dem Erstellen des Health HAL 2.1-Dienstes zu cherry-picken.

Testen

Android 11 enthält neue VTS-Tests, die speziell für das Health 2.1-HAL geschrieben wurden. Wenn in der Geräte-Manifestdatei die health@2.1-HAL deklariert ist, muss das Gerät die entsprechenden VTS-Tests bestehen. Tests werden sowohl für die Standardinstanz (um sicherzustellen, dass das Gerät das HAL korrekt implementiert) als auch für die Sicherungsinstanz (um sicherzustellen, dass healthd weiterhin korrekt funktioniert, bevor sie entfernt wird) geschrieben.

Anforderungen an Akkuinformationen

Die Health 2.0-HAL enthält eine Reihe von Anforderungen an die HAL-Schnittstelle, die entsprechenden VTS-Tests sind jedoch relativ locker. In Android 11 werden neue VTS-Tests hinzugefügt, um die folgenden Anforderungen für Geräte mit Android 11 und höher durchzusetzen:

  • Die Einheiten für den momentanen und durchschnittlichen Akku-Strom müssen Mikroampere (μA) sein.
  • Das Vorzeichen des momentanen und durchschnittlichen Batteriestroms muss korrekt sein. Konkret:
    • current == 0, wenn der Akkustatus UNKNOWN ist
    • current > 0, wenn der Akkustatus CHARGING ist
    • current <= 0, wenn der Akkustatus NOT_CHARGING ist
    • Der Strom ist < 0, wenn der Akkustatus DISCHARGING ist.
    • Wird nicht erzwungen, wenn der Akkustand FULL ist
  • Der Akkustatus muss korrekt sein, je nachdem, ob eine Stromquelle angeschlossen ist oder nicht. Konkret:
    • Der Akkustatus muss CHARGING, NOT_CHARGING oder FULL sein, wenn und nur wenn eine Stromquelle angeschlossen ist.
    • Der Akkustatus muss DISCHARGING sein, wenn und nur wenn eine Stromquelle getrennt ist.

Wenn Sie libbatterymonitor in Ihrer Implementierung verwenden und Werte über Kernelschnittstellen weitergeben, müssen Sie dafür sorgen, dass die sysfs-Knoten korrekte Werte melden:

  • Achte darauf, dass der Batteriestrom mit dem richtigen Vorzeichen und den richtigen Einheiten angegeben wird. Dazu gehören die folgenden sysfs-Knoten:
    • /sys/class/power_supply/*/current_avg
    • /sys/class/power_supply/*/current_max
    • /sys/class/power_supply/*/current_now
    • Positive Werte geben an, dass Strom in die Batterie fließt.
    • Die Werte sollten in Mikroampere (μA) angegeben werden.
  • Die Akkuspannung muss in Mikrovolt (μV) angegeben werden. Dazu gehören die folgenden sysfs-Knoten:
    • /sys/class/power_supply/*/voltage_max
    • /sys/class/power_supply/*/voltage_now
    • Bei der Standard-HAL-Implementierung wird voltage_now durch 1000 geteilt und die Werte werden in Millivolt (mV) angegeben. Weitere Informationen finden Sie unter @1.0::HealthInfo.

Weitere Informationen finden Sie unter Linux power supply class.