Cómo implementar particiones dinámicas

La partición dinámica se implementa con el asignador de dispositivos dm-linear en el kernel de Linux. La partición super contiene metadatos que enumeran los nombres y rangos de bloques de cada partición dinámica en super. Durante la primera etapa de init, esta se analizan y validan los metadatos y se crean dispositivos de bloques virtuales representan cada partición dinámica.

Cuando se aplica una OTA, las particiones dinámicas se crean automáticamente cambiar su tamaño o borrarlo según sea necesario. Para los dispositivos A/B, hay dos copias de los metadatos y los cambios se aplican solo a la copia que representa el ranura de destino.

Debido a que las particiones dinámicas se implementan en el espacio del usuario, se necesitan por el bootloader no pueden ser dinámicas. Por ejemplo, boot, El bootloader lee dtbo y vbmeta. deben permanecer como particiones físicas.

Cada partición dinámica puede pertenecer a un grupo de actualización. Estos limitan el espacio máximo que pueden consumir las particiones de ese grupo. Por ejemplo, system y vendor pueden pertenecer a un que restringe el tamaño total de system y vendor

Cómo implementar particiones dinámicas en dispositivos nuevos

En esta sección, se explica cómo implementar particiones dinámicas en dispositivos nuevos lanzamiento con Android 10 y versiones posteriores. Para actualizar dispositivos existentes, consulta Cómo actualizar Android dispositivos.

Cambios en las particiones

Para los dispositivos que se lanzan con Android 10, crea una partición llamada super. El super que la partición controla las ranuras A/B internamente, por lo que los dispositivos A/B no necesitan particiones super_a y super_b separadas. Todas las particiones del AOSP de solo lectura que no use el bootloader deben Debe ser dinámico y debe quitarse de la tabla de particiones GUID (GPT). Las particiones específicas del proveedor no tienen que ser dinámicas y se pueden colocar en la etiqueta GPT.

Para estimar el tamaño de super, agrega los tamaños de que se borran de GPT. Para los dispositivos A/B, esta debe incluir el tamaño de ambas ranuras. En la figura 1, se muestra una tabla de particiones de ejemplo antes y después de convertirla en dinámica y particiones.

Diseño de tabla de particiones
Figura 1: Nuevo diseño de tabla de partición física cuando convertir a particiones dinámicas

Las particiones dinámicas compatibles son las siguientes:

  • Sistema
  • Proveedor
  • Producto
  • Extensión del sistema
  • ODM

En el caso de los dispositivos que se lanzan con Android 10, la opción de línea de comandos de kernel androidboot.super_partition debe estar vacío para que el comando sysprop El campo ro.boot.super_partition está vacío.

Alineación de particiones

El módulo asignador de dispositivos puede funcionar de manera menos eficiente si el La partición super no está alineada correctamente. El La partición super DEBE estar alineada con la E/S mínima. el tamaño de la solicitud según lo determinado por la capa de bloque. De forma predeterminada, el de compilación (a través de lpmake, que genera el super), asume que una alineación de 1 MiB es suficiente para cada partición dinámica. Sin embargo, los proveedores asegúrate de que la partición super esté alineada de forma correcta.

Puedes determinar el tamaño mínimo de solicitud de un dispositivo de almacenamiento en bloques inspeccionando sysfs. Por ejemplo:

# 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

Puedes verificar la alineación de la partición super en un de forma similar:

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

El desplazamiento de alineación DEBE ser 0.

Cambios en la configuración del dispositivo

Para habilitar la partición dinámica, agrega la siguiente marca en device.mk:

PRODUCT_USE_DYNAMIC_PARTITIONS := true

Cambios en la configuración de la placa

Debes configurar el tamaño de la partición super:

BOARD_SUPER_PARTITION_SIZE := <size-in-bytes>

En dispositivos A/B, el sistema de compilación arroja un error si el tamaño total de las imágenes de partición dinámica es más de la mitad del super el tamaño de la partición.

