Virtuelle A/B-Tests implementieren

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

Build-Flags

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

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

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

Für Geräte, die mit Virtual A/B auf den Markt kommen, ist für BOARD_SUPER_PARTITION_SIZE nur die Hälfte der Boardgröße erforderlich, da sich die B-Slots nicht mehr in der Superpartition befinden. Das bedeutet, dass BOARD_SUPER_PARTITION_SIZE größer oder gleich Summe(Größe der Updategruppen) + Overhead sein muss, was wiederum größer oder gleich Summe(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 aktiviert, 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 weiter an die Geräteanforderungen 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-Komprimierung standardmäßig nicht aktiviert. Wenn Sie die XOR-Komprimierung aktivieren möchten, fügen Sie der .mk-Datei des Geräts Folgendes hinzu:

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 übernommen werden.

Userspace-Zusammenführung

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

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

Boot Control HAL

Die Boot Control HAL bietet eine Schnittstelle für OTA-Clients, um Boot-Slots zu steuern. Für Virtual A/B ist ein Upgrade auf eine Nebenversion der 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 neueste 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 Fstab-Datei

Die Integrität der Metadatenpartition ist für den Bootvorgang von entscheidender Bedeutung, insbesondere direkt nach der Anwendung eines OTA-Updates. Daher muss die Metadatenpartition geprüft werden, bevor sie von first_stage_init gemountet wird. Fügen Sie dazu das check-Flag für fs_mgr dem Eintrag für /metadata 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 die Snapshot-Funktion zu aktivieren.

Fügen Sie für Geräte, die F2FS verwenden, den Kernel-Patch f2fs: export FS_NOCOW_FL in den Nutzer Kernel-Patch ein, 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 Kernel-Version 4.3 hinzugefügt wurden: dem overflow Statusbit in den Zielen snapshot und snapshot-merge. Auf allen Geräten, die mit Android 9 und höher auf den Markt kommen, sollte bereits Kernel-Version 4.4 oder höher installiert sein.

Die unterstützte Mindestversion des Kernels für komprimierte Snapshots ist 4.19. Setzen Sie CONFIG_DM_USER=m oder CONFIG_DM_USER=y. Wenn Sie die erste Option (ein Modul) verwenden, muss das Modul in der Ramdisk der ersten Phase geladen werden. Fügen Sie dazu die folgende Zeile zur Geräte-Makefile hinzu:

BOARD_GENERIC_RAMDISK_KERNEL_MODULES_LOAD := dm-user.ko

Änderungen an den Fastboot-Tools

In Android 11 wurden 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 Zusammenführungsvorgang ab und startet bei Bedarf den Wiederherstellungsmodus oder fastbootd. Dieser Befehl ist nur gültig, wenn snapshot-update-status den Wert merging hat, und wird nur in fastbootd unterstützt.
  • snapshot-update cancel setzt den Zusammenführungsstatus der Boot Control HAL auf CANCELLED. Dieser Befehl ist ungültig, wenn das Gerät gesperrt ist.
  • erase oder wipe: Bei einem erase- oder wipe-Befehl für metadata, userdata oder eine Partition, die den Zusammenführungsstatus für die Boot Control HAL enthält, sollte der Status der Snapshot-Zusammenführung geprüft werden. Wenn der Status MERGING oder SNAPSHOTTED ist, sollte das Gerät den Vorgang abbrechen.
  • set_active : Ein set_active-Befehl, der den aktiven Slot ändert, sollte den Status der Snapshot-Zusammenführung prüfen. Wenn der Status MERGING ist, 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 gestartet werden kann. Sie können jedoch störend für automatisierte Tools sein. Wenn die Befehle als Komponente des Flashings aller Partitionen verwendet werden, z. B. bei der Ausführung von fastboot flashall, empfiehlt sich der folgende Ablauf:

  1. Fragen Sie getvar snapshot-update-status ab.
  2. Wenn der Wert merging oder snapshotted ist, geben Sie snapshot-update cancel aus.
  3. Fahren Sie mit den Schritten zum Flashing fort.

Speicheranforderungen reduzieren

Geräten, denen in der Superpartition nicht der gesamte A/B-Speicher zugewiesen ist und die /data bei Bedarf verwenden möchten, wird dringend empfohlen, das Tool zur Blockzuordnung zu verwenden. Das Tool zur Blockzuordnung sorgt für eine konsistente Blockzuweisung zwischen Builds und reduziert unnötige Schreibvorgänge in den Snapshot. Weitere Informationen finden Sie unter OTA-Größe reduzieren.

OTA-Komprimierungsalgorithmen

OTA-Pakete können für verschiedene Leistungsmesswerte optimiert werden. Android bietet mehrere unterstützte Komprimierungsmethoden (lz4, zstd und none), die unterschiedliche Vor- und Nachteile in Bezug auf Installationszeit, COW-Speicherplatznutzung, Bootzeit und Snapshot-Zusammenführungszeit haben. Die Standardoption für Virtual A/B mit Komprimierung ist die lz4 compression method.

Komprimierung optimieren

Komprimierungsalgorithmen können mit zwei Methoden weiter angepasst werden: (Komprimierungsstufe) (die Menge der Komprimierung, die auf Kosten der Geschwindigkeit erreicht wird) 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 Größe des Komprimierungsfensters, das während der OTA-Installation verwendet wird. Der Standardwert ist 64 KB, kann aber durch Anpassen des Build-Parameters PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR überschrieben werden. Unterstützte Komprimierungsfaktoren sind 4 KB, 8 KB, 16 KB, 32 KB, 64 KB, 128 KB und 256 KB.

PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR := 65536

Inkrementelles OTA auf dem Pixel 8 Pro

Installationszeit ohne PostInstall-Phase COW-Speicherplatznutzung Bootzeit nach OTA Snapshot-Zusammenführungszeit
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 PostInstall-Phase COW-Speicherplatznutzung Bootzeit nach OTA Snapshot-Zusammenführungszeit
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.