ใช้พาร์ติชันแบบไดนามิก

การแบ่งพาร์ติชันแบบไดนามิกจะใช้โมดูล dm-linear device-mapper ในเคอร์เนล Linux พาร์ติชัน super มี ข้อมูลเมตาที่แสดงชื่อและช่วงบล็อกของพาร์ติชันแบบไดนามิกแต่ละรายการ ภายใน super ในระหว่างinitระยะแรก ระบบจะแยกวิเคราะห์และตรวจสอบข้อมูลเมตานี้ และสร้างอุปกรณ์บล็อกเสมือนเพื่อ แสดงถึงแต่ละพาร์ติชันแบบไดนามิก

เมื่อใช้ OTA ระบบจะสร้าง ปรับขนาด หรือลบพาร์ติชันแบบไดนามิกโดยอัตโนมัติตามความจำเป็น สำหรับอุปกรณ์ A/B จะมีข้อมูลเมตา 2 ชุด และการเปลี่ยนแปลงจะมีผลกับชุดที่แสดงถึง สล็อตเป้าหมายเท่านั้น

เนื่องจากมีการใช้พาร์ติชันแบบไดนามิกในพื้นที่ผู้ใช้ จึงไม่สามารถสร้างพาร์ติชันที่จำเป็น สำหรับโปรแกรมโหลดระบบให้เป็นแบบไดนามิกได้ เช่น Bootloader จะอ่าน boot, dtbo และ vbmeta ดังนั้นพาร์ติชันเหล่านี้จึงต้องคงอยู่เป็นพาร์ติชันจริง

พาร์ติชันแบบไดนามิกแต่ละรายการจะอยู่ในกลุ่มการอัปเดตได้ กลุ่มเหล่านี้ จะจำกัดพื้นที่สูงสุดที่พาร์ติชันในกลุ่มนั้นใช้ได้ เช่น system และ vendor อาจอยู่ในกลุ่มที่จำกัดขนาดรวมของ system และ vendor

ใช้พาร์ติชันแบบไดนามิกในอุปกรณ์ใหม่

ส่วนนี้จะอธิบายรายละเอียดวิธีใช้พาร์ติชันแบบไดนามิกในอุปกรณ์ใหม่ ที่เปิดตัวพร้อม Android 10 ขึ้นไป หากต้องการอัปเดต อุปกรณ์ที่มีอยู่ โปรดดูการอัปเกรดอุปกรณ์ Android

การเปลี่ยนแปลงพาร์ติชัน

สำหรับอุปกรณ์ที่เปิดตัวด้วย Android 10 ให้สร้าง พาร์ติชันชื่อ super super พาร์ติชันจะจัดการสล็อต A/B ภายใน ดังนั้นอุปกรณ์ A/B จึงไม่จำเป็นต้องมี พาร์ติชัน super_a และ super_b แยกกัน พาร์ติชัน AOSP แบบอ่านอย่างเดียวทั้งหมดที่ไม่ได้ใช้โดย Bootloader ต้อง เป็นแบบไดนามิกและต้องนำออกจากตารางพาร์ติชัน GUID (GPT) พาร์ติชันเฉพาะผู้ให้บริการไม่จำเป็นต้องเป็นแบบไดนามิกและอาจวางไว้ ใน GPT

หากต้องการประมาณขนาดของ super ให้เพิ่มขนาดของ พาร์ติชันที่จะลบออกจาก GPT สำหรับอุปกรณ์ A/B ควรระบุขนาดของทั้ง 2 สล็อต รูปที่ 1 แสดง ตัวอย่างตารางพาร์ติชันก่อนและหลังการแปลงเป็นพาร์ติชันแบบไดนามิก

เลย์เอาต์ตารางพาร์ติชัน
รูปที่ 1 เลย์เอาต์ตารางพาร์ติชันจริงใหม่เมื่อ แปลงเป็นพาร์ติชันแบบไดนามิก

