Reduce el tamaño de la actualización OTA

En esta página, se describen los cambios que se agregaron a AOSP para reducir los cambios de archivos innecesarios entre compilaciones. Los implementadores de dispositivos que mantienen sus propios sistemas de compilación pueden usar esta información como guía para reducir el tamaño de sus actualizaciones inalámbricas (OTA).

En ocasiones, las actualizaciones OTA de Android contienen archivos modificados que no corresponden a cambios de código. En realidad, son artefactos del sistema de compilación. Esto puede ocurrir cuando el mismo código, compilado en diferentes momentos, desde diferentes directorios o en diferentes máquinas, produce una gran cantidad de archivos modificados. Estos archivos adicionales aumentan el tamaño de un parche OTA y dificultan la determinación de qué código cambió.

Para que el contenido de una actualización OTA sea más transparente, AOSP incluye cambios en el sistema de compilación diseñados para reducir el tamaño de los parches OTA. Se eliminaron los cambios de archivos innecesarios entre compilaciones, y solo los archivos relacionados con parches se incluyen en las actualizaciones OTA. AOSP también incluye una herramienta de comparación de compilaciones, que filtra los cambios comunes de archivos relacionados con la compilación para proporcionar una comparación de archivos de compilación más clara, y una herramienta de asignación de bloques, que te ayuda a mantener la asignación de bloques coherente.

Un sistema de compilación puede crear parches innecesariamente grandes de varias maneras. Para mitigar esto, en Android 8.0 y versiones posteriores, se implementaron nuevas funciones para reducir el tamaño del parche para cada diferencia de archivo. Entre las mejoras que redujeron el tamaño de los paquetes de actualización OTA, se incluyen las siguientes:

  • Uso de ZSTD, un algoritmo de compresión sin pérdidas de uso general para imágenes completas en actualizaciones de dispositivos que no son A/B. ZSTD se puede personalizar para obtener relaciones de compresión más altas aumentando el nivel de compresión. El nivel de compresión se establece durante el tiempo de generación de OTA y se puede configurar pasando la marca --vabc_compression_param=zstd,$COMPRESSION_LEVEL.
  • Se aumentó el tamaño de la ventana de compresión que se usa durante la actualización OTA. Para establecer el tamaño máximo de la ventana de compresión, puedes personalizar el parámetro de compilación en el archivo .mk de un dispositivo. Esta variable se establece como PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR := 262144.
  • Uso de la recompresión de Puffin, una herramienta de parcheo determinista para flujos de desinflado que controla las funciones de compresión y diferencia para la generación de actualizaciones OTA A/B.
  • Cambios en el uso de la herramienta de generación de deltas, como la forma en que se usa la biblioteca bsdiff para comprimir parches. En Android 9 y versiones posteriores, la herramienta bsdiff selecciona el algoritmo de compresión que brindaría los mejores resultados de compresión para un parche.
  • Las mejoras en update_engine generaron menos consumo de memoria cuando se aplican parches para las actualizaciones de dispositivos A/B.

En las siguientes secciones, se analizan varios problemas que afectan los tamaños de las actualizaciones OTA, sus soluciones y ejemplos de implementación en AOSP.

Orden de archivos

Problema: Los sistemas de archivos no garantizan un orden de archivos cuando se solicita una lista de archivos en un directorio, aunque suele ser el mismo para la misma confirmación de la compra. Las herramientas como ls ordenan los resultados de forma predeterminada, pero la función de comodín que usan comandos como find y make no los ordenan. Antes de usar estas herramientas, debes ordenar los resultados.

Solución: Cuando uses herramientas como find y make con la función de comodín, ordena el resultado de estos comandos antes de usarlos. Cuando uses $(wildcard) o $(shell find) en archivos Android.mk, ordénalos también. Algunas herramientas, como Java, ordenan las entradas, por lo que, antes de ordenar los archivos, verifica que la herramienta que usas no lo haya hecho.

Ejemplos: Se corrigieron muchas instancias en el sistema de compilación principal con la macro all-*-files-under integrada, que incluye all-cpp-files-under (ya que varias definiciones se distribuyeron en otros archivos de configuración de make). Para obtener más información, consulta los siguientes recursos:

