Android 10 introduce User Data Checkpoint (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 in modo sicuro allo stato precedente. Sebbene
gli aggiornamenti A/B risolvano questo problema per l'avvio anticipato, il rollback
non è supportato quando viene modificata la partizione dei dati utente (montata su /data
).
UDC consente al dispositivo di ripristinare la partizione dei dati utente anche dopo essere stata modificata. La funzionalità UDC lo fa con 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, supportando anche gli aggiornamenti non A/B, nonché il supporto per il binding della versione della chiave e la prevenzione del rollback della chiave.
Impatto sugli utenti
La funzionalità UDC migliora l'esperienza di aggiornamento OTA per gli utenti, in quanto un numero inferiore di utenti perde i propri dati quando un aggiornamento OTA non va a buon fine. In questo modo è possibile ridurre il numero di chiamate di 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 ne esegue il backporting a tutti i kernel comuni supportati dai dispositivi con Android 10.
Per gli altri file system, UDC utilizza un dispositivo virtuale di mappatura dei dispositivi chiamato dm_bow
per la funzionalità di checkpoint. dm_bow
si trova tra il dispositivo e il file
system. Quando una partizione viene montata, viene emesso un comando TRIM che fa sì che il file system
emetta comandi TRIM su tutti i blocchi liberi. dm_bow
intercetta questi tagli e li utilizza
per configurare un elenco di blocchi senza costi. Le letture e le scritture vengono quindi inviate al dispositivo
senza modifiche, ma prima che sia consentita una scrittura, i dati necessari per un ripristino vengono
eseguiti il backup in un blocco libero.
Procedura di checkpoint
Quando viene montata una partizione con il flag checkpoint=fs/block
, Android chiama
restoreCheckpoint
sull'unità per consentire al dispositivo di ripristinare qualsiasi checkpoint
corrente. init
chiama quindi la funzione needsCheckpoint
per determinare se
il dispositivo si trova in uno stato bootloader A/B o ha impostato il conteggio dei tentativi
di aggiornamento. Se una delle due condizioni è vera, Android chiama createCheckpoint
per aggiungere flag di montaggio
o creare un dispositivo dm_bow
.
Dopo il montaggio della partizione, viene chiamato il codice del checkpoint per emettere i comandi di taglio.
La procedura di avvio continua normalmente. Alle ore LOCKED_BOOT_COMPLETE
, Android
chiama commitCheckpoint
per eseguire il commit del checkpoint corrente e l'aggiornamento
continua normalmente.
Gestire le chiavi KeyMint (in precedenza Keymaster)
Le chiavi KeyMint vengono utilizzate per la crittografia del dispositivo o per altri scopi. Per gestire queste chiavi, Android ritarda le chiamate di eliminazione delle chiavi finché il checkpoint non viene eseguito.
Monitorare la salute
Un daemon di integrità verifica che ci sia spazio su disco sufficiente per creare un
checkpoint. Il daemon di monitoraggio della salute si trova in
cp_healthDaemon
in Checkpoint.cpp
.
Il daemon di integrità ha i seguenti comportamenti configurabili:
ro.sys.cp_msleeptime
: Controlla la frequenza con cui il dispositivo verifica l'utilizzo del disco.ro.sys.cp_min_free_bytes
: Controlla il valore minimo che il daemon di controllo dell'integrità cerca.ro.sys.cp_commit_on_full
: Controlla se il daemon di integrità riavvia il dispositivo o esegue il commit del checkpoint e continua quando il disco è pieno.
API Checkpoint
Le API checkpoint vengono utilizzate dalla funzionalità UDC. Per altre API utilizzate da UDC, vedi
IVold.aidl
.
void startCheckpoint(int retry)
Crea un checkpoint.
Il framework chiama questo metodo quando è pronto per avviare un aggiornamento. Il
checkpoint viene creato prima che i file system con checkpoint, come userdata, vengano
montati in lettura/scrittura dopo il riavvio. Se il conteggio dei tentativi è positivo, l'API gestisce
i tentativi di monitoraggio e l'updater chiama needsRollback
per verificare se è necessario
un rollback dell'aggiornamento. Se il conteggio dei tentativi è -1
, l'API si affida al giudizio del bootloader A/B.
Questo metodo non viene chiamato quando viene eseguito un normale aggiornamento A/B.
void commitChanges()
Esegue il commit delle modifiche.
Il framework chiama questo metodo dopo il riavvio quando le modifiche sono pronte per essere
commitate. Viene chiamato prima che i dati (ad esempio immagini, video, SMS, ricezione
della ricezione dal server) vengano scritti in userdata e prima di BootComplete
.
Se non esiste un aggiornamento con checkpoint attivo, questo metodo non ha effetto.
abortChanges()
Forza il riavvio e il ripristino del checkpoint. Abbandona tutte le modifiche ai dati utente dal primo riavvio.
Il framework chiama questo metodo dopo il riavvio, ma prima di commitChanges
.
retry_counter
viene decrementato quando viene chiamato questo metodo. Vengono generate
le voci di log.
bool needsRollback()
Determina se è necessario un rollback.
Sui dispositivi non checkpoint, restituisce false
. Sui dispositivi di checkpoint, restituisce true
durante un avvio non di checkpoint.
Implementare UDC
Implementazione di riferimento
Per un esempio di come implementare UDC, consulta dm-bow.c. Per ulteriore documentazione sulla funzionalità, consulta dm-bow.txt.
Configura
In 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 taggato 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
Aggiungi partizione di metadati
UDC richiede una partizione di metadati per archiviare il conteggio dei tentativi non bootloader e le chiavi. Configura una partizione di metadati e montala in anticipo in /metadata
.
Nel file fstab.hardware
, assicurati che /metadata
sia taggato 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 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 maggiori informazioni, consulta Funzionalità di checkpoint in diversi file system.
Aggiungi il flag checkpoint=fs
alla sezione <fs_mgr_flags>
di fstab per il
dispositivo montato in /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 in /data
.
Controllare i log
Le voci di log vengono generate quando vengono chiamate le API Checkpoint.
Convalida
Per testare l'implementazione di UDC, esegui il set di test VTS VtsKernelCheckpointTest
.