พาร์ติชันแบบไดนามิกที่รองรับมีดังนี้

  • ระบบ
  • ตัวแทนจำหน่ายรายย่อย
  • ผลิตภัณฑ์
  • System Ext
  • ODM

สำหรับอุปกรณ์ที่เปิดตัวด้วย Android 10 ตัวเลือกบรรทัดคำสั่งของเคอร์เนล androidboot.super_partition ต้องว่างเปล่าเพื่อให้คำสั่ง sysprop ro.boot.super_partition ว่างเปล่า

การจัดแนวพาร์ติชัน

โมดูล Device-Mapper อาจทำงานได้ไม่เต็มประสิทธิภาพหาก super พาร์ติชันไม่ได้รับการจัดแนวอย่างถูกต้อง super พาร์ติชันต้องสอดคล้องกับขนาดคำขอ I/O ขั้นต่ำตามที่กำหนดโดยเลเยอร์บล็อก โดยค่าเริ่มต้น ระบบบิลด์ (ผ่าน lpmake ซึ่งสร้างอิมเมจพาร์ติชัน super) จะถือว่าการจัดแนว 1 MiB เพียงพอสำหรับพาร์ติชันแบบไดนามิกทุกพาร์ติชัน อย่างไรก็ตาม ผู้ให้บริการควร ตรวจสอบว่าsuperพาร์ติชันได้รับการจัดแนวอย่างถูกต้อง

คุณกำหนดขนาดคำขอขั้นต่ำของอุปกรณ์บล็อกได้โดย ตรวจสอบ sysfs เช่น

# 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

คุณยืนยันการจัดแนวของsuperพาร์ติชันได้ในลักษณะเดียวกันดังนี้

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

ออฟเซ็ตการจัดแนวต้องเป็น 0

การเปลี่ยนแปลงการกำหนดค่าอุปกรณ์

หากต้องการเปิดใช้การแบ่งพาร์ติชันแบบไดนามิก ให้เพิ่มแฟล็กต่อไปนี้ใน device.mk

PRODUCT_USE_DYNAMIC_PARTITIONS := true

การเปลี่ยนแปลงการกำหนดค่าบอร์ด

คุณต้องตั้งค่าขนาดของพาร์ติชัน super ดังนี้

BOARD_SUPER_PARTITION_SIZE := <size-in-bytes>

ในอุปกรณ์ A/B ระบบบิลด์จะแสดงข้อผิดพลาดหากขนาดรวม ของอิมเมจพาร์ติชันแบบไดนามิกมีขนาดมากกว่าครึ่งหนึ่งของsuper ขนาดพาร์ติชัน

คุณกำหนดค่ารายการพาร์ติชันแบบไดนามิกได้ดังนี้ สำหรับ อุปกรณ์ที่ใช้กลุ่มการอัปเดต ให้แสดงรายการกลุ่มในตัวแปร BOARD_SUPER_PARTITION_GROUPS ชื่อกลุ่มแต่ละชื่อ จะมีตัวแปร BOARD_group_SIZE และ BOARD_group_PARTITION_LIST สำหรับอุปกรณ์ A/B ขนาดสูงสุดของกลุ่มควรครอบคลุมเพียงช่องเดียว เนื่องจากชื่อกลุ่มจะต่อท้ายด้วยช่องภายใน

ต่อไปนี้คือตัวอย่างอุปกรณ์ที่จัดพาร์ติชันทั้งหมดไว้ในกลุ่ม ชื่อ 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

