Layout della partizione

In Android 10, il file system root non è più incluso in ramdisk.img e viene invece unito a system.img (ovvero system.img viene sempre creato come se BOARD_BUILD_SYSTEM_ROOT_IMAGE fosse impostato). Dispositivi con Android 10 al lancio:

  • Utilizza un layout di partizione system-as-root (applicato automaticamente dalla build senza opzioni per modificare il comportamento).
  • Deve utilizzare un ramdisk, necessario per dm-linear.
  • Deve impostare BOARD_BUILD_SYSTEM_ROOT_IMAGE su false. Questa impostazione viene utilizzata solo per distinguere i dispositivi che utilizzano un ramdisk e i dispositivi che non lo utilizzano (e montano invece system.img direttamente).

Il significato di una configurazione system-as-root varia tra Android 9 e Android 10. In una configurazione system-as-root di Android 9, BOARD_BUILD_SYSTEM_ROOT_IMAGE è impostato su true, il che forza la build a unire il file system principale in system.img, quindi monta system.img come file system principale (rootfs). Questa configurazione è obbligatoria per i dispositivi che vengono lanciati con Android 9, ma è facoltativa per i dispositivi che eseguono l'upgrade ad Android 9 e per i dispositivi con versioni precedenti di Android. In una configurazione di sistema come root di Android 10, la build unisce sempre $TARGET_SYSTEM_OUT e $TARGET_ROOT_OUT in system.img; questa configurazione è il comportamento predefinito per tutti i dispositivi con Android 10.

Android 10 apporta ulteriori modifiche per supportare le partizioni dinamiche, un sistema di partizionamento dello spazio utente che consente agli aggiornamenti over-the-air (OTA) di creare, ridimensionare o eliminare partizioni. Nell'ambito di questa modifica, il kernel Linux non può più montare la partizione di sistema logica sui dispositivi con Android 10, quindi questa operazione viene gestita dall'inizializzazione della prima fase.

Le sezioni seguenti descrivono i requisiti di sistema come root per gli aggiornamenti OTA solo di sistema e forniscono indicazioni sull'aggiornamento dei dispositivi per utilizzare il sistema come root (inclusi i cambiamenti del layout delle partizioni e i requisiti del kernel dm-verity). Per i dettagli sulle modifiche al ramdisk, vedi Partizioni ramdisk.

Informazioni sugli aggiornamenti OTA solo di sistema

Gli aggiornamenti OTA solo di sistema, che consentono di aggiornare le release di Android system.img e product.img senza modificare altre partizioni, richiedono un layout di partizione system-as-root. Tutti i dispositivi con Android 10 devono utilizzare un layout di partizione system-as-root per attivare gli aggiornamenti OTA solo di sistema.

  • I dispositivi A/B, che montano la partizione system come rootfs, utilizzano già system-as-root e non richiedono modifiche per supportare gli aggiornamenti OTA del sistema.
  • I dispositivi non A/B, che montano la partizione system in /system, devono essere aggiornati per utilizzare un layout di partizione system-as-root per supportare gli aggiornamenti OTA del sistema.

Per informazioni dettagliate sui dispositivi A/B e non A/B, consulta Aggiornamenti di sistema A/B (senza interruzioni).

Utilizzare l'overlay del fornitore (<=AOSP 14)

L'overlay del fornitore consente di sovrapporre le modifiche alla partizione vendor al momento dell'avvio del dispositivo. Un overlay del fornitore è un insieme di moduli del fornitore nella partizione product che vengono sovrapposti alla partizione vendor all'avvio del dispositivo, sostituendo e aggiungendo i moduli esistenti.

Quando il dispositivo si avvia, il processo init completa il montaggio della prima fase e legge le proprietà predefinite. Poi cerca /product/vendor_overlay/<target_vendor_version> e monta ogni sottodirectory nella directory di partizione vendor corrispondente, se vengono soddisfatte le seguenti condizioni:

  • /vendor/<overlay_dir> esiste.
  • /product/vendor_overlay/<target_vendor_version>/<overlay_dir> ha lo stesso contesto del file di /vendor/<overlay_dir>.
  • init è autorizzato a eseguire il montaggio nel contesto del file /vendor/<overlay_dir>.

Implementare l'overlay del fornitore

Installa i file di overlay del fornitore in /product/vendor_overlay/<target_vendor_version>. Questi file si sovrappongono alla partizione vendor all'avvio del dispositivo, sostituendo i file con lo stesso nome e aggiungendo eventuali nuovi file. La sovrapposizione del fornitore non può rimuovere file dalla partizione vendor.

I file di overlay del fornitore devono avere lo stesso contesto dei file di destinazione che sostituiscono nella partizione vendor. Per impostazione predefinita, i file nella directory /product/vendor_overlay/<target_vendor_version> hanno il contesto vendor_file. Se si verificano mancate corrispondenze del contesto dei file tra i file di overlay del fornitore e i file che sostituiscono, specifica questo problema nel sepolicy specifico del dispositivo. Il contesto del file viene impostato a livello di directory. Se il contesto del file di una directory di overlay del fornitore non corrisponde alla directory di destinazione e il contesto del file corretto non è specificato in sepolicy specifico del dispositivo, la directory di overlay del fornitore non viene sovrapposta alla directory di destinazione.

Per utilizzare l'overlay del fornitore, il kernel deve abilitare OverlayFS impostando CONFIG_OVERLAY_FS=y. Inoltre, il kernel deve essere unito dal kernel comune 4.4 o versioni successive oppure corretto con "overlayfs: override_creds=off option bypass creator_cred".

Esempio di implementazione dell'overlay del fornitore

