Implementieren Sie dynamische Partitionen

Die dynamische Partitionierung wird mithilfe des dm-linearen Device-Mapper-Moduls im Linux-Kernel implementiert. Die super Partition enthält Metadaten, die die Namen und Blockbereiche jeder dynamischen Partition innerhalb von super auflisten. Während der ersten Stufe init werden diese Metadaten analysiert und validiert, und es werden virtuelle Blockgeräte erstellt, um jede dynamische Partition darzustellen.

Bei der Anwendung eines OTA werden dynamische Partitionen je nach Bedarf automatisch erstellt, in der Größe geändert oder gelöscht. Für A/B-Geräte gibt es zwei Kopien der Metadaten und Änderungen werden nur auf die Kopie angewendet, die den Zielslot darstellt.

Da dynamische Partitionen im Userspace implementiert sind, können vom Bootloader benötigte Partitionen nicht dynamisch gemacht werden. Beispielsweise werden boot , dtbo und vbmeta vom Bootloader gelesen und müssen daher als physische Partitionen verbleiben.

Jede dynamische Partition kann zu einer Update-Gruppe 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.

Implementieren Sie dynamische Partitionen auf neuen Geräten

In diesem Abschnitt erfahren Sie, wie Sie dynamische Partitionen auf neuen Geräten implementieren, die mit Android 10 und höher starten. Informationen zum Aktualisieren vorhandener Geräte finden Sie unter Aktualisieren von Android-Geräten .

Partitionsänderungen

Erstellen Sie für Geräte, die mit Android 10 starten, eine Partition mit dem Namen super . Die super verwaltet die A/B-Steckplätze intern, sodass A/B-Geräte keine separaten super_a und super_b Partitionen 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 im GPT platziert werden.

Um die Größe von super abzuschätzen, addieren Sie die Größen der Partitionen, die aus dem GPT gelöscht werden. Bei A/B-Geräten sollte dies die Größe beider Steckplätze umfassen. Abbildung 1 zeigt eine Beispielpartitionstabelle vor und nach der Konvertierung in dynamische Partitionen.

Layout der Partitionstabelle
Abbildung 1. Neues Layout der physischen Partitionstabelle bei der Konvertierung in dynamische Partitionen

Die unterstützten dynamischen Partitionen sind:

  • System
  • Verkäufer
  • Produkt
  • System-Ext
  • ODM

Bei Geräten, die mit Android 10 gestartet werden, muss die Kernel-Befehlszeilenoption androidboot.super_partition leer sein, damit der Befehl sysprop ro.boot.super_partition leer ist.

Partitionsausrichtung

Das Device-Mapper-Modul arbeitet möglicherweise weniger effizient, wenn die super nicht richtig ausgerichtet ist. Die super MUSS auf die minimale E/A-Anforderungsgröße ausgerichtet sein, die von der Blockschicht festgelegt 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 ausreichend ist. Allerdings sollten Anbieter sicherstellen, dass die super richtig ausgerichtet ist.

Sie können die minimale Anforderungsgröße eines Blockgeräts ermitteln, indem Sie sysfs überprüfen. Zum 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 auf ähnliche Weise überprüfen:

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

Der Ausrichtungsoffset MUSS 0 sein.

Änderungen der Gerätekonfiguration

Um die dynamische Partitionierung zu aktivieren, fügen Sie das folgende Flag in device.mk hinzu:

PRODUCT_USE_DYNAMIC_PARTITIONS := true

Änderungen an der Platinenkonfiguration

Sie müssen die Größe der super 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 Partitionsbilder mehr als die Hälfte der super beträgt.

Sie können die Liste der dynamischen Partitionen wie folgt konfigurieren. Listen Sie für Geräte, die Aktualisierungsgruppen verwenden, die Gruppen in der Variablen BOARD_SUPER_PARTITION_GROUPS auf. Jeder Gruppenname verfügt dann über eine BOARD_ group _SIZE und BOARD_ group _PARTITION_LIST . Bei A/B-Geräten sollte die maximale Größe einer Gruppe nur einen Steckplatz abdecken, da die Gruppennamen intern mit einem Steckplatzsuffix versehen sind.

