No Android 10, o sistema de arquivos raiz não está mais incluído em ramdisk.img e, em vez disso, é mesclado em system.img (ou seja, system.img é sempre criado como se BOARD_BUILD_SYSTEM_ROOT_IMAGE estivesse definido). Dispositivos lançados com Android 10:
- Use um layout de partição do sistema como raiz (imposto automaticamente pela compilação sem opções para alterar o comportamento).
- Deve usar um ramdisk, que é necessário para dm-linear.
- Deve definir
BOARD_BUILD_SYSTEM_ROOT_IMAGEcomofalse. Essa configuração é usada apenas para diferenciar entre dispositivos que usam um ramdisk e dispositivos que não usam um ramdisk (e, em vez disso, montamsystem.imgdiretamente).
O significado de uma configuração de sistema como raiz difere entre o Android 9 e o Android 10. Em uma configuração de sistema como raiz do Android 9, BOARD_BUILD_SYSTEM_ROOT_IMAGE é definido como true , o que força a compilação a mesclar o sistema de arquivos raiz em system.img e mount system.img como o sistema de arquivos raiz (rootfs). Essa configuração é obrigatória para dispositivos iniciados com o Android 9, mas é opcional para dispositivos que atualizam para o Android 9 e para dispositivos que executam versões anteriores do Android. Em uma configuração de sistema como raiz do Android 10, a compilação sempre mescla $TARGET_SYSTEM_OUT e $TARGET_ROOT_OUT em system.img ; esta configuração é o comportamento padrão para todos os dispositivos que executam o Android 10.
O Android 10 faz outras alterações para oferecer suporte a partições dinâmicas , um sistema de particionamento de espaço do usuário que permite atualizações OTA (over-the-air) para criar, redimensionar ou destruir partições. Como parte dessa alteração, o kernel do Linux não pode mais montar a partição do sistema lógico em dispositivos que executam o Android 10, portanto, essa operação é tratada pelo init do primeiro estágio.
As seções a seguir descrevem os requisitos de sistema como raiz para OTAs somente de sistema, fornecem orientação sobre a atualização de dispositivos para usar o sistema como raiz (incluindo alterações de layout de partição e requisitos de kernel dm-verity). Para obter detalhes sobre as alterações no ramdisk, consulte Ramdisk Partitions .
Sobre OTAs somente do sistema
OTAs somente do sistema, que permitem que versões do Android atualizem system.img e product.img sem alterar outras partições, exigem um layout de partição de sistema como raiz. Todos os dispositivos que executam o Android 10 devem usar um layout de partição do sistema como raiz para habilitar OTAs somente do sistema.
- Os dispositivos A/B, que montam a partição do
systemcomo rootfs, já usam o sistema como root e não exigem alterações para oferecer suporte a OTAs do sistema. - Dispositivos não A/B, que montam a partição do
systemem/system, devem ser atualizados para usar um layout de partição do sistema como raiz para oferecer suporte a OTAs do sistema.
Para obter detalhes sobre dispositivos A/B e não A/B, consulte Atualizações do sistema A/B (sem interrupções) .
Usando sobreposição de fornecedor
A sobreposição do fornecedor permite sobrepor alterações na partição do vendor no momento da inicialização do dispositivo. Uma sobreposição de fornecedor é um conjunto de módulos de fornecedor na partição do product que são sobrepostos na partição de vendor quando o dispositivo é inicializado, substituindo e adicionando aos módulos existentes.
Quando o dispositivo é inicializado, o processo init conclui a montagem do primeiro estágio e lê as propriedades padrão. Em seguida, ele pesquisa /product/vendor_overlay/<target_vendor_version> e monta cada subdiretório em seu diretório de partição de vendor correspondente, se as seguintes condições forem atendidas:
-
/vendor/<overlay_dir>existe. -
/product/vendor_overlay/<target_vendor_version>/<overlay_dir>tem o mesmo contexto de arquivo que/vendor/<overlay_dir>. -
inittem permissão para montar no contexto de arquivo de/vendor/<overlay_dir>.
Implementando a sobreposição do fornecedor
Instale os arquivos de sobreposição do fornecedor em /product/vendor_overlay/<target_vendor_version> . Esses arquivos se sobrepõem à partição do 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 do vendor .
Os arquivos de sobreposição do fornecedor devem ter o mesmo contexto de arquivo que os arquivos de destino que eles substituem na partição do 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 política de segurança 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 deve habilitar o OverlayFS configurando CONFIG_OVERLAY_FS=y . Além disso, o kernel deve ser mesclado do kernel comum 4.4 ou posterior, ou corrigido com "overlayfs: override_creds=off option bypass creator_cred" .
Exemplo de implementação de sobreposição de 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/* .
Adicione arquivos de fornecedor pré-construídos 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
Instale os arquivos de fornecedor pré-criados em
product/vendor_overlayemdevice/google/device/device.mk:PRODUCT_COPY_FILES += \ $(call find-copy-subdir-files,*,device/google/device/vendor_overlay,$(TARGET_COPY_OUT_PRODUCT)/vendor_overlay)Defina os contextos de arquivo se os arquivos de partição do
vendorde destino tiverem contextos diferentes devendor_file. Como/vendor/lib/*usa o contextovendor_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
Permita que o processo de
initmonte a sobreposição de fornecedor em contextos de arquivo diferentes devendor_file. Como o processoinitjá tem permissão para montar no contextovendor_file, este exemplo não define a política paravendor_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;
Validando 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 os arquivos estão sobrepostos nos arquivos em /vendor/<overlay_dir> .
Para builds de userdebug , há um módulo de teste para Atest :
$ atest -v fs_mgr_vendor_overlay_test
Atualizando para sistema como root
Para atualizar dispositivos não A/B para usar o sistema como raiz, você deve atualizar o esquema de particionamento para boot.img e system.img , configurar dm-verity e remover quaisquer dependências de inicialização nas pastas raiz específicas do dispositivo.
Atualizando partições
Ao contrário dos dispositivos A/B que redirecionam /boot como partição de recuperação , os dispositivos não A/B devem manter a partição /recovery separada, pois não possuem a partição do 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á ser interrompido durante uma atualização com falha na partição /boot . Por esse motivo, a partição /recovery deve ser uma partição separada de /boot para dispositivos não A/B, o que implica que a imagem de recuperação continuará sendo atualizada de maneira diferida (ou seja, da mesma forma que em dispositivos com Android 8.1.0 ou inferior).
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 de 9) | Sistema como root (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 do 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; tanto o ramdisk quanto o system-as-root usam o seguinte esquema de partição:
-
/boot -
/system -
/system -
/recovery -
/vendor, etc
Configurando o dm-verity
Em system-as-root, o kernel deve montar system.img em / (ponto de montagem) com dm-verity . O AOSP suporta as seguintes implementações de dm-verity para system.img .
vboot 1.0
Para vboot 1.0 , o kernel deve analisar metadados específicos do Android em /system , depois converter para parâmetros dm-verity para configurar dm-verity (requer esses patches do kernel ). O exemplo a seguir mostra as configurações relacionadas ao dm-verity para system-as-root 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 vboot 2.0 ( AVB ), o bootloader deve integrar external/avb/libavb , que então analisa o descritor hashtree para /system , converte-o em dm-verity params e finalmente passa os parâmetros para o kernel através da linha de comando do kernel. (Os descritores de hashtree de /system podem estar em /vbmeta ou no próprio /system .)
O vboot 2.0 requer os seguintes patches de kernel:
- https://android-review.googlesource.com/#/c/kernel/common/+/158491/
- patches do kernel 4.4, patches do kernel 4.9 , etc.
O exemplo a seguir mostra as configurações relacionadas ao dm-verity para system-as-root 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"
Usando pastas raiz específicas do dispositivo
Com o sistema como raiz, depois que a imagem genérica do sistema (GSI) é exibida no dispositivo (e antes de executar os testes do Vendor Test Suite ), todas as pastas raiz específicas do dispositivo adicionadas com BOARD_ROOT_EXTRA_FOLDERS desaparecem porque todo o conteúdo do diretório raiz foi substituído pelo GSI do sistema como raiz. A remoção dessas pastas pode fazer com que o dispositivo não inicialize se existir uma dependência nas pastas raiz específicas do dispositivo (por exemplo, elas são 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 nestas listas de alterações). Esses pontos de montagem específicos do fornecedor podem ser especificados diretamente na árvore de dispositivos fstab (para montagem de primeiro estágio) e no arquivo /vendor/etc/fstab.{ro.hardware} sem configuração adicional (já que o fs_mgr os cria em /mnt/vendor/* automaticamente).