Implémenter des tests A/B virtuels

Pour implémenter le test A/B virtuel sur un nouvel appareil ou pour adapter un appareil lancé, vous devez modifier le code spécifique à l'appareil.

Indicateurs de compilation

Les appareils qui utilisent le test A/B virtuel doivent être configurés en tant qu'appareil A/B et doivent démarrer avec des partitions dynamiques.

Pour les appareils lancés avec le déploiement A/B virtuel, définissez-les pour qu'ils héritent de la configuration de base de l'appareil A/B virtuel:

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

Les appareils qui se lancent avec A/B virtuels n'ont besoin que de la moitié de la taille de la carte pour BOARD_SUPER_PARTITION_SIZE, car les emplacements B ne sont plus en mode super. Autrement dit, BOARD_SUPER_PARTITION_SIZE doit être supérieur ou égal à somme(taille des groupes de mises à jour) + dépassement, qui, à son tour, doit être supérieur ou égal à somme(taille des partitions) + dépassement.

Pour Android 13 et versions ultérieures, pour activer les instantanés compressés avec Virtual A/B, héritez de la configuration de base suivante:

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

Cela permet d'utiliser des instantanés de l'espace utilisateur avec Virtual A/B tout en utilisant une méthode de compression sans opération. Vous pouvez ensuite configurer la méthode de compression sur l'une des méthodes compatibles,zstd et lz4. Pour Android 15, la compression peut être davantage personnalisée pour répondre aux besoins de l'appareil. Pour en savoir plus, consultez la section Ajuster la compression.

PRODUCT_VIRTUAL_AB_COMPRESSION_METHOD := lz4
PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR := 65536

Pour Android 12, pour activer les instantanés compressés avec l'A/B virtuelle, héritez de la configuration de base suivante:

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

Compression XOR

Pour les appareils qui passent à Android 13 ou version ultérieure, la fonctionnalité de compression XOR n'est pas activée par défaut. Pour activer la compression XOR, ajoutez ce qui suit au fichier .mk de l'appareil.

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

La compression XOR est activée par défaut pour les appareils qui héritent de android_t_baseline.mk.

Fusion de l'espace utilisateur

Dans la version moderne de Virtual A/B (Android T et versions ultérieures), le processus de fusion d'instantanés se déroule entièrement dans l'espace utilisateur. Cette modification est rendue possible par snapuserd et dm-user. La fusion de l'espace utilisateur est activée par défaut pour les appareils lancés avec Android 13 ou version ultérieure. Pour les appareils plus anciens qui effectuent une mise à niveau, cette propriété peut être définie comme suit:

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

HAL de contrôle du démarrage

Le HAL de contrôle de démarrage fournit une interface permettant aux clients OTA de contrôler les emplacements de démarrage. L'A/B virtuel nécessite une mise à niveau mineure du HAL de contrôle de démarrage, car des API supplémentaires sont nécessaires pour garantir que le bootloader est protégé lors du flash ou du rétablissement de la configuration d'usine. Consultez IBootControl.hal et types.hal pour obtenir la dernière version de la définition 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
}

Modifications fstab

L'intégrité de la partition de métadonnées est essentielle au processus de démarrage, en particulier juste après l'application d'une mise à jour OTA. Par conséquent, la partition de métadonnées doit être vérifiée avant que first_stage_init ne la monte. Pour vous en assurer, ajoutez l'indicateur fs_mgr check à l'entrée pour /metadata. Voici un exemple:

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

Exigences du noyau

Pour activer la création d'instantanés, définissez CONFIG_DM_SNAPSHOT sur true.

Pour les appareils utilisant F2FS, incluez l'indicateur f2fs: export FS_NOCOW_FL vers le correctif du noyau de l'utilisateur pour corriger l'épinglage de fichiers. Incluez également le correctif de noyau f2fs: support aligné sur le fichier épinglé.

Le test A/B virtuel s'appuie sur des fonctionnalités ajoutées dans la version 4.3 du kernel: le bit d'état dépassement dans les cibles snapshot et snapshot-merge. Tous les appareils lancés avec Android 9 ou version ultérieure doivent déjà disposer de la version 4.4 du kernel ou d'une version ultérieure.

Pour activer les instantanés compressés, la version minimale du noyau compatible est la version 4.19. Définissez CONFIG_DM_USER=m ou CONFIG_DM_USER=y. Si vous utilisez l'ancien (un module), il doit être chargé dans le ramdisk de première étape. Pour ce faire, ajoutez la ligne suivante au Makefile de l'appareil:

