Virtual A/B ist der wichtigste Updatemechanismus von Android. Virtuelle A/B-Updates basieren auf den alten A/B-Updates (siehe A/B-Systemupdates) und Nicht-A/B-Updates, die in Android 15 eingestellt werden, um den Speicherbedarf von Updates zu reduzieren.
Bei Virtual A/B gibt es keinen zusätzlichen Slot für dynamische Partitionen. Weitere Informationen finden Sie unter Dynamische Partitionen. Stattdessen wird das Delta in einen Snapshot geschrieben und dann in die Basispartition eingefügt, nachdem ein erfolgreicher Start bestätigt wurde. Für Virtual A/B wird ein Android-spezifisches Snapshot-Format verwendet. Weitere Informationen finden Sie unter COW-Format für komprimierte Snapshots. Damit können Snapshots komprimiert werden, um den Speicherplatzbedarf zu minimieren. Bei einem vollständigen OTA wird die Snapshot-Größe durch die Komprimierung um etwa 45% reduziert, bei einem inkrementellen OTA um etwa 55%.
Android 12 bietet die Option der virtuellen A/B-Komprimierung zum Komprimieren von Partitionen, für die ein Snapshot erstellt wurde. 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. Virtuelle A/B-Updates minimieren die Zeit, in der ein Gerät offline und nicht nutzbar ist.
- Virtuelle A/B-Updates können rückgängig gemacht werden. Wenn das neue Betriebssystem nicht gestartet werden kann, wird automatisch ein Rollback auf die vorherige Version durchgeführt.
- Bei virtuellen A/B-Updates wird nur wenig zusätzlicher Speicherplatz benötigt, da nur die Partitionen dupliziert werden, die vom Bootloader verwendet werden. Andere aktualisierbare Partitionen werden per Snapshot gesichert.
Hintergrund und Terminologie
In diesem Abschnitt werden die Terminologie definiert und die Technologie beschrieben, die virtuelles A/B unterstützt. Während 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 von dm-user und snapuserd-Daemon wieder in das Basisgerät eingefügt. Dieser Vorgang findet vollständig im Nutzerbereich statt.
Device Mapper
Device Mapper ist eine virtuelle Linux-Blockebene, die häufig in Android verwendet wird. Bei dynamischen Partitionen sind Partitionen wie /system
ein Stapel aus geschichteten Geräten:
- Unten im Stapel befindet sich die physische Super-Partition (z. B.
/dev/block/by-name/super
). - In der Mitte befindet sich ein
dm-linear
-Gerät, das angibt, welche Blöcke in der Superpartition die angegebene dynamische Partition bilden. Auf einem A/B-Gerät wird dies als/dev/block/mapper/system_[a|b]
und auf einem Nicht-A/B-Gerät als/dev/block/mapper/system
angezeigt. - Oben befindet sich ein
dm-verity
-Gerät, das für überprüfte Partitionen erstellt wurde. Dieses Gerät überprüft, ob Blöcke auf demdm-linear
-Gerät korrekt signiert sind. Sie 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: Stapel unter dem Bereitstellungspunkt „/system“
Komprimierte Snapshots
In Android 12 und höher können Sie komprimierte Snapshots in Ihrem Build aktivieren, um den hohen Speicheranforderungen der /data
-Partition gerecht zu werden, da die Speicheranforderungen in der /data
-Partition hoch sein können.
Virtuelle A/B-komprimierte Snapshots basieren auf den folgenden Komponenten, die in Android 12 und höher verfügbar sind:
dm-user
ist ein Kernelmodul, das FUSE ähnelt und mit dem der Userspace Blockgeräte implementieren kann.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 sind in den folgenden Abschnitten beschrieben: COW-Format für komprimierte Snapshots, dm-user und snapuserd.
COW-Format für komprimierte Snapshots
In Android 12 und höher verwenden komprimierte Snapshots ein Android-spezifisches COW-Format. Das COW-Format enthält Metadaten zum OTA und separate Puffer mit COW-Vorgängen und neuen Betriebssystemdaten. Im Vergleich zum Kernel-Snapshot-Format, das nur replace-Vorgänge zulässt (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 sollte 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 mit GZ-Kompression 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-Updates bestehen nur aus replace- und zero-Vorgängen. Inkrementelle OTA-Updates können zusätzlich copy-Vorgänge enthalten.
Das vollständige Snapshot-Layout auf der Festplatte sieht so aus:
Abbildung 2: Android-COW-Format auf der Festplatte
dm-user
Mit dem dm-user-Kernelmodul kann userspace
Device Mapper-Blockgeräte implementieren. Durch einen dm-user-Tabelleneintrag wird unter /dev/dm-user/<control-name>
ein sonstiges Gerät erstellt. Ein userspace
-Prozess kann das Gerät abfragen, um Lese- und Schreibanfragen vom Kernel zu empfangen. Jeder Anfrage ist ein Puffer für den Nutzerbereich zugeordnet, der entweder gefüllt (für einen Lesevorgang) oder weitergegeben (für einen Schreibvorgang) wird.
Das dm-user
-Kernelmodul bietet eine neue, für Nutzer sichtbare 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
-Schnittstelle in Android zu ändern.
snapuserd
Die snapuserd
-Nutzerbereichskomponente für dm-user
implementiert die Virtual A/B-Kompression. Snapuserd ist ein Userspace-Daemon, der für das Schreiben und Lesen der Android-COW-Geräte zuständig ist. Alle Ein-/Ausgaben 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 die neuen Blockdaten entpackt.
XOR-Komprimierung
Bei Geräten, die mit Android 13 und höher auf den Markt kommen, können mit der standardmäßig aktivierten XOR-Komprimierungsfunktion XOR-komprimierte Bytes zwischen alten und neuen Blöcken in Userspace-Snapshots 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 Reduzierung der Snapshot-Größe ist möglich, da XOR-Daten viele Nullen enthalten und leichter zu komprimieren sind als Rohblockdaten. Auf Pixel-Geräten wird die Snapshot-Größe durch die XOR-Komprimierung um 25% bis 40 % reduziert.
Für Geräte, die auf Android 13 und höher aktualisiert werden, muss die XOR-Komprimierung aktiviert sein. Weitere Informationen finden Sie unter XOR-Komprimierung.
Snapshot-Zusammenführung
Bei Geräten, die bei Markteinführung Android 13 oder höher nutzen, werden die Snapshot- und Snapshot-Zusammenführungsprozesse in der virtuellen A/B-Komprimierung von der snapuserd
-Userspace-Komponente ausgeführt. Auf Geräten, die auf Android 13 und höher aktualisiert werden, muss diese Funktion aktiviert sein. Weitere Informationen finden Sie unter Userspace-Merge.
Im Folgenden wird die virtuelle A/B-Kompression beschrieben:
- Das Framework mountet die Partition
/system
von einemdm-verity
-Gerät, das auf einemdm-user
-Gerät gestapelt ist. Das bedeutet, dass jede E/A-Operation des Root-Dateisystems andm-user
weitergeleitet wird. dm-user
leitet die E/A an den Userspace-Daemonsnapuserd
weiter, der die E/A-Anfrage verarbeitet.- Wenn der Zusammenführungsvorgang abgeschlossen ist, wird
dm-verity
im Framework überdm-linear
(system_base
) platziert unddm-user
wird entfernt.
Abbildung 3: Virtual A/B-Komprimierungsprozess
Der Snapshot-Zusammenführungsprozess kann unterbrochen werden. Wenn das Gerät während des Zusammenführungsvorgangs neu gestartet wird, wird der Vorgang nach dem Neustart fortgesetzt.
Übergänge initialisieren
Beim Booten mit komprimierten Snapshots muss die Initialisierung der ersten Phase snapuserd
starten, um Partitionen bereitzustellen. Das ist ein Problem: Wenn sepolicy
geladen und erzwungen wird, wird snapuserd
in den falschen Kontext gesetzt und seine Leseanfragen schlagen mit SELinux-Verweigerungen fehl.
Um dieses Problem zu beheben, wird snapuserd
synchron mit init
umgestellt:
- Die erste Phase
init
startetsnapuserd
über die RAM-Disk und speichert einen offenen Dateideskriptor dafür in einer Umgebungsvariablen. - In der ersten Phase wird mit
init
das Root-Dateisystem auf die Systempartition umgestellt und dann die Systemkopie voninit
ausgeführt. - Beim Systemkopieren von
init
wird die kombinierte sepolicy in einen String gelesen. Init
ruftmlock()
auf allen ext4-basierten Seiten auf. Anschließend werden alle Device-Mapper-Tabellen für Snapshot-Geräte deaktiviert undsnapuserd
wird beendet. Danach ist es verboten, aus Partitionen zu lesen, da dies zu einem Deadlock führt.- Mit dem offenen Deskriptor für die RAM-Disk-Kopie von
snapuserd
wirdinit
mit dem richtigen SELinux-Kontext neu gestartet. Device-Mapper-Tabellen für Snapshot-Geräte werden reaktiviert. - „Init“ ruft
munlockall()
auf. Es ist sicher, E/A-Vorgänge wieder auszuführen.
Speicherplatznutzung
In der folgenden Tabelle wird die Speicherplatznutzung für verschiedene OTA-Mechanismen anhand der Betriebssystem- und OTA-Größen von Pixel verglichen.
Auswirkungen der Größe | Nicht-A/B | A/B | Virtual A/B | Virtual A/B (komprimiert) |
---|---|---|---|---|
Original-Werksabbild | 4,5 GB Super (3,8 GB Bild + 700 MB reserviert)1 | 9 GB Super (3,8 GB + 700 MB reserviert, für zwei Slots) | 4,5 GB (3,8 GB Bild + 700 MB reserviert) | 4,5 GB (3,8 GB Bild + 700 MB reserviert) |
Andere statische Partitionen | /cache | Keine | Keine | Keine |
Zusätzlicher Speicher während OTA (Speicherplatz wird nach der Anwendung von OTA zurückgegeben) | 1,4 GB auf /data | 0 | 3,8 GB2 auf /data | 2,1 GB2 auf /data |
Gesamtspeicherplatz, der für die Anwendung von OTA erforderlich ist | 5,9 GB3 (Super und Daten) | 9 GB (Super) | 8,3 GB3 (Super und Daten) | 6,6 GB3 (Super und Daten) |
1 Gibt das angenommene Layout basierend auf der Pixelzuordnung an.
2: Das neue Systemimage hat dieselbe Größe wie das Original.
3 Der Speicherplatzbedarf ist vorübergehend, bis das Gerät neu gestartet wird.
Virtual A/B in Android 11
Unter Android 11 wurde Virtual A/B mit dem Kernel-COW-Format in die dynamische Partition geschrieben. Es wurde schließlich eingestellt, da das Kernel-COW-Format keine Komprimierung unterstützt.
Virtual A/B unter Android 12
Unter Android 12 wird die Komprimierung in Form eines Android-spezifischen COW-Formats unterstützt. Für diese Version von Virtual A/B war eine Übersetzung des android-spezifischen COW in das Kernel-COW-Format erforderlich. Schließlich wurde dies in Android 13 ersetzt, wodurch die Abhängigkeit vom Kernel-COW-Format und von dm-snapshot
entfiel.
Informationen zur Implementierung von Virtual A/B oder zur Verwendung von komprimierten Snapshots finden Sie unter Virtual A/B implementieren.