A/B-Aktualisierungen implementieren

OEMs und SoC-Anbieter, die A/B-Systemupdates implementieren möchten, müssen sicherstellen, dass ihr Bootloader implementiert den HAL "boot_control" und übergibt die richtigen Parameter an den Kernel.

Bootsteuerungs-HAL implementieren

A/B-fähige Bootloader müssen den HAL boot_control unter folgendem Pfad implementieren: hardware/libhardware/include/hardware/boot_control.h. Sie können Implementierungen mit dem system/extras/bootctl Dienstprogramm und system/extras/tests/bootloader/.

Sie müssen auch den unten gezeigten Zustandsautomaten implementieren:

Abbildung 1: Bootloader-Zustandsmaschine

Kernel einrichten

So implementieren Sie A/B-Systemupdates:

  1. Cherrypick für die folgende Kernel-Patch-Serie (falls erforderlich): <ph type="x-smartling-placeholder">
  2. Achten Sie darauf, dass die Kernel-Befehlszeilenargumente die folgenden zusätzlichen Argumente enthalten:
    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>"
    Dabei ist der Wert <public-key-id> die ID des öffentlichen Schlüssels, der für Folgendes verwendet wird: Überprüfen Sie die Signatur der Gültigkeitstabelle (Details finden Sie unter dm-verity).
  3. Fügen Sie dem Systemschlüsselring das .X509-Zertifikat mit dem öffentlichen Schlüssel hinzu: <ph type="x-smartling-placeholder">
      </ph>
    1. Kopieren Sie das im .der-Format formatierte X509-Zertifikat in das Stammverzeichnis der kernel-Verzeichnis. Wenn das X509-Zertifikat als .pem-Datei verwenden, verwenden Sie den folgenden openssl-Befehl für die Konvertierung aus Format .pem in .der:
      openssl x509 -in <x509-pem-certificate> -outform der -out <x509-der-certificate>
    2. Erstellen Sie den zImage so, dass das Zertifikat als Teil des Systemschlüsselrings enthalten ist. Prüfen Sie zur Bestätigung den Eintrag procfs (erfordert KEYS_CONFIG_DEBUG_PROC_KEYS zu aktivieren):
      angler:/# cat /proc/keys
      
      1c8a217e I------ 1 perm 1f010000 0 0 Asymmetri
      Android: 7e4333f9bba00adfe0ede979e28ed1920492b40f: X509.RSA 0492b40f []
      2d454e3e I------ 1 perm 1f030000 0 0 Schlüsselbund
      .system_keyring: 1/4
      Erfolgreiche Aufnahme des .X509-Zertifikats zeigt an, dass der öffentliche Schlüssel vorhanden ist im Systemschlüsselring (Hervorhebung gibt die ID des öffentlichen Schlüssels an).
    3. Ersetzen Sie das Leerzeichen durch # und übergeben Sie es als <public-key-id> in die Kernel-Befehlszeile. Beispiel: Übergeben Sie Android:#7e4333f9bba00adfe0ede979e28ed1920492b40f anstelle von <public-key-id>.

Build-Variablen festlegen

A/B-fähige Bootloader müssen die folgenden Kriterien für Build-Variablen erfüllen:

Für A/B-Ziel muss definiert werden
  • AB_OTA_UPDATER := true
  • AB_OTA_PARTITIONS := \
      boot \
      system \
      vendor
    und andere mit update_engine aktualisierte Partitionen (Radio, Bootloader, etc.)
  • PRODUCT_PACKAGES += \
      update_engine \
      update_verifier
Ein Beispiel finden Sie unter /device/google/marlin/+/android-7.1.0_r1/device-common.mk. Optional können Sie den Dex2oat-Schritt nach der Installation (aber vor dem Neustart) unter Kompilierung:
Dringend empfohlen für A/B-Ziel
  • TARGET_NO_RECOVERY := true definieren
  • BOARD_USES_RECOVERY_AS_BOOT := true definieren
  • BOARD_RECOVERYIMAGE_PARTITION_SIZE nicht definieren
