เลย์เอาต์พาร์ติชัน

ใน Android 10 ระบบไฟล์รูทจะใช้ไม่ได้อีกต่อไป ซึ่งรวมอยู่ใน ramdisk.img และรวมเข้ากับ system.img (กล่าวคือ system.img จะสร้างขึ้นเป็น หากตั้งค่า BOARD_BUILD_SYSTEM_ROOT_IMAGE ไว้) อุปกรณ์ ที่เปิดตัวพร้อม Android 10

  • ใช้เลย์เอาต์พาร์ติชันของระบบระดับรูท (บังคับใช้โดยอัตโนมัติโดย สร้างโดยไม่มีตัวเลือกในการเปลี่ยนลักษณะการทำงาน)
  • ต้องใช้ Ramdisk ซึ่งจำเป็นสำหรับ dm-Linear
  • ต้องตั้งค่า BOARD_BUILD_SYSTEM_ROOT_IMAGE เป็น false การตั้งค่านี้ใช้เพื่อแยกความแตกต่างระหว่างอุปกรณ์ที่ใช้ RAM เท่านั้น และอุปกรณ์ที่ไม่ใช้ Ramdisk (และต่อเชื่อมแทน system.img โดยตรง)

ความหมายของการกำหนดค่าระดับรูทของระบบจะแตกต่างกันระหว่าง Android 9 กับ Android 10 ใน Android 9 ในเวอร์ชันรูท การกำหนดค่า BOARD_BUILD_SYSTEM_ROOT_IMAGE ได้รับการตั้งค่าเป็น true ซึ่งบังคับให้บิลด์รวมระบบไฟล์รูทเป็น system.img แล้วต่อเชื่อม system.img เป็นไฟล์รูท (rootfs) การกำหนดค่านี้บังคับสำหรับอุปกรณ์ เปิดตัวด้วย Android 9 แต่ไม่บังคับสำหรับอุปกรณ์ที่อัปเกรดเป็น Android 9 และสำหรับอุปกรณ์ที่ใช้ Android เวอร์ชันต่ำกว่า ใน Android การกำหนดค่าแบบรูทของระบบ 10 รายการ บิลด์จะเสมอ รวม $TARGET_SYSTEM_OUT และ $TARGET_ROOT_OUT เป็น system.img; การกำหนดค่านี้เป็นลักษณะการทำงานเริ่มต้นสำหรับอุปกรณ์ทั้งหมด ที่ใช้ Android 10

Android 10 มีการเปลี่ยนแปลงการรองรับเพิ่มเติม พาร์ติชันแบบไดนามิก ระบบการแบ่งพาร์ติชันพื้นที่ผู้ใช้ที่เปิดใช้การอัปเดตผ่านอากาศ (OTA) สร้าง ปรับขนาด หรือทำลายพาร์ติชัน ในการเปลี่ยนแปลงนี้ ทาง Linux เคอร์เนลจะต่อเชื่อมพาร์ติชันระบบเชิงตรรกะกับอุปกรณ์ที่ทำงานอยู่ไม่ได้อีกต่อไป Android 10 ดังนั้นการดำเนินการนี้จะจัดการโดย ระยะ init

ส่วนต่อไปนี้จะอธิบายข้อกำหนดรูทของระบบสำหรับ OTA เฉพาะระบบเท่านั้น ให้คำแนะนำในการอัปเดตอุปกรณ์ให้ใช้ระบบในระดับราก (รวมถึงการเปลี่ยนแปลงเลย์เอาต์พาร์ติชันและข้อกำหนดเคอร์เนล dm-verity) สำหรับ รายละเอียดเกี่ยวกับการเปลี่ยนแปลงใน ramdisk นั้นอยู่ที่ Ramdisk พาร์ติชัน

เกี่ยวกับ OTA เฉพาะระบบ

OTA เฉพาะระบบเท่านั้น ซึ่งทำให้สามารถอัปเดตรุ่น Android ได้ system.img และ product.img โดยไม่เปลี่ยนแปลงรายการอื่นๆ ต้องมีเลย์เอาต์พาร์ติชันของระบบเป็นรูท อุปกรณ์ทั้งหมดที่ใช้ Android 10 ต้องใช้เลย์เอาต์พาร์ติชันของระบบเป็นรูทเพื่อ เปิดใช้ OTA เฉพาะระบบเท่านั้น

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

โปรดดูรายละเอียดเกี่ยวกับอุปกรณ์ A/B และอุปกรณ์ที่ไม่ใช่ A/B โปรดดูที่ การอัปเดตระบบ A/B (ที่ราบรื่น)

ใช้การวางซ้อนผู้ให้บริการ (<=AOSP 14)

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

