Wdrożenie Health 2.1

W Androidzie 11 cały healthd kod jest refaktoryzowany do libhealthlooplibhealth2impl, a następnie modyfikowany w celu wdrożenia interfejsu HAL health@2.1. Te 2 biblioteki są połączone statycznie przez health@2.0-impl-2.1, czyli implementację Health 2.1 typu passthrough. Biblioteki połączone statycznie umożliwiają health@2.0-impl-2.1 wykonywanie tych samych zadań co healthd, np. uruchamianie healthd_mainloop i przeprowadzanie ankiet. W funkcji init health@2.1-service rejestruje implementację interfejsu IHealthhwservicemanager. Podczas uaktualniania urządzeń z obrazem dostawcy w Androidzie 8.x lub 9 i platformą Androida 11 obraz dostawcy może nie udostępniać usługi health@2.1. Wsteczna kompatybilność ze starymi obrazami dostawców jest wymuszana przez harmonogram wycofywania.

Aby zapewnić zgodność wsteczną:

  1. healthd rejestruje IHealthhwservicemanager, mimo że jest demonem systemowym. IHealth jest dodawany do manifestu systemu z nazwą instancji „backup”.
  2. Platforma i storaged komunikują się z healthd za pomocą hwbinder zamiast binder.
  3. Kod platformy i storaged został zmieniony tak, aby pobierać instancję „default”, jeśli jest dostępna, a następnie „backup”.
    • Kod klienta C++ korzysta z logiki zdefiniowanej w libhealthhalutils.
    • Kod klienta Java korzysta z logiki zdefiniowanej w pliku HealthServiceWrapper.
  4. Gdy iHealth/default będzie powszechnie dostępny, a obrazy dostawcy Androida 8.1 zostaną wycofane, można wycofać iHealth/backup i healthd.

Zmienne kompilacji specyficzne dla płyty w przypadku usługi healthd

BOARD_PERIODIC_CHORES_INTERVAL_* to zmienne specyficzne dla tablicy, które służą do tworzeniahealthd. W ramach podziału na kompilację systemu i kompilację dostawcy nie można definiować wartości specyficznych dla płyty w przypadku modułów systemowych. Te wartości były wcześniej zastępowane w wycofanej funkcji healthd_board_init.

W health@2.1 dostawcy mogą zastąpić te dwie wartości interwałów okresowych zadań w strukturze healthd_config przed przekazaniem ich do konstruktora klasy implementacji usługi health. Klasa implementacji stanu powinna dziedziczyć z klasy android::hardware::health::V2_1::implementation::Health.

Wdrażanie usługi Health 2.1

Informacje o wdrażaniu usługi Health 2.1 znajdziesz w pliku hardware/interfaces/health/2.1/README.md.

Klienci z branży opieki zdrowotnej

health@2.x ma tych klientów:

  • ładowarkę. Kod libbatterymonitorhealthd_common jest umieszczony w health@2.0-impl.
  • odzyskiwania. Połączenie z libbatterymonitor jest zawarte w health@2.0-impl. Wszystkie wywołania funkcji BatteryMonitor są zastępowane wywołaniami klasy implementacji Health.
  • BatteryManager BatteryManager.queryProperty(int id) był jedynym klientem IBatteryPropertiesRegistrar.getProperty. IBatteryPropertiesRegistrar.getProperty został dostarczony przez healthd i odczytany bezpośrednio przez /sys/class/power_supply.

    Ze względów bezpieczeństwa aplikacje nie mogą bezpośrednio wywoływać interfejsu HAL usługi zdrowotnej. W Androidzie 9 i nowszym usługa IBatteryPropertiesRegistrar jest dostarczana przez BatteryService zamiast przez healthd. BatteryService przekazuje połączenie do warstwy HAL usługi zdrowia, aby pobrać żądane informacje.

  • BatteryService. W Androidzie 9 i nowszych BatteryService używa HealthServiceWrapper, aby określić, czy użyć domyślnej instancji usługi zdrowotnej z vendor, czy zapasowej instancji usługi zdrowotnej z healthd. BatteryService nasłuchuje zdarzeń związanych ze zdrowiem za pomocą IHealth.registerCallback.

  • Storaged W Androidzie 9 i nowszych storaged używa libhealthhalutils, aby określić, czy użyć domyślnej instancji usługi zdrowotnej z vendor, czy zapasowej instancji usługi zdrowotnej z healthd. storaged, a następnie nasłuchuje zdarzeń związanych ze stanem urządzenia za pomocą IHealth.registerCallback i pobiera informacje o pamięci.

Zmiany w SELinux

Warstwa HAL health@2.1 zawiera w platformie te zmiany w SELinux:

  • Dodaje android.hardware.health@2.1-service do file_contexts.

