ใช้ Virtual A/B

หากต้องการใช้ A/B เสมือนในอุปกรณ์ใหม่ หรือติดตั้งเพิ่มเติมในอุปกรณ์ที่เปิดใช้งาน คุณต้องทำการเปลี่ยนแปลงรหัสเฉพาะอุปกรณ์

สร้างธง

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

สำหรับอุปกรณ์ที่เปิดใช้งานด้วย A/B เสมือน ให้ตั้งค่าให้สืบทอดการกำหนดค่าพื้นฐานอุปกรณ์ A/B เสมือน:

$(call inherit-product, \
    $(SRC_TARGET_DIR)/product/virtual_ab_ota.mk)

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

สำหรับ Android 13 และสูงกว่า หากต้องการเปิดใช้สแน็ปช็อตที่บีบอัดด้วย Virtual A/B ให้รับการกำหนดค่าพื้นฐานต่อไปนี้:

$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_ramdisk.mk)
$(call inherit-product, \
    $(SRC_TARGET_DIR)/product/virtual_ab_ota/android_t_baseline.mk)

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

PRODUCT_VIRTUAL_AB_COMPRESSION_METHOD := gz

สำหรับ Android 12 หากต้องการเปิดใช้งานสแน็ปช็อตที่บีบอัดด้วย Virtual A/B ให้รับการกำหนดค่าพื้นฐานต่อไปนี้:

$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_ramdisk.mk)
$(call inherit-product, \
    $(SRC_TARGET_DIR)/product/virtual_ab_ota/compression.mk)

การบีบอัด XOR

สำหรับอุปกรณ์ที่อัปเกรดเป็น Android 13 ขึ้นไป คุณลักษณะการบีบอัด XOR จะไม่เปิดใช้งานตามค่าเริ่มต้น หากต้องการเปิดใช้งานการบีบอัด XOR ให้เพิ่มสิ่งต่อไปนี้ในไฟล์ .mk ของอุปกรณ์

PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.compression.xor.enabled=true

การบีบอัด XOR เปิดใช้งานโดยค่าเริ่มต้นสำหรับอุปกรณ์ที่สืบทอดมาจาก android_t_baseline.mk

การรวมพื้นที่ผู้ใช้

สำหรับอุปกรณ์ที่อัปเกรดเป็น Android 13 ขึ้นไป กระบวนการผสานพื้นที่ผู้ใช้ตามที่อธิบายไว้ใน การแบ่งชั้น Device-mapper จะไม่ถูกเปิดใช้งานตามค่าเริ่มต้น หากต้องการเปิดใช้งานการผสานพื้นที่ผู้ใช้ ให้เพิ่มบรรทัดต่อไปนี้ในไฟล์ .mk ของอุปกรณ์:

PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.userspace.snapshots.enabled=true

การรวม Userspace เปิดใช้งานโดยค่าเริ่มต้นบนอุปกรณ์ที่เปิดใช้งานตั้งแต่ 13 ขึ้นไป

การควบคุมการบูต HAL

การควบคุมการบูต HAL จัดเตรียมอินเทอร์เฟซสำหรับไคลเอนต์ OTA เพื่อควบคุมสล็อตบูต Virtual A/B ต้องการการอัปเกรดเวอร์ชันรองของการควบคุมการบูต HAL เนื่องจากจำเป็นต้องมี API เพิ่มเติมเพื่อให้แน่ใจว่า bootloader ได้รับการปกป้องระหว่างการแฟลช/การรีเซ็ตเป็นค่าจากโรงงาน ดู IBootControl.hal และ types.hal สำหรับข้อกำหนด HAL เวอร์ชันล่าสุด

// hardware/interfaces/boot/1.1/types.hal
enum MergeStatus : uint8_t {
    NONE, UNKNOWN, SNAPSHOTTED, MERGING, CANCELLED };

// hardware/interfaces/boot/1.1/IBootControl.hal
package android.hardware.boot@1.1;
interface IBootControl extends @1.0::IBootControl {
    setSnapshotMergeStatus(MergeStatus status)
        generates (bool success);
    getSnapshotMergeStatus()
        generates (MergeStatus status);
}
// Recommended implementation

