Producenci OEM i producenci układów SoC, którzy chcą wdrażać aktualizacje systemu A/B, muszą zadbać o to, aby ich bootloader implementował interfejs HAL boot_control i przekazywał prawidłowe parametry do jądra.
Zaimplementuj interfejs HAL sterowania rozruchem
Bootloadery obsługujące A/B muszą implementować interfejs boot_control
HAL w ramach hardware/libhardware/include/hardware/boot_control.h
. Implementacje możesz testować za pomocą narzędzia system/extras/bootctl
i system/extras/tests/bootloader/
.
Musisz też zaimplementować maszynę stanów przedstawioną poniżej:

Konfigurowanie jądra
Aby wdrożyć aktualizacje systemu A/B:
-
Wybierz z nich te serie poprawek do jądra (w razie potrzeby):
- Jeśli uruchamiasz bez ramdiska i używasz opcji „Uruchom jako odzyskiwanie”, wybierz android-review.googlesource.com/#/c/158491/.
- Aby skonfigurować dm-verity bez ramdiska, wybierz android-review.googlesource.com/#/q/status:merged+project:kernel/common+branch:android-3.18+topic:A_B_Changes_3.18.
-
Upewnij się, że argumenty wiersza poleceń jądra zawierają te dodatkowe argumenty:
gdzie wartośćskip_initramfs rootwait ro init=/init root="/dev/dm-0 dm=system none ro,0 1 android-verity <public-key-id> <path-to-system-partition>"
<public-key-id>
to identyfikator klucza publicznego użytego do zweryfikowania podpisu tabeli verity (szczegóły znajdziesz w artykule dm-verity). -
Dodaj certyfikat .X509 zawierający klucz publiczny do pęku kluczy systemowego:
-
Skopiuj certyfikat X509 sformatowany w formacie
.der
do katalogukernel
. Jeśli certyfikat X509 ma format pliku.pem
, użyj poleceniaopenssl
, aby przekonwertować format.pem
na.der
:openssl x509 -in <x509-pem-certificate> -outform der -out <x509-der-certificate>
-
Utwórz
zImage
, aby uwzględnić certyfikat w ramach pęku kluczy systemu. Aby to sprawdzić,sprawdź wpisprocfs
(wymaga włączenia opcjiKEYS_CONFIG_DEBUG_PROC_KEYS
): Udane uwzględnienie certyfikatu X .509 wskazuje obecność klucza publicznego w pęku kluczy systemu (zaznaczone na żółto pole to identyfikator klucza publicznego).angler:/# cat /proc/keys 1c8a217e I------ 1 perm 1f010000 0 0 asymmetri Android: 7e4333f9bba00adfe0ede979e28ed1920492b40f: X509.RSA 0492b40f [] 2d454e3e I------ 1 perm 1f030000 0 0 keyring .system_keyring: 1/4
-
Zastąp spację znakiem
#
i przekaż jako<public-key-id>
w wierszu poleceń jądra. Na przykład zamiast<public-key-id>
możesz podaćAndroid:#7e4333f9bba00adfe0ede979e28ed1920492b40f
.
-
Skopiuj certyfikat X509 sformatowany w formacie
Ustawianie zmiennych kompilacji
Bootloadery obsługujące A/B muszą spełniać te kryteria zmiennych kompilacji:
Musisz określić docelową grupę w ramach testu A/B. |
/device/google/marlin/+/android-7.1.0_r1/device-common.mk Opcjonalnie możesz wykonać po instalacji (ale przed ponownym uruchomieniem) krok dex2oat opisany w sekcji Kompilowanie.
|
---|---|
Zdecydowanie zalecane w przypadku testu A/B |
|
Nie można zdefiniować celu testu A/B |
|
Opcjonalne w przypadku wersji debugowania | PRODUCT_PACKAGES_DEBUG += update_engine_client |
Ustaw partycje (gniazda)
Urządzenia A/B nie potrzebują partycji odzyskiwania ani partycji pamięci podręcznej, ponieważ Android nie używa już tych partycji. Partycja danych jest teraz używana do pobranego pakietu OTA, a kod obrazu odzyskiwania jest na partycji rozruchowej. Wszystkie partycje, które są testowane metodą A/B, powinny mieć nazwy podane poniżej (sloty mają zawsze nazwy a
, b
itd.): boot_a
,
boot_b
, system_a
, system_b
, vendor_a
,
vendor_b
.
Pamięć podręczna
W przypadku aktualizacji innych niż A/B partycja pamięci podręcznej była używana do przechowywania pobranych pakietów OTA oraz do tymczasowego przechowywania bloków podczas stosowania aktualizacji. Nigdy nie było dobrego sposobu na określenie rozmiaru partycji pamięci podręcznej: jej wielkość zależała od tego, jakie aktualizacje chcesz wprowadzić. Najgorszym przypadkiem jest partycja pamięci podręcznej o rozmiarze równym obrazowi systemu. W przypadku aktualizacji A/B nie trzeba ukrywać bloków (ponieważ zawsze zapisujesz na partycji, która nie jest obecnie używana), a w przypadku strumieniowego przesyłania aktualizacji A/B nie trzeba pobierać całego pakietu OTA przed jego zastosowaniem.
Odzyskiwanie
Dysk RAM do przywracania jest teraz zawarty w pliku boot.img
. Podczas przechodzenia do trybu odzyskiwania bootloader nie może umieścić opcji skip_initramfs
w wierszu poleceń jądra.
W przypadku aktualizacji innych niż A/B partycja odzyskiwania zawiera kod używany do stosowania aktualizacji. Aktualizacje A/B są stosowane przez update_engine
działający w ramach zwykłego obrazu systemu.
Nadal istnieje tryb odzyskiwania, który służy do przywracania danych do ustawień fabrycznych i instalowania pakietów aktualizacji (stąd nazwa „recovery”). Kod i dane trybu odzyskiwania są przechowywane na zwykłym dysku rozruchowym w ramdisku. Aby uruchomić obraz systemu, program rozruchowy informuje jądro, aby pominęło ramdisk (w przeciwnym razie urządzenie uruchomi się w trybie odzyskiwania). Tryb odzyskiwania zajmuje niewiele miejsca (a duża część była już na partycji rozruchowej), więc rozmiar partycji rozruchowej nie zwiększy się.
Fstab
Argument slotselect
musi znajdować się na linii dotyczącej partycji A/B. Przykład:
<path-to-block-device>/vendor /vendor ext4 ro wait,verify=<path-to-block-device>/metadata,slotselect
Żadna partycja nie może mieć nazwy vendor
. Zamiast tego partycja vendor_a
lub vendor_b
zostanie wybrana i zamontowana w punkcie montażowym /vendor
.
Argumenty przedziału jądra
Obecny przyrostek slotu powinien być przekazywany przez konkretny węzeł drzewa urządzenia (DT) (/firmware/android/slot_suffix
) lub przez wiersz poleceń jądra (androidboot.slot_suffix
) lub argument bootconfig.
Domyślnie fastboot flashuje bieżący slot na urządzeniu A/B. Jeśli pakiet aktualizacji zawiera również obrazy dla innego, nieaktualnego slotu, fastboot flashuje również te obrazy. Dostępne opcje:
-
--slot SLOT
. Zastąpić domyślne zachowanie i poprosić fastboot o przeflashowanie slotu przekazanego jako argument. -
--set-active [SLOT]
. Ustaw slot jako aktywny. Jeśli nie zostanie podany żaden argument opcjonalny, bieżący slot zostanie ustawiony jako aktywny. fastboot --help
. Uzyskaj informacje o poleceniach.
Jeśli bootloader obsługuje fastboot, powinien obsługiwać polecenie
set_active <slot>
, które ustawia bieżący aktywny slot na dany slot (musi też usunąć flagę unbootable dla tego slotu i zresetować liczbę prób do wartości domyślnych). Program rozruchowy powinien też obsługiwać te zmienne:
-
has-slot:<partition-base-name-without-suffix>
. Zwraca „yes” (tak), jeśli dana partycja obsługuje sloty, w przeciwnym razie zwraca „no” (nie). current-slot
. Zwraca sufiks przedziału, z którego zostanie uruchomiony następny system.-
slot-count
. Zwraca liczbę całkowitą odpowiadającą liczbie dostępnych miejsc. Obecnie obsługiwane są 2 miejsca, więc ta wartość wynosi2
. -
slot-successful:<slot-suffix>
. Zwraca wartość „yes” (tak), jeśli dany slot został oznaczony jako uruchomiony, w przeciwnym razie zwraca „no” (nie). -
slot-unbootable:<slot-suffix>
. Zwraca „yes” (tak), jeśli dany slot jest oznaczony jako nieuruchamialny, w przeciwnym razie zwraca „no” (nie). -
slot-retry-count:<slot-suffix>
. Liczba pozostałych prób uruchomienia danego gniazda.
Aby wyświetlić wszystkie zmienne, uruchom poleceniefastboot getvar all
.
Generowanie pakietów OTA
Narzędzia do pakietów OTA działają na tych samych zasadach co polecenia dotyczące innych urządzeń niż A/B. Plik target_files.zip
musi być wygenerowany przez definiowanie zmiennych kompilacji dla celu A/B. Narzędzia do pakietów OTA automatycznie identyfikują i generują pakiety w formacie dla aktualizatora A/B.
Przykłady:
-
Aby wygenerować pełny OTA:
./build/make/tools/releasetools/ota_from_target_files \ dist_output/tardis-target_files.zip \ ota_update.zip
-
Aby wygenerować przyrostową OTA:
./build/make/tools/releasetools/ota_from_target_files \ -i PREVIOUS-tardis-target_files.zip \ dist_output/tardis-target_files.zip \ incremental_ota_update.zip
Konfigurowanie partycji
update_engine
może zaktualizować dowolną parę partycji A/B zdefiniowaną na tym samym dysku.
Para partycji ma wspólny prefiks (np. system
lub boot
) oraz sufiks na potrzeby poszczególnych slotów (np. _a
). Lista partycji, dla których generator payload definiuje aktualizację, jest konfigurowana za pomocą zmiennej AB_OTA_PARTITIONS
make.
Jeśli na przykład uwzględnisz parę partycji bootloader_a
i booloader_b
(_a
i _b
to sufiksy slotu), możesz zaktualizować te partycje, określając w konfiguracji produktu lub płytki:
AB_OTA_PARTITIONS := \ boot \ system \ bootloader
Wszystkie partycje aktualizowane przez update_engine
nie mogą być modyfikowane przez pozostałą część systemu. Podczas aktualizacji cząstkowych lub delta dane binarne z bieżącego slotu są wykorzystywane do generowania danych w nowym slocie. Wszelkie zmiany mogą spowodować, że dane nowego slotu nie przejdą weryfikacji podczas procesu aktualizacji, przez co aktualizacja się nie powiedzie.
Konfigurowanie po instalacji
Możesz skonfigurować krok po instalacji inaczej w przypadku każdej zaktualizowanej partycji, używając zestawu par klucz-wartość. Aby uruchomić program znajdujący się w pliku /system/usr/bin/postinst
na nowej partycji, określ ścieżkę względną do katalogu głównego systemu plików na partycji systemowej.
Na przykład usr/bin/postinst
to system/usr/bin/postinst
(jeśli nie używasz dysku RAM). Dodatkowo określ typ systemu plików, który ma zostać przekazany do wywołania systemu mount(2)
. Dodaj do plików .mk
(jeśli są dostępne) te informacje o produkcie lub urządzeniu:
AB_OTA_POSTINSTALL_CONFIG += \ RUN_POSTINSTALL_system=true \ POSTINSTALL_PATH_system=usr/bin/postinst \ FILESYSTEM_TYPE_system=ext4
Kompilowanie aplikacji
Aplikacje mogą być kompilowane w tle przed ponownym uruchomieniem z nową wersją obrazu systemu. Aby kompilować aplikacje w tle, dodaj do konfiguracji urządzenia produktu (w pliku product.mk) następujące informacje:
-
Uwzględnij w kompilacji komponenty natywne, aby mieć pewność, że skrypt kompilacji i pliki binarne zostaną skompilowane i zawarowane w obrazie systemu.
# A/B OTA dexopt package PRODUCT_PACKAGES += otapreopt_script
-
Połącz skrypt kompilacji z parametrem
update_engine
, aby uruchamiał się jako krok po instalacji.# A/B OTA dexopt update_engine hookup AB_OTA_POSTINSTALL_CONFIG += \ RUN_POSTINSTALL_system=true \ POSTINSTALL_PATH_system=system/bin/otapreopt_script \ FILESYSTEM_TYPE_system=ext4 \ POSTINSTALL_OPTIONAL_system=true
Aby dowiedzieć się, jak zainstalować w nieużywanym drugim partycji systemu pliki z opcją wczesnszego optymalizowania, zapoznaj się z artykułem Pierwsze uruchomienie z zainstalowanymi plikami DEX_PREOPT.