Triển khai phân vùng động

Quá trình phân vùng động được triển khai bằng cách sử dụng mô-đun trình ánh xạ thiết bị dm-linear trong nhân Linux. Phân vùng super chứa siêu dữ liệu liệt kê tên và phạm vi khối của từng phân vùng động trong super. Trong init giai đoạn đầu, siêu dữ liệu này được phân tích cú pháp và xác thực, đồng thời các thiết bị khối ảo được tạo để đại diện cho từng phân vùng động.

Khi áp dụng OTA, các phân vùng động sẽ tự động được tạo, đổi kích thước hoặc xoá nếu cần. Đối với thiết bị A/B, có hai bản sao siêu dữ liệu và các thay đổi chỉ được áp dụng cho bản sao đại diện cho khung mục tiêu.

Vì các phân vùng động được triển khai trong không gian người dùng, nên các phân vùng mà trình tải khởi động cần đến không thể được tạo động. Ví dụ: boot, dtbovbmeta được trình tải khởi động đọc và do đó phải vẫn là các phân vùng vật lý.

Mỗi phân vùng động có thể thuộc về một nhóm cập nhật. Các nhóm này giới hạn dung lượng tối đa mà các phân vùng trong nhóm đó có thể sử dụng. Ví dụ: systemvendor có thể thuộc một nhóm hạn chế tổng kích thước của systemvendor.

Triển khai các phân vùng động trên thiết bị mới

Phần này trình bày chi tiết cách triển khai các phân vùng động trên các thiết bị mới chạy Android 10 trở lên. Để cập nhật các thiết bị hiện có, hãy xem phần Nâng cấp thiết bị Android.

Thay đổi về phân vùng

Đối với các thiết bị chạy Android 10, hãy tạo một phân vùng có tên super. Phân vùng super xử lý các khe A/B trong nội bộ, vì vậy, các thiết bị A/B không cần phân vùng super_asuper_b riêng biệt. Tất cả các phân vùng AOSP chỉ có thể đọc mà trình tải khởi động không sử dụng phải là phân vùng động và phải được xoá khỏi Bảng phân vùng GUID (GPT). Các phân vùng dành riêng cho nhà cung cấp không nhất thiết phải là phân vùng động và có thể được đặt trong GPT.

Để ước tính kích thước của super, hãy thêm kích thước của các phân vùng đang bị xoá khỏi GPT. Đối với thiết bị A/B, kích thước này phải bao gồm kích thước của cả hai khe. Hình 1 cho thấy một ví dụ về bảng phân vùng trước và sau khi chuyển đổi sang phân vùng động.

Bố cục bảng phân vùng
Hình 1. Bố cục bảng phân vùng vật lý mới khi chuyển đổi sang phân vùng động

Các phân vùng động được hỗ trợ là:

  • Hệ thống
  • Nhà cung cấp
  • Sản phẩm
  • Tiện ích hệ thống
  • ODM

Đối với các thiết bị chạy Android 10, tuỳ chọn dòng lệnh hạt nhân androidboot.super_partition phải trống để lệnh sysprop ro.boot.super_partition trống.

Căn chỉnh phân vùng

Mô-đun trình liên kết thiết bị có thể hoạt động kém hiệu quả hơn nếu phân vùng super không được căn chỉnh đúng cách. Phân vùng super PHẢI được căn chỉnh theo kích thước yêu cầu I/O tối thiểu do lớp khối xác định. Theo mặc định, hệ thống xây dựng (thông qua lpmake tạo ra hình ảnh phân vùng super) giả định rằng căn chỉnh 1 MiB là đủ cho mọi phân vùng động. Tuy nhiên, nhà cung cấp phải đảm bảo rằng phân vùng super được căn chỉnh đúng cách.

Bạn có thể xác định kích thước yêu cầu tối thiểu của thiết bị khối bằng cách kiểm tra sysfs. Ví dụ:

# 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

Bạn có thể xác minh cách căn chỉnh của phân vùng super theo cách tương tự:

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

