Les OEM et les fournisseurs de SoC qui souhaitent implémenter des mises à jour système A/B doivent s'assurer que leur bootloader implémente le HAL boot_control et transmet les paramètres appropriés au kernel.
Implémenter le HAL de contrôle du démarrage
Les bootloaders compatibles avec A/B doivent implémenter le HAL boot_control
à 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 illustrée ci-dessous:

Configurer le noyau
Pour implémenter des mises à jour système A/B:
-
Sélectionnez les séries de correctifs du kernel suivantes (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 kernel 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 de clés 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 convertir le format.pem
en.der
: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 (l'identification de la clé publique est mise en surbrillance).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 sous la forme<public-key-id>
dans la ligne de commande du kernel. 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 la section Compilation.
|
---|---|
Fortement recommandé pour la cible A/B |
|
Impossible de définir pour la cible A/B |
|
Facultatif pour les builds de débogage | PRODUCT_PACKAGES_DEBUG += update_engine_client |
Définir des partitions (emplacements)
Les appareils A/B n'ont pas besoin d'une partition de récupération ni d'une 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 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 autres que A/B, la partition de cache était utilisée pour stocker les packages OTA téléchargés et pour mettre en cache temporairement des blocs lors de l'application des mises à jour. Il n'a jamais été possible de dimensionner correctement la partition de cache: sa taille dépendait des mises à jour que vous souhaitiez appliquer. Le pire des cas est 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 des blocs (car vous écrivez toujours sur une partition qui n'est pas actuellement utilisée), et 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 de la récupération, le bootloader ne peut pas placer l'option skip_initramfs
sur la ligne de commande du noyau.
Pour les mises à jour autres que celles de type 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
exécuté dans l'image système démarrée normalement.
Un mode de récupération est toujours utilisé pour implémenter le rétablissement de la configuration d'usine et le téléchargement parallèle de packages de mise à jour (d'où le nom "recovery"). Le code et les données du mode de récupération sont stockés dans la partition de démarrage standard dans un ramdisk. Pour démarrer dans l'image système, le bootloader indique au noyau d'ignorer le ramdisk (sinon, l'appareil démarre en mode de récupération). Le mode de récupération 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 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 d'installation /vendor
.
Arguments de l'emplacement du noyau
Le suffixe d'emplacement actuel doit être transmis via un nœud d'arborescence d'appareil (/firmware/android/slot_suffix
) spécifique ou via la ligne de commande du kernel androidboot.slot_suffix
ou l'argument bootconfig.
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. Les options disponibles sont les suivantes:
-
--slot SLOT
. Ignorez 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é (cela doit également effacer l'indicateur de non-démarrage de 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" sinon. current-slot
. Renvoie le suffixe d'emplacement à partir duquel le démarrage sera effectué la prochaine fois.-
slot-count
. Renvoie un entier représentant le nombre d'emplacements disponibles. Actuellement, deux emplacements sont acceptés. Cette valeur est donc2
. -
slot-successful:<slot-suffix>
. Renvoie "yes" si l'emplacement donné a été marqué comme démarré avec succès, 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 restantes pour tenter de démarrer l'emplacement donné.
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 des appareils autres qu'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 mise à jour 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 comporte un préfixe commun (par exemple, system
ou boot
) et un suffixe par emplacement (par exemple, _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 de compilation 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 l'emplacement pendant le processus de mise à jour, ce qui entraîne 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 par rapport à la racine du système de fichiers dans la partition système.
Par exemple, usr/bin/postinst
est 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 des applications en arrière-plan, ajoutez ce qui suit à 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
afin qu'il s'exécute comme é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 savoir comment installer les fichiers préoptimisés dans la deuxième partition système inutilisée, consultez la section Installation au premier démarrage des fichiers DEX_PREOPT.