นำการอัปเดต A/B ไปใช้

ผู้ให้บริการ OEM และ SoC ที่ต้องการใช้การอัปเดตระบบ A/B ต้องตรวจสอบ Bootloader ติดตั้งใช้งาน Boot_control HAL และส่งพารามิเตอร์ที่ถูกต้องไปยัง เคอร์เนล

ใช้งาน HAL การควบคุมการเปิดเครื่อง

Bootloader ที่รองรับ A/B ต้องใช้ boot_control HAL ที่ hardware/libhardware/include/hardware/boot_control.h คุณสามารถทดสอบการติดตั้งใช้งานได้โดยใช้ system/extras/bootctl ยูทิลิตีและ system/extras/tests/bootloader/

นอกจากนี้ คุณต้องติดตั้งใช้งานเครื่องสถานะดังที่แสดงด้านล่างด้วย

รูปที่ 1. เครื่องสถานะ Bootloader

ตั้งค่าเคอร์เนล

วิธีใช้การอัปเดตระบบ A/B

  1. ตรวจสอบชุดแพตช์ของเคอร์เนลต่อไปนี้ (หากจำเป็น)
  2. ตรวจสอบว่าอาร์กิวเมนต์บรรทัดคำสั่งเคอร์เนลมีอาร์กิวเมนต์เพิ่มเติมต่อไปนี้
    skip_initramfs rootwait ro init=/init root="/dev/dm-0 dm=system none ro,0 1 android-verity <public-key-id> <path-to-system-partition>"
    ... โดยที่ค่า <public-key-id> คือรหัสของคีย์สาธารณะที่ใช้เพื่อ ตรวจสอบลายเซ็นของตารางการยืนยัน (โปรดดูรายละเอียดที่หัวข้อ dm-verity)
  3. เพิ่มใบรับรอง .X509 ที่มีคีย์สาธารณะไปยังคีย์ริงของระบบดังนี้
    1. คัดลอกใบรับรอง .X509 ที่จัดรูปแบบในรูปแบบ .der ไปยังรูทของ ไดเรกทอรี kernel ถ้าใบรับรอง .X509 มีการจัดรูปแบบเป็น .pem จะใช้คำสั่ง openssl ต่อไปนี้เพื่อแปลง รูปแบบ .pem เป็น .der:
      opensl x509 -in <x509-pem-certificate> -outform der -out <x509-der-certificate>
      
    2. สร้าง zImage เพื่อรวมใบรับรองเป็นส่วนหนึ่งของคีย์ริงของระบบ ในการยืนยัน ให้ตรวจสอบรายการ procfs (ต้องระบุ KEYS_CONFIG_DEBUG_PROC_KEYSที่จะเปิดใช้):
      angler:/# cat /proc/keys
      
      1c8a217e I------ 1 เพิร์ม 1f010000 0 0 ไม่ตรง
      Android: 7e4333f9bba00adfe0ede979e28ed1920492b40f: X509.RSA 0492b40f []
      2d454e3e I------ 1 ถาวร 1f030000 0 0 คีย์ริง
      .system_keyring: 1/4
      รวมใบรับรอง .X509 เรียบร้อยแล้ว แสดงว่ามีคีย์สาธารณะ ในคีย์ริงของระบบ (ไฮไลต์จะแสดงรหัสคีย์สาธารณะ)
    3. แทนที่พื้นที่ทำงานด้วย # และส่งต่อเป็น <public-key-id> ในบรรทัดคำสั่งของเคอร์เนล เช่น Pass Android:#7e4333f9bba00adfe0ede979e28ed1920492b40fแทน <public-key-id>

ตั้งค่าตัวแปรบิลด์

Bootloader ที่รองรับ A/B ต้องเป็นไปตามเกณฑ์ตัวแปรบิลด์ต่อไปนี้

ต้องระบุสำหรับเป้าหมาย A/B
  • AB_OTA_UPDATER := true
  • AB_OTA_PARTITIONS := \

      boot \   system \
      vendor
    และพาร์ติชันอื่นๆ ที่อัปเดตผ่าน update_engine (วิทยุ, Bootloader, etc.)
  • PRODUCT_PACKAGES += \
      update_engine \
      update_verifier