Độ lệch căn chỉnh PHẢI là 0.

Thay đổi về cấu hình thiết bị

Để bật tính năng phân vùng động, hãy thêm cờ sau đây vào device.mk:

PRODUCT_USE_DYNAMIC_PARTITIONS := true

Thay đổi về cấu hình của bảng

Bạn cần đặt kích thước của phân vùng super:

BOARD_SUPER_PARTITION_SIZE := <size-in-bytes>

Trên các thiết bị A/B, hệ thống xây dựng sẽ gửi lỗi nếu tổng kích thước của hình ảnh phân vùng động lớn hơn một nửa kích thước phân vùng super.

Bạn có thể định cấu hình danh sách các phân vùng động như sau. Đối với các thiết bị sử dụng nhóm cập nhật, hãy liệt kê các nhóm trong biến BOARD_SUPER_PARTITION_GROUPS. Sau đó, mỗi tên nhóm sẽ có một biến BOARD_group_SIZEBOARD_group_PARTITION_LIST. Đối với thiết bị A/B, kích thước tối đa của một nhóm chỉ được bao gồm một khe, vì tên nhóm được thêm hậu tố khe trong nội bộ.

Dưới đây là ví dụ về một thiết bị đặt tất cả các phân vùng vào một nhóm có tên là 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

Dưới đây là ví dụ về một thiết bị đặt các dịch vụ hệ thống và sản phẩm vào group_foo, đồng thời đặt vendor, productodm vào 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
  • Đối với thiết bị chạy thử nghiệm A/B ảo, tổng kích thước tối đa của tất cả các nhóm phải là:
    BOARD_SUPER_PARTITION_SIZE – hao tổn
    Xem phần Triển khai thử nghiệm A/B ảo.
  • Đối với các thiết bị chạy A/B, tổng kích thước tối đa của tất cả các nhóm phải là:
    BOARD_SUPER_PARTITION_SIZE / 2 - mức hao tổn
  • Đối với các thiết bị không phải A/B và thiết bị A/B được cải tiến, tổng kích thước tối đa của tất cả các nhóm phải là:
    BOARD_SUPER_PARTITION_SIZE – hao tổn
  • Tại thời điểm tạo, tổng kích thước hình ảnh của từng phân vùng trong nhóm cập nhật không được vượt quá kích thước tối đa của nhóm.
  • Bạn cần tính phần hao tổn trong quá trình tính toán để tính đến siêu dữ liệu, căn chỉnh, v.v. Mức hao tổn hợp lý là 4 MiB, nhưng bạn có thể chọn mức hao tổn lớn hơn theo yêu cầu của thiết bị.

Định kích thước các phân vùng động

Trước khi có phân vùng động, kích thước phân vùng được phân bổ nhiều hơn để đảm bảo rằng các phân vùng đó có đủ dung lượng cho các bản cập nhật trong tương lai. Kích thước thực tế được lấy nguyên trạng và hầu hết các phân vùng chỉ có thể đọc đều có một lượng dung lượng trống trong hệ thống tệp. Trong các phân vùng động, không gian trống đó không thể sử dụng được và có thể được dùng để mở rộng các phân vùng trong quá trình OTA. Điều quan trọng là phải đảm bảo các phân vùng không lãng phí dung lượng và được phân bổ với kích thước tối thiểu có thể.

Đối với hình ảnh ext4 chỉ có thể đọc, hệ thống xây dựng sẽ tự động phân bổ kích thước tối thiểu nếu bạn không chỉ định kích thước phân vùng được cố định giá trị trong mã. Hệ thống xây dựng vừa với hình ảnh để hệ thống tệp có ít dung lượng không sử dụng nhất có thể. Điều này đảm bảo rằng thiết bị không lãng phí dung lượng có thể dùng cho OTA.

Ngoài ra, bạn có thể nén thêm các hình ảnh ext4 bằng cách bật tính năng loại bỏ trùng lặp ở cấp khối. Để bật tính năng này, hãy sử dụng cấu hình sau:

