Kanoniczna przyczyna uruchamiania

Android 9 zawiera te zmiany specyfikacji powodu uruchamiania bootloadera:

Powody uruchamiania

Bootloader używa unikalnych zasobów sprzętowych i pamięciowych, aby określić, dlaczego urządzenie zostało ponownie uruchomione, a potem przekazuje tę informację, dodając androidboot.bootreason=<reason> do wiersza poleceń jądra Androida. init przekształca następnie tę linię poleceń w celu propagowania jej do właściwości Androida bootloader_boot_reason_prop (ro.boot.bootreason). W przypadku urządzeń uruchamianych z Androidem 12 lub nowszym, które używają jądra w wersji 5.10 lub nowszej, do bootconfiga zamiast linii poleceń jądra dodawany jest parametr androidboot.bootreason=<reason>.

Specyfikacje przyczyny uruchomienia

W poprzednich wersjach Androida format powodu rozruchu nie zawierał spacji, był w pełni w małej literze, miał niewiele wymagań (np. dotyczących raportowania kernel_panic, watchdog, cold/warm/hard) i umożliwiał inne unikalne powody. Ta luźna specyfikacja spowodowała rozpowszechnienie setek niestandardowych (a czasem bezsensownych) ciągów znaków powodu rozruchu, co z kolei doprowadziło do niekontrolowanej sytuacji. W ramach obecnej wersji Androida ilość treści, które są prawie nie do zinterpretowania lub bez znaczenia, przesłanych przez program rozruchowy, spowodowała problemy z zgodnoscią z zasadami w przypadku bootloader_boot_reason_prop.

W ramach Androida 9 zespół Androida zdaje sobie sprawę, że starsza wersja bootloader_boot_reason_prop ma znaczną dynamikę i nie można jej ponownie napisać w czasie wykonywania. Wszelkie ulepszenia specyfikacji przyczyny rozruchu muszą więc pochodzić od programistów bootloadera i polegać na interakcji z dotychczasowym systemem. W związku z tym zespół Androida:

  • Współpraca z deweloperami programów rozruchowych w celu zachęcenia ich do:
    • Podaj kanoniczne, możliwe do zanalizowania i rozpoznawania przyczyny, które uzasadniają: bootloader_boot_reason_prop.
    • uczestniczyć w programie system/core/bootstat/bootstat.cpp kBootReasonMap.
  • Dodanie kontrolowanego źródła danych system_boot_reason_prop (sys.boot.reason), które można zapisywać na etapie wykonywania. Ten obiekt może być zastępowany przez ograniczony zestaw aplikacji systemowych (takich jak bootstatinit), ale wszystkie aplikacje mogą mieć uprawnienia do jego odczytu.
  • Informowanie użytkowników o powodzie rozruchu i proszeniu ich o poczekanie, aż dane użytkownika zostaną zamontowane, zanim zaufają treści w 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 zabezpieczeń Androida w miarę potrzeby, ponieważ zawiera nieprawidłowe, nierozpoznawalne i niekanoniczne informacje. W większości przypadków dostęp do tych informacji powinni mieć tylko deweloperzy, którzy mają dogłębną wiedzę na temat systemu uruchamiania. Ulepszony, możliwy do zanalizowania i kanoniczny interfejs API dla powodu rozruchu z system_boot_reason_prop może być wiarygodnie i precyzyjnie pobierany tylko po zamontowaniu danych użytkownika. Więcej szczegółów:

  • Zanim userdata zostanie zamontowane, system_boot_reason_prop będzie zawierać wartość z bootloader_boot_reason_prop.
  • Po zamontowaniu userdata system_boot_reason_prop może zostać zaktualizowany, aby był zgodny z wymaganiami lub aby przekazywał dokładniejsze informacje.

Z tego powodu Android 9 wydłuża okres, w którym można oficjalnie uzyskać przyczynę rozruchu, zmieniając ją z natychmiastowej dokładności podczas rozruchu (z bootloader_boot_reason_prop) na dostępną dopiero po zamontowaniu danych użytkownika (z system_boot_reason_prop).

Logika bootstat zależy od bardziej przydatnych i zgodny z przepisami bootloader_boot_reason_prop. Jeśli usługa korzysta z przewidywalnego formatu, zwiększa się dokładność wszystkich scenariuszy kontrolowanego ponownego uruchamiania i wyłączania, co z kolei pozwala zwiększyć dokładność i znaczenie system_boot_reason_prop.

Kanoniczny format przyczyny uruchamiania

Kanoniczny format powodu uruchamiania dla bootloader_boot_reason_prop w Androidzie 9 używa tej składni:

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

Reguły formatowania:

  • Małe litery
  • Brak pustych miejsc (użyj podkreślenia)
  • wszystkie znaki drukowalne.
  • reason, subreason i co najmniej 1 występ detail rozdzielone przecinkami.
    • Wymagane reason, które reprezentuje najwyższy priorytet powód, dla którego urządzenie musiało się ponownie uruchomić lub wyłączyć.
    • Opcjonalny element subreason, który zawiera krótkie podsumowanie tego, dlaczego urządzenie musiało zostać ponownie uruchomione lub wyłączone (lub kto je uruchomił lub wyłączył).
    • Co najmniej 1 opcjonalna wartość detail. detailmoże wskazywać podsystem, aby ułatwić określenie, który konkretny system spowodował subreason. Możesz określić wiele wartości detail, które powinny być uporządkowane według hierarchii ważności. Dopuszczalne jest też raportowanie wielu wartości detail o równym znaczeniu.