ตัวอย่างเช่น อ้างถึง /device/google/marlin/+/android-7.1.0_r1/device-common.mk คุณสามารถเลือกดำเนินการขั้นตอน dex2oat หลังการติดตั้ง (แต่ต้องรีบูตล่วงหน้า) ตามที่อธิบายไว้ใน การคอมไพล์
ขอแนะนำอย่างยิ่งสำหรับเป้าหมาย A/B
  • นิยามคำว่า TARGET_NO_RECOVERY := true
  • นิยามคำว่า BOARD_USES_RECOVERY_AS_BOOT := true
  • อย่ากำหนด BOARD_RECOVERYIMAGE_PARTITION_SIZE
กำหนดเป้าหมาย A/B ไม่ได้
  • BOARD_CACHEIMAGE_PARTITION_SIZE
  • BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE
ไม่บังคับสำหรับบิลด์การแก้ไขข้อบกพร่อง PRODUCT_PACKAGES_DEBUG += update_engine_client

ตั้งค่าพาร์ติชัน (ช่อง)

อุปกรณ์ A/B ไม่จำเป็นต้องมีพาร์ติชันการกู้คืนหรือพาร์ติชันแคชเนื่องจาก Android ไม่ได้ใช้แล้ว พาร์ติชันเหล่านี้ ตอนนี้ระบบใช้พาร์ติชันข้อมูลกับแพ็กเกจ OTA ที่ดาวน์โหลด และ รหัสอิมเมจการกู้คืนอยู่ในพาร์ติชันเปิดเครื่อง ควรตั้งชื่อพาร์ติชันทั้งหมดที่เป็น A/B-ed ดังนี้ (ช่องจะมีชื่อว่า a, b เสมอ เป็นต้น): boot_a, boot_b, system_a, system_b, vendor_a vendor_b

แคช

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

แย่งลูกคืนมา

ขณะนี้ดิสก์ RAM สำหรับการกู้คืนอยู่ในไฟล์ boot.img เมื่อเข้าไปใน การกู้คืน Bootloader ไม่สามารถเปิดใช้ตัวเลือก skip_initramfs บรรทัดคำสั่งของเคอร์เนล