Directorio de compilación

Problema: Cambiar el directorio en el que se compilan los elementos puede hacer que los objetos binarios sean diferentes. La mayoría de las rutas de acceso en la compilación de Android son rutas de acceso relativas, por lo que __FILE__ en C/C++ no es un problema. Sin embargo, los símbolos de depuración codifican la ruta de acceso completa de forma predeterminada, y .note.gnu.build-id se genera a partir del hash del binario despojado previamente, por lo que cambiará si cambian los símbolos de depuración.

Solución: AOSP ahora hace que las rutas de depuración sean relativas. Para obtener más información, consulta CL: https://android.googlesource.com/platform/build/+/6a66a887baadc9eb3d0d60e26f748b8453e27a02.

Marcas de tiempo

Problema: Las marcas de tiempo en el resultado de la compilación generan cambios innecesarios en los archivos. Es probable que esto suceda en las siguientes ubicaciones:

  • Macros __DATE__/__TIME__/__TIMESTAMP__ en código C o C++
  • Marcas de tiempo incorporadas en archivos basados en ZIP

Soluciones o ejemplos: Para quitar las marcas de tiempo del resultado de la compilación, usa las instrucciones que se indican a continuación en __DATE__/__TIME__/__TIMESTAMP__ en C/C++. y Marcas de tiempo incorporadas en archivos.

__DATE__/__TIME__/__TIMESTAMP__ en C/C++

Estas macros siempre producen resultados diferentes para compilaciones diferentes, por lo que no debes usarlas. Estas son algunas opciones para eliminar estas macros:

Marcas de tiempo incorporadas en archivos (zip, jar)

Android 7.0 solucionó el problema de las marcas de tiempo incorporadas en los archivos ZIP agregando -X a todos los usos del comando zip. Esto quitó el UID/GID del compilador y la marca de tiempo de Unix extendida del archivo ZIP.

Una nueva herramienta, ziptime (ubicada en /platform/build/+/android16-release/tools/ziptime/), restablece las marcas de tiempo normales en los encabezados de ZIP. Para obtener más información, consulta el archivo README.

La herramienta signapk establece marcas de tiempo para los archivos APK que pueden variar según la zona horaria del servidor. Para obtener más información, consulta el CL https://android.googlesource.com/platform/build/+/6c41036bcf35fe39162b50d27533f0f3bfab3028.

La herramienta signapk establece marcas de tiempo para los archivos APK que pueden variar según la zona horaria del servidor. Para obtener más información, consulta el CL https://android.googlesource.com/platform/build/+/6c41036bcf35fe39162b50d27533f0f3bfab3028.

Cadenas de versión

Problema: Las cadenas de versión del APK a menudo tenían BUILD_NUMBER agregado a sus versiones codificadas. Incluso si no se cambiara nada más en un APK, el APK seguiría siendo diferente.

Solución: Quita el número de compilación de la cadena de versión del APK.

Ejemplos:

Habilita el procesamiento de verificación integrado en el dispositivo

Si dm-verity está habilitado en tu dispositivo, las herramientas OTA detectan automáticamente tu configuración de Verity y habilitan el procesamiento de Verity en el dispositivo. Esto permite que los bloques de Verity se calculen en dispositivos Android, en lugar de almacenarse como bytes sin procesar en tu paquete OTA. Los bloques de Verity pueden usar aproximadamente 16 MB para una partición de 2 GB.

Sin embargo, el procesamiento de la verificación en el dispositivo puede llevar mucho tiempo. Específicamente, el código de corrección de errores de reenvío puede tardar mucho tiempo. En dispositivos Pixel, suele tardar hasta 10 minutos. En dispositivos de baja gama, podría tardar más. Si quieres inhabilitar el procesamiento de Verity integrado en el dispositivo, pero aún así habilitar dm-verity, puedes pasar --disable_fec_computation a la herramienta ota_from_target_files cuando generes una actualización OTA. Esta marca inhabilita el procesamiento de verificación en el dispositivo durante las actualizaciones OTA. Disminuye el tiempo de instalación inalámbrica, pero aumenta el tamaño del paquete inalámbrico. Si tu dispositivo no tiene habilitado dm-verity, pasar esta marca no tiene efecto.

