Wirtualne przeglądy A/B

Wirtualne A/B to główny mechanizm aktualizacji Androida. Wirtualne testy A/B są oparte na starszych aktualizacjach testów A/B (patrz Aktualizacje systemu A/B) i aktualizacjach innych niż A/B, które w wersji 15 zostały wycofane, aby zmniejszyć rozmiar aktualizacji.

Wirtualne testy A/B nie mają dodatkowego miejsca na partycje dynamiczne. Więcej informacji znajdziesz w sekcji partycje dynamiczne. Zamiast tego delta jest zapisywana w migawce, a następnie scalana z partycją podstawową po potwierdzeniu pomyślnego uruchomienia. Wirtualny test A/B korzysta z formatu migawki specyficznego dla Androida. Więcej informacji znajdziesz w artykule Format COW dla skompresowanych migawek, który umożliwia kompresowanie migawek i minimalizuje wykorzystanie miejsca na dysku. W przypadku pełnej aktualizacji OTA rozmiar migawki jest zmniejszany o około 45% dzięki kompresji, a w przypadku przyrostowej aktualizacji OTA – o około 55%.

Android 12 oferuje opcję kompresji Virtual A/B, która umożliwia kompresowanie migawek partycji. Wirtualne testy A/B oferują:

  • Aktualizacje wirtualne A/B są płynne (aktualizacja odbywa się w całości w tle, gdy urządzenie jest włączone), podobnie jak aktualizacje A/B. Aktualizacje wirtualne A/B minimalizują czas, w którym urządzenie jest offline i nie można go używać.
  • Aktualizacje wirtualnego testu A/B można wycofać. Jeśli nowy system operacyjny nie uruchomi się, urządzenia automatycznie przywrócą poprzednią wersję.
  • Aktualizacje wirtualne A/B wykorzystują minimalną ilość dodatkowego miejsca, ponieważ duplikują tylko partycje używane przez program rozruchowy. Pozostałe partycje, które można zaktualizować, są zapisywane w postaci migawek.

Wprowadzenie i terminologia

W tej sekcji znajdziesz definicje terminów i opis technologii, która obsługuje wirtualne testy A/B. Podczas instalacji OTA nowe dane systemu operacyjnego są zapisywane w nowym slocie w przypadku partycji fizycznych lub na urządzeniu COW specyficznym dla Androida. Po ponownym uruchomieniu urządzenia dane partycji dynamicznej są ponownie scalane z urządzeniem bazowym za pomocą demona dm-user i snapuserd. Ten proces odbywa się w całości w przestrzeni użytkownika.

Device-mapper

Device-mapper to wirtualna warstwa blokowa systemu Linux, która jest często używana w Androidzie. W przypadku partycji dynamicznych partycje takie jak /system to stos warstwowych urządzeń:

  • Na dole stosu znajduje się fizyczna superpartycja (np./dev/block/by-name/super).
  • Pośrodku znajduje się urządzenie dm-linear, które określa, które bloki w superpartycji tworzą daną partycję dynamiczną. Na urządzeniu A/B jest to /dev/block/mapper/system_[a|b], a na urządzeniu bez podziału A/B – /dev/block/mapper/system.
  • U góry znajduje się dm-verity urządzenie utworzone dla zweryfikowanych partycji. To urządzenie sprawdza, czy bloki na urządzeniu dm-linear są prawidłowo podpisane. Wyświetla się jako /dev/block/mapper/system-verity i jest źródłem punktu montowania /system.

Na ilustracji 1 widać, jak wygląda stos pod punktem montażowym /system.

Partycja ułożona pod systemem

Rysunek 1. Stos pod punktem montowania /system

Skompresowane zrzuty

W Androidzie 12 i nowszych wersjach wymagania dotyczące miejsca na partycji /data mogą być wysokie. Aby rozwiązać ten problem, możesz włączyć w kompilacji skompresowane migawki./data

Skompresowane migawki wirtualnego testu A/B są oparte na tych komponentach, które są dostępne w Androidzie 12 i nowszym:

  • dm-user, moduł jądra podobny do FUSE, który umożliwia przestrzeni użytkownika implementowanie urządzeń blokowych.
  • snapuserd, demon przestrzeni użytkownika do implementacji nowego formatu zrzutu.

Te komponenty umożliwiają kompresję. Pozostałe niezbędne zmiany wprowadzone w celu wdrożenia funkcji skompresowanych zrzutów są opisane w kolejnych sekcjach: format COW dla skompresowanych zrzutów, dm-usersnapuserd.

Format COW dla skompresowanych zrzutów

