Almacenamiento en caché de APK

Este documento describe el diseño de una solución de almacenamiento en caché de APK para la instalación rápida de aplicaciones precargadas en un dispositivo que admita particiones A/B.

Los OEM pueden colocar precargas y aplicaciones populares en la caché de APK almacenada en la partición B, en su mayoría vacía, en los nuevos dispositivos con particiones A/B sin afectar el espacio de datos del usuario. Al tener un caché de APK disponible en el dispositivo, los dispositivos nuevos o con restablecimiento de fábrica reciente están listos para usar casi de inmediato, sin necesidad de descargar archivos APK de Google Play.

casos de uso

  • Almacene aplicaciones precargadas en la partición B para una configuración más rápida
  • Almacene aplicaciones populares en la partición B para una restauración más rápida

requisitos previos

Para utilizar esta función, el dispositivo necesita:

  • Versión de Android 8.1 (O MR1) instalada
  • Partición A/B implementada

El contenido precargado solo se puede copiar durante el primer arranque. Esto se debe a que en los dispositivos que admiten actualizaciones del sistema A/B, la partición B en realidad no almacena archivos de imagen del sistema, sino contenido precargado como recursos de demostración minorista, archivos OAT y la caché APK. Después de que los recursos se hayan copiado en la partición /data (esto sucede en el primer arranque), las actualizaciones inalámbricas (OTA) usarán la partición B para descargar versiones actualizadas de la imagen del sistema.

Por lo tanto, la caché de APK no se puede actualizar a través de OTA; solo se puede precargar en una fábrica. El restablecimiento de fábrica afecta solo a la partición /data. La partición del sistema B todavía tiene el contenido precargado hasta que se descarga la imagen OTA. Después del restablecimiento de fábrica, el sistema realizará el primer arranque nuevamente. Esto significa que el almacenamiento en caché de APK no está disponible si la imagen OTA se descarga a la partición B y luego el dispositivo se restablece de fábrica.

Implementación

Enfoque 1. Contenido en system_other partición

Pro : el contenido precargado no se pierde después del restablecimiento de fábrica; se copiará de la partición B después de reiniciar.

Con : Requiere espacio en la partición B. Arrancar después del restablecimiento de fábrica requiere tiempo adicional para copiar el contenido precargado.

Para que las precargas se copien durante el primer arranque, el sistema llama a un script en /system/bin/preloads_copy.sh . El script se llama con un solo argumento (ruta al punto de montaje de solo lectura para la partición system_b ):

Para implementar esta función, realice estos cambios específicos del dispositivo. Aquí hay un ejemplo de Marlin:

  1. Agregue la secuencia de comandos que realiza la copia en el archivo device-common.mk (en este caso, device/google/marlin/device-common.mk ), así:
    # 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
    
    Encuentre una fuente de secuencia de comandos de ejemplo en: device/google/marlin /preloads_copy.sh
  2. Edite el archivo init.common.rc para que cree el directorio /data/preloads y los subdirectorios necesarios:
    mkdir /data/preloads 0775 system system
    mkdir /data/preloads/media 0775 system system
    mkdir /data/preloads/demo 0775 system system
    
    Encuentre una fuente de archivo de init de ejemplo en: device/google/marlin/init.common.rc
  3. Defina un nuevo dominio SELinux en el archivo 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;
    
    Encuentre un archivo de dominio SELinux de ejemplo en: /device/google/marlin/+/master/sepolicy/preloads_copy.te
  4. Registre el dominio en un nuevo /sepolicy/file_contexts :
    /system/bin/preloads_copy\.sh     u:object_r:preloads_copy_exec:s0
    
    Encuentre un ejemplo de archivo de contextos de SELinux en: device/google/marlin/sepolicy/preloads_copy.te
  5. En el momento de la compilación, el directorio con el contenido precargado debe copiarse en la partición 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)
    
    Este es un ejemplo de un cambio en un Makefile que permite copiar recursos de caché APK del repositorio Git del proveedor (en nuestro caso, era vendor/google_devices/ marlin/preloads) a la ubicación en system_other partición que luego se copiará a /data/preloads cuando el dispositivo arranque por primera vez. Este script se ejecuta en el momento de la compilación para preparar la imagen system_other. Espera que el contenido precargado esté disponible en vendor/google_devices/marlin/preloads. El OEM es libre de elegir el nombre/ruta real del repositorio.
  6. La caché de APK se encuentra en /data/preloads/file_cache y tiene el siguiente diseño:
    /data/preloads/file_cache/
        app.package.name.1/
              file1
              fileN
        app.package.name.N/
    
    Esta es la estructura de directorio final en los dispositivos. Los OEM son libres de elegir cualquier enfoque de implementación, siempre que la estructura final del archivo reproduzca la descrita anteriormente.

Enfoque 2. Contenido en la imagen de datos del usuario flasheada en fábrica

Este enfoque alternativo asume que el contenido precargado ya está incluido en el directorio /data/preloads en la partición /data .

Pro : funciona de forma inmediata: no es necesario personalizar el dispositivo para copiar archivos en el primer arranque. El contenido ya está en la partición /data .

Con : el contenido precargado se pierde después de un restablecimiento de fábrica. Si bien esto puede ser aceptable para algunos, es posible que no siempre funcione para los OEM que restablecen los dispositivos de fábrica después de realizar inspecciones de control de calidad.

Se agregó un nuevo método @SystemApi, getPreloadsFileCache() , a android.content.Context . Devuelve una ruta absoluta a un directorio específico de la aplicación en la memoria caché precargada.

Se agregó un nuevo método, IPackageManager.deletePreloadsFileCache , que permite eliminar el directorio de precargas para recuperar todo el espacio. Solo las aplicaciones con SYSTEM_UID, es decir, el servidor del sistema o la configuración, pueden llamar al método.

preparación de la aplicación

Solo las aplicaciones privilegiadas pueden acceder al directorio de caché de precargas. Para ese acceso, las aplicaciones deben estar instaladas en el directorio /system/priv-app .

Validación

  • Después del primer arranque, el dispositivo debe tener contenido en el directorio /data/preloads/file_cache .
  • El contenido del directorio file_cache/ debe eliminarse si el dispositivo se queda sin almacenamiento.

Utilice la aplicación de ejemplo ApkCacheTest para probar la caché de APK.

  1. Compile la aplicación ejecutando este comando desde el directorio raíz:
    make ApkCacheTest
    
  2. Instale la aplicación como una aplicación privilegiada. (Recuerde, solo las aplicaciones privilegiadas pueden acceder a la caché de APK). Esto requiere un dispositivo rooteado:
    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. Simule el directorio de caché de archivos y su contenido si es necesario (también requiere privilegios de 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"
    
  4. Prueba la aplicación. Después de instalar la aplicación y crear el directorio file_cache de prueba, abra la aplicación ApkCacheTest. Debería mostrar un archivo test.txt y su contenido. Vea esta captura de pantalla para ver cómo aparecen estos resultados en la interfaz de usuario.

    Figura 1. Resultados de ApkCacheTest