BOARD_EXT4_SHARE_DUP_BLOCKS := true

Nếu bạn không muốn phân bổ tự động kích thước tối thiểu của phân vùng, có hai cách để kiểm soát kích thước phân vùng. Bạn có thể chỉ định dung lượng trống tối thiểu bằng BOARD_partitionIMAGE_PARTITION_RESERVED_SIZE hoặc chỉ định BOARD_partitionIMAGE_PARTITION_SIZE để buộc các phân vùng động có kích thước cụ thể. Bạn không nên làm cả hai việc này trừ phi cần thiết.

Ví dụ:

BOARD_PRODUCTIMAGE_PARTITION_RESERVED_SIZE := 52428800

Thao tác này buộc hệ thống tệp trong product.img phải có 50 MiB dung lượng không sử dụng.

Thay đổi về hệ thống dưới dạng thư mục gốc

Các thiết bị chạy Android 10 không được sử dụng system-as-root.

Các thiết bị có phân vùng động (cho dù chạy cùng hay trang bị thêm phân vùng động) không được sử dụng hệ thống dưới dạng gốc. Hạt nhân Linux không thể diễn giải phân vùng super và do đó không thể tự gắn system. system hiện được gắn bằng init giai đoạn đầu, nằm trong ramdisk.

Không đặt BOARD_BUILD_SYSTEM_ROOT_IMAGE. Trong Android 10, cờ BOARD_BUILD_SYSTEM_ROOT_IMAGE chỉ được dùng để phân biệt liệu hệ thống được gắn bằng hạt nhân hay init giai đoạn đầu trong ramdisk.

Việc đặt BOARD_BUILD_SYSTEM_ROOT_IMAGE thành true sẽ gây ra lỗi bản dựng khi PRODUCT_USE_DYNAMIC_PARTITIONS cũng là true.

Khi BOARD_USES_RECOVERY_AS_BOOT được đặt thành true, hình ảnh khôi phục sẽ được tạo dưới dạng boot.img, chứa ổ đĩa RAM của quá trình khôi phục. Trước đây, trình tải khởi động sử dụng tham số dòng lệnh hạt nhân skip_initramfs để quyết định chế độ khởi động. Đối với các thiết bị Android 10, trình tải khởi động KHÔNG ĐƯỢC truyền skip_initramfs đến dòng lệnh hạt nhân. Thay vào đó, trình tải khởi động phải truyền androidboot.force_normal_boot=1 để bỏ qua quá trình khôi phục và khởi động Android bình thường. Các thiết bị chạy Android 12 trở lên phải sử dụng bootconfig để truyền androidboot.force_normal_boot=1.

Thay đổi về cấu hình AVB

Khi sử dụng phiên bản Xác minh quy trình khởi động của Android 2.0, nếu thiết bị không sử dụng trình mô tả phân vùng theo chuỗi, thì bạn không cần thay đổi gì. Tuy nhiên, nếu sử dụng các phân vùng theo chuỗi và một trong các phân vùng đã xác minh là động, thì bạn cần thực hiện các thay đổi.

Dưới đây là cấu hình mẫu cho một thiết bị liên kết vbmeta cho phân vùng systemvendor.

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

Với cấu hình này, trình tải khởi động dự kiến sẽ tìm thấy chân trang vbmeta ở cuối các phân vùng systemvendor. Vì các phân vùng này không còn hiển thị với trình tải khởi động (chúng nằm trong super), nên bạn cần thực hiện hai thay đổi.

  • Thêm các phân vùng vbmeta_systemvbmeta_vendor vào bảng phân vùng của thiết bị. Đối với thiết bị A/B, hãy thêm vbmeta_system_a, vbmeta_system_b, vbmeta_vendor_avbmeta_vendor_b. Nếu thêm một hoặc nhiều phân vùng trong số này, thì các phân vùng này phải có cùng kích thước với phân vùng vbmeta.
  • Đổi tên cờ cấu hình bằng cách thêm VBMETA_ và chỉ định các phân vùng mà chuỗi mở rộng đến:
    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

