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

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

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

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

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

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

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

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

สำหรับอุปกรณ์ที่เปิดตัวด้วย Android 10 ให้สร้างพาร์ติชันชื่อ super พาร์ติชัน super จะจัดการช่อง A/B ภายใน ดังนั้นอุปกรณ์ A/B จึงไม่จำเป็นต้องมีพาร์ติชัน super_a และ super_b แยกกัน พาร์ติชัน AOSP แบบอ่านอย่างเดียวทั้งหมดที่ไม่ได้ใช้โดยโปรแกรมบูตต้องเป็นแบบไดนามิกและต้องนำออกจากตารางพาร์ติชัน 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

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

หากต้องการเปิดใช้การแบ่งพาร์ติชันแบบไดนามิก ให้เพิ่ม Flag ต่อไปนี้ใน 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 - overhead
  • สําหรับอุปกรณ์ที่ไม่ใช่ 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 เพื่อบังคับให้พาร์ติชันแบบไดนามิกมีขนาดใหญ่ที่เจาะจง เราไม่แนะนำให้ใช้ทั้งสองวิธีนี้เว้นแต่จะจำเป็น

เช่น

BOARD_PRODUCTIMAGE_PARTITION_RESERVED_SIZE := 52428800

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

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

อุปกรณ์ที่ใช้ Android 10 ต้องไม่ใช้ "รูท" ของระบบ

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

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

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

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

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

เมื่อใช้ Android Verified Boot 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

เมื่อใช้การกำหนดค่านี้ บูตโหลดเดอร์จะคาดหวังว่าจะพบส่วนท้าย 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
  • เปลี่ยนชื่อ Flag การกําหนดค่าโดยเพิ่ม 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

หากโปรแกรมโหลดบูตฝัง libavb ให้ใส่แพตช์ต่อไปนี้

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

  • 49936b4c0109411fdd38bd4ba3a32a01c40439a9 — "libavb: รองรับ vbmeta blob ในช่วงต้นของพาร์ติชัน"

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

คุณต้องเพิ่มพารามิเตอร์ใหม่ 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

ตัวอย่างเช่น หากซูเปอร์พาร์ติชันตามชื่อคือ /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 ที่จะเป็นส่วนหนึ่งของ RAM

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

  • ช่อง Flag ของ fs_mgr ต้องมี Flag logical และ Flag 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 ไปยัง RAM disk ระยะที่ 1

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

อุปกรณ์บล็อกพาร์ติชันระดับซูเปอร์ต้องติดป้ายกำกับ super_block_device ตัวอย่างเช่น หากลิงก์สัญลักษณ์ของพาร์ติชันหลักตามชื่อคือ /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

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

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

adb remount

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

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

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

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

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

หากต้องการปรับค่าใช้จ่ายในการแบ่งพาร์ติชันแบบไดนามิก ให้เพิ่ม Flag ต่อไปนี้ใน 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 ในพื้นที่ผู้ใช้เพื่อแฟลชอิมเมจโรงงาน เนื่องจากการบูตไปยังพื้นที่ผู้ใช้จะช้ากว่าวิธีการแฟลชอื่นๆ

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

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

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

การปรับแต่งพื้นที่เก็บข้อมูลของอุปกรณ์แมปเปอร์

การแบ่งพาร์ติชันแบบไดนามิกรองรับออบเจ็กต์ 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

เมื่อการประมวลผลคําสั่งเริ่มขึ้นในระยะที่ 2 init จะทํางาน และค่าต่างๆ จะเริ่มอัปเดต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}