Herramientas de compilación coherentes

Problema: Las herramientas que generan archivos instalados deben ser coherentes (una entrada determinada siempre debe producir el mismo resultado).

Soluciones o ejemplos: Se requirieron cambios en las siguientes herramientas de compilación:

Usa la herramienta de diferencias de compilación

En los casos en que no es posible eliminar los cambios de archivos relacionados con la compilación, AOSP incluye una herramienta de comparación de compilaciones, target_files_diff.py, para comparar dos paquetes de archivos. Esta herramienta realiza una diferencia recursiva entre dos compilaciones, sin incluir los cambios comunes de archivos relacionados con la compilación, como los siguientes:

  • Cambios esperados en el resultado de la compilación (por ejemplo, debido a un cambio en el número de compilación)
  • Cambios debido a problemas conocidos en el sistema de compilación actual.

Para usar la herramienta de diferencias de compilación, ejecuta el siguiente comando:

target_files_diff.py dir1 dir2

dir1 y dir2 son directorios base que contienen los archivos de destino extraídos para cada compilación.

Mantén la coherencia de la asignación de bloques

En un archivo determinado, aunque su contenido permanezca igual entre dos compilaciones, es posible que los bloques reales que contienen los datos hayan cambiado. Como resultado, el actualizador debe realizar E/S innecesarias para mover los bloques para una actualización OTA.

En una actualización OTA A/B virtual, la E/S innecesaria puede aumentar en gran medida el espacio de almacenamiento necesario para almacenar la instantánea de copia en escritura. En una actualización OTA que no es A/B, mover los bloques para una actualización OTA contribuye al tiempo de actualización, ya que hay más E/S debido a los movimientos de bloques.

Para solucionar este problema, en Android 7.0, Google amplió la herramienta make_ext4fs para mantener la asignación de bloques coherente en todas las compilaciones. La herramienta make_ext4fs acepta una marca -d base_fs opcional que intenta asignar archivos a los mismos bloques cuando se genera una imagen ext4. Puedes extraer los archivos de asignación de bloques (como los archivos de mapa base_fs) del archivo ZIP de los archivos de destino de una compilación anterior. Para cada partición ext4, hay un archivo .map en el directorio IMAGES (por ejemplo, IMAGES/system.map corresponde a la partición system). Luego, estos archivos base_fs se pueden registrar y especificar a través de PRODUCT_<partition>_BASE_FS_PATH, como en este ejemplo:

  PRODUCT_SYSTEM_BASE_FS_PATH := path/to/base_fs_files/base_system.map
  PRODUCT_SYSTEM_EXT_BASE_FS_PATH := path/to/base_fs_files/base_system_ext.map
  PRODUCT_VENDOR_BASE_FS_PATH := path/to/base_fs_files/base_vendor.map
  PRODUCT_PRODUCT_BASE_FS_PATH := path/to/base_fs_files/base_product.map
  PRODUCT_ODM_BASE_FS_PATH := path/to/base_fs_files/base_odm.map

Si bien esto no ayuda a reducir el tamaño general del paquete OTA, mejora el rendimiento de la actualización OTA, ya que reduce la cantidad de E/S. En el caso de las actualizaciones A/B virtuales, reduce de forma drástica la cantidad de espacio de almacenamiento necesario para aplicar la actualización inalámbrica.

Evita actualizar las apps

Además de minimizar las diferencias de compilación, puedes reducir los tamaños de las actualizaciones OTA si excluyes las actualizaciones para las apps que reciben actualizaciones a través de tiendas de aplicaciones. Los APKs suelen representar una parte significativa de varias particiones en un dispositivo. Incluir las versiones más recientes de las apps que se actualizan en las tiendas de aplicaciones en una actualización OTA puede tener un gran impacto en el tamaño de los paquetes OTA y proporcionar pocos beneficios para los usuarios. Cuando los usuarios reciben un paquete OTA, es posible que ya tengan la app actualizada o una versión aún más reciente, que recibieron directamente de las tiendas de aplicaciones.