ตัวอย่างอุปกรณ์ที่วางบริการของระบบและผลิตภัณฑ์ไว้ใน group_foo และ vendor, product และ odm ไว้ใน 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
  • สำหรับอุปกรณ์ที่เปิดตัวด้วย A/B เสมือน ขนาดสูงสุดของกลุ่มทั้งหมดต้องไม่เกิน BOARD_SUPER_PARTITION_SIZE - ค่าใช้จ่าย
    ดูการติดตั้งใช้งาน A/B เสมือน
  • สำหรับอุปกรณ์ที่เปิดตัวด้วยการทดสอบ A/B ผลรวมของขนาดสูงสุดของทุกกลุ่มต้องเป็น
    BOARD_SUPER_PARTITION_SIZE / 2 - ค่าใช้จ่ายเพิ่มเติม
  • สําหรับอุปกรณ์ที่ไม่ใช่ A/B และอุปกรณ์ A/B ที่ดัดแปลงใหม่ ผลรวมของขนาดสูงสุด ของทุกกลุ่มต้องเป็น
    BOARD_SUPER_PARTITION_SIZE - ค่าใช้จ่าย
  • ในเวลาบิลด์ ผลรวมของขนาดรูปภาพของแต่ละพาร์ติชัน ในกลุ่มการอัปเดตต้องไม่เกินขนาดสูงสุดของกลุ่ม
  • ค่าใช้จ่ายจำเป็นต้องใช้ในการคำนวณเพื่อพิจารณาข้อมูลเมตา การจัดแนว และอื่นๆ ค่าใช้จ่ายที่เหมาะสมคือ 4 MiB แต่คุณ สามารถเลือกค่าใช้จ่ายที่สูงกว่านี้ได้ตามที่อุปกรณ์ต้องการ

ปรับขนาดพาร์ติชันแบบไดนามิก

ก่อนที่จะมีพาร์ติชันแบบไดนามิก ระบบจะจัดสรรขนาดพาร์ติชันมากเกินไปเพื่อ ให้มั่นใจว่ามีพื้นที่เพียงพอสำหรับการอัปเดตในอนาคต ระบบจะใช้ขนาดจริง และพาร์ติชันแบบอ่านอย่างเดียวส่วนใหญ่มีพื้นที่ว่าง ในระบบไฟล์อยู่บ้าง ในพาร์ติชันแบบไดนามิก พื้นที่ว่างดังกล่าวจะ ใช้ไม่ได้และอาจใช้เพื่อขยายพาร์ติชันในระหว่าง OTA คุณต้องตรวจสอบว่าพาร์ติชันไม่ได้ใช้พื้นที่อย่างสิ้นเปลืองและ ได้รับการจัดสรรให้มีขนาดเล็กที่สุดเท่าที่จะเป็นไปได้

สำหรับอิมเมจ ext4 แบบอ่านอย่างเดียว ระบบบิลด์จะจัดสรรขนาดขั้นต่ำโดยอัตโนมัติ หากไม่ได้ระบุขนาดพาร์ติชันที่ฮาร์ดโค้ด ระบบบิลด์จะปรับรูปภาพเพื่อให้ระบบไฟล์มีพื้นที่ ที่ไม่ได้ใช้ให้น้อยที่สุด ซึ่งจะช่วยให้มั่นใจได้ว่าอุปกรณ์จะไม่ใช้พื้นที่ ที่ใช้สำหรับการอัปเดตผ่านอากาศ (OTA)

นอกจากนี้ คุณยังบีบอัดรูปภาพ ext4 เพิ่มเติมได้โดยการเปิดใช้การขจัดข้อมูลที่ซ้ำกันระดับบล็อก- หากต้องการเปิดใช้ ให้ใช้การกำหนดค่าต่อไปนี้

BOARD_EXT4_SHARE_DUP_BLOCKS := true

หากไม่ต้องการให้ระบบจัดสรรขนาดขั้นต่ำของการแบ่งพาร์ติชันโดยอัตโนมัติ คุณสามารถควบคุมขนาดพาร์ติชันได้ 2 วิธี คุณระบุ จำนวนพื้นที่ว่างขั้นต่ำได้ด้วย BOARD_partitionIMAGE_PARTITION_RESERVED_SIZE หรือจะระบุ BOARD_partitionIMAGE_PARTITION_SIZE เพื่อบังคับให้ พาร์ติชันแบบไดนามิกมีขนาดที่เฉพาะเจาะจงก็ได้ เราไม่แนะนำให้ใช้ทั้ง 2 อย่างนี้ เว้นแต่จำเป็น

เช่น

BOARD_PRODUCTIMAGE_PARTITION_RESERVED_SIZE := 52428800

