OEM และผู้จำหน่าย SoC ที่ต้องการใช้การอัปเดตระบบ A/B ต้องแน่ใจว่าโปรแกรมโหลดบูตของตนใช้ 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 ที่จัดรูปแบบในรูปแบบ .
การตั้งค่าตัวแปรบิวด์
bootloaders ที่รองรับ 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 ที่ดาวน์โหลดมา และเพื่อ stash block ชั่วคราวในขณะที่ใช้การอัปเดต ไม่เคยมีวิธีที่ดีในการกำหนดขนาดพาร์ติชั่นแคช: ขนาดใหญ่แค่ไหนขึ้นอยู่กับว่าคุณต้องการใช้อัพเดตใด กรณีที่เลวร้ายที่สุดคือพาร์ติชั่นแคชที่ใหญ่เท่ากับอิมเมจระบบ ด้วยการอัปเดต 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
-
slot-successful:<slot-suffix>
. ส่งคืน "ใช่" หากช่องที่ระบุถูกทำเครื่องหมายว่าบูตสำเร็จ "ไม่" มิฉะนั้น -
slot-unbootable:<slot-suffix>
. ส่งคืน "ใช่" หากช่องที่ระบุถูกทำเครื่องหมายว่าไม่สามารถบูตได้ "ไม่" มิฉะนั้น -
slot-retry-count
. จำนวนครั้งของการลองใหม่ที่เหลือเพื่อพยายามบูตช่องที่กำหนด
หากต้องการดูตัวแปรทั้งหมด ให้รัน 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 \ incremental_ota_update.zip
การกำหนดค่าพาร์ติชั่น
update_engine
สามารถอัปเดตคู่ของพาร์ติชั่น A/B ที่กำหนดไว้ในดิสก์เดียวกัน พาร์ติชั่นคู่หนึ่งมีคำนำหน้าร่วมกัน (เช่น system
หรือ boot
) และส่วนต่อท้ายต่อสล็อต (เช่น _a
) รายการพาร์ติชั่นที่ตัวสร้างเพย์โหลดกำหนดการอัปเดตได้รับการกำหนดค่าโดยตัวแปรสร้าง AB_OTA_PARTITIONS
ตัวอย่างเช่น หากรวมพาร์ติชั่นคู่ bootloader_a
และ booloader_b
( _b
_a
ส่วนต่อท้ายของสล็อต) คุณสามารถอัพเดตพาร์ติชั่นเหล่านี้โดยระบุสิ่งต่อไปนี้บนคอนฟิกูเรชันผลิตภัณฑ์หรือบอร์ด:
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
กำลังรวบรวม
ด้วยเหตุผลด้านความปลอดภัย system_server
ไม่สามารถใช้การคอมไพล์ แบบ just-in-time (JIT) ได้ ซึ่งหมายความว่าคุณต้องคอมไพล์ไฟล์ odex ล่วงหน้าสำหรับ system_server
และการพึ่งพาอย่างน้อยที่สุด อย่างอื่นเป็นตัวเลือก
ในการคอมไพล์แอปในเบื้องหลัง คุณต้องเพิ่มสิ่งต่อไปนี้ในการกำหนดค่าอุปกรณ์ของผลิตภัณฑ์ (ใน 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