Puedes configurar la lista de particiones dinámicas de la siguiente manera. Para dispositivos con grupos de actualización, enumera los grupos en Variable BOARD_SUPER_PARTITION_GROUPS. El nombre de cada grupo luego tiene un BOARD_group_SIZE y la variable BOARD_group_PARTITION_LIST. En el caso de los dispositivos A/B, el tamaño máximo de un grupo debe abarcar solo una ranura, ya que los nombres de los grupos tienen un sufijo interno con ranuras.

Este es un dispositivo de ejemplo que coloca todas las particiones en un grupo Se llama 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

Este es un dispositivo de ejemplo en el que se ubican los servicios del sistema y del producto en group_foo, y vendor, product, y odm en 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
  • En el caso de los dispositivos de lanzamiento virtuales A/B, la suma de los tamaños máximos de todos los grupos debe ser como máximo:
    BOARD_SUPER_PARTITION_SIZE - sobrecarga
    Consulta Implementación de A/B virtual.
  • Para los dispositivos de lanzamiento A/B, la suma de los tamaños máximos de todos los grupos debe ser:
    BOARD_SUPER_PARTITION_SIZE / 2: sobrecarga
  • En el caso de los dispositivos que no son A/B y que se actualizan con el sistema A/B, la suma del máximo los tamaños de todos los grupos deben ser:
    BOARD_SUPER_PARTITION_SIZE: sobrecarga
  • En el momento de la compilación, la suma de los tamaños de las imágenes de cada partición de un grupo de actualización no debe exceder el tamaño máximo del grupo.
  • Se requiere sobrecarga en el procesamiento para tener en cuenta los metadatos, las alineaciones, etcétera. Una sobrecarga razonable es de 4 MiB, pero puede elegir una sobrecarga mayor según lo necesite el dispositivo.

Cómo establecer el tamaño de las particiones dinámicas

Antes de las particiones dinámicas, los tamaños de las particiones se asignaban en exceso a asegurarse de que tuvieran suficiente espacio para las actualizaciones futuras. El tamaño real se tomaron como están, y la mayoría de las particiones de solo lectura tenían cierta en su sistema de archivos. En las particiones dinámicas, ese espacio libre inutilizable y podría usarse para aumentar las particiones durante una actualización inalámbrica. Es fundamental asegurarse de que las particiones no desperdicien asignar a un tamaño mínimo posible.

Para las imágenes ext4 de solo lectura, el sistema de compilación asigna automáticamente el tamaño mínimo si no se especifica un tamaño de partición codificado El de compilación se ajusta a la imagen, por lo que el sistema de archivos tiene el menor espacio sin usar posible. Esto garantiza que el dispositivo no se desperdicie espacio que se puede usar para OTA.

Además, las imágenes ext4 se pueden comprimir aún más habilitando el uso de la anulación de duplicación a nivel. Para habilitar esto, usa la siguiente configuración:

BOARD_EXT4_SHARE_DUP_BLOCKS := true

Si la asignación automática de un tamaño mínimo de partición no es deseable, hay dos formas de controlar el tamaño de la partición. Puedes especificar cantidad mínima de espacio libre con BOARD_partitionIMAGE_PARTITION_RESERVED_SIZE, o puedes especificar BOARD_partitionIMAGE_PARTITION_SIZE para forzar particiones dinámicas a un tamaño específico. Ninguna de estas opciones es se recomienda, a menos que sea necesario.

Por ejemplo:

BOARD_PRODUCTIMAGE_PARTITION_RESERVED_SIZE := 52428800

Esto obliga al sistema de archivos de product.img a tener 50 MiB de espacio sin usar

Cambios de sistema como raíz

Los dispositivos que se lanzan con Android 10 no deben usar system-as-root.

Dispositivos con particiones dinámicas (ya sea que se lance con o se actualice particiones dinámicas) no deben usar system-as-root. El kernel de Linux no puede interpretar la partición super y, por lo tanto, no se puede activar system. system ahora es activado por init de primera etapa, que reside en el disco RAM.

