Wdrażaj wirtualne A/B

Aby zaimplementować wirtualne A/B na nowym urządzeniu lub zmodernizować uruchomione urządzenie, należy wprowadzić zmiany w kodzie specyficznym dla urządzenia.

Buduj flagi

Urządzenia korzystające z wirtualnego A/B muszą być skonfigurowane jako urządzenia A/B i muszą być uruchamiane z partycjami dynamicznymi .

W przypadku urządzeń uruchamianych z wirtualnym A/B ustaw je tak, aby dziedziczyły podstawową konfigurację wirtualnego urządzenia A/B:

$(call inherit-product, \
    $(SRC_TARGET_DIR)/product/virtual_ab_ota.mk)

Urządzenia uruchamiane z wirtualnym A/B potrzebują tylko połowy rozmiaru płytki dla BOARD_SUPER_PARTITION_SIZE , ponieważ gniazda B nie są już w super. Oznacza to, że BOARD_SUPER_PARTITION_SIZE musi być większe lub równe suma(rozmiar grup aktualizacji) + narzut , która z kolei musi być większa lub równa suma(rozmiar partycji) + narzut .

Aby włączyć skompresowane migawki w systemie Android 13 i nowszych wersjach za pomocą funkcji Virtual A/B, odziedzicz następującą konfigurację podstawową:

$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_ramdisk.mk)
$(call inherit-product, \
    $(SRC_TARGET_DIR)/product/virtual_ab_ota/android_t_baseline.mk)

Umożliwia to tworzenie migawek przestrzeni użytkownika za pomocą wirtualnego A/B przy użyciu metody kompresji bez operacji. Następnie możesz skonfigurować metodę kompresji na jedną z obsługiwanych metod, gz , zstd i lz4 .

PRODUCT_VIRTUAL_AB_COMPRESSION_METHOD := lz4

Aby włączyć skompresowane migawki w systemie Android 12 za pomocą funkcji Virtual A/B, odziedzicz następującą konfigurację podstawową:

$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_ramdisk.mk)
$(call inherit-product, \
    $(SRC_TARGET_DIR)/product/virtual_ab_ota/compression.mk)

Kompresja XOR

W przypadku urządzeń z systemem Android 13 lub nowszym funkcja kompresji XOR nie jest domyślnie włączona. Aby włączyć kompresję XOR, dodaj następujący fragment do pliku .mk urządzenia.

PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.compression.xor.enabled=true

Kompresja XOR jest domyślnie włączona dla urządzeń dziedziczących z android_t_baseline.mk .

Scalanie przestrzeni użytkownika

W przypadku urządzeń uaktualnionych do wersji Android 13 lub nowszej proces scalania przestrzeni użytkownika opisany w sekcji Warstwy mapowania urządzeń nie jest domyślnie włączony. Aby włączyć scalanie przestrzeni użytkownika, dodaj następujący wiersz do pliku .mk urządzenia:

PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.userspace.snapshots.enabled=true

Scalanie przestrzeni użytkownika jest domyślnie włączone na urządzeniach uruchamianych w wersji 13 i nowszej.

Kontrola rozruchu HAL

Kontrola rozruchu HAL zapewnia interfejs dla klientów OTA do kontrolowania gniazd rozruchowych. Virtual A/B wymaga niewielkiej aktualizacji HAL kontroli rozruchu, ponieważ potrzebne są dodatkowe interfejsy API, aby zapewnić ochronę programu ładującego podczas flashowania/resetowania do ustawień fabrycznych. Zobacz pliki IBootControl.hal i type.hal , aby zapoznać się z najnowszą wersją definicji HAL.

// hardware/interfaces/boot/1.1/types.hal
enum MergeStatus : uint8_t {
    NONE, UNKNOWN, SNAPSHOTTED, MERGING, CANCELLED };

// hardware/interfaces/boot/1.1/IBootControl.hal
package android.hardware.boot@1.1;
interface IBootControl extends @1.0::IBootControl {
    setSnapshotMergeStatus(MergeStatus status)
        generates (bool success);
    getSnapshotMergeStatus()
        generates (MergeStatus status);
}
// Recommended implementation

Return<bool> BootControl::setSnapshotMergeStatus(MergeStatus v) {
    // Write value to persistent storage
    // e.g. misc partition (using libbootloader_message)
    // bootloader rejects wipe when status is SNAPSHOTTED
    // or MERGING
}

Zmiany w Fstabie

Integralność partycji metadanych ma kluczowe znaczenie dla procesu rozruchu, zwłaszcza zaraz po zastosowaniu aktualizacji OTA. Zatem partycję metadanych należy sprawdzić przed zamontowaniem jej w first_stage_init . Aby mieć pewność, że tak się stanie, dodaj flagę check fs_mgr do wpisu /metadata . Poniżej przedstawiono przykład:

/dev/block/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard,sync wait,formattable,first_stage_mount,check

Wymagania jądra

Aby włączyć tworzenie migawek, ustaw CONFIG_DM_SNAPSHOT na true .