Một thiết bị có thể đang sử dụng một, cả hai hoặc không sử dụng phân vùng nào trong số này. Bạn chỉ cần thay đổi khi tạo chuỗi đến một phân vùng logic.

Thay đổi đối với trình tải khởi động AVB

Nếu trình tải khởi động đã nhúng libavb, hãy thêm các bản vá sau:

Nếu sử dụng các phân vùng theo chuỗi, hãy thêm một bản vá bổ sung:

  • 49936b4c0109411fdd38bd4ba3a32a01c40439a9 — "libavb: Hỗ trợ các blob vbmeta ở đầu phân vùng."

Thay đổi về dòng lệnh của hạt nhân

Bạn phải thêm một tham số mới, androidboot.boot_devices, vào dòng lệnh hạt nhân. init sử dụng thuộc tính này để bật đường liên kết tượng trưng /dev/block/by-name. Đây phải là thành phần đường dẫn thiết bị đến đường liên kết tượng trưng theo tên cơ bản do ueventd tạo, tức là /dev/block/platform/device-path/by-name/partition-name. Các thiết bị khởi chạy bằng Android 12 trở lên phải sử dụng bootconfig để truyền androidboot.boot_devices đến init.

Ví dụ: nếu đường liên kết tượng trưng theo tên của siêu phân vùng là /dev/block/platform/soc/100000.ufshc/by-name/super, thì bạn có thể thêm tham số dòng lệnh vào tệp BoardConfig.mk như sau:

BOARD_KERNEL_CMDLINE += androidboot.boot_devices=soc/100000.ufshc
Bạn có thể thêm thông số bootconfig vào tệp BoardConfig.mk như sau:
BOARD_BOOTCONFIG += androidboot.boot_devices=soc/100000.ufshc

thay đổi fstab

Cây thiết bị và lớp phủ cây thiết bị không được chứa các mục nhập fstab. Sử dụng tệp fstab sẽ là một phần của ramdisk.

Bạn phải thực hiện các thay đổi đối với tệp fstab cho các phân vùng logic:

  • Trường cờ fs_mgr phải bao gồm cờ logical và cờ first_stage_mount, được giới thiệu trong Android 10, cho biết một phân vùng sẽ được gắn trong giai đoạn đầu tiên.
  • Một phân vùng có thể chỉ định avb=vbmeta partition name làm cờ fs_mgr, sau đó phân vùng vbmeta được chỉ định sẽ được khởi chạy bằng init giai đoạn đầu trước khi cố gắng gắn bất kỳ thiết bị nào.
  • Trường dev phải là tên phân vùng.

Các mục nhập fstab sau đây đặt hệ thống, nhà cung cấp và sản phẩm thành các phân vùng logic theo các quy tắc ở trên.

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

Sao chép tệp fstab vào ramdisk giai đoạn đầu tiên.

Thay đổi về SELinux

Thiết bị khối phân vùng siêu phải được đánh dấu bằng nhãn super_block_device. Ví dụ: nếu đường liên kết tượng trưng theo tên của phân vùng siêu là /dev/block/platform/soc/100000.ufshc/by-name/super, hãy thêm dòng sau vào file_contexts:

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

fastbootd

Trình tải khởi động (hoặc bất kỳ công cụ cài đặt ROM nào không phải không gian người dùng) không hiểu các phân vùng động, vì vậy không thể cài đặt ROM cho các phân vùng đó. Để giải quyết vấn đề này, các thiết bị phải sử dụng phương thức triển khai giao thức khởi động nhanh trong không gian người dùng, được gọi là fastbootd.

Để biết thêm thông tin về cách triển khai fastbootd, hãy xem phần Di chuyển Fastboot sang không gian người dùng.

adb remount

