O Google tem o compromisso de promover a igualdade racial para as comunidades negras. Saiba como.

Atualizações dinâmicas do sistema

As atualizações dinâmicas do sistema (DSU) permitem que você crie uma imagem do sistema Android que os usuários podem baixar da Internet e experimentar sem o risco de corromper a imagem do sistema atual. Este documento descreve como apoiar o DSU.

Requisitos de kernel

Consulte Implementando dinâmico partições para as necessidades do kernel.

Além disso, o DSU depende do recurso de kernel device-mapper-verity (dm-verity) para verificar a imagem do sistema Android. Portanto, você deve habilitar as seguintes configurações de kernel:

  • CONFIG_DM_VERITY=y
  • CONFIG_DM_VERITY_FEC=y

Requisitos de partição

A partir de Android 11, DSU requer a /data partição para usar os F2FS ou sistema de arquivos ext4. F2FS oferece melhor desempenho e é recomendado, mas a diferença deve ser insignificante.

Aqui estão alguns exemplos de quanto tempo leva uma atualização dinâmica do sistema com um dispositivo Pixel:

  • Usando F2FS:
    • 109s, usuário 8G, sistema 867M, tipo de sistema de arquivos: F2FS: criptografia = aes-256-xts: aes-256-cts
    • 104s, usuário 8G, sistema 867M, tipo de sistema de arquivo: F2FS: criptografia = gelo
  • Usando ext4:
    • 135s, usuário 8G, sistema 867M, tipo de sistema de arquivos: ext4: criptografia = aes-256-xts: aes-256-cts

Se demorar muito mais em sua plataforma, você pode querer verificar se o sinalizador de montagem contém qualquer sinalizador que faça “sincronização” de gravação, ou você pode especificar um sinalizador “async” explicitamente para obter melhor desempenho.

O metadata partição (16 MB ou maior) é necessário para o armazenamento de dados relacionados com as imagens instalados. Deve ser montado durante a montagem do primeiro estágio.

O userdata partição deve usar F2FS ou sistema de arquivos ext4. Ao usar F2FS, incluem todos os F2FS correções disponíveis no kernel do comum Android .

O DSU foi desenvolvido e testado com kernel / common 4.9. É recomendado usar kernel 4.9 e superior para este recurso.

Comportamento do fornecedor HAL

Weaver HAL

O HAL weaver fornece um número fixo de slots para armazenar as chaves do usuário. O DSU consome dois slots de chave extras. Se um OEM tem um HAL de tecelagem, ele precisa ter slots suficientes para uma imagem de sistema genérica (GSI) e uma imagem de host.

Gatekeeper HAL

O Gatekeeper HAL precisa suportar grandes USER_ID valores, porque UIDs O GSI offsets ao HAL por um milhão.

Verifique a inicialização

Se você quiser suportar o arranque de Desenvolvedor GSI Imagens em estado bloqueado sem desativar inicialização verificada, incluem chaves GSI desenvolvedores adicionando a seguinte linha ao arquivo device/<device_name>/device.mk :

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

Proteção contra reversão

Ao usar o DSU, a imagem do sistema Android baixada deve ser mais recente do que a imagem do sistema atual no dispositivo. Isto é feito através da comparação dos níveis de patch de segurança no Android Verificado Bota (AVB) AVB descritor de propriedade de ambas as imagens do sistema: Prop: com.android.build.system.security_patch -> '2019-04-05' .

Para dispositivos que não utilizam AVB, coloque o nível de patch de segurança da imagem do sistema atual para o cmdline kernel ou bootconfig com o bootloader: androidboot.system.security_patch=2019-04-05 .

Requisitos de hardware

Quando você inicia uma instância de DSU, dois arquivos temporários são alocados:

  • Uma partição lógica para armazenar GSI.img (1 ~ 1,5 L)
  • Um vazio de 8 GB /data partição que a área de segurança para o funcionamento do GSI

Recomendamos reservar pelo menos 10 GB de espaço livre antes de iniciar uma instância de DSU. O DSU também oferece suporte à alocação de um cartão SD. Quando um cartão SD está presente, ele tem a prioridade mais alta para a alocação. O suporte ao cartão SD é crítico para dispositivos de baixa potência que podem não ter armazenamento interno suficiente. Quando um cartão SD estiver presente, certifique-se de que ele não seja adotado. O DSU não suporta cartões SD adotadas .