W przypadku urządzeń używających F2FS dołącz flagę f2fs: eksport FS_NOCOW_FL do łatki jądra użytkownika, aby naprawić przypinanie plików. Dołącz także łatkę jądra f2fs: support dostosowaną do przypiętych plików .

Wirtualny A/B opiera się na funkcjach dodanych w wersji jądra 4.3: bitu stanu przepełnienia w obiektach snapshot i snapshot-merge . Wszystkie urządzenia uruchamiane z systemem Android 9 i nowszym powinny już mieć jądro w wersji 4.4 lub nowszej.

Aby włączyć skompresowane migawki, minimalna obsługiwana wersja jądra to 4.19. Ustaw CONFIG_DM_USER=m lub CONFIG_DM_USER=y . Jeśli używasz pierwszego (modułu), moduł musi zostać załadowany do ramdysku pierwszego stopnia. Można to osiągnąć dodając następujący wiersz do pliku Makefile urządzenia:

BOARD_GENERIC_RAMDISK_KERNEL_MODULES_LOAD := dm-user.ko

Dostosuj na urządzeniach aktualizujących się do Androida 11

Podczas aktualizacji do systemu Android 11 urządzenia uruchomione z partycjami dynamicznymi mogą opcjonalnie doposażyć wirtualne A/B. Proces aktualizacji jest w większości taki sam, jak w przypadku urządzeń uruchamianych za pomocą wirtualnego A/B, z pewnymi drobnymi różnicami:

  • Lokalizacja plików COW — w przypadku urządzeń uruchamiających klient OTA wykorzystuje całe dostępne puste miejsce na super partycji przed użyciem miejsca w /data . W przypadku urządzeń modernizowanych na super partycji zawsze jest wystarczająco dużo miejsca, aby plik COW nigdy nie był tworzony na /data .

  • Flagi funkcji w czasie kompilacji — w przypadku urządzeń doposażających wirtualne A/B zarówno PRODUCT_VIRTUAL_AB_OTA , jak i PRODUCT_VIRTUAL_AB_OTA_RETROFIT są ustawione na true , jak pokazano poniżej:

    (call inherit-product, \
        (SRC_TARGET_DIR)/product/virtual_ab_ota_retrofit.mk)
    
  • Rozmiar super partycji — urządzenia uruchamiane z wirtualną partycją A/B mogą zmniejszyć BOARD_SUPER_PARTITION_SIZE o połowę, ponieważ gniazda B nie znajdują się w super partycji. Urządzenia doposażające wirtualne A/B zachowują stary rozmiar super partycji, więc BOARD_SUPER_PARTITION_SIZE jest większy lub równy 2 * suma (rozmiar grup aktualizacji) + narzut , który z kolei jest większy lub równy 2 * suma (rozmiar partycji) + nad głową .

Zmiany w bootloaderze

Na etapie łączenia aktualizacji /data przechowuje jedyną całą instancję systemu operacyjnego Android. Po rozpoczęciu migracji partycje system macierzystego, vendor i product będą niekompletne do czasu zakończenia kopiowania. Jeśli w trakcie tego procesu urządzenie zostanie przywrócone do ustawień fabrycznych (w drodze odzyskiwania lub w oknie dialogowym Ustawienia systemu), uruchomienie urządzenia będzie niemożliwe.

Przed usunięciem /data zakończ scalanie w procesie odzyskiwania lub przywracania w zależności od stanu urządzenia:

  • Jeśli nowa kompilacja została wcześniej pomyślnie uruchomiona, zakończ migrację.
  • W przeciwnym razie przywróć stare gniazdo:
    • W przypadku partycji dynamicznych przywróć poprzedni stan.
    • W przypadku partycji statycznych ustaw aktywne gniazdo na stare.

Zarówno bootloader, jak i fastbootd mogą usunąć partycję /data jeśli urządzenie jest odblokowane. Podczas gdy fastbootd może wymusić zakończenie migracji, program ładujący nie może. Program ładujący nie wie, czy trwa scalanie ani jakie bloki w /data stanowią partycje systemu operacyjnego. Urządzenia muszą uniemożliwiać użytkownikowi nieświadome spowodowanie niesprawności urządzenia (zamurowanie), wykonując następujące czynności:

  1. Zaimplementuj kontrolę rozruchu HAL, aby program ładujący mógł odczytać wartość ustawioną przez metodę setSnapshotMergeStatus() .
  2. Jeśli status scalania to MERGING lub jeśli status scalania to SNAPSHOTTED , a gniazdo zmieniło się na nowo zaktualizowane gniazdo, wówczas żądania usunięcia userdata , metadata lub partycji przechowującej status scalania muszą zostać odrzucone w programie ładującym.
  3. Zaimplementuj polecenie fastboot snapshot-update cancel , aby użytkownicy mogli zasygnalizować programowi ładującemu, że chcą ominąć ten mechanizm ochronny.
  4. Zmodyfikuj niestandardowe narzędzia lub skrypty do flashowania, aby fastboot snapshot-update cancel podczas flashowania całego urządzenia. Można to bezpiecznie wydać, ponieważ flashowanie całego urządzenia usuwa OTA. Narzędzia mogą wykryć to polecenie w czasie wykonywania, implementując fastboot getvar snapshot-update-status . To polecenie pomaga rozróżnić warunki błędu.

