Virtual A/B ist der Hauptaktualisierungsmechanismus von Android. Virtuelle A/B-Builds bauen auf älteren A/B-Updates (siehe A/B-Systemupdates) und nicht A/B-Builds auf, die in Android 15 eingestellt werden, um den Speicheraufwand von Updates zu reduzieren.
Bei virtuellen A/B-Tests gibt es keinen zusätzlichen Steckplatz für dynamische Partitionen. Weitere Informationen finden Sie unter Dynamische Partitionen. Stattdessen wird das Delta in einen Snapshot geschrieben und nach Bestätigung eines erfolgreichen Starts in die Basispartition zusammengeführt. Für virtuelle A/B-Tests wird ein Android-spezifisches Snapshot-Format verwendet. Weitere Informationen finden Sie unter COW-Format für komprimierte Snapshots. Damit können Snapshots komprimiert werden und die Nutzung des Speicherplatzes wird minimiert. Bei einer vollständigen OTA-Aktualisierung wird die Snapshot-Größe durch Komprimierung um etwa 45% reduziert. Bei einer inkrementellen OTA-Aktualisierung wird die Snapshot-Größe um etwa 55 % reduziert.
Android 12 bietet die Möglichkeit der virtuellen A/B-Komprimierung, um Snapshot-Partitionen zu komprimieren. Virtual A/B bietet Folgendes:
- Virtuelle A/B-Updates sind wie A/B-Updates nahtlos (das Update erfolgt vollständig im Hintergrund, während das Gerät in Betrieb ist). Bei virtuellen A/B-Updates ist ein Gerät nur für kurze Zeit offline und nicht nutzbar.
- Virtuelle A/B-Updates können rückgängig gemacht werden. Wenn das neue Betriebssystem nicht gestartet werden kann, wird auf den Geräten automatisch ein Rollback auf die vorherige Version durchgeführt.
- Bei virtuellen A/B-Updates wird nur ein Minimum an zusätzlichem Speicherplatz belegt, da nur die Partitionen dupliziert werden, die vom Bootloader verwendet werden. Von anderen aktualisierbaren Partitionen wird ein Snapshot erstellt.
Hintergrund und Terminologie
In diesem Abschnitt wird die Terminologie definiert und die Technologie beschrieben, die virtuelle A/B-Tests unterstützt. Bei der OTA-Installation werden neue Betriebssystemdaten entweder in den neuen Slot für physische Partitionen oder auf ein Android-spezifisches COW-Gerät geschrieben. Nach dem Neustart des Geräts werden die Daten der dynamischen Partition mithilfe des dm-user- und des snapuserd-Daemons wieder mit dem Basisgerät zusammengeführt. Dieser Vorgang findet vollständig im Nutzerbereich statt.
Device-mapper
Device Mapper ist eine virtuelle Blockschicht von Linux, die häufig in Android verwendet wird. Bei dynamischen Partitionen sind Partitionen wie /system
ein Stapel von gestapelten Geräten:
- Unten im Stapel befindet sich die physische Super-Partition (z. B.
/dev/block/by-name/super
). - In der Mitte ist ein
dm-linear
-Gerät zu sehen, das angibt, welche Blöcke in der Superpartition die angegebene dynamische Partition bilden. Auf einem A/B-Gerät wird/dev/block/mapper/system_[a|b]
angezeigt, auf einem Nicht-A/B-Gerät/dev/block/mapper/system
. - Oben befindet sich ein
dm-verity
-Gerät, das für bestätigte Partitionen erstellt wurde. Dieses Gerät prüft, ob Blöcke auf demdm-linear
-Gerät korrekt signiert sind. Er wird als/dev/block/mapper/system-verity
angezeigt und ist die Quelle des Bereitstellungspunkts/system
.
Abbildung 1 zeigt, wie der Stack unter dem Bereitstellungspunkt /system
aussieht.
Abbildung 1: Stack unter dem Bereitstellungspunkt „/system“
Komprimierte Snapshots
Da der Speicherplatzbedarf der /data
-Partition in Android 12 und höher hoch sein kann, können Sie komprimierte Snapshots in Ihrem Build aktivieren, um den höheren Speicherplatzbedarf der /data
-Partition zu erfüllen.
Komprimierte virtuelle A/B-Snapshots basieren auf den folgenden Komponenten, die in Android 12 und höher verfügbar sind:
dm-user
, ein Kernelmodul, das FUSE ähnelt und es dem Userspace ermöglicht, Blockgeräte zu implementieren.snapuserd
, ein Userspace-Daemon zur Implementierung eines neuen Snapshot-Formats.
Diese Komponenten ermöglichen die Komprimierung. Die anderen erforderlichen Änderungen zur Implementierung der Funktionen für komprimierte Snapshots werden in den folgenden Abschnitten beschrieben: COW-Format für komprimierte Snapshots, dm-user und snapuserd.
COW-Format für komprimierte Snapshots
Unter Android 12 und höher wird für komprimierte Snapshots ein Android-spezifisches COW-Format verwendet. Das COW-Format enthält Metadaten zur OTA-Aktualisierung und separate Puffer mit COW-Vorgängen und neuen Betriebssystemdaten. Im Vergleich zum Kernel-Snapshot-Format, das nur Ersetzen-Vorgänge zuließ (Block X im Basis-Image durch den Inhalt von Block Y im Snapshot ersetzen), ist das COW-Format für komprimierte Android-Snapshots ausdrucksstärker und unterstützt die folgenden Vorgänge:
- Kopieren: Block X im Basisgerät muss durch Block Y im Basisgerät ersetzt werden.
- Ersetzen: Block X auf dem Basisgerät sollte durch den Inhalt von Block Y im Snapshot ersetzt werden. Jeder dieser Blöcke ist gz-komprimiert.
- Null: Block X im Basisgerät sollte durch Nullen ersetzt werden.
- XOR: Das COW-Gerät speichert XOR-komprimierte Bytes zwischen Block X und Block Y. (Verfügbar ab Android 13.)
Vollständige OTA-Aktualisierungen bestehen nur aus den Vorgängen replace (Ersetzen) und zero (Null setzen). Inkrementelle OTA-Updates können zusätzlich Kopiervorgänge umfassen.
Das vollständige Snapshot-Layout auf dem Laufwerk sieht so aus:
Abbildung 2: Android-COW-Format auf dem Laufwerk
dm-user
Mit dem Kernelmodul „dm-user“ kann userspace
Device Mapper-Blockgeräte implementieren. Ein dm-user-Tabelleneintrag erstellt ein sonstiges Gerät unter /dev/dm-user/<control-name>
. Ein userspace
-Prozess kann das Gerät abfragen, um Lese- und Schreibanfragen vom Kernel zu erhalten. Jede Anfrage hat einen zugeordneten Puffer für den Userspace, der entweder gefüllt (beim Lesen) oder weitergegeben (beim Schreiben) wird.
Das dm-user
-Kernelmodul bietet eine neue nutzerfreundliche Schnittstelle zum Kernel, die nicht Teil der Upstream-Codebasis von kernel.org ist. Bis dahin behält sich Google das Recht vor, die dm-user
-Oberfläche in Android zu ändern.
snapuserd
Die snapuserd
-Nutzerbereichskomponente für dm-user
implementiert die virtuelle A/B-Komprimierung. Snapuserd ist ein User-Space-Daemon, der für das Schreiben und Lesen der Android-COW-Geräte verantwortlich ist. Alle I/O-Vorgänge für den Snapshot müssen über diesen Dienst erfolgen.
Während der OTA-Installation werden neue Betriebssystemdaten von snapuserd (mit Komprimierung) in den Snapshot geschrieben. Hier werden auch die Metadaten geparst und neue Blockdaten entpackt.
XOR-Komprimierung
Auf Geräten, die mit Android 13 oder höher ausgeliefert werden, ermöglicht die standardmäßig aktivierte XOR-Komprimierungsfunktion, dass in Userspace-Snapshots XOR-komprimierte Bytes zwischen alten und neuen Blöcken gespeichert werden. Wenn bei einem virtuellen A/B-Update nur wenige Byte in einem Block geändert werden, benötigt das XOR-Komprimierungsspeicherschema weniger Speicherplatz als das Standardspeicherschema, da in Snapshots keine vollständigen 4 KB gespeichert werden. Diese Verringerung der Snapshot-Größe ist möglich, da XOR-Daten viele Nullen enthalten und leichter komprimiert werden können als Rohblockdaten. Auf Pixel-Geräten reduziert die XOR-Komprimierung die Größe des Snapshots um 25 bis 40 %.
Bei Geräten, die auf Android 13 oder höher umgestellt werden, muss die XOR-Komprimierung aktiviert sein. Weitere Informationen finden Sie unter XOR-Komprimierung.
Snapshot-Merge
Auf Geräten, die mit Android 13 oder höher gestartet werden, werden die Snapshot- und Snapshot-Merge-Prozesse bei der virtuellen A/B-Komprimierung von der snapuserd
-Userspace-Komponente ausgeführt. Bei Geräten, die auf Android 13 oder höher umgestellt werden, muss diese Funktion aktiviert sein. Weitere Informationen finden Sie unter Userspace-Merge.
Im Folgenden wird der Virtual A/B-Komprimierungsprozess beschrieben:
- Das Framework bindet die
/system
-Partition von einemdm-verity
-Gerät aus, das auf einemdm-user
-Gerät gestapelt ist. Das bedeutet, dass jede I/O-Operation aus dem Stammdateisystem andm-user
weitergeleitet wird. dm-user
leitet die E/A an den Userspace-snapuserd
-Daemon weiter, der die E/A-Anfrage verarbeitet.- Wenn der Zusammenführungsvorgang abgeschlossen ist, minimiert das Framework
dm-verity
aufdm-linear
(system_base
) und entferntdm-user
.
Abbildung 3: Virtueller A/B-Komprimierungsprozess
Der Zusammenführungsprozess von Snapshots kann unterbrochen werden. Wenn das Gerät während des Zusammenführens neu gestartet wird, wird der Vorgang nach dem Neustart fortgesetzt.
Init-Übergänge
Beim Starten mit komprimierten Snapshots muss die erste Phase von init snapuserd
starten, um Partitionen bereitzustellen. Das stellt ein Problem dar: Wenn sepolicy
geladen und erzwungen wird, wird snapuserd
in den falschen Kontext gesetzt und seine Leseanfragen schlagen fehl, da sie von SELinux abgelehnt werden.
Um dies zu vermeiden, werden snapuserd
und init
synchron übergangen:
- Die erste Phase von
init
startetsnapuserd
über das RAM-Disk und speichert einen offenen Dateideskriptor in einer Umgebungsvariablen. - Die erste Phase von
init
wechselt das Stammdateisystem zur Systempartition und führt dann die Systemkopie voninit
aus. - Die Systemkopie von
init
liest die kombinierte SEPolicy in einen String ein. Init
ruftmlock()
auf allen mit ext4 gesicherten Seiten auf. Anschließend werden alle Device-Mapper-Tabellen für Snapshot-Geräte deaktiviert undsnapuserd
beendet. Danach ist das Lesen aus Partitionen nicht mehr zulässig, da dies zu einem Deadlock führt.- Mit dem offenen Descriptor für die Ramdisk-Kopie von
snapuserd
startetinit
den Daemon mit dem richtigen SELinux-Kontext neu. Device-Mapper-Tabellen für Snapshot-Geräte werden wieder aktiviert. - Init ruft
munlockall()
auf – es ist wieder sicher, I/O auszuführen.
Gruppenbereichsnutzung
In der folgenden Tabelle wird die Speichernutzung für verschiedene OTA-Mechanismen verglichen. Dabei werden das Betriebssystem und die OTA-Größe von Pixel verwendet.
Auswirkungen der Größe | Nicht A/B | A/B | Virtueller A/B-Test | Virtuelle A/B-Tests (komprimiert) |
---|---|---|---|---|
Originales Werks-Image | 4,5 GB Super (3,8 GB Image + 700 MB reserviert)1 | 9 GB Super (3,8 GB + 700 MB reserviert, für zwei Slots) | 4,5 GB Super (3,8 GB Image + 700 M reserviert) | 4,5 GB Super (3,8 GB Image + 700 M reserviert) |
Sonstige statische Partitionen | /cache | Keine | Keine | Keine |
Zusätzlicher Speicherplatz während der Over-the-air-Aktualisierung (Speicherplatz, der nach der Anwendung der Over-the-air-Aktualisierung zurückgegeben wird) | 1,4 GB auf /data | 0 | 3,8 GB2 unter /data | 2,1 GB2 unter /data |
Gesamtspeicherplatz, der zum Anwenden der OTA-Aktualisierung erforderlich ist | 5,9 GB3 (Super- und Datenebene) | 9 GB (Super) | 8,3 GB3 (Super und Daten) | 6,6 GB3 (Super und Daten) |
1: Das Layout wird anhand der Pixelzuordnung angenommen.
2: Es wird davon ausgegangen, dass das neue Systemimage dieselbe Größe wie das Original hat.
3: Der Speicherplatzbedarf ist bis zum Neustart vorübergehend.
Android 11 Virtual A/B
Android 11 von Virtual A/B wurde im Kernel-COW-Format in die dynamische Partition geschrieben. Diese Option wurde schließlich eingestellt, da das Kernel-COW-Format keine Komprimierung unterstützt.
Android 12 – virtuelles A/B-Testen
Unter Android 12 wird die Komprimierung in Form eines Android-spezifischen COW-Formats unterstützt. Für diese Version von Virtual A/B musste die Android-spezifische COW in das Kernel-COW-Format übersetzt werden. In Android 13 wurde dies schließlich ersetzt, wodurch die Abhängigkeit vom Kernel-COW-Format und auch von dm-snapshot
aufgehoben wurde.
Informationen zum Implementieren von Virtual A/B oder zum Verwenden komprimierter Snapshot-Funktionen finden Sie unter Virtual A/B implementieren.