No configures BOARD_BUILD_SYSTEM_ROOT_IMAGE. En Android 10, La marca BOARD_BUILD_SYSTEM_ROOT_IMAGE solo se usa para diferenciar si el sistema está activado por el kernel o por el init de primera etapa en ramdisk.

Establece BOARD_BUILD_SYSTEM_ROOT_IMAGE en true causa un error de compilación cuando PRODUCT_USE_DYNAMIC_PARTITIONS también es true.

Cuando BOARD_USES_RECOVERY_AS_BOOT se establece como verdadero, de recuperación se compila como boot.img, que contiene el archivo ramdisk Anteriormente, el bootloader usaba el kernel skip_initramfs. el parámetro de la línea de comandos para decidir en qué modo iniciar. Para En dispositivos con Android 10, el bootloader NO DEBE pasar skip_initramfs a la línea de comandos del kernel En su lugar, el bootloader debes pasar androidboot.force_normal_boot=1 para omitir la recuperación e iniciar Android normal. Dispositivos que se lanzan con Android 12 o una posterior, debe usar bootconfig para pasar androidboot.force_normal_boot=1.

Cambios en la configuración de AVB

Si usas Android Inicio verificado 2.0, si el dispositivo no usa una partición encadenada de Kubernetes, no es necesario realizar ningún cambio. Si se usan particiones verificadas y una de las que se verifica es dinámica, se necesitan cambios.

Esta es una configuración de ejemplo para un dispositivo que encadena vbmeta para system y vendor particiones.

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

Con esta configuración, el bootloader espera encontrar un vbmeta pie de página al final de system y vendor. Como estas particiones ya no son visibles para el bootloader (residen en super); dos se necesitan cambios.

  • Agrega vbmeta_system y vbmeta_vendor. particiones a la tabla de particiones del dispositivo. Para los dispositivos A/B, agrega vbmeta_system_a, vbmeta_system_b, vbmeta_vendor_a y vbmeta_vendor_b. Si agregar una o más de estas particiones, deberían tener el mismo tamaño como la partición vbmeta.
  • Para cambiar el nombre de las marcas de configuración, agrega VBMETA_ y especificar a qué particiones se extiende el encadenamiento:
    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 dispositivo puede usar una, ambas particiones o ninguna de estas. Cambios solo son necesarias cuando se encadenan a una partición lógica.

Cambios en el bootloader de AVB

Si el bootloader tiene libavb incorporado, incluye los siguientes parches:

Si usas particiones en cadena, incluye un parche adicional:

  • 49936b4c0109411fdd38bd4ba3a32a01c40439a9 — "libavb: Compatibilidad con BLOB vbmeta al comienzo de la partición".

Cambios en la línea de comandos del kernel

Se debe agregar un parámetro nuevo, androidboot.boot_devices. a la línea de comandos del kernel. init usa esta información para Habilita symlinks de /dev/block/by-name. Debe ser el componente de ruta de acceso del dispositivo al symlink por nombre subyacente creado por ueventd, es decir, /dev/block/platform/device-path/by-name/partition-name Los dispositivos que se lanzan con Android 12 o versiones posteriores deben usar bootconfig para pasar androidboot.boot_devices a init.

Por ejemplo, si el symlink de superpartición por nombre es /dev/block/platform/soc/100000.ufshc/by-name/super, puedes agregar el parámetro de línea de comandos en el archivo BoardConfig.mk como sigue:

BOARD_KERNEL_CMDLINE += androidboot.boot_devices=soc/100000.ufshc
Puedes agregar el parámetro bootconfig en el archivo BoardConfig.mk de la siguiente manera:
BOARD_BOOTCONFIG += androidboot.boot_devices=soc/100000.ufshc

cambios fstab

Las superposiciones del árbol de dispositivos y del árbol de dispositivos no deben incluir fstab de entradas de registro. Usa un archivo fstab que será parte del ramdisk.

Se deben realizar cambios en el archivo fstab para las particiones lógicas:

  • El campo de marcas fs_mgr debe incluir la marca logical y la marca first_stage_mount, que se introdujo en Android 10, que indica que una partición se se activará en la primera etapa.
  • Una partición puede especificar avb=vbmeta partition name como La marca fs_mgr y, luego, el vbmeta especificado la partición se inicializa en la primera etapa init antes intentar activar ningún dispositivo.
  • El campo dev debe ser el nombre de la partición.

