Ce document décrit la conception d'une solution de mise en cache des APK pour l'installation rapide d'applications préchargées sur un appareil compatible avec les partitions A/B.
Les OEM peuvent placer des applications préchargées et populaires dans le cache APK stocké dans la partition B, qui est presque vide, sur les nouveaux appareils partitionnés A/B sans affecter l'espace de données destiné aux utilisateurs. Grâce à un cache d'APK disponible sur l'appareil, les appareils neufs ou récemment réinitialisés aux paramètres d'usine sont prêts à l'emploi presque immédiatement, sans avoir à télécharger de fichiers APK depuis Google Play.
Cas d'utilisation
- Stocker les applications préchargées dans la partition B pour une configuration plus rapide
- Stocker les applications populaires dans la partition B pour une restauration plus rapide
Prérequis
Pour utiliser cette fonctionnalité, l'appareil doit :
- Version Android 8.1 (O MR1) installée
- Partition A/B implémentée
Le contenu préchargé ne peut être copié qu'au premier démarrage. En effet, sur les appareils compatibles avec les mises à jour du système A/B, la partition B ne stocke pas de fichiers d'image système, mais plutôt du contenu préchargé comme des ressources de démonstration commerciale, des fichiers OAT et le cache APK. Une fois les ressources copiées dans la partition /data (ce qui se produit au premier démarrage), la partition B sera utilisée par les mises à jour OTA (Over-The-Air) pour télécharger les versions mises à jour de l'image système.
Par conséquent, le cache APK ne peut pas être mis à jour via OTA. Il ne peut être préchargé qu'en usine. La réinitialisation des données d'usine n'affecte que la partition /data. La partition B du système contient toujours le contenu préchargé jusqu'à ce que l'image OTA soit téléchargée. Une fois la configuration d'usine rétablie, le système redémarre. Cela signifie que la mise en cache des APK n'est pas disponible si l'image OTA est téléchargée sur la partition B, puis que la configuration d'usine de l'appareil est rétablie.
Implémentation
Approche 1. Contenu de la partition system_other
Avantage : Le contenu préchargé n'est pas perdu après le rétablissement de la configuration d'usine. Il est copié à partir de la partition B après un redémarrage.
Inconvénient : Nécessite de l'espace sur la partition B. Le démarrage après le rétablissement de la configuration d'usine nécessite plus de temps pour copier le contenu préchargé.
Pour que les préchargements soient copiés lors du premier démarrage, le système appelle un script dans /system/bin/preloads_copy.sh
. Le script est appelé avec un seul argument (chemin d'accès au point de montage en lecture seule pour la partition system_b
) :
Pour implémenter cette fonctionnalité, apportez les modifications spécifiques à l'appareil. Voici un exemple tiré de Marlin :
- Ajoutez le script qui effectue la copie au fichier
device-common.mk
(dans ce cas,device/google/marlin/device-common.mk
), comme suit : Vous trouverez un exemple de source de script à l'adresse suivante : device/google/marlin/preloads_copy.sh# Script that copies preloads directory from system_other to data partition PRODUCT_COPY_FILES += \ device/google/marlin/preloads_copy.sh:system/bin/preloads_copy.sh
- Modifiez le fichier
init.common.rc
pour qu'il crée le répertoire/data/preloads
et les sous-répertoires nécessaires : Vous trouverez un exemple de fichiermkdir /data/preloads 0775 system system
mkdir /data/preloads/media 0775 system system
mkdir /data/preloads/demo 0775 system system
init
à l'adresse suivante : device/google/marlin/init.common.rc. - Définissez un nouveau domaine SELinux dans le fichier
preloads_copy.te
: Vous trouverez un exemple de fichier de domaine SELinux à l'adresse suivante : /device/google/marlin/+/android16-release/sepolicy/preloads_copy.tetype preloads_copy, domain, coredomain; type preloads_copy_exec, exec_type, vendor_file_type, file_type; init_daemon_domain(preloads_copy) allow preloads_copy shell_exec:file rx_file_perms; allow preloads_copy toolbox_exec:file rx_file_perms; allow preloads_copy preloads_data_file:dir create_dir_perms; allow preloads_copy preloads_data_file:file create_file_perms; allow preloads_copy preloads_media_file:dir create_dir_perms; allow preloads_copy preloads_media_file:file create_file_perms; # Allow to copy from /postinstall allow preloads_copy system_file:dir r_dir_perms;
- Enregistrez le domaine dans un nouveau fichier
:/sepolicy/file_contexts Vous trouverez un exemple de fichier de contexte SELinux à l'adresse suivante : device/google/marlin/sepolicy/preloads_copy.te./system/bin/preloads_copy\.sh u:object_r:preloads_copy_exec:s0
- Au moment de la compilation, le répertoire contenant le contenu préchargé doit être copié dans la partition
system_other
: Voici un exemple de modification d'un fichier Makefile qui permet de copier les ressources du cache APK à partir du dépôt Git du fournisseur (dans notre cas, il s'agissait de vendor/google_devices/marlin/preloads) vers l'emplacement de la partition system_other qui sera ensuite copié dans /data/preloads lorsque l'appareil démarrera pour la première fois. Ce script s'exécute au moment de la compilation pour préparer l'image system_other. Il s'attend à ce que le contenu préchargé soit disponible dans vendor/google_devices/marlin/preloads. L'OEM est libre de choisir le nom/chemin d'accès du dépôt.# Copy contents of preloads directory to system_other partition PRODUCT_COPY_FILES += \ $(call find-copy-subdir-files,*,vendor/google_devices/marlin/preloads,system_other/preloads)
- Le cache APK se trouve dans
/data/preloads/file_cache
et présente la structure suivante : Il s'agit de la structure de répertoire finale sur les appareils. Les OEM sont libres de choisir l'approche d'implémentation de leur choix, à condition que la structure du fichier final soit identique à celle décrite ci-dessus./data/preloads/file_cache/ app.package.name.1/ file1 fileN app.package.name.N/
Approche 2. Contenu de l'image des données utilisateur flashée en usine
Cette approche alternative suppose que le contenu préchargé est déjà inclus dans le répertoire /data/preloads
de la partition /data
.
Pro : fonctionne prêt à l'emploi. Il n'est pas nécessaire de personnaliser l'appareil pour copier des fichiers au premier démarrage. Le contenu se trouve déjà dans la partition /data
.
Inconvénient : Le contenu préchargé est perdu après le rétablissement de la configuration d'usine. Bien que cela puisse être acceptable pour certains, cela ne fonctionne pas toujours pour les OEM qui réinitialisent les appareils en usine après avoir effectué des contrôles qualité.
Une nouvelle méthode @SystemApi, getPreloadsFileCache()
, a été ajoutée à android.content.Context
. Elle renvoie un chemin d'accès absolu à un répertoire spécifique à l'application dans le cache préchargé.
Ajout d'une méthode IPackageManager.deletePreloadsFileCache
permettant de supprimer le répertoire de préchargement pour récupérer tout l'espace. Cette méthode ne peut être appelée que par des applications avec SYSTEM_UID, c'est-à-dire le serveur système ou les paramètres.
Préparation de l'application
Seules les applications privilégiées peuvent accéder au répertoire du cache des préchargements. Pour y accéder, les applications doivent être installées dans le répertoire /system/priv-app
.
Validation
- Après le premier démarrage, l'appareil doit contenir du contenu dans le répertoire
/data/preloads/file_cache
. - Le contenu du répertoire
file_cache/
doit être supprimé si l'espace de stockage de l'appareil est presque plein.
Utilisez l'exemple d'application ApkCacheTest pour tester le cache APK.
- Créez l'application en exécutant cette commande à partir du répertoire racine :
make ApkCacheTest
- Installez l'application en tant qu'application privilégiée. (N'oubliez pas que seules les applications privilégiées peuvent accéder au cache APK.)
Pour ce faire, vous devez disposer d'un appareil rooté :
adb root && adb remount
adb shell mkdir /system/priv-app/ApkCacheTest
adb push $ANDROID_PRODUCT_OUT/data/app/ApkCacheTest/ApkCacheTest.apk /system/priv-app/ApkCacheTest/
adb shell stop && adb shell start
- Simulez le répertoire du cache de fichiers et son contenu si nécessaire (nécessite également des droits root) :
adb shell mkdir -p /data/preloads/file_cache/com.android.apkcachetest
adb shell restorecon -r /data/preloads
adb shell "echo "Test File" > /data/preloads/file_cache/com.android.apkcachetest/test.txt"
- Testez l'application. Après avoir installé l'application et créé le répertoire de test
file_cache
, ouvrez l'application ApkCacheTest. Elle devrait afficher un fichiertest.txt
et son contenu. Consultez cette capture d'écran pour voir comment ces résultats s'affichent dans l'interface utilisateur.
Figure 1 : Résultats d'ApkCacheTest.