เมื่ออุปกรณ์เปิดเครื่อง กระบวนการ init จะดำเนินการในขั้นตอนแรก แท่นยึดบนเวทีและอ่านคุณสมบัติเริ่มต้น จากนั้นการค้นหา /product/vendor_overlay/<target_vendor_version> และการต่อเชื่อม ไดเรกทอรีย่อยแต่ละรายการในไดเรกทอรีพาร์ติชัน vendor ที่เกี่ยวข้อง ในกรณีที่ตรงตามเงื่อนไขต่อไปนี้

  • มี /vendor/<overlay_dir> อยู่แล้ว
  • /product/vendor_overlay/<target_vendor_version>/<overlay_dir> มีบริบทไฟล์เหมือนกับ /vendor/<overlay_dir>
  • init ได้รับอนุญาตให้ต่อเชื่อมกับบริบทไฟล์ของ /vendor/<overlay_dir>

ใช้การวางซ้อนผู้ให้บริการ

ติดตั้งไฟล์ซ้อนทับผู้ให้บริการใน /product/vendor_overlay/<target_vendor_version> ไฟล์เหล่านี้ วางซ้อนพาร์ติชัน vendor เมื่ออุปกรณ์เปิดเครื่องโดยแทนที่ไฟล์ ที่มีชื่อเดียวกันและเพิ่มไฟล์ใหม่ ผู้ให้บริการซ้อนทับจะนำไฟล์ออกไม่ได้ จากพาร์ติชัน vendor

ไฟล์ซ้อนทับของผู้ให้บริการต้องมีบริบทไฟล์เหมือนกับไฟล์เป้าหมาย จะแทนที่ในพาร์ติชัน vendor โดยค่าเริ่มต้น ไฟล์ใน ไดเรกทอรี /product/vendor_overlay/<target_vendor_version> มีบริบทvendor_file หากบริบทไฟล์ไม่ตรงกัน ระหว่างไฟล์ข้อมูลของผู้ให้บริการและไฟล์ที่แทนที่ ให้ระบุใน Sepolicy เฉพาะอุปกรณ์ บริบทไฟล์มีการตั้งค่าที่ระดับไดเรกทอรี หาก บริบทไฟล์ของไดเรกทอรีซ้อนทับผู้ให้บริการไม่ตรงกับไดเรกทอรีเป้าหมาย และไม่ได้ระบุบริบทไฟล์ที่ถูกต้องใน sepolicy เฉพาะอุปกรณ์ ไม่ได้วางซ้อนไดเรกทอรีผู้ให้บริการซ้อนทับบนไดเรกทอรีเป้าหมาย

หากต้องการใช้การวางซ้อนผู้ให้บริการ เคอร์เนลต้องเปิดใช้ OverlayFS โดยการตั้งค่า CONFIG_OVERLAY_FS=y นอกจากนี้ เคอร์เนลจะต้องผสานจาก เคอร์เนลทั่วไป 4.4 ขึ้นไป หรือแพตช์ด้วย "overlayfs: override_creds=off option bypass creator_cred"

ตัวอย่างการใช้การวางซ้อนผู้ให้บริการ

