En este documento, se describe el diseño de una solución de almacenamiento en caché de APKs para la instalación rápida de apps precargadas en un dispositivo que admite particiones A/B.
Los OEM pueden colocar las precargas y las apps populares en la memoria caché de APK almacenadas en la partición B casi vacía en dispositivos nuevos con particiones A/B sin afectar de manera negativa el espacio de datos del usuario. Al tener una caché de APK disponible en el dispositivo, los dispositivos nuevos o restablecidos recientemente a la configuración de fábrica están listos para usarse casi de inmediato, sin necesidad de descargar archivos APK de Google Play.
Casos de uso
- Almacena apps cargadas previamente en la partición B para una configuración más rápida
- Almacena apps populares en la partición B para una restauración más rápida
Requisitos previos
Para usar esta función, el dispositivo debe cumplir con los siguientes requisitos:
- Se instaló la versión de Android 8.1 (O MR1).
- Se implementó la partición A/B
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 no almacena archivos de imagen del sistema, sino contenido precargado, como recursos de demostración para tiendas, archivos OAT y la caché de APK. Después de que los recursos se copien en la partición /data (esto sucede en el primer inicio), la partición B se usará en las actualizaciones inalámbricas (OTA) para descargar versiones actualizadas de la imagen del sistema.
Por lo tanto, la caché del APK no se puede actualizar a través de OTA, sino que solo se puede precargar en una fábrica. El restablecimiento de la configuración de fábrica solo afecta la partición /data. La partición B del sistema aún tiene el contenido precargado hasta que se descarga la imagen OTA. Después de restablecer la configuración de fábrica, el sistema volverá a iniciar el dispositivo por primera vez. 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, se restablece la configuración de fábrica del dispositivo.
Implementación
Enfoque 1. Contenido en la partición system_other
Ventaja: El contenido precargado no se pierde después de restablecer la configuración de fábrica, ya que se copiará de la partición B después de reiniciar el dispositivo.
Desventaja: Requiere espacio en la partición B. El inicio después del restablecimiento de la configuración de fábrica requiere tiempo adicional para copiar el contenido precargado.
Para que las precargas se copien durante el primer inicio, el sistema llama a una secuencia de comandos en /system/bin/preloads_copy.sh
. La secuencia de comandos se llama con un solo argumento (ruta de acceso al punto de montaje de solo lectura para la partición system_b
):
Para implementar esta función, realiza los siguientes cambios específicos del dispositivo. Aquí tienes un ejemplo de Marlin:
- Agrega la secuencia de comandos que realiza la copia al archivo
device-common.mk
(en este caso,device/google/marlin/device-common.mk
), de la siguiente manera: Encuentra el código fuente de la secuencia de comandos de ejemplo en: 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
- Edita el archivo
init.common.rc
para que cree el directorio y los subdirectorios/data/preloads
necesarios: Encuentra un ejemplo de la fuente del archivomkdir /data/preloads 0775 system system
mkdir /data/preloads/media 0775 system system
mkdir /data/preloads/demo 0775 system system
init
en: device/google/marlin/init.common.rc - Define un nuevo dominio de SELinux en el archivo
preloads_copy.te
: Encuentra un ejemplo de archivo de dominio de SELinux en: /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;
- Registra el dominio en un nuevo archivo
:/sepolicy/file_contexts Encuentra un ejemplo de archivo de contextos de SELinux en: device/google/marlin/sepolicy/preloads_copy.te/system/bin/preloads_copy\.sh u:object_r:preloads_copy_exec:s0
- En el momento de la compilación, el directorio con contenido precargado se debe copiar en la partición
system_other
: Este es un ejemplo de un cambio en un archivo Makefile que permite copiar recursos de caché de APK desde el repositorio de Git del proveedor (en nuestro caso, era vendor/google_devices/marlin/preloads) a la ubicación en la partición system_other que se copiará más tarde a /data/preloads cuando el dispositivo se inicie por primera vez. Esta secuencia de comandos se ejecuta en el momento de la compilación para preparar la imagen system_other. Se espera que el contenido precargado esté disponible en vendor/google_devices/marlin/preloads. El OEM puede elegir libremente el nombre o la ruta de acceso del repositorio.# 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)
- La caché de APK se encuentra en
/data/preloads/file_cache
y tiene el siguiente diseño: Esta es la estructura de directorios final en los dispositivos. Los OEM pueden elegir cualquier enfoque de implementación, siempre y cuando la estructura de archivos final replique la que se describió anteriormente./data/preloads/file_cache/ app.package.name.1/ file1 fileN app.package.name.N/
Enfoque 2. Contenido de la imagen de datos del usuario grabada en la 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 personalizar el dispositivo para copiar archivos en el primer inicio. El contenido ya está en la partición /data
.
Desventaja: El contenido precargado se pierde después de restablecer la configuración de fábrica. Si bien esto puede ser aceptable para algunos, es posible que no siempre funcione para los OEM que restablecen la configuración de fábrica de los dispositivos después de realizar inspecciones de control de calidad.
Se agregó un nuevo método @SystemApi, getPreloadsFileCache()
, a android.content.Context
. Devuelve una ruta de acceso absoluta a un directorio específico de la app en la caché precargada.
Se agregó un método nuevo, IPackageManager.deletePreloadsFileCache
, que permite borrar el directorio de precargas para recuperar todo el espacio. Solo las apps con SYSTEM_UID, es decir, el servidor del sistema o Configuración, pueden llamar al método.
Preparación de la app
Solo las apps con privilegios pueden acceder al directorio de caché de precargas. Para tener ese acceso, las apps deben instalarse en el directorio /system/priv-app
.
Validación
- Después del primer inicio, el dispositivo debería tener contenido en el directorio
/data/preloads/file_cache
. - Se debe borrar el contenido del directorio
file_cache/
si el dispositivo se queda sin espacio de almacenamiento.
Usa la app de ejemplo ApkCacheTest para probar la caché de APK.
- Compila la app ejecutando este comando desde el directorio raíz:
make ApkCacheTest
- Instala la app como una app con privilegios (recuerda que solo las apps con privilegios pueden acceder a la caché de APK).
Para ello, se requiere un dispositivo con permisos de administrador:
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
- Simula el directorio de caché de archivos y su contenido si es necesario (también requiere privilegios de administrador):
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"
- Prueba la app. Después de instalarla y crear el directorio
file_cache
de prueba, abre la app de ApkCacheTest. Debería mostrar un archivotest.txt
y su contenido. Consulta esta captura de pantalla para ver cómo aparecen estos resultados en la interfaz de usuario.
Figura 1: Son los resultados de ApkCacheTest.