Dynamische Partitionen implementieren

Die dynamische Partitionierung wird mithilfe des dm-linear-Device-Mapper-Moduls im Linux-Kernel implementiert. Die Partition super enthält Metadaten mit den Namen und Blockbereichen der einzelnen dynamischen Partitionen in super. In der ersten Phase init werden diese Metadaten geparst und validiert und virtuelle Blockgeräte erstellt, um jede dynamische Partition darzustellen.

Beim Anwenden eines OTA werden dynamische Partitionen automatisch nach Bedarf erstellt, in der Größe angepasst oder gelöscht. Bei A/B-Geräten gibt es zwei Kopien der Metadaten und Änderungen werden nur auf die Kopie angewendet, die den Ziel-Slot darstellt.

Da dynamische Partitionen im Userspace implementiert sind, können Partitionen, die vom Bootloader benötigt werden, nicht dynamisch sein. Beispiele: boot, dtbo und vbmeta werden vom Bootloader gelesen und müssen daher als physische Partitionen erhalten bleiben.

Jede dynamische Partition kann zu einer Aktualisierungsgruppe gehören. Diese Gruppen begrenzen den maximalen Speicherplatz, den Partitionen in dieser Gruppe belegen können. Beispielsweise können system und vendor zu einer Gruppe gehören, die die Gesamtgröße von system und vendor einschränkt.

Dynamische Partitionen auf neuen Geräten implementieren

In diesem Abschnitt wird beschrieben, wie Sie dynamische Partitionen auf neuen Geräten implementieren, die mit Android 10 oder höher auf den Markt kommen. Informationen zum Aktualisieren vorhandener Geräte finden Sie unter Android-Geräte aktualisieren.

Änderungen an Partitionen

Erstellen Sie für Geräte, die mit Android 10 auf den Markt kommen, eine Partition namens super. Die Partition super verarbeitet A/B-Slots intern, sodass A/B-Geräte keine separaten Partitionen super_a und super_b benötigen. Alle schreibgeschützten AOSP-Partitionen, die nicht vom Bootloader verwendet werden, müssen dynamisch sein und aus der GUID-Partitionstabelle (GPT) entfernt werden. Herstellerspezifische Partitionen müssen nicht dynamisch sein und können in der GPT platziert werden.

Um die Größe von super zu schätzen, addieren Sie die Größen der Partitionen, die aus der GPT gelöscht werden. Bei A/B-Geräten sollte dies die Größe beider Slots umfassen. Abbildung 1 zeigt ein Beispiel für eine Partitionstabelle vor und nach der Umstellung auf dynamische Partitionen.

Layout der Partitionstabelle
Abbildung 1. Neues physisches Partitionstabellenlayout bei der Umstellung auf dynamische Partitionen

Folgende dynamische Partitionen werden unterstützt:

  • System
  • Vendor
  • Produkt
  • System Ext
  • ODM

Bei Geräten, die mit Android 10 eingeführt werden, muss die Kernel-Befehlszeilenoption androidboot.super_partition leer sein, damit die System-Property ro.boot.super_partition leer ist.

Partitionsausrichtung

Das Device-Mapper-Modul funktioniert möglicherweise weniger effizient, wenn die Partition super nicht richtig ausgerichtet ist. Die Partition super MUSS an der Mindestgröße für E/A-Anfragen ausgerichtet sein, die von der Blockebene bestimmt wird. Standardmäßig geht das Build-System (über lpmake, das das super-Partitions-Image generiert) davon aus, dass eine 1 MiB-Ausrichtung für jede dynamische Partition ausreicht. Anbieter sollten jedoch darauf achten, dass die super-Partition richtig ausgerichtet ist.

Sie können die Mindestanfragegröße eines Blockgeräts ermitteln, indem Sie sysfs untersuchen. Beispiel:

# ls -l /dev/block/by-name/super
lrwxrwxrwx 1 root root 16 1970-04-05 01:41 /dev/block/by-name/super -> /dev/block/sda17
# cat /sys/block/sda/queue/minimum_io_size
786432

Sie können die Ausrichtung der super-Partition auf ähnliche Weise prüfen:

# cat /sys/block/sda/sda17/alignment_offset

Der Ausrichtungs-Offset MUSS 0 sein.

Änderungen der Gerätekonfiguration