Return<bool> BootControl::setSnapshotMergeStatus(MergeStatus v) {
    // Write value to persistent storage
    // e.g. misc partition (using libbootloader_message)
    // bootloader rejects wipe when status is SNAPSHOTTED
    // or MERGING
}

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

ความสมบูรณ์ของพาร์ติชันข้อมูลเมตามีความสำคัญต่อกระบวนการบู๊ต โดยเฉพาะอย่างยิ่งหลังจากใช้การอัปเดต OTA ดังนั้นจึงต้องตรวจสอบพาร์ติชันข้อมูลเมตาก่อนที่ first_stage_init จะเมานต์ เพื่อให้แน่ใจว่าสิ่งนี้เกิดขึ้น ให้เพิ่มแฟ check กาเครื่องหมาย fs_mgr ให้กับรายการสำหรับ /metadata ต่อไปนี้เป็นตัวอย่าง:

/dev/block/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard,sync wait,formattable,first_stage_mount,check

ข้อกำหนดเคอร์เนล

หากต้องการเปิดใช้งานสแน็ปช็อต ให้ตั้งค่า CONFIG_DM_SNAPSHOT เป็น true

สำหรับอุปกรณ์ที่ใช้ F2FS ให้รวม f2fs: เอ็กซ์พอร์ตแฟล็ก FS_NOCOW_FL ไปยังแพตช์เคอร์เนลของผู้ใช้ เพื่อแก้ไขการปักหมุดไฟล์ รวม f2fs: รองรับแพตช์เคอร์เนลไฟล์ที่ตรึงไว้ เช่นกัน

Virtual A/B อาศัยฟีเจอร์ที่เพิ่มเข้ามาในเคอร์เนลเวอร์ชัน 4.3: บิตสถานะ โอเวอร์โฟลว์ ใน snapshot และเป้าหมาย snapshot-merge อุปกรณ์ทั้งหมดที่เปิดตัวด้วย Android 9 และใหม่กว่าควรมีเคอร์เนลเวอร์ชัน 4.4 หรือใหม่กว่าอยู่แล้ว

หากต้องการเปิดใช้งานสแน็ปช็อตที่บีบอัด เวอร์ชันเคอร์เนลขั้นต่ำที่รองรับคือ 4.19 ตั้งค่า CONFIG_DM_USER=m หรือ CONFIG_DM_USER=y หากใช้โมดูลเดิม (โมดูล) จะต้องโหลดโมดูลในแรมดิสก์ขั้นแรก สามารถทำได้โดยเพิ่มบรรทัดต่อไปนี้ลงใน Makefile ของอุปกรณ์:

BOARD_GENERIC_RAMDISK_KERNEL_MODULES_LOAD := dm-user.ko

ติดตั้งเพิ่มเติมบนอุปกรณ์ที่อัปเกรดเป็น Android 11

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

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

  • แฟล็กคุณลักษณะเวลาบิลด์ — สำหรับอุปกรณ์ที่ดัดแปลง A/B เสมือน ทั้ง PRODUCT_VIRTUAL_AB_OTA และ PRODUCT_VIRTUAL_AB_OTA_RETROFIT จะถูกตั้งค่าเป็น true ดังที่แสดงด้านล่าง:

    (call inherit-product, \
        (SRC_TARGET_DIR)/product/virtual_ab_ota_retrofit.mk)
    
  • ขนาดซูเปอร์พาร์ติชัน — อุปกรณ์ที่เปิดใช้ A/B เสมือนสามารถลด BOARD_SUPER_PARTITION_SIZE ลงครึ่งหนึ่งได้ เนื่องจากสล็อต B ไม่ได้อยู่ในซูเปอร์พาร์ติชัน อุปกรณ์ที่ดัดแปลง A/B เสมือนจะเก็บขนาดพาร์ติชันเก่าไว้ ดังนั้น BOARD_SUPER_PARTITION_SIZE จึงมากกว่าหรือเท่ากับ 2 * ผลรวม (ขนาดของกลุ่มการอัปเดต) + ค่าโอเวอร์เฮด ซึ่งจะมากกว่าหรือเท่ากับ 2 * ผลรวม (ขนาดของพาร์ติชัน) + ค่าโสหุ้ย .

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

