Implementazione dell'A/B virtuale

Per implementare l'A/B virtuale su un nuovo dispositivo o per aggiornare un dispositivo avviato, è necessario apportare modifiche al codice specifico del dispositivo.

Costruisci bandiere

I dispositivi che utilizzano A/B virtuale devono essere configurati come dispositivo A/B e devono essere avviati con partizioni dinamiche .

Per i dispositivi avviati con A/B virtuale, impostali per ereditare la configurazione di base del dispositivo A/B virtuale:

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

I dispositivi avviati con A/B virtuale richiedono solo la metà delle dimensioni della scheda per BOARD_SUPER_PARTITION_SIZE perché gli slot B non sono più in super. Ovvero, BOARD_SUPER_PARTITION_SIZE deve essere maggiore o uguale a sum(size of update groups) + overhead , che, a sua volta, deve essere maggiore o uguale a sum(size of partitions) + overhead .

Per abilitare gli snapshot compressi con Virtual A/B, eredita invece la seguente configurazione di base:

$(call inherit-product, \
    $(SRC_TARGET_DIR)/product/virtual_ab_ota/compression.mk)

Controllo di avvio HAL

Il controllo di avvio HAL fornisce un'interfaccia per i client OTA per controllare gli slot di avvio. Virtual A/B richiede un aggiornamento della versione minore dell'HAL di controllo di avvio perché sono necessarie API aggiuntive per garantire che il bootloader sia protetto durante il flashing/il ripristino delle impostazioni di fabbrica. Vedere IBootControl.hal e types.hal per la versione più recente della definizione HAL.

// hardware/interfaces/boot/1.1/types.hal
enum MergeStatus : uint8_t {
    NONE, UNKNOWN, SNAPSHOTTED, MERGING, CANCELLED };

// hardware/interfaces/boot/1.1/IBootControl.hal
package android.hardware.boot@1.1;
interface IBootControl extends @1.0::IBootControl {
    setSnapshotMergeStatus(MergeStatus status)
        generates (bool success);
    getSnapshotMergeStatus()
        generates (MergeStatus status);
}
// Recommended implementation

Return<bool> BootControl::setSnapshotMergeStatus(MergeStatus v) {
    // Write value to persistent storage
    // e.g. misc partition (using libbootloader_message)
    // bootloader rejects wipe when status is SNAPSHOTTED
    // or MERGING
}

Fstab cambia

L'integrità della partizione dei metadati è essenziale per il processo di avvio, soprattutto subito dopo l'applicazione di un aggiornamento OTA. Quindi, la partizione dei metadati deve essere controllata prima che first_stage_init la monti. Per assicurarti che ciò accada, aggiungi il flag check fs_mgr alla voce per /metadata . Di seguito viene fornito un esempio:

/dev/block/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard,sync wait,formattable,first_stage_mount,check

Requisiti del kernel

Per abilitare lo snapshot, imposta CONFIG_DM_SNAPSHOT su true .

Per i dispositivi che utilizzano F2FS, includere il flag f2fs: export FS_NOCOW_FL nella patch del kernel dell'utente per correggere il blocco del file. Includi f2fs: supporta anche la patch del kernel con file bloccati allineati .

Virtual A/B si basa sulle funzionalità aggiunte nella versione del kernel 4.3: il bit di stato di overflow nello snapshot e le destinazioni snapshot-merge . Tutti i dispositivi che si avviano con Android 9 e versioni successive dovrebbero già avere la versione del kernel 4.4 o successiva.

Per abilitare gli snapshot compressi, la versione minima del kernel supportata è 4.19. Impostare CONFIG_DM_USER=m o CONFIG_DM_USER=y . Se si utilizza il primo (un modulo), il modulo deve essere caricato nel ramdisk di primo stadio. Ciò può essere ottenuto aggiungendo la seguente riga al Makefile del dispositivo:

BOARD_GENERIC_RAMDISK_KERNEL_MODULES_LOAD := dm-user.ko

Retrofit su dispositivi che eseguono l'aggiornamento ad Android 11

Quando si esegue l'aggiornamento ad Android 11, i dispositivi avviati con partizioni dinamiche possono opzionalmente adattare A/B virtuale. Il processo di aggiornamento è per lo più lo stesso dei dispositivi avviati con A/B virtuale, con alcune piccole differenze:

  • Posizione dei file COW — Per i dispositivi di avvio, il client OTA utilizza tutto lo spazio vuoto disponibile nella super partizione prima di utilizzare lo spazio in /data . Per i dispositivi di retrofit, c'è sempre spazio sufficiente nella super partizione in modo che il file COW non venga mai creato su /data .

  • Flag delle funzionalità in fase di creazione : per i dispositivi che eseguono il retrofit di A/B virtuale, sia PRODUCT_VIRTUAL_AB_OTA che PRODUCT_VIRTUAL_AB_OTA_RETROFIT sono impostati su true , come mostrato di seguito:

    (call inherit-product, \
        (SRC_TARGET_DIR)/product/virtual_ab_ota_retrofit.mk)
    
  • Dimensioni della super partizione : i dispositivi avviati con A/B virtuale possono BOARD_SUPER_PARTITION_SIZE perché gli slot B non si trovano nella super partizione. I dispositivi che adattano A/B virtuale mantengono la vecchia dimensione della super partizione, quindi BOARD_SUPER_PARTITION_SIZE è maggiore o uguale a 2 * sum(dimensione dei gruppi di aggiornamento) + overhead , che a sua volta è maggiore o uguale a 2 * sum(dimensione delle partizioni) + spese generali .