ซึ่งจะบังคับให้ระบบไฟล์ใน product.img มีพื้นที่ว่าง 50 MiB

การเปลี่ยนแปลง System-as-root

อุปกรณ์ที่เปิดตัวพร้อม Android 10 ต้องไม่ ใช้ระบบเป็นรูท

อุปกรณ์ที่มีพาร์ติชันแบบไดนามิก (ไม่ว่าจะเปิดตัวหรือติดตั้งพาร์ติชันแบบไดนามิกย้อนหลัง ) ต้องไม่ใช้ระบบเป็นรูท เคอร์เนล Linux ไม่สามารถ ตีความพาร์ติชัน super จึงไม่สามารถติดตั้ง system ได้ system ตอนนี้ติดตั้งโดย init ระยะแรกซึ่งอยู่ใน Ramdisk

ไม่ต้องตั้งค่า BOARD_BUILD_SYSTEM_ROOT_IMAGE ใน Android 10 BOARD_BUILD_SYSTEM_ROOT_IMAGE จะใช้เพื่อแยกความแตกต่างว่าระบบได้รับการติดตั้งโดยเคอร์เนลหรือโดย init ในระยะแรกใน ramdisk

การตั้งค่า BOARD_BUILD_SYSTEM_ROOT_IMAGE เป็น true จะทำให้เกิดข้อผิดพลาดในการสร้างเมื่อ PRODUCT_USE_DYNAMIC_PARTITIONS เป็น true ด้วย

เมื่อตั้งค่า BOARD_USES_RECOVERY_AS_BOOT เป็น true ระบบจะสร้างอิมเมจการกู้คืนเป็น boot.img ซึ่งมี ramdisk ของการกู้คืน ก่อนหน้านี้ Bootloader ใช้พารามิเตอร์บรรทัดคำสั่งskip_initramfsเคอร์เนล เพื่อตัดสินใจว่าจะบูตเข้าสู่โหมดใด สำหรับ อุปกรณ์ Android 10, Bootloader ต้องไม่ส่ง skip_initramfs ไปยังบรรทัดคำสั่งของเคอร์เนล แต่ Bootloader ควรส่ง androidboot.force_normal_boot=1 เพื่อข้ามการกู้คืน และบูต Android ปกติ อุปกรณ์ที่เปิดตัวด้วย Android 12 ขึ้นไปต้องใช้ bootconfig เพื่อส่งผ่าน androidboot.force_normal_boot=1

การเปลี่ยนแปลงการกำหนดค่า AVB

เมื่อใช้ Android การเปิดเครื่องที่ได้รับการยืนยัน 2.0 หากอุปกรณ์ไม่ได้ใช้ตัวอธิบายพาร์ติชันที่เชื่อมโยง ก็ไม่จำเป็นต้องเปลี่ยนแปลงอะไร อย่างไรก็ตาม หากใช้พาร์ติชันที่เชื่อมโยงกันและพาร์ติชันที่ยืนยันแล้วรายการใดรายการหนึ่งเป็นแบบไดนามิก คุณจะต้องทำการเปลี่ยนแปลง

ต่อไปนี้คือตัวอย่างการกำหนดค่าสำหรับอุปกรณ์ที่เชื่อมโยง vbmeta สำหรับพาร์ติชัน system และ 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

การกำหนดค่านี้ทำให้ Bootloader คาดหวังที่จะเห็นส่วนท้าย vbmetaที่ส่วนท้ายของพาร์ติชัน system และ vendor เนื่องจากพาร์ติชันเหล่านี้จะไม่ปรากฏต่อ Bootloader อีกต่อไป (พาร์ติชันอยู่ใน super) จึงต้องมีการเปลี่ยนแปลง 2 อย่าง

  • เพิ่มพาร์ติชัน vbmeta_system และ vbmeta_vendor ลงในตารางพาร์ติชันของอุปกรณ์ สําหรับอุปกรณ์ A/B ให้เพิ่ม vbmeta_system_a, vbmeta_system_b, vbmeta_vendor_a และ vbmeta_vendor_b หาก เพิ่มพาร์ติชันเหล่านี้อย่างน้อย 1 รายการ พาร์ติชันดังกล่าวควรมีขนาดเท่ากับ พาร์ติชัน vbmeta
  • เปลี่ยนชื่อแฟล็กการกำหนดค่าโดยเพิ่ม VBMETA_ และ ระบุพาร์ติชันที่การเชื่อมโยงขยายไปถึง
    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