Fügen Sie das folgende Flag in device.mk ein, um die dynamische Partitionierung zu aktivieren:

PRODUCT_USE_DYNAMIC_PARTITIONS := true

Änderungen an der Board-Konfiguration

Sie müssen die Größe der super-Partition festlegen:

BOARD_SUPER_PARTITION_SIZE := <size-in-bytes>

Auf A/B-Geräten gibt das Build-System einen Fehler aus, wenn die Gesamtgröße der dynamischen Partitions-Images mehr als die Hälfte der Partitionsgröße von super beträgt.

Sie können die Liste der dynamischen Partitionen so konfigurieren: Für Geräte, die Updategruppen verwenden, listen Sie die Gruppen in der Variablen BOARD_SUPER_PARTITION_GROUPS auf. Jeder Gruppenname hat dann eine BOARD_group_SIZE- und eine BOARD_group_PARTITION_LIST-Variable. Bei A/B-Geräten sollte die maximale Größe einer Gruppe nur einen Slot umfassen, da die Gruppennamen intern mit einem Slot-Suffix versehen werden.

Hier ist ein Beispiel für ein Gerät, bei dem alle Partitionen in einer Gruppe namens example_dynamic_partitions platziert werden:

BOARD_SUPER_PARTITION_GROUPS := example_dynamic_partitions
BOARD_EXAMPLE_DYNAMIC_PARTITIONS_SIZE := 6442450944
BOARD_EXAMPLE_DYNAMIC_PARTITIONS_PARTITION_LIST := system vendor product

Hier ist ein Beispielgerät, bei dem System- und Produktdienste in group_foo und vendor, product und odm in group_bar platziert werden:

BOARD_SUPER_PARTITION_GROUPS := group_foo group_bar
BOARD_GROUP_FOO_SIZE := 4831838208
BOARD_GROUP_FOO_PARTITION_LIST := system product_services
BOARD_GROUP_BAR_SIZE := 1610612736
BOARD_GROUP_BAR_PARTITION_LIST := vendor product odm
  • Bei Geräten mit virtuellem A/B-Start muss die Summe der maximalen Größen aller Gruppen höchstens
    betragen:BOARD_SUPER_PARTITION_SIZE – Overhead
    Weitere Informationen finden Sie unter Virtuelles A/B implementieren.
  • Bei Geräten, die mit A/B-Updates eingeführt werden, muss die Summe der maximalen Größen aller Gruppen
    BOARD_SUPER_PARTITION_SIZE / 2 – Overhead betragen.
  • Für Geräte, die keine A/B‑Geräte sind, und für A/B‑Geräte, die nachgerüstet wurden, muss die Summe der maximalen Größen aller Gruppen
    sein:BOARD_SUPER_PARTITION_SIZE – Overhead
  • Zur Build-Zeit darf die Summe der Größen der Bilder jeder Partition in einer Updategruppe die maximale Größe der Gruppe nicht überschreiten.
  • Für die Berechnung ist ein Overhead erforderlich, um Metadaten, Ausrichtungen usw. zu berücksichtigen. Ein angemessener Overhead ist 4 MiB. Sie können aber auch einen größeren Overhead auswählen, wenn das Gerät dies erfordert.

Größe dynamischer Partitionen anpassen

Vor der Einführung dynamischer Partitionen wurden die Partitionsgrößen überdimensioniert, um sicherzustellen, dass genügend Speicherplatz für zukünftige Updates vorhanden war. Die tatsächliche Größe wurde unverändert übernommen und die meisten schreibgeschützten Partitionen hatten etwas freien Speicherplatz in ihrem Dateisystem. In dynamischen Partitionen ist dieser kostenlose Speicherplatz nicht nutzbar und könnte verwendet werden, um Partitionen während eines OTA zu vergrößern. Es ist wichtig, dass Partitionen keinen Speicherplatz verschwenden und auf die kleinstmögliche Größe zugewiesen werden.

Bei schreibgeschützten ext4-Images weist das Build-System automatisch die Mindestgröße zu, wenn keine fest codierte Partitionsgröße angegeben ist. Das Build-System passt das Image so an, dass das Dateisystem möglichst wenig ungenutzten Speicherplatz hat. So wird verhindert, dass das Gerät Speicherplatz verschwendet, der für OTAs verwendet werden kann.

