Android verfügt über zwei Update-Mechanismen: A/B-Updates (seamless) und Nicht-A/B-Updates. Um die Codekomplexität zu reduzieren und den Aktualisierungsprozess zu verbessern, werden in Android 11 die beiden Mechanismen durch virtuelles A/B vereinheitlicht, um nahtlose Aktualisierungen für alle Geräte mit minimierten Speicherkosten bereitzustellen. Android 12 bietet die Option der virtuellen A/B-Komprimierung, um Snapshot-Partitionen zu komprimieren. Sowohl in Android 11 als auch in Android 12 gilt Folgendes:
- Virtuelle A/B-Updates sind nahtlos wie A/B-Updates. Virtuelle A/B-Updates minimieren die Zeit, in der ein Gerät offline und unbrauchbar ist.
- Virtuelle A/B-Updates können rückgängig gemacht werden . Wenn das neue Betriebssystem nicht gestartet werden kann, werden die Geräte automatisch auf die vorherige Version zurückgesetzt.
- Virtuelle A/B-Updates verwenden ein Minimum an zusätzlichem Speicherplatz, indem nur die Partitionen dupliziert werden, die vom Bootloader verwendet werden. Von anderen aktualisierbaren Partitionen wird ein Snapshot erstellt .
Hintergrund und Terminologie
Dieser Abschnitt definiert die Terminologie und beschreibt die Technologie, die virtuelles A/B unterstützt.
Gerätemapper
Device-Mapper ist eine virtuelle Linux-Blockschicht, die häufig in Android verwendet wird. Bei dynamischen Partitionen sind Partitionen wie /system
ein Stapel von geschichteten Geräten:
- Am Ende des Stapels befindet sich die physische Superpartition (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 Partition bilden. Dies erscheint als/dev/block/mapper/system_[a|b]
auf einem A/B-Gerät oder/dev/block/mapper/system
auf einem Nicht-A/B-Gerät. - Ganz oben befindet sich ein
dm-verity
Gerät, das für verifizierte Partitionen erstellt wurde. Dieses Gerät überprüft, ob Blöcke auf demdm-linear
Gerät korrekt signiert sind. Es erscheint als/dev/block/mapper/system-verity
und ist die Quelle des Einhängepunkts/system
.
Abbildung 1 zeigt, wie der Stack unter dem Einhängepunkt /system
aussieht.
Abbildung 1. Stack unter dem Einhängepunkt /system
dm-Schnappschuss
Virtuelles A/B basiert auf dm-snapshot
, einem Device-Mapper-Modul zum Erstellen von Snapshots des Zustands eines Speichergeräts. Bei der Verwendung von dm-snapshot
sind vier Geräte im Spiel:
- Das Basisgerät ist das Gerät, das einen Snapshot erstellt. Auf dieser Seite ist das Basisgerät immer eine dynamische Partition, z. B. System oder Hersteller.
- Das COW-Gerät ( Copy-on-Write ) zum Protokollieren von Änderungen am Basisgerät. Es kann beliebig groß sein, muss aber groß genug sein, um alle Änderungen am Basisgerät aufzunehmen.
- Das Snapshot -Gerät wird mithilfe des
snapshot
-Ziels erstellt. Schreibvorgänge auf das Snapshot-Gerät werden auf das COW-Gerät geschrieben. Lesevorgänge vom Snapshot-Gerät lesen entweder vom Basisgerät oder vom COW-Gerät, je nachdem, ob die Daten, auf die zugegriffen wird, durch den Snapshot geändert wurden. - Das Ursprungsgerät wird mithilfe des
snapshot-origin
Ziels erstellt. Liest auf dem Ursprungsgerät, das direkt vom Basisgerät gelesen wird. Schreibvorgänge auf das Ursprungsgerät schreiben direkt auf das Basisgerät, aber die ursprünglichen Daten werden gesichert, indem auf das COW-Gerät geschrieben wird.
Abbildung 2. Gerätezuordnung für dm-snapshot
Komprimierte Schnappschüsse
Da der Speicherplatzbedarf auf 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 bewältigen.
Virtuelle A/B-komprimierte Snapshots bauen auf den folgenden Komponenten auf, die in Android 12 und höher verfügbar sind:
-
dm-user
, ein Kernel-Modul ähnlich FUSE, das 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 notwendigen Änderungen, die zur Implementierung der Funktionen für komprimierte Snapshots vorgenommen wurden, werden in den nächsten Abschnitten beschrieben: COW-Format für komprimierte Snapshots , dm-user und Snapuserd .
COW-Format für komprimierte Schnappschüsse
In Android 12 und höher verwenden komprimierte Snapshots ein COW-Format. Ähnlich wie das eingebaute Format des Kernels, das für unkomprimierte Snapshots verwendet wird, hat das COW-Format für die komprimierten Snapshots abwechselnde Abschnitte von Metadaten und Daten. Die Metadaten des ursprünglichen Formats sind nur für Ersetzungsvorgänge zulässig: Ersetzen Sie Block X im Basisbild durch den Inhalt von Block Y im Snapshot. Das komprimierte COW-Snapshot-Format ist ausdrucksstärker und unterstützt die folgenden Operationen:
- Kopieren : Block X im Basisgerät sollte durch Block Y im Basisgerät ersetzt werden.
- Ersetzen : Block X im 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 alle Nullen ersetzt werden.
- XOR : Das COW-Gerät speichert XOR-komprimierte Bytes zwischen Block X und Block Y. (Verfügbar in Android 13 und höher.)
Vollständige OTA-Updates bestehen nur aus Ersetzungs- und Nulloperationen . Inkrementelle OTA-Updates können zusätzlich Kopiervorgänge haben.
dm-Benutzer in Android 12
Das dm-user-Kernelmodul ermöglicht es userspace
, Device-Mapper-Blockgeräte zu 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 Schreibanforderungen vom Kernel zu erhalten. Jede Anfrage hat einen zugehörigen Puffer, den der Userspace entweder füllen (für einen Lesevorgang) oder propagieren (für einen Schreibvorgang) kann.
Das dm-user
Kernelmodul bietet eine neue, für den Benutzer 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
in Android zu ändern.
snapuserd
Die Userspace-Komponente snapuserd
für dm-user
implementiert die virtuelle A/B-Komprimierung.
In der unkomprimierten Version von Virtual A/B (entweder in Android 11 und niedriger oder in Android 12 ohne die komprimierte Snapshot-Option) ist das COW-Gerät eine Rohdatei. Wenn die Komprimierung aktiviert ist, fungiert der COW stattdessen als dm-user
Gerät, das mit einer Instanz des snapuserd
Daemons verbunden ist.
Der Kernel verwendet das neue COW-Format nicht. Die snapuserd
Komponente übersetzt also Anfragen zwischen dem Android COW-Format und dem eingebauten Format des Kernels:
Abbildung 3. Flussdiagramm von snapuserd als Übersetzer zwischen Android- und Kernel-COW-Formaten
Diese Übersetzung und Dekomprimierung erfolgt niemals auf der Festplatte. Die snapuserd
Komponente fängt die COW-Lese- und -Schreibvorgänge ab, die im Kernel auftreten, und implementiert sie mithilfe des Android-COW-Formats.
XOR-Komprimierung
Bei Geräten, die mit Android 13 und höher gestartet werden, ermöglicht die standardmäßig aktivierte XOR-Komprimierungsfunktion, dass Userspace-Snapshots XOR-komprimierte Bytes zwischen alten Blöcken und neuen Blöcken speichern. Wenn nur wenige Bytes in einem Block in einem virtuellen A/B-Update geändert werden, verwendet das XOR-Komprimierungsspeicherschema weniger Speicherplatz als das Standardspeicherschema, da Snapshots keine vollen 4K-Bytes speichern. Diese Reduzierung der Snapshot-Größe ist möglich, da XOR-Daten viele Nullen enthalten und einfacher zu komprimieren sind als Rohblockdaten. Auf Pixel-Geräten reduziert die XOR-Komprimierung die Snapshot-Größe um 25 % bis 40 %.
Für Geräte, die auf Android 13 und höher aktualisieren, muss die XOR-Komprimierung aktiviert sein. Einzelheiten finden Sie unter XOR-Komprimierung .
Virtuelle A/B-Komprimierungsverfahren
Dieser Abschnitt enthält Details zum virtuellen A/B-Komprimierungsprozess, der in Android 13 und Android 12 verwendet wird.
Metadaten lesen (Android 12)
Metadaten werden von einem snapuserd
Daemon erstellt. Die Metadaten sind in erster Linie eine Abbildung von zwei IDs mit jeweils 8 Bytes, die die zusammenzuführenden Sektoren darstellen. In dm-snapshot
heißt es disk_exception
.
struct disk_exception {
uint64_t old_chunk;
uint64_t new_chunk;
};
Eine Plattenausnahme wird verwendet, wenn ein alter Datenblock durch einen neuen ersetzt wird.
Ein snapuserd
Daemon liest die interne COW-Datei über die COW-Bibliothek und erstellt die Metadaten für jede der in der COW-Datei vorhandenen COW-Operationen.
Metadaten-Lesevorgänge werden vom dm-snapshot
im Kernel initiiert, wenn das dm- dm- snapshot
-Gerät erstellt wird.
Die folgende Abbildung zeigt ein Sequenzdiagramm für den IO-Pfad für die Metadatenkonstruktion.
Abbildung 4. Sequenzfluss für den IO-Pfad in der Metadatenkonstruktion
Zusammenführen (Android 12)
Sobald der Startvorgang abgeschlossen ist, markiert die Update-Engine den Steckplatz als Start erfolgreich und leitet die Zusammenführung ein, indem sie das dm-snapshot
Ziel auf das dm-snapshot-merge
Ziel umschaltet.
dm-snapshot
durchläuft die Metadaten und initiiert einen Zusammenführungs-E/A für jede Datenträgerausnahme. Eine allgemeine Übersicht über den Zusammenführungs-E/A-Pfad ist unten dargestellt.
Abbildung 5. Übersicht über Merge-IO-Pfade
Wenn das Gerät während des Zusammenführungsvorgangs neu gestartet wird, wird die Zusammenführung beim nächsten Neustart fortgesetzt und die Zusammenführung abgeschlossen.
Device-Mapper-Layering
Bei Geräten, die mit Android 13 und höher gestartet werden, werden die Snapshot- und Snapshot-Zusammenführungsprozesse in der virtuellen A/B-Komprimierung von der snapuserd
Userspace-Komponente durchgeführt. Für Geräte, die auf Android 13 und höher aktualisieren, muss diese Funktion aktiviert werden. Einzelheiten finden Sie unter Userspace-Merge .
Im Folgenden wird der virtuelle A/B-Komprimierungsprozess beschrieben:
- Das Framework stellt die
/system
Partition von einemdm-verity
Gerät bereit, das auf einemdm-user
Gerät gestapelt ist. Das bedeutet, dass jede E/A vom Root-Dateisystem andm-user
weitergeleitet wird. -
dm-user
leitet die E/A an den userspacesnapuserd
Daemon weiter, der die E/A-Anforderung verarbeitet. - Wenn der Zusammenführungsvorgang abgeschlossen ist, reduziert das Framework
dm-verity
aufdm-linear
(system_base
) und entferntdm-user
.
Abbildung 6. Virtueller A/B-Komprimierungsprozess
Der Snapshot-Zusammenführungsprozess kann unterbrochen werden. Wenn das Gerät während des Zusammenführungsvorgangs neu gestartet wird, wird der Zusammenführungsvorgang nach dem Neustart fortgesetzt.
Übergänge einleiten
Beim Booten mit komprimierten Snapshots muss die Init der ersten Stufe snapuserd
starten, um Partitionen zu mounten. Dies stellt ein Problem dar: Wenn sepolicy
geladen und erzwungen wird, wird snapuserd
in den falschen Kontext versetzt, und seine Leseanforderungen schlagen mit selinux-Denials fehl.
Um dies zu beheben, werden snapuserd
-Übergänge im Gleichschritt mit init
wie folgt ausgeführt:
-
init
der ersten Stufe startetsnapuserd
von der Ramdisk und speichert einen offenen Dateideskriptor in einer Umgebungsvariablen. -
init
der ersten Stufe schaltet das Root-Dateisystem auf die Systempartition um und führt dann die Systemkopie voninit
aus. - Die Systemkopie von
init
liest die kombinierte sepolicy in einen String. -
Init
ruftmlock()
auf allen ext4-unterstützten Seiten auf. Es deaktiviert dann alle Device-Mapper-Tabellen für Snapshot-Geräte und stopptsnapuserd
. Danach ist es verboten, von Partitionen zu lesen, da dies zu einem Deadlock führt. - Unter Verwendung des offenen Deskriptors für die Ramdisk-Kopie von
snapuserd
init
den Daemon mit dem korrekten Selinux-Kontext neu. Device-Mapper-Tabellen für Snapshot-Devices werden reaktiviert. - Init ruft
munlockall()
auf - es ist sicher, IO erneut auszuführen.
Platznutzung
Die folgende Tabelle bietet einen Vergleich der Speicherplatznutzung für verschiedene OTA-Mechanismen unter Verwendung der OS- und OTA-Größen von Pixel.
Einfluss auf die Größe | Nicht-A/B | A/B | Virtuelles A/B | Virtuelles A/B (komprimiert) |
---|---|---|---|---|
Originalbild der Fabrik | 4,5 GB Super (3,8 GB Bild + 700 MB reserviert) 1 | 9 GB Super (3,8 G + 700 MB reserviert, für zwei Steckplätze) | 4,5 GB Super (3,8 GB Bild + 700 MB reserviert) | 4,5 GB Super (3,8 GB Bild + 700 MB reserviert) |
Andere statische Partitionen | /Zwischenspeicher | Keiner | Keiner | Keiner |
Zusätzlicher Speicher während OTA (Speicherplatz wird nach Anwendung von OTA zurückgegeben) | 1,4 GB auf /data | 0 | 3,8 GB 2 auf /data | 2,1 GB 2 auf /data |
Für die Anwendung von OTA erforderlicher Gesamtspeicher | 5,9 GB 3 (Super und Daten) | 9 GB (super) | 8,3 GB 3 (Super und Daten) | 6,6 GB 3 (Super und Daten) |
1 Zeigt das angenommene Layout basierend auf der Pixelzuordnung an.
2 Geht davon aus, dass das neue Systemabbild die gleiche Größe wie das Original hat.
3 Speicherplatzbedarf ist vorübergehend bis zum Neustart.
Informationen zum Implementieren von Virtual A/B oder zum Verwenden komprimierter Snapshot-Funktionen finden Sie unter Implementieren von Virtual A/B