Punto de control de datos de usuario

Android 10 presenta el Punto de control de datos de usuario (UDC), que permite que Android vuelva a su estado anterior cuando falla una actualización inalámbrica (OTA) de Android. Con UDC, si falla una actualización OTA de Android, el dispositivo puede volver de forma segura a su estado anterior. Aunque las actualizaciones A/B resuelven este problema para el arranque temprano, no se admite la reversión cuando se modifica la partición de datos del usuario (montada en /data ).

UDC permite que el dispositivo revierta la partición de datos del usuario incluso después de haber sido modificado. La función UDC logra esto con capacidades de puntos de control para el sistema de archivos, una implementación alternativa cuando el sistema de archivos no admite puntos de control, integración con el mecanismo A/B del gestor de arranque y al mismo tiempo admite actualizaciones que no son A/B y compatibilidad con el enlace de versiones de claves. y prevención de retrocesos clave.

Impacto del usuario

La función UDC mejora la experiencia de actualización OTA para los usuarios, ya que menos usuarios pierden sus datos cuando falla una actualización OTA. Esto puede reducir la cantidad de llamadas de soporte de usuarios que tienen problemas durante el proceso de actualización. Sin embargo, cuando falla una actualización OTA, los usuarios pueden notar que el dispositivo se reinicia varias veces.

Cómo funciona

Funcionalidad de punto de control en diferentes sistemas de archivos

Para el sistema de archivos F2FS, UDC agrega la funcionalidad de punto de control al kernel de Linux 4.20 y la respalda a todos los kernels comunes compatibles con dispositivos que ejecutan Android 10.

Para otros sistemas de archivos, UDC utiliza un dispositivo virtual asignador de dispositivos llamado dm_bow para la funcionalidad de punto de control. dm_bow se encuentra entre el dispositivo y el sistema de archivos. Cuando se monta una partición, se emite un recorte que hace que el sistema de archivos emita comandos de recorte en todos los bloques libres. dm_bow intercepta estos recortes y los usa para configurar una lista de bloqueo gratuita. Luego, las lecturas y escrituras se envían al dispositivo sin modificaciones, pero antes de permitir una escritura, se realiza una copia de seguridad de los datos necesarios para una restauración en un bloque libre.

Proceso de punto de control

Cuando se monta una partición con el indicador checkpoint=fs/block , Android llama a restoreCheckpoint en la unidad para permitir que el dispositivo restaure cualquier punto de control actual. Luego, init llama a la función needsCheckpoint para determinar si el dispositivo está en un estado de cargador de arranque A/B o ha configurado el recuento de reintentos de actualización. Si cualquiera de los dos es cierto, Android llama createCheckpoint para agregar indicadores de montaje o crear un dispositivo dm_bow .

Una vez montada la partición, se llama al código del punto de control para emitir ajustes. El proceso de arranque continúa normalmente. En LOCKED_BOOT_COMPLETE , Android llama commitCheckpoint para confirmar el punto de control actual y la actualización continúa normalmente.

Administrar claves maestras

Las claves Keymaster se utilizan para cifrar dispositivos u otros fines. Para administrar estas claves, Android retrasa las llamadas de eliminación de claves hasta que se confirma el punto de control.

Monitorear la salud

Un demonio de salud verifica que haya suficiente espacio en disco para crear un punto de control. El demonio de salud se encuentra en cp_healthDaemon en Checkpoint.cpp .

El demonio de salud tiene los siguientes comportamientos que se pueden configurar:

API de punto de control

La función UDC utiliza las API de Checkpoint. Para conocer otras API utilizadas por UDC, consulte IVold.aidl .

anular startCheckpoint (int reintentar)

Crea un punto de control.

El marco llama a este método cuando está listo para iniciar una actualización. El punto de control se crea antes de que los sistemas de archivos con puntos de control, como los datos de usuario, se monten en lectura/escritura después del reinicio. Si el recuento de reintentos es positivo, la API maneja los reintentos de seguimiento y el actualizador llama needsRollback para comprobar si es necesaria una reversión de la actualización. Si el recuento de reintentos es -1 , la API se remite al criterio del gestor de arranque A/B.

Este método no se llama cuando se realiza una actualización A/B normal.

cambios de confirmación nulos()

Confirma los cambios.

El marco llama a este método después del reinicio, cuando los cambios están listos para confirmarse. Esto se llama antes de que los datos (como imágenes, videos, SMS, recibo de recepción del servidor) se escriban en los datos del usuario y antes de BootComplete .

Si no existe ninguna actualización activa con puntos de control, este método no tiene ningún efecto.

abortar cambios()

Fuerza el reinicio y vuelve al punto de control. Abandona todas las modificaciones de datos de usuario desde el primer reinicio.

El marco llama a este método después del reinicio pero antes de commitChanges . retry_counter disminuye cuando se llama a este método. Se generan entradas de registro.

bool necesitaRollback()

Determina si se requiere una reversión.

En dispositivos que no son de punto de control, devuelve false . En dispositivos de punto de control, devuelve true durante un arranque sin punto de control.

Implementar UDC

Implementación de referencia

Para ver un ejemplo de cómo se puede implementar UDC, consulte dm-bow.c . Para obtener documentación adicional sobre la función, consulte dm-bow.txt .

Configuración

En on fs en su archivo init.hardware.rc , asegúrese de tener:

mount_all /vendor/etc/fstab.${ro.boot.hardware.platform} --early

En on late-fs en su archivo init.hardware.rc , asegúrese de tener:

mount_all /vendor/etc/fstab.${ro.boot.hardware.platform} --late

En su archivo fstab.hardware , asegúrese de que /data esté etiquetado como latemount .

/dev/block/bootdevice/by-name/userdata              /data              f2fs
noatime,nosuid,nodev,discard,reserve_root=32768,resgid=1065,fsync_mode=nobarrier
latemount,wait,check,fileencryption=ice,keydirectory=/metadata/vold/metadata_encryption,quota,formattable,sysfs_path=/sys/devices/platform/soc/1d84000.ufshc,reservedsize=128M,checkpoint=fs

Agregar partición de metadatos

UDC requiere una partición de metadatos para almacenar las claves y el recuento de reintentos que no son del cargador de arranque. Configure una partición de metadatos y móntela anticipadamente en /metadata .

En su archivo fstab.hardware , asegúrese de que /metadata esté etiquetado como earlymount o first_stage_mount .

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

Inicialice la partición a todo ceros.

Agregue las siguientes líneas a BoardConfig.mk :

BOARD_USES_METADATA_PARTITION := true
BOARD_ROOT_EXTRA_FOLDERS := existing_folders metadata

Actualizar sistemas

Sistemas F2FS

Para los sistemas que usan F2FS para formatear datos, asegúrese de que su versión de F2FS admita puntos de control. Para obtener más información, consulte Funcionalidad de Checkpoint en diferentes sistemas de archivos .

Agregue el checkpoint=fs a la sección <fs_mgr_flags> de fstab para el dispositivo montado en /data .

Sistemas que no son F2FS

Para sistemas que no son F2FS, dm-bow debe estar habilitado en la configuración del kernel.

Agregue el checkpoint=block a la sección <fs_mgr_flags> de fstab para el dispositivo montado en /data .

comprobar registros

Las entradas de registro se generan cuando se llama a las API de Checkpoint.

Validación

Para probar su implementación de UDC, ejecute el conjunto de pruebas VTS VtsKernelCheckpointTest .