Questions fréquentes

Google a-t-il utilisé des mises à jour OTA A/B sur des appareils ?

Oui. Le nom marketing des mises à jour A/B est mises à jour continues. Les téléphones Pixel et Pixel XL sortis en octobre 2016 étaient fournis avec A/B, et tous les Chromebooks utilisent la même implémentation update_engine d'A/B. L'implémentation du code de plate-forme nécessaire est publique dans Android 7.1 et versions ultérieures.

Pourquoi les OTA de type A/B sont-elles plus efficaces ?

Les mises à jour OTA A/B offrent une meilleure expérience utilisateur. Les mesures issues des mises à jour de sécurité mensuelles montrent que cette fonctionnalité a déjà fait ses preuves : en mai 2017, 95 % des propriétaires de Pixel utilisaient la dernière mise à jour de sécurité après un mois, contre 87 % des utilisateurs de Nexus. De plus, les utilisateurs de Pixel effectuent les mises à jour plus rapidement que les utilisateurs de Nexus. Les échecs de mise à jour des blocs lors d'une mise à jour OTA n'entraînent plus le blocage du démarrage de l'appareil. Tant que la nouvelle image système n'a pas démarré correctement, Android conserve la possibilité de revenir à l'image système fonctionnelle précédente.

Qu'est-ce que system_other ?

Les applications sont stockées dans des fichiers .apk, qui sont en fait des archives ZIP. Chaque fichier .apk contient un ou plusieurs fichiers .dex contenant du bytecode Dalvik portable. Un fichier .odex (fichier .dex optimisé) est distinct du fichier .apk et peut contenir du code machine spécifique à l'appareil. Si un fichier .odex est disponible, Android peut exécuter les applications à des vitesses de compilation AOT (Ahead-Of-Time) sans avoir à attendre que le code soit compilé à chaque lancement de l'application. Un fichier .odex n'est pas strictement nécessaire : Android peut en fait exécuter le code .dex directement via l'interprétation ou la compilation Just-In-Time (JIT), mais un fichier .odex offre la meilleure combinaison de vitesse de lancement et de vitesse d'exécution si de l'espace est disponible.

Exemple : Pour le fichier installed-files.txt d'un Nexus 6P exécutant Android 7.1 avec une taille totale de l'image système de 2 628 Mio (2 755 792 836 octets), la répartition des principaux contributeurs à la taille globale de l'image système par type de fichier est la suivante :

.odex 1 391 770 312 octets 50,5 %
.apk 846878259 octets 30,7 %
.so (code C/C++ natif) 202162479 octets 7,3 %
Fichiers .oat/Images .art 163 892 188 octets 5,9 %
Polices 38 952 361 octets 1,4 %
Données de paramètres régionaux ICU 27 468 687 octets 0,9 %

Ces chiffres sont similaires pour les autres appareils. Ainsi, sur les appareils Nexus/Pixel, les fichiers .odex occupent environ la moitié de la partition système. Cela signifiait que nous pouvions continuer à utiliser ext4, mais écrire les fichiers .odex dans la partition B en usine, puis les copier dans /data au premier démarrage. L'espace de stockage réellement utilisé avec ext4 A/B est identique à celui utilisé avec SquashFS A/B, car si nous avions utilisé SquashFS, nous aurions fourni les fichiers .odex préoptimisés sur system_a au lieu de system_b.

Si je copie des fichiers .odex dans /data, l'espace libéré dans /system est-il perdu dans /data ?

Pas exactement. Sur Pixel, la plupart de l'espace occupé par les fichiers .odex est destiné aux applications, qui se trouvent généralement sur /data. Ces applications reçoivent les mises à jour de Google Play. Les fichiers .apk et .odex de l'image système ne sont donc pas utilisés pendant la majeure partie de la durée de vie de l'appareil. Ces fichiers peuvent être entièrement exclus et remplacés par de petits fichiers .odex basés sur le profil lorsque l'utilisateur utilise réellement chaque application (ce qui ne nécessite aucun espace pour les applications que l'utilisateur n'utilise pas). Pour en savoir plus, consultez la présentation Google I/O 2016 The Evolution of Art.