Außerdem können ext4-Images durch Aktivieren der Deduplizierung auf Blockebene weiter komprimiert werden. Verwenden Sie dazu die folgende Konfiguration:

BOARD_EXT4_SHARE_DUP_BLOCKS := true

Wenn die automatische Zuweisung einer Mindestgröße für eine Partition nicht gewünscht ist, gibt es zwei Möglichkeiten, die Partitionsgröße zu steuern. Sie können mit BOARD_partitionIMAGE_PARTITION_RESERVED_SIZE einen Mindestbetrag an freiem Speicherplatz angeben oder mit BOARD_partitionIMAGE_PARTITION_SIZE die Größe dynamischer Partitionen erzwingen. Keine dieser Optionen wird empfohlen, sofern sie nicht erforderlich ist.

Beispiel:

BOARD_PRODUCTIMAGE_PARTITION_RESERVED_SIZE := 52428800

Dadurch wird das Dateisystem in product.img gezwungen, 50 MiB freien Speicherplatz zu haben.

Änderungen an „System-as-root“

Geräte, die bei Markteinführung Android 10 nutzen, dürfen nicht System‑as‑Root verwenden.

Geräte mit dynamischen Partitionen (unabhängig davon, ob sie mit dynamischen Partitionen ausgeliefert werden oder diese nachgerüstet werden) dürfen nicht „system-as-root“ verwenden. Der Linux-Kernel kann die Partition super nicht interpretieren und daher system nicht bereitstellen. system wird jetzt von der init der ersten Phase bereitgestellt, die sich auf der RAM-Disk befindet.

Legen Sie BOARD_BUILD_SYSTEM_ROOT_IMAGE nicht fest. In Android 10 wird das Flag BOARD_BUILD_SYSTEM_ROOT_IMAGE nur verwendet, um zu unterscheiden, ob das System vom Kernel oder von der ersten Phase init in der Ramdisk bereitgestellt wird.

Wenn Sie BOARD_BUILD_SYSTEM_ROOT_IMAGE auf true setzen, tritt ein Build-Fehler auf, wenn PRODUCT_USE_DYNAMIC_PARTITIONS ebenfalls true ist.

Wenn BOARD_USES_RECOVERY_AS_BOOT auf „true“ gesetzt ist, wird das Wiederherstellungsimage als „boot.img“ erstellt und enthält die Ramdisk der Wiederherstellung. Bisher wurde im Bootloader der Kernel-Befehlszeilenparameter skip_initramfs verwendet, um zu entscheiden, in welchem Modus gebootet werden soll. Bei Geräten mit Android 10 darf der Bootloader skip_initramfs NICHT an die Kernel-Befehlszeile übergeben. Stattdessen sollte der Bootloader androidboot.force_normal_boot=1 übergeben, um die Wiederherstellung zu überspringen und normales Android zu starten. Auf Geräten, die mit Android 12 oder höher auf den Markt kommen, muss bootconfig verwendet werden, um androidboot.force_normal_boot=1 zu übergeben.

AVB-Konfigurationsänderungen

Wenn Sie Android Verified Boot 2.0 verwenden und das Gerät keine verketteten Partitionsdeskriptoren verwendet, ist keine Änderung erforderlich. Wenn Sie jedoch verkettete Partitionen verwenden und eine der bestätigten Partitionen dynamisch ist, sind Änderungen erforderlich.

Hier ist ein Beispiel für die Konfiguration eines Geräts, das vbmeta für die Partitionen system und vendor verkettet.

BOARD_AVB_SYSTEM_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
BOARD_AVB_SYSTEM_ALGORITHM := SHA256_RSA2048
BOARD_AVB_SYSTEM_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
BOARD_AVB_SYSTEM_ROLLBACK_INDEX_LOCATION := 1

BOARD_AVB_VENDOR_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
BOARD_AVB_VENDOR_ALGORITHM := SHA256_RSA2048
BOARD_AVB_VENDOR_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
BOARD_AVB_VENDOR_ROLLBACK_INDEX_LOCATION := 1

