Android verfügt über zwei Update-Mechanismen: A/B-Updates (nahtlos) und Nicht-A/B-Updates. Um die Komplexität des Codes zu reduzieren und den Update-Prozess zu verbessern, werden in Android 11 die beiden Mechanismen durch virtuelles A/B vereinheitlicht, um nahtlose Updates auf allen Geräten 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 erfolgen 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 startet, werden die Geräte automatisch auf die vorherige Version zurückgesetzt.
- Virtuelle A/B-Updates beanspruchen nur ein Minimum an zusätzlichem Speicherplatz, indem nur die Partitionen dupliziert werden, die vom Bootloader verwendet werden. Andere aktualisierbare Partitionen werden per Snapshot erstellt .
Hintergrund und Terminologie
In diesem Abschnitt wird die Terminologie definiert und die Technologie beschrieben, die virtuelles A/B unterstützt.
Geräte-Mapper
Device-Mapper ist eine virtuelle Linux-Blockschicht, die häufig in Android verwendet wird. Bei dynamischen Partitionen sind Partitionen wie /system
ein Stapel geschichteter Geräte:
- Am unteren Ende des Stapels befindet sich die physische Superpartition (z
/dev/block/by-name/super
). - In der Mitte befindet sich ein
dm-linear
Gerät, das angibt, welche Blöcke in der Superpartition die gegebene 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. - 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/system
Mountpunkts.
Abbildung 1 zeigt, wie der Stapel unter dem Mountpunkt /system
aussieht.
Abbildung 1. Stapel unter dem Mountpunkt /system
dm-Schnappschuss
Virtual A/B basiert auf dm-snapshot
, einem Device-Mapper-Modul zum Snapshoten des Zustands eines Speichergeräts. Bei Verwendung von dm-snapshot
sind vier Geräte im Spiel:
- Das Basisgerät ist das Gerät, von dem ein Snapshot erstellt wird. 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. Die Größe kann beliebig sein, sie muss jedoch 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. Liest vom Snapshot-Gerät entweder vom Basisgerät oder vom COW-Gerät, abhängig davon, 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 das Ursprungsgerät, das direkt vom Basisgerät gelesen wird. Schreibt auf das Ursprungsgerät und schreibt direkt auf das Basisgerät, die Originaldaten werden jedoch durch Schreiben auf das COW-Gerät gesichert.
Abbildung 2. Gerätezuordnung für dm-snapshot
Komprimierte Schnappschüsse
Da in Android 12 und höher der Speicherplatzbedarf auf der /data
Partition hoch sein kann, können Sie komprimierte Snapshots in Ihrem Build aktivieren, um den höheren Speicherplatzbedarf der /data
Partition zu decken.
Virtuelle A/B-komprimierte Snapshots basieren auf den folgenden Komponenten, die in Android 12 und höher verfügbar sind:
-
dm-user
, ein Kernelmodul ähnlich wie 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 im Kernel integrierte Format für unkomprimierte Snapshots verfügt das COW-Format für die komprimierten Snapshots über abwechselnde Abschnitte mit Metadaten und Daten. Die Metadaten des Originalformats sind nur für Ersetzungsvorgänge zulässig: Ersetzen Sie Block X im Basis-Image durch den Inhalt von Block Y im Snapshot. Das komprimierte COW-Snapshot-Format ist ausdrucksvoller 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 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 ausschließlich 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 Nullvorgängen . Inkrementelle OTA-Updates können zusätzlich Kopiervorgänge beinhalten.
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 empfangen. Jeder Anfrage ist ein Puffer zugeordnet, den der Benutzerbereich entweder füllen (für einen Lesevorgang) oder weitergeben (für einen Schreibvorgang) kann.
Das dm-user
Kernelmodul stellt eine neue, für den Benutzer sichtbare Schnittstelle zum Kernel bereit, 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 snapuserd
Userspace-Komponente 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 Option für komprimierte Snapshots) ist das COW-Gerät eine Rohdatei. Wenn die Komprimierung aktiviert ist, fungiert das COW stattdessen als dm-user
, das mit einer Instanz des snapuserd
Daemons verbunden ist.
Der Kernel verwendet nicht das neue COW-Format. Die snapuserd
Komponente übersetzt also Anfragen zwischen dem Android COW-Format und dem integrierten Format des Kernels:
Abbildung 3. Flussdiagramm von snapuserd als Übersetzer zwischen Android- und Kernel-COW-Formaten
Diese Übersetzung und Dekomprimierung findet nie auf der Festplatte statt. Die snapuserd
Komponente fängt die COW-Lese- und Schreibvorgänge im Kernel ab und implementiert sie mithilfe des Android COW-Formats.
XOR-Komprimierung
Bei Geräten, die mit Android 13 und höher starten, ermöglicht die standardmäßig aktivierte XOR-Komprimierungsfunktion Userspace-Snapshots, um XOR-komprimierte Bytes zwischen alten und neuen Blöcken zu speichern. Wenn bei einem Virtual A/B-Update nur wenige Bytes in einem Block geändert werden, verbraucht das XOR-Komprimierungsspeicherschema weniger Speicherplatz als das Standardspeicherschema, da Snapshots nicht die gesamten 4 KB speichern. Diese Reduzierung der Snapshot-Größe ist möglich, weil 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 aktualisiert werden, muss die XOR-Komprimierung aktiviert sein. Einzelheiten finden Sie unter XOR-Komprimierung .
Virtuelle A/B-Komprimierungsverfahren
Dieser Abschnitt enthält Details zum Virtual A/B-Komprimierungsprozess, der in Android 13 und Android 12 verwendet wird.
Metadaten lesen (Android 12)
Metadaten werden von einem snapuserd
Daemon erstellt. Bei den Metadaten handelt es sich in erster Linie um eine Zuordnung 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 Festplattenausnahme 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- snapshot
Gerät erstellt wird.
Die folgende Abbildung zeigt ein Sequenzdiagramm für den E/A-Pfad für die Metadatenkonstruktion.
Abbildung 4. Sequenzfluss für den E/A-Pfad bei der Metadatenkonstruktion
Zusammenführen (Android 12)
Sobald der Startvorgang abgeschlossen ist, markiert die Update-Engine den Steckplatz als Start erfolgreich und initiiert die Zusammenführung, indem sie das dm-snapshot
Ziel auf das dm-snapshot-merge
Ziel umstellt.
dm-snapshot
durchsucht die Metadaten und initiiert für jede Festplattenausnahme einen Merge-IO. Nachfolgend finden Sie eine allgemeine Übersicht über den Merge-IO-Pfad.
Abbildung 5. Übersicht über den Merge-IO-Pfad
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 ist abgeschlossen.
Device-Mapper-Layering
Bei Geräten, die mit Android 13 und höher gestartet werden, werden die Snapshot- und Snapshot-Merge-Prozesse bei der Virtual A/B-Komprimierung von der snapuserd
Userspace-Komponente ausgeführt. Für Geräte, die auf Android 13 und höher aktualisiert werden, muss diese Funktion aktiviert sein. Einzelheiten finden Sie unter Userspace-Zusammenführung .
Im Folgenden wird der virtuelle A/B-Komprimierungsprozess beschrieben:
- Das Framework mountet die
/system
-Partition von einemdm-verity
-Gerät, 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-Anfrage 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.
Init-Übergänge
Beim Booten mit komprimierten Snapshots muss die Init-Initialisierung der ersten Stufe snapuserd
starten, um Partitionen bereitzustellen. Dies stellt ein Problem dar: Wenn sepolicy
geladen und durchgesetzt wird, wird snapuserd
in den falschen Kontext gestellt und seine Leseanforderungen schlagen fehl, was zu Selinux-Ablehnungen führt.
Um dieses Problem zu beheben, snapuserd
einen Lockstep-Übergang mit init
wie folgt durch:
- In der ersten Stufe startet
init
snapuserd
von der Ramdisk und speichert dort einen offenen Dateideskriptor in einer Umgebungsvariablen. - Init der ersten Stufe schaltet das Root-Dateisystem auf die Systempartition
init
und führt dann die Systemkopie voninit
aus. - Die Systemkopie von
init
liest die kombinierte Sepolicy in einen String. -
Init
ruftmlock()
auf allen ext4-gestützten Seiten auf. Anschließend werden alle Device-Mapper-Tabellen für Snapshot-Geräte deaktiviert undsnapuserd
gestoppt. Danach ist das Lesen von Partitionen verboten, da dies zu einem Deadlock führt. - Unter Verwendung des offenen Deskriptors für die Ramdisk-Kopie von
snapuserd
startetinit
den Daemon mit dem richtigen Selinux-Kontext neu. Gerätezuordnungstabellen für Snapshot-Geräte werden erneut aktiviert. - Init ruft
munlockall()
auf – es ist sicher, IO erneut durchzuführen.
Raumnutzung
Die folgende Tabelle bietet einen Vergleich der Speicherplatznutzung für verschiedene OTA-Mechanismen unter Verwendung der Betriebssystem- und OTA-Größen von Pixel.
Auswirkungen auf die Größe | Nicht-A/B | A/B | Virtuelles A/B | Virtuelles A/B (komprimiert) |
---|---|---|---|---|
Originales Werksbild | 4,5 GB Super (3,8 GB Bild + 700 MB reserviert) 1 | 9 GB Super (3,8 GB + 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, der nach der Anwendung von OTA zurückgegeben wird) | 1,4 GB auf /data | 0 | 3,8 GB 2 auf /data | 2,1 GB 2 auf /data |
Gesamter Speicherplatz, der für die Anwendung von OTA erforderlich ist | 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 Der Speicherplatzbedarf ist bis zum Neustart vorübergehend.
Informationen zur Implementierung von Virtual A/B oder zur Verwendung komprimierter Snapshot-Funktionen finden Sie unter Implementieren von Virtual A/B