W Androidzie 12 i nowszych wersjach skompresowane migawki używają formatu COW specyficznego dla Androida. Format COW zawiera metadane dotyczące aktualizacji OTA i ma odrębne bufory zawierające operacje COW oraz nowe dane systemu operacyjnego. W porównaniu z formatem zrzutu jądra, który umożliwiał tylko operacje zastępowania (zastąp blok X w obrazie podstawowym zawartością bloku Y w zrzucie), format COW skompresowanych zrzutów Androida jest bardziej wyrazisty i obsługuje te operacje:

  • Kopiowanie: blok X w urządzeniu podstawowym należy zastąpić blokiem Y w urządzeniu podstawowym.
  • Zastąp: blok X na urządzeniu podstawowym należy zastąpić zawartością bloku Y w migawce. Każdy z tych bloków jest skompresowany za pomocą algorytmu gzip.
  • Zero: blok X w urządzeniu podstawowym należy zastąpić zerami.
  • XOR: urządzenie COW przechowuje bajty skompresowane za pomocą XOR między blokiem X a blokiem Y. (Dostępne na Androidzie 13 i nowszych wersjach).

Pełne aktualizacje OTA składają się tylko z operacji replacezero. Aktualizacje OTA przyrostowe mogą dodatkowo zawierać operacje kopiowania.

Pełny układ zrzutu na dysku wygląda tak:

format krowy,

Rysunek 2. Format COW na dysku w Androidzie

dm-user

Moduł jądra dm-user umożliwia userspace implementację urządzeń blokowych device-mapper. Wpis w tabeli dm-user tworzy urządzenie różne w sekcji/dev/dm-user/<control-name>. userspace proces może odpytywać urządzenie, aby odbierać żądania odczytu i zapisu z jądra. Z każdym żądaniem jest powiązany bufor przestrzeni użytkownika, który może być wypełniany (w przypadku odczytu) lub propagowany (w przypadku zapisu).

Moduł jądra dm-user udostępnia nowy interfejs widoczny dla użytkownika, który nie jest częścią kodu źródłowego jądra w kernel.org. Do tego czasu Google zastrzega sobie prawo do modyfikowania interfejsu dm-user na Androidzie.

snapuserd

Komponent snapuserd przestrzeni użytkownika dm-user implementuje kompresję Virtual A/B. Snapuserd to demon przestrzeni użytkownika odpowiedzialny za zapisywanie i odczytywanie urządzeń COW w Androidzie. Cała operacja wejścia/wyjścia do migawki musi przechodzić przez tę usługę. Podczas instalacji OTA nowe dane systemu operacyjnego są zapisywane w migawce przez proces snapuserd (z kompresją). Tutaj odbywa się też parsowanie metadanych i rozpakowywanie nowych danych bloków.

Kompresja XOR

W przypadku urządzeń z Androidem 13 lub nowszym funkcja kompresji XOR, która jest domyślnie włączona, umożliwia migawkom przestrzeni użytkownika przechowywanie bajtów skompresowanych za pomocą XOR między starymi i nowymi blokami. Gdy w ramach aktualizacji wirtualnego testu A/B zmieni się tylko kilka bajtów w bloku, schemat przechowywania danych z kompresją XOR zajmuje mniej miejsca niż domyślny schemat przechowywania danych, ponieważ migawki nie przechowują pełnych 4096 bajtów. Zmniejszenie rozmiaru migawki jest możliwe, ponieważ dane XOR zawierają wiele zer i łatwiej je skompresować niż surowe dane blokowe. Na urządzeniach Pixel kompresja XOR zmniejsza rozmiar migawki o 25–40%.

W przypadku urządzeń, na których zainstalowano Androida 13 lub nowszego, musi być włączona kompresja XOR. Więcej informacji znajdziesz w artykule Kompresja XOR.

Scalanie zrzutów

W przypadku urządzeń z Androidem 13 lub nowszym procesy tworzenia i scalania migawek w kompresji Virtual A/B są wykonywane przez komponent snapuserd w przestrzeni użytkownika. W przypadku urządzeń, na których zainstalowano Androida 13 lub nowszego, ta funkcja musi być włączona. Więcej informacji znajdziesz w sekcji Scalanie przestrzeni użytkownika.

Proces kompresji wirtualnych testów A/B wygląda tak:

  1. Platforma montuje partycję /system z urządzenia dm-verity, które jest umieszczone na urządzeniu dm-user. Oznacza to, że wszystkie operacje wejścia/wyjścia z głównego systemu plików są kierowane do dm-user.
  2. dm-user kieruje operacje wejścia/wyjścia do demona snapuserd przestrzeni użytkownika, który obsługuje żądanie wejścia/wyjścia.
  3. Po zakończeniu operacji scalania ramka dm-verity zostanie umieszczona na ramce dm-linear (system_base), a ramka dm-user zostanie usunięta.

