Domande frequenti

Google ha utilizzato gli aggiornamenti OTA A/B su alcuni dispositivi?

Sì. Il nome commerciale per gli aggiornamenti A/B è aggiornamenti continui. Gli smartphone Pixel e Pixel XL di ottobre 2016 sono stati spediti con A/B e tutti i Chromebook utilizzano la stessa update_engine implementazione di A/B. L'implementazione del codice della piattaforma necessaria è pubblica in Android 7.1 e versioni successive.

Perché gli aggiornamenti OTA A/B sono migliori?

Gli aggiornamenti OTA A/B offrono una migliore esperienza utente durante l'esecuzione degli aggiornamenti. Le misurazioni degli aggiornamenti di sicurezza mensili dimostrano che questa funzionalità ha già avuto successo: a maggio 2017, il 95% dei proprietari di Pixel utilizzava l'ultimo aggiornamento di sicurezza dopo un mese, rispetto all'87% degli utenti Nexus, e gli utenti Pixel eseguono l'aggiornamento prima degli utenti Nexus. Gli errori di aggiornamento dei blocchi durante un aggiornamento OTA non comportano più un dispositivo che non si avvia; finché la nuova immagine di sistema non viene avviata correttamente, Android mantiene la possibilità di eseguire il rollback all'immagine di sistema funzionante precedente.

Che cos'è system_other?

Le applicazioni vengono archiviate in file .apk, che sono in realtà archivi ZIP. Ogni file .apk contiene uno o più file .dex contenenti bytecode Dalvik portatile. Un file .odex (file .dex ottimizzato ) si trova separatamente dal file .apk e può contenere codice macchina specifico per il dispositivo. Se è disponibile un file .odex, Android può eseguire le applicazioni a velocità di compilazione AOT (Ahead-Of-Time) senza dover attendere la compilazione del codice ogni volta che l'applicazione viene avviata. Un file .odex non è strettamente necessario: Android può effettivamente eseguire il codice .dex direttamente tramite interpretazione o compilazione JIT (Just-In-Time), ma un file .odex offre la migliore combinazione di velocità di avvio e velocità di runtime se è disponibile spazio.

Esempio: per il file installed-files.txt di un Nexus 6P con Android 7.1 con una dimensione totale dell'immagine di sistema di 2628 MiB (2755792836 byte), la suddivisione dei maggiori contributori alla dimensione complessiva dell'immagine di sistema per tipo di file è la seguente:

.odex 1391770312 byte 50,5%
.apk 846878259 byte 30,7%
.so (codice C/C++ nativo) 202162479 byte 7,3%
File .oat/immagini .art 163892188 byte 5,9%
Caratteri 38952361 byte 1,4%
Dati delle impostazioni internazionali ICU 27468687 byte 0,9%

Questi dati sono simili anche per altri dispositivi, quindi sui dispositivi Nexus/Pixel i file .odex occupano circa la metà della partizione di sistema. Ciò significava che potevamo continuare a utilizzare ext4, ma scrivere i file .odex nella partizione B in fabbrica e poi copiarli in /data al primo avvio. Lo spazio di archiviazione effettivo utilizzato con ext4 A/B è identico a SquashFS A/B, perché se avessimo utilizzato SquashFS avremmo spedito i file .odex preottimizzati su system_a anziché su system_b.

La copia dei file .odex in /data non comporta la perdita dello spazio salvato in /system in /data?