Hier ist ein Beispielgerät, das alle Partitionen in einer Gruppe namens example_dynamic_partitions ablegt:

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, das System- und Produktdienste in group_foo und vendor , product “ und odm in group_bar platziert:

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
  • Für virtuelle A/B-Startgeräte darf die Summe der maximalen Größen aller Gruppen höchstens betragen:
    BOARD_SUPER_PARTITION_SIZE – Overhead
    Siehe Implementierung von Virtual A/B .
  • Für A/B-Startgeräte muss die Summe der maximalen Größen aller Gruppen sein:
    BOARD_SUPER_PARTITION_SIZE / 2 - Overhead
  • Für Nicht-A/B-Geräte und Nachrüst-A/B-Geräte muss die Summe der maximalen Größen aller Gruppen sein:
    BOARD_SUPER_PARTITION_SIZE – Overhead
  • Zum Zeitpunkt der Erstellung darf die Summe der Größen der Images jeder Partition in einer Update-Gruppe die maximale Größe der Gruppe nicht überschreiten.
  • Bei der Berechnung ist ein Mehraufwand erforderlich, um Metadaten, Ausrichtungen usw. zu berücksichtigen. Ein angemessener Overhead beträgt 4 MiB, Sie können jedoch je nach Bedarf des Geräts einen größeren Overhead auswählen.

Größe dynamischer Partitionen

Vor dynamischen Partitionen wurden die Partitionsgrößen überbelegt, um sicherzustellen, dass sie genügend Platz für zukünftige Updates hatten. Die tatsächliche Größe wurde unverändert übernommen und die meisten schreibgeschützten Partitionen verfügten über etwas freien Speicherplatz in ihrem Dateisystem. In dynamischen Partitionen ist dieser freie Speicherplatz unbrauchbar und könnte zum Erweitern von Partitionen während eines OTA verwendet werden. Es ist wichtig, sicherzustellen, dass Partitionen keinen Speicherplatz verschwenden und einer möglichst geringen Größe zugewiesen werden.

Für schreibgeschützte 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 Platz hat. Dadurch wird sichergestellt, dass das Gerät keinen Platz verschwendet, der für OTAs genutzt werden kann.

Darüber hinaus können ext4-Images durch die Aktivierung der Deduplizierung auf Blockebene weiter komprimiert werden. Um dies zu aktivieren, verwenden Sie die folgende Konfiguration:

BOARD_EXT4_SHARE_DUP_BLOCKS := true

Wenn die automatische Zuweisung der Mindestgröße einer Partition unerwünscht ist, gibt es zwei Möglichkeiten, die Partitionsgröße zu steuern. Sie können mit BOARD_ partition IMAGE_PARTITION_RESERVED_SIZE eine Mindestmenge an freiem Speicherplatz angeben oder Sie können BOARD_ partition IMAGE_PARTITION_SIZE angeben, um dynamische Partitionen auf eine bestimmte Größe zu erzwingen. Keines davon wird empfohlen, es sei denn, es ist notwendig.

Zum Beispiel:

BOARD_PRODUCTIMAGE_PARTITION_RESERVED_SIZE := 52428800

Dies zwingt das Dateisystem in product.img dazu, über 50 MiB ungenutzten Speicherplatz zu verfügen.

System-als-Root-Änderungen

Geräte, die mit Android 10 gestartet werden, dürfen nicht „System-as-Root“ verwenden.

Geräte mit dynamischen Partitionen (unabhängig davon, ob sie mit dynamischen Partitionen gestartet oder nachgerüstet werden) dürfen kein System-als-Root verwenden. Der Linux-Kernel kann die super nicht interpretieren und daher system selbst nicht mounten. system wird nun durch die erste Stufe init gemountet, die sich auf der Ramdisk 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 init -Stufe in der Ramdisk gemountet wird.

Das Festlegen BOARD_BUILD_SYSTEM_ROOT_IMAGE auf true führt zu einem Buildfehler, wenn PRODUCT_USE_DYNAMIC_PARTITIONS ebenfalls true ist.

Wenn BOARD_USES_RECOVERY_AS_BOOT auf „true“ gesetzt ist, wird das Wiederherstellungsabbild als boot.img erstellt, das die Ramdisk der Wiederherstellung enthält. Bisher verwendete der Bootloader den Kernel-Befehlszeilenparameter skip_initramfs , um zu entscheiden, in welchem ​​Modus gebootet werden soll. Bei Android 10-Geräten 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. Geräte, die mit Android 12 oder höher gestartet werden, müssen bootconfig verwenden, um androidboot.force_normal_boot=1 zu übergeben.

AVB-Konfigurationsänderungen

Wenn das Gerät bei Verwendung von Android Verified Boot 2.0 keine verketteten Partitionsdeskriptoren verwendet, ist keine Änderung erforderlich. Wenn jedoch verkettete Partitionen verwendet werden und eine der überprüften Partitionen dynamisch ist, sind Änderungen erforderlich.

