Les OEM et les fournisseurs de SoC qui souhaitent implémenter les mises à jour du système A/B doivent s'assurer que leur bootloader implémente le HAL boot_control et transmet les paramètres corrects au noyau.
Implémenter le HAL de contrôle du démarrage
Les bootloaders compatibles avec les tests A/B doivent implémenter le HAL boot_control
à l'adresse hardware/libhardware/include/hardware/boot_control.h
. Vous pouvez tester les implémentations à l'aide de l'utilitaire system/extras/bootctl
et de system/extras/tests/bootloader/
.
Vous devez également implémenter la machine à états ci-dessous :

Configurer le noyau
Pour implémenter les mises à jour système A/B :
-
Sélectionnez la série de correctifs du noyau suivante (si nécessaire) :
- Si vous démarrez sans ramdisk et utilisez "boot as recovery", sélectionnez android-review.googlesource.com/#/c/158491/.
- Pour configurer dm-verity sans ramdisk, sélectionnez android-review.googlesource.com/#/q/status:merged+project:kernel/common+branch:android-3.18+topic:A_B_Changes_3.18.
-
Assurez-vous que les arguments de ligne de commande du noyau contiennent les arguments supplémentaires suivants :
... où la valeurskip_initramfs rootwait ro init=/init root="/dev/dm-0 dm=system none ro,0 1 android-verity <public-key-id> <path-to-system-partition>"
<public-key-id>
correspond à l'ID de la clé publique utilisée pour valider la signature de la table verity (pour en savoir plus, consultez dm-verity). -
Ajoutez le certificat .X509 contenant la clé publique au trousseau du système :
-
Copiez le certificat .X509 au format
.der
à la racine du répertoirekernel
. Si le certificat .X509 est au format.pem
, utilisez la commandeopenssl
suivante pour le convertir au format.der
:.pem
openssl x509 -in <x509-pem-certificate> -outform der -out <x509-der-certificate>
-
Créez le
zImage
pour inclure le certificat dans le trousseau système. Pour vérifier,consultez l'entréeprocfs
(KEYS_CONFIG_DEBUG_PROC_KEYS
doit être activé) : L'inclusion réussie du certificat .X509 indique la présence de la clé publique dans le trousseau système (la mise en surbrillance indique l'ID de la clé publique).angler:/# cat /proc/keys 1c8a217e I------ 1 perm 1f010000 0 0 asymmetri Android: 7e4333f9bba00adfe0ede979e28ed1920492b40f: X509.RSA 0492b40f [] 2d454e3e I------ 1 perm 1f030000 0 0 keyring .system_keyring: 1/4
-
Remplacez l'espace par
#
et transmettez-le en tant que<public-key-id>
dans la ligne de commande du noyau. Par exemple, transmettezAndroid:#7e4333f9bba00adfe0ede979e28ed1920492b40f
au lieu de<public-key-id>
.
-
Copiez le certificat .X509 au format
Définir des variables de compilation
Les bootloaders compatibles avec A/B doivent répondre aux critères de variable de compilation suivants :
Doit être défini pour la cible A/B |
/device/google/marlin/+/android-7.1.0_r1/device-common.mk . Vous pouvez éventuellement effectuer l'étape dex2oat post-installation (mais avant le redémarrage) décrite dans Compilation.
|
---|---|
Fortement recommandé pour la cible de test A/B |
|
Impossible de définir la cible de test A/B |
|
Facultatif pour les versions de débogage | PRODUCT_PACKAGES_DEBUG += update_engine_client |
Définir des partitions (emplacements)
Les appareils A/B n'ont pas besoin de partition de récupération ni de partition de cache, car Android n'utilise plus ces partitions. La partition de données est désormais utilisée pour le package OTA téléchargé, et le code de l'image de récupération se trouve sur la partition de démarrage. Toutes les partitions testées en A/B doivent être nommées comme suit (les emplacements sont toujours nommés a
, b
, etc.) : boot_a
,
boot_b
, system_a
, system_b
, vendor_a
,
vendor_b
.
Cache
Pour les mises à jour non A/B, la partition de cache était utilisée pour stocker les packages OTA téléchargés et pour stocker temporairement les blocs lors de l'application des mises à jour. Il n'y a jamais eu de bonne façon de dimensionner la partition du cache : sa taille dépendait des mises à jour que vous souhaitiez appliquer. Le pire des cas serait une partition de cache aussi grande que l'image système. Avec les mises à jour A/B, il n'est pas nécessaire de mettre en cache les blocs (car vous écrivez toujours dans une partition qui n'est pas utilisée actuellement). Avec le streaming A/B, il n'est pas nécessaire de télécharger l'intégralité du package OTA avant de l'appliquer.
Récupération
Le disque RAM de récupération est désormais contenu dans le fichier boot.img
. Lors du passage en mode Recovery, le bootloader ne peut pas placer l'option skip_initramfs
sur la ligne de commande du noyau.
Pour les mises à jour non A/B, la partition de récupération contient le code utilisé pour appliquer les mises à jour. Les mises à jour A/B sont appliquées par update_engine
s'exécutant dans l'image système démarrée normale.
Un mode Récupération est toujours utilisé pour implémenter le rétablissement de la configuration d'usine et le transfert de packages de mise à jour (d'où le nom "Récupération"). Le code et les données du mode Recovery sont stockés dans la partition de démarrage habituelle dans un ramdisk. Pour démarrer sur l'image système, le bootloader indique au noyau d'ignorer le ramdisk (sinon, l'appareil démarre en mode Recovery). Le mode Recovery est petit (et une grande partie se trouvait déjà sur la partition de démarrage), de sorte que la taille de la partition de démarrage n'augmente pas.
Fstab
L'argument slotselect
doit se trouver sur la ligne des partitions testées par A/B. Exemple :
<path-to-block-device>/vendor /vendor ext4 ro wait,verify=<path-to-block-device>/metadata,slotselect
Aucune partition ne doit être nommée vendor
. À la place, la partition vendor_a
ou vendor_b
sera sélectionnée et montée sur le point de montage /vendor
.
Arguments de l'emplacement du noyau
Le suffixe de slot actuel doit être transmis via un nœud DT (Device Tree) spécifique (/firmware/android/slot_suffix
) ou via l'argument de ligne de commande ou de bootconfig du noyau androidboot.slot_suffix
.
Par défaut, fastboot flashe l'emplacement actuel sur un appareil A/B. Si le package de mise à jour contient également des images pour l'autre emplacement (non actuel), fastboot flashe également ces images. Voici les options disponibles :
-
--slot SLOT
. Remplacez le comportement par défaut et invitez fastboot à flasher l'emplacement transmis en tant qu'argument. -
--set-active [SLOT]
. Définissez l'emplacement comme actif. Si aucun argument facultatif n'est spécifié, l'emplacement actuel est défini comme actif. fastboot --help
. Obtenez des informations sur les commandes.
Si le bootloader implémente fastboot, il doit prendre en charge la commande set_active <slot>
qui définit l'emplacement actif actuel sur l'emplacement donné (il doit également effacer l'indicateur non amorçable pour cet emplacement et réinitialiser le nombre de tentatives sur les valeurs par défaut). Le bootloader doit également prendre en charge les variables suivantes :
-
has-slot:<partition-base-name-without-suffix>
. Renvoie "yes" si la partition donnée est compatible avec les emplacements, "no" dans le cas contraire. current-slot
: renvoie le suffixe de l'emplacement à partir duquel le démarrage sera effectué ensuite.-
slot-count
. Renvoie un entier représentant le nombre de créneaux disponibles. Actuellement, deux emplacements sont acceptés. La valeur est donc2
. -
slot-successful:<slot-suffix>
. Renvoie "yes" si l'emplacement donné a été marqué comme ayant démarré correctement, ou "no" dans le cas contraire. -
slot-unbootable:<slot-suffix>
. Renvoie "yes" si l'emplacement donné est marqué comme non amorçable, ou "no" dans le cas contraire. -
slot-retry-count:<slot-suffix>
. Nombre de tentatives de démarrage de l'emplacement donné restantes.
Pour afficher toutes les variables, exécutez fastboot getvar all
.
Générer des packages OTA
Les outils de package OTA suivent les mêmes commandes que celles pour les appareils non A/B. Le fichier target_files.zip
doit être généré en définissant les variables de compilation pour la cible A/B. Les outils de package OTA identifient et génèrent automatiquement des packages au format de l'outil de mise à jour A/B.
Exemples :
-
Pour générer une OTA complète :
./build/make/tools/releasetools/ota_from_target_files \ dist_output/tardis-target_files.zip \ ota_update.zip
-
Pour générer une mise à jour OTA incrémentielle :
./build/make/tools/releasetools/ota_from_target_files \ -i PREVIOUS-tardis-target_files.zip \ dist_output/tardis-target_files.zip \ incremental_ota_update.zip
Configurer des partitions
update_engine
peut mettre à jour n'importe quelle paire de partitions A/B définies sur le même disque.
Une paire de partitions possède un préfixe commun (tel que system
ou boot
) et un suffixe par emplacement (tel que _a
). La liste des partitions pour lesquelles le générateur de charge utile définit une mise à jour est configurée par la variable make AB_OTA_PARTITIONS
.
Par exemple, si une paire de partitions bootloader_a
et booloader_b
est incluse (_a
et _b
sont les suffixes d'emplacement), vous pouvez mettre à jour ces partitions en spécifiant les éléments suivants dans la configuration du produit ou de la carte :
AB_OTA_PARTITIONS := \ boot \ system \ bootloader
Toutes les partitions mises à jour par update_engine
ne doivent pas être modifiées par le reste du système. Lors des mises à jour incrémentielles ou delta, les données binaires de l'emplacement actuel sont utilisées pour générer les données du nouvel emplacement. Toute modification peut entraîner l'échec de la validation des nouvelles données de créneau lors du processus de mise à jour, et donc l'échec de la mise à jour.
Configurer la post-installation
Vous pouvez configurer l'étape post-installation différemment pour chaque partition mise à jour à l'aide d'un ensemble de paires clé/valeur. Pour exécuter un programme situé à /system/usr/bin/postinst
dans une nouvelle image, spécifiez le chemin d'accès relatif à la racine du système de fichiers dans la partition système.
Par exemple, usr/bin/postinst
correspond à system/usr/bin/postinst
(si vous n'utilisez pas de disque RAM). Spécifiez également le type de système de fichiers à transmettre à l'appel système mount(2)
. Ajoutez ce qui suit aux fichiers .mk
du produit ou de l'appareil (le cas échéant) :
AB_OTA_POSTINSTALL_CONFIG += \ RUN_POSTINSTALL_system=true \ POSTINSTALL_PATH_system=usr/bin/postinst \ FILESYSTEM_TYPE_system=ext4
Compiler des applications
Les applications peuvent être compilées en arrière-plan avant le redémarrage avec la nouvelle image système. Pour compiler les applications en arrière-plan, ajoutez les éléments suivants à la configuration de l'appareil du produit (dans le fichier device.mk du produit) :
-
Incluez les composants natifs dans la compilation pour vous assurer que le script de compilation et les binaires sont compilés et inclus dans l'image système.
# A/B OTA dexopt package PRODUCT_PACKAGES += otapreopt_script
-
Connectez le script de compilation à
update_engine
pour qu'il s'exécute en tant qu'étape post-installation.# A/B OTA dexopt update_engine hookup AB_OTA_POSTINSTALL_CONFIG += \ RUN_POSTINSTALL_system=true \ POSTINSTALL_PATH_system=system/bin/otapreopt_script \ FILESYSTEM_TYPE_system=ext4 \ POSTINSTALL_OPTIONAL_system=true
Pour obtenir de l'aide concernant l'installation des fichiers préoptimisés dans la deuxième partition système inutilisée, consultez Installation des fichiers DEX_PREOPT au premier démarrage.