Ce document décrit la conception d'une solution de mise en cache d'APK pour une installation rapide des applications préchargées sur un appareil compatible avec les partitions A/B.
Les OEM peuvent placer des préchargements et des applications populaires dans le cache APK stocké dans la partition B, qui est presque vide, sur les nouveaux appareils partitionnés en A/B sans affecter l'espace de données visible par l'utilisateur. En disposant d'un cache APK sur l'appareil, les appareils neufs ou récemment réinitialisés 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é que lors du premier démarrage. En effet, sur les appareils compatibles avec les mises à jour système A/B, la partition B ne stocke pas réellement de fichiers d'image système, mais du contenu préchargé tel que des ressources de démonstration en magasin, des fichiers OAT et le cache APK. Une fois les ressources copiées dans la partition /data (cela se produit au premier démarrage), la partition B est utilisée par les mises à jour Over-The-Air (OTA) 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 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 effectuera de nouveau son premier démarrage. Cela signifie que la mise en cache de l'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
Conseil: Le contenu préchargé n'est pas perdu après la réinitialisation 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 un temps supplémentaire 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 d'installation en lecture seule de la partition system_b
):
Pour implémenter cette fonctionnalité, apportez les modifications suivantes, spécifiques à l'appareil. Voici un exemple 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: 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 et les sous-répertoires/data/preloads
nécessaires: Vous trouverez un exemple de source de fichiermkdir /data/preloads 0775 system system
mkdir /data/preloads/media 0775 system system
mkdir /data/preloads/demo 0775 system system
init
à l'adresse: 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: /device/google/marlin/+/main/sepolicy/preloads_copy.te.type 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 contextes SELinux à l'adresse: 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é sur la partition
system_other
: Il s'agit d'un exemple de modification dans un Makefile qui permet de copier les ressources de cache APK à partir du dépôt Git du fournisseur (dans notre cas, il s'agissait de vendor/google_devices/marlin/preloads) à l'emplacement de la partition system_other qui sera ensuite copiée dans /data/preloads lorsque l'appareil démarre 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 réel.# 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 se présente comme suit: Il s'agit de la structure de répertoire finale sur les appareils. Les OEM sont libres de choisir n'importe quelle approche d'implémentation, à condition que la structure de fichiers finale reproduise 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é en usine
Cette autre approche suppose que le contenu préchargé est déjà inclus dans le répertoire /data/preloads
de la partition /data
.
Avantages: fonctionne dès la sortie de la boîte. Vous n'avez pas besoin de personnaliser l'appareil pour copier des fichiers au premier démarrage. Le contenu se trouve déjà sur la partition /data
.
Inconvénient: le contenu préchargé est perdu après une réinitialisation 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 inspections de contrôle qualité.
Une nouvelle méthode @SystemApi, getPreloadsFileCache()
, a été ajoutée à android.content.Context
. Il renvoie un chemin d'accès absolu vers un répertoire spécifique à l'application dans le cache préchargé.
Une nouvelle méthode, IPackageManager.deletePreloadsFileCache
, a été ajoutée pour supprimer le répertoire de préchargement afin de récupérer tout l'espace. La méthode ne peut être appelée que par les 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 de cache de préchargement. Pour cet accès, 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 insuffisant.
Utilisez l'exemple d'application ApkCacheTest pour tester le cache APK.
- Créez l'application en exécutant la commande suivante à 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 en mode 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 de cache de fichiers et son contenu si nécessaire (ce qui nécessite également des droits d'accès 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. Un fichiertest.txt
et son contenu devraient s'afficher. Consultez cette capture d'écran pour voir comment ces résultats apparaissent dans l'interface utilisateur.
Figure 1 : Résultats d'ApkCacheTest.