El A/B virtual es el mecanismo de actualización principal de Android. A/B virtual se basa en actualizaciones de A/B heredadas (consulta Actualizaciones del sistema A/B) y no A/B, que dejarán de estar disponibles en 15 para reducir la sobrecarga de espacio de las actualizaciones.
En realidad, la A/B virtual no tiene un espacio adicional para particiones dinámicas. Consulta particiones dinámicas. En su lugar, la delta se escribe en una instantánea y, luego, se combina en la partición base después de confirmar que el inicio se realizó correctamente. A/B virtual usa un formato de instantáneas específico de Android. Consulta el formato COW para las instantáneas comprimidas, que permite comprimir las instantáneas y minimizar el uso del espacio en el disco. En una actualización OTA completa, el tamaño de la instantánea se reduce en alrededor de un 45% con la compresión, y el tamaño de la instantánea OTA incremental se reduce en alrededor de un 55%.
Android 12 ofrece la opción de compresión de A/B virtual para comprimir las particiones con instantáneas. A/B virtual ofrece lo siguiente:
- Las actualizaciones de A/B virtuales son sin interrupciones (la actualización se realiza por completo en segundo plano mientras el dispositivo está en funcionamiento), al igual que las actualizaciones de A/B. Las actualizaciones de A/B virtual minimizan el tiempo que un dispositivo está desconectado y no se puede usar.
- Las actualizaciones de A/B virtuales se pueden revertir. Si el SO nuevo no se inicia, los dispositivos vuelven automáticamente a la versión anterior.
- Las actualizaciones A/B virtuales usan un espacio adicional mínimo, ya que duplican solo las particiones que usa el bootloader. Se crean instantáneas de otras particiones actualizables.
Información general y terminología
En esta sección, se define la terminología y se describe la tecnología que admite pruebas A/B virtuales. Durante la instalación OTA, los datos del sistema operativo nuevo se escriben en su nuevo espacio para particiones físicas o en un dispositivo COW específico de Android. Una vez que se reinicia el dispositivo, los datos de la partición dinámica se vuelven a combinar con el dispositivo base mediante el uso de dm-user y daemon Snapuserd. Este proceso ocurre completamente en el espacio del usuario.
Device-mapper
Device-mapper es una capa de bloques virtual de Linux que se usa con frecuencia en Android. Con las particiones dinámicas, las particiones como /system
son una pila de dispositivos en capas:
- En la parte inferior de la pila, se encuentra la partición física super (por ejemplo,
/dev/block/by-name/super
). - En el medio, hay un dispositivo
dm-linear
que especifica qué bloques de la superpartición forman la partición dinámica determinada. Aparece como/dev/block/mapper/system_[a|b]
en un dispositivo A/B o como/dev/block/mapper/system
en un dispositivo que no es A/B. - En la parte superior, se encuentra un dispositivo
dm-verity
creado para particiones verificadas. Este dispositivo verifica que los bloqueos en el dispositivodm-linear
estén firmados de forma correcta. Se muestra como/dev/block/mapper/system-verity
y es la fuente del punto de activación/system
.
En la Figura 1, se muestra cómo se ve la pila debajo del punto de activación /system
.
Figura 1: Se apila debajo del punto de activación /system.
Instantáneas comprimidas
En Android 12 y versiones posteriores, como los requisitos de espacio en la partición /data
pueden ser altos, puedes habilitar instantáneas comprimidas en tu compilación para abordar los requisitos de espacio más altos de la partición /data
.
Las instantáneas comprimidas de A/B virtual se compilan sobre los siguientes componentes disponibles en Android 12 y versiones posteriores:
dm-user
, un módulo de kernel similar a FUSE que permite que el espacio del usuario implemente dispositivos de almacenamiento en bloquesnapuserd
, un daemon de espacio de usuario para implementar un nuevo formato de instantánea.
Estos componentes habilitan la compresión. Los otros cambios necesarios que se realizan con el fin de implementar las capacidades de las instantáneas comprimidas se proporcionan en las siguientes secciones: Formato COW para instantáneas comprimidas, dm-user y Snapuserd.
Formato COW para instantáneas comprimidas
En Android 12 y versiones posteriores, las instantáneas comprimidas usan un formato de COW específico de Android. El formato COW contiene metadatos sobre la OTA y tiene búferes distintos que contienen operaciones de COW y datos nuevos del sistema operativo. En comparación con el formato de instantánea del kernel que solo se permitía para las operaciones replace (Reemplazar bloque X en la imagen base con el contenido del bloque Y en la instantánea), el formato COW de instantáneas comprimidas de Android es más expresivo y admite las siguientes operaciones:
- Copiar: El bloque X en el dispositivo base debe reemplazarse por el bloque Y en el dispositivo base.
- Reemplazo: El bloque X en el dispositivo base debe reemplazarse por el contenido del bloque Y en la instantánea. Cada uno de estos bloques está comprimido en gz.
- Cero: El bloque X del dispositivo base debe reemplazarse por ceros.
- XOR: El dispositivo COW almacena bytes comprimidos XOR entre el bloque X y el bloque Y. (Disponible en Android 13 y versiones posteriores).
Las actualizaciones OTA completas consisten solo en operaciones de reemplazo y cero. Además, las actualizaciones OTA incrementales pueden tener operaciones de copia.
El diseño completo de la instantánea en el disco se ve de la siguiente manera:
Figura 2: Formato COW de Android en el disco
dm-user
El módulo del kernel dm-user permite que userspace
implemente dispositivos de bloqueo de mapeo de dispositivos. Una entrada de la tabla dm-user crea un dispositivo misceláneo en /dev/dm-user/<control-name>
. Un proceso userspace
puede sondear el dispositivo para recibir solicitudes de lectura y escritura del kernel. Cada solicitud tiene un búfer asociado para que el espacio de usuario lo propague (para una operación de escritura) o lo propague (para una operación de lectura).
El módulo de kernel dm-user
proporciona una nueva interfaz visible para el usuario al kernel que no forma parte de la base de código ascendente de kernel.org. Hasta que lo haga, Google se reserva el derecho de modificar la interfaz dm-user
en Android.
Snapuserd
El componente de espacio de usuario snapuserd
para dm-user
implementa la compresión A/B virtual. Snapuserd es un daemon de espacio de usuario a cargo de escribir y leer los dispositivos COW de Android. Toda la E/S de la instantánea debe pasar por este servicio.
Durante la instalación inalámbrica, Snapuserd (con compresión) escribe los datos nuevos del sistema operativo en la instantánea. Aquí también se controla el análisis de los metadatos y el desempaquetado de datos de bloques nuevos.
Compresión XOR
En el caso de los dispositivos que se lanzan con Android 13 y versiones posteriores, la función de compresión XOR, que está habilitada de forma predeterminada, permite que las instantáneas del espacio del usuario almacenen bytes comprimidos XOR entre bloques antiguos y nuevos. Cuando solo se cambian algunos bytes en un bloque en una actualización A/B virtual, el esquema de almacenamiento de compresión XOR usa menos espacio que el esquema de almacenamiento predeterminado, ya que las instantáneas no almacenan 4K de bytes completos. Esta reducción en el tamaño de la instantánea es posible porque los datos XOR contienen muchos ceros y son más fáciles de comprimir que los datos de bloque sin procesar. En los dispositivos Pixel, la compresión XOR reduce el tamaño de los resúmenes entre un 25% y un 40%.
En el caso de los dispositivos que se actualizan a Android 13 y versiones posteriores, se debe habilitar la compresión XOR. Para obtener más información, consulta Compresión XOR.
Combinación de instantáneas
En el caso de los dispositivos que se lanzan con Android 13 y versiones posteriores, el componente de espacio de usuario snapuserd
realiza los procesos de combinación de instantáneas en la compresión A/B virtual. En el caso de los dispositivos que se actualizan a Android 13 y versiones posteriores, esta función debe estar habilitada. Para obtener más información, consulta Combinación de espacio de usuario.
A continuación, se describe el proceso de compresión A/B virtual:
- El framework activa la partición
/system
de un dispositivodm-verity
, que se apila sobre un dispositivodm-user
. Esto significa que cada E/S del sistema de archivos raíz se enruta adm-user
. dm-user
enruta la E/S al daemonsnapuserd
del espacio de usuario, que controla la solicitud de E/S.- Cuando se completa la operación de combinación, el framework contrae
dm-verity
sobredm-linear
(system_base
) y quitadm-user
.
Figura 3: Proceso de compresión de A/B virtual
El proceso de combinación de instantáneas se puede interrumpir. Si el dispositivo se reinicia durante el proceso de combinación, este se reanuda después del reinicio.
Transiciones de init
Cuando se inicia con instantáneas comprimidas, el init de primera etapa debe iniciar snapuserd
para activar las particiones. Esto plantea un problema: cuando se carga y aplica sepolicy
, snapuserd
se coloca en el contexto incorrecto y sus solicitudes de lectura fallan, con rechazos de SELinux.
Para solucionar este problema, snapuserd
realiza transiciones en sincronía con init
, de la siguiente manera:
- El
init
de primera etapa iniciasnapuserd
desde el ramdisk y le guarda un descriptor de archivo abierto en una variable de entorno. - La primera etapa,
init
, cambia el sistema de archivos raíz a la partición del sistema y, luego, ejecuta la copia del sistema deinit
. - La copia del sistema de
init
lee la sepolicy combinada en una cadena. Init
invoca amlock()
en todas las páginas con copia de seguridad de ext4. Luego, desactiva todas las tablas de Device Mapper para los dispositivos de instantáneas y detienesnapuserd
. Después de esto, no se permitirá la lectura de particiones, ya que esto provoca un interbloqueo.- Con el descriptor abierto para la copia de ramdisk de
snapuserd
,init
reinicia el daemon con el contexto de selinux correcto. Se vuelven a activar las tablas de Device-mapper para los dispositivos de instantáneas. - Init invoca a
munlockall()
; es seguro volver a realizar operaciones de E/S.
Uso del espacio
En la siguiente tabla, se proporciona una comparación del uso de espacio para diferentes mecanismos de OTA con los tamaños del SO y OTA de Pixel.
Impacto del tamaño | no A/B | A/B | A/B virtual | A/B virtual (comprimido) |
---|---|---|---|---|
Imagen de fábrica original | Super 4.5 GB (imagen de 3.8 GB + 700 M reservados)1 | 9 GB de almacenamiento super (3.8 G + 700 M reservados, para dos ranuras) | 4.5 GB super (imagen de 3.8 GB + 700 M reservados) | 4.5 GB super (imagen de 3.8 GB + 700 M reservados) |
Otras particiones estáticas | /cache | Ninguno | Ninguno | Ninguno |
Almacenamiento adicional durante la actualización inalámbrica (espacio que se muestra después de aplicar la actualización inalámbrica) | 1.4 GB en /data | 0 | 3.8 GB2 en /data | 2.1 GB2 en /data |
Almacenamiento total necesario para aplicar la actualización OTA | 5.9 GB3 (super y datos) | 9 GB (super) | 8.3 GB3 (super y datos) | 6.6 GB3 (super y datos) |
1 Indica el diseño adoptado en función de la asignación de píxeles.
2Se supone que la nueva imagen del sistema tiene el mismo tamaño que la original.
3El requisito de espacio es transitorio hasta el reinicio.
A/B virtual de Android 11
El android 11 de Virtual A/B escribió en la partición dinámica con el formato COW de kernel. Con el tiempo, dejó de estar disponible, ya que el formato COW del kernel no admite la compresión.
A/B virtual de Android 12
En Android 12, la compresión se admite en forma de un formato COW específico de Android. Esta versión de A/B virtual requirió una traducción de la COW específica de Android al formato de COW del kernel. Con el tiempo, esto se reemplazó en Android 13, que quitó la dependencia del formato COW del kernel y también de dm-snapshot
.
Para implementar A/B virtual o usar las funciones de instantáneas comprimidas, consulta Implementa un A/B virtual.