อุปกรณ์อาจใช้พาร์ติชันใดพาร์ติชันหนึ่ง ทั้ง 2 พาร์ติชัน หรือไม่ใช้เลยก็ได้ การเปลี่ยนแปลง จำเป็นเมื่อเชื่อมโยงกับพาร์ติชันเชิงตรรกะเท่านั้น

การเปลี่ยนแปลง Bootloader ของ AVB

หาก Bootloader มี libavb แบบฝัง ให้รวมแพตช์ต่อไปนี้

หากใช้พาร์ติชันที่เชื่อมโยง ให้รวมแพตช์เพิ่มเติมต่อไปนี้

  • 49936b4c0109411fdd38bd4ba3a32a01c40439a9 — "libavb: Support vbmeta blobs in beginning of partition."

การเปลี่ยนแปลงบรรทัดคำสั่งของเคอร์เนล

ต้องเพิ่มพารามิเตอร์ใหม่ androidboot.boot_devices ลงในบรรทัดคำสั่งของเคอร์เนล init ใช้ตัวเลือกนี้เพื่อ เปิดใช้ /dev/block/by-name Symlink โดยควรเป็น คอมโพเนนต์เส้นทางอุปกรณ์ไปยังซิมลิงก์แบบมีชื่อที่สร้างโดย ueventd ซึ่งก็คือ /dev/block/platform/device-path/by-name/partition-name อุปกรณ์ที่เปิดตัวด้วย Android 12 ขึ้นไปต้องใช้ bootconfig เพื่อส่ง androidboot.boot_devices ไปยัง init

ตัวอย่างเช่น หาก Symlink แบบ by-name ของพาร์ติชัน Super คือ /dev/block/platform/soc/100000.ufshc/by-name/super คุณสามารถเพิ่มพารามิเตอร์บรรทัดคำสั่งในไฟล์ BoardConfig.mk ได้ดังนี้

BOARD_KERNEL_CMDLINE += androidboot.boot_devices=soc/100000.ufshc
คุณเพิ่มพารามิเตอร์ bootconfig ในไฟล์ BoardConfig.mk ได้ดังนี้
BOARD_BOOTCONFIG += androidboot.boot_devices=soc/100000.ufshc

การเปลี่ยนแปลง fstab

แผนผังอุปกรณ์และแผนผังอุปกรณ์ที่ซ้อนทับกันต้องไม่มีรายการ fstab ใช้ไฟล์ fstab ที่จะเป็นส่วนหนึ่งของ ramdisk

ต้องทำการเปลี่ยนแปลงในไฟล์ fstab สำหรับพาร์ติชันแบบตรรกะดังนี้

  • ฟิลด์แฟล็ก fs_mgr ต้องมีแฟล็ก logical และแฟล็ก first_stage_mount ซึ่งเปิดตัวใน Android 10 ซึ่งบ่งบอกว่าพาร์ติชันจะ ต้องติดตั้งในระยะแรก
  • พาร์ติชันอาจระบุ avb=vbmeta partition name เป็นแฟล็ก fs_mgr จากนั้นพาร์ติชัน vbmeta ที่ระบุจะได้รับการเริ่มต้นโดย init ในระยะแรกก่อนที่จะพยายามติดตั้งอุปกรณ์ใดๆ
  • ฟิลด์ dev ต้องเป็นชื่อพาร์ติชัน

รายการ fstab ต่อไปนี้จะตั้งค่า system, vendor และ product เป็นพาร์ติชันเชิงตรรกะ ตามกฎข้างต้น

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

