Mise en cache de l'APK

Ce document décrit la conception d'une solution de mise en cache des APK pour une installation rapide. d'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 le cache partition B vide sur les nouveaux appareils partitionnés A/B sans incidence n'importe quel espace de données visible par l'utilisateur. En ayant un cache APK disponible sur l'appareil, nouveau ou les appareils récemment réinitialisés sont prêts à être utilisés presque immédiatement, sans sans avoir besoin de télécharger des fichiers APK à partir de Google Play.

Cas d'utilisation

  • Stocker les applications préchargées dans la partition B pour une configuration plus rapide
  • Stockez les applis populaires dans la partition B pour une restauration plus rapide

Prérequis

Pour utiliser cette fonctionnalité, l'appareil doit disposer des éléments suivants:

  • Version d'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 prenant en charge les mises à jour du système A/B, la partition B ne stocke pas d'image système, mais du contenu préchargé, comme les ressources de démonstration en magasin, les fichiers OAT et le cache APK. Une fois les ressources copiées dans /data (cela se produit au premier démarrage), la partition B est utilisée par Over The Air (OTA) mises à jour pour télécharger les versions mises à jour de l'image système.

Par conséquent, le cache de l'APK ne peut pas être mis à jour via une OTA. il ne peut être préchargé en usine. Le rétablissement de la configuration d'usine n'affecte que la partition /data. Le système B dispose toujours du 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 est relancé par le premier démarrage. Autrement dit, l'APK la mise en cache n'est pas disponible si l'image OTA est téléchargée sur la partition B et la configuration d'usine de l'appareil est alors rétablie.

Implémentation

Méthode 1 : Contenu activé partition system_other

Pro: le contenu préchargé n'est pas perdu après le rétablissement de la configuration d'usine. sera copié à partir de la partition B après un redémarrage.

Inconvénient: nécessite de l'espace sur la partition B. Démarrer après rétablissement de la configuration d'usine nécessite davantage de temps pour copier du contenu préchargé.

Pour que les préchargements soient copiés au premier démarrage, le système appelle un script dans /system/bin/preloads_copy.sh. Le script est appelé avec une seule argument (chemin d'accès au point d'installation en lecture seule de system_b partition):

Pour implémenter cette fonctionnalité, effectuez les modifications spécifiques à l'appareil. Voici une exemple tiré de Marlin:

  1. Ajoutez le script qui effectue la copie à device-common.mk. (device/google/marlin/device-common.mk, dans ce cas), comme ceci:
    # 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
    
    Recherchez l'exemple de source de script à l'adresse device/google/marlin/preloads_copy.sh.
  2. Modifiez le fichier init.common.rc pour qu'il crée le répertoire et sous-répertoires /data/preloads nécessaires:
    mkdir /data/preloads 0775 system system
    mkdir /data/preloads/media 0775 system system
    mkdir /data/preloads/demo 0775 system system
    
    Recherchez l'exemple de source du fichier init à l'emplacement suivant: device/google/marlin/init.common.rc
  3. Définissez un nouveau domaine SELinux dans le fichier 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;
    
    Recherchez un exemple de fichier de domaine SELinux à l'adresse /device/google/marlin/+/main/sepolicy/preloads_copy.te.
  4. Enregistrer le domaine dans un nouveau /sepolicy/file_contexts :
    /system/bin/preloads_copy\.sh     u:object_r:preloads_copy_exec:s0
    
    Vous trouverez un exemple de fichier de contextes SELinux à l'adresse device/google/marlin/sepolicy/preloads_copy.te.
  5. Au moment de la compilation, le répertoire avec le contenu préchargé doit être copié dans Partition system_other:
    # 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)
    
    Voici un exemple de modification d'un Makefile qui permet de copier le cache de l'APK du dépôt Git du fournisseur (dans notre cas, il s'agissait provider/google_devices/marlin/preloads) vers l'emplacement situé sur la partition system_other. qui sera ensuite copié dans /data/preloads lorsque l'appareil démarrera pour le premier en temps réel. Ce script s'exécute au moment de la compilation pour préparer l'image system_other. Il attend le contenu préchargé sera disponible dans provider/google_devices/marlin/preloads. OEM est libre de choisir le nom/chemin du dépôt réel.
  6. Le cache de l'APK se trouve dans /data/preloads/file_cache et a la mise en page suivante:
    /data/preloads/file_cache/
        app.package.name.1/
              file1
              fileN
        app.package.name.N/
    
    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 réplique décrite ci-dessus.

Méthode 2 : Contenu lié aux données utilisateur image flashée en usine

Cette approche alternative suppose que le contenu préchargé est déjà inclus dans le répertoire /data/preloads sur la partition /data.

Pro: produit prêt à l'emploi, pas besoin de remanier l'appareil des personnalisations pour copier les fichiers au premier démarrage. Le contenu figure déjà sur le /data.

Inconvénient: les contenus préchargés sont perdus après le rétablissement de la configuration d'usine. Alors que Cela peut être acceptable dans certains cas, mais ne fonctionne pas toujours pour les OEM qui utilisent réinitialiser les appareils après les inspections de contrôle qualité.

Une nouvelle méthode @SystemApi, getPreloadsFileCache(), a été ajoutée à android.content.Context Elle renvoie un chemin absolu vers spécifique à l'application dans le cache préchargé.

Une nouvelle méthode, IPackageManager.deletePreloadsFileCache, a été ajoutée qui permet de supprimer le répertoire des préchargements pour récupérer tout l'espace. Cette méthode peut être appelés uniquement 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 du cache de préchargements. Pour cela les applications doivent être installées dans le répertoire /system/priv-app.

Validation

  • Après le premier démarrage, le contenu de l'appareil doit être Répertoire /data/preloads/file_cache.
  • Le contenu du répertoire file_cache/ doit être supprimé si le l'appareil manque d'espace de stockage.

Utiliser l'exemple ApkCacheTest pour tester le cache de l'APK.

  1. Créez l'application en exécutant la commande suivante depuis le répertoire racine:
    make ApkCacheTest
    
  2. 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. Cette opération nécessite 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
    
  3. Si nécessaire, simulez le répertoire de cache de fichiers et son contenu (nécessite également des droits racine):
    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"
    
  4. Testez l'application. Après avoir installé l'application et créé le répertoire file_cache de test, ouvrez l'application ApkCacheTest. Un fichier test.txt et son contenu devraient s'afficher. Regardez cette capture d'écran pour voir comment ces résultats apparaissent dans l'interface utilisateur.

    Figure 1 : Résultats d'ApkCacheTest.