Virtuelle A/B-Tests implementieren

Wenn Sie virtuelles A/B auf einem neuen Gerät implementieren oder ein bereits eingeführtes Gerät nachrüsten möchten, müssen Sie Änderungen am gerätespezifischen Code vornehmen.

Flags erstellen

Geräte, die virtuelle A/B-Updates verwenden, müssen als A/B-Gerät konfiguriert sein und mit dynamischen Partitionen gestartet werden.

Legen Sie für Geräte, die mit virtuellen A/B-Partitionen auf den Markt kommen, fest, dass sie die Geräte-Basiskonfiguration für virtuelle A/B-Partitionen übernehmen:

$(call inherit-product, \
    $(SRC_TARGET_DIR)/product/virtual_ab_ota.mk)

Geräte, die mit Virtual A/B auf den Markt kommen, benötigen nur halb so viel Speicherplatz für BOARD_SUPER_PARTITION_SIZE, da B-Slots nicht mehr im Super-Partition enthalten sind. Das bedeutet, dass BOARD_SUPER_PARTITION_SIZE größer oder gleich sum(Größe der Updategruppen) + Overhead sein muss, was wiederum größer oder gleich sum(Größe der Partitionen) + Overhead sein muss.

Wenn Sie unter Android 13 und höher komprimierte Snapshots mit Virtual A/B aktivieren möchten, übernehmen Sie die folgende Basiskonfiguration:

$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_ramdisk.mk)
$(call inherit-product, \
    $(SRC_TARGET_DIR)/product/virtual_ab_ota/vabc_features.mk)

Dadurch werden Userspace-Snapshots mit Virtual A/B ermöglicht, während eine No-Op-Komprimierungsmethode verwendet wird. Anschließend können Sie die Komprimierungsmethode auf eine der unterstützten Methoden zstd und lz4 konfigurieren. Unter Android 15 kann die Komprimierung noch weiter an die Anforderungen des Geräts angepasst werden. Weitere Informationen finden Sie unter Komprimierung optimieren.

PRODUCT_VIRTUAL_AB_COMPRESSION_METHOD := lz4
PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR := 65536

Wenn Sie unter Android 12 komprimierte Snapshots mit Virtual A/B aktivieren möchten, übernehmen Sie die folgende Basiskonfiguration:

$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_ramdisk.mk)
$(call inherit-product, \
    $(SRC_TARGET_DIR)/product/virtual_ab_ota/compression.mk)

XOR-Komprimierung

Bei Geräten, die auf Android 13 und höher aktualisiert werden, ist die XOR-Komprimierungsfunktion nicht standardmäßig aktiviert. Fügen Sie der Datei .mk des Geräts Folgendes hinzu, um die XOR-Komprimierung zu aktivieren.

PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.compression.xor.enabled=true

Die XOR-Komprimierung ist standardmäßig für Geräte aktiviert, die von android_t_baseline.mk abgeleitet werden.

Zusammenführung von Userspaces

In der modernen Version von Virtual A/B (Android T und höher) erfolgt der Snapshot-Merge-Prozess vollständig im Userspace. Diese Änderung wird durch snapuserd und dm-user ermöglicht. Auf Geräten, die mit Android 13 und höher auf den Markt kommen, ist die Zusammenführung des Nutzerbereichs standardmäßig aktiviert. Bei älteren Geräten, die aktualisiert werden, kann diese Eigenschaft mit Folgendem festgelegt werden:

PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.userspace.snapshots.enabled=true

Boot-Control-HAL

Das Boot Control HAL bietet eine Schnittstelle für OTA-Clients zum Steuern von Boot-Slots. Für Virtual A/B ist ein Upgrade der Nebenversion des Boot Control HAL erforderlich, da zusätzliche APIs benötigt werden, um den Bootloader während des Flashings oder des Zurücksetzens auf die Werkseinstellungen zu schützen. Die aktuelle Version der HAL-Definition finden Sie unter IBootControl.hal und types.hal.