กระบวนการนี้จะสาธิตการใช้การวางซ้อนผู้ให้บริการที่วางซ้อน ไดเรกทอรี /vendor/lib/*, /vendor/etc/* และ /vendor/app/*

  1. เพิ่มไฟล์ผู้ให้บริการที่สร้างไว้ล่วงหน้าใน device/<vendor>/<target>/vendor_overlay/<target_vendor_version>/:

    device/google/device/vendor_overlay/28/lib/libfoo.so
    device/google/device/vendor_overlay/28/lib/libbar.so
    device/google/device/vendor_overlay/28/etc/baz.xml
    device/google/device/vendor_overlay/28/app/qux.apk
    
  2. ติดตั้งไฟล์ผู้ให้บริการที่สร้างไว้ล่วงหน้าไปยัง product/vendor_overlay นิ้ว device/google/device/device.mk:

    PRODUCT_COPY_FILES += \
        $(call find-copy-subdir-files,*,device/google/device/vendor_overlay,$(TARGET_COPY_OUT_PRODUCT)/vendor_overlay)
    
  3. กำหนดบริบทไฟล์หากไฟล์พาร์ติชัน vendor เป้าหมาย มีบริบทอื่นๆ ที่ไม่ใช่ vendor_file เพราะ /vendor/lib/* ใช้บริบทvendor_file ค่านี้ ที่ไม่มีไดเรกทอรีดังกล่าว

    เพิ่มรายการต่อไปนี้ใน device/google/device-sepolicy/private/file_contexts:

    /(product|system/product)/vendor_overlay/[0-9]+/etc(/.*)?   u:object_r:vendor_configs_file:s0
    /(product|system/product)/vendor_overlay/[0-9]+/app(/.*)?   u:object_r:vendor_app_file:s0
    
  4. อนุญาตให้กระบวนการ init ต่อเชื่อมการวางซ้อนผู้ให้บริการกับไฟล์ บริบทอื่นๆ ที่ไม่ใช่ vendor_file เนื่องจากinit มีสิทธิ์ต่อเชื่อมกับบริบท vendor_file อยู่แล้ว ตัวอย่างนี้ไม่ได้กำหนดนโยบายสำหรับ vendor_file

    เพิ่มรายการต่อไปนี้ใน device/google/device-sepolicy/public/init.te:

    allow init vendor_configs_file:dir mounton;
    allow init vendor_app_file:dir mounton;
    

ตรวจสอบการวางซ้อนผู้ให้บริการ

หากต้องการตรวจสอบการกำหนดค่าการวางซ้อนผู้ให้บริการ ให้เพิ่มไฟล์ใน /product/vendor_overlay/<target_vendor_version>/<overlay_dir> และดูว่าไฟล์ซ้อนอยู่บนไฟล์ใน /vendor/<overlay_dir>

สำหรับบิลด์ userdebug จะมีโมดูลทดสอบสำหรับ Atest:

$ atest -v fs_mgr_vendor_overlay_test

อัปเดตเป็นรูทของระบบ

หากต้องการอัปเดตอุปกรณ์ที่ไม่ใช่ A/B ให้ใช้ระบบที่เป็นรูท คุณต้องอัปเดต รูปแบบการแบ่งพาร์ติชันสำหรับ boot.img และ system.img ตั้งค่าแล้ว เพิ่มค่า dm-verity และลบการพึ่งพาการเปิดเครื่องในรูทเฉพาะอุปกรณ์ โฟลเดอร์

อัปเดตพาร์ติชัน

ซึ่งแตกต่างจากอุปกรณ์ A/B ที่เปลี่ยนวัตถุประสงค์การใช้งาน /boot เป็น พาร์ติชัน recovery อุปกรณ์ที่ไม่ใช่ A/B ต้องเก็บพาร์ติชัน /recovery ไว้ แยกกันเนื่องจากไม่มีพาร์ติชันช่องสำรอง (เช่น ตั้งแต่ boot_a ถึง boot_b) หาก /recovery คือ นำออกจากอุปกรณ์ที่ไม่ใช่ A/B และทำให้คล้ายกับรูปแบบ A/B นั่นคือโหมดการกู้คืน อาจเสียหายระหว่างการอัปเดตพาร์ติชัน /boot ที่ไม่สำเร็จ สำหรับ ด้วยเหตุนี้ พาร์ติชัน /recovery ต้องเป็น แยกพาร์ติชันจาก /boot สำหรับอุปกรณ์ที่ไม่ใช่ A/B ซึ่งหมายความว่า อิมเมจการกู้คืนจะยังคงได้รับการอัปเดตอย่างต่อเนื่อง (ซึ่ง ซึ่งเหมือนกันกับในอุปกรณ์ที่ใช้ Android 8.1.0 หรือต่ำกว่า)

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

รูปภาพ Ramdisk (ก่อน 9 ขวบ) รูทของระบบ (หลัง 9)
boot.img มีเคอร์เนลและ ramdisk.img: วันที่
ramdisk.img
  -/
    - init.rc
    - init
    - etc -> /system/etc
    - system/ (mount point)
    - vendor/ (mount point)
    - odm/ (mount point)
    ...
มีเฉพาะเคอร์เนลการเปิดเครื่องปกติเท่านั้น
recovery.img มีเคอร์เนลการกู้คืนและการกู้คืน ramdisk.img
system.img ประกอบด้วยข้อมูลต่อไปนี้
system.img
  -/
    - bin/
    - etc
    - vendor -> /vendor
    - ...
มีเนื้อหาที่ผสานรวมของ system.img ต้นฉบับและ ramdisk.img:
system.img
  -/
    - init.rc
    - init
    - etc -> /system/etc
    - system/
      - bin/
      - etc/
      - vendor -> /vendor
      - ...
    - vendor/ (mount point)
    - odm/ (mount point)
    ...

พาร์ติชันจะไม่เปลี่ยนแปลง ทั้งการใช้ ramdisk และการใช้งานในระบบเป็นรูท รูปแบบพาร์ติชันต่อไปนี้

  • /boot
  • /system
  • /system
  • /recovery
  • /vendor ฯลฯ

ตั้งค่า DM-verity

ในรูทของระบบ เคอร์เนลต้องต่อเชื่อม system.img ไว้ใต้ / (จุดต่อเชื่อม) พร้อม dm-verity AOSP รองรับ dm-verity ต่อไปนี้ การติดตั้งใช้งานสำหรับ system.img

vboot 1.0

สำหรับ vboot 1.0 เคอร์เนลจะต้องแยกวิเคราะห์ เฉพาะสำหรับ Android metadata เปิดอยู่ /system จากนั้นแปลงเป็น พารามิเตอร์ dm-verity เพื่อตั้งค่า dm-verity (ต้องมี แพตช์เคอร์เนลเหล่านี้) ตัวอย่างต่อไปนี้แสดงการตั้งค่าที่เกี่ยวข้องกับ dm-verity สำหรับระดับรากของระบบ บรรทัดคำสั่งเคอร์เนล:

ro root=/dev/dm-0 rootwait skip_initramfs init=/init
dm="system none ro,0 1 android-verity /dev/sda34"
veritykeyid=id:7e4333f9bba00adfe0ede979e28ed1920492b40f

Vboot 2.0

สำหรับ vboot 2.0 (AVB) ตัวโหลดบูทต้องผสานรวม external/avb/libavb ซึ่งจะแยกวิเคราะห์ฟังก์ชัน ข้อบ่งชี้แฮชทรีสำหรับ /system, แปลง เพื่อ พารามิเตอร์ dm-verity และสุดท้ายจะส่งพารามิเตอร์ไปยัง เคอร์เนลผ่านบรรทัดคำสั่งของเคอร์เนล (ข้อบ่งชี้แฮชทรีของ /system อาจอยู่ใน /vbmeta หรือ /system เอง)

vboot 2.0 ต้องการแพตช์ของเคอร์เนลต่อไปนี้

ตัวอย่างต่อไปนี้แสดงการตั้งค่าที่เกี่ยวข้องกับ dm-verity สำหรับระดับรากของระบบ บรรทัดคำสั่งเคอร์เนล:

ro root=/dev/dm-0 rootwait  skip_initramfs init=/init

dm="1 vroot none ro 1,0 5159992 verity 1
PARTUUID=00000016-0000-0000-0000-000000000000
PARTUUID=00000016-0000-0000-0000-000000000000 4096 4096 644999 644999
sha1 d80b4a8be3b58a8ab86fad1b498640892d4843a2
8d08feed2f55c418fb63447fec0d32b1b107e42c 10 restart_on_corruption
ignore_zero_blocks use_fec_from_device
PARTUUID=00000016-0000-0000-0000-000000000000 fec_roots 2 fec_blocks
650080 fec_start 650080"

ใช้โฟลเดอร์รูทเฉพาะอุปกรณ์

โดยใช้ระบบที่เป็นรูท หลังอิมเมจระบบทั่วไป (GSI) กะพริบในอุปกรณ์ (และก่อนเรียกใช้ ชุดทดสอบของผู้ให้บริการ) เพิ่มโฟลเดอร์รูทเฉพาะอุปกรณ์ด้วย BOARD_ROOT_EXTRA_FOLDERS แล้ว หายไปเนื่องจากเนื้อหาของไดเรกทอรีรากทั้งหมดถูกแทนที่โดย GSI ของระบบในระดับราก การนำโฟลเดอร์เหล่านี้ออกอาจทำให้อุปกรณ์ บูตไม่ได้หากมีทรัพยากร Dependency ในโฟลเดอร์รูทเฉพาะอุปกรณ์อยู่ (เช่น ใช้เป็นจุดต่อเชื่อม)

หากไม่ต้องการให้เกิดปัญหานี้ โปรดอย่าใช้ BOARD_ROOT_EXTRA_FOLDERS เพื่อ เพิ่มโฟลเดอร์รูทเฉพาะอุปกรณ์ หากจำเป็นต้องระบุตัวยึดเฉพาะอุปกรณ์ ใช้ /mnt/vendor/<mount point> (เพิ่มในรายการต่อไปนี้ changelists) จุดต่อเชื่อมเฉพาะผู้ให้บริการเหล่านี้อาจ ที่ระบุโดยตรงในแผนผังอุปกรณ์ของ fstab ทั้ง 2 โครงสร้าง (สำหรับระยะแรก ต่อเชื่อม) และไฟล์ /vendor/etc/fstab.{ro.hardware} ที่ไม่มี การตั้งค่าเพิ่มเติม (เนื่องจาก fs_mgr สร้างการตั้งค่าภายใต้ /mnt/vendor/* โดยอัตโนมัติ)