ระหว่างขั้นตอนการรวมการอัปเดต /data จะเก็บอินสแตนซ์ทั้งหมดของระบบปฏิบัติการ Android เพียงตัวเดียว เมื่อการโอนย้ายเริ่มต้นขึ้น system เนทีฟ vendor และพาร์ติชัน product จะไม่สมบูรณ์จนกว่าการคัดลอกจะเสร็จสิ้น หากอุปกรณ์ถูกรีเซ็ตเป็นค่าเริ่มต้นระหว่างขั้นตอนนี้ ไม่ว่าจะโดยการกู้คืนหรือผ่านกล่องโต้ตอบการตั้งค่าระบบ อุปกรณ์ก็จะไม่สามารถบู๊ตได้

ก่อนลบ /data ให้เสร็จสิ้นการผสานในการกู้คืนหรือย้อนกลับ ทั้งนี้ขึ้นอยู่กับสถานะของอุปกรณ์:

  • ถ้าบิวด์ใหม่บูทสำเร็จก่อน ให้ย้ายข้อมูลให้เสร็จ
  • มิฉะนั้น ให้ย้อนกลับไปยังสล็อตเก่า:
    • สำหรับพาร์ติชันไดนามิก ให้ย้อนกลับไปยังสถานะก่อนหน้า
    • สำหรับพาร์ติชันแบบสแตติก ให้ตั้งค่าสล็อตที่ใช้งานเป็นสล็อตเก่า

ทั้ง bootloader และ fastbootd สามารถลบพาร์ติชัน /data ได้หากอุปกรณ์ไม่ได้ล็อก แม้ว่า fastbootd สามารถบังคับให้การย้ายข้อมูลเสร็จสิ้น แต่ bootloader ทำไม่ได้ bootloader ไม่ทราบว่าการผสานกำลังดำเนินการอยู่หรือไม่ หรือบล็อกใดใน /data ที่ประกอบเป็นพาร์ติชันระบบปฏิบัติการ อุปกรณ์ต้องป้องกันไม่ให้ผู้ใช้ทำให้อุปกรณ์ใช้งานไม่ได้โดยไม่รู้ตัว (bricking) โดยดำเนินการดังต่อไปนี้:

  1. ใช้การควบคุมการบูต HAL เพื่อให้ bootloader สามารถอ่านค่าที่กำหนดโดยเมธอด setSnapshotMergeStatus()
  2. หากสถานะการผสานเป็น MERGING หรือถ้าสถานะการผสานเป็น SNAPSHOTTED และสล็อตเปลี่ยนเป็นสล็อตที่อัปเดตใหม่ คำขอให้ล้าง userdata metadata หรือพาร์ติชันที่จัดเก็บสถานะการผสานจะต้องถูกปฏิเสธใน bootloader
  3. ใช้คำสั่ง fastboot snapshot-update cancel เพื่อให้ผู้ใช้สามารถส่งสัญญาณไปยัง bootloader ว่าต้องการข้ามกลไกการป้องกันนี้
  4. ปรับเปลี่ยนเครื่องมือหรือสคริปต์การแฟลชแบบกำหนดเองเพื่อ fastboot snapshot-update cancel เมื่อทำการแฟลชทั้งอุปกรณ์ ปัญหานี้ปลอดภัยเนื่องจากการกระพริบอุปกรณ์ทั้งหมดจะลบ OTA เครื่องมือสามารถตรวจจับคำสั่งนี้ในขณะรันไทม์ได้โดยใช้ fastboot getvar snapshot-update-status คำสั่งนี้ช่วยแยกความแตกต่างระหว่างเงื่อนไขข้อผิดพลาด

ตัวอย่าง

struct VirtualAbState {
    uint8_t StructVersion;
    uint8_t MergeStatus;
    uint8_t SourceSlot;
};

bool ShouldPreventUserdataWipe() {
    VirtualAbState state;
    if (!ReadVirtualAbState(&state)) ...
    return state.MergeStatus == MergeStatus::MERGING ||
           (state.MergeStatus == MergeStatus::SNAPSHOTTED &&
            state.SourceSlot != CurrentSlot()));
}

การเปลี่ยนแปลงเครื่องมือ Fastboot