Bei dieser Konfiguration erwartet der Bootloader, dass am Ende der Partitionen system und vendor ein vbmeta-Footer vorhanden ist. Da diese Partitionen für den Bootloader nicht mehr sichtbar sind (sie befinden sich in super), sind zwei Änderungen erforderlich.

  • Fügen Sie der Partitionstabelle des Geräts die Partitionen vbmeta_system und vbmeta_vendor hinzu. Fügen Sie für A/B-Geräte vbmeta_system_a, vbmeta_system_b, vbmeta_vendor_a und vbmeta_vendor_b hinzu. Wenn Sie eine oder mehrere dieser Partitionen hinzufügen, sollten sie dieselbe Größe wie die vbmeta-Partition haben.
  • Benennen Sie die Konfigurations-Flags um, indem Sie VBMETA_ hinzufügen, und geben Sie an, auf welche Partitionen sich die Verkettung erstreckt:
    BOARD_AVB_VBMETA_SYSTEM := system
    BOARD_AVB_VBMETA_SYSTEM_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
    BOARD_AVB_VBMETA_SYSTEM_ALGORITHM := SHA256_RSA2048
    BOARD_AVB_VBMETA_SYSTEM_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
    BOARD_AVB_VBMETA_SYSTEM_ROLLBACK_INDEX_LOCATION := 1
    
    BOARD_AVB_VBMETA_VENDOR := vendor
    BOARD_AVB_VBMETA_VENDOR_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
    BOARD_AVB_VBMETA_VENDOR_ALGORITHM := SHA256_RSA2048
    BOARD_AVB_VBMETA_VENDOR_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
    BOARD_AVB_VBMETA_VENDOR_ROLLBACK_INDEX_LOCATION := 1

Ein Gerät kann eine, beide oder keine dieser Partitionen verwenden. Änderungen sind nur erforderlich, wenn eine Verkettung mit einer logischen Partition erfolgt.

AVB-Bootloader-Änderungen

Wenn der Bootloader libavb eingebettet hat, füge die folgenden Patches hinzu:

Wenn Sie verkettete Partitionen verwenden, fügen Sie einen zusätzlichen Patch hinzu:

  • 49936b4c0109411fdd38bd4ba3a32a01c40439a9 – „libavb: Support vbmeta blobs in beginning of partition.“

Änderungen an der Kernel-Befehlszeile

Der Kernelbefehlszeile muss ein neuer Parameter, androidboot.boot_devices, hinzugefügt werden. Dies wird von init verwendet, um /dev/block/by-name-Symlinks zu aktivieren. Es sollte die Gerätepfadkomponente des zugrunde liegenden „by-name“-Symlinks sein, der von ueventd erstellt wurde, also /dev/block/platform/device-path/by-name/partition-name. Geräte, die mit Android 12 oder höher auf den Markt kommen, müssen bootconfig verwenden, um androidboot.boot_devices an init zu übergeben.

Wenn der Symlink für die Superpartition nach Name beispielsweise /dev/block/platform/soc/100000.ufshc/by-name/super ist, können Sie den Befehlszeilenparameter in der Datei „BoardConfig.mk“ so hinzufügen:

BOARD_KERNEL_CMDLINE += androidboot.boot_devices=soc/100000.ufshc
Sie können den bootconfig-Parameter in der Datei „BoardConfig.mk“ so hinzufügen:
BOARD_BOOTCONFIG += androidboot.boot_devices=soc/100000.ufshc

fstab-Änderungen

Der Gerätebaum und die Gerätebaum-Overlays dürfen keine fstab-Einträge enthalten. Verwenden Sie eine fstab-Datei, die Teil der Ramdisk ist.

An der fstab-Datei müssen Änderungen für logische Partitionen vorgenommen werden:

  • Das Feld „fs_mgr flags“ muss das Flag logical und das in Android 10 eingeführte Flag first_stage_mount enthalten, das angibt, dass eine Partition in der ersten Phase eingebunden werden soll.
  • In einer Partition kann avb=vbmeta partition name als fs_mgr-Flag angegeben werden. Die angegebene vbmeta-Partition wird dann von der ersten Phase init initialisiert, bevor versucht wird, Geräte zu mounten.
  • Das Feld dev muss der Name der Partition sein.

Die folgenden fstab-Einträge legen System-, Anbieter- und Produktpartitionen als logische Partitionen gemäß den oben genannten Regeln fest.