Definition für A/B-Ziel nicht möglich
  • BOARD_CACHEIMAGE_PARTITION_SIZE
  • BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE
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. Die Datenpartition wird nun für das heruntergeladene OTA-Paket verwendet. den Code für das Wiederherstellungsabbild auf der Bootpartition. Alle Partitionen mit A/B-Codierung sollten benannt werden wie folgt (Slots haben immer die Bezeichnung a, b usw.): 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 während der Aktualisierung Blöcke vorübergehend verstopft. Es gab nie eine gute Möglichkeit, die Größe des Cache zu bestimmen. partition: Wie groß es sein musste, hängt davon ab, welche Updates Sie anwenden wollten. Das Schlimmste wäre eine Cache-Partition so groß wie das System-Image. Dank A/B-Updates ist um Blöcke zu verstecken (da Sie immer in eine Partition schreiben, die gerade nicht verwendet wird) und Bei A/B-Streaming muss nicht das gesamte OTA-Paket heruntergeladen werden, bevor es angewendet wird.

Recovery

Die RAM-Disk für die Wiederherstellung ist jetzt in der Datei boot.img enthalten. Wenn Sie kann der Bootloader die Option skip_initramfs nicht aktivieren. über die Kernel-Befehlszeile.

Bei Nicht-A/B-Updates enthält die Wiederherstellungspartition den Code, mit dem Updates angewendet werden. A/B-Tests Updates werden angewendet, indem update_engine im regulären gestarteten System-Image ausgeführt wird. Es gibt immer noch einen Wiederherstellungsmodus, um das Zurücksetzen auf die Werkseinstellungen und das Sideloading von Updates zu implementieren Paketen (wovon der Name „recovery“ stammt). Code und Daten für den Wiederherstellungsmodus wird in der regulären Bootpartition auf einer Ramdisk gespeichert. das System-Image startet, Bootloader weist den Kernel an, die Ramdisk zu überspringen. Andernfalls startet das Gerät zur Wiederherstellung. . Der Wiederherstellungsmodus ist klein (und ein Großteil davon befand sich bereits auf der Bootpartition), sodass der Startvorgang wird die Partition nicht größer.

FSTAB

Das Argument slotselect muss sich in der Zeile für das A/B-Testing befinden. Partitionen. Beispiel:

<path-to-block-device>/vendor  /vendor ext4 ro
Wait,verify=<Pfad-zum-Blockieren-Gerät>/metadata,slotselect

Keine Partition sollte den Namen vendor haben. Partitionieren Sie stattdessen vendor_a oder vendor_b wird ausgewählt und am Bereitstellungspunkt /vendor bereitgestellt.

Argumente für Kernel-Slot

Das aktuelle Slotsuffix sollte entweder über einen bestimmten Device Tree-Knoten (DT) übergeben werden (/firmware/android/slot_suffix) oder über das androidboot.slot_suffix-Kernel-Befehlszeile oder bootconfig-Argument.

Standardmäßig zeigt Fastboot den aktuellen Slot auf einem A/B-Gerät an. Wenn das Update-Paket auch Images für den anderen, nicht aktuellen Slot enthält, lädt Fastboot diese Images ebenfalls. Folgende Optionen sind verfügbar:

  • --slot SLOT. Überschreibt das Standardverhalten und fordert Fastboot auf, den als übergebenen Slot zu blinken. ein Argument.
  • --set-active [SLOT]. Legen Sie den Slot als aktiv fest. Wenn kein optionales Argument angegeben wird, wird der aktuelle Slot als aktiv festgelegt.
  • fastboot --help Weitere Informationen zu Befehlen.

Wenn der Bootloader Fastboot implementiert, sollte er den Befehl set_active <slot>, mit dem die aktuell aktive Anzeigenfläche auf den angegebenen Slot festgelegt wird (dieser muss auch das Flag „nicht bootfähig“ für diesen Slot löschen und die Anzahl der Wiederholungen auf die Standardeinstellung zurücksetzen -Werten). Der Bootloader sollte außerdem die folgenden Variablen unterstützen:

  • has-slot:<partition-base-name-without-suffix>. Gibt "yes" zurück, wenn die angegebene Partition unterstützt Slots, andernfalls „no“.
  • current-slot Gibt das Slot-Suffix zurück, ab dem als Nächstes gebootet wird.
  • slot-count. Gibt eine Ganzzahl zurück, die die Anzahl der verfügbaren Slots darstellt. Derzeit werden zwei Slots unterstützt, sodass dieser Wert 2 ist.
  • slot-successful:<slot-suffix>. Gibt „yes“ zurück ob der angegebene Slot als „Start erfolgreich“ gekennzeichnet, „Nein“ sonst.
  • slot-unbootable:<slot-suffix>. Gibt „yes“ zurück, wenn die angegebene Anzeigenfläche als nicht bootfähig, „nein“ sonst.
  • slot-retry-count:<slot-suffix>. Anzahl der verbleibenden Wiederholungsversuche um den entsprechenden Slot zu starten.

