Google se compromete a impulsar la igualdad racial para las comunidades afrodescendientes. Obtén información al respecto.

Actualizaciones dinámicas del sistema

Las actualizaciones dinámicas del sistema (DSU) le permiten crear una imagen del sistema Android que los usuarios pueden descargar de Internet y probar sin el riesgo de dañar la imagen actual del sistema. Este documento describe cómo admitir DSU.

Requisitos del kernel

Ver Ejecución dinámica particiones para los requisitos del núcleo.

Además, DSU se basa en la función del kernel device-mapper-verity (dm-verity) para verificar la imagen del sistema Android. Por lo tanto, debe habilitar las siguientes configuraciones del kernel:

  • CONFIG_DM_VERITY=y
  • CONFIG_DM_VERITY_FEC=y

Requisitos de partición

A partir de Android 11, ESD requiere que el /data partición para utilizar los f2fs o sistema de archivos ext4. F2FS ofrece un mejor rendimiento y se recomienda, pero la diferencia debería ser insignificante.

A continuación, se muestran algunos ejemplos de cuánto tiempo lleva una actualización dinámica del sistema con un dispositivo Pixel:

  • Usando F2FS:
    • 109s, usuario 8G, sistema 867M, tipo de sistema de archivos: F2FS: cifrado = aes-256-xts: aes-256-cts
    • 104s, usuario 8G, sistema 867M, tipo de sistema de archivos: F2FS: cifrado = hielo
  • Usando ext4:
    • 135s, usuario 8G, sistema 867M, tipo de sistema de archivos: ext4: cifrado = aes-256-xts: aes-256-cts

Si tarda mucho más en su plataforma, es posible que desee comprobar si el indicador de montaje contiene algún indicador que hace que la escritura sea "sincronizada", o puede especificar un indicador "asíncrono" explícitamente para obtener un mejor rendimiento.

El metadata se requiere partición (16 MB o más) para almacenar datos relacionados con las imágenes instaladas. Debe montarse durante el montaje de la primera etapa.

El userdata partición debe utilizar f2fs o sistema de archivos ext4. Al utilizar f2fs, incluir todos los f2fs parches disponibles en el núcleo común de Android .

DSU fue desarrollado y probado con kernel / common 4.9. Se recomienda utilizar el kernel 4.9 y superior para esta función.

Comportamiento HAL del proveedor

Weaver HAL

El tejedor HAL proporciona un número fijo de ranuras para almacenar claves de usuario. La DSU consume dos ranuras de clave adicionales. Si un OEM tiene una HAL de tejedor, debe tener suficientes ranuras para una imagen de sistema genérica (GSI) y una imagen de host.

Gatekeeper HAL

El Gatekeeper HAL tiene que soportar grandes USER_ID valores, porque el UID GSI compensaciones a la HAL por millón.

Verificar arranque

Si desea admitir el inicio Desarrollador GSI Imágenes en estado bloqueado sin desactivar el arranque verificado, incluyen teclas GSI Desarrollador añadiendo la siguiente línea en el fichero de device/<device_name>/device.mk :

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

Protección contra retroceso

Al usar DSU, la imagen del sistema Android descargada debe ser más reciente que la imagen del sistema actual en el dispositivo. Esto se realiza mediante la comparación de los niveles de parches de seguridad en el Android inicio verificado (BAV) AVB descriptor de propiedad de las dos imágenes del sistema: Prop: com.android.build.system.security_patch -> '2019-04-05' .

Para los dispositivos que no utilizan AVB, poner el nivel de parches de seguridad de la imagen del sistema actual en el kernel o línea_de_órdenes bootconfig con el gestor de arranque: androidboot.system.security_patch=2019-04-05 .

Requisitos de hardware

Cuando lanza una instancia de DSU, se asignan dos archivos temporales:

  • Una partición lógica para almacenar GSI.img (1 ~ 1,5 G)
  • Un vacío de 8 GB /data partición como la caja de arena para el funcionamiento de la GSI