Android 11 ทำการเปลี่ยนแปลงต่อไปนี้กับโปรโตคอล fastboot:

  • getvar snapshot-update-status — ส่งคืนค่าที่ตัวควบคุมการบูต HAL สื่อสารกับ bootloader:
    • หากสถานะเป็น MERGING bootloader จะต้องส่งคืน merging
    • หากสถานะเป็น SNAPSHOTTED bootloader จะต้องส่งคืน snapshotted
    • มิฉะนั้น bootloader จะต้องส่งคืน none
  • snapshot-update merge — เสร็จสิ้นการดำเนินการผสาน บูทไปที่ Recovery/fastbootd ถ้าจำเป็น คำสั่งนี้ใช้ได้เฉพาะเมื่อ merging snapshot-update-status และรองรับใน fastbootd เท่านั้น
  • snapshot-update cancel — ตั้งค่าสถานะการผสานของการควบคุมการบูต HAL เป็น CANCELLED คำสั่งนี้ใช้ไม่ได้เมื่ออุปกรณ์ถูกล็อก
  • erase หรือ wipeerase หรือ wipe metadata userdata หรือพาร์ติชันที่มีสถานะการผสานสำหรับการควบคุมการบูต HAL ควรตรวจสอบสถานะการรวมสแน็ปช็อต หากสถานะเป็น MERGING หรือ SNAPSHOTTED อุปกรณ์ควรยกเลิกการทำงาน
  • set_active — คำสั่ง set_active ที่เปลี่ยนช่องที่ใช้งานอยู่ควรตรวจสอบสถานะการรวมสแนปชอต หากสถานะเป็น MERGING อุปกรณ์ควรยกเลิกการทำงาน สล็อตสามารถเปลี่ยนได้อย่างปลอดภัยในสถานะ SNAPSHOTTED

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

  1. ค้นหา getvar snapshot-update-status
  2. หาก merging หรือ snapshotted snapshot-update cancel
  3. ดำเนินการตามขั้นตอนการกระพริบ

ลดความต้องการในการจัดเก็บ

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

วิธีการบีบอัด OTA

แพ็คเกจ Ota สามารถปรับได้สำหรับเมตริกประสิทธิภาพต่างๆ ขณะนี้ Android มีวิธีการบีบอัดที่รองรับอยู่สองสามวิธี ( gz , lz4 และ none ) ซึ่งมีการแลกเปลี่ยนระหว่างเวลาติดตั้ง การใช้พื้นที่ COW เวลาบูต และเวลารวมสแน็ปช็อต ตัวเลือกเริ่มต้นที่เปิดใช้งานสำหรับ ab เสมือนที่มีการบีบอัดคือ gz compression method (หมายเหตุ: ประสิทธิภาพสัมพัทธ์ระหว่างวิธีการบีบอัดจะแตกต่างกันไปขึ้นอยู่กับความเร็วของ CPU และปริมาณงานของพื้นที่จัดเก็บ ซึ่งสามารถเปลี่ยนแปลงได้ขึ้นอยู่กับอุปกรณ์ แพ็คเกจ OTA ทั้งหมดที่สร้างขึ้นด้านล่างจะปิดใช้งาน PostInstall ซึ่งจะทำให้เวลาบูตช้าลงเล็กน้อย ขนาดพาร์ติชันไดนามิกรวม ของ ota เต็ม ไม่มีการบีบอัดคือ 4.81 GB )

OTA ที่เพิ่มขึ้นใน Pixel 6 Pro

เวลาติดตั้งโดยไม่มีขั้นตอนหลังการติดตั้ง การใช้พื้นที่ COW โพสต์เวลาบูต OTA เวลารวมสแนปชอต
gz 24 นาที 1.18GB 40.2 วินาที 45.5 วินาที
lz4 13 นาที 1.49GB 37.4 วินาที 37.1 วินาที
ไม่มี 13 นาที 2.90 กิกะไบต์ 37.6 วินาที 40.7 วินาที

OTA เต็มรูปแบบใน Pixel 6 Pro

เวลาติดตั้งโดยไม่มีขั้นตอนหลังการติดตั้ง การใช้พื้นที่ COW โพสต์เวลาบูต OTA เวลารวมสแนปชอต
gz 23 นาที 2.79GB 24.9 วินาที 41.7 วินาที
lz4 12 นาที 3.46GB 20.0 วินาที 25.3 วินาที
ไม่มี 10 นาที 4.85GB 20.6 วินาที 29.8 วินาที