Virtuelles A/B implementieren

Um virtuelles A/B auf einem neuen Gerät zu implementieren oder ein eingeführtes Gerät nachzurüsten, müssen Sie Änderungen am gerätespezifischen Code vornehmen.

Fahnen bauen

Geräte, die virtuelles A/B verwenden, müssen als A/B-Gerät konfiguriert und mit dynamischen Partitionen gestartet werden .

Legen Sie für Geräte, die mit virtuellem A/B gestartet werden, fest, dass sie die Basiskonfiguration des virtuellen A/B-Geräts erben:

$(call inherit-product, \
    $(SRC_TARGET_DIR)/product/virtual_ab_ota.mk)

Geräte, die mit virtuellem A/B starten, benötigen nur halb so viel Platinengröße für BOARD_SUPER_PARTITION_SIZE da B-Steckplätze nicht mehr in Super vorhanden sind. Das heißt, BOARD_SUPER_PARTITION_SIZE muss größer oder gleich sum(Größe der Updategruppen) + Overhead sein, was wiederum größer oder gleich sum(Size of Partitions) + Overhead sein muss.

Um komprimierte Snapshots mit Virtual A/B zu aktivieren, erben Sie stattdessen die folgende Basiskonfiguration:

$(call inherit-product, \
    $(SRC_TARGET_DIR)/product/virtual_ab_ota/compression.mk)

Bootsteuerung HAL

Die Boot-Steuerungs-HAL stellt eine Schnittstelle für OTA-Clients bereit, um Boot-Slots zu steuern. Virtuelles A/B erfordert ein kleineres Versions-Upgrade der Boot-Steuerungs-HAL, da zusätzliche APIs benötigt werden, um sicherzustellen, dass der Bootloader während des Flashens/Zurücksetzens auf die Werkseinstellungen geschützt ist. Siehe IBootControl.hal und types.hal für die neueste Version der HAL-Definition.

// hardware/interfaces/boot/1.1/types.hal
enum MergeStatus : uint8_t {
    NONE, UNKNOWN, SNAPSHOTTED, MERGING, CANCELLED };

// hardware/interfaces/boot/1.1/IBootControl.hal
package android.hardware.boot@1.1;
interface IBootControl extends @1.0::IBootControl {
    setSnapshotMergeStatus(MergeStatus status)
        generates (bool success);
    getSnapshotMergeStatus()
        generates (MergeStatus status);
}
// Recommended implementation

Return<bool> BootControl::setSnapshotMergeStatus(MergeStatus v) {
    // Write value to persistent storage
    // e.g. misc partition (using libbootloader_message)
    // bootloader rejects wipe when status is SNAPSHOTTED
    // or MERGING
}

Fstab-Änderungen

Die Integrität der Metadatenpartition ist für den Startvorgang von entscheidender Bedeutung, insbesondere direkt nach der Anwendung eines OTA-Updates. Daher muss die Metadatenpartition überprüft werden, bevor first_stage_init sie einhängt. Um dies sicherzustellen, fügen Sie dem Eintrag für /metadata das Flag check fs_mgr hinzu. Im Folgenden finden Sie ein Beispiel:

/dev/block/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard,sync wait,formattable,first_stage_mount,check

Kernel-Anforderungen

Um Snapshots zu aktivieren, setzen CONFIG_DM_SNAPSHOT auf true .

Schließen Sie für Geräte, die F2FS verwenden, das Flag f2fs: export FS_NOCOW_FL in den Benutzer -Kernel-Patch ein, um das Anheften von Dateien zu beheben. Schließen Sie auch den Kernel-Patch für f2fs: Support Aligned Pinned File ein .

Virtuelles A/B stützt sich auf Funktionen, die in Kernel-Version 4.3 hinzugefügt wurden: das Overflow -Statusbit in den snapshot und snapshot-merge Zielen. Alle Geräte, die mit Android 9 und höher starten, sollten bereits Kernel-Version 4.4 oder höher haben.