คัดลอกไฟล์ fstab ไปยัง ramdisk ในระยะแรก

การเปลี่ยนแปลง SELinux

อุปกรณ์บล็อกพาร์ติชันขั้นสูงต้องมีป้ายกำกับ super_block_device ตัวอย่างเช่น หากซิมลิงก์ super partition by-name คือ /dev/block/platform/soc/100000.ufshc/by-name/super, ให้เพิ่มบรรทัดต่อไปนี้ลงใน file_contexts

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

fastbootd

Bootloader (หรือเครื่องมือแฟลชที่ไม่ใช่พื้นที่ผู้ใช้) ไม่เข้าใจ พาร์ติชันแบบไดนามิก จึงแฟลชพาร์ติชันเหล่านั้นไม่ได้ เพื่อแก้ไขปัญหานี้ อุปกรณ์ ต้องใช้การติดตั้งใช้งานในพื้นที่ผู้ใช้ของโปรโตคอล fastboot ซึ่งเรียกว่า fastbootd

ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีใช้งาน fastbootd ได้ที่ย้าย Fastboot ไปยังพื้นที่ผู้ใช้

adb remount

สำหรับนักพัฒนาแอปที่ใช้บิลด์ eng หรือ userdebug adb remount มีประโยชน์อย่างยิ่งสำหรับการทำซ้ำอย่างรวดเร็ว พาร์ติชันแบบไดนามิกทำให้เกิดปัญหาสำหรับ adb remount เนื่องจากไม่มีพื้นที่ว่าง ภายในระบบไฟล์แต่ละระบบอีกต่อไป อุปกรณ์สามารถเปิดใช้ overlayfs เพื่อแก้ไขปัญหานี้ได้ ตราบใดที่ยังมีพื้นที่ว่างภายในพาร์ติชันหลัก adb remount จะสร้างพาร์ติชันแบบไดนามิกชั่วคราวโดยอัตโนมัติ และใช้ overlayfs สำหรับการเขียน พาร์ติชันชั่วคราวมีชื่อว่า scratch ดังนั้นอย่าใช้ชื่อนี้กับพาร์ติชันอื่นๆ

ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีเปิดใช้ overlayfs ได้ที่ overlayfs README ใน AOSP

อัปเกรดอุปกรณ์ Android

หากอัปเกรดอุปกรณ์เป็น Android 10 และ ต้องการรวมการรองรับพาร์ติชันแบบไดนามิกไว้ใน OTA คุณไม่จำเป็นต้อง เปลี่ยนตารางพาร์ติชันในตัว คุณต้องกำหนดค่าเพิ่มเติม

การเปลี่ยนแปลงการกำหนดค่าอุปกรณ์

หากต้องการติดตั้งการแบ่งพาร์ติชันแบบไดนามิกย้อนหลัง ให้เพิ่มแฟล็กต่อไปนี้ใน device.mk

PRODUCT_USE_DYNAMIC_PARTITIONS := true
PRODUCT_RETROFIT_DYNAMIC_PARTITIONS := true

การเปลี่ยนแปลงการกำหนดค่าบอร์ด

