Layout della partizione

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

  • Utilizza un layout della partizione del sistema come radice (applicato automaticamente dalla compilazione senza opzioni per modificare il comportamento).
  • Deve essere utilizzato un ramdisk, che è obbligatorio per dm-linear.
  • Deve essere impostato BOARD_BUILD_SYSTEM_ROOT_IMAGE su false. Questa impostazione viene utilizzata solo per distinguere i dispositivi che utilizzano un ramdisk da quelli che non lo utilizzano (e montano invece system.img direttamente).

Il significato di una configurazione del sistema come root è diverso 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 compilazione a unire il file system principale in system.img e poi a montare system.img come file system principale (rootfs). Questa configurazione è obbligatoria per i dispositivi avviati 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 system-as-root di Android 10, la compilazione unisce sempre $TARGET_SYSTEM_OUT e $TARGET_ROOT_OUT in system.img. Questo è il comportamento predefinito per tutti i dispositivi con Android 10.

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

Le sezioni seguenti descrivono i requisiti di sistema come root per gli aggiornamenti OTA solo del sistema e forniscono indicazioni su come aggiornare i dispositivi per utilizzare il sistema come root (incluse le modifiche al layout delle partizioni e i requisiti del kernel dm-verity). Per dettagli sulle modifiche al ramdisk, consulta Partizioni del ramdisk.

Informazioni sugli aggiornamenti OTA solo di sistema

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

Per maggiori dettagli sui dispositivi A/B e non A/B, consulta Aggiornamenti di sistema A/B (seamless).

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

L'overlay del fornitore ti 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 viene sovrapposto alla partizione vendor al momento dell'avvio del dispositivo, sostituendo e integrando i moduli esistenti.

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

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

Implementare l'overlay del fornitore

Installa i file di overlay del fornitore in /product/vendor_overlay/<target_vendor_version>. Questi file sovrappongono la partizione vendor all'avvio del dispositivo, sostituendo i file dello stesso nome e aggiungendo eventuali nuovi file. L'overlay del fornitore non può rimuovere i 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 esistono discrepanze nel contesto dei file tra i file in overlay del fornitore e i file che sostituiscono, specificalo nel file sepolicy specifico del dispositivo. Il contesto file viene impostato a livello di directory. Se il contesto file di una directory overlay del fornitore non corrisponde alla directory di destinazione e il contesto file corretto non è specificato nel file sepolicy specifico del dispositivo, la directory overlay del fornitore non viene sovrapposta alla directory di destinazione.

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

Esempio di implementazione dell'overlay del fornitore

Questa procedura mostra l'implementazione di un overlay del fornitore che sovrappone le directory /vendor/lib/*, /vendor/etc/* e /vendor/app/*.

  1. Aggiungi i file dei fornitori 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 predefiniti 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 della 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 su contesti di file diversi da vendor_file. Poiché il processo init ha già l'autorizzazione per il montaggio nel contesto vendor_file, in questo esempio non viene definito il criterio 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 l'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 sono sovrapposti ai file 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 il sistema come utente root, devi aggiornare lo schema di partizione per boot.img e system.img, configurare dm-verity e rimuovere eventuali dipendenze di avvio dalle cartelle principali specifiche del dispositivo.

Aggiornare le partizioni

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

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

Immagine Ramdisk (prima della versione 9) Sistema come root (dopo 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 normale kernel di avvio.
recovery.img Contiene un kernel di recupero e un recupero ramdisk.img.
system.img Contiene quanto segue:
system.img
  -/
    - bin/
    - etc
    - vendor -> /vendor
    - ...
Contiene i contenuti uniti di system.img e ramdisk.img originali:
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 il ramdisk sia il sistema come 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 sotto / (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 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 il sistema come utente 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 poi analizza il descrittore hashtree per /system, lo converte in dm-verity params e infine passa i parametri al kernel tramite la riga di comando del kernel. I descrittori dell'albero hash di /system potrebbero trovarsi su /vbmeta o su /system stesso.

vboot 2.0 richiede le seguenti patch del kernel:

L'esempio seguente mostra le impostazioni relative a dm-verity per il sistema come utente 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 principali specifiche del dispositivo

Con il sistema come utente root, dopo aver eseguito il flashing dell'immagine di sistema generica (GSI) sul dispositivo (e prima di eseguire i test della Vendor Test Suite), tutte le cartelle principali specifiche del dispositivo aggiunte con BOARD_ROOT_EXTRA_FOLDERS non sono più disponibili perché l'intera directory principale è stata sostituita dall'immagine di sistema generica (GSI). La rimozione di queste cartelle potrebbe causare l'impossibilità di avviare il dispositivo se esiste una dipendenza dalle cartelle principali specifiche del dispositivo (ad esempio, se vengono utilizzate come punti di montaggio).

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