Implémenter des partitions dynamiques

Le partitionnement dynamique est implémenté à l'aide du module dm-linear device-mapper du noyau Linux. La super partition contient des métadonnées répertoriant les noms et les plages de blocs de chaque partition dynamique au sein super . Lors de la première étape init , ces métadonnées sont analysées et validées, et des périphériques de bloc virtuels sont créés pour représenter chaque partition dynamique.

Lors de l'application d'un OTA, les partitions dynamiques sont automatiquement créées, redimensionnées ou supprimées selon les besoins. Pour les appareils A/B, il existe deux copies des métadonnées et les modifications sont appliquées uniquement à la copie représentant l'emplacement cible.

Étant donné que les partitions dynamiques sont implémentées dans l'espace utilisateur, les partitions nécessaires au chargeur de démarrage ne peuvent pas être rendues dynamiques. Par exemple, boot , dtbo et vbmeta sont lus par le chargeur de démarrage et doivent donc rester sous forme de partitions physiques.

Chaque partition dynamique peut appartenir à un groupe de mise à jour . Ces groupes limitent l'espace maximum que les partitions de ce groupe peuvent consommer. Par exemple, system et vendor peuvent appartenir à un groupe qui restreint la taille totale du system et vendor .

Implémenter des partitions dynamiques sur les nouveaux appareils

Cette section explique comment implémenter des partitions dynamiques sur les nouveaux appareils lancés avec Android 10 et versions ultérieures. Pour mettre à jour les appareils existants, consultez Mise à niveau des appareils Android .

Modifications des partitions

Pour les appareils lancés avec Android 10, créez une partition appelée super . La super partition gère les emplacements A/B en interne, de sorte que les périphériques A/B n'ont pas besoin de partitions super_a et super_b séparées. Toutes les partitions AOSP en lecture seule qui ne sont pas utilisées par le chargeur de démarrage doivent être dynamiques et doivent être supprimées de la table de partition GUID (GPT). Les partitions spécifiques au fournisseur ne doivent pas nécessairement être dynamiques et peuvent être placées dans le GPT.

Pour estimer la taille de super , ajoutez les tailles des partitions supprimées du GPT. Pour les appareils A/B, cela doit inclure la taille des deux emplacements. La figure 1 montre un exemple de table de partition avant et après la conversion en partitions dynamiques.

Disposition des tables de partition
Figure 1. Nouvelle disposition de la table de partition physique lors de la conversion en partitions dynamiques

Les partitions dynamiques prises en charge sont :

  • Système
  • Fournisseur
  • Produit
  • Poste système
  • ODM

Pour les appareils lancés avec Android 10, l'option de ligne de commande du noyau androidboot.super_partition doit être vide afin que la commande sysprop ro.boot.super_partition soit vide.

Alignement des partitions