คุณต้องตั้งค่าตัวแปรบอร์ดต่อไปนี้

  • ตั้งค่า BOARD_SUPER_PARTITION_BLOCK_DEVICES เป็นรายการอุปกรณ์ที่บล็อกซึ่งใช้ เพื่อจัดเก็บขอบเขตของพาร์ติชันแบบไดนามิก นี่คือรายการชื่อของพาร์ติชันจริงที่มีอยู่ ในอุปกรณ์
  • ตั้งค่า BOARD_SUPER_PARTITION_partition_DEVICE_SIZE เป็นขนาด ของอุปกรณ์บล็อกแต่ละรายการใน BOARD_SUPER_PARTITION_BLOCK_DEVICES ตามลำดับ นี่คือรายการขนาดของพาร์ติชันจริงที่มีอยู่ในอุปกรณ์ โดยปกติแล้วจะ BOARD_partitionIMAGE_PARTITION_SIZE ในบอร์ดที่มีอยู่ การกำหนดค่า
  • ยกเลิกการตั้งค่า BOARD_partitionIMAGE_PARTITION_SIZE ที่มีอยู่สำหรับพาร์ติชันทั้งหมด ใน BOARD_SUPER_PARTITION_BLOCK_DEVICES
  • ตั้งค่า BOARD_SUPER_PARTITION_SIZE เป็นผลรวมของ BOARD_SUPER_PARTITION_partition_DEVICE_SIZE
  • ตั้งค่า BOARD_SUPER_PARTITION_METADATA_DEVICE เป็นอุปกรณ์ที่บล็อกซึ่งจัดเก็บ ข้อมูลเมตาของพาร์ติชันแบบไดนามิก โดยต้องเป็นหนึ่งใน BOARD_SUPER_PARTITION_BLOCK_DEVICES โดยปกติแล้ว ค่านี้จะตั้งเป็น system
  • ตั้งค่า BOARD_SUPER_PARTITION_GROUPS BOARD_group_SIZE และ BOARD_group_PARTITION_LIST ตามลำดับ ดูรายละเอียดได้ที่ การเปลี่ยนแปลงการกำหนดค่าบอร์ดในอุปกรณ์ใหม่

เช่น หากอุปกรณ์มีพาร์ติชันระบบและพาร์ติชันของผู้ให้บริการอยู่แล้ว และคุณต้องการแปลง พาร์ติชันเหล่านั้นเป็นพาร์ติชันแบบไดนามิกและเพิ่มพาร์ติชันผลิตภัณฑ์ใหม่ระหว่างการอัปเดต ให้ตั้งค่าบอร์ดดังนี้

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

อุปกรณ์บล็อกพาร์ติชันขั้นสูงต้องมีแอตทริบิวต์ super_block_device_type เช่น หากอุปกรณ์มีพาร์ติชัน system และ vendor อยู่แล้ว คุณต้องการใช้พาร์ติชันเหล่านั้นเป็นอุปกรณ์บล็อกเพื่อจัดเก็บขอบเขตของพาร์ติชันแบบไดนามิก และระบบจะทำเครื่องหมายลิงก์แบบสัญลักษณ์ตามชื่อของพาร์ติชันเหล่านั้นเป็น 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

จากนั้นเพิ่มบรรทัดต่อไปนี้ใน device.te

typeattribute system_block_device super_block_device_type;

สำหรับการกำหนดค่าอื่นๆ โปรดดูการใช้ พาร์ติชันแบบไดนามิกในอุปกรณ์ใหม่

ดูข้อมูลเพิ่มเติมเกี่ยวกับการอัปเดตแบบติดตั้งเพิ่มเติมได้ที่ OTA สำหรับอุปกรณ์ A/B ที่ไม่มีพาร์ติชันแบบไดนามิก

ค่าเริ่มต้น

สำหรับอุปกรณ์ที่เปิดตัวพร้อมรองรับพาร์ติชันแบบไดนามิก ให้หลีกเลี่ยงการใช้ fastboot ใน Userspace เพื่อแฟลชอิมเมจจากโรงงาน เนื่องจาก การบูตไปยัง Userspace จะช้ากว่าวิธีการแฟลชอื่นๆ

make dist จึงสร้างsuper.imgรูปภาพเพิ่มเติมที่สามารถแฟลชไปยังพาร์ติชัน super ได้โดยตรง โดยจะจัดกลุ่มเนื้อหาของพาร์ติชันเชิงตรรกะโดยอัตโนมัติ ซึ่งหมายความว่าจะมี system.img vendor.img และอื่นๆ นอกเหนือจากข้อมูลเมตาของพาร์ติชัน super คุณแฟลชรูปภาพนี้ไปยังพาร์ติชัน super ได้โดยตรงโดยไม่ต้องใช้เครื่องมือเพิ่มเติมหรือใช้ fastbootd หลังจากสร้างแล้ว ระบบจะวาง super.img ไว้ใน ${ANDROID_PRODUCT_OUT}