La comparaison est difficile pour plusieurs raisons clés :

  • Les fichiers .odex des applications mises à jour par Google Play ont toujours été placés dans /data dès leur première mise à jour.
  • Les applications que l'utilisateur n'exécute pas n'ont pas besoin de fichier .odex.
  • La compilation axée sur le profil génère des fichiers .odex plus petits que la compilation anticipée (car la première n'optimise que le code essentiel aux performances).

Pour en savoir plus sur les options de réglage disponibles pour les OEM, consultez Configurer ART.

N'y a-t-il pas deux copies des fichiers .odex sur /data ?

C'est un peu plus compliqué… Une fois la nouvelle image système écrite, la nouvelle version de dex2oat est exécutée sur les nouveaux fichiers .dex pour générer les nouveaux fichiers .odex. Cela se produit alors que l'ancien système est toujours en cours d'exécution. Les anciens et les nouveaux fichiers .odex se trouvent donc tous les deux sur /data en même temps.

Le code dans OtaDexoptService (frameworks/base/+/android16-release/services/core/java/com/android/server/pm/OtaDexoptService.java) appelle getAvailableSpace avant d'optimiser chaque package pour éviter le surremplissage /data. Notez que la valeur disponible ici reste prudente : il s'agit de l'espace restant avant d'atteindre le seuil habituel de manque d'espace du système (mesuré à la fois en pourcentage et en nombre d'octets). Ainsi, si /data est plein, il n'y aura pas deux copies de chaque fichier .odex. Le même code comporte également un BULK_DELETE_THRESHOLD : si l'appareil est sur le point de remplir l'espace disponible (comme décrit ci-dessus), les fichiers .odex appartenant aux applications qui ne sont pas utilisées sont supprimés. Il s'agit d'un autre cas où il n'y a pas deux copies de chaque fichier .odex.

Dans le pire des cas, lorsque /data est complètement plein, la mise à jour attend que l'appareil ait redémarré dans le nouveau système et n'ait plus besoin des fichiers .odex de l'ancien système. Le PackageManager gère cette opération : (frameworks/base/+/android16-release/services/core/java/com/android/server/pm/PackageManagerService.java#7215). Une fois que le nouveau système a démarré avec succès, installd (frameworks/native/+/android16-release/cmds/installd/dexopt.cpp#2422) peut supprimer les fichiers .odex utilisés par l'ancien système, ce qui permet de rétablir l'état stable où il n'y a qu'une seule copie.

Il est donc possible que /data contienne deux copies de tous les fichiers .odex, mais (a) cette situation est temporaire et (b) ne se produit que si vous disposiez déjà de beaucoup d'espace libre sur /data. Sauf lors d'une mise à jour, il n'y a qu'une seule copie. De plus, dans le cadre des fonctionnalités de robustesse générale d'ART, il ne remplira jamais /data avec des fichiers .odex (car cela poserait également problème sur un système non A/B).

Toutes ces opérations d'écriture/copie n'augmentent-elles pas l'usure de la mémoire flash ?

Seule une petite partie de la mémoire flash est réécrite : une mise à jour complète du système Pixel écrit environ 2,3 Gio. (Les applications sont également recompilées, mais cela vaut aussi pour les applications non A/B.) Traditionnellement, les mises à jour OTA complètes basées sur des blocs écrivaient une quantité de données similaire, de sorte que les taux d'usure du flash devraient être similaires.

Le temps de flashage d'usine est-il plus long si je flashe deux partitions système ?

