Los OEMs y los proveedores de SoC que quieran implementar actualizaciones del sistema A/B deben asegurarse de que su bootloader implemente el HAL de boot_control y pase los parámetros correctos al kernel.
Implementa el HAL de control de inicio
Los bootloaders compatibles con A/B deben implementar el HAL de boot_control
en hardware/libhardware/include/hardware/boot_control.h
. Puedes probar las implementaciones con la utilidad system/extras/bootctl
y system/extras/tests/bootloader/
.
También debes implementar la máquina de estados que se muestra a continuación:

Cómo configurar el kernel
Para implementar actualizaciones del sistema A/B, haz lo siguiente:
-
Selecciona las siguientes series de parches del kernel (si es necesario):
- Si inicias el dispositivo sin ramdisk y usas "boot as recovery", elige android-review.googlesource.com/#/c/158491/.
- Para configurar dm-verity sin ramdisk, elige lo que quieras de android-review.googlesource.com/#/q/status:merged+project:kernel/common+branch:android-3.18+topic:A_B_Changes_3.18.
-
Asegúrate de que los argumentos de línea de comandos del kernel contengan los siguientes argumentos adicionales:
… donde el valorskip_initramfs rootwait ro init=/init root="/dev/dm-0 dm=system none ro,0 1 android-verity <public-key-id> <path-to-system-partition>"
<public-key-id>
es el ID de la clave pública que se usa para verificar la firma de la tabla de Verity (para obtener más información, consulta dm-verity). -
Agrega el certificado .X509 que contiene la clave pública al llavero del sistema:
-
Copia el certificado .X509 con formato
.der
en la raíz del directoriokernel
. Si el certificado .X509 tiene el formato de un archivo.pem
, usa el siguiente comandoopenssl
para convertirlo de.pem
a.der
:openssl x509 -in <x509-pem-certificate> -outform der -out <x509-der-certificate>
-
Compila el
zImage
para incluir el certificado como parte del llavero del sistema. Para verificar,revisa la entradaprocfs
(requiere queKEYS_CONFIG_DEBUG_PROC_KEYS
esté habilitado): La inclusión correcta del certificado .X509 indica la presencia de la clave pública en el llavero del sistema (la parte destacada indica el ID de la clave pública).angler:/# cat /proc/keys 1c8a217e I------ 1 perm 1f010000 0 0 asymmetri Android: 7e4333f9bba00adfe0ede979e28ed1920492b40f: X509.RSA 0492b40f [] 2d454e3e I------ 1 perm 1f030000 0 0 keyring .system_keyring: 1/4
-
Reemplaza el espacio por
#
y pásalo como<public-key-id>
en la línea de comandos del kernel. Por ejemplo, pasaAndroid:#7e4333f9bba00adfe0ede979e28ed1920492b40f
en lugar de<public-key-id>
.
-
Copia el certificado .X509 con formato
Cómo configurar variables de compilación
Los bootloaders compatibles con A/B deben cumplir con los siguientes criterios de variables de compilación:
Debe definirse para el objetivo de A/B |
/device/google/marlin/+/android-7.1.0_r1/device-common.mk . De manera opcional, puedes realizar el paso de dex2oat posterior a la instalación (pero antes del reinicio) que se describe en Compilación.
|
---|---|
Muy recomendable para el objetivo A/B |
|
No se puede definir para el objetivo de pruebas A/B |
|
Opcional para compilaciones de depuración | PRODUCT_PACKAGES_DEBUG += update_engine_client |
Cómo establecer particiones (ranuras)
Los dispositivos A/B no necesitan una partición de recuperación ni una partición de caché porque Android ya no usa estas particiones. La partición de datos ahora se usa para el paquete OTA descargado, y el código de la imagen de recuperación está en la partición de inicio. Todas las particiones que se someten a pruebas A/B deben tener los siguientes nombres (las ranuras siempre se denominan a
, b
, etcétera): boot_a
,
boot_b
, system_a
, system_b
, vendor_a
,
vendor_b
.
Caché
En el caso de las actualizaciones que no son de A/B, la partición de caché se usaba para almacenar paquetes OTA descargados y ocultar bloques temporalmente mientras se aplicaban las actualizaciones. Nunca hubo una buena manera de determinar el tamaño de la partición de caché: su tamaño dependía de las actualizaciones que querías aplicar. El peor caso sería una partición de caché tan grande como la imagen del sistema. Con las actualizaciones A/B, no es necesario ocultar bloques (porque siempre escribes en una partición que no se usa actualmente) y, con la transmisión A/B, no es necesario descargar todo el paquete OTA antes de aplicarlo.
Recuperación
El disco RAM de recuperación ahora se encuentra en el archivo boot.img
. Cuando se ingresa al modo de recuperación, el bootloader no puede colocar la opción skip_initramfs
en la línea de comandos del kernel.
En el caso de las actualizaciones que no son A/B, la partición de recuperación contiene el código que se usa para aplicar las actualizaciones. update_engine
ejecuta las actualizaciones A/B en la imagen del sistema iniciada de forma normal.
Todavía hay un modo de recuperación que se usa para implementar el restablecimiento de la configuración de fábrica y la transferencia lateral de paquetes de actualización (de ahí proviene el nombre "recuperación"). El código y los datos del modo de recuperación se almacenan en la partición de arranque normal en un ramdisk. Para iniciar la imagen del sistema, el bootloader le indica al kernel que omita el ramdisk (de lo contrario, el dispositivo se inicia en el modo de recuperación). El modo de recuperación es pequeño (y gran parte ya estaba en la partición de inicio), por lo que el tamaño de la partición de inicio no aumenta.
Fstab
El argumento slotselect
debe estar en la línea para las particiones con A/B. Por ejemplo:
<path-to-block-device>/vendor /vendor ext4 ro wait,verify=<path-to-block-device>/metadata,slotselect
Ninguna partición debe llamarse vendor
. En su lugar, se seleccionará la partición vendor_a
o vendor_b
y se activará en el punto de activación /vendor
.
Argumentos de ranura del kernel
El sufijo de ranura actual se debe pasar a través de un nodo de árbol de dispositivos (DT) específico (/firmware/android/slot_suffix
) o a través de la línea de comandos del kernel androidboot.slot_suffix
o el argumento bootconfig.
De forma predeterminada, fastboot escribe en la memoria flash el zócalo actual en un dispositivo A/B. Si el paquete de actualización también contiene imágenes para el otro zócalo que no es el actual, fastboot también las prenderá. Las opciones disponibles incluyen las siguientes:
-
--slot SLOT
. Anula el comportamiento predeterminado y solicita a fastboot que escriba en el espacio que se pasa como argumento. -
--set-active [SLOT]
. Establece el espacio como activo. Si no se especifica ningún argumento opcional, el espacio actual se establece como activo. fastboot --help
: Obtén detalles sobre los comandos.
Si el bootloader implementa fastboot, debe admitir el comando set_active <slot>
que establece el zócalo activo actual en el zócalo determinado (esto también debe borrar la marca de no inicio de ese zócalo y restablecer el recuento de reintentos a los valores predeterminados). El bootloader también debe admitir las siguientes variables:
-
has-slot:<partition-base-name-without-suffix>
. Muestra “sí” si la partición proporcionada admite espacios, “no” en caso contrario. current-slot
. Muestra el sufijo del zócalo desde el que se iniciará el siguiente.-
slot-count
. Muestra un número entero que representa la cantidad de ranuras disponibles. Actualmente, se admiten dos ranuras, por lo que este valor es2
. -
slot-successful:<slot-suffix>
. Muestra “sí” si el zócalo determinado se marcó como que se inició correctamente, “no” en caso contrario. -
slot-unbootable:<slot-suffix>
. Muestra “sí” si el zócalo determinado está marcado como no inicializable, y “no” en caso contrario. -
slot-retry-count:<slot-suffix>
. Cantidad de reintentos restantes para intentar iniciar el espacio determinado.
Para ver todas las variables, ejecuta fastboot getvar all
.
Genera paquetes inalámbricos
Las herramientas de paquetes OTA siguen los mismos comandos que los comandos para dispositivos que no son A/B. Para generar el archivo target_files.zip
, debes definir las variables de compilación del objetivo de A/B. Las herramientas de paquetes OTA identifican y generan automáticamente paquetes en el formato del actualizador A/B.
Ejemplos:
-
Para generar una OTA completa, haz lo siguiente:
./build/make/tools/releasetools/ota_from_target_files \ dist_output/tardis-target_files.zip \ ota_update.zip
-
Para generar una actualización OTA incremental, haz lo siguiente:
./build/make/tools/releasetools/ota_from_target_files \ -i PREVIOUS-tardis-target_files.zip \ dist_output/tardis-target_files.zip \ incremental_ota_update.zip
Configura particiones
update_engine
puede actualizar cualquier par de particiones A/B definidas en el mismo disco.
Un par de particiones tiene un prefijo común (como system
o boot
) y un sufijo por ranura (como _a
). La variable de compilación AB_OTA_PARTITIONS
configura la lista de particiones para las que el generador de carga útil define una actualización.
Por ejemplo, si se incluye un par de particiones bootloader_a
y booloader_b
(_a
y _b
son los sufijos de ranura), puedes actualizar estas particiones especificando lo siguiente en la configuración del producto o la placa:
AB_OTA_PARTITIONS := \ boot \ system \ bootloader
El resto del sistema no debe modificar todas las particiones que actualizó update_engine
. Durante las actualizaciones incrementales o delta, se usan los datos binarios del espacio actual para generar los datos del espacio nuevo. Cualquier modificación puede hacer que los datos de los nuevos segmentos no se verifiquen durante el proceso de actualización y, por lo tanto, que esta falle.
Configura la postinstalación
Puedes configurar el paso de postinstalación de forma diferente para cada partición actualizada con un conjunto de
pares clave-valor. Para ejecutar un programa ubicado en /system/usr/bin/postinst
en una imagen nueva, especifica la ruta de acceso en relación con la raíz del sistema de archivos en la partición del sistema.
Por ejemplo, usr/bin/postinst
es system/usr/bin/postinst
(si no se usa un disco RAM). Además, especifica el tipo de sistema de archivos que se pasará a la llamada al sistema mount(2)
. Agrega lo siguiente a los archivos .mk
del producto o dispositivo (si corresponde):
AB_OTA_POSTINSTALL_CONFIG += \ RUN_POSTINSTALL_system=true \ POSTINSTALL_PATH_system=usr/bin/postinst \ FILESYSTEM_TYPE_system=ext4
Compila apps
Las apps se pueden compilar en segundo plano antes del reinicio con la nueva imagen del sistema. Para compilar apps en segundo plano, agrega lo siguiente a la configuración del dispositivo del producto (en device.mk del producto):
-
Incluye los componentes nativos en la compilación para asegurarte de que la secuencia de comandos de compilación y los objetos binarios se compilen y se incluyan en la imagen del sistema.
# A/B OTA dexopt package PRODUCT_PACKAGES += otapreopt_script
-
Conecta la secuencia de comandos de compilación a
update_engine
para que se ejecute como un paso posterior a la instalación.# A/B OTA dexopt update_engine hookup AB_OTA_POSTINSTALL_CONFIG += \ RUN_POSTINSTALL_system=true \ POSTINSTALL_PATH_system=system/bin/otapreopt_script \ FILESYSTEM_TYPE_system=ext4 \ POSTINSTALL_OPTIONAL_system=true
Para obtener ayuda para instalar los archivos preopcionados en la segunda partición del sistema sin usar, consulta Primera instalación de arranque de archivos DEX_PREOPT.