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, mayoritariamente vacía, en nuevos dispositivos con particiones A/B sin afectar el espacio de datos de cara al usuario. Al tener un caché de APK disponible en el dispositivo, los dispositivos nuevos o recientemente restablecidos de fábrica 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 inicio. 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 el caché APK. Después de que los recursos se hayan copiado a la partición /data (esto sucede en el primer arranque), las actualizaciones inalámbricas (OTA) utilizarán la partición B para descargar versiones actualizadas de la imagen del sistema.

Por lo tanto, la caché del APK no se puede actualizar mediante OTA; solo se puede precargar en 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 inicio nuevamente. Esto significa que el almacenamiento en caché de APK no está disponible si la imagen OTA se descarga en la partición B y luego el dispositivo se restablece de fábrica.

Implementación

Método 1. Contenido en la partición system_other

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

Desventaja : Requiere espacio en la partición B. El inicio 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 único 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 el script que realiza la copia al 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 la fuente del script de ejemplo en: dispositivo/google/marlin /preloads_copy.sh
  2. Edite el archivo init.common.rc para que cree el directorio y los subdirectorios /data/preloads necesarios:
    mkdir /data/preloads 0775 system system
    mkdir /data/preloads/media 0775 system system
    mkdir /data/preloads/demo 0775 system system
    
    Encuentre la fuente del archivo 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/+/main/sepolicy/preloads_copy.te
  4. Registra el dominio en un nuevo Archivo /sepolicy/file_contexts :
    /system/bin/preloads_copy\.sh     u:object_r:preloads_copy_exec:s0
    
    Encuentre un archivo de contextos SELinux de ejemplo en: dispositivo/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 desde el repositorio Git del proveedor (en nuestro caso fue proveedor/google_devices/ marlin/preloads) a la ubicación en system_other partición que luego se copiará en /data/preloads cuando el dispositivo se inicie 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 proveedor/google_devices/marlin/preloads. OEM es libre de elegir el nombre/ruta real del repositorio.
  6. El 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 de archivos final replique la descrita anteriormente.

Método 2. El contenido de la imagen de datos del usuario aparece en fábrica

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

Ventaja : funciona de inmediato: no es necesario realizar personalizaciones del dispositivo para copiar archivos en el primer arranque. El contenido ya está en la partición /data .

Desventaja : 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 el caché precargado.

Se agregó un nuevo método, IPackageManager.deletePreloadsFileCache , que permite eliminar el directorio de cargas previas para recuperar todo el espacio. El método solo puede ser invocado por aplicaciones con SYSTEM_UID, es decir, servidor del sistema o Configuración.

Preparación de la aplicación

Sólo las aplicaciones privilegiadas pueden acceder al directorio de caché de precargas. Para ese acceso, las aplicaciones deben instalarse en el directorio /system/priv-app .

Validación

  • Después del primer arranque, el dispositivo debería 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 ApkCacheTest de ejemplo 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 al 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.