BOARD_GENERIC_RAMDISK_KERNEL_MODULES_LOAD := dm-user.ko

Modifications apportées aux outils Fastboot

Android 11 apporte les modifications suivantes au protocole fastboot:

  • getvar snapshot-update-status : renvoie la valeur que le HAL de la commande de démarrage a communiquée au bootloader :
    • Si l'état est MERGING, le bootloader doit renvoyer merging.
    • Si l'état est SNAPSHOTTED, le bootloader doit renvoyer snapshotted.
    • Sinon, le bootloader doit renvoyer none.
  • snapshot-update merge : termine une opération de fusion, en démarrant en mode récupération/fastbootd si nécessaire. Cette commande n'est valide que si snapshot-update-status est merging et n'est compatible qu'avec fastbootd.
  • snapshot-update cancel : définit l'état de fusion du HAL de contrôle du démarrage sur CANCELLED. Cette commande n'est pas valide lorsque l'appareil est verrouillé.
  • erase ou wipe : un erase ou wipe de metadata, userdata ou d'une partition contenant l'état de fusion pour le HAL de contrôle du démarrage doit vérifier l'état de fusion de l'instantané. Si l'état est MERGING ou SNAPSHOTTED, l'appareil doit interrompre l'opération.
  • set_active : une commande set_active qui modifie l'emplacement actif doit vérifier l'état de la fusion d'instantanés. Si l'état est MERGING, l'appareil doit interrompre l'opération. L'emplacement peut être modifié en toute sécurité à l'état SNAPSHOTTED.

Ces modifications sont conçues pour empêcher de rendre accidentellement un appareil non amorçable, mais elles peuvent perturber les outils automatisés. Lorsque les commandes sont utilisées comme composant du flashage de toutes les partitions, comme l'exécution de fastboot flashall, il est recommandé d'utiliser le flux suivant:

  1. Requête getvar snapshot-update-status.
  2. Si la valeur est merging ou snapshotted, émettez snapshot-update cancel.
  3. Suivez les étapes de clignotement.

Réduire les besoins de stockage

Nous vous recommandons vivement d'utiliser l'outil de mappage de blocs pour les appareils qui ne disposent pas d'un espace de stockage A/B complet alloué dans Super et qui s'attendent à utiliser /data si nécessaire. L'outil de mappage de blocs maintient l'allocation de blocs cohérente entre les builds, ce qui réduit les écritures inutiles dans l'instantané. Cette opération est décrite dans la section Réduire la taille de l'OTA.

Algorithmes de compression OTA

Les packages OTA peuvent être configurés pour différentes métriques de performances. Android fournit plusieurs méthodes de compression compatibles (lz4, zstd et none) qui présentent des compromis entre le temps d'installation, l'espace d'utilisation de la mémoire de page de copie, le temps de démarrage et le temps de fusion des instantanés. L'option par défaut activée pour l'AB virtuel avec compression est lz4 compression method.

Affiner la compression

Les algorithmes de compression peuvent être personnalisés de deux manières : (niveau de compression) (quantité de compression obtenue au détriment de la vitesse) et (facteur de compression) (taille maximale de la fenêtre compressable). Le niveau de compression est disponible pour certains algorithmes tels que zstd. Modifier le niveau implique un compromis entre la vitesse et le taux de compression. Le facteur de compression décrit la taille maximale de la fenêtre de compression utilisée lors de l'installation OTA. La valeur par défaut est définie sur 64 ko, mais elle peut être remplacée en personnalisant le paramètre de compilation PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR. Facteurs de compression compatibles : 4 k, 8 k, 16 k, 32 k, 64 k, 128 k et 256 k.

PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR := 65536

Mise à jour OTA incrémentielle sur le Pixel 8 Pro

Durée d'installation sans phase post-installation Utilisation de l'espace COW Après le démarrage OTA Heure de fusion des instantanés
LZ4 18 min 15 s 2,5 Go 32,7 s 98,6 s
zstd 24 min 49 s 2,05 Go 36,3 s 133,2 s
none 16 min 42 s 4,76 Go 28,7 s 76,6 s

Mise à jour OTA complète sur le Pixel 8 Pro

Durée d'installation sans phase post-installation Utilisation de l'espace COW Après le démarrage OTA Heure de fusion des instantanés
lz4 15 min 11 s 4,16 Go 17,6 s 82,2 s
zstd 16 min 19 s 3,46 Go 21,0 s 106,3 s
none 13 min 33 s 6,39 Go 18,5 s 92,5 s