Frontends disponíveis

Você pode lançar DSU usando adb , um aplicativo OEM, ou a um clique loader DSU (em Android 11 ou superior).

Lançando DSU usando adb

Para iniciar o DSU usando adb, insira estes 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

Lançar DSU usando um aplicativo

O principal ponto de entrada para DSU é o 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);
    }

Você deve agrupar / pré-instalar este aplicativo no dispositivo. Porque DynamicSystemClient é uma API do sistema, você não pode construir o aplicativo com a API SDK regular e você não pode publicá-lo no Google Play. O objetivo deste aplicativo é:

  1. Obtenha uma lista de imagens e o URL correspondente com um esquema definido pelo fornecedor.
  2. Compare as imagens na lista com o dispositivo e mostre imagens compatíveis para o usuário selecionar.
  3. Invoke DynamicSystemClient.start assim:

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

O URL aponta para um arquivo de imagem do sistema compactado, não esparso, que você pode criar com os seguintes comandos:

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

O nome do arquivo deve seguir este formato:

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

Exemplos:

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

Carregador DSU de um clique

O Android 11 apresenta o carregador DSU de um clique, que é um front-end nas configurações do desenvolvedor.

Iniciando o carregador DSU

Figura 1. Iniciação do carregador DSU

Quando o desenvolvedor clica no botão DSU Loader, ele busca um descritor pré-configurado DSU JSON a partir da web e exibe todas as imagens aplicáveis no menu flutuante. Selecione uma imagem para iniciar a instalação do DSU e o andamento será mostrado na barra de notificação.

Progresso da instalação da imagem DSU

Progresso da instalação imagem Figura 2. DSU

Por padrão, o carregador DSU carrega um descritor JSON que contém as imagens GSI. As seções a seguir demonstram como fazer pacotes de DSU assinados por OEM e carregá-los do carregador de DSU.

Sinalizador de recurso

O recurso DSU está sob a settings_dynamic_android bandeira recurso. Antes de usar o DSU, certifique-se de que o sinalizador de recurso correspondente esteja habilitado.

Ativando o sinalizador de recurso.

Figura 3. Activar a bandeira característica

A IU do sinalizador de recurso pode estar indisponível em um dispositivo que executa uma construção de usuário. Neste caso, use o adb comando:

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

Imagens do sistema host do fornecedor no GCE (opcional)

Um dos locais de armazenamento possíveis para as imagens do sistema é o intervalo do Google Compute Engine (GCE). O administrador liberação utiliza o console de armazenamento GCP para adicionar / excluir / mudar a imagem do sistema liberado.

As imagens devem ser de acesso público, conforme mostrado aqui:

Acesso público no GCE

Acesso Figura 4. Pública em GCE

O procedimento para fazer um público item está disponível na documentação do Google Cloud .

DSU de partição múltipla em arquivo ZIP

A partir do Android 11, o DSU pode ter mais de uma partição. Por exemplo, ele pode conter um product.img além da system.img . Quando o dispositivo é inicializado, a primeira etapa init detecta as partições DSU instalados e substitui a partição no dispositivo temporariamente, quando o DSU instalada está habilitado. O pacote DSU pode conter uma partição que não possui uma partição correspondente no dispositivo.

Processo DSU com múltiplas partições

Figura 5. processo DSU com múltiplas partições

DSU assinado por OEM

Para garantir que todas as imagens em execução no dispositivo sejam autorizadas pelo fabricante do dispositivo, todas as imagens em um pacote DSU devem ser assinadas. Por exemplo, suponha que haja um pacote DSU que contém duas imagens de partição como abaixo:

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

