การใช้ 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 ไม่ได้อยู่ใน super อีกต่อไป นั่นคือ BOARD_SUPER_PARTITION_SIZE ต้องมากกว่าหรือเท่ากับ sum(ขนาดของกลุ่มการอัพเดต) + overhead ซึ่งในทางกลับกันต้องมากกว่าหรือเท่ากับ sum(ขนาดของพาร์ติชั่น) + overhead

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

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

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

การ ควบคุมการบูต HAL จัดเตรียมอินเทอร์เฟซสำหรับไคลเอ็นต์ OTA เพื่อควบคุมช่องสำหรับบูต 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: รองรับไฟล์ แพทช์เคอร์เนลที่จัดตำแหน่งไว้ด้วยเช่นกัน

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

ในการเปิดใช้งานสแน็ปช็อตที่บีบอัด เวอร์ชันเคอร์เนลขั้นต่ำที่รองรับคือ 4.19 ตั้งค่า CONFIG_DM_USER=m หรือ CONFIG_DM_USER=y หากใช้โมดูลเดิม (โมดูล) ต้องโหลดโมดูลใน ramdisk ระยะแรก สามารถทำได้โดยเพิ่มบรรทัดต่อไปนี้ลงในอุปกรณ์ 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 ประกอบเป็นพาร์ติชั่นระบบปฏิบัติการ อุปกรณ์ต้องป้องกันผู้ใช้จากการทำให้อุปกรณ์ใช้งานไม่ได้ (อิฐ) โดยทำดังนี้:

  1. ใช้การควบคุมการบูต HAL เพื่อให้ bootloader สามารถอ่านค่าที่กำหนดโดย setSnapshotMergeStatus()
  2. หากสถานะการรวมเป็น MERGING หรือหากสถานะการรวมเป็น SNAPSHOTTED และสล็อตเปลี่ยนเป็นสล็อตที่อัพเดตใหม่ คำขอให้ลบข้อมูลผู้ใช้ ข้อมูล userdata metadata หรือพาร์ติชั่นที่เก็บสถานะการผสานจะต้องถูกปฏิเสธใน bootloader
  3. ใช้คำสั่ง fastboot snapshot-update cancel เพื่อให้ผู้ใช้สามารถส่งสัญญาณไปยัง bootloader ว่าต้องการข้ามกลไกการป้องกันนี้
  4. แก้ไขเครื่องมือหรือสคริปต์การกะพริบแบบกำหนดเองเพื่อ fastboot snapshot-update cancel เมื่อแฟลชทั้งอุปกรณ์ ปัญหานี้มีความปลอดภัยเนื่องจากการแฟลชอุปกรณ์ทั้งหมดจะเป็นการนำ OTA ออก Tooling สามารถตรวจจับคำสั่งนี้ขณะรันไทม์โดยใช้ 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 โปรแกรมโหลดบูตต้องส่งคืน merging
    • หากสถานะเป็น SNAPSHOTTED โปรแกรมโหลดบูตต้องส่งคืน snapshotted
    • มิฉะนั้น bootloader จะต้องส่งคืน none
  • snapshot-update merge ให้เสร็จสิ้น ทำการบูตไปที่การกู้คืน/fastbootd หากจำเป็น คำสั่งนี้ใช้ได้เฉพาะในกรณี snapshot-update-status กำลัง merging และได้รับการสนับสนุนใน fastbootd เท่านั้น
  • snapshot-update cancel — ตั้งค่าสถานะการรวมของการควบคุมการบูต HAL เป็น CANCELLED คำสั่งนี้ไม่ถูกต้องเมื่ออุปกรณ์ถูกล็อค
  • erase หรือ wipe — การ erase หรือ wipe metadata userdata ใช้ หรือพาร์ติชันที่มีสถานะการรวมสำหรับการควบคุมการบูต HAL ควรตรวจสอบสถานะการรวมสแน็ปช็อต หากสถานะเป็น MERGING หรือ SNAPSHOTTED อุปกรณ์ควรยกเลิกการทำงาน
  • set_active — คำสั่ง set_active ที่เปลี่ยนช่องที่ใช้งานอยู่ควรตรวจสอบสถานะการรวมสแน็ปช็อต หากสถานะเป็น MERGING อุปกรณ์ควรยกเลิกการทำงาน สล็อตสามารถเปลี่ยนแปลงได้อย่างปลอดภัยในสถานะ SNAPSHOTTED

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

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

ลดข้อกำหนดการจัดเก็บ

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