Pustą wartość atrybutu bootloader_boot_reason_prop uznaje się za nielegalną (ponieważ pozwala innym procesom wstrzyknąć przyczynę rozruchu w dowolnym momencie).

Wymagania dotyczące uzasadnienia

Wartość podana dla reason (pierwszy element zakresu, przed przecinkiem) musi należeć do jednego z tych zbiorów podzielonych na przyczyny podstawowe, silne i ostre:

  • kernel set:
    • watchdog"
    • "kernel_panic"
  • strong set:
    • "recovery"
    • "bootloader"
  • zestaw do palenia:
    • "cold". Zazwyczaj oznacza pełny reset wszystkich urządzeń, w tym pamięci.
    • "hard". Ogólnie oznacza to, że sprzęt został zresetowany i ramoops powinien zachować trwałe treści.
    • "warm". Ogólnie oznacza to, że pamięć i urządzenia zachowują pewien stan, a pamięć podręczna ramoops (patrz sterownik pstore w rdzeniu) zawiera trwałe dane.
    • "shutdown"
    • "reboot". Oznacza to, że stan ramoops jest nieznany, a stan sprzętu jest nieznany. Ta wartość jest zbiorcza, ponieważ wartości cold, hardwarm wskazują na głębokość resetu urządzenia.

Bootloadery muszą zawierać zestaw jądra lub zestaw Blunt reason. Zalecamy również podanie subreason, jeśli jest to możliwe. Na przykład przytrzymanie przycisku zasilania z ramoops kopią zapasową lub bez niej będzie miało powód rozruchu"reboot,longkey".

Żaden element pierwszego zakresu reason nie może być częścią żadnego elementu subreason ani detail. Jednak ponieważ przyczyny zestawów jądra nie mogą być generowane przez przestrzeń użytkownika, "watchdog" może być używany ponownie po użyciu prostej przyczyny zestawu wraz ze szczegółami źródła (na przykład "reboot,watchdog,service_manager_unresponsive" lub "reboot,software,watchdog").

Powody uruchamiania nie powinny wymagać znajomości wewnętrznych informacji, aby je zrozumieć, lub powinny być czytelne dla człowieka w ramach intuicyjnego raportu. Przykłady: "shutdown,vbxd" (nieprawidłowe), "shutdown,uv" (lepsze), "shutdown,undervoltage" (preferowane).

Kombinacje przyczyny i podprzyczyny

Android rezerwuje zestaw kombinacji reason-subreason, które nie powinny być przeciążone w ramach normalnego użytkowania, ale mogą być używane w każdym przypadku, jeśli kombinacja dokładnie odzwierciedla powiązane warunki. Przykłady zarezerwowanych kombinacji:

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

Więcej informacji znajdziesz w kBootReasonMapsystem/core/bootstat/bootstat.cpp oraz w powiązanej historii zmian w gałęzi git w repozytorium kodu źródłowego Androida.

Zgłaszanie przyczyn uruchamiania

Wszystkie przyczyny rozruchu, zarówno z bootloadera, jak i zapisane w kanonicznych przyczynach rozruchu, muszą być zarejestrowane w sekcji kBootReasonMap w pliku system/core/bootstat/bootstat.cpp. Lista kBootReasonMap zawiera zarówno zgodne, jak i starsze przyczyny niezgodności. Deweloperzy programów ładujących powinni rejestrować tylko nowe zgodne powody (nie powinni rejestrować niezgodnych powodów, chyba że produkt został już wysłany i nie można go zmienić).

Zdecydowanie zalecamy korzystanie z dotychczasowych zgodnych wpisów w system/core/bootstat/bootstat.cpp i zachowanie ostrożności przed użyciem niespełniającego wymogów ciągu znaków. Oto kilka wskazówek:

  • OK, aby zgłosić "kernel_panic" z bootloadera, ponieważ bootstat może sprawdzić ramoops pod kątem kernel_panic signatures, aby doprecyzować przyczyny podrzędne w kanonicznym system_boot_reason_prop.
  • Nie jest to dopuszczalne, aby zgłosić niespełniający wymogów ciąg znaków w kBootReasonMap (np. "panic") z bootloadera), ponieważ spowoduje to utratę możliwości doprecyzowania reason.

Jeśli na przykład kBootReasonMap zawiera "wdog_bark", deweloper programu rozruchowego powinien:

  • Zmień na "watchdog,bark" i dodaj do listy w kBootReasonMap.
  • Zastanów się, co oznacza "bark" dla osób, które nie znają tej technologii, i sprawdź, czy dostępna jest bardziej odpowiednia subreason.

Sprawdzanie zgodności z przyczyną uruchomienia

Obecnie Android nie udostępnia aktywnego testu CTS, który mógłby dokładnie wywołać lub sprawdzić wszystkie możliwe powody uruchamiania przez bootloader. Partnerzy mogą jednak spróbować przeprowadzić test pasywny, aby określić zgodność.

Dlatego zgodność z tymi zasadami wymaga od deweloperów bootloaderów dobrowolnego przestrzegania zasad i wytycznych opisanych powyżej. Zachęcamy takich deweloperów do tworzenia w ramach AOSP (szczególnie w ramach system/core/bootstat/bootstat.cpp) i korzystanie z tej okazji jako forum do dyskusji na temat przyczyn uruchamiania.