Führen Sie den folgenden Befehl aus, um alle Variablen anzuzeigen: fastboot getvar all

OTA-Pakete generieren

Die OTA-Pakettools folgen denselben Befehlen wie die für Nicht-A/B-Geräte. Die Datei target_files.zip muss von die Build-Variablen für das A/B-Ziel definieren. Die OTA-Pakettools identifizieren und Pakete im Format für den A/B-Updater generieren.

Beispiele:

  • So generierst du ein vollständiges OTA-Update:
    ./build/make/tools/releasetools/ota_from_target_files
        dist_output/tardis-target_files.zip \
        ota_update.zip
    
  • So generieren Sie ein inkrementelles OTA-Update:
    ./build/make/tools/releasetools/ota_from_target_files
        -i PREVIOUS-tardis-target_files.zip \
        dist_output/tardis-target_files.zip \
        inkrementelles_ota_update.zip
    

Partitionen konfigurieren

Mit update_engine kann jedes Paar von A/B-Partitionen aktualisiert werden, die auf demselben Laufwerk definiert sind. Ein Partitionspaar hat ein gemeinsames Präfix (z. B. system oder boot) und das Suffix für die jeweilige Anzeigenfläche (z. B. _a). Die Liste der Partitionen, für die die Nutzlast Generator definiert, dass eine Aktualisierung durch die AB_OTA_PARTITIONS-Make-Variable konfiguriert wird.

Wenn beispielsweise ein Partitionspaar bootloader_a und booloader_b sind enthalten (_a und _b sind der Slot) Suffixe) können Sie diese Partitionen aktualisieren, indem Sie auf dem Produkt oder der Tafel Folgendes angeben: Konfiguration:

AB_OTA_PARTITIONS := \
  starten \
  System\
  Bootloader

Alle von update_engine aktualisierten Partitionen dürfen nicht durch den Rest der System. Bei inkrementellen oder Delta-Aktualisierungen werden die Binärdaten aus dem aktuellen Slot zum Generieren der Daten in der neuen Anzeigenfläche verwendet wird. Jede Änderung kann dazu führen, dass die die Prüfung nicht bestehen, sodass das Update fehlschlägt.

Nachinstallation konfigurieren

Sie können den Schritt nach der Installation für jede aktualisierte Partition Schlüssel/Wert-Paare. So führen Sie ein Programm unter /system/usr/bin/postinst in einem neuen Image den Pfad relativ zum Stammverzeichnis des Dateisystems in der Systempartition angeben.

Beispiel: usr/bin/postinst ist system/usr/bin/postinst (wenn nicht mithilfe einer RAM-Disk). Geben Sie außerdem den Dateisystemtyp an, der an die mount(2)-Systemaufruf. Dem Produkt oder Gerät Folgendes hinzufügen .mk-Dateien (falls zutreffend):

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 vor dem Neustart mit dem neuen System-Image kompiliert werden. Zusammenstellen im Hintergrund ausführen, fügen Sie Folgendes zur Gerätekonfiguration des Produkts hinzu (in der device.mk des Produkts):

  1. Native Komponenten in den Build aufnehmen, um sicherzustellen, dass das Kompilierungsskript und die Binärdateien korrekt sind kompiliert und im System-Image enthalten sein.
      # A/B-OTA-Dexopt-Paket
      PRODUCT_PACKAGES += otapreopt_script
    
  2. Verbinden Sie das Kompilierungsskript mit update_engine, sodass es als nach der Installation.
      # Anschluss von A/B OTA dexopt update_engine
      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 vorab optimierten Dateien in der nicht verwendeten zweiten Systempartition finden Sie unter Installation von DEX_PREOPT-Dateien beim ersten Start.