Virtuelle A/B-Tests implementieren

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

Build-Flags

Geräte mit virtuellem A/B-System müssen als A/B-Gerät konfiguriert und mit dynamischen Partitionen gestartet werden.

Legen Sie für Geräte, die mit virtuellem A/B gestartet werden, fest, dass die Basiskonfiguration des virtuellen A/B-Geräts übernommen werden soll:

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

Geräte, die mit virtuellem A/B eingeführt werden, benötigen nur halb so viel Platinenfläche für BOARD_SUPER_PARTITION_SIZE, da B-Slots nicht mehr in Super sind. Das heißt, BOARD_SUPER_PARTITION_SIZE muss größer oder gleich Summe(Größe der Updategruppen) + Overhead sein, die wiederum größer oder gleich Summe(Größe der Partitionen) + Overhead sein muss.

Wenn Sie für Android 13 und höher komprimierte Snapshots mit virtuellem A/B-Verfahren 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 sind Userspace-Snapshots mit Virtual A/B möglich, während eine No-Op-Komprimierungsmethode verwendet wird. Sie können dann die Komprimierungsmethode auf eine der unterstützten Methoden, zstd und lz4, konfigurieren. Unter Android 15 kann die Komprimierung 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 für 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

Auf Geräten, die auf Android 13 oder höher umgestellt werden, ist die XOR-Komprimierungsfunktion standardmäßig nicht aktiviert. Wenn Sie die XOR-Komprimierung aktivieren möchten, fügen Sie der Datei .mk 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 abgeleitet sind.

Zusammenführung des Nutzerbereichs

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

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

HAL für die Bootsteuerung

Die Boot Control HAL bietet eine Schnittstelle für OTA-Clients zum Steuern von Boot-Slots. Für virtuelle A/B-Partitionen ist ein Minor-Version-Upgrade der HAL für die Bootsteuerung erforderlich, da zusätzliche APIs erforderlich sind, um den Bootloader während des Flashens oder 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 Datei „/etc/fstab“

Die Integrität der Metadatenpartition ist für den Bootvorgang unerlässlich, insbesondere direkt nach der Anwendung eines OTA-Updates. Daher muss die Metadatenpartition geprüft werden, bevor first_stage_init sie bereitstellt. Fügen Sie dazu 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

Kernelanforderungen

Wenn Sie Snapshots aktivieren möchten, setzen Sie CONFIG_DM_SNAPSHOT auf true.

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

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

Zum Aktivieren komprimierter Snapshots ist die Kernelversion 4.19 erforderlich. Legen Sie CONFIG_DM_USER=m oder CONFIG_DM_USER=y fest. Bei der ersten Methode (Modul) muss das Modul in das RAM-Disk der ersten Stufe geladen werden. Dazu fügen Sie dem Makefile des Geräts die folgende Zeile hinzu:

BOARD_GENERIC_RAMDISK_KERNEL_MODULES_LOAD := dm-user.ko

Änderungen an den Fastboot-Tools

Mit Android 11 wurden die folgenden Änderungen am Fastboot-Protokoll vorgenommen:

  • getvar snapshot-update-status – Gibt den Wert zurück, den die HAL für die Bootsteuerung an den Bootloader gesendet 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: Führt einen Zusammenführungsvorgang aus und startet bei Bedarf in die Wiederherstellung/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 der HAL für die Bootsteuerung auf CANCELLED fest. Dieser Befehl ist ungültig, wenn das Gerät gesperrt ist.
  • erase oder wipe: Eine erase oder wipe von metadata, userdata oder eine Partition, die den Zusammenführungsstatus für die Boot Control HAL enthält, sollte den Snapshot-Zusammenführungsstatus prüfen. Wenn der Status MERGING oder SNAPSHOTTED lautet, sollte das Gerät den Vorgang abbrechen.
  • set_active: Bei einem set_active-Befehl, mit dem der aktive Slot geändert wird, sollte der Status der Snapshot-Datenzusammenfü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 bootbar ist. Sie können jedoch die Verwendung automatisierter Tools beeinträchtigen. Wenn die Befehle zum Flashen aller Partitionen verwendet werden, z. B. fastboot flashall, wird die folgende Vorgehensweise empfohlen:

  1. Abfrage getvar snapshot-update-status
  2. Wenn merging oder snapshotted, geben Sie snapshot-update cancel ein.
  3. Fahren Sie mit den Schritten zum Flashen fort.

Speicheranforderungen reduzieren

Für Geräte, denen nicht der gesamte A/B-Speicherplatz in super zugewiesen ist und die bei Bedarf /data verwenden sollen, wird dringend empfohlen, das Blockzuordnungstool zu verwenden. Das Blockzuordnungstool sorgt für eine einheitliche Blockzuweisung zwischen Builds, wodurch unnötige Schreibvorgänge auf den Snapshot reduziert werden. Weitere Informationen finden Sie unter Größe der Over-the-air-Aktualisierung reduzieren.

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-Merge-Zeit erfordern. Die standardmäßig für virtuelle AB-Tests mit Komprimierung aktivierte Option ist lz4 compression method.

Komprimierung optimieren

Komprimierungsalgorithmen können mit zwei Methoden weiter angepasst werden: Komprimierungsebene (die Komprimierungsmenge, 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, die bei der OTA-Installation verwendet wird. Standardmäßig ist 64 kB festgelegt. Diese Einstellung kann jedoch überschrieben werden, indem der Build-Parameter PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR angepasst wird. Unterstützte Komprimierungsfaktoren: 4k, 8k, 16k, 32k, 64k, 128k und 256k.

PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR := 65536

Inkrementelle OTA-Updates auf Google Pixel 8 Pro

Installationszeit ohne Phase nach der Installation COW-Speicherplatznutzung Bootzeit nach OTA-Update Zeitpunkt der Snapshot-Zusammenführung
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ändige OTA-Aktualisierung auf Google Pixel 8 Pro

Installationszeit ohne Phase nach der Installation COW-Speicherplatznutzung Bootzeit nach OTA-Update Zeitpunkt der Snapshot-Zusammenführung
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.