Layout da partição

No Android 10, o sistema de arquivos raiz não está mais incluído em ramdisk.img. Em vez disso, ele é mesclado em system.img. Ou seja, system.img é sempre criado como se BOARD_BUILD_SYSTEM_ROOT_IMAGE tivesse sido definido. Dispositivos lançados com o Android 10:

  • Use um layout de partição de sistema como raiz (forçado automaticamente pelo build sem opções para mudar o comportamento).
  • É necessário usar um ramdisk, que é obrigatório para dm-linear.
  • Defina BOARD_BUILD_SYSTEM_ROOT_IMAGE como false. Essa configuração é usada apenas para diferenciar dispositivos que usam um ramdisk e dispositivos que não usam um ramdisk (e montam system.img diretamente).

O significado de uma configuração do sistema como raiz é diferente entre o Android 9 e o Android 10. Em uma configuração do sistema como raiz do Android 9, BOARD_BUILD_SYSTEM_ROOT_IMAGE é definido como true, o que força o build a mesclar o sistema de arquivos raiz em system.img e, em seguida, montar system.img como o sistema de arquivos raiz (rootfs). Essa configuração é obrigatória para dispositivos lançados com o Android 9, mas é opcional para dispositivos que estão sendo atualizados para o Android 9 e para dispositivos que executam versões anteriores do Android. Em uma configuração do sistema como raiz do Android 10, o build sempre mescla $TARGET_SYSTEM_OUT e $TARGET_ROOT_OUT em system.img. Essa configuração é o comportamento padrão para todos os dispositivos que executam o Android 10.

O Android 10 faz outras mudanças para oferecer suporte a partições dinâmicas, um sistema de particionamento no espaço do usuário que permite que as atualizações over the air (OTA) criem, redimensionem ou destruam partições. Como parte dessa mudança, o kernel do Linux não pode mais montar a partição do sistema lógico em dispositivos com o Android 10. Portanto, essa operação é processada pela inicialização do primeiro estágio.

As seções a seguir descrevem os requisitos do sistema como raiz para OTAs somente do sistema e fornecem orientações sobre como atualizar dispositivos para usar o sistema como raiz, incluindo mudanças no layout da partição e requisitos do kernel dm-verity. Para detalhes sobre as mudanças no ramdisk, consulte Partições de ramdisk.

Sobre as OTAs somente do sistema

As OTAs exclusivas do sistema, que permitem que as versões do Android atualizem system.img e product.img sem alterar outras partições, exigem um layout de partição do sistema como raiz. Todos os dispositivos com o Android 10 precisam usar um layout de partição do sistema como raiz para ativar as OTAs somente do sistema.

  • Dispositivos A/B, que montam a partição system como rootfs, já usam o sistema como raiz e não exigem mudanças para oferecer suporte a OTAs do sistema.
  • Os dispositivos que não são A/B, que montam a partição system em /system, precisam ser atualizados para usar um layout de partição do sistema como raiz para oferecer suporte a OTAs do sistema.

Para saber mais sobre dispositivos A/B e não A/B, consulte Atualizações do sistema A/B (seamless).

Usar a sobreposição do fornecedor (<=AOSP 14)

A sobreposição do fornecedor permite que você faça mudanças na partição vendor no momento da inicialização do dispositivo. Uma sobreposição de fornecedor é um conjunto de módulos de fornecedores na partição product que são sobrepostos à partição vendor quando o dispositivo é inicializado, substituindo e adicionando aos módulos existentes.

Quando o dispositivo é inicializado, o processo init conclui a montagem da primeira etapa e lê as propriedades padrão. Em seguida, ele procura /product/vendor_overlay/<target_vendor_version> e monta cada subdiretório no diretório de partição vendor correspondente, se as seguintes condições forem atendidas:

  • /vendor/<overlay_dir> já existe.
  • /product/vendor_overlay/<target_vendor_version>/<overlay_dir> tem o mesmo contexto de arquivo que /vendor/<overlay_dir>.
  • init tem permissão para montagem no contexto de arquivo de /vendor/<overlay_dir>.

Implementar a sobreposição do fornecedor

Instale arquivos de sobreposição do fornecedor em /product/vendor_overlay/<target_vendor_version>. Esses arquivos são sobrepostos à partição vendor quando o dispositivo é inicializado, substituindo arquivos com o mesmo nome e adicionando novos arquivos. A sobreposição do fornecedor não pode remover arquivos da partição vendor.