#<dev>  <mnt_point> <type>  <mnt_flags options> <fs_mgr_flags>
system   /system     ext4    ro,barrier=1        wait,slotselect,avb=vbmeta,logical,first_stage_mount
vendor   /vendor     ext4    ro,barrier=1        wait,slotselect,avb,logical,first_stage_mount
product  /product    ext4    ro,barrier=1        wait,slotselect,avb,logical,first_stage_mount

Kopieren Sie die fstab-Datei in die Ramdisk der ersten Phase.

SELinux-Änderungen

Das Blockgerät der Superpartition muss mit dem Label super_block_device gekennzeichnet sein. Wenn der Symlink für die Superpartition mit dem Namen /dev/block/platform/soc/100000.ufshc/by-name/super lautet, fügen Sie file_contexts die folgende Zeile hinzu:

/dev/block/platform/soc/10000\.ufshc/by-name/super   u:object_r:super_block_device:s0

fastbootd

Der Bootloader (oder ein anderes Flash-Tool, das nicht im Nutzerbereich ausgeführt wird) kann dynamische Partitionen nicht verarbeiten und daher auch nicht flashen. Um dieses Problem zu beheben, müssen Geräte eine User-Space-Implementierung des Fastboot-Protokolls namens „fastbootd“ verwenden.

Weitere Informationen zur Implementierung von fastbootd finden Sie unter Fastboot in den Nutzerbereich verschieben.

adb remount

Für Entwickler, die eng- oder userdebug-Builds verwenden, ist adb remount äußerst nützlich für schnelle Iterationen. Dynamische Partitionen stellen ein Problem für adb remount dar, da in den einzelnen Dateisystemen kein freier Speicherplatz mehr vorhanden ist. Um dieses Problem zu beheben, können Geräte „overlayfs“ aktivieren. Solange in der Superpartition freier Speicherplatz vorhanden ist, erstellt adb remount automatisch eine temporäre dynamische Partition und verwendet overlayfs für Schreibvorgänge. Die temporäre Partition hat den Namen scratch. Verwenden Sie diesen Namen also nicht für andere Partitionen.

Weitere Informationen zum Aktivieren von overlayfs finden Sie in der README-Datei zu overlayfs in AOSP.

Android-Geräte aktualisieren

Wenn Sie ein Gerät auf Android 10 aktualisieren und Unterstützung für dynamische Partitionen in das OTA aufnehmen möchten, müssen Sie die integrierte Partitionstabelle nicht ändern. Es ist eine zusätzliche Konfiguration erforderlich.

Änderungen der Gerätekonfiguration

Wenn Sie die dynamische Partitionierung nachrüsten möchten, fügen Sie die folgenden Flags in device.mk hinzu:

PRODUCT_USE_DYNAMIC_PARTITIONS := true
PRODUCT_RETROFIT_DYNAMIC_PARTITIONS := true

Änderungen an der Board-Konfiguration

Sie müssen die folgenden Board-Variablen festlegen:

  • Legen Sie für BOARD_SUPER_PARTITION_BLOCK_DEVICES die Liste der Blockgeräte fest, die zum Speichern von Extents dynamischer Partitionen verwendet werden. Dies ist die Liste der Namen der vorhandenen physischen Partitionen auf dem Gerät.
  • Setzen Sie BOARD_SUPER_PARTITION_partition_DEVICE_SIZE auf die Größen der einzelnen Blockgeräte in BOARD_SUPER_PARTITION_BLOCK_DEVICES. Dies ist die Liste der Größen der vorhandenen physischen Partitionen auf dem Gerät. Dies ist in vorhandenen Board-Konfigurationen normalerweise BOARD_partitionIMAGE_PARTITION_SIZE.
  • Heben Sie die Festlegung von BOARD_partitionIMAGE_PARTITION_SIZE für alle Partitionen in BOARD_SUPER_PARTITION_BLOCK_DEVICES auf.
  • Setzen Sie BOARD_SUPER_PARTITION_SIZE auf die Summe von BOARD_SUPER_PARTITION_partition_DEVICE_SIZE.
  • Legen Sie BOARD_SUPER_PARTITION_METADATA_DEVICE auf das Blockgerät fest, auf dem die Metadaten der dynamischen Partition gespeichert sind. Dieser muss einer der folgenden Werte sein: BOARD_SUPER_PARTITION_BLOCK_DEVICES. Normalerweise ist dies auf system festgelegt.
  • Legen Sie BOARD_SUPER_PARTITION_GROUPS, BOARD_group_SIZE und BOARD_group_PARTITION_LIST fest. Weitere Informationen finden Sie unter Änderungen an der Boardkonfiguration auf neuen Geräten.

