Implementa A/B virtual

Para implementar A/B virtual en un dispositivo nuevo o adaptar un dispositivo lanzado, debes realizar cambios en el código específico del dispositivo.

Marcas de compilación

Los dispositivos que usan A/B virtual deben estar configurados como un dispositivo A/B y deben lanzarse con particiones dinámicas.

Para los dispositivos que se lanzan con A/B virtual, configúralos para que hereden la configuración base del dispositivo A/B virtual:

$(call inherit-product, \
    $(SRC_TARGET_DIR)/product/virtual_ab_ota.mk)

Los dispositivos que se lanzan con A/B virtual solo necesitan la mitad del tamaño de la placa para BOARD_SUPER_PARTITION_SIZE, ya que las ranuras B ya no están en super. Es decir, BOARD_SUPER_PARTITION_SIZE debe ser mayor o igual que sum(tamaño de los grupos de actualización) + sobrecarga, que, a su vez, debe ser mayor o igual que sum(tamaño de las particiones) + sobrecarga.

Para Android 13 y versiones posteriores, para habilitar las instantáneas comprimidas con A/B virtual, hereda la siguiente configuración base:

$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_ramdisk.mk)
$(call inherit-product, \
    $(SRC_TARGET_DIR)/product/virtual_ab_ota/vabc_features.mk)

Esto habilita las instantáneas del espacio del usuario con A/B virtual mientras se usa un método de compresión no operativo. Luego, puedes configurar el método de compresión en uno de los métodos admitidos, zstd y lz4. Para Android 15, la compresión se puede personalizar aún más para satisfacer las necesidades del dispositivo. Para obtener más información, consulta Ajuste de la compresión.

PRODUCT_VIRTUAL_AB_COMPRESSION_METHOD := lz4
PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR := 65536

Para Android 12, para habilitar las instantáneas comprimidas con A/B virtual, hereda la siguiente configuración base:

$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_ramdisk.mk)
$(call inherit-product, \
    $(SRC_TARGET_DIR)/product/virtual_ab_ota/compression.mk)

Compresión XOR

En el caso de los dispositivos que se actualizan a Android 13 y versiones posteriores, la función de compresión XOR no está habilitada de forma predeterminada. Para habilitar la compresión XOR, agrega lo siguiente al archivo .mk del dispositivo.

PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.compression.xor.enabled=true

La compresión XOR está habilitada de forma predeterminada para los dispositivos que heredan de android_t_baseline.mk.

Combinación de espacio del usuario

En la versión moderna de A/B virtual (Android T y versiones posteriores), el proceso de combinación de instantáneas se realiza por completo en el espacio del usuario. Este cambio es posible gracias a snapuserd y dm-user. Los dispositivos que se lanzan con Android 13 y versiones posteriores tienen habilitada la combinación de espacio del usuario de forma predeterminada, y, para los dispositivos más antiguos que se actualizan, esta propiedad se puede configurar con lo siguiente:

PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.userspace.snapshots.enabled=true

HAL de control de arranque

El control de arranque HAL proporciona una interfaz para que los clientes de OTA controlen las ranuras de arranque. A/B virtual requiere una actualización de versión secundaria del HAL de control de arranque porque se necesitan APIs adicionales para garantizar que el bootloader esté protegido durante el restablecimiento de la configuración de fábrica o el flasheo. Consulta IBootControl.hal y types.hal para obtener la versión más reciente de la definición de HAL.

// hardware/interfaces/boot/1.1/types.hal
enum MergeStatus : uint8_t {
    NONE, UNKNOWN, SNAPSHOTTED, MERGING, CANCELLED };

// hardware/interfaces/boot/1.1/IBootControl.hal
package android.hardware.boot@1.1;
interface IBootControl extends @1.0::IBootControl {
    setSnapshotMergeStatus(MergeStatus status)
        generates (bool success);
    getSnapshotMergeStatus()
        generates (MergeStatus status);
}
// Recommended implementation

Return<bool> BootControl::setSnapshotMergeStatus(MergeStatus v) {
    // Write value to persistent storage
    // e.g. misc partition (using libbootloader_message)
    // bootloader rejects wipe when status is SNAPSHOTTED
    // or MERGING
}

Cambios en Fstab

La integridad de la partición de metadatos es esencial para el proceso de arranque, en especial, justo después de que se aplica una actualización OTA. Por lo tanto, la partición de metadatos debe verificarse antes de que first_stage_init la monte. Para asegurarte de que esto suceda, agrega la marca check fs_mgr a la entrada de /metadata. A continuación, se muestra un ejemplo:

/dev/block/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard,sync wait,formattable,first_stage_mount,check

Requisitos del kernel

Para habilitar la creación de instantáneas, establece CONFIG_DM_SNAPSHOT en true.

Para los dispositivos que usan F2FS, incluye la marca f2fs: export FS_NOCOW_FL en el parche del kernel del usuario para corregir la fijación de archivos. También incluye el parche del kernel de archivos fijados alineados compatibles con f2fs: support aligned pinned file.