// hardware/interfaces/boot/1.1/types.hal
enum MergeStatus : uint8_t {
    NONE, UNKNOWN, SNAPSHOTTED, MERGING, CANCELLED };

// hardware/interfaces/boot/1.1/IBootControl.hal
package android.hardware.boot@1.1;
interface IBootControl extends @1.0::IBootControl {
    setSnapshotMergeStatus(MergeStatus status)
        generates (bool success);
    getSnapshotMergeStatus()
        generates (MergeStatus status);
}
// Recommended implementation

Return<bool> BootControl::setSnapshotMergeStatus(MergeStatus v) {
    // Write value to persistent storage
    // e.g. misc partition (using libbootloader_message)
    // bootloader rejects wipe when status is SNAPSHOTTED
    // or MERGING
}

Änderungen an der Datei „fstab“

Die Integrität der Metadatenpartition ist für den Bootvorgang von entscheidender Bedeutung, insbesondere direkt nach der Anwendung eines OTA-Updates. Die Metadatenpartition muss also geprüft werden, bevor sie von first_stage_init gemountet wird. Damit das passiert, fügen Sie dem Eintrag für /metadata das Flag check fs_mgr hinzu. Hier ein Beispiel:

/dev/block/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard,sync wait,formattable,first_stage_mount,check

Kernel-Anforderungen

Setzen Sie CONFIG_DM_SNAPSHOT auf true, um Snapshots zu aktivieren.

Für Geräte, die F2FS verwenden, fügen Sie den Kernel-Patch f2fs: export FS_NOCOW_FL flag to user hinzu, um das Anpinnen von Dateien zu korrigieren. Fügen Sie auch den Kernel-Patch f2fs: support aligned pinned file ein.

Virtual A/B basiert auf Funktionen, die in Kernelversion 4.3 hinzugefügt wurden: dem Statusbit overflow in den Zielen snapshot und snapshot-merge. Alle Geräte, die mit Android 9 und höher auf den Markt kommen, sollten bereits die Kernel-Version 4.4 oder höher haben.

Die unterstützte Mindestversion des Kernels für komprimierte Snapshots ist 4.19. Legen Sie CONFIG_DM_USER=m oder CONFIG_DM_USER=y fest. Wenn Sie das Modul verwenden, muss es in der Ramdisk der ersten Phase geladen werden. Fügen Sie dazu die folgende Zeile in die Makefile-Datei des Geräts ein:

BOARD_GENERIC_RAMDISK_KERNEL_MODULES_LOAD := dm-user.ko

Änderungen an Fastboot-Tools

Unter Android 11 werden die folgenden Änderungen am Fastboot-Protokoll vorgenommen:

  • getvar snapshot-update-status: Gibt den Wert zurück, den die Boot-Control-HAL an den Bootloader übermittelt hat:
    • Wenn der Status MERGING ist, muss der Bootloader merging zurückgeben.
    • Wenn der Status SNAPSHOTTED ist, muss der Bootloader snapshotted zurückgeben.
    • Andernfalls muss der Bootloader none zurückgeben.
  • snapshot-update merge: Schließt einen Merge-Vorgang ab und bootet bei Bedarf in den Wiederherstellungsmodus oder in fastbootd. Dieser Befehl ist nur gültig, wenn snapshot-update-status merging ist, und wird nur in fastbootd unterstützt.
  • snapshot-update cancel: Legt den Zusammenführungsstatus des Boot-Control-HAL auf CANCELLED fest. Dieser Befehl ist ungültig, wenn das Gerät gesperrt ist.
  • erase oder wipe: Bei einem erase oder wipe von metadata, userdata oder einer Partition mit dem Zusammenführungsstatus für die Boot-Control-HAL sollte der Snapshot-Zusammenführungsstatus geprüft werden. Wenn der Status MERGING oder SNAPSHOTTED lautet, sollte das Gerät den Vorgang abbrechen.
  • set_active: Bei einem set_active-Befehl, der den aktiven Slot ändert, sollte der Status der Snapshot-Zusammenführung geprüft werden. Wenn der Status MERGING lautet, sollte das Gerät den Vorgang abbrechen. Der Slot kann im Status SNAPSHOTTED sicher geändert werden.