Um komprimierte Snapshots zu aktivieren, ist die unterstützte Mindestkernelversion 4.19. Setzen CONFIG_DM_USER=m oder CONFIG_DM_USER=y . Wenn Sie Ersteres (ein Modul) verwenden, muss das Modul in die Ramdisk der ersten Stufe geladen werden. Dies kann durch Hinzufügen der folgenden Zeile zum Geräte-Makefile erreicht werden:

BOARD_GENERIC_RAMDISK_KERNEL_MODULES_LOAD := dm-user.ko

Nachrüstung auf Geräten mit Upgrade auf Android 11

Beim Upgrade auf Android 11 können Geräte, die mit dynamischen Partitionen gestartet wurden, optional virtuelles A/B nachrüsten. Der Aktualisierungsprozess ist größtenteils derselbe wie für Geräte, die mit virtuellem A/B gestartet werden, mit einigen geringfügigen Unterschieden:

  • Speicherort der COW-Dateien – Für Startgeräte verwendet der OTA-Client den gesamten verfügbaren leeren Speicherplatz in der Superpartition, bevor er den Speicherplatz in /data . Bei nachgerüsteten Geräten ist immer genügend Platz in der Superpartition vorhanden, sodass die COW-Datei niemals auf /data erstellt wird.

  • Build-Time-Feature-Flags – Für Geräte, die virtuelles A/B nachrüsten, werden sowohl PRODUCT_VIRTUAL_AB_OTA als auch PRODUCT_VIRTUAL_AB_OTA_RETROFIT auf true gesetzt, wie unten gezeigt:

    (call inherit-product, \
        (SRC_TARGET_DIR)/product/virtual_ab_ota_retrofit.mk)
    
  • Super-Partitionsgröße – Geräte, die mit virtuellem A/B gestartet werden, können BOARD_SUPER_PARTITION_SIZE , da B-Slots nicht in der Super-Partition sind. Geräte, die virtuelles A/B nachrüsten, behalten die alte Superpartitionsgröße bei, sodass BOARD_SUPER_PARTITION_SIZE größer oder gleich 2 * sum(size of update groups) + Overhead ist, was wiederum größer oder gleich 2 * sum(size of partitions) ist. + Overhead .

Bootloader-Änderungen

Während des Zusammenführungsschritts eines Updates enthält /data die einzige vollständige Instanz des Android-Betriebssystems. Sobald die Migration beginnt, sind die nativen system , vendor und product unvollständig, bis die Kopie abgeschlossen ist. Wenn das Gerät während dieses Vorgangs entweder durch Wiederherstellung oder über das Dialogfeld „Systemeinstellungen“ auf die Werkseinstellungen zurückgesetzt wird, ist das Gerät nicht mehr bootfähig.

Beenden Sie vor dem Löschen /data die Zusammenführung in Wiederherstellung oder Rollback je nach Gerätestatus:

  • Wenn der neue Build zuvor erfolgreich gestartet wurde, schließen Sie die Migration ab.
  • Andernfalls Rollback zum alten Steckplatz:
    • Führen Sie für dynamische Partitionen ein Rollback zum vorherigen Zustand durch.
    • Legen Sie für statische Partitionen den aktiven Steckplatz auf den alten Steckplatz fest.

