Réduire la taille de l'OTA

Cette page décrit les modifications ajoutées à AOSP pour réduire les modifications de fichiers inutiles entre les versions. Les implémenteurs d'appareils qui gèrent leurs propres systèmes de build peuvent utiliser ces informations comme guide pour réduire la taille de leurs mises à jour en direct (OTA).

Les mises à jour Android OTA contiennent parfois des fichiers modifiés qui ne correspondent pas aux modifications du code. Ce sont en fait des artefacts système de construction. Cela peut se produire lorsque le même code, construit à des moments différents, à partir de répertoires différents ou sur des machines différentes, produit un grand nombre de fichiers modifiés. De tels fichiers excédentaires augmentent la taille d'un correctif OTA et rendent difficile la détermination du code modifié.

Pour rendre le contenu d'un OTA plus transparent, AOSP inclut des modifications du système de construction conçues pour réduire la taille des correctifs OTA. Les modifications de fichiers inutiles entre les versions ont été éliminées et seuls les fichiers liés aux correctifs sont contenus dans les mises à jour OTA. AOSP comprend également un outil de comparaison de build , qui filtre les modifications de fichiers courantes liées à la build pour fournir une différence de fichier de build plus propre, et un outil de mappage de blocs , qui vous aide à maintenir la cohérence de l'allocation de blocs.

Un système de build peut créer des correctifs inutilement volumineux de plusieurs manières. Pour atténuer ce problème, dans Android 8.0 et versions ultérieures, de nouvelles fonctionnalités ont été implémentées pour réduire la taille du correctif pour chaque différence de fichier. Les améliorations qui ont réduit la taille des packages de mise à jour OTA sont les suivantes :

  • Utilisation de Brotli , un algorithme de compression sans perte à usage générique pour les images complètes sur les mises à jour d'appareils non A/B. Brotli peut être personnalisé pour optimiser la compression. Sur les mises à jour plus volumineuses composées de deux blocs ou plus dans le système de fichiers (par exemple, system.img ), les fabricants de périphériques ou les partenaires peuvent ajouter leurs propres algorithmes de compression et utiliser différents algorithmes de compression sur différents blocs de la même mise à jour.
  • Utilisation de la recompression Puffin , un outil de correction déterministe pour les flux dégonflés, qui gère les fonctions de compression et de comparaison pour la génération de mises à jour A/B OTA.
  • Modifications apportées à l'utilisation de l'outil de génération delta, telles que la manière dont la bibliothèque bsdiff est utilisée pour compresser les correctifs. Sous Android 9 et versions ultérieures, l'outil bsdiff sélectionne l'algorithme de compression qui donnerait les meilleurs résultats de compression pour un correctif.
  • Les améliorations apportées à update_engine ont permis de réduire la consommation de mémoire lors de l'application de correctifs pour les mises à jour A/B des appareils.
  • Améliorations du fractionnement des fichiers zip volumineux pour les mises à jour OTA basées sur des blocs. Un mode dans imgdiff divise les fichiers APK surdimensionnés, en fonction des noms d'entrée. Cela produit un patch plus petit par rapport au fractionnement linéaire des fichiers et à l'utilisation de l'outil bsdiff pour les compresser.

Les sections suivantes abordent divers problèmes qui affectent la taille des mises à jour OTA, leurs solutions et des exemples de mise en œuvre dans AOSP.

Ordre des fichiers

Problème : les systèmes de fichiers ne garantissent pas l'ordre des fichiers lorsqu'on leur demande une liste de fichiers dans un répertoire, même si c'est généralement la même chose pour la même extraction. Des outils tels que ls trient les résultats par défaut, mais la fonction générique utilisée par des commandes telles que find et make ne trie pas. Avant d'utiliser ces outils, vous devez trier les sorties.

Solution : Lorsque vous utilisez des outils tels que find et make avec la fonction générique, triez le résultat de ces commandes avant de les utiliser. Lorsque vous utilisez $(wildcard) ou $(shell find) dans les fichiers Android.mk , triez-les également. Certains outils, tels que Java, trient les entrées. Avant de trier les fichiers, vérifiez que l'outil que vous utilisez ne l'a pas déjà fait.

