Per implementare l'A/B virtuale su un nuovo dispositivo o per aggiornare un dispositivo lanciato, è 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 in modo che ereditino 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. Cioè, BOARD_SUPER_PARTITION_SIZE
deve essere maggiore o uguale a sum(dimensione dei gruppi di aggiornamento) + sovraccarico , che, a sua volta, deve essere maggiore o uguale a sum(dimensione delle partizioni) + sovraccarico .
Per Android 13 e versioni successive, per abilitare gli snapshot compressi con Virtual A/B, eredita la seguente configurazione di base:
$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_ramdisk.mk)
$(call inherit-product, \
$(SRC_TARGET_DIR)/product/virtual_ab_ota/android_t_baseline.mk)
Ciò consente snapshot dello spazio utente con Virtual A/B utilizzando un metodo di compressione no-op. È quindi possibile configurare il metodo di compressione su uno dei metodi supportati, gz
, zstd
e lz4
.
PRODUCT_VIRTUAL_AB_COMPRESSION_METHOD := lz4
Per Android 12, per abilitare gli snapshot compressi con Virtual A/B, eredita la seguente configurazione di base:
$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_ramdisk.mk)
$(call inherit-product, \
$(SRC_TARGET_DIR)/product/virtual_ab_ota/compression.mk)
Compressione XOR
Per i dispositivi che eseguono l'aggiornamento ad Android 13 e versioni successive, la funzionalità di compressione XOR non è abilitata per impostazione predefinita. Per abilitare la compressione XOR, aggiungi quanto segue al file .mk
del dispositivo.
PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.compression.xor.enabled=true
La compressione XOR è abilitata per impostazione predefinita per i dispositivi che ereditano da android_t_baseline.mk
.
Unione dello spazio utente
Per i dispositivi che eseguono l'aggiornamento ad Android 13 e versioni successive, il processo di unione dello spazio utente descritto in Stratificazione del mapping dei dispositivi non è abilitato per impostazione predefinita. Per abilitare l'unione dello spazio utente, aggiungi la seguente riga al file .mk
del dispositivo:
PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.userspace.snapshots.enabled=true
L'unione dello spazio utente è abilitata per impostazione predefinita sui dispositivi che si avviano con 13 e versioni successive.
Controllo di avvio HAL
L' HAL di controllo di avvio fornisce un'interfaccia per i client OTA per controllare gli slot di avvio. L'A/B virtuale richiede un aggiornamento della versione minore dell'HAL di controllo di avvio poiché sono necessarie API aggiuntive per garantire che il bootloader sia protetto durante il flashing/il ripristino delle impostazioni di fabbrica. Vedere IBootControl.hal etypes.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. Pertanto, la partizione dei metadati deve essere controllata prima che first_stage_init
la monti. Per garantire che ciò accada, aggiungi il flag check
fs_mgr alla voce /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, impostare 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 dei file. Includi f2fs: supporta anche la patch del kernel del file bloccato allineato .
L'A/B virtuale si basa sulle funzionalità aggiunte nella versione 4.3 del kernel: il bit di stato di overflow nelle destinazioni snapshot
e snapshot-merge
. Tutti i dispositivi avviati 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 del primo stadio. Ciò può essere ottenuto aggiungendo la seguente riga al Makefile del dispositivo:
BOARD_GENERIC_RAMDISK_KERNEL_MODULES_LOAD := dm-user.ko
Retrofit sui dispositivi che stanno aggiornando ad Android 11
Quando si esegue l'aggiornamento ad Android 11, i dispositivi avviati con partizioni dinamiche possono facoltativamente eseguire il retrofit A/B virtuale. Il processo di aggiornamento è sostanzialmente lo stesso dell'avvio dei dispositivi 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 retrofit, c'è sempre spazio sufficiente nella super partizione in modo che il file COW non venga mai creato su/data
.Flag funzionalità in fase di creazione : per i dispositivi che eseguono il retrofit di A/B virtuale, sia
PRODUCT_VIRTUAL_AB_OTA
chePRODUCT_VIRTUAL_AB_OTA_RETROFIT
sono impostati sutrue
, 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 dimezzare
BOARD_SUPER_PARTITION_SIZE
perché gli slot B non si trovano nella super partizione. I dispositivi che eseguono il retrofit A/B virtuale mantengono la vecchia dimensione della super partizione, quindiBOARD_SUPER_PARTITION_SIZE
è maggiore o uguale a 2 * sum(dimensione dei gruppi di aggiornamento) + sovraccarico , che a sua volta è maggiore o uguale a 2 * sum(dimensione delle partizioni) + sopraelevato .
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 native system
, vendor
e product
saranno incomplete fino al termine della copia. Se durante questo processo vengono ripristinate le impostazioni di fabbrica del dispositivo, tramite ripristino o tramite la finestra di dialogo Impostazioni di sistema, il dispositivo non sarà avviabile.
Prima di cancellare /data
, completa l'unione in ripristino o rollback a seconda dello stato del dispositivo:
- Se la nuova build è stata avviata correttamente in precedenza, completa la migrazione.
- Altrimenti, torna al vecchio slot:
- Per le partizioni dinamiche, ripristina lo stato precedente.
- Per le partizioni statiche, imposta lo slot attivo sul vecchio slot.
Sia il bootloader che 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:
- Implementare l'HAL del controllo di avvio in modo che il bootloader possa leggere il valore impostato dal metodo
setSnapshotMergeStatus()
. - Se lo stato di unione è
MERGING
o se lo stato di unione èSNAPSHOTTED
e lo slot è cambiato nello slot appena aggiornato, le richieste di cancellazioneuserdata
,metadata
o della partizione che memorizza lo stato di unione devono essere rifiutate nel bootloader. - Implementa il comando
fastboot snapshot-update cancel
in modo che gli utenti possano segnalare al bootloader che desiderano bypassare questo meccanismo di protezione. - Modifica gli strumenti o gli script di flashing personalizzati per
fastboot snapshot-update cancel
durante il flashing dell'intero dispositivo. Questo è sicuro perché il flashing dell'intero dispositivo rimuove l'OTA. Gli strumenti possono rilevare questo comando in fase di esecuzione implementandofastboot 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 fastboot:
-
getvar snapshot-update-status
— Restituisce il valore che l'HAL di controllo di avvio ha comunicato al bootloader:- Se lo stato è
MERGING
, il bootloader deve restituiremerging
. - Se lo stato è
SNAPSHOTTED
, il bootloader deve restituiresnapshotted
. - Altrimenti il bootloader deve restituire
none
.
- Se lo stato è
-
snapshot-update merge
— Completa un'operazione di unione, avviando tramite recovery/fastbootd se necessario. Questo comando è valido solo sesnapshot-update-status
stamerging
ed è supportato solo in fastbootd. -
snapshot-update cancel
— Imposta lo stato di unione dell'HAL di controllo di avvio suCANCELLED
. Questo comando non è valido quando il dispositivo è bloccato. -
erase
owipe
: unaerase
owipe
dimetadata
,userdata
o una partizione che mantiene lo stato di unione per l'HAL di controllo di avvio dovrebbe controllare lo stato di unione dello snapshot. Se lo stato èMERGING
oSNAPSHOTTED
, il dispositivo dovrebbe interrompere l'operazione. -
set_active
: un comandoset_active
che modifica lo slot attivo dovrebbe verificare lo stato di unione degli snapshot. Se lo stato èMERGING
, il dispositivo dovrebbe interrompere l'operazione. Lo slot può essere modificato in sicurezza nello statoSNAPSHOTTED
.
Queste modifiche sono progettate per impedire di rendere accidentalmente non avviabile un dispositivo, ma possono disturbare gli strumenti automatizzati. Quando i comandi vengono utilizzati come componente del flashing di tutte le partizioni, come l'esecuzione fastboot flashall
, si consiglia di utilizzare il seguente flusso:
- Interroga
getvar snapshot-update-status
. - In caso di
merging
osnapshotted
, emetteresnapshot-update cancel
. - Procedere con i passaggi lampeggianti.
Ridurre i requisiti di archiviazione
Si consiglia vivamente ai dispositivi che non dispongono di spazio di archiviazione A/B completo allocato in super e che prevedono di utilizzare /data
secondo necessità, di utilizzare lo strumento di mappatura dei blocchi. Lo strumento di mappatura dei blocchi mantiene coerente l'allocazione dei blocchi tra le build, riducendo le scritture non necessarie sullo snapshot. Ciò è documentato in Riduzione delle dimensioni OTA .
Metodi di compressione OTA
I pacchetti OTA possono essere ottimizzati per diversi parametri di prestazione. Android fornisce diversi metodi di compressione supportati ( gz
, lz4
, zstd
e none
) che presentano compromessi tra tempo di installazione, utilizzo dello spazio COW, tempo di avvio e tempo di unione degli snapshot. L'opzione predefinita abilitata per ab virtuale con compressione è il gz compression method
. (Nota: le prestazioni relative tra i metodi di compressione variano a seconda della velocità della CPU e del throughput di archiviazione, che può variare a seconda del dispositivo. Tutti i pacchetti OTA generati di seguito hanno PostInstall disabilitato, il che rallenterà leggermente il tempo di avvio. La dimensione totale della partizione dinamica di un ota completo senza compressione è 4,81 GB ).
OTA incrementale su Pixel 6 Pro
Tempo di installazione senza fase postinstallazione | Utilizzo dello spazio MUCCA | Orario di avvio post OTA | Ora di unione delle istantanee | |
---|---|---|---|---|
gz | 24 minuti | 1,18GB | 40,2 secondi | 45,5 secondi |
lz4 | 13 minuti | 1,49GB | 37,4 secondi | 37,1 secondi |
nessuno | 13 minuti | 2,90GB | 37,6 secondi | 40,7 secondi |
OTA completo su Pixel 6 Pro
Tempo di installazione senza fase postinstallazione | Utilizzo dello spazio MUCCA | Orario di avvio post OTA | Ora di unione delle istantanee | |
---|---|---|---|---|
gz | 23 minuti | 2,79GB | 24,9 secondi | 41,7 secondi |
lz4 | 12 minuti | 3,46GB | 20,0 secondi | 25,3 secondi |
nessuno | 10 minuti | 4,85GB | 20,6 secondi | 29,8 secondi |