สำหรับอุปกรณ์ A/B ที่เปิดตัวพร้อมพาร์ติชันแบบไดนามิก super.img มีรูปภาพในช่อง A หลังจากแฟลช อิมเมจ super โดยตรงแล้ว ให้ทำเครื่องหมายช่อง A เป็นช่องที่บูตได้ก่อนรีบูต อุปกรณ์

สำหรับอุปกรณ์ที่ดัดแปลง make dist จะสร้างชุดอิมเมจ super_*.img ที่แฟลชไปยังพาร์ติชันจริงที่เกี่ยวข้องได้โดยตรง ตัวอย่างเช่น make dist สร้าง super_system.img และ super_vendor.img เมื่อ BOARD_SUPER_PARTITION_BLOCK_DEVICES เป็นผู้จำหน่ายระบบ ระบบจะวางรูปภาพเหล่านี้ไว้ในโฟลเดอร์ OTA ใน target_files.zip

การปรับแต่งอุปกรณ์จัดเก็บข้อมูล Device Mapper

การแบ่งพาร์ติชันแบบไดนามิกรองรับออบเจ็กต์ device-mapper แบบไม่กำหนดจำนวน ซึ่งอาจไม่ได้สร้างอินสแตนซ์ทั้งหมดตามที่คาดไว้ ดังนั้นคุณต้องติดตามการติดตั้งทั้งหมด และอัปเดตพร็อพเพอร์ตี้ Android ของพาร์ติชันที่เชื่อมโยงทั้งหมดด้วยอุปกรณ์จัดเก็บข้อมูลพื้นฐาน

กลไกภายใน init จะติดตามการติดตั้งและอัปเดตพร็อพเพอร์ตี้ Android แบบไม่พร้อมกัน ระยะเวลาที่ใช้ในการดำเนินการนี้ไม่ได้รับประกันว่าจะอยู่ภายในระยะเวลาที่เฉพาะเจาะจง ดังนั้นคุณต้องให้เวลาเพียงพอเพื่อให้on propertyทริกเกอร์ทั้งหมดตอบสนอง พร็อพเพอร์ตี้คือ dev.mnt.blk.<partition> โดยที่ <partition> คือ root, system, data หรือ vendor เช่น แต่ละพร็อพเพอร์ตี้จะเชื่อมโยงกับ ชื่ออุปกรณ์จัดเก็บข้อมูลพื้นฐาน ดังที่แสดงในตัวอย่างต่อไปนี้

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]

init.rc ช่วยให้พร็อพเพอร์ตี้ Android ขยายได้เป็นส่วนหนึ่งของกฎ และแพลตฟอร์มสามารถปรับแต่งอุปกรณ์จัดเก็บข้อมูลได้ตามต้องการด้วยคำสั่งต่อไปนี้

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

เมื่อการประมวลผลคำสั่งเริ่มขึ้นในinitระยะที่ 2 epoll loop จะใช้งานได้ และค่าจะเริ่มอัปเดต อย่างไรก็ตาม เนื่องจากทริกเกอร์ของพร็อพเพอร์ตี้จะยังไม่ทำงานจนกว่าจะถึงช่วงปลายinit จึงไม่สามารถใช้ในขั้นตอนการบูตเริ่มต้นเพื่อจัดการ root, system หรือ vendor ได้ คุณอาจคาดหวังว่าread_ahead_kbเริ่มต้นของเคอร์เนลจะเพียงพอจนกว่าสคริปต์ init.rc จะลบล้างได้ใน early-fs (เมื่อเริ่มดีมอนและสิ่งอำนวยความสะดวกต่างๆ) ดังนั้น Google ขอแนะนําให้คุณใช้ฟีเจอร์ on property ร่วมกับพร็อพเพอร์ตี้ที่ควบคุมโดย init.rc เช่น sys.read_ahead_kb เพื่อจัดการกับการกำหนดเวลาการดำเนินการและป้องกันการแข่งขัน ดังตัวอย่างต่อไปนี้

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}