Exemples : De nombreuses instances ont été corrigées dans le système de construction principal à l'aide de la macro intégrée all-*-files-under , qui inclut all-cpp-files-under (car plusieurs définitions étaient réparties dans d'autres makefiles). Pour plus de détails, reportez-vous à ce qui suit :

Répertoire de construction

Problème : Changer le répertoire dans lequel les éléments sont construits peut entraîner une différence entre les binaires. La plupart des chemins dans la version Android sont des chemins relatifs, donc __FILE__ en C/C++ n'est pas un problème. Cependant, les symboles de débogage codent par défaut le chemin d'accès complet et le .note.gnu.build-id est généré à partir du hachage du binaire pré-supprimé, il changera donc si les symboles de débogage changent.

Solution : AOSP rend désormais les chemins de débogage relatifs. Pour plus de détails, reportez-vous à CL : https://android.googlesource.com/platform/build/+/6a66a887baadc9eb3d0d60e26f748b8453e27a02 .

Horodatages

Problème : les horodatages dans la sortie de build entraînent des modifications de fichiers inutiles. Cela est susceptible de se produire dans les endroits suivants :

  • Macros __DATE__/__TIME__/__TIMESTAMP__ en code C ou C++.
  • Horodatages intégrés dans des archives zip.

Solutions/Exemples : Pour supprimer les horodatages de la sortie de build, utilisez les instructions données ci-dessous dans __DATE__/__TIME__/__TIMESTAMP__ en C/C++. et Horodatages intégrés dans les archives .

__DATE__/__TIME__/__TIMESTAMP__ en C/C++

Ces macros produisent toujours des sorties différentes pour différentes versions, ne les utilisez donc pas. Voici quelques options pour éliminer ces macros :

Horodatages intégrés dans les archives (zip, jar)

Android 7.0 a résolu le problème des horodatages intégrés dans les archives zip en ajoutant -X à toutes les utilisations de la commande zip . Cela a supprimé l'UID/GID du constructeur et l'horodatage Unix étendu du fichier zip.

Un nouvel outil, ziptime (situé dans /platform/build/+/main/tools/ziptime/ ) réinitialise les horodatages normaux dans les en-têtes zip. Pour plus de détails, reportez-vous au fichier README .

L'outil signapk définit des horodatages pour les fichiers APK qui peuvent varier en fonction du fuseau horaire du serveur. Pour plus de détails, reportez-vous au CL https://android.googlesource.com/platform/build/+/6c41036bcf35fe39162b50d27533f0f3bfab3028 .

Chaînes de version

Problème : Les chaînes de version APK avaient souvent le BUILD_NUMBER ajouté à leurs versions codées en dur. Même si rien d’autre ne changeait dans un APK, l’APK serait toujours différent.

Solution : supprimez le numéro de build de la chaîne de version APK.

Exemples:

Activer le calcul de la vérité sur l'appareil

Si dm-verity est activé sur votre appareil, les outils OTA récupèrent automatiquement votre configuration Verity et activent le calcul de Verity sur l'appareil. Cela permet aux blocs Verity d'être calculés sur les appareils Android, au lieu d'être stockés sous forme d'octets bruts dans votre package OTA. Les blocs Verity peuvent utiliser environ 16 Mo pour une partition de 2 Go.

Cependant, le calcul de la vérité sur l'appareil peut prendre beaucoup de temps. Plus précisément, le code de correction d'erreur directe peut prendre beaucoup de temps. Sur les appareils Pixel, cela prend généralement jusqu'à 10 minutes. Sur les appareils bas de gamme, cela peut prendre plus de temps. Si vous souhaitez désactiver le calcul de la vérité sur l'appareil, tout en activant dm-verity, vous pouvez le faire en transmettant --disable_fec_computation à l'outil ota_from_target_files lors de la génération d'une mise à jour OTA. Cet indicateur désactive le calcul de la vérité sur l'appareil lors des mises à jour OTA. Cela réduit le temps d’installation de l’OTA, mais augmente la taille du package OTA. Si dm-verity n'est pas activé sur votre appareil, la transmission de cet indicateur n'a aucun effet.