Non esattamente. Su Pixel, la maggior parte dello spazio occupato dai file .odex è destinata alle app, che in genere si trovano in /data. Queste app ricevono gli aggiornamenti di Google Play, quindi i file .apk e .odex nell'immagine di sistema non vengono utilizzati per la maggior parte della durata del dispositivo. Questi file possono essere esclusi completamente e sostituiti da piccoli file .odex basati sul profilo quando l'utente utilizza effettivamente ogni app (quindi non è necessario spazio per le app che l'utente non utilizza). Per maggiori dettagli, consulta il talk di Google I/O 2016 The Evolution of Art.

Il confronto è difficile per alcuni motivi principali:

  • I file .odex delle app aggiornate da Google Play si trovano sempre in /data non appena ricevono il primo aggiornamento.
  • Le app che l'utente non esegue non hanno bisogno di un file .odex.
  • La compilazione basata sul profilo genera file .odex più piccoli rispetto alla compilazione AOT (Ahead-Of-Time) (perché la prima ottimizza solo il codice critico per il rendimento).

Per maggiori dettagli sulle opzioni di ottimizzazione disponibili per gli OEM, vedi Configurare ART.

Non ci sono due copie dei file .odex in /data?

È un po' più complicato ... Dopo aver scritto la nuova immagine di sistema, viene eseguita la nuova versione di dex2oat sui nuovi file .dex per generare i nuovi file .odex. Questa operazione viene eseguita mentre il vecchio sistema è ancora in esecuzione, quindi i file .odex vecchi e nuovi si trovano contemporaneamente in /data.

Il codice in OtaDexoptService (frameworks/base/+/android17-release/services/core/java/com/android/server/pm/OtaDexoptService.java) chiama getAvailableSpace prima di ottimizzare ogni pacchetto per evitare di riempire eccessivamente /data. Tieni presente che available qui è ancora conservativo: è la quantità di spazio rimanente prima di raggiungere la soglia di spazio insufficiente del sistema (misurata sia come percentuale sia come numero di byte). Quindi, se /data è pieno, non ci saranno due copie di ogni file .odex. Lo stesso codice ha anche una soglia BULK_DELETE_THRESHOLD: se il dispositivo si avvicina così tanto al riempimento dello spazio disponibile (come appena descritto), vengono rimossi i file .odex appartenenti alle app non utilizzate. Questo è un altro caso in cui non sono presenti due copie di ogni file .odex.

Nel caso peggiore in cui /data sia completamente pieno, l'aggiornamento attende che il dispositivo venga riavviato nel nuovo sistema e non abbia più bisogno dei file .odex del vecchio sistema. Questa operazione viene gestita da PackageManager (frameworks/base/+/android17-release/services/core/java/com/android/server/pm/PackageManagerService.java#7215). Dopo che il nuovo sistema è stato avviato correttamente, installd (frameworks/native/+/android17-release/cmds/installd/dexopt.cpp#2422) può rimuovere i file .odex utilizzati dal vecchio sistema, riportando il dispositivo allo stato stazionario in cui è presente una sola copia.

Pertanto, anche se è possibile che /data contenga due copie di tutti i file .odex, (a) questa situazione è temporanea e (b) si verifica solo se avevi comunque molto spazio libero in /data anyway. Tranne durante un aggiornamento, è presente una sola copia. Inoltre, nell'ambito delle funzionalità di robustezza generale di ART, non riempirà mai /data con file .odex comunque (perché sarebbe un problema anche su un sistema non A/B).

Tutte queste operazioni di scrittura/copia non aumentano l'usura della memoria flash?

Viene riscritta solo una piccola parte della memoria flash: un aggiornamento completo del sistema Pixel scrive circa 2,3 GiB. (Anche le app vengono ricompilate, ma questo vale anche per i sistemi non A/B.) Tradizionalmente, gli aggiornamenti OTA completi basati su blocchi scrivevano una quantità simile di dati, quindi i tassi di usura della memoria flash dovrebbero essere simili.

Il flashing di due partizioni di sistema aumenta il tempo di flashing in fabbrica?

No. La dimensione dell'immagine di sistema di Pixel non è aumentata (lo spazio è stato semplicemente suddiviso in due partizioni).

La conservazione dei file .odex in B non rallenta il riavvio dopo il ripristino dei dati di fabbrica?

Sì. Se hai effettivamente utilizzato un dispositivo, hai eseguito un aggiornamento OTA e hai eseguito un ripristino dei dati di fabbrica, il primo riavvio sarà più lento di quanto non sarebbe altrimenti (1 minuto e 40 secondi rispetto a 40 secondi su un Pixel XL) perché i file .odex saranno stati persi da B dopo il primo aggiornamento OTA e quindi non possono essere copiati in /data. Questo è il compromesso.

Il ripristino dei dati di fabbrica dovrebbe essere un'operazione rara rispetto all'avvio normale, quindi il tempo impiegato è meno importante. (Questo non influisce sugli utenti o sui recensori che ricevono il dispositivo dalla fabbrica, perché in questo caso la partizione B è disponibile.) L'utilizzo del compilatore JIT significa che non è necessario ricompilare tutto, quindi non è così grave come potresti pensare. È anche possibile contrassegnare le app come richiedenti la compilazione AOT (Ahead-Of-Time) utilizzando coreApp="true" nel file manifest: (frameworks/base/+/android17-release/packages/SystemUI/AndroidManifest.xml#23). Questa opzione viene attualmente utilizzata da system_server perché non è consentito JIT per motivi di sicurezza.

La conservazione dei file .odex in /data anziché in /system non rallenta il riavvio dopo un aggiornamento OTA?

No. Come spiegato sopra, il nuovo dex2oat viene eseguito mentre la vecchia immagine di sistema è ancora in esecuzione per generare i file necessari al nuovo sistema. L'aggiornamento non è considerato disponibile finché non viene completata questa operazione.

Possiamo (dobbiamo) spedire un dispositivo A/B da 32 GiB? Da 16 GiB? Da 8 GiB?

32 GiB funziona bene, come dimostrato su Pixel, e 320 MiB su 16 GiB significa una riduzione del 2%. Allo stesso modo, 320 MiB su 8 GiB significa una riduzione del 4%. Ovviamente A/B non sarebbe la scelta consigliata sui dispositivi con 4 GiB, poiché l'overhead di 320 MiB è quasi il 10% dello spazio totale disponibile.

AVB2.0 richiede gli aggiornamenti OTA A/B?

No. L'avvio verificato di Android ha sempre richiesto aggiornamenti basati su blocchi, ma non necessariamente aggiornamenti A/B.

Gli aggiornamenti OTA A/B richiedono AVB2.0?

No.

Gli aggiornamenti OTA A/B interrompono la protezione rollback di AVB2.0?

No. C'è un po' di confusione perché se un sistema A/B non riesce ad avviarsi nella nuova immagine di sistema verrà eseguito automaticamente il rollback all'immagine di sistema "precedente" (dopo un certo numero di tentativi determinati dal bootloader) . Il punto chiave è che "precedente" nel senso di A/B è in realtà ancora l'immagine di sistema "corrente". Non appena il dispositivo avvia correttamente una nuova immagine, la protezione rollback entra in vigore e garantisce che non sia possibile tornare indietro. Tuttavia, finché non hai avviato correttamente la nuova immagine, la protezione rollback non la considera l'immagine di sistema corrente.

Se installi un aggiornamento mentre il sistema è in esecuzione, non è lento?

Con gli aggiornamenti non A/B, l'obiettivo è installare l'aggiornamento il più rapidamente possibile perché l'utente è in attesa e non può utilizzare il dispositivo durante l'applicazione dell'aggiornamento. Con gli aggiornamenti A/B, è vero il contrario: poiché l'utente sta ancora utilizzando il dispositivo, l'obiettivo è ridurre al minimo l'impatto, quindi l'aggiornamento è volutamente lento. Tramite la logica nel client di aggiornamento del sistema Java (che per Google è GmsCore, il pacchetto principale fornito da GMS), Android tenta anche di scegliere un momento in cui gli utenti non utilizzano affatto i propri dispositivi. La piattaforma supporta la sospensione/ripresa dell'aggiornamento e il client può utilizzarla per sospendere l'aggiornamento se l'utente inizia a utilizzare il dispositivo e riprenderla quando il dispositivo è di nuovo inattivo.

Durante l'esecuzione di un aggiornamento OTA, sono presenti due fasi, indicate chiaramente nell'interfaccia utente come Passaggio 1 di 2 e Passaggio 2 di 2 sotto la barra di avanzamento. Il passaggio 1 corrisponde alla scrittura dei blocchi di dati, mentre il passaggio 2 è la precompilazione dei file .dex. Queste due fasi sono molto diverse in termini di impatto sul rendimento. La prima fase è semplice I/O. Richiede poche risorse (RAM, CPU, I/O) perché si tratta solo di copiare lentamente i blocchi.

La seconda fase esegue dex2oat per precompilare la nuova immagine di sistema. Ovviamente, i requisiti di questa fase non sono così chiari perché compila le app effettive. Inoltre, la compilazione di un'app grande e complessa richiede ovviamente molto più lavoro rispetto a un'app piccola e semplice, mentre nella fase 1 non esistono blocchi di disco più grandi o più complessi di altri.

La procedura è simile a quella utilizzata da Google Play per installare un aggiornamento dell'app in background prima di mostrare la notifica 5 app aggiornate, come avviene da anni.

Cosa succede se un utente è effettivamente in attesa dell'aggiornamento?

L'implementazione attuale in GmsCore non distingue tra aggiornamenti in background e aggiornamenti avviati dall'utente, ma potrebbe farlo in futuro. Nel caso in cui l'utente abbia chiesto esplicitamente l'installazione dell'aggiornamento o stia guardando la schermata di avanzamento dell'aggiornamento, daremo la priorità al lavoro di aggiornamento presupponendo che stia aspettando attivamente il completamento.

Cosa succede se non è possibile applicare un aggiornamento?

Con gli aggiornamenti non A/B, se non era possibile applicare un aggiornamento, l'utente in genere si ritrovava con un dispositivo inutilizzabile. L'unica eccezione si verificava se l'errore si verificava prima dell'avvio di un'applicazione (ad esempio perché il pacchetto non è stato verificato). Con gli aggiornamenti A/B, un errore durante l'applicazione di un aggiornamento non influisce sul sistema attualmente in esecuzione. L'aggiornamento può essere ritentato in un secondo momento.