A/B virtual se basa en las funciones agregadas en la versión 4.3 del kernel: el overflow bit de estado en los objetivos snapshot y snapshot-merge. Todos los dispositivos que se lanzan con Android 9 y versiones posteriores ya deberían tener la versión de kernel 4.4 o una posterior.

Para habilitar las instantáneas comprimidas, la versión de kernel mínima admitida es 4.19. Establece CONFIG_DM_USER=m o CONFIG_DM_USER=y. Si usas la primera (un módulo), el módulo debe cargarse en el disco RAM de la primera etapa. Para ello, agrega la siguiente línea al archivo Makefile del dispositivo:

BOARD_GENERIC_RAMDISK_KERNEL_MODULES_LOAD := dm-user.ko

Cambios en las herramientas de Fastboot

Android 11 realiza los siguientes cambios en el protocolo fastboot:

  • getvar snapshot-update-status : Muestra el valor que el HAL de control de arranque comunicó al cargador de arranque:
    • Si el estado es MERGING, el cargador de arranque debe mostrar merging.
    • Si el estado es SNAPSHOTTED, el cargador de arranque debe mostrar snapshotted.
    • De lo contrario, el cargador de arranque debe mostrar none.
  • snapshot-update merge : Completa una operación de combinación y arranca en recovery/fastbootd si es necesario. Este comando solo es válido si snapshot-update-status es merging y solo se admite en fastbootd.
  • snapshot-update cancel : Establece el estado de combinación del HAL de control de arranque en CANCELLED. Este comando no es válido cuando el dispositivo está bloqueado.
  • erase o wipe: Una operación erase o wipe de metadata, userdata o una partición que contiene el estado de combinación para el HAL de control de arranque debe verificar el estado de combinación de la instantánea. Si el estado es MERGING o SNAPSHOTTED, el dispositivo debe anular la operación.
  • set_active : Un comando set_active que cambia la ranura activa debe verificar el estado de combinación de la instantánea. Si el estado es MERGING, el dispositivo debe anular la operación. La ranura se puede cambiar de forma segura en el estado SNAPSHOTTED.

Estos cambios están diseñados para evitar que un dispositivo se vuelva no arrancable de forma accidental, pero pueden interrumpir las herramientas automatizadas. Cuando los comandos se usan como un componente del flasheo de todas las particiones, como la ejecución de fastboot flashall, se recomienda usar el siguiente flujo:

  1. Consulta getvar snapshot-update-status.
  2. Si es merging o snapshotted, emite snapshot-update cancel.
  3. Continúa con los pasos de flasheo.

Reduce los requisitos de almacenamiento

Se recomienda usar la herramienta de asignación de bloques en los dispositivos que no tienen almacenamiento A/B completo asignado en super y que esperan usar /data según sea necesario. La herramienta de asignación de bloques mantiene la asignación de bloques coherente entre las compilaciones, lo que reduce las escrituras innecesarias en la instantánea. Esto se documenta en Reducción del tamaño de OTA.

Algoritmos de compresión OTA

Los paquetes OTA se pueden ajustar para diferentes métricas de rendimiento. Android proporciona varios métodos de compresión admitidos (lz4, zstd y none) que tienen compensaciones entre el tiempo de instalación, el uso del espacio COW, el tiempo de arranque y el tiempo de combinación de instantáneas. La opción predeterminada habilitada para ab virtual con compresión es el lz4 compression method.

Ajuste de la compresión

Los algoritmos de compresión se pueden personalizar aún más con dos métodos: (nivel de compresión) (la cantidad de compresión que se logra a expensas de la velocidad) y (factor de compresión) (el tamaño máximo de la ventana comprimible). El nivel de compresión está disponible para ciertos algoritmos, como zstd, y cambiar el nivel implica una compensación entre la velocidad y el índice de compresión. El factor de compresión describe el tamaño máximo de la ventana de compresión que se usa durante la instalación de OTA. El valor predeterminado se establece en 64k, pero se puede anular personalizando el parámetro de compilación PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR. Factores de compresión admitidos: 4k, 8k, 16k, 32k, 64k, 128k y 256k.

PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR := 65536

OTA incremental en el Pixel 8 Pro

Tiempo de instalación sin la fase de postinstalación Uso del espacio COW Tiempo de arranque posterior a la OTA Tiempo de combinación de instantáneas
lz4 18 min 15s 2.5 GB 32.7 s 98.6 s
zstd 24 min 49s 2.05 GB 36.3 s 133.2 s
none 16 min 42s 4.76 GB 28.7 s 76.6 s

OTA completa en el Pixel 8 Pro

Tiempo de instalación sin la fase de postinstalación Uso del espacio COW Tiempo de arranque posterior a la OTA Tiempo de combinación de instantáneas
lz4 15 min 11s 4.16 GB 17.6 s 82.2 s
zstd 16 min 19s 3.46 GB 21.0 s 106.3 s
none 13 min 33s 6.39 GB 18.5 s 92.5 s