Questa procedura mostra l'implementazione di una sovrapposizione del fornitore che si sovrappone alle directory /vendor/lib/*, /vendor/etc/* e /vendor/app/*.

  1. Aggiungi file fornitore predefiniti in 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. Installa i file del fornitore precompilati in product/vendor_overlay in 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. Definisci i contesti dei file se i file di partizione vendor di destinazione hanno contesti diversi da vendor_file. Poiché /vendor/lib/* utilizza il contesto vendor_file, questo esempio non include questa directory.

    Aggiungi quanto segue 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. Consenti al processo init di montare l'overlay del fornitore sui contesti dei file diversi da vendor_file. Poiché il processo init ha già l'autorizzazione per il montaggio nel contesto vendor_file, questo esempio non definisce le norme per vendor_file.

    Aggiungi quanto segue a device/google/device-sepolicy/public/init.te:

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

Convalida dell'overlay del fornitore

Per convalidare la configurazione dell'overlay del fornitore, aggiungi file in /product/vendor_overlay/<target_vendor_version>/<overlay_dir> e controlla se i file vengono sovrapposti a quelli in /vendor/<overlay_dir>.

Per le build userdebug, è disponibile un modulo di test per Atest:

$ atest -v fs_mgr_vendor_overlay_test

Aggiornamento a system-as-root

Per aggiornare i dispositivi non A/B in modo che utilizzino system-as-root, devi aggiornare lo schema di partizionamento per boot.img e system.img, configurare dm-verity e rimuovere eventuali dipendenze di avvio dalle cartelle root specifiche del dispositivo.

Aggiorna partizioni

A differenza dei dispositivi A/B che riutilizzano /boot come partizione di recupero, i dispositivi non A/B devono mantenere separata la partizione /recovery in quanto non dispongono della partizione di slot di fallback (ad esempio, da boot_a a boot_b). Se /recovery viene rimossa su un dispositivo non A/B e resa simile allo schema A/B, la modalità di recupero potrebbe non funzionare durante un aggiornamento non riuscito alla partizione /boot. Per questo motivo, la partizione /recovery deve essere una partizione separata da /boot per i dispositivi non A/B, il che implica che l'immagine di ripristino continua a essere aggiornata in modo differito (ovvero come nei dispositivi con Android 8.1.0 o versioni precedenti).

La seguente tabella elenca le differenze tra le partizioni delle immagini per i dispositivi non A/B prima e dopo Android 9.

Immagine Ramdisk (prima di Android 9) System-as-root (dopo Android 9)
boot.img Contiene un kernel e un ramdisk.img:
ramdisk.img
  -/
    - init.rc
    - init
    - etc -> /system/etc
    - system/ (mount point)
    - vendor/ (mount point)
    - odm/ (mount point)
    ...
Contiene solo un kernel di avvio normale.
recovery.img Contiene un kernel di ripristino e un ripristino ramdisk.img.
system.img Contiene quanto segue:
system.img
  -/
    - bin/
    - etc
    - vendor -> /vendor
    - ...
Contiene i contenuti uniti di system.img e ramdisk.img:
system.img
  -/
    - init.rc
    - init
    - etc -> /system/etc
    - system/
      - bin/
      - etc/
      - vendor -> /vendor
      - ...
    - vendor/ (mount point)
    - odm/ (mount point)
    ...

Le partizioni stesse non cambiano; sia ramdisk che system-as-root utilizzano il seguente schema di partizione:

  • /boot
  • /system
  • /system
  • /recovery
  • /vendor e così via.

Configurare dm-verity

In system-as-root, il kernel deve montare system.img in / (punto di montaggio) con dm-verity. AOSP supporta le seguenti implementazioni di dm-verity per system.img.

vboot 1.0

Per vboot 1.0, il kernel deve analizzare i metadati specifici di Android su /system, quindi convertirli in parametri dm-verity per configurare dm-verity (richiede queste patch del kernel). L'esempio seguente mostra le impostazioni relative a dm-verity per system-as-root nella riga di comando del 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

Per vboot 2.0 (AVB), il bootloader deve integrare external/avb/libavb, che analizza il descrittore dell'albero hash per /system, lo converte in parametri dm-verity e infine li passa al kernel tramite la riga di comando del kernel. (I descrittori Hashtree di /system potrebbero trovarsi in /vbmeta o in /system stesso.)

vboot 2.0 richiede le seguenti patch del kernel:

L'esempio seguente mostra le impostazioni relative a dm-verity per system-as-root nella riga di comando del 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"

Utilizzare cartelle radice specifiche del dispositivo

Con system-as-root, dopo che l'immagine di sistema generica (GSI) è stata caricata sul dispositivo (e prima di eseguire i test della Vendor Test Suite), tutte le cartelle root specifiche del dispositivo aggiunte con BOARD_ROOT_EXTRA_FOLDERS non sono più presenti perché l'intero contenuto della directory root è stato sostituito dalla GSI system-as-root. La rimozione di queste cartelle potrebbe rendere il dispositivo non avviabile se esiste una dipendenza dalle cartelle root specifiche del dispositivo (ad esempio, vengono utilizzate come punti di montaggio).

Per evitare questo problema, non utilizzare BOARD_ROOT_EXTRA_FOLDERS per aggiungere cartelle principali specifiche del dispositivo. Se devi specificare punti di montaggio specifici per dispositivo, utilizza /mnt/vendor/<mount point> (aggiunto in questi elenchi delle modifiche). Questi punti di montaggio specifici del fornitore possono essere specificati direttamente sia nel Device Tree fstab (per il montaggio di primo livello) sia nel file /vendor/etc/fstab.{ro.hardware} senza configurazione aggiuntiva (in quanto fs_mgr li crea automaticamente in /mnt/vendor/*).