สำหรับการอัปเดตที่ไม่ใช่ A/B พาร์ติชันการกู้คืนจะมีโค้ดที่ใช้อัปเดต อัลฟา/เบต้า การอัปเดตจะดำเนินการโดย update_engine ที่ทำงานในอิมเมจระบบที่เปิดเครื่องตามปกติ ยังมีโหมดการกู้คืนเพื่อใช้การรีเซ็ตข้อมูลเป็นค่าเริ่มต้นและการโหลดจากแหล่งที่ไม่รู้จัก (ซึ่งเป็นที่มาของชื่อ "การกู้คืน") โค้ดและข้อมูลสำหรับโหมดการกู้คืน จัดเก็บไว้ในพาร์ติชันการเปิดเครื่องปกติใน RAM เพื่อบูตเข้าสู่อิมเมจระบบ Bootloader บอกเคอร์เนลให้ข้าม RAM ดิสก์ (มิฉะนั้นอุปกรณ์จะเริ่มต้นระบบเข้าสู่การกู้คืน โหมดการกู้คืนมีขนาดเล็ก (และส่วนใหญ่อยู่ในพาร์ติชันการเปิดเครื่องอยู่แล้ว) การเปิดเครื่อง ขนาดพาร์ติชันไม่เพิ่มขึ้น

Fstab

อาร์กิวเมนต์ slotselect ต้องอยู่ในบรรทัดสำหรับ A/B-ed พาร์ติชัน เช่น

<path-to-block-device>/vendor  /vendor ext4 ro
โปรดรอสักครู่,verify=<path-to-block-device>/metadata,slotselect

ไม่ควรตั้งชื่อพาร์ติชันเป็น vendor แต่ให้แบ่งพาร์ติชัน vendor_a หรือ ระบบจะเลือก vendor_b และต่อเชื่อมบนจุดต่อเชื่อม /vendor

อาร์กิวเมนต์ช่องเคอร์เนล

คำต่อท้ายช่องปัจจุบันควรส่งผ่านโหนดแผนผังอุปกรณ์ (DT) ที่เฉพาะเจาะจง (/firmware/android/slot_suffix) หรือผ่าน androidboot.slot_suffix บรรทัดคำสั่งเคอร์เนลหรืออาร์กิวเมนต์ Bootconfig

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

  • --slot SLOT ลบล้างการทำงานเริ่มต้นและแจ้งให้ Fastboot แฟลชช่องที่มีการส่งผ่านเป็น อาร์กิวเมนต์
  • --set-active [SLOT] ตั้งค่าสล็อตเป็นใช้งานอยู่ หากไม่มีอาร์กิวเมนต์ที่ไม่บังคับ ช่องปัจจุบันจะถูกตั้งค่าเป็นใช้งานอยู่
  • fastboot --help ดูรายละเอียดเกี่ยวกับคำสั่ง

หาก Bootloader ใช้ Fastboot ก็ควรจะรองรับคำสั่ง set_active <slot> ที่กำหนดช่องที่ใช้งานอยู่ในปัจจุบันไปยังช่องที่กำหนด ( ต้องล้างแฟล็กที่ไม่สามารถบูตได้สำหรับช่องนั้นและรีเซ็ตจำนวนครั้งในการดำเนินการซ้ำให้เป็นค่าเริ่มต้น ค่า) Bootloader ควรรองรับตัวแปรต่อไปนี้ด้วย

  • has-slot:<partition-base-name-without-suffix> แสดงค่า "yes" หากระบุ พาร์ติชันรองรับสล็อต "ไม่"
  • current-slot แสดงคำต่อท้ายของสล็อตที่จะบูตจากรายการถัดไป
  • slot-count แสดงผลจำนวนเต็มที่แทนจำนวนสล็อตที่ใช้ได้ ปัจจุบันมีการรองรับ 2 สล็อต ดังนั้นค่านี้จึงเป็น 2
  • slot-successful:<slot-suffix> แสดงค่า "yes" หากช่องโฆษณาที่ระบุเป็น ทำเครื่องหมายว่าเปิดเครื่องเรียบร้อยแล้ว "ไม่" หรือไม่เช่นนั้น
  • slot-unbootable:<slot-suffix> แสดงค่า "yes" หากช่องที่ระบุมีการทำเครื่องหมายไว้ ว่าไม่สามารถบูตได้, "ไม่" หรือไม่เช่นนั้น
  • slot-retry-count:<slot-suffix> จำนวนการลองซ้ำที่เหลือเพื่อพยายาม เปิดเครื่องช่องที่กำหนด

หากต้องการดูตัวแปรทั้งหมด ให้เรียกใช้ fastboot getvar all

สร้างแพ็กเกจ OTA

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

ตัวอย่าง

  • วิธีสร้าง OTA เต็มรูปแบบ
    ./build/make/tools/releasetools/ota_from_target_files \
        Dist_output/tardis-target_files.zip \
        ota_update.zip
    
  • วิธีสร้าง OTA ที่เพิ่มขึ้น
    ./build/make/tools/releasetools/ota_from_target_files \
        -i PREVIOUS-tardis-target_files.zip \
        Dist_output/tardis-target_files.zip \
        ส่วนเพิ่ม_OTA_update.zip
    

กำหนดค่าพาร์ติชัน

update_engine อัปเดตพาร์ติชัน A/B คู่ใดก็ได้ที่กำหนดไว้ในดิสก์เดียวกัน พาร์ติชันคู่มีคำนำหน้าเหมือนกัน (เช่น system หรือ boot) และส่วนต่อท้ายช่อง (เช่น _a) รายการพาร์ติชันที่มีเพย์โหลด โปรแกรมสร้างเป็นตัวกำหนดการอัปเดตที่กำหนดค่าโดยตัวแปรยี่ห้อ AB_OTA_PARTITIONS

เช่น หากพาร์ติชันคู่หนึ่งคือ bootloader_a และ รวม booloader_b (_a และ _b เป็นช่องโฆษณา ต่อท้าย) คุณสามารถอัปเดตพาร์ติชันเหล่านี้ได้โดยระบุข้อมูลต่อไปนี้บนผลิตภัณฑ์หรือบอร์ด การกำหนดค่า:

AB_OTA_PARTITIONS := \
  เปิดเครื่อง \
  ระบบ \
  Bootloader

พาร์ติชันทั้งหมดที่อัปเดตโดย update_engine ต้องไม่แก้ไขโดยส่วนที่เหลือของ ระบบ ในระหว่างการอัปเดตเพิ่มหรือแบบเดลต้า ข้อมูลไบนารีจากช่องปัจจุบันจะเป็น ที่ใช้สร้างข้อมูลในช่องใหม่ การแก้ไขใดๆ อาจทําให้ข้อมูลช่องใหม่ ไม่ผ่านการยืนยันระหว่างกระบวนการอัปเดต ดังนั้นการอัปเดตจึงล้มเหลว

กำหนดค่าหลังการติดตั้ง

คุณกำหนดค่าขั้นตอนหลังการติดตั้งให้แตกต่างกันสำหรับพาร์ติชันที่อัปเดตแต่ละพาร์ติชันได้โดยใช้ชุด คู่คีย์-ค่า หากต้องการเรียกใช้โปรแกรมที่อยู่ที่ /system/usr/bin/postinst ใน ให้ระบุเส้นทางที่สัมพันธ์กับรูทของระบบไฟล์ในพาร์ติชันระบบ

ตัวอย่างเช่น usr/bin/postinst คือ system/usr/bin/postinst (หากไม่ใช่ โดยใช้ดิสก์ RAM) นอกจากนี้ ให้ระบุประเภทระบบไฟล์ที่จะส่งต่อไปยัง การเรียกใช้ระบบ mount(2) เพิ่มข้อมูลต่อไปนี้ลงในผลิตภัณฑ์หรืออุปกรณ์ .mk ไฟล์ (หากมี):

AB_OTA_POSTINSTALL_CONFIG += \
  RUN_POSTINSTALL_system=true \
  POSTINSTALL_PATH_system=usr/bin/postinst \
  FILESYSTEM_TYPE_system=ext4

คอมไพล์แอป

ระบบอาจคอมไพล์แอปในเบื้องหลังก่อนรีบูตด้วยอิมเมจระบบใหม่ เพื่อคอมไพล์ ในเบื้องหลัง ให้เพิ่มค่าต่อไปนี้ในการกำหนดค่าอุปกรณ์ของผลิตภัณฑ์ (ใน device.mk ของผลิตภัณฑ์):

  1. รวมคอมโพเนนต์ดั้งเดิมในบิลด์เพื่อให้แน่ใจว่าสคริปต์คอมไพล์และไบนารีนั้น ได้รับการคอมไพล์และรวมไว้ในอิมเมจของระบบ
      # แพ็กเกจ Dexopt ของ OTA ในระดับ A/B
      PRODUCT_PACKAGES += otapreopt_script
    
  2. เชื่อมต่อสคริปต์การคอมไพล์กับ update_engine ที่เรียกใช้เป็น หลังการติดตั้ง
      # การเชื่อมต่อ A/B OTA dexopt update_engine
      AB_OTA_POSTINSTALL_CONFIG += \
        RUN_POSTINSTALL_system=true \
        POSTINSTALL_PATH_system=ระบบ/bin/otapreopt_script \
        FILESYSTEM_TYPE_system=ext4 \
        POSTINSTALL_OPTIONAL_system=จริง
    

หากต้องการความช่วยเหลือในการติดตั้งไฟล์ซึ่งกำหนดไว้ล่วงหน้าในพาร์ติชันระบบที่ 2 ที่ไม่ได้ใช้ โปรดดู การติดตั้งไฟล์ DEX_PREOPT ครั้งแรก