Per implementare l'A/B virtuale su un nuovo dispositivo o per eseguire il retrofit di un dispositivo avviato, è necessario apportare modifiche al codice specifico del dispositivo.
Costruisci bandiere
I dispositivi che utilizzano A/B virtuale devono essere configurati come dispositivi A/B e devono essere avviati con partizioni dinamiche .
Per i dispositivi che si avviano 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 che si avviano 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(size of update groups) + overhead , che, a sua volta, deve essere maggiore o uguale a sum(size of partitions) + overhead .
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ò abilita le istantanee dello spazio utente con Virtual A/B mentre si utilizza un metodo di compressione no-op. È quindi possibile configurare il metodo di compressione su uno dei metodi supportati, gz
e brotli
.
PRODUCT_VIRTUAL_AB_COMPRESSION_METHOD := gz
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 funzione 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
.
Fusione dello spazio utente
Per i dispositivi che eseguono l'aggiornamento ad Android 13 e versioni successive, il processo di unione dello spazio utente come descritto in Stratificazione device-mapper 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. Virtual A/B richiede un aggiornamento della versione minore dell'HAL di controllo di avvio perché sono necessarie API aggiuntive per garantire la protezione del bootloader durante il flashing/ripristino delle impostazioni di fabbrica. Vedere IBootControl.hal e types.hal per l'ultima versione 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
. Quanto segue fornisce 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, includi 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 dei file bloccati allineati .
Virtual A/B 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 che si avviano con Android 9 e versioni successive dovrebbero già disporre della versione del kernel 4.4 o successiva.
Per abilitare gli snapshot compressi, la versione minima del kernel supportata è 4.19. Imposta CONFIG_DM_USER=m
CONFIG_DM_USER=y
. Se si utilizza il primo (un modulo), il modulo deve essere caricato nel ramdisk di prima fase. 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 facoltativamente aggiornare A/B virtuale. Il processo di aggiornamento è sostanzialmente lo stesso dei dispositivi che si avviano 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 delle funzionalità in fase di compilazione : per i dispositivi che aggiornano 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 che si avviano con A/B virtuale possono dimezzare
BOARD_SUPER_PARTITION_SIZE
perché gli slot B non si trovano nella super partizione. I dispositivi che aggiornano l'A/B virtuale mantengono la vecchia dimensione della super partizione, quindiBOARD_SUPER_PARTITION_SIZE
è maggiore o uguale a 2 * sum(size of update groups) + overhead , che a sua volta è maggiore o uguale a 2 * sum(size of partitions) + 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 , vendor
e 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 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, terminare la migrazione.
- Altrimenti, esegui il rollback al vecchio slot:
- Per le partizioni dinamiche, eseguire il rollback allo stato precedente.
- Per le partizioni statiche, impostare 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 no. 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 inutilizzabile il dispositivo (bricking) procedendo come segue:
- Implementare l'HAL di 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 cancellareuserdata
,metadata
o la 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 vogliono ignorare questo meccanismo di protezione. - Modifica gli strumenti o gli script di flashing personalizzati per eseguire
fastboot snapshot-update cancel
durante il flashing dell'intero dispositivo. Questo è sicuro da emettere 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 differenziare 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 Fastboot
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
. - In caso contrario, il bootloader deve restituire
none
.
- Se lo stato è
-
snapshot-update merge
— Completa un'operazione di unione, avviando in recovery/fastbootd se necessario. Questo comando è valido solo sesnapshot-update-status
èmerging
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
orwipe
— Unaerase
owipe
dimetadata
,userdata
o una partizione contenente 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 controllare lo stato di unione delle istantanee. Se lo stato èMERGING
, il dispositivo dovrebbe interrompere l'operazione. Lo slot può essere tranquillamente modificato nello statoSNAPSHOTTED
.
Queste modifiche sono progettate per evitare di rendere accidentalmente un dispositivo non avviabile, ma possono essere dannose per 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:
- Query
getvar snapshot-update-status
. - In caso di
merging
osnapshotted
, emetteresnapshot-update cancel
. - Procedere con passaggi lampeggianti.
Riduzione dei requisiti di archiviazione
I dispositivi che non dispongono di spazio di archiviazione A/B completo allocato in super e prevedono di utilizzare /data
se necessario, sono vivamente consigliati di utilizzare lo strumento di mappatura dei blocchi. Lo strumento di mappatura dei blocchi mantiene l'allocazione dei blocchi coerente tra le build, riducendo le scritture non necessarie sullo snapshot. Questo è documentato in Riduzione delle dimensioni OTA .
Metodi di compressione OTA
I pacchetti Ota possono essere ottimizzati per diverse metriche delle prestazioni. Android attualmente fornisce alcuni metodi di compressione supportati ( gz
, lz4
e none
) che presentano compromessi tra tempo di installazione, utilizzo dello spazio della mucca, tempo di avvio e tempo di unione delle istantanee. 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 possono variare a seconda del dispositivo. Tutti i pacchetti OTA generati di seguito sono con 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 )
1. OTA incrementale su Pixel 6 Pro
Tempo di installazione senza fase di postinstallazione | Uso dello spazio della mucca | Dopo il tempo di avvio OTA | Ora unione istantanee | |
---|---|---|---|---|
gz | 24 min | 1,18GB | 40,2 sec | 45,5 sec |
z4 | 13 min | 1,49GB | 37,4 sec | 37,1 sec |
nessuno | 13 min | 2,90GB | 37,6 sec | 40,7 sec |
2. OTA completo su Pixel 6 Pro
Tempo di installazione senza fase di postinstallazione | Uso dello spazio della mucca | Dopo il tempo di avvio OTA | Ora unione istantanee | |
---|---|---|---|---|
gz | 23 min | 2,79GB | 24,9 sec | 41,7 sec |
z4 | 12 min | 3,46GB | 20,0 sec | 25,3 sec |
nessuno | 10 minuti | 4,85GB | 20,6 sec | 29,8 sec |