Las siguientes entradas fstab establecen el sistema, el proveedor y el producto como lógicos particiones siguiendo las reglas anteriores.

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

Copia el archivo fstab en el ramdisk de la primera etapa.

Cambios de SELinux

El dispositivo de bloques de superpartición debe estar marcado con la etiqueta super_block_device Por ejemplo, si el symlink de superpartición por nombre es /dev/block/platform/soc/100000.ufshc/by-name/super, Agrega la siguiente línea a file_contexts:

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

inicio rápido

El bootloader (o cualquier herramienta de escritura en la memoria flash que no sea del espacio del usuario) no entienda particiones dinámicas, por lo que no puede escribirlas en la memoria flash. Para solucionar esto, los dispositivos debes usar una implementación en el espacio de usuario del protocolo fastboot, llamada fastbootd.

Si quieres obtener más información para implementar fastboot, consulta Cómo trasladar Fastboot al espacio del usuario.

Volver a activar adb

Para desarrolladores que usan compilaciones eng o userdebug, adb remount es extremadamente útil para lograr una iteración rápida. Las particiones dinámicas plantean problema para adb remount porque ya no hay espacio dentro de cada sistema de archivos. Para solucionar esto, los dispositivos pueden habilitar Overlayfs. Siempre que haya espacio libre dentro de la superpartición, adb remount crea automáticamente una dinámica temporal partición y usa superposicionesf para las escrituras. La partición temporal es llamado scratch, así que no uses este nombre para otras y particiones.

Para obtener más información acerca de cómo habilitar las superposiciones, consulta la documentación de overlayfs README en el AOSP.

Cómo actualizar dispositivos Android

Si actualizas un dispositivo a Android 10 incluir compatibilidad con particiones dinámicas en la OTA, no es necesario cambiar la tabla de partición integrada. Hay parámetros de configuración adicionales como en los productos necesarios.

Cambios en la configuración del dispositivo

Para actualizar la partición dinámica, agrega las siguientes marcas en device.mk:

PRODUCT_USE_DYNAMIC_PARTITIONS := true
PRODUCT_RETROFIT_DYNAMIC_PARTITIONS := true

Cambios en la configuración de la placa

Debes configurar las siguientes variables de la placa:

  • Establece BOARD_SUPER_PARTITION_BLOCK_DEVICES en la lista de dispositivos de almacenamiento en bloques que se usaron. para almacenar extensiones de particiones dinámicas. Esta es la lista de nombres de centros de datos particiones en el dispositivo.
  • Configura BOARD_SUPER_PARTITION_partition_DEVICE_SIZE en los tamaños de cada dispositivo de bloques en BOARD_SUPER_PARTITION_BLOCK_DEVICES, respectivamente. Esta es la lista de tamaños de particiones físicas existentes en el dispositivo. Por lo general, BOARD_partitionIMAGE_PARTITION_SIZE en el tablero existente parámetros de configuración.
  • Anular la configuración de BOARD_partitionIMAGE_PARTITION_SIZE existente para todos particiones en BOARD_SUPER_PARTITION_BLOCK_DEVICES.
  • Establece BOARD_SUPER_PARTITION_SIZE en la suma de BOARD_SUPER_PARTITION_partition_DEVICE_SIZE
  • Establece BOARD_SUPER_PARTITION_METADATA_DEVICE en el dispositivo de almacenamiento en bloques en el que y los metadatos de partición dinámica se almacenan. Debe ser uno de BOARD_SUPER_PARTITION_BLOCK_DEVICES Por lo general, este parámetro está configurado como system
  • Establecer BOARD_SUPER_PARTITION_GROUPS, BOARD_group_SIZE y BOARD_group_PARTITION_LIST, respectivamente. Consulta Cambios en la configuración de la placa en dispositivos nuevos para conocer los detalles.

