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 fluides. Les téléphones Pixel et Pixel XL à partir d'octobre 2016 sont livrés 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 A/B sont-elles meilleures ?
Les OTA A/B offrent une meilleure expérience utilisateur lors de la mise à jour. Les mesures 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 exécutaient 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 ne provoquent plus de démarrage de l'appareil. Tant que la nouvelle image système n'a pas démarré, Android conserve la possibilité de revenir à l'ancienne image système fonctionnelle.
Qu'est-ce que system_other ?
Les applications sont stockées dans des fichiers .apk, qui sont en réalité des archives ZIP. Chaque fichier .apk contient un ou plusieurs fichiers .dex contenant du bytecode Dalvik portable. Un fichier .odex (.dex optimisé) se trouve séparément du fichier .apk et peut contenir du code machine spécifique à l'appareil. Si un fichier .odex est disponible, Android peut exécuter des applications à des vitesses de compilation anticipée sans avoir à attendre que le code soit compilé chaque fois que l'application est lancée. Un fichier .odex n'est pas strictement nécessaire: Android peut 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 d'image système totale de 2 628 Mo (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 | 139 177 0312 octets | 50,5% |
.apk | 846 878 259 octets | 30,7% |
.so (code C/C++ natif) | 202162479 octets | 7,3% |
Fichiers .oat/Images .art | 16 389 2188 octets | 5,9 % |
Polices | 38 952 361 octets | 1,4 % |
Données locales icu | 274 68687 octets | 0,9 % |
Ces chiffres sont également similaires pour d'autres appareils. Par conséquent, sur les appareils Nexus/Pixel, les fichiers .odex occupent environ la moitié de la partition système. Cela nous a permis de continuer à utiliser ext4, mais d'écrire les fichiers .odex sur la partition B en usine, puis de les copier sur /data
au premier démarrage. Le stockage réel utilisé avec ext4 A/B est identique à SquashFS A/B, car si nous avions utilisé SquashFS, nous aurions expédié les fichiers .odex préoptimisés sur system_a au lieu de system_b.
La copie de fichiers .odex dans /data ne signifie-t-elle pas que l'espace économisé sur /system est perdu sur /data ?
Pas exactement. Sur Pixel, la majeure partie de l'espace occupé par les fichiers .odex est réservée aux applications, qui existent généralement sur /data
. Ces applications reçoivent des mises à jour Google Play. Par conséquent, les fichiers .apk et .odex de l'image système ne sont 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 qu'il n'utilise pas). Pour en savoir plus, consultez la présentation The Evolution of Art (L'évolution de l'art) lors de Google I/O 2016.
La comparaison est difficile pour plusieurs raisons:
-
Les fichiers .odex des applications mises à jour par Google Play ont toujours été sur
/data
dès qu'elles ont reçu leur première mise à jour. - Les applications que l'utilisateur n'exécute pas n'ont pas besoin d'un fichier .odex.
- La compilation guidée par le profil génère des fichiers .odex plus petits que la compilation anticipée (car la première n'optimise que le code critique pour les performances).
Pour en savoir plus sur les options de réglage disponibles pour les OEM, consultez la section Configurer ART.
N'y a-t-il pas deux copies des fichiers .odex sur /data ?
C'est un peu plus compliqué. Une fois l'image système nouvellement é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 lorsque l'ancien système est toujours en cours d'exécution. Par conséquent, les anciens et nouveaux fichiers .odex se trouvent tous les deux sur /data
en même temps.
Le code dans OtaDexoptService (frameworks/base/+/main/services/core/java/com/android/server/pm/OtaDexoptService.java
) appelle getAvailableSpace
avant d'optimiser chaque package pour éviter de trop remplir /data
. Notez que la valeur disponible est toujours conservatrice: il s'agit de l'espace restant avant d'atteindre le seuil d'espace système faible habituel (mesuré à la fois en pourcentage et en nombre d'octets). Par conséquent, si /data
est saturé, 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 précédemment), les fichiers .odex appartenant aux applications qui ne sont pas utilisées sont supprimés. Il s'agit d'un autre cas sans deux copies de chaque fichier .odex.
Dans le pire des cas, lorsque /data
est complètement saturé, la mise à jour attend que l'appareil ait redémarré dans le nouveau système et qu'il n'ait plus besoin des fichiers .odex de l'ancien système. Le PackageManager gère cela: (frameworks/base/+/main/services/core/java/com/android/server/pm/PackageManagerService.java#7215
). Une fois le nouveau système démarré, installd
(frameworks/native/+/main/cmds/installd/dexopt.cpp#2422
) peut supprimer les fichiers .odex utilisés par l'ancien système, ce qui ramène l'appareil à l'état stable où il n'y a qu'une seule copie.
Par conséquent, bien qu'il soit possible que /data
contienne deux copies de tous les fichiers .odex, (a) il s'agit d'une situation temporaire et (b) elle ne se produit que si vous disposez de beaucoup d'espace libre sur /data
. Sauf lors d'une mise à jour, il n'existe qu'une seule copie. En outre, dans le cadre des fonctionnalités de robustesse générales d'ART, il ne remplira jamais /data
de fichiers .odex (car cela poserait également un problème sur un système non A/B).
Tout cet écriture/copier n'augmente-t-il 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 Go. (Les applications sont également recompilées, mais cela est également vrai pour les tests non A/B.) Traditionnellement, les OTA complètes basées sur des blocs écrivaient une quantité similaire de données. Par conséquent, les taux d'usure des flashs devraient être similaires.
Le flashage de deux partitions système augmente-t-il le temps de flashage d'usine ?
Non. La taille de l'image système n'a pas augmenté (elle a simplement divisé l'espace en deux partitions).
Le fait de conserver les fichiers .odex sur B ne ralentit-il pas 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 mn 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 doit être une opération rare par rapport au démarrage normal. Le temps nécessaire est donc moins important. (Cela n'affecte pas les utilisateurs ni les réviseurs qui reçoivent leur appareil 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. Ce n'est donc pas aussi grave que vous pourriez le penser. Il est également possible de marquer les applications comme nécessitant une compilation anticipée à l'aide de coreApp="true"
dans le fichier manifeste: (frameworks/base/+/main/packages/SystemUI/AndroidManifest.xml#23
). Cette option est actuellement utilisée par system_server
, car elle n'est pas autorisée à utiliser la compilation JIT pour des raisons de sécurité.
Le fait de conserver les fichiers .odex sur /data plutôt que sur /system ne ralentit-il pas le redémarrage après une mise à jour OTA ?
Non. Comme expliqué ci-dessus, le nouveau dex2oat est exécuté pendant que l'ancienne image système est toujours en cours d'exécution afin de 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 Go ? 16 Gio ? 8 Gio ?
32 Gio fonctionne bien, comme cela a été prouvé sur Pixel, et 320 Mo sur 16 Gio représentent une réduction de 2%. De même, 320 Mo sur 8 Go correspond à une réduction de 4%. Évidemment, le choix A/B ne serait pas le choix recommandé sur les appareils de 4 Go, car les 320 Mo de surcharge représentent presque 10% de l'espace total disponible.
AVB2.0 nécessite-t-il des mises à jour OTA A/B ?
Non. Le démarrage validé d'Android a toujours nécessité des mises à jour basées sur des blocs, mais pas nécessairement des mises à jour A/B.
Les OTA A/B nécessitent-elles AVB2.0 ?
de série
Les OTA A/B endommagent-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 dans la nouvelle image système, il revient automatiquement à l'image système "précédente" (après un certain nombre de tentatives déterminées par votre bootloader). Le point essentiel est que "précédent" au sens A/B est toujours l'image système "actuelle". Dès que l'appareil démarre une nouvelle image, la protection contre le rollback se déclenche et vous empêche de revenir en arrière. Toutefois, tant que vous n'avez pas démarré 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 alors que le système est en cours d'exécution, cela n'est-il pas lent ?
Avec les mises à jour autres que celles de type A/B, l'objectif est d'installer la mise à jour aussi rapidement que 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, l'inverse est vrai. Étant donné que l'utilisateur utilise toujours son appareil, l'objectif est de limiter autant que possible l'impact de la mise à jour. Elle est donc délibérément lente. Via la logique du client de mise à jour du système Java (qui, pour Google, est GmsCore, le package de base 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 suspendre/de reprendre la mise à jour. Le client peut utiliser cette fonctionnalité pour suspendre la mise à jour si l'utilisateur commence à utiliser l'appareil et la reprendre lorsqu'il est à nouveau inactif.
Une mise à jour OTA se déroule en deux phases, clairement indiquées dans l'UI sous la barre de progression (Étape 1 sur 2 et Étape 2 sur 2). 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 une E/S simple. Cela nécessite peu de ressources (RAM, CPU, E/S), car il ne s'agit que 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. Il est évidemment beaucoup plus difficile de compiler une application volumineuse et complexe qu'une application petite et simple. En revanche, dans la phase 1, aucun bloc de disque n'est plus volumineux ni plus complexe que les autres.
Le processus est semblable à celui de Google Play qui installe une mise à jour d'application en arrière-plan avant d'afficher la notification 5 applications mises à jour, comme cela se fait depuis des années.
Que se passe-t-il si un utilisateur attend 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 déclenchées par l'utilisateur, mais elle pourrait le faire à l'avenir. Si l'utilisateur a explicitement demandé l'installation de la mise à jour ou qu'il regarde l'écran de progression de la mise à jour, nous priorisons la tâche de mise à jour en supposant qu'il attend activement qu'elle se termine.
Que se passe-t-il si l'application d'une mise à jour échoue ?
Avec les mises à jour autres que 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 s'était produit avant même le démarrage d'une application (par exemple, en raison d'une erreur de validation du package). 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.