OEM และผู้จำหน่าย SoC ที่ต้องการใช้การอัปเดตระบบ A/B จะต้องตรวจสอบให้แน่ใจว่า bootloader ของตนใช้ boot_control HAL และส่ง พารามิเตอร์ที่ถูกต้อง ไปยังเคอร์เนล
ใช้การควบคุมการบูต HAL
bootloaders ที่รองรับ A/B ต้องใช้ boot_control
HAL ที่ hardware/libhardware/include/hardware/boot_control.h
คุณสามารถทดสอบการใช้งานได้โดยใช้ยูทิลิตี system/extras/bootctl
และ system/extras/tests/bootloader/
คุณต้องใช้เครื่องสถานะที่แสดงด้านล่างด้วย:
ตั้งค่าเคอร์เนล
หากต้องการใช้การอัปเดตระบบ A/B:
- Cherrypick ชุดแพทช์เคอร์เนลต่อไปนี้ (หากจำเป็น):
- หากทำการบูทโดยไม่ใช้ ramdisk และใช้ "boot as recovery" ให้ cherrypick android-review.googlesource.com/#/c/158491/
- หากต้องการตั้งค่า dm-verity โดยไม่มี ramdisk ให้ cherrypick android-review.googlesource.com/#/q/status:merged+project:kernel/common+branch:android-3.18+topic:A_B_Changes_3.18
- ตรวจสอบให้แน่ใจว่าอาร์กิวเมนต์บรรทัดคำสั่งเคอร์เนลมีอาร์กิวเมนต์พิเศษต่อไปนี้:
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>
คือ ID ของคีย์สาธารณะที่ใช้ในการตรวจสอบลายเซ็นตารางความจริง (สำหรับรายละเอียด โปรดดูที่ dm-verity ) . - เพิ่มใบรับรอง .X509 ที่มีรหัสสาธารณะไปยังพวงกุญแจระบบ:
- คัดลอกใบรับรอง .X509 ที่จัดรูปแบบในรูปแบบ
.der
ไปยังรากของkernel
เคอร์เนล หากใบรับรอง .X509 มีรูปแบบเป็นไฟล์.pem
ให้ใช้คำสั่งopenssl
ต่อไปนี้เพื่อแปลงจากรูปแบบ.pem
เป็น.der
:openssl x509 -in <x509-pem-certificate> -outform der -out <x509-der-certificate>
- สร้าง
zImage
เพื่อรวมใบรับรองเป็นส่วนหนึ่งของพวงกุญแจระบบ ในการตรวจสอบ ให้ตรวจสอบรายการprocfs
(ต้องเปิดใช้งานKEYS_CONFIG_DEBUG_PROC_KEYS
):angler:/# cat /proc/keys 1c8a217e I------ 1 perm 1f010000 0 0 asymmetri Android: 7e4333f9bba00adfe0ede979e28ed1920492b40f: X509.RSA 0492b40f [] 2d454e3e I------ 1 perm 1f030000 0 0 keyring .system_keyring: 1/4
การรวมใบรับรอง .X509 ได้สำเร็จบ่งชี้ว่ามีคีย์สาธารณะอยู่ในคีย์ริงของระบบ (ไฮไลต์หมายถึง ID คีย์สาธารณะ) - แทนที่ช่องว่างด้วย
#
และส่งผ่านเป็น<public-key-id>
ในบรรทัดคำสั่งเคอร์เนล ตัวอย่างเช่น ส่งAndroid:#7e4333f9bba00adfe0ede979e28ed1920492b40f
แทน<public-key-id>
- คัดลอกใบรับรอง .X509 ที่จัดรูปแบบในรูปแบบ
ตั้งค่าตัวแปรบิวด์
บูตโหลดเดอร์ที่รองรับ A/B ต้องเป็นไปตามเกณฑ์ตัวแปรบิวด์ต่อไปนี้:
ต้องกำหนดเป้าหมาย A/B |
/device/google/marlin/+/android-7.1.0_r1/device-common.mk คุณสามารถเลือกดำเนินการขั้นตอน dex2oat หลังการติดตั้ง (แต่ก่อนรีบูต) ที่อธิบายไว้ใน การคอมไพล์ |
---|---|
ขอแนะนำอย่างยิ่งสำหรับเป้าหมาย A/B |
|
ไม่สามารถกำหนดเป้าหมาย A/B ได้ |
|
ทางเลือกสำหรับบิลด์การดีบัก | 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 พาร์ติชั่นการกู้คืนจะมีโค้ดที่ใช้ในการอัพเดต การอัปเดต A/B จะถูกใช้โดย update_engine
ที่ทำงานอยู่ในอิมเมจระบบที่บูตตามปกติ ยังคงมีโหมดการกู้คืนที่ใช้ในการรีเซ็ตข้อมูลเป็นค่าเริ่มต้นและไซด์โหลดแพ็คเกจการอัปเดต (ซึ่งเป็นที่มาของชื่อ "การกู้คืน") รหัสและข้อมูลสำหรับโหมดการกู้คืนจะถูกจัดเก็บไว้ในพาร์ติชันสำหรับเริ่มระบบปกติใน ramdisk ในการบูตเข้าสู่อิมเมจระบบ bootloader จะบอกให้เคอร์เนลข้าม ramdisk (ไม่เช่นนั้นอุปกรณ์จะบู๊ตเข้าสู่โหมดการกู้คืน โหมดการกู้คืนมีขนาดเล็ก (และส่วนใหญ่อยู่ในพาร์ติชันสำหรับเริ่มระบบแล้ว) ดังนั้นพาร์ติชันสำหรับบูตจึงไม่เพิ่มขึ้น ในขนาด.
Fstab
อาร์กิวเมนต์ slotselect
ต้อง อยู่ในบรรทัดสำหรับพาร์ติชัน A/B-ed ตัวอย่างเช่น:
<path-to-block-device>/vendor /vendor ext4 ro wait,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>
ส่งคืน "ใช่" หากพาร์ติชันที่กำหนดรองรับสล็อต มิฉะนั้น "ไม่" -
current-slot
ส่งคืนส่วนต่อท้ายสล็อตที่จะถูกบูตจากครั้งถัดไป -
slot-count
ส่งกลับจำนวนเต็มที่แสดงถึงจำนวนช่องที่มีอยู่ ปัจจุบัน รองรับช่อง 2 ช่อง ดังนั้นค่านี้คือ2
-
slot-successful:<slot-suffix>
. ส่งคืน "ใช่" หากช่องที่กำหนดถูกทำเครื่องหมายว่าบูตได้สำเร็จ มิฉะนั้น "ไม่" -
slot-unbootable:<slot-suffix>
. ส่งคืน "ใช่" หากช่องที่ระบุถูกทำเครื่องหมายว่าไม่สามารถบูตได้ หากไม่เป็นเช่นนั้น ให้ "ไม่" -
slot-retry-count
. จำนวนครั้งในการลองใหม่ที่เหลืออยู่เพื่อพยายามบูตช่องที่กำหนด
หากต้องการดูตัวแปรทั้งหมด ให้รัน fastboot getvar all
สร้างแพ็คเกจ OTA
เครื่องมือแพ็คเกจ OTA ทำตามคำสั่งเดียวกันกับคำสั่งสำหรับอุปกรณ์ที่ไม่ใช่ A/B ไฟล์ target_files.zip
ต้องถูกสร้างขึ้นโดยการกำหนดตัวแปร build สำหรับเป้าหมาย 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 \ incremental_ota_update.zip
กำหนดค่าพาร์ติชัน
update_engine
สามารถอัพเดตคู่พาร์ติชั่น A/B ใดๆ ที่กำหนดไว้ในดิสก์เดียวกัน คู่ของพาร์ติชันมีคำนำหน้าทั่วไป (เช่น system
หรือ boot
) และส่วนต่อท้ายต่อสล็อต (เช่น _a
) รายการพาร์ติชันที่ตัวสร้างเพย์โหลดกำหนดการอัปเดตได้รับการกำหนดค่าโดยตัวแปร make AB_OTA_PARTITIONS
ตัวอย่างเช่น หากมีคู่ของพาร์ติชัน bootloader_a
และ booloader_b
รวมอยู่ด้วย ( _a
และ _b
เป็นส่วนต่อท้ายของสล็อต) คุณสามารถอัพเดตพาร์ติชันเหล่านี้ได้โดยการระบุสิ่งต่อไปนี้บนผลิตภัณฑ์หรือคอนฟิกูเรชันของบอร์ด:
AB_OTA_PARTITIONS := \ boot \ system \ 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 ของผลิตภัณฑ์):
- รวมส่วนประกอบดั้งเดิมไว้ในบิลด์เพื่อให้แน่ใจว่าสคริปต์การคอมไพล์และไบนารีได้รับการคอมไพล์และรวมอยู่ในอิมเมจระบบ
# A/B OTA dexopt package PRODUCT_PACKAGES += otapreopt_script
- เชื่อมต่อสคริปต์การคอมไพล์กับ
update_engine
ซึ่งรันเป็นขั้นตอนหลังการติดตั้ง# A/B OTA dexopt update_engine hookup AB_OTA_POSTINSTALL_CONFIG += \ RUN_POSTINSTALL_system=true \ POSTINSTALL_PATH_system=system/bin/otapreopt_script \ FILESYSTEM_TYPE_system=ext4 \ POSTINSTALL_OPTIONAL_system=true
หากต้องการความช่วยเหลือในการติดตั้งไฟล์ที่เลือกใช้ล่วงหน้าในพาร์ติชันระบบที่สองที่ไม่ได้ใช้ โปรดดูที่ การติดตั้งการบูตครั้งแรกของไฟล์ DEX_PREOPT