การอัปเดตระบบ A/B หรือที่เรียกว่าการอัปเดตแบบไม่มีสะดุด ช่วยให้มั่นใจว่าระบบการบูตที่ใช้งานได้จะยังคงอยู่บนดิสก์ระหว่างการ อัปเดตแบบ over-the-air (OTA) วิธีนี้ช่วยลดโอกาสที่อุปกรณ์ที่ไม่ได้ใช้งานหลังการอัปเดต ซึ่งหมายความว่ามีการเปลี่ยนอุปกรณ์และการรีเฟลชอุปกรณ์ที่ศูนย์ซ่อมและการรับประกันน้อยลง ระบบปฏิบัติการเชิงพาณิชย์อื่นๆ เช่น ChromeOS ก็ใช้การอัปเดต A/B ได้สำเร็จเช่นกัน
สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการอัปเดตระบบ A/B และวิธีการทำงาน โปรดดูที่ การเลือกพาร์ติชัน (สล็อต)
การอัปเดตระบบ A/B มีประโยชน์ดังต่อไปนี้:
- การอัปเดต OTA สามารถเกิดขึ้นได้ในขณะที่ระบบกำลังทำงานโดยไม่รบกวนผู้ใช้ ผู้ใช้สามารถใช้อุปกรณ์ของตนต่อไปได้ระหว่าง OTA—การหยุดทำงานเพียงอย่างเดียวระหว่างการอัปเดตคือเมื่ออุปกรณ์รีบูตในพาร์ติชั่นดิสก์ที่อัพเดต
- หลังจากการอัพเดต การรีบูตจะใช้เวลาไม่เกินการรีบูตปกติ
- หากใช้ OTA ไม่ได้ (เช่น เนื่องจากแฟลชไม่ดี) ผู้ใช้จะไม่ได้รับผลกระทบ ผู้ใช้จะใช้ระบบปฏิบัติการเก่าต่อไป และไคลเอ็นต์สามารถลองอัปเดตอีกครั้งได้ฟรี
- หากมีการใช้การอัปเดต OTA แต่ไม่สามารถบู๊ตได้ อุปกรณ์จะรีบูตกลับเข้าไปในพาร์ติชั่นเก่าและยังคงใช้งานได้ ไคลเอ็นต์มีอิสระที่จะลองอัปเดตอีกครั้ง
- ข้อผิดพลาดใดๆ (เช่น ข้อผิดพลาด I/O) มีผลกับชุดพาร์ติชันที่ ไม่ได้ใช้ เท่านั้น และสามารถลองใหม่ได้ ข้อผิดพลาดดังกล่าวก็มีโอกาสน้อยลงเช่นกันเนื่องจากโหลด I/O นั้นต่ำโดยเจตนาเพื่อหลีกเลี่ยงการทำให้ประสบการณ์ของผู้ใช้ลดลง
- สามารถสตรีมการอัปเดตไปยังอุปกรณ์ A/B โดยไม่จำเป็นต้องดาวน์โหลดแพ็คเกจก่อนทำการติดตั้ง การสตรีมหมายความว่าผู้ใช้ไม่จำเป็นต้องมีพื้นที่ว่างเพียงพอในการจัดเก็บแพ็คเกจการอัปเดตใน
/data
หรือ/cache
- พาร์ติชั่นแคชไม่ได้ใช้เพื่อจัดเก็บแพ็คเกจการอัปเดต OTA อีกต่อไป ดังนั้นจึงไม่จำเป็นต้องตรวจสอบให้แน่ใจว่าพาร์ติชั่นแคชมีขนาดใหญ่พอสำหรับการอัปเดตในอนาคต
- dm-verity รับประกันว่าอุปกรณ์จะบู๊ตภาพที่ไม่เสียหาย หากอุปกรณ์ไม่บู๊ตเนื่องจากปัญหา OTA หรือ dm-verity ที่ไม่ดี อุปกรณ์สามารถรีบูตเป็นอิมเมจเก่าได้ (Android Verified Boot ไม่ต้องการการอัปเดต A/B)
เกี่ยวกับการอัปเดตระบบ A/B
การอัปเดต A/B จำเป็นต้องเปลี่ยนแปลงทั้งไคลเอ็นต์และระบบ อย่างไรก็ตาม เซิร์ฟเวอร์แพ็คเกจ OTA ไม่จำเป็นต้องมีการเปลี่ยนแปลง: แพ็คเกจการอัปเดตยังคงให้บริการผ่าน HTTPS สำหรับอุปกรณ์ที่ใช้โครงสร้างพื้นฐาน OTA ของ Google การเปลี่ยนแปลงระบบทั้งหมดอยู่ใน AOSP และรหัสไคลเอ็นต์มีให้โดยบริการ Google Play OEM ที่ไม่ได้ใช้โครงสร้างพื้นฐาน OTA ของ Google จะสามารถใช้รหัสระบบ AOSP ซ้ำได้ แต่จะต้องจัดหาไคลเอ็นต์ของตนเอง
สำหรับ OEM ที่จัดหาลูกค้าของตนเอง ลูกค้าต้อง:
- ตัดสินใจว่าจะอัปเดตเมื่อใด เนื่องจากการอัปเดต A/B เกิดขึ้นในพื้นหลัง จึงไม่ได้เริ่มต้นโดยผู้ใช้อีกต่อไป เพื่อหลีกเลี่ยงการรบกวนผู้ใช้ ขอแนะนำให้กำหนดเวลาอัปเดตเมื่ออุปกรณ์อยู่ในโหมดการบำรุงรักษาที่ไม่ได้ใช้งาน เช่น ข้ามคืน และเปิด Wi-Fi อย่างไรก็ตาม ลูกค้าของคุณสามารถใช้การวิเคราะห์พฤติกรรมใดๆ ที่คุณต้องการได้
- ตรวจสอบกับเซิร์ฟเวอร์แพ็คเกจ OTA ของคุณและตรวจสอบว่ามีการอัปเดตหรือไม่ ซึ่งควรจะเหมือนกับรหัสลูกค้าที่มีอยู่เป็นส่วนใหญ่ ยกเว้นว่าคุณจะต้องการส่งสัญญาณว่าอุปกรณ์รองรับ A/B (ไคลเอ็นต์ของ Google ยังมีปุ่ม " ตรวจ สอบเลย" ให้ผู้ใช้ตรวจสอบการอัปเดตล่าสุดด้วย)
- โทร
update_engine
ด้วย HTTPS URL สำหรับแพ็คเกจการอัพเดทของคุณ สมมติว่ามีupdate_engine
จะอัปเดตบล็อกดิบบนพาร์ติชั่นที่ไม่ได้ใช้ในปัจจุบันในขณะที่สตรีมแพ็คเกจอัพเดต - รายงานความสำเร็จหรือความล้มเหลวในการติดตั้งไปยังเซิร์ฟเวอร์ของคุณ ตามรหัสผลลัพธ์ของ
update_engine
หากใช้การอัปเดตสำเร็จupdate_engine
จะแจ้งให้ bootloader บูตเข้าสู่ระบบปฏิบัติการใหม่ในการรีบูตครั้งถัดไป bootloader จะย้อนกลับไปใช้ OS เก่าหาก OS ใหม่ไม่สามารถบู๊ตได้ ดังนั้นจึงไม่จำเป็นต้องดำเนินการใดๆ จากไคลเอ็นต์ หากการอัปเดตล้มเหลว ไคลเอ็นต์จำเป็นต้องตัดสินใจว่าจะลองอีกครั้งเมื่อใด (และหรือไม่) ตามรหัสข้อผิดพลาดโดยละเอียด ตัวอย่างเช่น ลูกค้าที่ดีสามารถรับรู้ได้ว่าแพ็คเกจ OTA บางส่วน ("diff") ล้มเหลวและลองใช้แพ็คเกจ OTA แบบเต็มแทน
ลูกค้าสามารถ:
- แสดงการแจ้งเตือนที่ขอให้ผู้ใช้รีบูต หากคุณต้องการใช้นโยบายที่แนะนำให้ผู้ใช้อัปเดตเป็นประจำ คุณสามารถเพิ่มการแจ้งเตือนนี้ไปยังไคลเอนต์ของคุณได้ หากไคลเอ็นต์ไม่แสดงข้อความแจ้งผู้ใช้ ผู้ใช้จะได้รับการอัปเดตในครั้งต่อไปที่รีบูต (ไคลเอนต์ของ Google มีความล่าช้าที่กำหนดค่าได้ต่อการอัปเดต)
- แสดงการแจ้งเตือนที่แจ้งให้ผู้ใช้ทราบว่าพวกเขาบูตระบบปฏิบัติการเป็นเวอร์ชันใหม่หรือไม่ หรือคาดว่าพวกเขาจะทำเช่นนั้น แต่จะกลับไปใช้ระบบปฏิบัติการเวอร์ชันเก่า (ลูกค้าของ Google มักจะไม่ทำเช่นนั้น)
ทางฝั่งระบบ การอัปเดตระบบ A/B จะมีผลดังต่อไปนี้:
- การเลือกพาร์ติชัน (สล็อต),
update_engine
daemon และการโต้ตอบของ bootloader (อธิบายด้านล่าง) - กระบวนการสร้างและการสร้างแพ็คเกจการอัปเดต OTA (อธิบายไว้ใน Implementing A/B Updates )
การเลือกพาร์ติชั่น (สล็อต)
การอัพเดตระบบ A/B ใช้พาร์ติชั่นสองชุดที่เรียกว่า สล็อต (ปกติคือสล็อต A และสล็อต B) ระบบรันจากสล็อต ปัจจุบัน ในขณะที่พาร์ติชั่นในสล็อตที่ ไม่ได้ใช้ จะไม่ถูกเข้าถึงโดยระบบที่ทำงานอยู่ระหว่างการทำงานปกติ วิธีการนี้ทำให้การอัปเดตสามารถต้านทานข้อผิดพลาดได้โดยการรักษาสล็อตที่ไม่ได้ใช้ไว้เป็นทางเลือกสำรอง: หากเกิดข้อผิดพลาดระหว่างหรือทันทีหลังจากการอัพเดต ระบบสามารถย้อนกลับไปยังสล็อตเก่าและยังคงมีระบบการทำงานต่อไป เพื่อให้บรรลุเป้าหมายนี้ ไม่ควรอัปเดตพาร์ติชันที่ใช้โดยสล็อต ปัจจุบัน เป็นส่วนหนึ่งของการอัปเดต OTA (รวมถึงพาร์ติชันที่มีเพียงสำเนาเดียว)
แต่ละสล็อตมีแอททริบิวต์ที่ สามารถบู๊ตได้ ซึ่งระบุว่าสล็อตมีระบบที่ถูกต้องซึ่งอุปกรณ์สามารถบู๊ตได้หรือไม่ สล็อตปัจจุบันสามารถบู๊ตได้เมื่อระบบกำลังทำงาน แต่สล็อตอื่นอาจมีระบบเวอร์ชันเก่า (ยังคงถูกต้อง) เวอร์ชันที่ใหม่กว่า หรือมีข้อมูลที่ไม่ถูกต้อง ไม่ว่าสล็อต ปัจจุบัน คืออะไร มีสล็อตหนึ่งสล็อตที่เป็นสล็อตที่ ใช้งานอยู่ (อันที่โปรแกรมโหลดบูตจะบูตจากการบู๊ตครั้งถัดไป) หรือสล็อต ที่ต้องการ
แต่ละช่องยังมีแอตทริบิวต์ที่ ประสบความสำเร็จ ซึ่งกำหนดโดยพื้นที่ผู้ใช้ ซึ่งมีความเกี่ยวข้องก็ต่อเมื่อช่องนั้นสามารถบูตได้เช่นกัน สล็อตที่ประสบความสำเร็จควรจะสามารถบู๊ต รัน และอัพเดตตัวเองได้ สล็อตที่สามารถบู๊ตได้ซึ่งไม่ได้ทำเครื่องหมายว่าสำเร็จ (หลังจากพยายามบู๊ตหลายครั้ง) ควรทำเครื่องหมายว่า bootloader ว่าไม่สามารถบู๊ตได้ รวมถึงการเปลี่ยนสล็อตที่แอ็คทีฟเป็นสล็อตอื่นที่สามารถบู๊ตได้ (โดยปกติจะเป็นสล็อตที่รันทันทีก่อนพยายามบู๊ต ใหม่ที่ใช้งาน) รายละเอียดเฉพาะของอินเทอร์เฟซถูกกำหนดไว้ใน boot_control.h
อัพเดทเดมอนเครื่องยนต์
การอัปเดตระบบ A/B ใช้ดีมอนพื้นหลังที่เรียกว่า update_engine
เพื่อเตรียมระบบให้บูตเข้าสู่เวอร์ชันใหม่ที่ได้รับการอัปเดต daemon นี้สามารถดำเนินการดังต่อไปนี้:
- อ่านจากพาร์ติชั่น A/B ของสล็อตปัจจุบัน และเขียนข้อมูลใดๆ ไปยังพาร์ติชั่น A/B ของสล็อตที่ไม่ได้ใช้ตามคำแนะนำของแพ็คเกจ OTA
- เรียกใช้อินเทอร์เฟซ
boot_control
ในเวิร์กโฟลว์ที่กำหนดไว้ล่วงหน้า - รันโปรแกรม หลังการติดตั้ง จากพาร์ติชั่น ใหม่ หลังจากเขียนพาร์ติชั่นสล็อตที่ไม่ได้ใช้ทั้งหมด ตามคำแนะนำของแพ็คเกจ OTA (สำหรับรายละเอียด โปรดดู หลังการติดตั้ง )
เนื่องจาก update_engine
daemon ไม่ได้เกี่ยวข้องกับกระบวนการบู๊ต จึงมีข้อ จำกัด ในสิ่งที่สามารถทำได้ในระหว่างการอัพเดตโดยนโยบายและคุณสมบัติ SELinux ในสล็อต ปัจจุบัน (นโยบายและคุณสมบัติดังกล่าวไม่สามารถอัปเดตได้จนกว่าระบบจะบู๊ตเป็น เวอร์ชั่นใหม่). เพื่อรักษาระบบที่แข็งแกร่ง กระบวนการอัพเดต ไม่ควร แก้ไขตารางพาร์ติชั่น เนื้อหาของพาร์ติชั่นในช่องปัจจุบัน หรือเนื้อหาของพาร์ติชั่นที่ไม่ใช่ A/B ที่ไม่สามารถล้างข้อมูลด้วยการรีเซ็ตเป็นค่าจากโรงงาน
อัปเดตแหล่งที่มาของเครื่องยนต์
แหล่งที่มาของ update_engine
อยู่ใน system/update_engine
ไฟล์ A/B OTA dexopt ถูกแยกระหว่าง installd
และ package manager:
-
frameworks/native/cmds/installd/
ota* รวมถึงสคริปต์หลังการติดตั้ง, ไบนารีสำหรับ chroot, โคลนที่ติดตั้งที่เรียก dex2oat, สคริปต์ post-OTA move-artifacts และไฟล์ rc สำหรับสคริปต์การย้าย -
frameworks/base/services/core/java/com/android/server/pm/OtaDexoptService.java
(บวกOtaDexoptShellCommand
) เป็นตัวจัดการแพ็คเกจที่เตรียมคำสั่ง dex2oat สำหรับแอปพลิเคชัน
สำหรับตัวอย่างการทำงาน โปรดดูที่ /device/google/marlin/device-common.mk
อัพเดทบันทึกเครื่องยนต์
สำหรับ Android 8.x ที่ออกวางจำหน่ายและรุ่นก่อนหน้า สามารถพบบันทึก update_engine
ได้ใน logcat
และในรายงานข้อบกพร่อง หากต้องการให้บันทึก update_engine
พร้อมใช้งานในระบบไฟล์ ให้แก้ไขการเปลี่ยนแปลงต่อไปนี้ในบิลด์ของคุณ:
การเปลี่ยนแปลงเหล่านี้จะบันทึกสำเนาบันทึกของ update_engine
ล่าสุดไปที่ /data/misc/update_engine_log/update_engine. YEAR - TIME
. นอกจากบันทึกปัจจุบันแล้ว รายการบันทึกล่าสุดห้ารายการยังถูกบันทึกภายใต้ /data/misc/update_engine_log/
ผู้ใช้ที่มี ID กลุ่ม บันทึก จะสามารถเข้าถึงบันทึกของระบบไฟล์ได้
การโต้ตอบของ Bootloader
boot_control
HAL ถูกใช้โดย update_engine
(และอาจเป็นภูตอื่น ๆ ) เพื่อสั่ง bootloader ว่าควรบูตจากอะไร สถานการณ์ตัวอย่างทั่วไปและสถานะที่เกี่ยวข้องมีดังต่อไปนี้:
- กรณีปกติ : ระบบกำลังทำงานจากช่องปัจจุบัน ไม่ว่าจะเป็นช่อง A หรือ B ยังไม่มีการอัปเดตใดๆ สล็อตปัจจุบันของระบบสามารถบู๊ตได้ สำเร็จ และสล็อตที่ใช้งานอยู่
- กำลังอัปเดต : ระบบกำลังทำงานจากสล็อต B ดังนั้นสล็อต B จึงเป็นสล็อตที่สามารถบู๊ตได้ สำเร็จ และใช้งานอยู่ สล็อต A ถูกทำเครื่องหมายว่าไม่สามารถบูตได้ เนื่องจากเนื้อหาของสล็อต A กำลังได้รับการอัปเดตแต่ยังไม่เสร็จสมบูรณ์ การรีบูตในสถานะนี้ควรทำการบูทต่อจากสล็อต B
- ใช้การอัปเดต การรีบูตที่รอดำเนิน การ : ระบบกำลังทำงานจากสล็อต B สล็อต B สามารถบู๊ตได้และประสบความสำเร็จ แต่สล็อต A ถูกทำเครื่องหมายว่าใช้งานได้ (และดังนั้นจึงถูกทำเครื่องหมายว่าบู๊ตได้) สล็อต A ยังไม่ถูกทำเครื่องหมายว่าสำเร็จ และจำนวนครั้งในการพยายามบูตจากสล็อต A ควรทำโดยโปรแกรมโหลดบูต
- ระบบรีบูตเป็นการอัปเดตใหม่ : ระบบกำลังทำงานจากสล็อต A เป็นครั้งแรก สล็อต B ยังคงสามารถบู๊ตได้และประสบความสำเร็จในขณะที่สล็อต A สามารถบู๊ตได้เท่านั้นและยังคงทำงานอยู่ แต่ไม่สำเร็จ daemon พื้นที่ผู้ใช้
update_verifier
ควรทำเครื่องหมายสล็อต A ว่าสำเร็จหลังจากทำการตรวจสอบแล้ว
รองรับการอัปเดตสตรีมมิ่ง
อุปกรณ์ของผู้ใช้ไม่มีที่ว่างเพียงพอใน /data
เพื่อดาวน์โหลดแพ็คเกจการอัปเดตเสมอไป เนื่องจากทั้ง OEM และผู้ใช้ไม่ต้องการเปลืองพื้นที่บนพาร์ติชั่น /cache
ผู้ใช้บางคนจึงไปโดยไม่มีการอัปเดตเนื่องจากอุปกรณ์ไม่มีที่สำหรับจัดเก็บแพ็คเกจการอัปเดต เพื่อแก้ไขปัญหานี้ Android 8.0 ได้เพิ่มการรองรับการสตรีมการอัปเดต A/B ที่เขียนบล็อกโดยตรงไปยังพาร์ติชัน B เมื่อดาวน์โหลด โดยไม่ต้องเก็บบล็อกใน /data
การอัปเดต A/B แบบสตรีมไม่จำเป็นต้องมีที่เก็บข้อมูลชั่วคราวและต้องการพื้นที่เก็บข้อมูลเพียงพอสำหรับข้อมูลเมตาประมาณ 100 KiB
หากต้องการเปิดใช้งานการอัปเดตการสตรีมใน Android 7.1 โปรดเลือกแพตช์ต่อไปนี้:
- อนุญาตให้ยกเลิกคำขอแก้ไขพร็อกซี
- แก้ไขการยกเลิกการโอนในขณะที่แก้ไขพร็อกซี่
- เพิ่มการทดสอบหน่วยสำหรับ TerminateTransfer ระหว่างช่วง
- ล้างข้อมูล RetryTimeoutCallback()
แพตช์เหล่านี้จำเป็นสำหรับการรองรับการสตรีมการอัปเดต A/B ใน Android 7.1 และใหม่กว่า ไม่ว่าจะใช้ Google Mobile Services (GMS) หรือไคลเอ็นต์การอัปเดตอื่นๆ
ชีวิตของการอัปเดต A/B
กระบวนการอัปเดตเริ่มต้นเมื่อแพ็คเกจ OTA (ในโค้ดเรียกว่าเพย์ โหลด ) พร้อมให้ดาวน์โหลด นโยบายในอุปกรณ์อาจเลื่อนการดาวน์โหลดเพย์โหลดและแอปพลิเคชันตามระดับแบตเตอรี่ กิจกรรมของผู้ใช้ สถานะการชาร์จ หรือนโยบายอื่นๆ นอกจากนี้ เนื่องจากการอัปเดตทำงานในเบื้องหลัง ผู้ใช้อาจไม่ทราบว่ากำลังดำเนินการอัปเดต ทั้งหมดนี้หมายความว่ากระบวนการอัปเดตอาจถูกขัดจังหวะเมื่อใดก็ได้เนื่องจากนโยบาย การรีบูตโดยไม่คาดคิด หรือการกระทำของผู้ใช้
ข้อมูลเมตาในแพ็คเกจ OTA เองระบุว่าการอัปเดตสามารถสตรีมได้ แพ็คเกจเดียวกันนี้ยังสามารถใช้สำหรับการติดตั้งที่ไม่ใช่การสตรีม เซิร์ฟเวอร์อาจใช้ข้อมูลเมตาเพื่อบอกไคลเอ็นต์ว่ากำลังสตรีม ดังนั้นไคลเอ็นต์จะส่งต่อ OTA เพื่อ update_engine
อย่างถูกต้อง ผู้ผลิตอุปกรณ์ที่มีเซิร์ฟเวอร์และไคลเอนต์ของตนเองสามารถเปิดใช้งานการอัปเดตการสตรีมโดยตรวจสอบให้แน่ใจว่าเซิร์ฟเวอร์ระบุว่าการอัปเดตกำลังสตรีม (หรือถือว่าการอัปเดตทั้งหมดเป็นการสตรีม) และไคลเอ็นต์ทำการเรียก update_engine
สำหรับการสตรีมที่ถูกต้อง ผู้ผลิตสามารถใช้ความจริงที่ว่าแพ็คเกจนั้นเป็นตัวแปรการสตรีมเพื่อส่งแฟล็กไปยังไคลเอนต์เพื่อส่งไปยังฝั่งเฟรมเวิร์กเป็นการสตรีม
หลังจากเพย์โหลดพร้อมใช้งาน กระบวนการอัพเดตจะเป็นดังนี้:
ขั้นตอน | กิจกรรม |
---|---|
1 | ช่องปัจจุบัน (หรือ "ช่องต้นทาง") ถูกทำเครื่องหมายว่าสำเร็จ (หากยังไม่ได้ทำเครื่องหมาย) ด้วย markBootSuccessful() |
2 | ช่องที่ไม่ได้ใช้ (หรือ "ช่องเป้าหมาย") ถูกทำเครื่องหมายว่าไม่สามารถบูตได้โดยการเรียกใช้ฟังก์ชัน setSlotAsUnbootable() สล็อตปัจจุบันจะถูกทำเครื่องหมายว่าสำเร็จในตอนเริ่มต้นของการอัปเดตเสมอ เพื่อป้องกันไม่ให้ bootloader ถอยกลับไปยังสล็อตที่ไม่ได้ใช้ ซึ่งจะมีข้อมูลที่ไม่ถูกต้องในเร็วๆ นี้ หากระบบมาถึงจุดที่เริ่มใช้การอัปเดตได้ ช่องปัจจุบันจะถูกทำเครื่องหมายว่าสำเร็จแม้ว่าส่วนประกอบหลักอื่นๆ จะเสียหาย (เช่น UI ในลูปการขัดข้อง) เนื่องจากสามารถผลักดันซอฟต์แวร์ใหม่เพื่อแก้ไขปัญหาเหล่านี้ได้ ปัญหา.เพย์โหลดการอัพเดทเป็นหยดทึบแสงพร้อมคำแนะนำในการอัปเดตเป็นเวอร์ชันใหม่ เพย์โหลดการอัพเดทประกอบด้วยสิ่งต่อไปนี้:
|
3 | ดาวน์โหลดข้อมูลเมตาของเพย์โหลดแล้ว |
4 | สำหรับแต่ละการดำเนินการที่กำหนดไว้ในข้อมูลเมตา ข้อมูลที่เกี่ยวข้อง (ถ้ามี) จะถูกดาวน์โหลดไปยังหน่วยความจำตามลำดับ การดำเนินการจะถูกนำไปใช้ และหน่วยความจำที่เกี่ยวข้องจะถูกละทิ้ง |
5 | พาร์ติชั่นทั้งหมดจะถูกอ่านซ้ำและตรวจสอบกับแฮชที่คาดไว้ |
6 | ขั้นตอนหลังการติดตั้ง (ถ้ามี) รันอยู่ ในกรณีที่มีข้อผิดพลาดระหว่างดำเนินการตามขั้นตอนใดๆ การอัปเดตจะล้มเหลวและจะพยายามอีกครั้งโดยอาจมีเพย์โหลดอื่น หากขั้นตอนทั้งหมดสำเร็จ การอัปเดตจะสำเร็จและจะดำเนินการตามขั้นตอนสุดท้าย |
7 | สล็อตที่ไม่ได้ใช้ ถูกทำเครื่องหมายว่าใช้งานอยู่โดยการเรียก setActiveBootSlot() การทำเครื่องหมายสล็อตที่ไม่ได้ใช้ว่าใช้งานอยู่ไม่ได้หมายความว่าจะทำการบูทเสร็จ bootloader (หรือตัวระบบเอง) สามารถเปลี่ยนสล็อตที่แอ็คทีฟกลับมาได้ หากไม่สามารถอ่านสถานะที่สำเร็จได้ |
8 | หลังการติดตั้ง (อธิบายด้านล่าง) เกี่ยวข้องกับการเรียกใช้โปรแกรมจากเวอร์ชัน "อัปเดตใหม่" ในขณะที่ยังคงทำงานในเวอร์ชันเก่า หากกำหนดไว้ในแพ็คเกจ OTA ขั้นตอนนี้ จำเป็น และโปรแกรมต้องส่งคืนพร้อมรหัสออก 0 ; มิฉะนั้น การอัปเดตจะล้มเหลว | 9 | หลังจากที่ระบบบู๊ตสำเร็จในสล็อตใหม่มากพอและเสร็จสิ้นการตรวจสอบหลังรีบูต ตอนนี้สล็อตปัจจุบัน (เดิมคือ "สล็อตเป้าหมาย") จะถูกทำเครื่องหมายว่าสำเร็จโดยการเรียก markBootSuccessful() |
หลังการติดตั้ง
สำหรับทุกพาร์ติชั่นที่มีการกำหนดขั้นตอนหลังการติดตั้ง update_engine
เมาท์พาร์ติชั่นใหม่ในตำแหน่งเฉพาะและรันโปรแกรมที่ระบุใน OTA ที่สัมพันธ์กับพาร์ติชั่นที่เมาท์ ตัวอย่างเช่น หากโปรแกรมหลังการติดตั้งถูกกำหนดเป็น usr/bin/postinstall
ในพาร์ติชันระบบ พาร์ติชันนี้จากสล็อตที่ไม่ได้ใช้จะถูกเมาต์ในตำแหน่งคงที่ (เช่น /postinstall_mount
) และ /postinstall_mount/usr/bin/postinstall
คำสั่ง /postinstall_mount/usr/bin/postinstall
ถูกดำเนินการ
เพื่อให้การติดตั้งสำเร็จ เคอร์เนลเก่าจะต้องสามารถ:
- เมานต์รูปแบบระบบไฟล์ใหม่ ประเภทระบบไฟล์ไม่สามารถเปลี่ยนแปลงได้ เว้นแต่จะมีการรองรับในเคอร์เนลเก่า รวมถึงรายละเอียดต่างๆ เช่น อัลกอริธึมการบีบอัดที่ใช้หากใช้ระบบไฟล์ที่บีบอัด (เช่น SquashFS)
- ทำความเข้าใจรูปแบบโปรแกรมหลังการติดตั้งของพาร์ติชันใหม่ หากใช้ไบนารี Executable and Linkable Format (ELF) ก็ควรเข้ากันได้กับเคอร์เนลเก่า (เช่น โปรแกรมใหม่ 64 บิตที่ทำงานบนเคอร์เนล 32 บิตแบบเก่า หากสถาปัตยกรรมเปลี่ยนจากบิลด์ 32- เป็น 64 บิต) เว้นแต่ว่าตัวโหลด (
ld
) จะได้รับคำสั่งให้ใช้พาธอื่นหรือสร้างไบนารีแบบสแตติก ไลบรารีจะถูกโหลดจากอิมเมจระบบเก่าและไม่ใช่อิมเมจใหม่
ตัวอย่างเช่น คุณสามารถใช้เชลล์สคริปต์เป็นโปรแกรมหลังการติดตั้งซึ่งแปลโดยเชลล์ไบนารีของระบบเก่าด้วย #!
ที่ด้านบนสุด) จากนั้นตั้งค่าพาธไลบรารีจากสภาพแวดล้อมใหม่สำหรับการรันโปรแกรมไบนารีหลังการติดตั้งที่ซับซ้อนมากขึ้น อีกวิธีหนึ่ง คุณสามารถเรียกใช้ขั้นตอนหลังการติดตั้งจากพาร์ติชันที่มีขนาดเล็กกว่าโดยเฉพาะ เพื่อเปิดใช้งานรูปแบบระบบไฟล์ในพาร์ติชันระบบหลักเพื่ออัปเดตโดยไม่เกิดปัญหาความเข้ากันได้แบบย้อนหลังหรือการอัปเดตแบบสเต็ปปิ้งสโตน ซึ่งจะทำให้ผู้ใช้สามารถอัปเดตเป็นเวอร์ชันล่าสุดได้โดยตรงจากอิมเมจจากโรงงาน
โปรแกรมหลังการติดตั้งใหม่ถูกจำกัดโดยนโยบาย SELinux ที่กำหนดไว้ในระบบเก่า ดังนั้น ขั้นตอนหลังการติดตั้งจึงเหมาะสำหรับการทำงานที่ต้องการโดยการออกแบบบนอุปกรณ์ที่กำหนดหรืองานอื่นๆ ที่มีความพยายามสูงสุด (เช่น การอัปเดตเฟิร์มแวร์หรือโปรแกรมโหลดบูตที่รองรับ A/B การเตรียมสำเนาของฐานข้อมูลสำหรับเวอร์ชันใหม่ เป็นต้น ). ขั้นตอนหลังการติดตั้ง ไม่เหมาะ สำหรับการแก้ไขจุดบกพร่องแบบครั้งเดียวก่อนรีบูตซึ่งต้องใช้สิทธิ์ที่ไม่คาดฝัน
โปรแกรมหลังการติดตั้งที่เลือกทำงานในบริบท postinstall
หลังการติดตั้ง ไฟล์ทั้งหมดในพาร์ติชั่นที่เมาท์ใหม่จะถูกแท็กด้วย postinstall_file
โดยไม่คำนึงถึงคุณลักษณะของพวกเขาหลังจากรีบูตระบบใหม่นั้น การเปลี่ยนแปลงแอตทริบิวต์ SELinux ในระบบใหม่จะไม่ส่งผลต่อขั้นตอนหลังการติดตั้ง หากโปรแกรมหลังการติดตั้งต้องการการอนุญาตพิเศษ จะต้องเพิ่มการอนุญาตเหล่านั้นในบริบทหลังการติดตั้ง
หลังจากรีบูต
หลังจากรีบูตแล้ว update_verifier
จะทริกเกอร์การตรวจสอบความสมบูรณ์โดยใช้ dm-verity การตรวจสอบนี้เริ่มต้นก่อนไซโกตเพื่อหลีกเลี่ยงบริการ Java ที่ทำการเปลี่ยนแปลงที่ไม่สามารถย้อนกลับได้ซึ่งจะป้องกันการย้อนกลับอย่างปลอดภัย ในระหว่างกระบวนการนี้ bootloader และเคอร์เนลอาจทริกเกอร์การรีบูตหากการบู๊ตที่ตรวจสอบแล้วหรือ dm-verity ตรวจพบความเสียหาย หลังจากการตรวจสอบเสร็จสิ้น update_verifier
จะทำเครื่องหมายการบูตสำเร็จ
update_verifier
จะอ่านเฉพาะบล็อกที่ระบุไว้ใน /data/ota_package/care_map.txt
ซึ่งรวมอยู่ในแพ็คเกจ A/B OTA เมื่อใช้รหัส AOSP ไคลเอ็นต์การอัปเดตระบบ Java เช่น GmsCore จะ care_map.txt
ตั้งค่าการอนุญาตการเข้าถึงก่อนที่จะรีบูตอุปกรณ์ และลบไฟล์ที่แยกออกมาหลังจากที่ระบบบู๊ตเป็นเวอร์ชันใหม่ได้สำเร็จ