Przykład

struct VirtualAbState {
    uint8_t StructVersion;
    uint8_t MergeStatus;
    uint8_t SourceSlot;
};

bool ShouldPreventUserdataWipe() {
    VirtualAbState state;
    if (!ReadVirtualAbState(&state)) ...
    return state.MergeStatus == MergeStatus::MERGING ||
           (state.MergeStatus == MergeStatus::SNAPSHOTTED &&
            state.SourceSlot != CurrentSlot()));
}

Zmiany w narzędziach Fastboot

Android 11 wprowadza następujące zmiany w protokole fastboot:

  • getvar snapshot-update-status — Zwraca wartość, którą kontrola rozruchu HAL przekazała programowi ładującemu:
    • Jeśli stan to MERGING , program ładujący musi zwrócić merging .
    • Jeśli stan to SNAPSHOTTED , program ładujący musi zwrócić snapshotted .
    • W przeciwnym razie program ładujący musi zwrócić none .
  • snapshot-update merge — kończy operację scalania, w razie potrzeby uruchamiając system recovery/fastbootd. To polecenie jest prawidłowe tylko wtedy, gdy snapshot-update-status jest merging i jest obsługiwany tylko w trybie fastbootd.
  • snapshot-update cancel — Ustawia status scalania HAL kontroli rozruchu na CANCELLED . To polecenie jest nieprawidłowe, gdy urządzenie jest zablokowane.
  • erase lub wipeerase lub wipe metadata , userdata lub partycji przechowującej status scalania dla kontroli rozruchu HAL powinno sprawdzić stan scalania migawki. Jeżeli status to MERGING lub SNAPSHOTTED , urządzenie powinno przerwać operację.
  • set_active — Polecenie set_active zmieniające aktywne gniazdo powinno sprawdzać stan scalania migawek. Jeżeli status to MERGING , urządzenie powinno przerwać operację. Slot można bezpiecznie zmienić w stanie SNAPSHOTTED .

Zmiany te mają na celu zapobieganie przypadkowemu uniemożliwieniu uruchomienia urządzenia, ale mogą zakłócać działanie zautomatyzowanych narzędzi. Gdy polecenia są używane jako element flashowania wszystkich partycji, na przykład uruchamiając fastboot flashall , zaleca się użycie następującego przepływu:

  1. Zapytanie getvar snapshot-update-status .
  2. W przypadku merging lub snapshotted wydaj snapshot-update cancel .
  3. Kontynuuj migające kroki.

Zmniejsz wymagania dotyczące przechowywania

W przypadku urządzeń, które nie mają pełnej pamięci A/B przydzielonej w super i które spodziewają się użycia /data w razie potrzeby, zdecydowanie zaleca się korzystanie z narzędzia do mapowania bloków. Narzędzie do mapowania bloków utrzymuje spójność alokacji bloków pomiędzy kompilacjami, redukując niepotrzebne zapisy w migawce. Jest to udokumentowane w sekcji Zmniejszanie rozmiaru OTA .

Metody kompresji OTA

Pakiety OTA można dostroić pod kątem różnych wskaźników wydajności. Android udostępnia kilka obsługiwanych metod kompresji ( gz , lz4 , zstd i none ), które wymagają kompromisów między czasem instalacji, wykorzystaniem przestrzeni COW, czasem rozruchu i czasem scalania migawek. Domyślną opcją włączoną dla wirtualnego ab z kompresją jest gz compression method . (Uwaga: względna wydajność pomiędzy metodami kompresji różni się w zależności od szybkości procesora i przepustowości pamięci, która może się zmieniać w zależności od urządzenia. Wszystkie wygenerowane poniżej pakiety OTA mają wyłączoną opcję PostInstall, co nieznacznie spowalnia czas uruchamiania. Całkowity rozmiar partycji dynamicznej pełnego OT bez kompresji wynosi 4,81 GB ).

Przyrostowe OTA na Pixelu 6 Pro

Czas instalacji bez fazy poinstalacyjnej Wykorzystanie przestrzeni COW Opublikuj czas rozruchu OTA Czas scalania migawki
gz 24 minuty 1,18 GB 40,2 sek 45,5 sek
lz4 13 minut 1,49 GB 37,4 sek 37,1 sek
nic 13 minut 2,90 GB 37,6 sek 40,7 sek

Pełna OTA na Pixelu 6 Pro

Czas instalacji bez fazy poinstalacyjnej Wykorzystanie przestrzeni KRÓW Opublikuj czas rozruchu OTA Czas scalania migawki
gz 23 minuty 2,79 GB 24,9 sek 41,7 sek
lz4 12 minut 3,46 GB 20,0 sek 25,3 sek
nic 10 minut 4,85 GB 20,6 sek 29,8 sek