Bonjour. Chez SberDevices, notre équipe est engagée dans le développement de divers matériels et micrologiciels pour eux basés sur AOSP.
À partir d'Android 8 (certains fournisseurs de la version 7.1), le système dispose d'un nouveau mécanisme de mise à jour OTA, le soi-disant. Mises à jour transparentes A / B OTA - mises à jour transparentes. Dans cet article, je décrirai les principes généraux de son fonctionnement, examinerai le mécanisme du point de vue du développeur et le comparerai également avec l'ancienne approche (nous l'appellerons basée sur la récupération) pour appliquer les mises à jour. Tout ce qui suit ne sera vrai que pour l'AOSP pur, puisque l'implémentation spécifique dépend du fournisseur.
OTA basé sur la récupération
Les mises à jour pour Android sont fournies sous la forme d'une archive zip avec des mises à jour basées sur des blocs. À l'époque de KitKat, il s'agissait simplement d'un ensemble de fichiers copiés sur l'appareil par le script inclus. Je ne m'attarderai pas sur ce mode en détail, je décrirai brièvement les principes de base de son fonctionnement:
- l'archive zip est téléchargée par le système sur l'appareil;
- le système redémarre en mode de récupération ;
- vérifier la compatibilité de la mise à jour avec l'appareil, sa signature;
- si tout va bien, le script de mise à jour de l'archive zip est exécuté ;
- lors de la mise à jour, l'appareil peut redémarrer plusieurs fois (par exemple, pour mettre à jour l' arborescence des appareils );
- si tout s'est bien passé, lancez le nouveau firmware.
Quels sont les inconvénients de ce schéma?
- La nécessité de réserver une quantité suffisante de mémoire interne pour l'archive OTA. La section / cache est utilisée pour cela . Certains fournisseurs utilisent / data , mais c'est rare. En conséquence, l'utilisateur se retrouve avec moins d'espace (oui, les applications peuvent toujours utiliser de l'espace dans la partition / cache , mais avec certaines restrictions).
- Le redémarrage et l'application de la mise à jour prennent du temps, ce qui peut être critique pour certains types d'appareils, par exemple pour les téléviseurs intelligents.
- L'interruption du processus de mise à jour peut entraîner une boucle de démarrage .
- Il n'y a aucun moyen de revenir à l'ancienne version du micrologiciel.
Cet inconvénient vous permet de contourner la méthode de mise à niveau transparente. Voyons voir comment ça fonctionne.
OTA A / B sans couture
Composants et mécanismes clés nécessaires pour mettre en œuvre des mises à jour A / B transparentes :
- balisage de l'emplacement de la mémoire flash;
- interaction avec le chargeur, gestion de l'état des slots ;
- démon système update_engine ;
- générer une archive zip avec une mise à jour. Cet aspect ne sera pas pris en compte dans cet article.
Machines à sous
Le principe de base de A / B OTA est le crénage . Toutes les partitions qui doivent être mises à jour (il peut s'agir de n'importe quelle partition, pas seulement de partition système) doivent être en deux copies ou, sinon, dans des emplacements. La mise en oeuvre prend en charge les applications 2 emplacements, qui sont nommées A et B, respectivement . Le système démarre et fonctionne à partir de l'emplacement actuel, le second n'est utilisé qu'au moment de la mise à jour. Un suffixe avec le nom de l'emplacement est ajouté au nom de la section.
Vous trouverez ci-dessous un tableau comparant les deux options d'organisation des partitions sur un périphérique. Toutes les partitions à fente sont marquées avec l'option de montage slotselect afin que le système puisse sélectionner le bon logement. Selon l'endroit où ils sont décrits, cela pourrait être fstab
ou dts .
Modifications de la table de partition
- Le cache B / n'est plus nécessaire. Maintenant, la mise à jour peut être enregistrée soit dans / data , soit immédiatement flashée dans un emplacement inactif (plus d'informations ci-dessous).
- La section de récupération n'est également plus utilisée. Cependant, le mode de récupération existe toujours, il est nécessaire, par exemple, de réinitialiser l'appareil aux paramètres d'usine (cela peut conduire à une équipe de secours ). Ou pour le soi-disant. mise à jour manuelle ( sideload ) via adb . Le disque de récupération est maintenant à l'intérieur de la partition de démarrage , le noyau est partagé.
- (android/recovery) cmdline ‑ skip_initramfs.
À première vue, il semble qu'un tel schéma ne soit pas optimal, car il est nécessaire d'allouer deux fois plus d'espace au système. Mais nous nous sommes débarrassés de / cache , ce qui signifie que nous avons déjà économisé beaucoup de mémoire. Ainsi, le système prendra un peu plus que l'option de récupération .
Le principal avantage des mises à jour A / B est la possibilité de diffuser le firmware. C'est elle qui assure des mises à jour fluides et transparentes pour l'utilisateur: pour mettre à jour l'appareil, il suffit de redémarrer dans un nouveau slot. Dans ce mode, il n'est pas nécessaire de télécharger l'archive zip à l'avance, occupant de l'espace dans / data . Au lieu de cela, le système écrit immédiatement des blocs de données à partir d'un fichier spécialement préparé ( payload, voir ci-dessous) dans chaque section d'un emplacement inactif. Du point de vue de la mise en œuvre, cela ne fait aucune différence que nous téléchargions la mise à jour à l'avance ou que nous la diffusions immédiatement sur l'emplacement.
Les emplacements ont les états suivants:
- actif - emplacement actif, le système en sera chargé au prochain redémarrage;
- amorçable - la mise à jour a été flashée avec succès dans l'emplacement, a été validée, les sommes de hachage correspondent, etc.
- réussi - le système a pu démarrer avec succès dans le nouvel emplacement;
- non amorçable - l'emplacement est endommagé. Le système marque toujours l'emplacement comme non amorçable avant de démarrer le processus de mise à niveau.
Les deux emplacements peuvent être amorçables et réussis , mais un seul est actif .
L'algorithme du bootloader lors du choix d'un slot:
- Le chargeur de démarrage détecte qu'il existe un ou plusieurs emplacements de démarrage .
- L'emplacement actif (ou l'emplacement avec la priorité la plus élevée) est sélectionné parmi eux.
- Si le système démarre correctement, l'emplacement est marqué comme réussi et actif .
- Sinon, l'emplacement est marqué comme non amorçable et le système redémarre.
Modification des états des logements pendant la mise à jour:
Prérequis pour Seamless A / B.
boot_control
Pour prendre en charge les mises à jour A / B, le fournisseur doit implémenter une interface HAL spéciale - boot_control . Il vous permet de changer les états des slots et d'obtenir des informations à leur sujet. Pour le travail externe (par exemple, via adb shell ), l'utilitaire est utilisé - bootctl . L'interface est utilisée comme moyen de communication entre le système d'exploitation et le chargeur de démarrage.
update_engine
Le composant principal de l' ensemble du circuit A / B. Gère le téléchargement, la diffusion en continu des mises à jour, la vérification des signatures, etc. Modifie les états des emplacements via boot_control . Vous permet de contrôler le processus de mise à jour de l'appareil: pause, reprise, annulation.
Le composant est arrivé à Android à partir de ChromeOS, où il est utilisé depuis un certain temps. AOSP maintient update_engine en tant qu'assemblage statique de chargement latéral . C'est ce qui est utilisé dans la récupération , car ce mode ne prend pas en charge la liaison dynamique.
Le processus de ce composant peut être divisé en les étapes suivantes:
- chargement de la mise à jour dans l'emplacement. Vous pouvez télécharger les deux à partir d'un package précédemment téléchargé avec une mise à jour, ou directement sur Internet via http / https. Lors du téléchargement, la signature est vérifiée, la clé publique est déjà sur l'appareil (/system/etc/update_engine/update-payload-key.pub.pem);
- vérification de la mise à jour téléchargée et comparaison des sommes de hachage;
- exécution de scripts post-installation .
Structure du Service Pack:
2009-01-01 00:00:00 ..... 360 360 META-INF/com/android/metadata
2009-01-01 00:00:00 ..... 107 107 care_map.txt
2009-01-01 00:00:00 ..... 384690699 384690699 payload.bin
2009-01-01 00:00:00 ..... 154 154 payload_properties.txt
2009-01-01 00:00:00 ..... 1675 943 META-INF/com/android/otacert
- care_map.txt - utilisé par update_verifier (voir ci-dessous);
- payload_properties.txt - contient des hachages et des tailles de données dans la charge utile ;
- payload.bin - package de mise à jour, contient des blocs de toutes les sections, métadonnées , signature.
update_engine_client
Client de gestion du démon update_engine . Peut être appelé directement par le fournisseur pour appliquer la mise à jour.
update_verifier
Utilitaire pour vérifier l'intégrité du système au premier démarrage (emplacement avec le drapeau actif , mais pas encore réussi ). Le contrôle d'intégrité est implémenté à l'aide du module noyau dm-verity . Si la vérification réussit, l'utilitaire marque l'emplacement actuel comme réussi . Sinon, le système redémarrera dans l'ancien emplacement. Seuls les blocs spécifiés dans le fichier care_map.txt sont vérifiés .
UpdateEngineApi
Il existe une API Java pour la mise en œuvre des services de mise à jour des fournisseurs . Il existe également un exemple d' une telle implémentation de service.
Regardons un exemple de mise à jour A / B dans AOSP. Pour ce faire, éditez le Makefile de la plateforme cible:
# A/B
AB_OTA_UPDATER := true
# :
AB_OTA_PARTITIONS := boot system vendor
#
PRODUCT_PACKAGES := update_engine update_engine_client update_verifier
# recovery
TARGET_NO_RECOVERY := true
#, cache:
#BOARD_CACHEIMAGE_PARTITION_SIZE := ...
#BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE := ...
Après avoir appelé make otapackage, nous obtenons une archive zip avec la mise à jour. Sous cette forme, il est déjà adapté au mode sideload . Nous pouvons redémarrer dans la récupération et appeler adb sideload ota.zip . Cette méthode est pratique pour le débogage.
L'application d'une mise à jour à partir d'un système de production est généralement spécifique au fournisseur. Le moyen le plus simple est de télécharger payload.bin sur un serveur http et d'appeler directement update_engine_client .
Exemple d'appel:
update_engine_client \
--payload=http://path/to/payload.bin \
--update \
--headers=" \
FILE_HASH=ozGgyQEddkI5Zax+Wbjo6I/PCR8PEZka9gGd0nWa+oY= \
FILE_SIZE=282344983 \
METADATA_HASH=GLIKfE6KRwylWMHsNadG/Q8iy5f786WTatvMdBlpOPg= \
METADATA_SIZE=26723"
Le contenu du fichier payload_properties.txt est passé au paramètre headers . Dans logcat, vous pouvez voir la progression de la mise à jour. Si vous passez le commutateur --follow , la progression sera dupliquée dans stdout .
Conclusion
Les avantages du nouveau mécanisme de mise à jour sont évidents:
- la mise à jour du système s'effectue en arrière-plan sans interrompre le travail de l'utilisateur. Oui, vous aurez toujours besoin d'un redémarrage (vers un nouvel emplacement), mais ce sera beaucoup plus rapide que le redémarrage en cours de récupération pour appliquer la mise à jour;
- la probabilité d'une boucle de démarrage est minimisée (personne n'est à l'abri des erreurs de mise en œuvre). Le processus de mise à jour peut être interrompu, cela n'affectera en aucun cas le slot actif;
- il devient possible de revenir à la version précédente du micrologiciel. Même si pour une raison quelconque la mise à jour a échoué, le système retournera simplement à l'ancienne version;
- grâce au streaming, l'appareil se mettra à jour plus rapidement;
- selon l'implémentation, vous pouvez exclure complètement l'utilisateur du processus de mise à jour.
Parmi les inconvénients, je soulignerais deux points:
- A / B OTA devient dépendant de la disposition actuelle du disque, car la mise à jour se produit pendant que le système est en cours d'exécution. Autrement dit, il devient impossible de lancer la mise à jour avec les partitions modifiées;
- la complexité relative de la mise en œuvre.
Et pourtant, à mon avis, les avantages l'emportent. À propos, dans notre appareil récemment annoncé , nous utilisons des mises à jour A / B OTA.