Os arquivos de sobreposição do fornecedor precisam ter o mesmo contexto de arquivo dos arquivos de destino que eles substituem na partição vendor. Por padrão, os arquivos no diretório /product/vendor_overlay/<target_vendor_version> têm o contexto vendor_file. Se houver incompatibilidades de contexto de arquivo entre os arquivos de sobreposição do fornecedor e os arquivos que eles substituem, especifique isso na sepolicy específica do dispositivo. O contexto do arquivo é definido no nível do diretório. Se o contexto de arquivo de um diretório de sobreposição de fornecedor não corresponder ao diretório de destino e o contexto de arquivo correto não for especificado na sepolicy específica do dispositivo, esse diretório de sobreposição de fornecedor não será sobreposto ao diretório de destino.

Para usar a sobreposição do fornecedor, o kernel precisa ativar o OverlayFS definindo CONFIG_OVERLAY_FS=y. Além disso, o kernel precisa ser mesclado do kernel comum 4.4 ou mais recente ou corrigido com "overlayfs: override_creds=off option bypass creator_cred".

Exemplo de implementação de sobreposição do fornecedor

Este procedimento demonstra a implementação de uma sobreposição de fornecedor que sobrepõe os diretórios /vendor/lib/*, /vendor/etc/* e /vendor/app/*.

  1. Adicione arquivos de fornecedores pré-criados em device/<vendor>/<target>/vendor_overlay/<target_vendor_version>/:

    device/google/device/vendor_overlay/28/lib/libfoo.so
    device/google/device/vendor_overlay/28/lib/libbar.so
    device/google/device/vendor_overlay/28/etc/baz.xml
    device/google/device/vendor_overlay/28/app/qux.apk
  2. Instale os arquivos pré-criados do fornecedor em product/vendor_overlay no device/google/device/device.mk:

    PRODUCT_COPY_FILES += \
        $(call find-copy-subdir-files,*,device/google/device/vendor_overlay,$(TARGET_COPY_OUT_PRODUCT)/vendor_overlay)
  3. Defina contextos de arquivo se os arquivos de partição vendor de destino tiverem contextos diferentes de vendor_file. Como /vendor/lib/* usa o contexto vendor_file, este exemplo não inclui esse diretório.

    Adicione o seguinte a device/google/device-sepolicy/private/file_contexts:

    /(product|system/product)/vendor_overlay/[0-9]+/etc(/.*)?   u:object_r:vendor_configs_file:s0
    /(product|system/product)/vendor_overlay/[0-9]+/app(/.*)?   u:object_r:vendor_app_file:s0
  4. Permitir que o processo init monte a sobreposição do fornecedor em contextos de arquivo diferentes de vendor_file. Como o processo init já tem permissão para montagem no contexto vendor_file, este exemplo não define a política para vendor_file.

    Adicione o seguinte a device/google/device-sepolicy/public/init.te:

    allow init vendor_configs_file:dir mounton;
    allow init vendor_app_file:dir mounton;

Validar a sobreposição do fornecedor

Para validar a configuração de sobreposição do fornecedor, adicione arquivos em /product/vendor_overlay/<target_vendor_version>/<overlay_dir> e verifique se eles são sobrepostos aos arquivos em /vendor/<overlay_dir>.

Para builds userdebug, há um módulo de teste para Atest:

$ atest -v fs_mgr_vendor_overlay_test

Atualizar para o sistema como raiz

Para atualizar dispositivos que não são A/B para usar o sistema como raiz, é necessário atualizar o esquema de particionamento para boot.img e system.img, configurar o dm-verity e remover todas as dependências de inicialização nas pastas raiz específicas do dispositivo.

Atualizar partições

Ao contrário dos dispositivos A/B que reutilizam /boot como a partição de recuperação, os dispositivos não A/B precisam manter a partição /recovery separada, já que não têm a partição de slot de fallback (por exemplo, de boot_a para boot_b). Se /recovery for removido em um dispositivo não A/B e for semelhante ao esquema A/B, o modo de recuperação poderá falhar durante uma atualização com falha na partição /boot. Por esse motivo, a partição /recovery precisa ser uma partição separada de /boot para dispositivos não A/B, o que implica que a imagem de recuperação continua sendo atualizada de forma adiada, ou seja, da mesma forma que em dispositivos com o Android 8.1.0 ou versões anteriores.

A tabela a seguir lista as diferenças de partição de imagem para dispositivos não A/B antes e depois do Android 9.

Imagem Ramdisk (antes da versão 9) Sistema como raiz (após 9)
boot.img Contém um kernel e um ramdisk.img:
ramdisk.img
  -/
    - init.rc
    - init
    - etc -> /system/etc
    - system/ (mount point)
    - vendor/ (mount point)
    - odm/ (mount point)
    ...
Contém apenas um kernel de inicialização normal.
recovery.img Contém um kernel de recuperação e um ramdisk.img de recuperação.
system.img Contém o seguinte:
system.img
  -/
    - bin/
    - etc
    - vendor -> /vendor
    - ...
Contém o conteúdo mesclado de system.img original e ramdisk.img:
system.img
  -/
    - init.rc
    - init
    - etc -> /system/etc
    - system/
      - bin/
      - etc/
      - vendor -> /vendor
      - ...
    - vendor/ (mount point)
    - odm/ (mount point)
    ...

As partições em si não mudam. O ramdisk e o sistema como raiz usam o seguinte esquema de partição:

  • /boot
  • /system
  • /system
  • /recovery
  • /vendor etc.

Configurar o dm-verity

No sistema-como-raiz, o kernel precisa montar system.img em / (ponto de montagem) com dm-verity. O AOSP oferece suporte às seguintes implementações do dm-verity para system.img.

vboot 1.0

Para a vboot 1.0, o kernel precisa analisar os metadados específicos do Android em /system e, em seguida, convertê-los em dm-verity params para configurar o dm-verity (requer estes patches do kernel). O exemplo a seguir mostra as configurações relacionadas à dm-verity para o sistema-como-raiz na linha de comando do kernel:

ro root=/dev/dm-0 rootwait skip_initramfs init=/init
dm="system none ro,0 1 android-verity /dev/sda34"
veritykeyid=id:7e4333f9bba00adfe0ede979e28ed1920492b40f

vboot 2.0

Para o vboot 2.0 (AVB), o carregador de inicialização precisa integrar external/avb/libavb, que analisa o descriptor de hashtree para /system, o converte em dm-verity params e, por fim, os transmite para o kernel pela linha de comando. Os descritores de hashtree de /system podem estar em /vbmeta ou no próprio /system.

O vboot 2.0 requer os seguintes patches do kernel:

O exemplo a seguir mostra as configurações relacionadas à dm-verity para o sistema-como-raiz na linha de comando do kernel:

ro root=/dev/dm-0 rootwait  skip_initramfs init=/init

dm="1 vroot none ro 1,0 5159992 verity 1
PARTUUID=00000016-0000-0000-0000-000000000000
PARTUUID=00000016-0000-0000-0000-000000000000 4096 4096 644999 644999
sha1 d80b4a8be3b58a8ab86fad1b498640892d4843a2
8d08feed2f55c418fb63447fec0d32b1b107e42c 10 restart_on_corruption
ignore_zero_blocks use_fec_from_device
PARTUUID=00000016-0000-0000-0000-000000000000 fec_roots 2 fec_blocks
650080 fec_start 650080"

Usar pastas raiz específicas do dispositivo

Com o sistema como raiz, depois que a imagem genérica do sistema (GSI) é atualizada no dispositivo (e antes da execução dos testes do Conjunto de teste de fornecedores), todas as pastas raiz específicas do dispositivo adicionadas com BOARD_ROOT_EXTRA_FOLDERS são removidas porque todo o conteúdo do diretório raiz foi substituído pela GSI do sistema como raiz. A remoção dessas pastas pode fazer com que o dispositivo não possa ser inicializado se houver uma dependência das pastas raiz específicas do dispositivo (por exemplo, se elas forem usadas como pontos de montagem).

Para evitar esse problema, não use BOARD_ROOT_EXTRA_FOLDERS para adicionar pastas raiz específicas do dispositivo. Se você precisar especificar pontos de montagem específicos do dispositivo, use /mnt/vendor/<mount point> (adicionado a essas listas de mudanças). Esses pontos de montagem específicos do fornecedor podem ser especificados diretamente na árvore de dispositivos fstab (para montagem de primeira fase) e no arquivo /vendor/etc/fstab.{ro.hardware} sem configuração adicional, já que o fs_mgr as cria automaticamente no /mnt/vendor/*.