Outils de construction cohérents

Problème : les outils qui génèrent les fichiers installés doivent être cohérents (une entrée donnée doit toujours produire la même sortie).

Solutions/Exemples : Des modifications ont été nécessaires dans les outils de construction suivants :

Utilisez l'outil de comparaison de build

Pour les cas où il n'est pas possible d'éliminer les modifications de fichiers liées à la construction, AOSP inclut un outil de comparaison de construction, target_files_diff.py , à utiliser pour comparer deux packages de fichiers. Cet outil effectue une comparaison récursive entre deux builds, à l'exclusion des modifications de fichiers courantes liées à la build, telles que

  • Modifications attendues dans la sortie de build (par exemple, en raison d'un changement de numéro de build).
  • Modifications dues à des problèmes connus dans le système de build actuel.

Pour utiliser l'outil build diff, exécutez la commande suivante :

target_files_diff.py dir1 dir2

dir1 et dir2 sont des répertoires de base contenant les fichiers cibles extraits pour chaque build.

Maintenir la cohérence de l'allocation des blocs

Pour un fichier donné, bien que son contenu reste le même entre deux builds, les blocs réels qui contiennent les données peuvent avoir changé. Par conséquent, le programme de mise à jour doit effectuer des E/S inutiles pour déplacer les blocs pour une mise à jour OTA.

Dans une mise à jour Virtual A/B OTA, les E/S inutiles peuvent augmenter considérablement l'espace de stockage requis pour stocker l'instantané de copie sur écriture. Dans une mise à jour OTA non-A/B, le déplacement des blocs pour une mise à jour OTA contribue au temps de mise à jour car il y a plus d'E/S en raison des déplacements de blocs.

Pour résoudre ce problème, dans Android 7.0, Google a étendu l'outil make_ext4fs pour maintenir la cohérence de l'allocation de blocs entre les versions. L'outil make_ext4fs accepte un indicateur -d base_fs facultatif qui tente d'attribuer des fichiers aux mêmes blocs lors de la génération d'une image ext4 . Vous pouvez extraire les fichiers de mappage de blocs (tels que les fichiers de mappage base_fs ) du fichier zip des fichiers cibles d'une version précédente. Pour chaque partition ext4 , il existe un fichier .map dans le répertoire IMAGES (par exemple, IMAGES/system.map correspond à la partition system ). Ces fichiers base_fs peuvent ensuite être archivés et spécifiés via PRODUCT_<partition>_BASE_FS_PATH , comme dans cet exemple :

  PRODUCT_SYSTEM_BASE_FS_PATH := path/to/base_fs_files/base_system.map
  PRODUCT_SYSTEM_EXT_BASE_FS_PATH := path/to/base_fs_files/base_system_ext.map
  PRODUCT_VENDOR_BASE_FS_PATH := path/to/base_fs_files/base_vendor.map
  PRODUCT_PRODUCT_BASE_FS_PATH := path/to/base_fs_files/base_product.map
  PRODUCT_ODM_BASE_FS_PATH := path/to/base_fs_files/base_odm.map

Bien que cela ne contribue pas à réduire la taille globale du package OTA, cela améliore les performances de mise à jour OTA en réduisant la quantité d'E/S. Pour les mises à jour Virtual A/B, cela réduit considérablement la quantité d’espace de stockage nécessaire pour appliquer l’OTA.

Évitez de mettre à jour les applications

En plus de minimiser les différences de build, vous pouvez réduire la taille des mises à jour OTA en excluant les mises à jour des applications qui reçoivent des mises à jour via les magasins d'applications. Les APK constituent souvent une partie importante des différentes partitions d’un appareil. L’inclusion des dernières versions des applications mises à jour par les magasins d’applications dans une mise à jour OTA peut avoir un impact important sur les packages OTA et offrir peu d’avantages à l’utilisateur. Au moment où les utilisateurs reçoivent un package OTA, ils disposent peut-être déjà de l'application mise à jour, ou d'une version encore plus récente, reçue directement des magasins d'applications.