Non. La taille de l'image système du Pixel n'a pas augmenté (l'espace a simplement été divisé en deux partitions).

Le fait de conserver les fichiers .odex sur B ralentit-il le redémarrage après le rétablissement de la configuration d'usine ?

Oui. Si vous avez réellement utilisé un appareil, effectué une mise à jour OTA et rétabli la configuration d'usine, le premier redémarrage sera plus lent que d'habitude (1 min 40 s contre 40 s sur un Pixel XL), car les fichiers .odex auront été perdus de B après la première mise à jour OTA et ne pourront donc pas être copiés dans /data. C'est le compromis.

La réinitialisation des données d'usine devrait être une opération rare par rapport au démarrage normal. Le temps nécessaire est donc moins important. (Cela n'a pas d'incidence sur les utilisateurs ni les réviseurs qui obtiennent leur appareil directement de l'usine, car dans ce cas, la partition B est disponible.) L'utilisation du compilateur JIT signifie que nous n'avons pas besoin de recompiler tout. La situation n'est donc pas aussi mauvaise que vous pourriez le penser. Il est également possible de marquer les applications comme nécessitant une compilation AOT à l'aide de coreApp="true" dans le fichier manifeste (frameworks/base/+/android16-release/packages/SystemUI/AndroidManifest.xml#23). Cette méthode est actuellement utilisée par system_server, car la compilation JIT n'est pas autorisée pour des raisons de sécurité.

Le fait de conserver les fichiers .odex sur /data plutôt que sur /system ralentit-il le redémarrage après une mise à jour OTA ?

Non. Comme expliqué ci-dessus, le nouveau dex2oat est exécuté alors que l'ancienne image système est toujours en cours d'exécution pour générer les fichiers dont le nouveau système aura besoin. La mise à jour n'est pas considérée comme disponible tant que ce travail n'a pas été effectué.

Pouvons-nous (devons-nous) expédier un appareil A/B de 32 Gio ? 16 Gio ? 8 Gio ?

32 Gio fonctionnent bien, comme cela a été prouvé sur Pixel. 320 Mio sur 16 Gio représentent une réduction de 2 %. De même, 320 Mio sur 8 Gio représentent une réduction de 4 %. Il est évident que le partitionnement A/B ne serait pas le choix recommandé sur les appareils disposant de 4 Gio, car la surcharge de 320 Mio représente près de 10 % de l'espace total disponible.

AVB2.0 nécessite-t-il des mises à jour OTA A/B ?

Non. La fonctionnalité Démarrage vérifié d'Android a toujours nécessité des mises à jour par blocs, mais pas nécessairement des mises à jour A/B.

Les mises à jour OTA A/B nécessitent-elles AVB2.0 ?

de série

Les mises à jour OTA A/B cassent-elles la protection contre le rollback d'AVB2.0 ?

Non. Il y a une certaine confusion ici, car si un système A/B ne parvient pas à démarrer sur la nouvelle image système, il reviendra automatiquement à l'image système "précédente" (après un certain nombre de tentatives déterminé par votre bootloader). Le point essentiel est que "précédent" dans le sens A/B correspond en fait toujours à l'image système "actuelle". Dès que l'appareil démarre correctement une nouvelle image, la protection contre la restauration se déclenche et vous empêche de revenir en arrière. Toutefois, tant que vous n'avez pas réussi à démarrer la nouvelle image, la protection contre le rollback ne la considère pas comme l'image système actuelle.

Si vous installez une mise à jour pendant que le système est en cours d'exécution, n'est-ce pas lent ?

Avec les mises à jour non A/B, l'objectif est d'installer la mise à jour le plus rapidement possible, car l'utilisateur attend et ne peut pas utiliser son appareil pendant l'application de la mise à jour. Avec les mises à jour A/B, c'est l'inverse : l'objectif est de minimiser l'impact, car l'utilisateur continue d'utiliser son appareil. La mise à jour est donc délibérément lente. Grâce à la logique du client de mise à jour du système Java (qui, pour Google, est GmsCore, le package principal fourni par GMS), Android tente également de choisir un moment où les utilisateurs n'utilisent pas du tout leurs appareils. La plate-forme permet de mettre en pause/reprendre la mise à jour. Le client peut l'utiliser pour mettre en pause la mise à jour si l'utilisateur commence à utiliser l'appareil et la reprendre lorsque l'appareil est de nouveau inactif.

La mise à jour OTA se déroule en deux phases, clairement indiquées dans l'UI par Étape 1 sur 2 et Étape 2 sur 2 sous la barre de progression. L'étape 1 correspond à l'écriture des blocs de données, tandis que l'étape 2 consiste à précompiler les fichiers .dex. Ces deux phases sont très différentes en termes d'impact sur les performances. La première phase est celle des E/S simples. Cela nécessite peu de ressources (RAM, processeur, E/S), car il s'agit simplement de copier lentement des blocs.

La deuxième phase exécute dex2oat pour précompiler la nouvelle image système. Les limites de ses exigences sont évidemment moins claires, car il compile des applications réelles. De toute évidence, la compilation d'une application volumineuse et complexe demande beaucoup plus de travail que celle d'une application petite et simple. En revanche, lors de la phase 1, il n'y a pas de blocs de disque plus volumineux ou plus complexes que d'autres.

Le processus est semblable à celui utilisé par Google Play pour installer une mise à jour d'application en arrière-plan avant d'afficher la notification 5 applications mises à jour, comme c'est le cas depuis des années.

Que se passe-t-il si un utilisateur attend réellement la mise à jour ?

L'implémentation actuelle dans GmsCore ne fait pas la distinction entre les mises à jour en arrière-plan et les mises à jour initiées par l'utilisateur, mais elle pourra le faire à l'avenir. Si l'utilisateur a explicitement demandé l'installation de la mise à jour ou s'il regarde l'écran de progression de la mise à jour, nous donnerons la priorité à la mise à jour en partant du principe qu'il attend activement qu'elle se termine.

Que se passe-t-il si une mise à jour ne peut pas être appliquée ?

Avec les mises à jour non A/B, si une mise à jour ne s'appliquait pas, l'utilisateur se retrouvait généralement avec un appareil inutilisable. La seule exception était si l'échec se produisait avant même le démarrage d'une application (parce que le package n'avait pas pu être vérifié, par exemple). Avec les mises à jour A/B, l'échec de l'application d'une mise à jour n'affecte pas le système en cours d'exécution. Vous pouvez simplement réessayer la mise à jour plus tard.