Sowohl der Bootloader als fastbootd können die /data Partition löschen, wenn das Gerät entsperrt ist. Während fastbootd die Migration erzwingen kann, kann der Bootloader dies nicht. Der Bootloader weiß nicht, ob eine Zusammenführung im Gange ist oder nicht, oder welche Blöcke in /data die Betriebssystempartitionen darstellen. Geräte müssen verhindern, dass der Benutzer das Gerät unwissentlich funktionsunfähig macht (Bricking), indem er Folgendes tut:

  1. Implementieren Sie die Boot-Control-HAL, damit der Bootloader den von der Methode setSnapshotMergeStatus() festgelegten Wert lesen kann.
  2. Wenn der Zusammenführungsstatus MERGING oder wenn der Zusammenführungsstatus SNAPSHOTTED und der Steckplatz auf den neu aktualisierten Steckplatz geändert wurde, müssen Anforderungen zum Löschen von userdata , metadata oder der Partition, die den Zusammenführungsstatus speichert, im Bootloader abgelehnt werden.
  3. Implementieren Sie den fastboot snapshot-update cancel , damit Benutzer dem Bootloader signalisieren können, dass sie diesen Schutzmechanismus umgehen möchten.
  4. Ändern Sie benutzerdefinierte Flashing-Tools oder -Skripts, um fastboot snapshot-update cancel wenn das gesamte Gerät geflasht wird. Dies ist sicher, da das Flashen des gesamten Geräts den OTA entfernt. Tools können diesen Befehl zur Laufzeit erkennen, indem sie fastboot getvar snapshot-update-status implementieren. Dieser Befehl hilft bei der Unterscheidung zwischen Fehlerbedingungen.

Beispiel

struct VirtualAbState {
    uint8_t StructVersion;
    uint8_t MergeStatus;
    uint8_t SourceSlot;
};

bool ShouldPreventUserdataWipe() {
    VirtualAbState state;
    if (!ReadVirtualAbState(&state)) ...
    return state.MergeStatus == MergeStatus::MERGING ||
           (state.MergeStatus == MergeStatus::SNAPSHOTTED &&
            state.SourceSlot != CurrentSlot()));
}

Änderungen der Fastboot-Werkzeuge

Android 11 nimmt die folgenden Änderungen am Fastboot-Protokoll vor:

  • getvar snapshot-update-status — Gibt den Wert zurück, den die Boot-Control-HAL an den Bootloader übermittelt hat:
    • Wenn der Zustand MERGING ist, muss der Bootloader merging zurückgeben.
    • Wenn der Zustand SNAPSHOTTED ist, muss der Bootloader snapshotted zurückgeben.
    • Andernfalls muss der Bootloader none zurückgeben.
  • snapshot-update merge – Schließt einen Zusammenführungsvorgang ab und bootet bei Bedarf mit recovery/fastbootd. Dieser Befehl ist nur gültig, wenn snapshot-update-status merging ist, und wird nur in fastbootd unterstützt.
  • snapshot-update cancel — Setzt den Zusammenführungsstatus der Boot-Steuerungs-HAL auf CANCELLED . Dieser Befehl ist ungültig, wenn das Gerät gesperrt ist.
  • erase or wipe – Ein erase oder wipe von metadata , userdata oder einer Partition, die den Merge-Status für die Boot-Control-HAL enthält, sollte den Snapshot-Merge-Status überprüfen. Wenn der Status MERGING oder SNAPSHOTTED , sollte das Gerät den Vorgang abbrechen.
  • set_active — Ein set_active Befehl, der den aktiven Slot ändert, sollte den Snapshot-Zusammenführungsstatus überprüfen. Wenn der Status MERGING , sollte das Gerät den Vorgang abbrechen. Der Steckplatz kann im SNAPSHOTTED -Zustand sicher geändert werden.

Diese Änderungen sollen verhindern, dass ein Gerät versehentlich nicht mehr bootfähig gemacht wird, aber sie können für automatisierte Tools störend sein. Wenn die Befehle als Komponente zum Flashen aller Partitionen verwendet werden, z. B. beim Ausführen von fastboot flashall , wird empfohlen, den folgenden Ablauf zu verwenden:

  1. getvar snapshot-update-status .
  2. Wenn merging oder ein snapshotted wird, geben snapshot-update cancel aus.
  3. Fahren Sie mit blinkenden Schritten fort.

Reduzierung der Speicheranforderungen

Geräten, denen in Super kein vollständiger A/B-Speicher zugewiesen ist und die voraussichtlich /data nach Bedarf verwenden, wird dringend empfohlen, das Block-Mapping-Tool zu verwenden. Das Block-Mapping-Tool hält die Blockzuordnung zwischen Builds konsistent und reduziert unnötige Schreibvorgänge in den Snapshot. Dies ist unter Reducing OTA Size dokumentiert.