Por ejemplo, si el dispositivo ya tiene particiones de sistema y proveedor, y quieres convertir a particiones dinámicas y agregar una nueva partición de producto durante la actualización. Configura la siguiente placa:

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

Cambios de SELinux

Los dispositivos de bloques de superpartición deben estar marcados con el atributo super_block_device_type Por ejemplo, si el dispositivo ya tiene particiones system y vendor, quieres usarlas como bloque para almacenar extensiones de particiones dinámicas y sus symlinks por nombre se marcan como 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

Luego, agrega la siguiente línea a device.te:

typeattribute system_block_device super_block_device_type;

Para otras configuraciones, consulta Cómo implementar particiones dinámicas en dispositivos nuevos.

Para obtener más información sobre las actualizaciones de Retrofit, consulta OTA para dispositivos A/B sin anuncios Particiones.

Imágenes de fábrica

Si un dispositivo es compatible con particiones dinámicas, evita usar fastboot del espacio de usuario para escribir en la memoria flash imágenes de fábrica, ya que el inicio en el espacio de usuario es más lento que otros métodos de escritura en la memoria flash.

Para solucionar esto, make dist ahora crea un Imagen super.img que se puede escribir en la memoria flash directamente en el super por cada partición. Empaqueta automáticamente los contenidos particiones, lo que significa que contiene system.img, vendor.img, etc., además de super en metadatos de particiones. Esta imagen se puede escribir directamente en la memoria flash del partición de super sin ninguna herramienta adicional ni uso fastbootd. Después de la compilación, super.img se coloca en ${ANDROID_PRODUCT_OUT}

Para los dispositivos A/B que se inician con particiones dinámicas, super.img contiene imágenes en el espacio A. Después de escribir en la memoria flash del dispositivo directamente a la superimagen, marca la ranura A como reiniciable antes de reiniciar el dispositivo.

Para los dispositivos de actualización, make dist crea un conjunto de super_*.img imágenes que se pueden escribir directamente en la memoria flash particiones físicas correspondientes. Por ejemplo, make dist. compilaciones super_system.img y super_vendor.img cuando BOARD_SUPER_PARTITION_BLOCK_DEVICES es el sistema con el proveedor de servicios en la nube. Estas imágenes se colocan en la carpeta OTA en target_files.zip

Ajuste de dispositivo de almacenamiento del asignador de dispositivos

La partición dinámica admite una serie de mapper de dispositivos no deterministas objetos. Es posible que no se creen instancias como se espera, por lo que debes hacer un seguimiento de todos y actualiza las propiedades de Android de todas las particiones asociadas con de sus dispositivos de almacenamiento subyacentes.

Un mecanismo dentro de init realiza un seguimiento de los montajes y de forma asíncrona. actualiza las propiedades de Android. No se garantiza la cantidad de tiempo que tomará este proceso. dentro de un período específico, por lo que se debe entregar para que reaccionen todos los activadores on property. Las propiedades son dev.mnt.blk.<partition> donde <partition> es root, system, data o vendor, por ejemplo. Cada propiedad se asocia con el nombre del dispositivo de almacenamiento base, como se muestra en estos ejemplos:

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]

El lenguaje init.rc permite que las propiedades de Android expandible como parte de las reglas, y la plataforma puede ajustar según sea necesario con comandos como los siguientes:

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

Una vez que se inicia el procesamiento de comandos en la segunda etapa init, el epoll loop se activa y los valores comienzan a actualizarse. Sin embargo, como los activadores de propiedad no están activos hasta tarde init, No se puede usar en las etapas iniciales de inicio para controlar root. system o vendor. Es de esperar read_ahead_kb predeterminado del kernel será suficiente hasta que Las secuencias de comandos init.rc pueden anularse en early-fs (cuando comienzan varios daemons e instalaciones). Por lo tanto, Google recomienda que usas la función on property, junto con un Una propiedad controlada por init.rc, como sys.read_ahead_kb, para manejar el tiempo de las operaciones y evitar condiciones de carrera, como en estas ejemplos:

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}