Ambos system.img e product.img deve ser assinado pela chave OEM antes de serem colocados no ficheiro ZIP. A prática comum é usar um algoritmo assimétrico, por exemplo, RSA, onde a chave secreta é usada para assinar o pacote e a chave pública é usada para verificá-lo. O primeiro disco em memória estágio deve incluir a chave pública apara, por exemplo, /avb/*.avbpubkey . Se o dispositivo já adota o AVB, o procedimento de assinatura existente será suficiente. As seções a seguir ilustram o processo de assinatura e destacam o posicionamento do pubkey AVB que é usado para verificar as imagens no pacote de DSU.

Descritor DSU JSON

O descritor DSU JSON descreve pacotes DSU. Ele suporta dois primitivos. Em primeiro lugar, a include primitivo inclui descritores JSON adicionais ou redirecciona o carregador DSU para uma nova localização. Por exemplo:

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

Em segundo lugar, a image primitiva é usado para descrever pacotes DSU liberados. Dentro da imagem primitiva, existem vários atributos:

  • Os name e details atributos são cadeias que são mostrados na caixa de diálogo para que o usuário selecionar.

  • Os cpu_api , vndk , e os_version atributos são usados para verificações de compatibilidade, que são descritos na secção seguinte.

  • O opcional pubkey atributo descreve a chave pública que pares com a chave secreta que é usada para assinar o pacote DSU. Quando especificado, o serviço DSU pode verificar se o dispositivo tem a chave usada para verificar o pacote DSU. Isso evita a instalação de um pacote de DSU não reconhecido, por exemplo, a instalação de um DSU assinado pelo OEM-A em um dispositivo fabricado pelo OEM-B.

  • Os opcionais tos atribuir pontos para um arquivo de texto que descreve os termos de serviço para o pacote DSU correspondente. Quando um desenvolvedor seleciona um pacote de DSU com o atributo de termos de serviço especificado, a caixa de diálogo mostrada na Figura 6 é aberta, solicitando que o desenvolvedor aceite os termos de serviço antes de instalar o pacote de DSU.

    Caixa de diálogo dos Termos de Serviço

    Figura 6. Termos caixa de diálogo serviço de

Para referência, aqui está um descritor JSON DSU para o 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"
      }
   ]
}

Gerenciamento de compatibilidade

Vários atributos são usados ​​para especificar a compatibilidade entre um pacote DSU e o dispositivo local:

  • cpu_api é uma cadeia que descreve a arquitetura do dispositivo. Este atributo é obrigatório e é comparado com o ro.product.cpu.abi propriedade do sistema. Seus valores devem corresponder exatamente.

  • os_version é um inteiro opcional que especifica uma versão Android. Por exemplo, para Android 10, os_version é 10 e para o Android 11, os_version é 11 . Quando esse atributo é especificado, deve ser igual ou maior do que o ro.system.build.version.release propriedade do sistema. Esta verificação é usada para evitar a inicialização de uma imagem GSI do Android 10 em um dispositivo do fornecedor do Android 11, que atualmente não é compatível. É permitido inicializar uma imagem GSI do Android 11 em um dispositivo Android 10.

  • vndk é uma disposição opcional que especifica todos os VNDKs que estão incluídos no pacote DSU. Quando é especificado, as verificações carregador DSU se o número extraído da ro.vndk.version propriedade do sistema está incluído.

Revogando chaves DSU para segurança

No caso extremamente raro em que o par de chaves RSA usado para assinar as imagens DSU está comprometido, o ramdisk deve ser atualizado o mais rápido possível para remover a chave comprometida. Além de atualizar a partição de inicialização, você pode bloquear as chaves comprometidas usando uma lista de revogação de chave DSU (lista negra de chave) de um URL HTTPS.

A lista de revogação de chave DSU contém uma lista de chaves públicas AVB revogadas. Durante a instalação do DSU, as chaves públicas dentro das imagens do DSU são validadas com a lista de revogação. Se as imagens contiverem uma chave pública revogada, o processo de instalação do DSU será interrompido.

O URL da lista de revogação de chave deve ser um URL HTTPS para garantir a força de segurança e é especificado em uma string de recurso:

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

O valor da string é https://dl.google.com/developers/android/gsi/gsi-keyblacklist.json , que é uma lista de revogação de chaves GSI Google-lançados. Essa sequência de recursos pode ser sobreposta e personalizada, para que os OEMs que adotam o recurso DSU possam fornecer e manter sua própria lista negra de chaves. Isso fornece uma maneira para o OEM bloquear certas chaves públicas sem atualizar a imagem do disco em memória do dispositivo.

O formato da lista de revogação é:

{
   "entries":[
      {
         "public_key":"bf14e439d1acf231095c4109f94f00fc473148e6",
         "status":"REVOKED",
         "reason":"Key revocation test key"
      },
      {
         "public_key":"d199b2f29f3dc224cca778a7544ea89470cbef46",
         "status":"REVOKED",
         "reason":"Key revocation test key"
      }
   ]
}
  • public_key é o SHA-1 digerir da chave revogada, no formato descrito na gerar o AVB pubkey secção.
  • status indica o estado de revogação da chave. Atualmente, o valor suportado apenas é REVOKED .
  • reason é uma cadeia opcional descrevendo o motivo da revogação.

Procedimentos DSU

Esta seção descreve como executar vários procedimentos de configuração de DSU.

Gerando um novo par de chaves

Use o openssl comando para gerar um RSA privado / par de chaves pública em .pem formato (por exemplo, com o tamanho de 2048 bits):

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

A chave privada pode não ser acessível e só é mantido em um módulo de segurança de hardware (HSM) . Nesse caso, pode haver um certificado de chave pública x509 disponível após a geração da chave. Consulte o Adicionando o pubkey emparelhamento para o ramdisk seção para obter instruções para gerar a chave pública AVB de um certificado x509.

Para converter um certificado x509 para o formato PEM:

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

Pule esta etapa se o certificado já for um arquivo PEM.

Adicionando o pubkey de emparelhamento ao ramdisk

O oem_cert.avbpubkey deve ser colocado sob /avb/*.avbpubkey para verificar o pacote DSU assinado. Primeiro, converta a chave pública no formato PEM para o formato de chave pública AVB:

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

Em seguida, inclua a chave pública no disco em memória do primeiro estágio com as etapas a seguir.

  1. Adicionar um módulo pré-construídos para copiar o avbpubkey . Por exemplo, add device/<company>/<board>/oem_cert.avbpubkey e device/<company>/<board>/avb/Android.mk com conteúdo como este:

    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. Fazer o alvo droidcore dependem do agregado oem_cert.avbpubkey :

    droidcore: oem_cert.avbpubkey
    

Gerando o atributo pubkey AVB no descritor JSON

O oem_cert.avbpubkey está no formato binário chave pública AVB. Use SHA-1 para torná-lo legível antes de colocá-lo no descritor JSON:

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

Este será o conteúdo do pubkey atributo do descritor de JSON.

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

Assinando um pacote DSU

Use um destes métodos para assinar um pacote DSU:

  • Método 1: Reutilize o artefato feito pelo processo de assinatura do AVB original para fazer um pacote DSU. Uma abordagem alternativa é extrair as imagens já assinadas do pacote de lançamento e usar as imagens extraídas para criar o arquivo ZIP diretamente.

  • Método 2: Use os seguintes comandos para assinar partições DSU se a chave privada estiver disponível. Cada img dentro de um pacote DSU (arquivo ZIP) é assinado separadamente:

    $ 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 mais informações sobre como adicionar add_hashtree_footer usando avbtool , consulte Usando avbtool .

Verificando o pacote DSU localmente

É recomendável verificar todas as imagens locais em relação à chave pública de emparelhamento com estes comandos:


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

A saída esperada é parecida com esta:

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

Fazendo um pacote DSU

O exemplo que se segue faz uma embalagem que contém um DSU system.img e um product.img :

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

Depois que as duas imagens forem assinadas, use o seguinte comando para fazer o arquivo ZIP:

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

Personalização do DSU de um clique

Por padrão, o DSU carregador aponta para um metadados de imagens GSI que é https://...google.com/.../gsi-src.json .

OEMs podem substituir a lista definindo a persist.sys.fflag.override.settings_dynamic_system.list propriedade que aponta para o seu próprio descritor JSON. Por exemplo, um OEM pode fornecer metadados JSON que incluem GSI, bem como imagens de propriedade do OEM como este:

{
    "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"
      },

}

É possível para um OEM encadear metadados DSU publicados, conforme mostrado na Figura 7.

Encadeamento de metadados DSU publicados

Figura 7. O encadeamento publicada DSU metadados