Diese Änderungen sollen verhindern, dass ein Gerät versehentlich nicht mehr gebootet werden kann. Sie können jedoch zu Problemen bei automatisierten Tools führen. Wenn die Befehle als Komponente des Flashings aller Partitionen verwendet werden, z. B. beim Ausführen von fastboot flashall, wird der folgende Ablauf empfohlen:

  1. Abfrage getvar snapshot-update-status.
  2. Wenn merging oder snapshotted, gib snapshot-update cancel aus.
  3. Fahre mit den Schritten zum Flashen fort.

Speicheranforderungen reduzieren

Geräte, denen im Super-Partition keine vollständige A/B-Speicherzuweisung zugewiesen ist und die /data nach Bedarf verwenden möchten, sollten das Blockzuordnungstool verwenden. Das Tool für die Blockzuordnung sorgt für eine konsistente Blockzuweisung zwischen Builds und reduziert unnötige Schreibvorgänge in den Snapshot. Dies ist unter OTA-Größe reduzieren dokumentiert.

OTA-Komprimierungsalgorithmen

OTA-Pakete können für verschiedene Leistungsmesswerte optimiert werden. Android bietet mehrere unterstützte Komprimierungsmethoden (lz4, zstd und none), die Kompromisse zwischen Installationszeit, COW-Speicherplatznutzung, Bootzeit und Snapshot-Zusammenführungszeit aufweisen. Die standardmäßig aktivierte Option für virtuelle A/B-Tests mit Komprimierung ist lz4 compression method.

Komprimierung optimieren

Komprimierungsalgorithmen können mit zwei Methoden weiter angepasst werden: Komprimierungsstufe (die erreichte Komprimierung auf Kosten der Geschwindigkeit) und Komprimierungsfaktor (die maximale komprimierbare Fenstergröße). Die Komprimierungsstufe ist für bestimmte Algorithmen wie zstd verfügbar. Wenn Sie die Stufe ändern, müssen Sie einen Kompromiss zwischen Geschwindigkeit und Komprimierungsverhältnis eingehen. Der Komprimierungsfaktor beschreibt die maximale Komprimierungsfenstergröße, die während der OTA-Installation verwendet wird. Der Standardwert ist 64.000, kann aber durch Anpassen des Build-Parameters PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR überschrieben werden. Unterstützte Komprimierungsfaktoren: 4k, 8k, 16k, 32k, 64k, 128k und 256k.

PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR := 65536

Inkrementelles OTA auf dem Pixel 8 Pro

Installationszeit ohne Post-Install-Phase COW-Speicherplatznutzung Bootzeit nach OTA Zeit für das Zusammenführen von Snapshots
lz4 18 Min. 15 Sek. 2,5 GB 32,7 Sek. 98,6 Sek.
zstd 24 Min. 49 Sek. 2,05 GB 36,3 Sek. 133,2 Sek.
Keine 16 Min. 42 Sek. 4,76 GB 28,7 Sek. 76,6 Sek.

Vollständiges OTA auf dem Pixel 8 Pro

Installationszeit ohne Post-Install-Phase COW-Speicherplatznutzung Bootzeit nach OTA Zeit für das Zusammenführen von Snapshots
lz4 15 Min. 11 Sek. 4,16 GB 17,6 Sek. 82,2 Sek.
zstd 16 Min. 19 Sek. 3,46 GB 21,0 Sek. 106,3 Sek.
Keine 13 Min. 33 Sek. 6,39 GB 18,5 Sek. 92,5 Sek.