Wirtualny proces kompresji A/B

Rysunek 3. Wirtualny proces kompresji A/B

Proces scalania zrzutów można przerwać. Jeśli urządzenie zostanie ponownie uruchomione podczas procesu scalania, proces scalania zostanie wznowiony po ponownym uruchomieniu.

Przejścia inicjujące

Podczas uruchamiania z użyciem skompresowanych migawek inicjowanie pierwszego etapu musi rozpocząć się od zamontowania partycji.snapuserd Stanowi to problem: gdy sepolicy jest wczytywany i wymuszany, snapuserd trafia do niewłaściwego kontekstu, a jego żądania odczytu kończą się niepowodzeniem z powodu odmowy SELinux.

Aby to zmienić, snapuserd przechodzi w tryb zsynchronizowany z init w ten sposób:

  1. Na pierwszym etapie init uruchamia snapuserd z dysku RAM i zapisuje w nim otwarty deskryptor pliku w zmiennej środowiskowej.
  2. Pierwszy etap init przełącza główny system plików na partycję systemową, a następnie wykonuje kopię systemową init.
  3. Kopia systemowa init odczytuje połączony plik sepolicy do ciągu tekstowego.
  4. Init wywołuje mlock() na wszystkich stronach obsługiwanych przez system ext4. Następnie dezaktywuje wszystkie tabele device-mapper dla urządzeń z migawkami i zatrzymuje snapuserd. Po tym kroku nie można odczytywać danych z partycji, ponieważ powoduje to zakleszczenie.
  5. Użycie otwartego deskryptora do kopii snapuserd w pamięci RAM init ponownie uruchamia demona z prawidłowym kontekstem SELinux. Tabele mapowania urządzeń dla urządzeń z migawkami są ponownie aktywowane.
  6. Funkcja Init wywołuje munlockall() – można ponownie wykonać operację wejścia/wyjścia.

Wykorzystanie miejsca

W tabeli poniżej znajdziesz porównanie wykorzystania miejsca w przypadku różnych mechanizmów OTA na podstawie rozmiarów systemu operacyjnego i aktualizacji OTA na urządzeniach Pixel.

Wpływ rozmiaru non-A/B A/B Wirtualny test A/B Wirtualne testy A/B (skompresowane)
Oryginalny obraz fabryczny 4,5 GB super (3,8 GB obrazu + 700 MB zarezerwowanych)1 9 GB super (3, 8 GB + 700 MB zarezerwowane na 2 gniazda) 4,5 GB super (3,8 GB obrazu + 700 MB zarezerwowanych) 4,5 GB super (3,8 GB obrazu + 700 MB zarezerwowanych)
Inne statyczne partycje /cache Brak Brak Brak
Dodatkowe miejsce na dane podczas aktualizacji OTA (miejsce jest zwracane po zastosowaniu aktualizacji OTA) 1,4 GB na partycji /data 0 3,8 GB2 na /data 2,1 GB2 na /data
Łączna ilość miejsca na dane wymagana do zastosowania aktualizacji OTA 5,9 GB3 (super i dane) 9 GB (super) 8,3 GB3 (super i dane) 6,6 GB3 (super i dane)

1 Wskazuje zakładany układ na podstawie mapowania Pixela.

2Zakłada, że nowy obraz systemu ma taki sam rozmiar jak oryginalny.

3Wymagania dotyczące miejsca są tymczasowe do momentu ponownego uruchomienia.

Wirtualne A/B w Androidzie 11

Android 11 w przypadku wirtualnego A/B zapisywał na partycji dynamicznej dane w formacie Kernel COW. Został on ostatecznie wycofany, ponieważ format Kernel COW nie obsługuje kompresji.

Wirtualne A/B w Androidzie 12

W Androidzie 12 kompresja jest obsługiwana w formacie COW specyficznym dla Androida. Ta wersja wirtualnych testów A/B wymagała przetłumaczenia COW specyficznego dla Androida na format COW jądra. W Androidzie 13 zastąpiono go innym rozwiązaniem, które nie wymagało formatu COW jądra i dm-snapshot.

Aby wdrożyć wirtualny test A/B lub korzystać ze skompresowanych zrzutów, zapoznaj się z artykułem Wdrażanie wirtualnego testu A/B.