Recomendamos reservar al menos 10 GB de espacio libre antes de lanzar una instancia de DSU. DSU también admite la asignación desde una tarjeta SD. Cuando hay una tarjeta SD, tiene la máxima prioridad para la asignación. La compatibilidad con tarjetas SD es fundamental para los dispositivos de menor potencia que pueden no tener suficiente almacenamiento interno. Cuando haya una tarjeta SD, asegúrese de que no sea adoptada. ESD no es compatible con tarjetas SD adoptadas .

Fronteras disponibles

Puede iniciar ESD usando adb , una aplicación OEM, o el de un solo clic cargador de ESD (en Android 11 o superior).

Lanzamiento de DSU usando adb

Para iniciar DSU usando adb, ingrese estos comandos:

$ simg2img out/target/product/.../system.img system.raw
$ gzip -c system.raw > system.raw.gz
$ adb push system.raw.gz /storage/emulated/0/Download
$ adb shell am start-activity \
-n com.android.dynsystem/com.android.dynsystem.VerificationActivity  \
-a android.os.image.action.START_INSTALL    \
-d file:///storage/emulated/0/Download/system.raw.gz  \
--el KEY_SYSTEM_SIZE $(du -b system.raw|cut -f1)  \
--el KEY_USERDATA_SIZE 8589934592

Lanzamiento de DSU usando una aplicación

El principal punto de entrada a la ESD es la android.os.image.DynamicSystemClient.java API:

public class DynamicSystemClient {


...
...

     /**
     * Start installing DynamicSystem from URL with default userdata size.
     *
     * @param systemUrl A network URL or a file URL to system image.
     * @param systemSize size of system image.
     */
    public void start(String systemUrl, long systemSize) {
        start(systemUrl, systemSize, DEFAULT_USERDATA_SIZE);
    }

Debe empaquetar / preinstalar esta aplicación en el dispositivo. Debido DynamicSystemClient es una API del sistema, no se puede construir la aplicación con la API SDK regular y no se puede publicarla en Google Play. El propósito de esta aplicación es:

  1. Obtenga una lista de imágenes y la URL correspondiente con un esquema definido por el proveedor.
  2. Haga coincidir las imágenes de la lista con el dispositivo y muestre imágenes compatibles para que el usuario las seleccione.
  3. Invocar DynamicSystemClient.start como esto:

    DynamicSystemClient aot = new DynamicSystemClient(...)
       aot.start(
            ...URL of the selected image...,
            ...uncompressed size of the selected image...);
    
    

La URL apunta a un archivo de imagen del sistema comprimido con gzip, no disperso, que puede crear con los siguientes comandos:

$ simg2img ${OUT}/system.img ${OUT}/system.raw
$ gzip ${OUT}/system.raw
$ ls ${OUT}/system.raw.gz

El nombre del archivo debe seguir este formato:

<android version>.<lunch name>.<user defined title>.raw.gz

Ejemplos:

