Gli OEM e i fornitori di SoC che desiderano implementare gli aggiornamenti del sistema A/B devono assicurarsi che il loro bootloader implementi boot_control HAL e passi i parametri corretti al kernel.
Implementazione del controllo di avvio HAL
I bootloader compatibili con A/B devono implementare l'HAL boot_control
in hardware/libhardware/include/hardware/boot_control.h
. È possibile testare le implementazioni utilizzando l'utilità system/extras/bootctl
e system/extras/tests/bootloader/
.
È inoltre necessario implementare la macchina a stati mostrata di seguito:

Configurazione del kernel
Per implementare gli aggiornamenti del sistema A/B:
- Cherrypick la seguente serie di patch del kernel (se necessario):
- Se si esegue l'avvio senza ramdisk e si utilizza "avvia come ripristino", cherrypick android-review.googlesource.com/#/c/158491/ .
- Per configurare dm-verity senza ramdisk, cherrypick android-review.googlesource.com/#/q/status:merged+project:kernel/common+branch:android-3.18+topic:A_B_Changes_3.18 .
- Assicurati che gli argomenti della riga di comando del kernel contengano i seguenti argomenti aggiuntivi:
skip_initramfs rootwait ro init=/init root="/dev/dm-0 dm=system none ro,0 1 android-verity <public-key-id> <path-to-system-partition>"
<public-key-id>
è l'ID della chiave pubblica utilizzata per verificare la firma della tabella di verità (per i dettagli, vedere dm-verity ) . - Aggiungi il certificato .X509 contenente la chiave pubblica al portachiavi di sistema:
- Copia il certificato .X509 formattato nel formato
.der
nella radice della directory delkernel
. Se il certificato .X509 è formattato come file.pem
, utilizzare il comandoopenssl
seguente per convertire dal formato.pem
a.der
:openssl x509 -in <x509-pem-certificate> -outform der -out <x509-der-certificate>
- Crea
zImage
per includere il certificato come parte del keyring di sistema. Per verificare, controllare la voceprocfs
(richiede l'abilitazione diKEYS_CONFIG_DEBUG_PROC_KEYS
):angler:/# cat /proc/keys 1c8a217e I------ 1 perm 1f010000 0 0 asymmetri Android: 7e4333f9bba00adfe0ede979e28ed1920492b40f: X509.RSA 0492b40f [] 2d454e3e I------ 1 perm 1f030000 0 0 keyring .system_keyring: 1/4
L'inclusione riuscita del certificato .X509 indica la presenza della chiave pubblica nel keyring di sistema (l'evidenziazione indica l'ID della chiave pubblica). - Sostituisci lo spazio con
#
e passalo come<public-key-id>
nella riga di comando del kernel. Ad esempio, passaAndroid:#7e4333f9bba00adfe0ede979e28ed1920492b40f
al posto di<public-key-id>
.
- Copia il certificato .X509 formattato nel formato
Impostazione delle variabili di build
I bootloader compatibili con A/B devono soddisfare i seguenti criteri per le variabili di build:
Deve definire per il target A/B |
/device/google/marlin/+/android-7.1.0_r1/device-common.mk . È possibile facoltativamente eseguire il passaggio dex2oat post-installazione (ma pre-riavvio) descritto in Compilazione . |
---|---|
Fortemente raccomandato per target A/B |
|
Impossibile definire per la destinazione A/B |
|
Facoltativo per build di debug | PRODUCT_PACKAGES_DEBUG += update_engine_client |
Impostazione delle partizioni (slot)
I dispositivi A/B non necessitano di una partizione di ripristino o di una partizione cache perché Android non utilizza più queste partizioni. La partizione dati viene ora utilizzata per il pacchetto OTA scaricato e il codice dell'immagine di ripristino si trova nella partizione di avvio. Tutte le partizioni A/B-ed devono essere denominate come segue (gli slot sono sempre denominati a
, b
, ecc.): boot_a
, boot_b
, system_a
, system_b
, vendor_a
, vendor_b
.
cache
Per gli aggiornamenti non A/B, la partizione cache è stata utilizzata per archiviare i pacchetti OTA scaricati e per riporre temporaneamente i blocchi durante l'applicazione degli aggiornamenti. Non c'è mai stato un buon modo per ridimensionare la partizione della cache: quanto grande doveva dipendere dagli aggiornamenti che si desiderava applicare. Il caso peggiore sarebbe una partizione cache grande quanto l'immagine di sistema. Con gli aggiornamenti A/B non è necessario riporre i blocchi (perché si scrive sempre su una partizione che non è attualmente utilizzata) e con lo streaming A/B non è necessario scaricare l'intero pacchetto OTA prima di applicarlo.
Recupero
Il disco RAM di ripristino è ora contenuto nel file boot.img
. Quando si avvia il ripristino, il bootloader non può inserire l'opzione skip_initramfs
sulla riga di comando del kernel.
Per gli aggiornamenti non A/B, la partizione di ripristino contiene il codice utilizzato per applicare gli aggiornamenti. Gli aggiornamenti A/B vengono applicati da update_engine
in esecuzione nella normale immagine di sistema avviata. Esiste ancora una modalità di ripristino utilizzata per implementare il ripristino dei dati di fabbrica e il sideloading dei pacchetti di aggiornamento (da cui deriva il nome "ripristino"). Il codice e i dati per la modalità di ripristino sono archiviati nella normale partizione di avvio in un ramdisk; per avviare l'immagine di sistema, il bootloader dice al kernel di saltare il ramdisk (altrimenti il dispositivo si avvia in modalità di ripristino. La modalità di ripristino è piccola (e gran parte era già nella partizione di avvio), quindi la partizione di avvio non aumenta in misura.
Fstab
L'argomento slotselect
deve essere sulla riga per le partizioni A/B-ed. Per esempio:
<path-to-block-device>/vendor /vendor ext4 ro wait,verify=<path-to-block-device>/metadata,slotselect
Nessuna partizione deve essere denominata vendor
. Al contrario, la partizione vendor_a
o vendor_b
verrà selezionata e montata sul punto di montaggio /vendor
.
Argomenti dello slot del kernel
Il suffisso dello slot corrente deve essere passato tramite un nodo specifico dell'albero del dispositivo (DT) ( /firmware/android/slot_suffix
) o tramite la riga di comando del kernel androidboot.slot_suffix
o l'argomento bootconfig.
Per impostazione predefinita, l'avvio rapido esegue il flash dello slot corrente su un dispositivo A/B. Se il pacchetto di aggiornamento contiene anche immagini per l'altro slot non corrente, anche fastboot esegue il flashing di tali immagini. Le opzioni disponibili includono:
-
--slot SLOT
. Sovrascrivere il comportamento predefinito e richiedere all'avvio rapido di eseguire il flashing dello slot passato come argomento. -
--set-active [ SLOT ]
. Imposta lo slot come attivo. Se non viene specificato alcun argomento facoltativo, lo slot corrente viene impostato come attivo. -
fastboot --help
. Ottieni dettagli sui comandi.
Se il bootloader implementa l'avvio rapido, dovrebbe supportare il comando set_active <slot>
che imposta lo slot attivo corrente sullo slot specificato (questo deve anche cancellare il flag non avviabile per quello slot e reimpostare il conteggio dei tentativi sui valori predefiniti). Il bootloader dovrebbe supportare anche le seguenti variabili:
-
has-slot:<partition-base-name-without-suffix>
. Restituisce "yes" se la partizione specificata supporta gli slot, "no" in caso contrario. -
current-slot
. Restituisce il suffisso dello slot che verrà avviato dal prossimo. -
slot-count
. Restituisce un numero intero che rappresenta il numero di slot disponibili. Attualmente sono supportati due slot, quindi questo valore è2
. -
slot-successful:<slot-suffix>
. Restituisce "yes" se lo slot specificato è stato contrassegnato come avviato correttamente, "no" in caso contrario. -
slot-unbootable:<slot-suffix>
. Restituisce "yes" se lo slot specificato è contrassegnato come non avviabile, "no" in caso contrario. -
slot-retry-count
. Numero di tentativi rimanenti per tentare di avviare lo slot specificato.
Per visualizzare tutte le variabili, eseguire fastboot getvar all
.
Generazione di pacchetti OTA
Gli strumenti del pacchetto OTA seguono gli stessi comandi dei comandi per i dispositivi non A/B. Il file target_files.zip
deve essere generato definendo le variabili di build per la destinazione A/B. Gli strumenti dei pacchetti OTA identificano e generano automaticamente i pacchetti nel formato per l'aggiornamento A/B.
Esempi:
- Per generare un'OTA completa:
./build/make/tools/releasetools/ota_from_target_files \ dist_output/tardis-target_files.zip \ ota_update.zip
- Per generare un OTA incrementale:
./build/make/tools/releasetools/ota_from_target_files \ -i PREVIOUS-tardis-target_files.zip \ dist_output/tardis-target_files.zip \ incremental_ota_update.zip
Configurazione delle partizioni
update_engine
può aggiornare qualsiasi coppia di partizioni A/B definite nello stesso disco. Una coppia di partizioni ha un prefisso comune (come system
o boot
) e un suffisso per slot (come _a
). L'elenco delle partizioni per le quali il generatore di payload definisce un aggiornamento è configurato dalla variabile make AB_OTA_PARTITIONS
.
Ad esempio, se sono incluse una coppia di partizioni bootloader_a
e booloader_b
( _a
e _b
sono i suffissi degli slot), è possibile aggiornare queste partizioni specificando quanto segue nella configurazione del prodotto o della scheda:
AB_OTA_PARTITIONS := \ boot \ system \ bootloader
Tutte le partizioni aggiornate da update_engine
non devono essere modificate dal resto del sistema. Durante gli aggiornamenti incrementali o delta , i dati binari dello slot corrente vengono utilizzati per generare i dati nel nuovo slot. Qualsiasi modifica potrebbe causare la mancata verifica dei dati del nuovo slot durante il processo di aggiornamento e quindi l'aggiornamento non riuscito.
Configurazione post-installazione
È possibile configurare il passaggio successivo all'installazione in modo diverso per ciascuna partizione aggiornata utilizzando un set di coppie chiave-valore. Per eseguire un programma che si trova in /system/usr/bin/postinst
in una nuova immagine, specificare il percorso relativo alla radice del filesystem nella partizione di sistema.
Ad esempio, usr/bin/postinst
è system/usr/bin/postinst
(se non si utilizza un disco RAM). Specificare inoltre il tipo di filesystem da passare alla chiamata di sistema mount(2)
. Aggiungi quanto segue ai file .mk
del prodotto o del dispositivo (se applicabile):
AB_OTA_POSTINSTALL_CONFIG += \ RUN_POSTINSTALL_system=true \ POSTINSTALL_PATH_system=usr/bin/postinst \ FILESYSTEM_TYPE_system=ext4
Compilazione
Per motivi di sicurezza, system_server
non può utilizzare la compilazione JIT (just-in-time) . Ciò significa che devi compilare in anticipo almeno i file odex per system_server
e le sue dipendenze; tutto il resto è facoltativo.
Per compilare le app in background, è necessario aggiungere quanto segue alla configurazione del dispositivo del prodotto (nel device.mk del prodotto):
- Includere i componenti nativi nella build per garantire che lo script di compilazione ei binari siano compilati e inclusi nell'immagine di sistema.
# A/B OTA dexopt package PRODUCT_PACKAGES += otapreopt_script
- Collega lo script di compilazione a
update_engine
in modo che venga eseguito come passaggio successivo all'installazione.# A/B OTA dexopt update_engine hookup AB_OTA_POSTINSTALL_CONFIG += \ RUN_POSTINSTALL_system=true \ POSTINSTALL_PATH_system=system/bin/otapreopt_script \ FILESYSTEM_TYPE_system=ext4 \ POSTINSTALL_OPTIONAL_system=true
Per assistenza sull'installazione dei file preoptati nella seconda partizione di sistema inutilizzata, fare riferimento a Prima installazione di avvio dei file DEX_PREOPT .