Wenn das Gerät beispielsweise bereits System- und Anbieterpartitionen hat und Sie diese während des Updates in dynamische Partitionen konvertieren und eine neue Produktpartition hinzufügen möchten, legen Sie diese Board-Konfiguration fest:

BOARD_SUPER_PARTITION_BLOCK_DEVICES := system vendor
BOARD_SUPER_PARTITION_METADATA_DEVICE := system

# Rename BOARD_SYSTEMIMAGE_PARTITION_SIZE to BOARD_SUPER_PARTITION_SYSTEM_DEVICE_SIZE.
BOARD_SUPER_PARTITION_SYSTEM_DEVICE_SIZE := <size-in-bytes>

# Rename BOARD_VENDORIMAGE_PARTITION_SIZE to BOARD_SUPER_PARTITION_VENDOR_DEVICE_SIZE
BOARD_SUPER_PARTITION_VENDOR_DEVICE_SIZE := <size-in-bytes>

# This is BOARD_SUPER_PARTITION_SYSTEM_DEVICE_SIZE + BOARD_SUPER_PARTITION_VENDOR_DEVICE_SIZE
BOARD_SUPER_PARTITION_SIZE := <size-in-bytes>

# Configuration for dynamic partitions. For example:
BOARD_SUPER_PARTITION_GROUPS := group_foo
BOARD_GROUP_FOO_SIZE := <size-in-bytes>
BOARD_GROUP_FOO_PARTITION_LIST := system vendor product

SELinux-Änderungen

Die Blockgeräte der Superpartition müssen mit dem Attribut super_block_device_type gekennzeichnet sein. Wenn das Gerät beispielsweise bereits die Partitionen system und vendor hat, möchten Sie diese als Blockgeräte zum Speichern von Extents dynamischer Partitionen verwenden. Die entsprechenden Symlinks mit Namen sind als system_block_device gekennzeichnet:

/dev/block/platform/soc/10000\.ufshc/by-name/system   u:object_r:system_block_device:s0
/dev/block/platform/soc/10000\.ufshc/by-name/vendor   u:object_r:system_block_device:s0

Fügen Sie dann die folgende Zeile zu device.te hinzu:

typeattribute system_block_device super_block_device_type;

Informationen zu anderen Konfigurationen finden Sie unter Dynamische Partitionen auf neuen Geräten implementieren.

Weitere Informationen zu Retrofit-Updates finden Sie unter OTA für A/B-Geräte ohne dynamische Partitionen.

Factory Images

Wenn ein Gerät mit Unterstützung für dynamische Partitionen auf den Markt kommt, sollten Sie zum Flashen von Werks-Images kein Userspace-Fastboot verwenden, da das Booten in den Userspace langsamer ist als andere Flash-Methoden.

Um dieses Problem zu beheben, erstellt make dist jetzt ein zusätzliches super.img-Image, das direkt auf die Superpartition geflasht werden kann. Sie fasst automatisch die Inhalte logischer Partitionen zusammen. Das bedeutet, dass sie zusätzlich zu den super-Partitionsmetadaten system.img, vendor.img usw. enthält. Dieses Image kann direkt auf die super-Partition geflasht werden, ohne dass zusätzliche Tools oder fastbootd erforderlich sind. Nach dem Build wird super.img in ${ANDROID_PRODUCT_OUT} platziert.

Für A/B‑Geräte, die mit dynamischen Partitionen eingeführt werden, enthält super.img Bilder im A‑Slot. Nachdem Sie das Super-Image direkt geflasht haben, markieren Sie Slot A als bootfähig, bevor Sie das Gerät neu starten.

Für Geräte, die nachgerüstet werden, erstellt make dist eine Reihe von super_*.img-Images, die direkt auf die entsprechenden physischen Partitionen geflasht werden können. Wenn BOARD_SUPER_PARTITION_BLOCK_DEVICES beispielsweise der Systemanbieter ist, werden mit make dist die Builds super_system.img und super_vendor.img erstellt. Diese Bilder werden im OTA-Ordner in target_files.zip platziert.

