Google ha utilizzato gli aggiornamenti OTA A/B su qualche dispositivo?
Sì. Il nome di marketing per gli aggiornamenti A/B è aggiornamenti senza interruzioni. 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 necessario è pubblica in Android 7.1 e
versioni successive.
Perché le OTA A/B sono migliori?
Gli aggiornamenti OTA A/B offrono una migliore esperienza utente durante l'aggiornamento. Le misurazioni degli aggiornamenti di sicurezza mensili dimostrano che questa funzionalità ha già avuto successo: a maggio 2017, il 95% dei proprietari di Pixel utilizza 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ù l'impossibilità di avviare il dispositivo. Fino all'avvio corretto della nuova immagine di sistema, Android mantiene la possibilità di eseguire il rollback all'immagine di sistema funzionante precedente.
Che cos'è system_other?
Le applicazioni sono 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 (ottimizzato .dex) 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 ahead-of-time senza dover attendere la compilazione del codice ogni volta che viene avviata l'applicazione. Un file .odex non è strettamente necessario: Android può eseguire il codice .dex direttamente tramite interpretazione o compilazione Just-In-Time (JIT), ma un file .odex offre la migliore combinazione di velocità di avvio e velocità di runtime se lo spazio è disponibile.
Esempio: per il file installed-files.txt di Nexus 6P con Android 7.1 e una dimensione totale dell'immagine di sistema di 2628 MiB (2755792836 byte), la suddivisione dei principali 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% |
icu locale data | 27468687 byte | 0,9% |
Questi valori 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 su /data?
Non esattamente. Su Pixel, la maggior parte dello spazio occupato dai file .odex è destinato alle app, che in genere
si trovano su /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 del ciclo di vita 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 l'intervento di Google
I/O 2016 The Evolution of Art.
Il confronto è difficile per alcuni motivi chiave:
-
Le app aggiornate da Google Play hanno sempre avuto i file .odex su
/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 ahead-of-time (perché la prima ottimizza solo il codice fondamentale per le prestazioni).
Per informazioni dettagliate sulle opzioni di ottimizzazione disponibili per gli OEM, vedi Configurazione di 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. Ciò
si verifica mentre il vecchio sistema è ancora in esecuzione, quindi i file .odex vecchi e nuovi si trovano entrambi su
/data
contemporaneamente.
Il codice in OtaDexoptService (frameworks/base/+/android16-release/services/core/java/com/android/server/pm/OtaDexoptService.java
) chiama getAvailableSpace
prima di ottimizzare ogni pacchetto per evitare il riempimento eccessivo
/data
. Tieni presente che lo spazio disponibile qui è ancora conservativo: è la quantità
di spazio rimasto prima di raggiungere la normale soglia di spazio insufficiente del sistema (misurata sia come
percentuale che come conteggio 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
al riempimento dello spazio disponibile (come appena descritto), vengono rimossi i file .odex appartenenti alle app
che non vengono utilizzate. Questo è un altro caso senza due copie di ogni file .odex.
Nel caso peggiore in cui /data
sia completamente pieno, l'aggiornamento attende che il
dispositivo sia stato riavviato nel nuovo sistema e non abbia più bisogno dei file .odex del vecchio sistema. PackageManager gestisce questa operazione: (frameworks/base/+/android16-release/services/core/java/com/android/server/pm/PackageManagerService.java#7215
). Dopo l'avvio corretto del nuovo sistema, installd
(frameworks/native/+/android16-release/cmds/installd/dexopt.cpp#2422
) può rimuovere i file .odex utilizzati dal vecchio sistema, riportando il dispositivo allo stato stabile 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 su
/data
. Tranne durante un aggiornamento, esiste una sola copia. Inoltre, nell'ambito delle funzionalità di robustezza generale di ART, non riempirà mai /data
con file .odex (perché sarebbe un problema anche su un sistema non A/B).
Tutta questa scrittura/copia non aumenta 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 le versioni non A/B. Tradizionalmente, le OTA complete basate su blocchi scrivevano una quantità simile di dati, quindi i tassi di usura del flash dovrebbero essere simili.
Il flashing di due partizioni di sistema aumenta il tempo di flashing di fabbrica?
No. Le dimensioni dell'immagine di sistema di Pixel non sono aumentate (lo spazio è stato semplicemente suddiviso in due partizioni).
Il mantenimento dei file .odex su 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 ripristinato i dati di fabbrica, il
primo riavvio sarà più lento del normale (1 minuto e 40 secondi anziché 40 secondi su Pixel XL) perché
i file .odex saranno stati persi da B dopo il primo aggiornamento OTA e quindi non potranno essere copiati in
/data
. Questo è il compromesso.
Il ripristino dei dati di fabbrica dovrebbe essere un'operazione rara rispetto all'avvio regolare, quindi il tempo impiegato
è meno importante. Ciò non influisce sugli utenti o sui revisori che ricevono il dispositivo dalla fabbrica, perché in questo caso la partizione B è disponibile. L'utilizzo del compilatore JIT significa che non dobbiamo ricompilare tutto, quindi non è così grave come potresti pensare. È anche
possibile contrassegnare le app come richiedenti la compilazione AOT utilizzando
coreApp="true"
nel manifest: (frameworks/base/+/android16-release/packages/SystemUI/AndroidManifest.xml#23
). Questa opzione viene attualmente utilizzata da system_server
perché non è consentito JIT per
motivi di sicurezza.
Il mantenimento 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 completato.
Possiamo (dobbiamo) spedire un dispositivo A/B da 32 GB? 16GiB? 8GiB?
32 GB funzionano bene, come dimostrato su Pixel, e 320 MB su 16 GB significano una riduzione del 2%. Analogamente, 320 MiB su 8 GiB rappresentano una riduzione del 4%. Ovviamente A/B non sarebbe la scelta consigliata su dispositivi con 4 GiB, in quanto l'overhead di 320 MiB è quasi il 10% dello spazio totale disponibile.
AVB2.0 richiede OTA A/B?
Gli aggiornamenti OTA A/B richiedono AVB2.0?
di serie
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, dopo un certo numero di tentativi determinati dal bootloader, tornerà automaticamente all'immagine di sistema "precedente". Il punto chiave qui è che "precedente" nel test A/B è in realtà ancora l'immagine di sistema "attuale". Non appena il dispositivo avvia correttamente una nuova immagine, viene attivata la protezione dal rollback, che impedisce di tornare indietro. Tuttavia, finché non avrai eseguito l'avvio della nuova immagine, la protezione dal rollback non la considererà l'immagine di sistema attuale.
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, invece, l'obiettivo è avere il minor impatto possibile, poiché l'utente continua a utilizzare il dispositivo, 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/la ripresa dell'aggiornamento e il client può utilizzarla per sospendere l'aggiornamento se l'utente inizia a utilizzare il dispositivo e riprenderlo quando il dispositivo è di nuovo inattivo.
L'OTA prevede due fasi, chiaramente indicate nella UI 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 alla precompilazione dei file .dex. Queste due fasi sono molto diverse in termini di impatto sulle prestazioni. La prima fase è semplice I/O. Questa operazione richiede poche risorse (RAM, CPU, I/O) perché si limita a copiare lentamente i blocchi.
La seconda fase esegue dex2oat per precompilare la nuova immagine di sistema. Ovviamente, i requisiti sono meno chiari perché compila app reali. Ovviamente, la compilazione di un'app grande e complessa richiede molto più lavoro rispetto a un'app piccola e semplice, mentre nella fase 1 non ci sono blocchi del disco più grandi o più complessi di altri.
La procedura è simile a quella che Google Play esegue quando installa un aggiornamento dell'app in background prima di mostrare la notifica 5 app aggiornate, come avviene da anni.
Cosa succede se un utente sta effettivamente aspettando l'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 che termini.
Che cosa succede se non viene applicato un aggiornamento?
Con gli aggiornamenti non A/B, se un aggiornamento non veniva applicato, l'utente si ritrovava in genere con un dispositivo inutilizzabile. L'unica eccezione si verifica se l'errore si è verificato prima dell'avvio di un'applicazione (ad esempio perché la verifica del pacchetto non è riuscita). Con gli aggiornamenti A/B, un errore di applicazione di un aggiornamento non influisce sul sistema attualmente in esecuzione. L'aggiornamento può essere semplicemente riprovato in un secondo momento.