Kanoniczny powód rozruchu

W systemie Android 9 wprowadzono następujące zmiany w specyfikacji przyczyny rozruchu programu ładującego.

Powody rozruchu

Program ładujący wykorzystuje unikalnie dostępne zasoby sprzętu i pamięci, aby określić, dlaczego urządzenie zostało ponownie uruchomione, a następnie przekazuje tę informację, dodając androidboot.bootreason=<reason> do wiersza poleceń jądra Androida w celu jego uruchomienia. init następnie tłumaczy ten wiersz poleceń, aby propagować go do właściwości Androida bootloader_boot_reason_prop ( ro.boot.bootreason ). W przypadku urządzeń uruchamianych z systemem Android 12 lub nowszym i korzystających z jądra w wersji 5.10 lub nowszej, do bootconfig zamiast wiersza poleceń jądra dodawany jest androidboot.bootreason=<reason> .

Specyfikacje powodu rozruchu

Poprzednie wersje Androida określały format przyczyny rozruchu, który nie zawierał spacji, był pisany małymi literami, zawierał kilka wymagań (takich jak raportowanie kernel_panic , watchdog , cold / warm / hard ) i uwzględniał inne unikalne powody. Ta luźna specyfikacja spowodowała rozprzestrzenienie się setek niestandardowych (i czasami bezsensownych) ciągów znaków powodujących rozruch, co z kolei doprowadziło do sytuacji, której nie można było zarządzać. Począwszy od bieżącej wersji Androida, sam pęd prawie niemożliwych do przeanalizowania lub bezsensownych treści przesyłanych przez program ładujący spowodował problemy ze zgodnością dla bootloader_boot_reason_prop .

Wraz z wydaniem Androida 9 zespół Androida zdaje sobie sprawę, że starsze bootloader_boot_reason_prop ma znaczny rozmach i nie można go ponownie zapisać w czasie wykonywania. Wszelkie ulepszenia specyfikacji powodu rozruchu muszą zatem wynikać z interakcji z twórcami programu ładującego i poprawek w istniejącym systemie. W tym celu zespół Androida to:

  • Współpraca z twórcami programów ładujących, aby zachęcić ich do:
    • Podaj kanoniczne, możliwe do przeanalizowania i rozpoznawalne powody bootloader_boot_reason_prop .
    • Weź udział w liście system/core/bootstat/bootstat.cpp kBootReasonMap .
  • Dodanie kontrolowanego źródła z możliwością wielokrotnego zapisu w czasie wykonywania system_boot_reason_prop ( sys.boot.reason ). Ograniczony zestaw aplikacji systemowych (takich jak bootstat i init ) może przepisać tę właściwość, ale wszystkim aplikacjom można przyznać uprawnienia sepolicy do jej odczytu.
  • Informowanie użytkowników o powodzie rozruchu, aby zaczekali do momentu zamontowania danych użytkownika, zanim zaufają zawartości właściwości powodu rozruchu systemu system_boot_reason_prop .

Dlaczego tak późno? Chociaż bootloader_boot_reason_prop jest dostępny na początku rozruchu, jest blokowany przez zasady bezpieczeństwa Androida w zależności od potrzeb, ponieważ reprezentuje niedokładne, niemożliwe do przeanalizowania i niekanoniczne informacje. W większości sytuacji dostęp do tych informacji powinni mieć jedynie programiści posiadający głęboką wiedzę na temat systemu rozruchowego. Udoskonalony, analizowalny i kanoniczny interfejs API do celów rozruchu za pośrednictwem system_boot_reason_prop można niezawodnie i dokładnie pobrać dopiero po zamontowaniu danych użytkownika. Konkretnie:

  • Zanim dane użytkownika zostaną zamontowane, system_boot_reason_prop będzie zawierać wartość z bootloader_boot_reason_prop .
  • Po zamontowaniu danych użytkownika system_boot_reason_prop może zostać zaktualizowany w celu zapewnienia zgodności lub raportowania dokładniejszych informacji.

Z tego powodu Android 9 wydłuża okres czasu, po którym można oficjalnie ustalić przyczynę rozruchu, zmieniając go z natychmiastowego dokładnego rozruchu (z bootloader_boot_reason_prop ) na dostępny dopiero po zamontowaniu danych użytkownika (z system_boot_reason_prop ).

Logika Bootstat zależy od bardziej informacyjnego i zgodnego bootloader_boot_reason_prop . Gdy ta właściwość używa przewidywalnego formatu, poprawia dokładność wszystkich kontrolowanych scenariuszy ponownego uruchamiania i zamykania, co z kolei udoskonala i rozszerza dokładność i znaczenie system_boot_reason_prop .

Kanoniczny format przyczyny rozruchu

Kanoniczny format przyczyny rozruchu dla bootloader_boot_reason_prop w systemie Android 9 wykorzystuje następującą składnię:

<reason>,<subreason>,<detail>…

Zasady formatowania:

  • Małe litery
  • Bez spacji (użyj podkreślenia)
  • Wszystkie znaki do wydrukowania
  • Oddzielona przecinkami reason , subreason i co najmniej jeden detail .
    • Wymagany reason , który reprezentuje powód o najwyższym priorytecie, dla którego urządzenie musiało zostać ponownie uruchomione lub wyłączone.
    • Opcjonalny subreason reprezentujący krótkie podsumowanie tego, dlaczego urządzenie musiało zostać ponownie uruchomione lub wyłączone (albo kto ponownie uruchomił lub zamknął urządzenie).
    • Co najmniej jedna opcjonalna wartość detail . detail może wskazywać na podsystem, co pomoże w ustaleniu, który konkretny system spowodował daną subreason . Można określić wiele wartości detail , które zazwyczaj powinny być zgodne z hierarchią ważności. Jednakże dopuszczalne jest również zgłaszanie wielu wartości detail o jednakowym znaczeniu.

