OEMs und SoC-Anbieter, die A/B-Systemupdates implementieren möchten, müssen dafür sorgen, dass ihr Bootloader die boot_control-HAL implementiert und die richtigen Parameter an den Kernel übergibt.
Boot-Control-HAL implementieren
A/B-fähige Bootloader müssen die boot_control
-HAL unter hardware/libhardware/include/hardware/boot_control.h
implementieren. Sie können Implementierungen mit dem Dienstprogramm system/extras/bootctl
und system/extras/tests/bootloader/
testen.
Außerdem müssen Sie die unten gezeigte Statusmaschine implementieren:

Kernel einrichten
So implementieren Sie A/B-Systemupdates:
-
Wählen Sie die folgenden Kernel-Patch-Serien aus (falls erforderlich):
- Wenn Sie ohne Ramdisk booten und „boot as recovery“ verwenden, führen Sie Cherrypick für android-review.googlesource.com/#/c/158491/ aus.
- Wenn Sie dm-verity ohne Ramdisk einrichten möchten, wählen Sie android-review.googlesource.com/#/q/status:merged+project:kernel/common+branch:android-3.18+topic:A_B_Changes_3.18 aus.
-
Die Kernel-Befehlszeilenargumente müssen die folgenden zusätzlichen Argumente enthalten:
... wobei der Wertskip_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>
die ID des öffentlichen Schlüssels ist, der zum Überprüfen der Signatur der Verity-Tabelle verwendet wird (weitere Informationen finden Sie unter dm-verity). -
Fügen Sie dem System-Keyring das .X509-Zertifikat mit dem öffentlichen Schlüssel hinzu:
-
Kopieren Sie das im
.der
-Format formatierte .X509-Zertifikat in das Stammverzeichnis deskernel
-Verzeichnisses. Wenn das X .509-Zertifikat als.pem
-Datei formatiert ist, verwenden Sie den folgendenopenssl
-Befehl, um es von.pem
in das.der
-Format zu konvertieren:openssl x509 -in <x509-pem-certificate> -outform der -out <x509-der-certificate>
-
Erstellen Sie das
zImage
, um das Zertifikat in den Systemschlüsselbund aufzunehmen. Prüfen Sie den Eintragprocfs
,um dies zu bestätigen (KEYS_CONFIG_DEBUG_PROC_KEYS
muss aktiviert sein): Wenn das X .509-Zertifikat erfolgreich eingebunden wurde, ist der öffentliche Schlüssel im Systemschlüsselbund vorhanden (die ID des öffentlichen Schlüssels ist hervorgehoben).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
-
Ersetzen Sie das Leerzeichen durch
#
und übergeben Sie es als<public-key-id>
in der Kernel-Befehlszeile. Übergeben Sie beispielsweiseAndroid:#7e4333f9bba00adfe0ede979e28ed1920492b40f
anstelle von<public-key-id>
.
-
Kopieren Sie das im
Build-Variablen festlegen
A/B-fähige Bootloader müssen die folgenden Build-Variablenkriterien erfüllen:
Muss für A/B-Ziel definiert werden |
/device/google/marlin/+/android-7.1.0_r1/device-common.mk . Optional können Sie den in Kompilieren beschriebenen dex2oat-Schritt nach der Installation, aber vor dem Neustart ausführen.
|
---|---|
Dringend für A/B-Zielvorhaben empfohlen |
|
Kann nicht für A/B-Zielvorhaben definiert werden |
|
Optional für Debug-Builds | PRODUCT_PACKAGES_DEBUG += update_engine_client |
Partitionen (Slots) festlegen
A/B-Geräte benötigen keine Wiederherstellungs- oder Cache-Partition, da Android diese Partitionen nicht mehr verwendet. Die Datenpartition wird jetzt für das heruntergeladene OTA-Paket verwendet und der Code des Recovery-Images befindet sich auf der Boot-Partition. Alle Partitionen, die A/B-getestet werden, sollten so benannt werden (Slots werden immer als a
, b
usw. bezeichnet): boot_a
,
boot_b
, system_a
, system_b
, vendor_a
,
vendor_b
.
Cache
Bei Nicht-A/B-Updates wurde die Cache-Partition verwendet, um heruntergeladene OTA-Pakete zu speichern und Blöcke während der Anwendung von Updates vorübergehend zu speichern. Es gab nie eine gute Möglichkeit, die Cache-Partition zu dimensionieren. Wie groß sie sein musste, hing davon ab, welche Updates angewendet werden sollten. Im schlimmsten Fall ist die Cache-Partition so groß wie das System-Image. Bei A/B-Updates müssen keine Blöcke zwischengespeichert werden, da immer in eine Partition geschrieben wird, die derzeit nicht verwendet wird. Bei Streaming-A/B-Updates muss das gesamte OTA-Paket nicht heruntergeladen werden, bevor es angewendet wird.
Recovery
Die Recovery-RAM-Disk ist jetzt in der Datei boot.img
enthalten. Beim Aufrufen des Wiederherstellungsmodus darf der Bootloader die Option skip_initramfs
nicht in die Kernel-Befehlszeile einfügen.
Bei Updates, die keine A/B-Updates sind, enthält die Wiederherstellungspartition den Code, der zum Anwenden von Updates verwendet wird. A/B-Updates werden von update_engine
angewendet, das im regulären gebooteten System-Image ausgeführt wird.
Es gibt weiterhin einen Wiederherstellungsmodus, der zum Zurücksetzen auf die Werkseinstellungen und zum Sideloading von Updatepaketen verwendet wird. Daher stammt auch der Name „Wiederherstellung“. Der Code und die Daten für den Wiederherstellungsmodus werden in der regulären Bootpartition in einer RAM-Disk gespeichert. Damit das System-Image gebootet wird, weist der Bootloader den Kernel an, die RAM-Disk zu überspringen. Andernfalls wird das Gerät im Wiederherstellungsmodus gebootet. Der Wiederherstellungsmodus ist klein (und ein Großteil davon war bereits auf der Bootpartition), sodass die Bootpartition nicht größer wird.
Fstab
Das slotselect
-Argument muss für die A/B-getesteten Partitionen in der Zeile stehen. Beispiel:
<path-to-block-device>/vendor /vendor ext4 ro wait,verify=<path-to-block-device>/metadata,slotselect
Keine Partition sollte den Namen vendor
haben. Stattdessen wird die Partition vendor_a
oder vendor_b
ausgewählt und am Mount-Point /vendor
gemountet.
Kernel-Slot-Argumente
Das aktuelle Slot-Suffix sollte entweder über einen bestimmten Gerätebaumknoten (/firmware/android/slot_suffix
) oder über das Kernel-Befehlszeilen- oder Bootconfig-Argument androidboot.slot_suffix
übergeben werden.
Standardmäßig wird mit Fastboot der aktuelle Slot auf einem A/B-Gerät geflasht. Wenn das Updatepaket auch Bilder für den anderen, nicht aktuellen Slot enthält, werden diese Bilder ebenfalls mit Fastboot geflasht. Folgende Optionen sind verfügbar:
-
--slot SLOT
. Überschreibt das Standardverhalten und fordert Fastboot auf, den Slot zu flashen, der als Argument übergeben wird. -
--set-active [SLOT]
. Legen Sie den Slot als aktiv fest. Wenn kein optionales Argument angegeben ist, wird der aktuelle Slot als aktiv festgelegt. fastboot --help
. Details zu Befehlen abrufen.
Wenn der Bootloader Fastboot implementiert, sollte er den Befehl set_active <slot>
unterstützen, mit dem der aktuelle aktive Slot auf den angegebenen Slot festgelegt wird. Dadurch muss auch das Flag „unbootable“ für diesen Slot gelöscht und die Anzahl der Wiederholungsversuche auf die Standardwerte zurückgesetzt werden. Der Bootloader sollte auch die folgenden Variablen unterstützen:
-
has-slot:<partition-base-name-without-suffix>
. Gibt „yes“ zurück, falls die angegebene Partition Slots unterstützt, andernfalls „no“. current-slot
: Gibt das Slot-Suffix zurück, von dem als Nächstes gebootet wird.-
slot-count
. Gibt eine Ganzzahl zurück, die die Anzahl der verfügbaren Slots angibt. Derzeit werden zwei Slots unterstützt. Der Wert ist also2
. -
slot-successful:<slot-suffix>
. Gibt „yes“ zurück, wenn der angegebene Slot als erfolgreich gebootet markiert wurde, andernfalls „no“. -
slot-unbootable:<slot-suffix>
. Gibt „yes“ zurück, wenn der angegebene Slot als nicht bootfähig markiert ist, andernfalls „no“. -
slot-retry-count:<slot-suffix>
. Anzahl der verbleibenden Wiederholungsversuche, um den angegebenen Slot zu starten.
Führen Sie fastboot getvar all
aus, um alle Variablen aufzurufen.
OTA-Pakete generieren
Für die OTA-Pakettools gelten dieselben Befehle wie für Geräte ohne A/B-Partitionen. Die Datei target_files.zip
muss generiert werden, indem die Build-Variablen für das A/B-Ziel definiert werden. Die OTA-Pakettools erkennen automatisch Pakete im Format für den A/B-Updater und generieren sie.
Beispiele:
-
So generieren Sie ein vollständiges OTA:
./build/make/tools/releasetools/ota_from_target_files \ dist_output/tardis-target_files.zip \ ota_update.zip
-
So generieren Sie ein inkrementelles OTA:
./build/make/tools/releasetools/ota_from_target_files \ -i PREVIOUS-tardis-target_files.zip \ dist_output/tardis-target_files.zip \ incremental_ota_update.zip
Partitionen konfigurieren
Der update_engine
kann jedes Paar von A/B-Partitionen aktualisieren, die auf derselben Festplatte definiert sind.
Ein Paar von Partitionen hat ein gemeinsames Präfix (z. B. system
oder boot
) und ein Suffix pro Slot (z. B. _a
). Die Liste der Partitionen, für die der Nutzlastgenerator ein Update definiert, wird durch die Make-Variable AB_OTA_PARTITIONS
konfiguriert.
Wenn beispielsweise die Partitionen bootloader_a
und booloader_b
enthalten sind (_a
und _b
sind die Slot-Suffixe), können Sie diese Partitionen aktualisieren, indem Sie Folgendes in der Produkt- oder Board-Konfiguration angeben:
AB_OTA_PARTITIONS := \ boot \ system \ bootloader
Alle Partitionen, die von update_engine
aktualisiert werden, dürfen nicht vom Rest des Systems geändert werden. Bei inkrementellen oder Delta-Updates werden die Binärdaten aus dem aktuellen Slot verwendet, um die Daten im neuen Slot zu generieren. Bei Änderungen kann es passieren, dass die neuen Slotdaten während des Aktualisierungsvorgangs nicht bestätigt werden und das Update fehlschlägt.
Konfiguration nach der Installation
Sie können den Post-Install-Schritt für jede aktualisierte Partition mithilfe einer Reihe von Schlüssel/Wert-Paaren unterschiedlich konfigurieren. Wenn Sie ein Programm ausführen möchten, das sich unter /system/usr/bin/postinst
in einem neuen Image befindet, geben Sie den Pfad relativ zum Stamm des Dateisystems in der Systempartition an.
Beispiel: usr/bin/postinst
ist system/usr/bin/postinst
(wenn keine RAM-Disk verwendet wird). Geben Sie außerdem den Dateisystemtyp an, der an den Systemaufruf mount(2)
übergeben werden soll. Fügen Sie den Produkt- oder Geräte-.mk
-Dateien (falls zutreffend) Folgendes hinzu:
AB_OTA_POSTINSTALL_CONFIG += \ RUN_POSTINSTALL_system=true \ POSTINSTALL_PATH_system=usr/bin/postinst \ FILESYSTEM_TYPE_system=ext4
Apps kompilieren
Apps können im Hintergrund kompiliert werden, bevor das neue System-Image installiert wird. Wenn Sie Apps im Hintergrund kompilieren möchten, fügen Sie der Gerätekonfiguration des Produkts (in device.mk des Produkts) Folgendes hinzu:
-
Nimm die nativen Komponenten in den Build auf, damit das Kompilierungsskript und die Binärdateien kompiliert und in das Systemimage aufgenommen werden.
# A/B OTA dexopt package PRODUCT_PACKAGES += otapreopt_script
-
Verbinden Sie das Kompilierungsskript mit
update_engine
, sodass es als Schritt nach der Installation ausgeführt wird.# 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
Hilfe bei der Installation der voroptimierten Dateien in der ungenutzten zweiten Systempartition finden Sie unter Installation von DEX_PREOPT-Dateien beim ersten Start.