Geräte-Mapper-Abstimmung für Speichergeräte

Die dynamische Partitionierung bietet Platz für eine Reihe von nicht deterministischen Device Mapper-Objekten. Möglicherweise werden nicht alle wie erwartet instanziiert. Sie müssen daher alle Mounts verfolgen und die Android-Attribute aller zugehörigen Partitionen mit den zugrunde liegenden Speichergeräten aktualisieren.

Ein Mechanismus in init verfolgt die Mounts und aktualisiert die Android-Properties asynchron. Es gibt keinen garantierten Zeitraum, in dem die Reaktion erfolgen muss. Sie müssen also genügend Zeit für alle on property-Trigger einplanen. Die Attribute sind dev.mnt.blk.<partition>, wobei <partition> beispielsweise root, system, data oder vendor ist. Jede Property ist dem Namen des zugrunde liegenden Speichergeräts zugeordnet, wie in diesen Beispielen gezeigt:

taimen:/ % getprop | grep dev.mnt.blk
[dev.mnt.blk.data]: [sda]
[dev.mnt.blk.firmware]: [sde]
[dev.mnt.blk.metadata]: [sde]
[dev.mnt.blk.persist]: [sda]
[dev.mnt.blk.root]: [dm-0]
[dev.mnt.blk.vendor]: [dm-1]

blueline:/ $ getprop | grep dev.mnt.blk
[dev.mnt.blk.data]: [dm-4]
[dev.mnt.blk.metadata]: [sda]
[dev.mnt.blk.mnt.scratch]: [sda]
[dev.mnt.blk.mnt.vendor.persist]: [sdf]
[dev.mnt.blk.product]: [dm-2]
[dev.mnt.blk.root]: [dm-0]
[dev.mnt.blk.system_ext]: [dm-3]
[dev.mnt.blk.vendor]: [dm-1]
[dev.mnt.blk.vendor.firmware_mnt]: [sda]

Mit der init.rc-Sprache können die Android-Attribute im Rahmen der Regeln erweitert werden. Speichergeräte können von der Plattform nach Bedarf mit Befehlen wie den folgenden optimiert werden:

write /sys/block/${dev.mnt.blk.root}/queue/read_ahead_kb 128
write /sys/block/${dev.mnt.blk.data}/queue/read_ahead_kb 128

Sobald die Befehlsverarbeitung in der zweiten Phase init beginnt, wird epoll loop aktiv und die Werte werden aktualisiert. Da Property-Trigger jedoch erst spät in der init aktiv werden, können sie in den ersten Boot-Phasen nicht verwendet werden, um root, system oder vendor zu verarbeiten. Die Kernel-Standardeinstellung read_ahead_kb sollte ausreichen, bis die init.rc-Scripts in early-fs überschrieben werden können (wenn verschiedene Daemons und Einrichtungen gestartet werden). Google empfiehlt daher, die Funktion on property in Kombination mit einer init.rc-gesteuerten Property wie sys.read_ahead_kb zu verwenden, um die Vorgänge zeitlich zu steuern und Race-Bedingungen zu vermeiden, wie in diesen Beispielen:

on property:dev.mnt.blk.root=* && property:sys.read_ahead_kb=*
    write /sys/block/${dev.mnt.blk.root}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048}

on property:dev.mnt.blk.system=* && property:sys.read_ahead_kb=*
    write /sys/block/${dev.mnt.blk.system}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048}

on property:dev.mnt.blk.vendor=* && property:sys.read_ahead_kb=*
    write /sys/block/${dev.mnt.blk.vendor}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048}

on property:dev.mnt.blk.product=* && property:sys.read_ahead_kb=*
    write /sys/block/${dev.mnt.blk.system_ext}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048}

on property:dev.mnt.blk.oem=* && property:sys.read_ahead_kb=*
    write /sys/block/${dev.mnt.blk.oem}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048}

on property:dev.mnt.blk.data=* && property:sys.read_ahead_kb=*
    write /sys/block/${dev.mnt.blk.data}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048}

on early-fs:
    setprop sys.read_ahead_kb ${ro.read_ahead_kb.boot:-2048}

on property:sys.boot_completed=1
   setprop sys.read_ahead_kb ${ro.read_ahead_kb.bootcomplete:-128}