Modifiche al bootloader

Durante la fase di unione di un aggiornamento, /data contiene l'unica istanza intera del sistema operativo Android. Una volta avviata la migrazione, le partizioni del system nativo, del vendor e del product sono incomplete fino al termine della copia. Se il dispositivo viene ripristinato alle impostazioni di fabbrica durante questo processo, tramite ripristino o tramite la finestra di dialogo Impostazioni di sistema, il dispositivo non sarebbe avviabile.

Prima di cancellare /data , termina l'unione in recovery o rollback a seconda dello stato del dispositivo:

  • Se la nuova build è stata avviata correttamente in precedenza, termina la migrazione.
  • Altrimenti, torna al vecchio slot:
    • Per le partizioni dinamiche, ripristinare lo stato precedente.
    • Per le partizioni statiche, impostare lo slot attivo sul vecchio slot.

Sia il bootloader che il fastbootd possono cancellare la partizione /data se il dispositivo è sbloccato. Mentre fastbootd può forzare il completamento della migrazione, il bootloader non può. Il bootloader non sa se è in corso o meno un'unione o quali blocchi in /data costituiscono le partizioni del sistema operativo. I dispositivi devono impedire all'utente di rendere inconsapevolmente il dispositivo inutilizzabile (bricking) effettuando le seguenti operazioni:

  1. Implementare il controllo di avvio HAL in modo che il bootloader possa leggere il valore impostato dal metodo setSnapshotMergeStatus() .
  2. Se lo stato di unione è MERGING o se lo stato di unione è SNAPSHOTTED e lo slot è cambiato nello slot appena aggiornato, le richieste di cancellare i dati userdata , i metadata o la partizione che memorizza lo stato di unione devono essere rifiutate nel bootloader.
  3. Implementare il comando fastboot snapshot-update cancel in modo che gli utenti possano segnalare al bootloader che desiderano bypassare questo meccanismo di protezione.
  4. Modifica gli strumenti o gli script di flashing personalizzati per eseguire fastboot snapshot-update cancel rapido durante il flashing dell'intero dispositivo. Questo è sicuro da emettere perché il flashing dell'intero dispositivo rimuove l'OTA. Tooling può rilevare questo comando in fase di esecuzione implementando fastboot getvar snapshot-update-status . Questo comando aiuta a distinguere tra le condizioni di errore.

Esempio

struct VirtualAbState {
    uint8_t StructVersion;
    uint8_t MergeStatus;
    uint8_t SourceSlot;
};

bool ShouldPreventUserdataWipe() {
    VirtualAbState state;
    if (!ReadVirtualAbState(&state)) ...
    return state.MergeStatus == MergeStatus::MERGING ||
           (state.MergeStatus == MergeStatus::SNAPSHOTTED &&
            state.SourceSlot != CurrentSlot()));
}

Modifiche agli strumenti di avvio rapido

Android 11 apporta le seguenti modifiche al protocollo di avvio rapido:

  • getvar snapshot-update-status — Restituisce il valore che il controllo di avvio HAL ha comunicato al bootloader:
    • Se lo stato è MERGING , il bootloader deve restituire merging .
    • Se lo stato è SNAPSHOTTED , il bootloader deve restituire lo snapshotted .
    • In caso contrario, il bootloader deve restituire none .
  • snapshot-update merge — Completa un'operazione di unione, avviando recovery/fastbootd se necessario. Questo comando è valido solo se snapshot-update-status è merging ed è supportato solo in fastbootd.
  • snapshot-update cancel — Imposta lo stato di unione del controllo di avvio HAL su CANCELLED . Questo comando non è valido quando il dispositivo è bloccato.
  • erase o wipe : una erase o wipe di metadata , dati userdata o una partizione che mantiene lo stato di unione per il controllo di avvio HAL dovrebbe controllare lo stato di unione delle istantanee. Se lo stato è MERGING o SNAPSHOTTED , il dispositivo dovrebbe interrompere l'operazione.
  • set_active — Un comando set_active che modifica lo slot attivo dovrebbe controllare lo stato di unione delle istantanee. Se lo stato è MERGING , il dispositivo dovrebbe interrompere l'operazione. Lo slot può essere modificato in sicurezza nello stato SNAPSHOTTED .

Queste modifiche sono progettate per impedire l'avvio accidentale di un dispositivo, ma possono essere di disturbo per gli strumenti automatizzati. Quando i comandi vengono utilizzati come componente del flashing di tutte le partizioni, ad esempio l'esecuzione di fastboot flashall , si consiglia di utilizzare il flusso seguente:

  1. Interroga getvar snapshot-update-status .
  2. In caso di merging o snapshotted , emettere snapshot-update cancel .
  3. Procedere con i passaggi lampeggianti.

Riduzione dei requisiti di archiviazione

Si consiglia vivamente di utilizzare lo strumento di mappatura dei blocchi per i dispositivi che non dispongono di memoria A/B completa allocata in super e si aspettano di utilizzare /data se necessario. Lo strumento di mappatura dei blocchi mantiene l'allocazione dei blocchi coerente tra le build, riducendo le scritture non necessarie sullo snapshot. Ciò è documentato in Riduzione delle dimensioni OTA .