W przypadku urządzeń z własną implementacją mogą być konieczne pewne zmiany w SELinuxie dostawcy. Przykład:

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

Interfejsy jądra

Demon healthd i domyślna implementacjaandroid.hardware.health@2.0-impl-2.1 korzystają z tych interfejsów jądra, aby pobierać informacje o baterii:

  • /sys/class/power_supply/*/capacity_level (dodano w 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 (dodano w 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 (dodano w Health 2.1)
  • /sys/class/power_supply/*/type
  • /sys/class/power_supply/*/voltage_max
  • /sys/class/power_supply/*/voltage_now

Każda implementacja HAL zdrowia specyficzna dla urządzenia, która korzysta z libbatterymonitor, domyślnie uzyskuje dostęp do tych interfejsów jądra, chyba że zostanie to zastąpione w konstruktorze klasy implementacji zdrowia.

Jeśli tych plików brakuje lub są one niedostępne z healthd lub z domyślnej usługi (np. plik jest symlinkiem do folderu specyficznego dla dostawcy, który odmawia dostępu z powodu nieprawidłowo skonfigurowanych zasad SELinux), mogą one nie działać prawidłowo. Dlatego nawet w przypadku korzystania z domyślnej implementacji mogą być konieczne dodatkowe zmiany SELinux specyficzne dla dostawcy.

Niektóre interfejsy jądra używane w Health 2.1, takie jak /sys/class/power_supply/*/capacity_level i /sys/class/power_supply/*/time_to_full_now, mogą być opcjonalne. Aby jednak zapobiec nieprawidłowemu działaniu platformy wynikającemu z braku interfejsów jądra, przed utworzeniem usługi Health HAL 2.1 zalecamy wybranie CL 1398913.

Testowanie

Android 11 zawiera nowe testy VTS napisane specjalnie dla interfejsu HAL health@2.1. Jeśli urządzenie deklaruje w manifeście urządzenia interfejs HAL health@2.1, musi przejść odpowiednie testy VTS. Testy są pisane zarówno dla instancji domyślnej (aby upewnić się, że urządzenie prawidłowo implementuje HAL), jak i dla instancji zapasowej (aby upewnić się, że healthd nadal działa prawidłowo przed usunięciem).

Wymagania dotyczące informacji o baterii

Specyfikacja HAL w Health 2.0 określa zestaw wymagań dotyczących interfejsu HAL, ale odpowiednie testy VTS są stosunkowo łagodne w zakresie ich egzekwowania. W Androidzie 11 dodano nowe testy VTS, aby wymusić na urządzeniach z Androidem 11 i nowszym spełnienie tych wymagań:

  • Jednostką natychmiastowego i średniego prądu baterii muszą być mikroampery (μA).
  • Znak natężenia prądu chwilowego i średniego musi być prawidłowy. W szczególności:
    • current == 0, gdy stan baterii to UNKNOWN
    • current > 0, gdy stan baterii to CHARGING
    • current <= 0, gdy stan baterii to NOT_CHARGING
    • current < 0, gdy stan baterii to DISCHARGING
    • Niewymuszane, gdy stan baterii to FULL
  • Stan baterii musi być prawidłowy w zależności od tego, czy źródło zasilania jest podłączone. W szczególności:
    • stan baterii musi być jednym z tych stanów: CHARGING, NOT_CHARGING lub FULL, jeśli i tylko wtedy, gdy podłączone jest źródło zasilania;
    • stan baterii musi być DISCHARGING tylko wtedy, gdy źródło zasilania jest odłączone.

Jeśli w implementacji używasz libbatterymonitor i przekazujesz wartości z interfejsów jądra, sprawdź, czy węzły sysfs raportują prawidłowe wartości:

  • Sprawdź, czy prąd baterii jest podawany z prawidłowym znakiem i w odpowiednich jednostkach. Obejmuje to te węzły sysfs:
    • /sys/class/power_supply/*/current_avg
    • /sys/class/power_supply/*/current_max
    • /sys/class/power_supply/*/current_now
    • Wartości dodatnie wskazują prąd wpływający do baterii.
    • Wartości powinny być podane w mikroamperach (μA).
  • Upewnij się, że napięcie baterii jest podawane w mikrowoltach (μV). Obejmuje to te węzły sysfs:
    • /sys/class/power_supply/*/voltage_max
    • /sys/class/power_supply/*/voltage_now
    • Pamiętaj, że domyślna implementacja HAL dzieli voltage_now przez 1000 i zgłasza wartości w miliwoltach (mV). Zobacz @1.0::HealthInfo.

Więcej informacji znajdziesz w artykule Klasa zasilacza w systemie Linux.