Android 10 introduce il controllo dei dati utente (UDC), che consente ad Android di eseguire il rollback allo stato precedente quando un aggiornamento over-the-air (OTA) di Android non va a buon fine. Con UDC, se un aggiornamento OTA di Android non va a buon fine, il dispositivo può eseguire il rollback allo stato precedente in tutta sicurezza. Sebbene gli aggiornamenti A/B risolvano il problema per l'avvio anticipato, il rollback non è supportato quando viene modificata la partizione dei dati utente (montata su /data
).
La funzionalità UDC consente al dispositivo di ripristinare la partizione dei dati utente anche dopo la sua modifica. La funzionalità UDC lo realizza con le funzionalità di checkpoint per il file system, un'implementazione alternativa quando il file system non supporta i checkpoint, l'integrazione con il meccanismo A/B del bootloader e supporta anche gli aggiornamenti non A/B, nonché il supporto per il binding delle versioni delle chiavi e la prevenzione del rollback delle chiavi.
Impatto sugli utenti
La funzionalità UDC migliora l'esperienza di aggiornamento OTA per gli utenti, poiché meno utenti perdono i propri dati quando un aggiornamento OTA non va a buon fine. In questo modo, puoi ridurre il numero di chiamate all'assistenza da parte degli utenti che riscontrano problemi durante la procedura di aggiornamento. Tuttavia, quando un aggiornamento OTA non va a buon fine, gli utenti potrebbero notare che il dispositivo si riavvia più volte.
Come funziona
Funzionalità di checkpoint in diversi file system
Per il file system F2FS, UDC aggiunge la funzionalità di checkpoint al kernel Linux 4.20 upstream e la esegue il backport a tutti i kernel comuni supportati dai dispositivi con Android 10.
Per altri file system, UDC utilizza un dispositivo virtuale mapper dei dispositivi denominato dm_bow
per la funzionalità di checkpoint. dm_bow
si trova tra il dispositivo e il
sistema di file. Quando una partizione viene montata, viene emesso un comando di trim che fa sì che il file system emetta comandi di trim su tutti i blocchi liberi. dm_bow
intercetta questi tagli e li utilizza per impostare un elenco di blocchi gratuito. Le letture e le scritture vengono quindi inviate al dispositivo senza modifiche, ma prima che una scrittura sia consentita, viene eseguito il backup dei dati necessari per un ripristino in un blocco libero.
Processo di checkpoint
Quando viene montata una partizione con il flag checkpoint=fs/block
, Android chiamarestoreCheckpoint
sul disco per consentire al dispositivo di ripristinare qualsiasi checkpoint corrente. init
chiama quindi la funzione needsCheckpoint
per determinare se il dispositivo è in uno stato del bootloader A/B o ha impostato il conteggio dei tentativi di aggiornamento. Se una delle due condizioni è vera, Android chiama createCheckpoint
per aggiungere i flag di montaggio o per creare un dispositivo dm_bow
.
Dopo il montaggio della partizione, viene chiamato il codice del checkpoint per emettere i trim.
La procedura di avvio continua normalmente. Alle ore LOCKED_BOOT_COMPLETE
, Android
chiama commitCheckpoint
per eseguire il commit del checkpoint attuale e l'aggiornamento
continua normalmente.
Gestire le chiavi keymaster
Le chiavi Keymaster vengono utilizzate per la crittografia del dispositivo o per altri scopi. Per gestire queste chiavi, Android ritarda le chiamate di eliminazione delle chiavi fino al commit del checkpoint.
Monitorare lo stato di salute
Un daemon di stato verifica che sia disponibile spazio su disco sufficiente per creare un checkpoint. Il daemon di salute si trova in
cp_healthDaemon
in Checkpoint.cpp
.
Il daemon di stato presenta i seguenti comportamenti che possono essere configurati:
ro.sys.cp_msleeptime
: controlla la frequenza con cui il dispositivo controlla l'utilizzo del disco.ro.sys.cp_min_free_bytes
: controlla il valore minimo cercato dal daemon di salute.ro.sys.cp_commit_on_full
: controlla se il daemon di salute riavvia il dispositivo o esegue il commit del checkpoint e continua quando il disco è pieno.
API di controllo
Le API Checkpoint vengono utilizzate dalla funzionalità UDC. Per altre API utilizzate da UDC, consulta
IVold.aidl
.
void startCheckpoint(int riprova)
Crea un checkpoint.
Il framework chiama questo metodo quando è pronto per avviare un aggiornamento. Il
check point viene creato prima che i file system sottoposti a controllo, come userdata, vengano
montati in lettura/scrittura dopo il riavvio. Se il numero di nuovi tentativi è positivo, l'API gestisce i nuovi tentativi di monitoraggio e il programma di aggiornamento chiama needsRollback
per verificare se è necessario un rollback dell'aggiornamento. Se il conteggio dei tentativi di ripetizione è -1
, l'API rimanda al giudizio del bootloader A/B.
Questo metodo non viene chiamato durante un normale aggiornamento A/B.
void commitChanges()
Apporta il commit delle modifiche.
Il framework chiama questo metodo dopo il riavvio quando le modifiche sono pronte per essere committate. Viene chiamato prima che i dati (ad esempio immagini, video, SMS, conferma di ricezione del server) vengano scritti in userdata e prima di BootComplete
.
Se non esiste un aggiornamento con checkpoint attivo, questo metodo non ha alcun effetto.
abortChanges()
Forza il riavvio e torna al checkpoint. Abbandona tutte le modifiche ai dati utente dall'ultimo riavvio.
Il framework chiama questo metodo dopo il riavvio, ma prima di commitChanges
.
retry_counter
viene diminuito quando viene chiamato questo metodo. Vengono generate
le voci di log.
bool needsRollback()
Determina se è necessario un rollback.
Sui dispositivi senza checkpoint, restituisce false
. Sui dispositivi con checkpoint, restituisce true
durante un avvio senza checkpoint.
Implementa UDC
Implementazione dei riferimenti
Per un esempio di come implementare i codici UDC, consulta dm-bow.c. Per ulteriore documentazione sulla funzionalità, consulta dm-bow.txt.
Configura
Nel file on fs
nel file init.hardware.rc
, assicurati di avere:
mount_all /vendor/etc/fstab.${ro.boot.hardware.platform} --early
In on late-fs
nel file init.hardware.rc
, assicurati di avere:
mount_all /vendor/etc/fstab.${ro.boot.hardware.platform} --late
Nel file fstab.hardware
, assicurati che /data
sia contrassegnato come latemount
.
/dev/block/bootdevice/by-name/userdata /data f2fs noatime,nosuid,nodev,discard,reserve_root=32768,resgid=1065,fsync_mode=nobarrier latemount,wait,check,fileencryption=ice,keydirectory=/metadata/vold/metadata_encryption,quota,formattable,sysfs_path=/sys/devices/platform/soc/1d84000.ufshc,reservedsize=128M,checkpoint=fs
Aggiungere una partizione di metadati
UDC richiede una partizione dei metadati per memorizzare le chiavi e il conteggio dei tentativi di non avvio del bootloader. Configura una partizione dei metadati e montala in anteprima in /metadata
.
Nel file fstab.hardware
, assicurati che /metadata
sia contrassegnato come earlymount
o first_stage_mount
.
/dev/block/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard,sync wait,formattable,first_stage_mount
Inizializza la partizione con tutti gli zeri.
Aggiungi le seguenti righe a BoardConfig.mk
:
BOARD_USES_METADATA_PARTITION := true BOARD_ROOT_EXTRA_FOLDERS := existing_folders metadata
Aggiornare i sistemi
Sistemi F2FS
Per i sistemi che utilizzano F2FS per formattare i dati, assicurati che la tua versione di F2FS supporti i checkpoint. Per ulteriori informazioni, consulta la funzionalità di checkpoint in diversi sistemi di file.
Aggiungi il flag checkpoint=fs
alla sezione <fs_mgr_flags>
di fstab per il
dispositivo montato su /data
.
Sistemi non F2FS
Per i sistemi non F2FS, dm-bow
deve essere abilitato nella configurazione del kernel.
Aggiungi il flag checkpoint=block
alla sezione <fs_mgr_flags>
di fstab per il
dispositivo montato su /data
.
Controllare i log
Le voci di log vengono generate quando vengono chiamate le API Checkpoint.
Convalida
Per testare l'implementazione del UDC, esegui il set VtsKernelCheckpointTest
di test VTS.