  • o.aosp_taimen-userdebug.2018dev.raw.gz
  • p.aosp_taimen-userdebug.2018dev.raw.gz

Cargador DSU con un clic

Android 11 presenta el cargador DSU de un clic, que es una interfaz en la configuración del desarrollador.

Lanzamiento del cargador DSU

Figura 1. Inicio del cargador ESD

Cuando el desarrollador hace clic en el botón de ESD cargador, se obtiene un descriptor ESD JSON preconfigurado de la web y muestra todas las imágenes aplicables en el menú flotante. Seleccione una imagen para iniciar la instalación de DSU y el progreso se muestra en la barra de notificaciones.

Progreso de la instalación de la imagen de DSU

Progreso de la instalación imagen Figura 2. ESD

De forma predeterminada, el cargador de DSU carga un descriptor JSON que contiene las imágenes GSI. Las siguientes secciones demuestran cómo crear paquetes de DSU firmados por el OEM y cargarlos desde el cargador de DSU.

Bandera de función

La función de ESD está bajo el settings_dynamic_android indicador de la función. Antes de usar DSU, asegúrese de que el indicador de función correspondiente esté habilitado.

Habilitando el indicador de función.

Figura 3. Activación de la bandera característica

Es posible que la interfaz de usuario del indicador de función no esté disponible en un dispositivo que ejecute una compilación de usuario. En este caso, utilice el adb comando:

$ adb shell setprop persist.sys.fflag.override.settings_dynamic_system 1

Imágenes del sistema host del proveedor en GCE (opcional)

Una de las posibles ubicaciones de almacenamiento para las imágenes del sistema es el depósito de Google Compute Engine (GCE). El administrador utiliza la versión de la consola de almacenamiento GCP añadir / eliminar / cambiar la imagen del sistema en libertad.

Las imágenes deben ser de acceso público, como se muestra aquí:

Acceso público en GCE

4. Acceso a la figura pública en la CME

El procedimiento para hacer público un artículo está disponible en la documentación de la nube de Google .

DSU de múltiples particiones en archivo ZIP

A partir de Android 11, DSU puede tener más de una partición. Por ejemplo, puede contener un product.img además de la system.img . Cuando se inicia el dispositivo, la primera etapa init detecta las particiones ESD instalados y sustituye a la partición en el dispositivo temporalmente, cuando el ESD instalado está activado. El paquete DSU puede contener una partición que no tiene una partición correspondiente en el dispositivo.

Proceso DSU con múltiples particiones

Proceso de la Figura 5. ESD con varias particiones

DSU firmado por el OEM

Para asegurarse de que todas las imágenes que se ejecutan en el dispositivo estén autorizadas por el fabricante del dispositivo, todas las imágenes dentro de un paquete DSU deben estar firmadas. Por ejemplo, suponga que hay un paquete DSU que contiene dos imágenes de partición como se muestra a continuación:

dsu.zip {
    - system.img
    - product.img
}

Tanto system.img y product.img debe ser firmado por la clave OEM antes de ser colocados en el archivo ZIP. La práctica común es usar un algoritmo asimétrico, por ejemplo, RSA, donde la clave secreta se usa para firmar el paquete y la clave pública se usa para verificarlo. El primer disco de memoria etapa debe incluir la clave pública pelar, por ejemplo, /avb/*.avbpubkey . Si el dispositivo ya adoptó AVB, el procedimiento de firma existente será suficiente. Las siguientes secciones ilustran el proceso de firma y resaltan la ubicación de la clave pública AVB que se usa para verificar las imágenes en el paquete DSU.

Descriptor DSU JSON

El descriptor DSU JSON describe los paquetes DSU. Soporta dos primitivas. En primer lugar, la include primitiva incluye descriptores adicionales JSON o vuelve a dirigir el cargador ESD a una nueva ubicación. Por ejemplo:

{
    "include": ["https://.../gsi-release/gsi-src.json"]
}

En segundo lugar, la image primitiva se utiliza para describir los paquetes ESD liberados. Dentro de la primitiva de la imagen hay varios atributos:

  • Los name y details atributos son cadenas que se muestran en el cuadro de diálogo para que el usuario seleccione.

  • Los cpu_api , vndk , y os_version atributos se utilizan para pruebas de compatibilidad, que se describen en la siguiente sección.

  • El opcional pubkey atributo describe la clave pública que se empareja con la clave secreta que se utiliza para firmar el paquete ESD. Cuando se especifica, el servicio DSU puede verificar si el dispositivo tiene la clave utilizada para verificar el paquete DSU. Esto evita instalar un paquete de DSU no reconocido, por ejemplo, instalar una DSU firmada por OEM-A en un dispositivo fabricado por OEM-B.

  • Los opcionales tos atribuyen puntos a un archivo de texto que describe los términos de servicio para el paquete ESD correspondientes. Cuando un desarrollador selecciona un paquete de DSU con el atributo de términos de servicio especificado, se abre el cuadro de diálogo que se muestra en la Figura 6, solicitando al desarrollador que acepte los términos de servicio antes de instalar el paquete de DSU.

    Cuadro de diálogo Condiciones de servicio

    Figura 6. Condiciones cuadro de diálogo de servicio de

Como referencia, aquí hay un descriptor DSU JSON para GSI:

{
   "images":[
      {
         "name":"GSI+GMS x86",
         "os_version":"10",
         "cpu_abi": "x86",
         "details":"exp-QP1A.190711.020.C4-5928301",
         "vndk":[
            27,
            28,
            29
         ],
         "pubkey":"",
         "tos": "https://dl.google.com/developers/android/gsi/gsi-tos.txt",
         "uri":"https://.../gsi/gsi_gms_x86-exp-QP1A.190711.020.C4-5928301.zip"
      },
      {
         "name":"GSI+GMS ARM64",
         "os_version":"10",
         "cpu_abi": "arm64-v8a",
         "details":"exp-QP1A.190711.020.C4-5928301",
         "vndk":[
            27,
            28,
            29
         ],
         "pubkey":"",
         "tos": "https://dl.google.com/developers/android/gsi/gsi-tos.txt",
         "uri":"https://.../gsi/gsi_gms_arm64-exp-QP1A.190711.020.C4-5928301.zip"
      },
      {
         "name":"GSI ARM64",
         "os_version":"10",
         "cpu_abi": "arm64-v8a",
         "details":"exp-QP1A.190711.020.C4-5928301",
         "vndk":[
            27,
            28,
            29
         ],
         "pubkey":"",
         "uri":"https://.../gsi/aosp_arm64-exp-QP1A.190711.020.C4-5928301.zip"
      },
      {
         "name":"GSI x86_64",
         "os_version":"10",
         "cpu_abi": "x86_64",
         "details":"exp-QP1A.190711.020.C4-5928301",
         "vndk":[
            27,
            28,
            29
         ],
         "pubkey":"",
         "uri":"https://.../gsi/aosp_x86_64-exp-QP1A.190711.020.C4-5928301.zip"
      }
   ]
}

Gestión de compatibilidad

Se utilizan varios atributos para especificar la compatibilidad entre un paquete DSU y el dispositivo local:

  • cpu_api es una cadena que describe la arquitectura del dispositivo. Este atributo es obligatorio y se compara con el ro.product.cpu.abi propiedad del sistema. Sus valores deben coincidir exactamente.

  • os_version es un número entero opcional que especifica una liberación Android. Por ejemplo, para Android 10, os_version es 10 y 11 para Android, os_version es 11 . Cuando se especifica este atributo, debe ser igual o mayor que el ro.system.build.version.release propiedad del sistema. Esta comprobación se utiliza para evitar el arranque de una imagen GSI de Android 10 en un dispositivo de proveedor de Android 11, que actualmente no es compatible. Se permite iniciar una imagen GSI de Android 11 en un dispositivo con Android 10.

  • vndk es una matriz opcional que especifica todos los VNDKs que se incluyen en el paquete de ESD. Cuando se especifica, los controles del cargador del ESD si el número extraído de la ro.vndk.version se incluye la propiedad del sistema.

Revocación de claves DSU por seguridad

En el caso extremadamente raro de que el par de claves RSA utilizado para firmar las imágenes de la DSU se vea comprometido, el ramdisk debe actualizarse lo antes posible para eliminar la clave comprometida. Además de actualizar la partición de arranque, puede bloquear las claves comprometidas mediante una lista de revocación de claves DSU (lista negra de claves) de una URL HTTPS.

La lista de revocación de claves DSU contiene una lista de claves públicas AVB revocadas. Durante la instalación de DSU, las claves públicas dentro de las imágenes de DSU se validan con la lista de revocación. Si se encuentra que las imágenes contienen una clave pública revocada, el proceso de instalación de DSU se detiene.

La URL de la lista de revocación de claves debe ser una URL HTTPS para garantizar la seguridad y se especifica en una cadena de recursos:

frameworks/base/packages/DynamicSystemInstallationService/res/values/strings.xml@key_revocation_list_url

El valor de la cadena es https://dl.google.com/developers/android/gsi/gsi-keyblacklist.json , que es una lista de revocación de claves GSI-liberados Google. Esta cadena de recursos se puede superponer y personalizar, de modo que los OEM que adopten la función DSU puedan proporcionar y mantener su propia lista negra de claves. Esto proporciona una forma para que el OEM bloquee ciertas claves públicas sin actualizar la imagen del disco ram del dispositivo.

El formato de la lista de revocación es:

{
   "entries":[
      {
         "public_key":"bf14e439d1acf231095c4109f94f00fc473148e6",
         "status":"REVOKED",
         "reason":"Key revocation test key"
      },
      {
         "public_key":"d199b2f29f3dc224cca778a7544ea89470cbef46",
         "status":"REVOKED",
         "reason":"Key revocation test key"
      }
   ]
}
  • public_key es el SHA-1 Recopilación de la clave revocada, en el formato descrito en la generación de la AVB pubkey sección.
  • status indica el estado de revocación de la clave. Actualmente, es el valor sólo está soportado REVOKED .
  • reason es una cadena opcional que describa el motivo de revocación.

Procedimientos DSU

Esta sección describe cómo realizar varios procedimientos de configuración de DSU.

Generando un nuevo par de claves

Utilice el openssl comando para generar una privada RSA / par de claves pública en .pem formato (por ejemplo, con un tamaño de 2.048 bits):

$ openssl genrsa -out oem_cert_pri.pem 2048
$ openssl rsa -in oem_cert_pri.pem -pubout -out oem_cert_pub.pem

La clave privada podría no ser accesible y sólo se mantiene en un módulo de seguridad de hardware (HSM) . En este caso, puede haber un certificado de clave pública x509 disponible después de la generación de la clave. Véase la adición del pubkey vínculo con el disco de memoria para las instrucciones para generar la clave pública BAV de un certificado X509.

Para convertir un certificado x509 a formato PEM:

$ openssl x509 -pubkey -noout -in oem_cert_pub.x509.pem > oem_cert_pub.pem

Omita este paso si el certificado ya es un archivo PEM.

Agregar la clave pública de emparejamiento al disco ram

El oem_cert.avbpubkey debe someterse a /avb/*.avbpubkey para verificar el paquete ESD firmado. Primero, convierta la clave pública en formato PEM al formato de clave pública AVB:

$ avbtool extract_public_key --key oem_cert_pub.pem --output oem_cert.avbpubkey

Luego, incluya la clave pública en el disco RAM de la primera etapa con los siguientes pasos.

  1. Añadir un módulo de pre-compilados para copiar el avbpubkey . Por ejemplo, agregue device/<company>/<board>/oem_cert.avbpubkey y device/<company>/<board>/avb/Android.mk con el contenido de la siguiente manera:

    include $(CLEAR_VARS)
    
    LOCAL_MODULE := oem_cert.avbpubkey
    LOCAL_MODULE_CLASS := ETC
    LOCAL_SRC_FILES := $(LOCAL_MODULE)
    ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
    LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/first_stage_ramdisk/avb
    else
    LOCAL_MODULE_PATH := $(TARGET_RAMDISK_OUT)/avb
    endif
    
    include $(BUILD_PREBUILT)
    
  2. Hacer que el objetivo droidcore dependerá del agregado oem_cert.avbpubkey :

    droidcore: oem_cert.avbpubkey
    

Generando el atributo pubkey AVB en el descriptor JSON

El oem_cert.avbpubkey está en el formato binario de clave pública AVB. Use SHA-1 para hacerlo legible antes de colocarlo en el descriptor JSON:

$ sha1sum oem_cert.avbpubkey | cut -f1 -d ' '
3e62f2be9d9d813ef5........866ac72a51fd20

Este será el contenido de la pubkey atributo del descriptor de JSON.

   "images":[
      {
         ...
         "pubkey":"3e62f2be9d9d813ef5........866ac72a51fd20",
         ...
      },

Firma de un paquete de DSU

Utilice uno de estos métodos para firmar un paquete de DSU:

  • Método 1: reutilice el artefacto creado por el proceso de firma AVB original para crear un paquete DSU. Un enfoque alternativo es extraer las imágenes ya firmadas del paquete de lanzamiento y usar las imágenes extraídas para crear el archivo ZIP directamente.

  • Método 2: utilice los siguientes comandos para firmar particiones DSU si la clave privada está disponible. Cada img dentro de un paquete ESD (el archivo ZIP) está firmado por separado:

    $ key_len=$(openssl rsa -in oem_cert_pri.pem -text | grep Private-Key | sed -e 's/.*(\(.*\) bit.*/\1/')
    $ for partition in system product; do
        avbtool add_hashtree_footer \
            --image ${OUT}/${partition}.img \
            --partition_name ${partition} \
            --algorithm SHA256_RSA${key_len} \
            --key oem_cert_pri.pem
    done
    

Para obtener más información sobre cómo agregar add_hashtree_footer usando avbtool , consulte Uso de avbtool .

Verificación del paquete DSU localmente

Se recomienda verificar todas las imágenes locales con la clave pública de emparejamiento con estos comandos:


for partition in system product; do
    avbtool verify_image --image ${OUT}/${partition}.img  --key oem_cert_pub.pem
done

La salida esperada se ve así:

Verifying image dsu/system.img using key at oem_cert_pub.pem
vbmeta: Successfully verified footer and SHA256_RSA2048 vbmeta struct in dsu/system.img
: Successfully verified sha1 hashtree of dsu/system.img for image of 898494464 bytes

Verifying image dsu/product.img using key at oem_cert_pub.pem
vbmeta: Successfully verified footer and SHA256_RSA2048 vbmeta struct in dsu/product.img
: Successfully verified sha1 hashtree of dsu/product.img for image of 905830400 bytes

Hacer un paquete DSU

El siguiente ejemplo hace que un paquete que contiene una ESD system.img y una product.img :

dsu.zip {
    - system.img
    - product.img
}

Después de que ambas imágenes estén firmadas, use el siguiente comando para crear el archivo ZIP:

$ mkdir -p dsu
$ cp ${OUT}/system.img dsu
$ cp ${OUT}/product.img dsu
$ cd dsu && zip ../dsu.zip *.img && cd -

Personalización de la DSU de un clic

Por defecto, los puntos de carga ESD de un metadatos de imágenes GSI que es https://...google.com/.../gsi-src.json .

OEM pueden sobrescribir la lista mediante la definición de la persist.sys.fflag.override.settings_dynamic_system.list propiedad que apunta a su propio descriptor de JSON. Por ejemplo, un OEM puede proporcionar metadatos JSON que incluyen GSI, así como imágenes patentadas del OEM como esta:

{
    "include": ["https://dl.google.com/.../gsi-src.JSON"]
    "images":[
      {
         "name":"OEM image",
         "os_version":"10",
         "cpu_abi": "arm64-v8a",
         "details":"...",
         "vndk":[
            27,
            28,
            29
         ],
         "spl":"...",
         "pubkey":"",
         "uri":"https://.../....zip"
      },

}

Es posible que un OEM encadene los metadatos de DSU publicados como se muestra en la Figura 7.

Encadenamiento de metadatos de DSU publicados

Figura 7. Chaining publicó ESD metadatos