Đối với các nhà phát triển sử dụng bản dựng eng hoặc userdebug, adb remount cực kỳ hữu ích cho việc lặp lại nhanh. Phân vùng động gây ra vấn đề cho adb remount vì không còn dung lượng trống trong mỗi hệ thống tệp. Để giải quyết vấn đề này, các thiết bị có thể bật overlayfs. Miễn là có dung lượng trống trong phân vùng siêu, adb remount sẽ tự động tạo một phân vùng động tạm thời và sử dụng overlayfs để ghi. Phân vùng tạm thời được đặt tên là scratch, vì vậy, đừng sử dụng tên này cho các phân vùng khác.

Để biết thêm thông tin về cách bật overlayfs, hãy xem README về overlayfs trong AOSP.

Nâng cấp thiết bị Android

Nếu nâng cấp thiết bị lên Android 10 và muốn đưa tính năng hỗ trợ phân vùng động vào OTA, bạn không cần thay đổi bảng phân vùng tích hợp. Cần có một số cấu hình bổ sung.

Thay đổi về cấu hình thiết bị

Để cải tiến tính năng phân vùng động, hãy thêm các cờ sau vào device.mk:

PRODUCT_USE_DYNAMIC_PARTITIONS := true
PRODUCT_RETROFIT_DYNAMIC_PARTITIONS := true

Thay đổi về cấu hình của bảng

Bạn bắt buộc phải đặt các biến bảng sau:

  • Đặt BOARD_SUPER_PARTITION_BLOCK_DEVICES thành danh sách các thiết bị khối dùng để lưu trữ phạm vi của các phân vùng động. Đây là danh sách tên của các phân vùng thực hiện có trên thiết bị.
  • Đặt BOARD_SUPER_PARTITION_partition_DEVICE_SIZE thành kích thước của từng thiết bị khối trong BOARD_SUPER_PARTITION_BLOCK_DEVICES. Đây là danh sách kích thước của các phân vùng thực tế hiện có trên thiết bị. Giá trị này thường là BOARD_partitionIMAGE_PARTITION_SIZE trong các cấu hình bảng hiện có.
  • Huỷ đặt BOARD_partitionIMAGE_PARTITION_SIZE hiện có cho tất cả các phân vùng trong BOARD_SUPER_PARTITION_BLOCK_DEVICES.
  • Đặt BOARD_SUPER_PARTITION_SIZE thành tổng của BOARD_SUPER_PARTITION_partition_DEVICE_SIZE.
  • Đặt BOARD_SUPER_PARTITION_METADATA_DEVICE thành thiết bị khối nơi siêu dữ liệu phân vùng động được lưu trữ. Phải là một trong BOARD_SUPER_PARTITION_BLOCK_DEVICES. Thông thường, giá trị này được đặt thành system.
  • Hãy đặt BOARD_SUPER_PARTITION_GROUPS, BOARD_group_SIZEBOARD_group_PARTITION_LIST tương ứng. Hãy xem phần Thay đổi về cấu hình bảng trên thiết bị mới để biết thông tin chi tiết.

Ví dụ: nếu thiết bị đã có các phân vùng hệ thống và nhà cung cấp và bạn muốn chuyển đổi các phân vùng đó thành phân vùng động và thêm một phân vùng sản phẩm mới trong quá trình cập nhật, hãy đặt cấu hình bảng này:

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

Thay đổi về SELinux

Các thiết bị khối phân vùng siêu phải được đánh dấu bằng thuộc tính super_block_device_type. Ví dụ: nếu thiết bị đã có các phân vùng systemvendor, bạn muốn sử dụng các phân vùng đó làm thiết bị khối để lưu trữ các phần của phân vùng động và các đường liên kết tượng trưng theo tên của chúng được đánh dấu là 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

Sau đó, hãy thêm dòng sau vào device.te:

typeattribute system_block_device super_block_device_type;

Đối với các cấu hình khác, hãy xem phần Triển khai các phân vùng động trên thiết bị mới.

Để biết thêm thông tin về các bản cập nhật cải tiến, hãy xem phần OTA cho thiết bị A/B không có phân vùng động.