Pusta wartość bootloader_boot_reason_prop jest uważana za nielegalną (ponieważ pozwala to innym agentom na podanie przyczyny rozruchu po fakcie).

Powód wymagań

Wartość podana jako reason (pierwszy zakres, przed zakończeniem lub przecinkiem) musi należeć do następującego zestawu podzielonego na przyczyny jądra, mocne i tępe:

  • zestaw jądra:
    • watchdog"
    • "kernel_panic"
  • mocny zestaw:
    • "recovery"
    • "bootloader"
  • tępy zestaw:
    • "cold" . Ogólnie oznacza pełny reset wszystkich urządzeń, łącznie z pamięcią.
    • "hard" . Ogólnie wskazuje, że stan sprzętu został zresetowany, a ramoops powinny zachować trwałą zawartość.
    • "warm" . Ogólnie wskazuje, że pamięć i urządzenia zachowują pewien stan, a magazyn zapasowy ramoops (patrz sterownik pstore w jądrze) zawiera trwałą zawartość.
    • "shutdown"
    • "reboot" . Ogólnie oznacza, że ​​stan ramoops jest nieznany i stan sprzętu jest nieznany. Ta wartość jest chwytliwa, ponieważ wartości cold , hard i warm dostarczają wskazówek co do głębokości resetowania urządzenia.

Programy ładujące muszą podać zestaw jądra lub bezpośredni reason i zdecydowanie zaleca się podanie subreason , jeśli można go ustalić. Na przykład długie naciśnięcie klawisza zasilania, które może mieć kopię zapasową ramoops lub nie, spowoduje uruchomienie jako "reboot,longkey" .

Żaden reason pierwszego zakresu nie może być częścią żadnego powodu subreason ani detail . Jednakże, ponieważ przestrzeń użytkownika nie może określić przyczyn ustawienia jądra, "watchdog" może zostać ponownie użyty po tępym ustawionym powodzie, wraz ze szczegółami źródła (np. "reboot,watchdog,service_manager_unresponsive" lub "reboot,software,watchdog" ).

Przyczyny rozruchu nie powinny wymagać wewnętrznej wiedzy eksperckiej do rozszyfrowania i/lub powinny być czytelne dla człowieka za pomocą intuicyjnego raportu. Przykłady: "shutdown,vbxd" (złe), "shutdown,uv" (lepsze), "shutdown,undervoltage" (preferowane).

Kombinacje przyczyny i podpowodu

Android zastrzega sobie zestaw kombinacji reason i subreason , które nie powinny być przeciążane podczas normalnego użytkowania, ale można ich używać w indywidualnych przypadkach, jeśli kombinacja dokładnie odzwierciedla powiązany stan. Przykłady zarezerwowanych kombinacji obejmują:

  • "reboot,userrequested"
  • "shutdown,userrequested"
  • "shutdown,thermal" (z thermald )
  • "shutdown,battery"
  • "shutdown,battery,thermal" (z BatteryStatsService )
  • "reboot,adb"
  • "reboot,shell"
  • "reboot,bootloader"
  • "reboot,recovery"

Aby uzyskać więcej informacji, zobacz kBootReasonMap w system/core/bootstat/bootstat.cpp i powiązaną historię dziennika zmian git w repozytorium źródłowym Androida.

Zgłaszanie przyczyn rozruchu

Wszystkie przyczyny rozruchu, czy to z programu ładującego, czy zapisane w kanonicznym powodzie rozruchu, muszą zostać zapisane w sekcji kBootReasonMap pliku system/core/bootstat/bootstat.cpp . Lista kBootReasonMap jest mieszanką powodów zgodnych i starszych, niezgodnych. Programiści programu ładującego powinni rejestrować tutaj tylko nowe przyczyny zgodne (i nie powinni rejestrować powodów niezgodnych, chyba że produkt został już wysłany i nie można go zmienić).

Zdecydowanie zalecamy użycie istniejących, zgodnych wpisów w system/core/bootstat/bootstat.cpp i zachowanie powściągliwości przed użyciem niezgodnego ciągu. Jako wytyczną jest to:

  • OK , aby zgłosić "kernel_panic" z bootloadera, ponieważ bootstat może być w stanie sprawdzić ramoops pod kątem kernel_panic signatures , aby udoskonalić przyczyny podrzędne w kanoniczny system_boot_reason_prop .
  • Niewłaściwe jest zgłaszanie niezgodnego ciągu znaków w kBootReasonMap (takiego jak "panic") z programu ładującego, ponieważ ostatecznie uniemożliwi to doprecyzowanie reason .

Na przykład, jeśli kBootReasonMap zawiera "wdog_bark" , programista bootloadera powinien:

  • Zmień na "watchdog,bark" i dodaj do listy w kBootReasonMap .
  • Zastanów się, co "bark" oznacza dla osób niezaznajomionych z technologią i ustal, czy dostępny jest bardziej znaczący subreason .

Sprawdzanie zgodności przyczyny rozruchu

W tej chwili system Android nie zapewnia aktywnego testu CTS, który mógłby dokładnie uruchomić lub sprawdzić wszystkie możliwe przyczyny rozruchu, jakie może zapewnić program ładujący; partnerzy mogą nadal próbować przeprowadzić test pasywny w celu ustalenia zgodności.

W rezultacie zgodność programu ładującego wymaga od jego twórców dobrowolnego przestrzegania zasad i wytycznych opisanych powyżej. Wzywamy takich programistów do wnoszenia wkładu w AOSP (w szczególności do system/core/bootstat/bootstat.cpp ) i wykorzystywania tej okazji jako forum do dyskusji na temat przyczyn uruchamiania.