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

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

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

เนื่องจากมีการใช้พาร์ติชันแบบไดนามิกในพื้นที่ผู้ใช้ พาร์ติชันที่ bootloader ต้องการจึงไม่สามารถทำให้เป็นแบบไดนามิกได้ ตัวอย่างเช่น 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 Partition Table (GPT) พาร์ติชันเฉพาะผู้จำหน่ายไม่จำเป็นต้องเป็นแบบไดนามิกและอาจอยู่ใน GPT

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

เค้าโครงตารางพาร์ทิชัน
รูปที่ 1. โครงร่างตารางฟิสิคัลพาร์ติชันใหม่เมื่อแปลงเป็นพาร์ติชันไดนามิก

พาร์ติชันไดนามิกที่รองรับคือ:

  • ระบบ
  • ผู้ขาย
  • ผลิตภัณฑ์
  • ต่อระบบ
  • โอเอ็มเอ็ม

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

การจัดตำแหน่งพาร์ติชัน

โมดูลตัวทำแผนที่อุปกรณ์อาจทำงานได้อย่างมีประสิทธิภาพน้อยลงหากพาร์ติชัน 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
  • สำหรับอุปกรณ์เปิดใช้ Virtual 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

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

ตัวอย่างเช่น:

BOARD_PRODUCTIMAGE_PARTITION_RESERVED_SIZE := 52428800

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

การเปลี่ยนแปลงระบบในฐานะรูท

อุปกรณ์ที่เปิดตัวด้วย 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 ถูกตั้งค่าเป็นจริง อิมเมจการกู้คืนจะถูกสร้างขึ้นเป็น 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 Verified Boot 2.0 หากอุปกรณ์ไม่ได้ใช้ chained partition descriptors ก็ไม่จำเป็นต้องเปลี่ยนแปลง อย่างไรก็ตาม หากใช้พาร์ติชันแบบลูกโซ่ และพาร์ติชันที่ตรวจสอบแล้วตัวใดตัวหนึ่งเป็นแบบไดนามิก จำเป็นต้องเปลี่ยนแปลง

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

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

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

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

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

หากใช้พาร์ติชันแบบลูกโซ่ ให้รวมแพตช์เพิ่มเติม:

  • 49936b4c0109411fdd38bd4ba3a32a01c40439a9 — "libavb: รองรับ vbmeta blobs ในจุดเริ่มต้นของพาร์ติชัน"

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

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

ตัวอย่างเช่น หาก symlink ตามชื่อพาร์ติชันซุปเปอร์คือ /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 flags จะต้องมีแฟล็ก logical และแฟล็ก first_stage_mount ซึ่งเปิดตัวใน Android 10 ซึ่งระบุว่าจะต้องติดตั้งพาร์ติชันในระยะแรก
  • พาร์ติชันอาจระบุ avb= vbmeta partition name เป็นแฟล็ก fs_mgr จากนั้นพาร์ติ vbmeta ที่ระบุจะถูกเตรียมใช้งานโดย init ระยะแรกก่อนที่จะพยายามเมาต์อุปกรณ์ใดๆ
  • ฟิลด์ dev ต้องเป็นชื่อพาร์ติชัน

รายการ fstab ต่อไปนี้จะตั้งค่าระบบ ผู้จำหน่าย และผลิตภัณฑ์เป็นโลจิคัลพาร์ติชันตามกฎข้างต้น

#<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 ตัวอย่างเช่น หาก symlink ตามชื่อพาร์ติชั่นซุปเปอร์คือ /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

บูตเร็ว

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

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีการใช้งาน fastbootd โปรดดูที่ การย้าย Fastboot ไปยัง User Space

adb ติดตั้งใหม่

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

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีการเปิดใช้งานการซ้อนทับ โปรดดูที่ การซ้อนทับ 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_ partition IMAGE_PARTITION_SIZE ในการกำหนดค่าบอร์ดที่มีอยู่
  • ยกเลิกการตั้ง BOARD_ partition IMAGE_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 เพิ่มเติมที่สามารถแฟลชไปยังพาร์ติชันขั้นสูงได้โดยตรง โดยจะรวมเนื้อหาของโลจิคัลพาร์ติชันโดยอัตโนมัติ ซึ่งหมายความว่าประกอบด้วย system.img , vendor.img และอื่นๆ นอกเหนือจากเมตาดาต้าของพาร์ติชัน super อิมเมจนี้สามารถแฟลชโดยตรงไปยังซุปเปอร์ super โดยไม่ต้องใช้เครื่องมือเพิ่มเติมหรือใช้ fastbootd หลังจากสร้าง super.img จะถูกวางไว้ใน ${ANDROID_PRODUCT_OUT}

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

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

การปรับอุปกรณ์จัดเก็บข้อมูลตัวทำแผนที่อุปกรณ์

การแบ่งพาร์ติชันแบบไดนามิกรองรับอ็อบเจ็กต์ตัวแมปอุปกรณ์ที่ไม่ได้กำหนดไว้จำนวนหนึ่ง สิ่งเหล่านี้อาจไม่เกิดขึ้นทั้งหมดตามที่คาดไว้ ดังนั้นคุณต้องติดตามการเมาท์ทั้งหมด และอัปเดตคุณสมบัติของ 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 epoll loop จะแอ็คทีฟ และค่าต่างๆ จะเริ่มอัปเดต อย่างไรก็ตาม เนื่องจากคุณสมบัติทริกเกอร์ไม่ทำงานจนกว่าจะ init จึงไม่สามารถใช้ในขั้นตอนการบูตเริ่มแรกเพื่อจัดการ root system หรือ vendor คุณอาจคาดหวังว่าค่าเริ่มต้นของเคอร์เนล read_ahead_kb จะเพียงพอจนกว่าสคริปต์ init.rc จะสามารถแทนที่ได้ใน early-fs (เมื่อ daemons และสิ่งอำนวยความสะดวกต่างๆ เริ่มต้นขึ้น) ดังนั้น 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}