Hình ảnh gốc

Đối với thiết bị khởi chạy có hỗ trợ phân vùng động, hãy tránh sử dụng tính năng khởi động nhanh không gian người dùng để cài đặt ROM hình ảnh ban đầu, vì việc khởi động vào không gian người dùng sẽ chậm hơn so với các phương thức cài đặt ROM khác.

Để giải quyết vấn đề này, make dist hiện tạo thêm một hình ảnh super.img có thể được cài đặt trực tiếp vào phân vùng siêu. Tệp này tự động gói nội dung của các phân vùng logic, nghĩa là chứa system.img, vendor.img, v.v., ngoài siêu dữ liệu phân vùng super. Bạn có thể cài đặt ROM trực tiếp vào phân vùng super mà không cần thêm công cụ hoặc sử dụng fastbootd. Sau khi tạo bản dựng, super.img sẽ được đặt trong ${ANDROID_PRODUCT_OUT}.

Đối với các thiết bị A/B khởi chạy bằng phân vùng động, super.img chứa hình ảnh trong khe A. Sau khi trực tiếp cài đặt ROM siêu hình ảnh, hãy đánh dấu khe A là có thể khởi động trước khi khởi động lại thiết bị.

Đối với các thiết bị cải tiến, make dist sẽ tạo một tập hợp hình ảnh super_*.img có thể được cài đặt ROM trực tiếp vào các phân vùng thực tế tương ứng. Ví dụ: make dist tạo super_system.imgsuper_vendor.img khi BOARD_SUPER_PARTITION_BLOCK_DEVICES là nhà cung cấp hệ thống. Các hình ảnh này được đặt trong thư mục OTA trong target_files.zip.

Điều chỉnh thiết bị lưu trữ của trình liên kết thiết bị

Tính năng phân vùng động phù hợp với một số đối tượng công cụ liên kết thiết bị không xác định. Không phải tất cả các phiên bản này đều tạo thực thể như dự kiến, vì vậy, bạn phải theo dõi tất cả các mối gắn kết và cập nhật các thuộc tính Android của mọi phân vùng được liên kết bằng các thiết bị lưu trữ cơ bản của chúng.

Một cơ chế bên trong init theo dõi các điểm gắn và cập nhật không đồng bộ các thuộc tính Android. Thời gian thực hiện việc này không được đảm bảo nằm trong một khoảng thời gian cụ thể, vì vậy, bạn phải cung cấp đủ thời gian để tất cả các trình kích hoạt on property phản ứng. Các thuộc tính là dev.mnt.blk.<partition>, trong đó <partition>root, system, data hoặc vendor. Mỗi thuộc tính được liên kết với tên thiết bị lưu trữ cơ sở, như trong các ví dụ sau:

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]

Ngôn ngữ init.rc cho phép mở rộng các thuộc tính Android như một phần của quy tắc và nền tảng có thể điều chỉnh các thiết bị lưu trữ khi cần bằng các lệnh như sau:

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

Sau khi quá trình xử lý lệnh bắt đầu trong init giai đoạn hai, epoll loop sẽ hoạt động và các giá trị bắt đầu cập nhật. Tuy nhiên, vì trình kích hoạt thuộc tính không hoạt động cho đến cuối init, nên bạn không thể sử dụng trình kích hoạt thuộc tính trong các giai đoạn khởi động ban đầu để xử lý root, system hoặc vendor. Bạn có thể dự kiến rằng read_ahead_kb mặc định của hạt nhân là đủ cho đến khi các tập lệnh init.rc có thể ghi đè trong early-fs (khi nhiều trình nền và cơ sở vật chất khởi động). Do đó, Google khuyên bạn nên sử dụng tính năng on property, kết hợp với một thuộc tính do init.rc kiểm soát như sys.read_ahead_kb, để xử lý việc định thời gian cho các thao tác và ngăn chặn tình trạng tranh đua, như trong các ví dụ sau:

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}