Implémenter un test A/B virtuel

Pour implémenter A/B virtuel sur un nouvel appareil ou pour adapter un appareil lancé, vous devez apporter des modifications au code spécifique à l'appareil.

Indicateurs de compilation

Les appareils qui utilisent A/B virtuel doivent être configurés comme des appareils A/B et doivent être lancés avec des partitions dynamiques.

Pour les appareils lancés avec A/B virtuel, configurez-les de manière à hériter de la configuration de base de l'appareil A/B virtuel :

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

Les appareils lancés avec A/B virtuel 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 super. Autrement dit, BOARD_SUPER_PARTITION_SIZE doit être supérieur ou égal à sum(taille des groupes de mise à jour) + surcharge, qui, à son tour, doit être supérieur ou égal à sum(taille des partitions) + surcharge.

Pour Android 13 et versions ultérieures, afin d'activer les instantanés compressés avec A/B virtuel, 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'activer les instantanés de l'espace utilisateur avec A/B virtuel tout en utilisant une méthode de compression no-op. 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 Affiner la compression.

PRODUCT_VIRTUAL_AB_COMPRESSION_METHOD := lz4
PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR := 65536

Pour Android 12, afin d'activer les instantanés compressés avec A/B virtuel, 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 passant à Android 13 et versions ultérieures, la fonctionnalité de compression XOR n'est pas activée par défaut. Pour activer la compression XOR, ajoutez les éléments suivants 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 d'A/B virtuel (Android T et versions ultérieures), le processus de fusion des 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 et versions ultérieures. Pour les appareils plus anciens qui sont mis à niveau, cette propriété peut être définie comme suit :

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

HAL de contrôle de 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. A/B virtuel nécessite une mise à niveau de version mineure du HAL de contrôle de démarrage, car des API supplémentaires sont nécessaires pour s'assurer que le bootloader est protégé lors du flashage ou du retour aux paramètres d'usine. Pour obtenir la dernière version de la définition HAL, consultez IBootControl.hal et 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
}

Modifications apportées à 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. La partition de métadonnées doit donc être vérifiée avant que first_stage_init ne la monte. Pour vous assurer que cela se produit, ajoutez l'option fs_mgr check à l'entrée de /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'option f2fs: export FS_NOCOW_FL dans le patch du noyau utilisateur pour corriger l'épinglage des fichiers. Incluez également le patch du noyau f2fs: support aligned pinned file.

A/B virtuel s'appuie sur des fonctionnalités ajoutées dans la version 4.3 du noyau : le overflow bit d'état dans les cibles snapshot et snapshot-merge. Tous les appareils lancés avec Android 9 et versions ultérieures devraient déjà disposer de la version 4.4 du noyau 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 la première option (un module), le module doit être chargé dans le ramdisk de première étape. Pour ce faire, ajoutez la ligne suivante au fichier Makefile de l'appareil :

BOARD_GENERIC_RAMDISK_KERNEL_MODULES_LOAD := dm-user.ko

Modifications apportées à l'outil Fastboot

Android 11 apporte les modifications suivantes au protocole Fastboot :

  • getvar snapshot-update-status : renvoie la valeur que le HAL de contrôle 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 et démarre 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 de démarrage sur CANCELLED. Cette commande n'est pas valide lorsque l'appareil est verrouillé.
  • erase ou wipe : une commande erase ou wipe de metadata, userdata ou d'une partition contenant l'état de fusion du HAL de contrôle de démarrage doit vérifier l'état de fusion de l'instantané. Si l'état est MERGING ou SNAPSHOTTED, l'appareil doit abandonner l'opération.
  • set_active : une commande set_active qui modifie l'emplacement actif doit vérifier l'état de fusion de l'instantané. Si l'état est MERGING, l'appareil doit abandonner l'opération. L'emplacement peut être modifié en toute sécurité dans l'état SNAPSHOTTED.

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

  1. Interrogez getvar snapshot-update-status.
  2. Si merging ou snapshotted, exécutez snapshot-update cancel.
  3. Passez aux étapes de flashage.

Réduire les exigences de stockage

Il est fortement recommandé aux appareils qui ne disposent pas d'un stockage A/B complet alloué en super et qui prévoient d'utiliser /data si nécessaire d'utiliser l'outil de mappage de blocs. L'outil de mappage de blocs assure la cohérence de l'allocation de blocs 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 des mises à jour OTA.

Algorithmes de compression OTA

Les packages OTA peuvent être ajusté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'utilisation de l'espace COW, le temps de démarrage et le temps de fusion des instantanés. L'option par défaut activée pour A/B virtuel avec compression est la lz4 compression method.

Affinage de la compression

Les algorithmes de compression peuvent être davantage personnalisés à l'aide de deux méthodes : (niveau de compression) (quantité de compression obtenue au détriment de la vitesse) et (facteur de compression) (taille maximale de la fenêtre compressible). Le niveau de compression est disponible pour certains algorithmes tels que zstd, et la modification du niveau entraîne 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 de 64 Ko, mais elle peut être remplacée en personnalisant le paramètre de compilation PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR. Les facteurs de compression compatibles sont 4 Ko, 8 Ko, 16 Ko, 32 Ko, 64 Ko, 128 Ko et 256 Ko.

PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR := 65536

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

Temps d'installation sans phase post-installation Utilisation de l'espace COW Temps de démarrage après la mise à jour OTA Temps de fusion des instantanés
lz4 18 min 15s 2,5 Go 32,7 s 98,6 s
zstd 24 min 49s 2,05 Go 36,3 s 133,2 s
aucun 16 min 42s 4,76 Go 28,7 s 76,6 s

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

Temps d'installation sans phase post-installation Utilisation de l'espace COW Temps de démarrage après la mise à jour OTA Temps de fusion des instantanés
lz4 15 min 11s 4,16 Go 17,6 s 82,2 s
zstd 16 min 19s 3,46 Go 21,0 s 106,3 s
aucun 13 min 33s 6,39 Go 18,5 s 92,5 s