Le module de mappage de périphériques peut fonctionner moins efficacement si la super partition n'est pas correctement alignée. La super partition DOIT être alignée sur la taille minimale de demande d'E/S telle que déterminée par la couche bloc. Par défaut, le système de build (via lpmake , qui génère l'image de super partition), suppose qu'un alignement de 1 Mo est suffisant pour chaque partition dynamique. Cependant, les fournisseurs doivent s'assurer que la super partition est correctement alignée.

Vous pouvez déterminer la taille minimale de requête d'un périphérique bloc en inspectant sysfs . Par exemple:

# 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

Vous pouvez vérifier l'alignement de la super partition de la même manière :

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

Le décalage d'alignement DOIT être 0.

Modifications de la configuration de l'appareil

Pour activer le partitionnement dynamique, ajoutez l'indicateur suivant dans device.mk :

PRODUCT_USE_DYNAMIC_PARTITIONS := true

Modifications de la configuration de la carte

Vous devez définir la taille de la super partition :

BOARD_SUPER_PARTITION_SIZE := <size-in-bytes>

Sur les périphériques A/B, le système de build génère une erreur si la taille totale des images de partition dynamique est supérieure à la moitié de la taille de la super partition.

Vous pouvez configurer la liste des partitions dynamiques comme suit. Pour les appareils utilisant des groupes de mise à jour, répertoriez les groupes dans la variable BOARD_SUPER_PARTITION_GROUPS . Chaque nom de groupe a ensuite une variable BOARD_ group _SIZE et BOARD_ group _PARTITION_LIST . Pour les appareils A/B, la taille maximale d'un groupe ne doit couvrir qu'un seul emplacement, car les noms de groupe comportent un suffixe d'emplacement en interne.

Voici un exemple de périphérique qui place toutes les partitions dans un groupe appelé example_dynamic_partitions :

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

Voici un exemple de périphérique qui place les services système et produits dans group_foo , et vendor , product et odm dans group_bar :

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
  • Pour les appareils de lancement Virtual A/B, la somme des tailles maximales de tous les groupes doit être au maximum :
    BOARD_SUPER_PARTITION_SIZE – frais généraux
    Voir Implémentation de l'A/B virtuel .
  • Pour les appareils de lancement A/B, la somme des tailles maximales de tous les groupes doit être :
    BOARD_SUPER_PARTITION_SIZE / 2 - frais généraux
  • Pour les appareils non-A/B et les appareils A/B modernisés, la somme des tailles maximales de tous les groupes doit être :
    BOARD_SUPER_PARTITION_SIZE – frais généraux
  • Au moment de la construction, la somme des tailles des images de chaque partition d'un groupe de mise à jour ne doit pas dépasser la taille maximale du groupe.
  • Une surcharge est nécessaire dans le calcul pour tenir compte des métadonnées, des alignements, etc. Une surcharge raisonnable est de 4 Mio, mais vous pouvez choisir une surcharge plus importante selon les besoins de l'appareil.

Dimensionner les partitions dynamiques

Avant les partitions dynamiques, les tailles des partitions étaient suraffectées pour garantir qu'elles disposaient de suffisamment d'espace pour les futures mises à jour. La taille réelle a été prise telle quelle et la plupart des partitions en lecture seule disposaient d'une certaine quantité d'espace libre dans leur système de fichiers. Dans les partitions dynamiques, cet espace libre est inutilisable et pourrait être utilisé pour agrandir les partitions lors d'une OTA. Il est essentiel de s'assurer que les partitions ne gaspillent pas d'espace et sont allouées à une taille minimale possible.

Pour les images ext4 en lecture seule, le système de construction alloue automatiquement la taille minimale si aucune taille de partition codée en dur n'est spécifiée. Le système de construction s'adapte à l'image afin que le système de fichiers dispose du moins d'espace inutilisé possible. Cela garantit que l'appareil ne gaspille pas d'espace pouvant être utilisé pour les OTA.

De plus, les images ext4 peuvent être davantage compressées en activant la déduplication au niveau des blocs. Pour activer cela, utilisez la configuration suivante :

BOARD_EXT4_SHARE_DUP_BLOCKS := true

Si l'allocation automatique d'une taille minimale de partition n'est pas souhaitable, il existe deux manières de contrôler la taille de la partition. Vous pouvez spécifier une quantité minimale d'espace libre avec BOARD_ partition IMAGE_PARTITION_RESERVED_SIZE , ou vous pouvez spécifier BOARD_ partition IMAGE_PARTITION_SIZE pour forcer les partitions dynamiques à une taille spécifique. Aucune de ces solutions n’est recommandée, sauf si cela est nécessaire.

Par exemple:

BOARD_PRODUCTIMAGE_PARTITION_RESERVED_SIZE := 52428800

Cela force le système de fichiers dans product.img à disposer de 50 Mo d'espace inutilisé.

Modifications du système en tant que racine

Les appareils lancés avec Android 10 ne doivent pas utiliser le système en tant que root.

Les appareils dotés de partitions dynamiques (qu'ils soient lancés avec ou modernisés par des partitions dynamiques) ne doivent pas utiliser le système en tant que racine. Le noyau Linux ne peut pas interpréter la super partition et ne peut donc pas monter system lui-même. system est maintenant monté par init de première étape, qui réside dans le disque virtuel.

Ne définissez pas BOARD_BUILD_SYSTEM_ROOT_IMAGE . Dans Android 10, l'indicateur BOARD_BUILD_SYSTEM_ROOT_IMAGE est uniquement utilisé pour différencier si le système est monté par le noyau ou par l' init de première étape dans le disque virtuel.

La définition BOARD_BUILD_SYSTEM_ROOT_IMAGE sur true provoque une erreur de construction lorsque PRODUCT_USE_DYNAMIC_PARTITIONS est également true .

Lorsque BOARD_USES_RECOVERY_AS_BOOT est défini sur true, l'image de récupération est créée sous le nom boot.img, contenant le disque virtuel de récupération. Auparavant, le chargeur de démarrage utilisait le paramètre de ligne de commande du noyau skip_initramfs pour décider dans quel mode démarrer. Pour les appareils Android 10, le chargeur de démarrage NE DOIT PAS transmettre skip_initramfs à la ligne de commande du noyau. Au lieu de cela, le chargeur de démarrage doit transmettre androidboot.force_normal_boot=1 pour ignorer la récupération et démarrer Android normal. Les appareils lancés avec Android 12 ou version ultérieure doivent utiliser bootconfig pour transmettre androidboot.force_normal_boot=1 .

Modifications de la configuration AVB

Lorsque vous utilisez Android Verified Boot 2.0 , si l'appareil n'utilise pas de descripteurs de partition chaînés , aucune modification n'est nécessaire. Toutefois, si vous utilisez des partitions chaînées et que l'une des partitions vérifiées est dynamique, des modifications sont nécessaires.

Voici un exemple de configuration pour un périphérique qui chaîne vbmeta pour les partitions system et vendor .

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

Avec cette configuration, le chargeur de démarrage s'attend à trouver un pied de page vbmeta à la fin des partitions system et vendor . Étant donné que ces partitions ne sont plus visibles par le chargeur de démarrage (elles résident dans super ), deux modifications sont nécessaires.

  • Ajoutez les partitions vbmeta_system et vbmeta_vendor à la table de partition du périphérique. Pour les appareils A/B, ajoutez vbmeta_system_a , vbmeta_system_b , vbmeta_vendor_a et vbmeta_vendor_b . Si vous ajoutez une ou plusieurs de ces partitions, elles doivent avoir la même taille que la partition vbmeta .
  • Renommez les indicateurs de configuration en ajoutant VBMETA_ et spécifiez à quelles partitions le chaînage s'étend :
    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
    

Un périphérique peut utiliser l'une de ces partitions, les deux ou aucune. Les modifications sont nécessaires uniquement lors du chaînage à une partition logique.

Modifications du chargeur de démarrage AVB

Si le chargeur de démarrage a intégré libavb , incluez les correctifs suivants :

Si vous utilisez des partitions chaînées, incluez un correctif supplémentaire :

  • 49936b4c0109411fdd38bd4ba3a32a01c40439a9 — "libavb : prise en charge des blobs vbmeta au début de la partition."

Modifications de la ligne de commande du noyau

Un nouveau paramètre, androidboot.boot_devices , doit être ajouté à la ligne de commande du noyau. Ceci est utilisé par init pour activer les liens /dev/block/by-name . Il doit s'agir du composant de chemin de périphérique vers le lien symbolique sous-jacent par nom créé par ueventd , c'est-à-dire /dev/block/platform/ device-path /by-name/ partition-name . Les appareils lancés avec Android 12 ou version ultérieure doivent utiliser bootconfig pour transmettre androidboot.boot_devices à init .

Par exemple, si le lien symbolique par nom de super partition est /dev/block/platform/ soc/100000.ufshc /by-name/super , vous pouvez ajouter le paramètre de ligne de commande dans le fichier BoardConfig.mk comme suit :

BOARD_KERNEL_CMDLINE += androidboot.boot_devices=soc/100000.ufshc
Vous pouvez ajouter le paramètre bootconfig dans le fichier BoardConfig.mk comme suit :
BOARD_BOOTCONFIG += androidboot.boot_devices=soc/100000.ufshc

changements fstab

L'arborescence des périphériques et les superpositions de l'arborescence des périphériques ne doivent pas contenir d'entrées fstab. Utilisez un fichier fstab qui fera partie du disque virtuel.

Des modifications doivent être apportées au fichier fstab pour les partitions logiques :

  • Le champ fs_mgr flags doit inclure l'indicateur logical et l'indicateur first_stage_mount , introduits dans Android 10, qui indiquent qu'une partition doit être montée dans la première étape.
  • Une partition peut spécifier avb= vbmeta partition name comme indicateur fs_mgr , puis la partition vbmeta spécifiée est initialisée par la première étape init avant de tenter de monter des périphériques.
  • Le champ dev doit être le nom de la partition.

Les entrées fstab suivantes définissent le système, le fournisseur et le produit comme partitions logiques suivant les règles ci-dessus.

#<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

Copiez le fichier fstab dans le disque virtuel de première étape.

Modifications de SELinux

Le périphérique de bloc de super partition doit être marqué avec l'étiquette super_block_device . Par exemple, si le lien symbolique par nom de super partition est /dev/block/platform/ soc/100000.ufshc /by-name/super , ajoutez la ligne suivante à file_contexts :

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

démarrage rapide

Le chargeur de démarrage (ou tout outil de flashage non-utilisateur) ne comprend pas les partitions dynamiques, il ne peut donc pas les flasher. Pour résoudre ce problème, les appareils doivent utiliser une implémentation dans l’espace utilisateur du protocole fastboot, appelée fastbootd.

Pour plus d'informations sur la façon d'implémenter fastbootd, consultez Déplacement de Fastboot vers l'espace utilisateur .

remontage de la BAD

Pour les développeurs utilisant des versions eng ou userdebug, adb remount est extrêmement utile pour une itération rapide. Les partitions dynamiques posent un problème pour adb remount car il n'y a plus d'espace libre dans chaque système de fichiers. Pour résoudre ce problème, les appareils peuvent activer les superpositions. Tant qu'il y a de l'espace libre dans la super partition, adb remount crée automatiquement une partition dynamique temporaire et utilise overlayfs pour les écritures. La partition temporaire est nommée scratch , n'utilisez donc pas ce nom pour d'autres partitions.

Pour plus d'informations sur la façon d'activer overlayfs, consultez le README overlayfs dans AOSP.

Mettre à niveau les appareils Android

Si vous mettez à niveau un appareil vers Android 10 et souhaitez inclure la prise en charge des partitions dynamiques dans l'OTA, vous n'avez pas besoin de modifier la table de partition intégrée. Une configuration supplémentaire est requise.

Modifications de la configuration de l'appareil

Pour moderniser le partitionnement dynamique, ajoutez les indicateurs suivants dans device.mk :

PRODUCT_USE_DYNAMIC_PARTITIONS := true
PRODUCT_RETROFIT_DYNAMIC_PARTITIONS := true

Modifications de la configuration de la carte

Vous devez définir les variables de tableau suivantes :

  • Définissez BOARD_SUPER_PARTITION_BLOCK_DEVICES sur la liste des périphériques de bloc utilisés pour stocker les extensions de partitions dynamiques. Il s'agit de la liste des noms des partitions physiques existantes sur le périphérique.
  • Définissez BOARD_SUPER_PARTITION_ partition _DEVICE_SIZE sur les tailles de chaque périphérique bloc dans BOARD_SUPER_PARTITION_BLOCK_DEVICES , respectivement. Il s'agit de la liste des tailles des partitions physiques existantes sur le périphérique. Il s'agit généralement BOARD_ partition IMAGE_PARTITION_SIZE dans les configurations de carte existantes.
  • Supprimez BOARD_ partition IMAGE_PARTITION_SIZE existante pour toutes les partitions de BOARD_SUPER_PARTITION_BLOCK_DEVICES .
  • Définissez BOARD_SUPER_PARTITION_SIZE sur la somme de BOARD_SUPER_PARTITION_ partition _DEVICE_SIZE .
  • Définissez BOARD_SUPER_PARTITION_METADATA_DEVICE sur le périphérique de bloc où les métadonnées de partition dynamique sont stockées. Il doit s'agir de l'un des BOARD_SUPER_PARTITION_BLOCK_DEVICES . Habituellement, cela est défini sur system .
  • Définissez respectivement BOARD_SUPER_PARTITION_GROUPS , BOARD_ group _SIZE et BOARD_ group _PARTITION_LIST . Voir Modifications de la configuration de la carte sur les nouveaux appareils pour plus de détails.

Par exemple, si l'appareil dispose déjà de partitions système et fournisseur et que vous souhaitez les convertir en partitions dynamiques et ajouter une nouvelle partition produit lors de la mise à jour, définissez cette configuration de carte :

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

Modifications de SELinux

Les périphériques de bloc de super partition doivent être marqués avec l'attribut super_block_device_type . Par exemple, si le périphérique possède déjà des partitions system et vendor , vous souhaitez les utiliser comme périphériques de bloc pour stocker des extensions de partitions dynamiques, et leurs liens symboliques par nom sont marqués comme system_block_device :

/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

Ensuite, ajoutez la ligne suivante à device.te :

typeattribute system_block_device super_block_device_type;

Pour d'autres configurations, consultez Implémentation de partitions dynamiques sur de nouveaux appareils .

Pour plus d'informations sur les mises à jour de mise à niveau, consultez OTA pour les appareils A/B sans partitions dynamiques .

Images d'usine

Pour un périphérique lancé avec prise en charge des partitions dynamiques, évitez d'utiliser le démarrage rapide de l'espace utilisateur pour flasher les images d'usine, car le démarrage dans l'espace utilisateur est plus lent que les autres méthodes de flashage.

Pour résoudre ce problème, make dist crée désormais une image super.img supplémentaire qui peut être flashée directement sur la super partition. Il regroupe automatiquement le contenu des partitions logiques, ce qui signifie qu'il contient system.img , vendor.img , etc., en plus des métadonnées de la super partition. Cette image peut être flashée directement sur la super partition sans aucun outil supplémentaire ni utilisation de fastbootd. Après la construction, super.img est placé dans ${ANDROID_PRODUCT_OUT} .

Pour les appareils A/B qui se lancent avec des partitions dynamiques, super.img contient des images dans l'emplacement A. Après avoir flashé directement la super image, marquez l'emplacement A comme amorçable avant de redémarrer l'appareil.

Pour les appareils de mise à niveau, make dist crée un ensemble d'images super_*.img qui peuvent être flashées directement sur les partitions physiques correspondantes. Par exemple, make dist builds super_system.img et super_vendor.img lorsque BOARD_SUPER_PARTITION_BLOCK_DEVICES est le fournisseur du système. Ces images sont placées dans le dossier OTA dans target_files.zip .

Réglage des périphériques de stockage du mappeur de périphériques

Le partitionnement dynamique prend en charge un certain nombre d'objets de mappage de périphériques non déterministes. Ceux-ci peuvent ne pas tous être instanciés comme prévu, vous devez donc suivre tous les montages et mettre à jour les propriétés Android de toutes les partitions associées avec leurs périphériques de stockage sous-jacents.

Un mécanisme à l'intérieur init suit les montages et met à jour de manière asynchrone les propriétés Android. Il n'est pas garanti que le temps que cela prendra se situe dans une période spécifique, vous devez donc prévoir suffisamment de temps pour que tous les déclencheurs on property réagissent. Les propriétés sont dev.mnt.blk. <partition><partition> est root , system , data ou vendor , par exemple. Chaque propriété est associée au nom du périphérique de stockage de base, comme indiqué dans ces exemples :

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]

Le langage init.rc permet d'étendre les propriétés Android dans le cadre des règles, et les périphériques de stockage peuvent être réglés par la plate-forme selon les besoins avec des commandes comme celles-ci :

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

Une fois que le traitement des commandes démarre lors de la deuxième étape init , la epoll loop devient active et les valeurs commencent à se mettre à jour. Cependant, comme les déclencheurs de propriété ne sont actifs qu'à la fin de init , ils ne peuvent pas être utilisés lors des étapes de démarrage initiales pour gérer root , system ou vendor . Vous pouvez vous attendre à ce que la valeur par défaut read_ahead_kb du noyau soit suffisante jusqu'à ce que les scripts init.rc puissent être remplacés dans early-fs (lorsque divers démons et fonctionnalités démarrent). Par conséquent, Google vous recommande d'utiliser la fonctionnalité on property , associée à une propriété contrôlée init.rc comme sys.read_ahead_kb , pour gérer la synchronisation des opérations et éviter les conditions de concurrence, comme dans ces exemples :

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}