Hier ist eine Beispielkonfiguration für ein Gerät, das vbmeta für die 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, am Ende der system und vendor eine vbmeta-Fußzeile zu finden. Da diese Partitionen für den Bootloader nicht mehr sichtbar sind (sie befinden sich in super ), sind zwei Änderungen erforderlich.

  • Fügen Sie die Partitionen vbmeta_system und vbmeta_vendor zur Partitionstabelle des Geräts 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 diese dieselbe Größe wie die vbmeta Partition haben.
  • Benennen Sie die Konfigurationsflags 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 bei der Verkettung mit einer logischen Partition erforderlich.

Änderungen am AVB-Bootloader

Wenn der Bootloader libavb eingebettet hat, schließen Sie die folgenden Patches ein:

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

  • 49936b4c0109411fdd38bd4ba3a32a01c40439a9 – „libavb: Unterstützt vbmeta-Blobs am Anfang der Partition.“

Änderungen an der Kernel-Befehlszeile

Ein neuer Parameter, androidboot.boot_devices , muss zur Kernel-Befehlszeile hinzugefügt werden. Dies wird von init verwendet, um /dev/block/by-name -Symlinks zu aktivieren. Es sollte die Gerätepfadkomponente zum zugrunde liegenden By-Name-Symlink sein, der von ueventd erstellt wurde, /dev/block/platform/ device-path /by-name/ partition-name . Geräte, die mit Android 12 oder höher gestartet werden, müssen bootconfig verwenden, um androidboot.boot_devices an init zu übergeben.

Wenn der Symlink für den Superpartitionsnamen beispielsweise /dev/block/platform/ soc/100000.ufshc /by-name/super lautet, können Sie den Befehlszeilenparameter wie folgt in die Datei BoardConfig.mk einfügen:

BOARD_KERNEL_CMDLINE += androidboot.boot_devices=soc/100000.ufshc
Sie können den Bootconfig-Parameter wie folgt in die Datei BoardConfig.mk einfügen:
BOARD_BOOTCONFIG += androidboot.boot_devices=soc/100000.ufshc

fstab ändert sich

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

Für logische Partitionen müssen Änderungen an der fstab-Datei vorgenommen werden:

  • Das Feld „fs_mgr flags“ muss das logical Flag und das in Android 10 eingeführte Flag first_stage_mount “ enthalten, das angibt, dass eine Partition in der ersten Stufe gemountet werden soll.
  • Eine Partition kann avb= vbmeta partition name als fs_mgr Flag angeben und dann wird die angegebene vbmeta Partition durch die erste init Stufe initialisiert, bevor versucht wird, Geräte zu mounten.
  • Das dev Feld muss der Partitionsname sein.

Die folgenden fstab-Einträge legen System, Hersteller und Produkt 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 Stufe.

SELinux-Änderungen

Das Superpartitionsblockgerät muss mit der Bezeichnung super_block_device gekennzeichnet sein. Wenn der Symlink für den Superpartitionsnamen beispielsweise /dev/block/platform/ soc/100000.ufshc /by-name/super lautet, fügen Sie die folgende Zeile zu file_contexts 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 zum Userspace gehört) versteht dynamische Partitionen nicht und kann sie daher nicht flashen. Um dieses Problem zu lösen, 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 User Space verschieben .

ADB-Remount

Für Entwickler, die eng- oder userdebug-Builds verwenden, ist adb remount für eine schnelle Iteration äußerst nützlich. Dynamische Partitionen stellen beim adb remount ein Problem dar, da in jedem Dateisystem nicht mehr freier Speicherplatz 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 trägt den Namen „ scratch , also verwenden Sie diesen Namen nicht für andere Partitionen.

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

Aktualisieren Sie Android-Geräte

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

Änderungen der Gerätekonfiguration

Um die dynamische Partitionierung nachzurüsten, fügen Sie die folgenden Flags in device.mk hinzu:

PRODUCT_USE_DYNAMIC_PARTITIONS := true
PRODUCT_RETROFIT_DYNAMIC_PARTITIONS := true

Änderungen an der Platinenkonfiguration

Sie müssen die folgenden Board-Variablen festlegen:

  • Setzen Sie BOARD_SUPER_PARTITION_BLOCK_DEVICES auf die Liste der Blockgeräte, die zum Speichern von Bereichen dynamischer Partitionen verwendet werden. Dies ist die Liste der Namen vorhandener physischer Partitionen auf dem Gerät.
  • Stellen Sie BOARD_SUPER_PARTITION_ partition _DEVICE_SIZE jeweils auf die Größe jedes Blockgeräts in BOARD_SUPER_PARTITION_BLOCK_DEVICES ein. Dies ist die Liste der Größen vorhandener physischer Partitionen auf dem Gerät. In vorhandenen Board-Konfigurationen ist dies normalerweise BOARD_ partition IMAGE_PARTITION_SIZE .
  • Setzen Sie die vorhandene BOARD_ partition IMAGE_PARTITION_SIZE für alle Partitionen in BOARD_SUPER_PARTITION_BLOCK_DEVICES zurück.
  • 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 dynamische Partitionsmetadaten gespeichert sind. Es muss eines von BOARD_SUPER_PARTITION_BLOCK_DEVICES sein. Normalerweise ist dies auf system eingestellt.
  • Legen Sie BOARD_SUPER_PARTITION_GROUPS , BOARD_ group _SIZE bzw. BOARD_ group _PARTITION_LIST fest. Weitere Informationen finden Sie unter „Änderungen der Platinenkonfiguration bei neuen Geräten“ .

Wenn das Gerät beispielsweise bereits über System- und Herstellerpartitionen verfügt und Sie diese während des Updates in dynamische Partitionen umwandeln und eine neue Produktpartition hinzufügen möchten, legen Sie diese Platinenkonfiguration 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 Superpartitionsblockgeräte müssen mit dem Attribut super_block_device_type gekennzeichnet sein. Wenn das Gerät beispielsweise bereits über system und vendor verfügt, möchten Sie diese als Blockgeräte verwenden, um Bereiche dynamischer Partitionen zu speichern, und ihre symbolischen Links nach Namen werden als system_block_device markiert:

/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;

Weitere Konfigurationen finden Sie unter Implementieren dynamischer Partitionen auf neuen Geräten .

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

Fabrikbilder

Vermeiden Sie bei einem Gerätestart mit Unterstützung für dynamische Partitionen die Verwendung von Userspace-Fastboot zum Flashen von Factory-Images, da das Booten in den Userspace langsamer ist als bei anderen 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. Es bündelt automatisch den Inhalt logischer Partitionen, d. h. es enthält zusätzlich zu den super system.img , vendor.img usw. Dieses Image kann ohne zusätzliche Tools oder die Verwendung von fastbootd direkt auf die super geflasht werden. Nach dem Build wird super.img in ${ANDROID_PRODUCT_OUT} platziert.

Bei A/B-Geräten, die mit dynamischen Partitionen starten, enthält super.img Bilder im A-Slot. Nachdem Sie das Super-Image direkt geflasht haben, markieren Sie Steckplatz A als bootfähig, bevor Sie das Gerät neu starten.

Für Nachrüstgeräte erstellt make dist einen Satz super_*.img Images, die direkt auf die entsprechenden physischen Partitionen geflasht werden können. Beispielsweise erstellt make dist super_system.img und super_vendor.img , wenn BOARD_SUPER_PARTITION_BLOCK_DEVICES der Systemanbieter ist. Diese Bilder werden im OTA-Ordner in target_files.zip abgelegt.

Optimierung des Device Mapper-Speichergeräts

Die dynamische Partitionierung berücksichtigt eine Reihe nichtdeterministischer Device-Mapper-Objekte. Da diese möglicherweise nicht alle wie erwartet instanziiert werden, müssen Sie alle Bereitstellungen verfolgen und die Android-Eigenschaften aller zugehörigen Partitionen mit den zugrunde liegenden Speichergeräten aktualisieren.

Ein Mechanismus in init verfolgt die Bereitstellungen und aktualisiert die Android-Eigenschaften asynchron. Es kann nicht garantiert werden, dass dies innerhalb eines bestimmten Zeitraums dauert. Sie müssen daher genügend Zeit einplanen, damit alle Auslöser on property reagieren können. Die Eigenschaften sind dev.mnt.blk. <partition> wobei <partition> beispielsweise root , system , data oder vendor ist. Jede Eigenschaft ist mit dem Namen des Basisspeichergeräts verknüpft, wie in den folgenden 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 Sprache init.rc können die Android-Eigenschaften im Rahmen der Regeln erweitert werden, und Speichergeräte können von der Plattform nach Bedarf mit Befehlen wie diesen 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 Stufe init beginnt, wird die epoll loop aktiv und die Werte werden aktualisiert. Da Eigenschaftsauslöser jedoch erst in der Late- init aktiv sind, können sie in den ersten Startphasen nicht zur Verarbeitung root , system oder vendor verwendet werden. Sie können davon ausgehen, dass die Kernel-Standardeinstellung read_ahead_kb ausreicht, bis die init.rc Skripte in early-fs überschreiben können (wenn verschiedene Daemons und Einrichtungen gestartet werden). Daher empfiehlt Google, dass Sie die on property Funktion in Verbindung mit einer init.rc -gesteuerten Eigenschaft wie sys.read_ahead_kb verwenden, um das Timing der Vorgänge zu steuern und Race Conditions zu verhindern, wie in den folgenden 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}