การอัปเดตระบบ A/B หรือที่เรียกว่าการอัปเดตที่ราบรื่น ช่วยให้มั่นใจได้ว่าระบบบูตที่ใช้งานได้จะยังคงอยู่ในดิสก์ระหว่าง การอัปเดตแบบ over-the-air (OTA) วิธีการนี้จะช่วยลดโอกาสของอุปกรณ์ที่ไม่ได้ใช้งานหลังจากการอัพเดต ซึ่งหมายความว่าจะมีการเปลี่ยนอุปกรณ์และการ reflash อุปกรณ์ที่ศูนย์ซ่อมและการรับประกันน้อยลง ระบบปฏิบัติการเชิงพาณิชย์อื่นๆ เช่น 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 บูตเข้าสู่ระบบปฏิบัติการใหม่ในการรีบูตครั้งถัดไป โปรแกรมโหลดบูตจะถอยกลับไปใช้ระบบปฏิบัติการเก่าหากระบบปฏิบัติการใหม่ไม่สามารถบู๊ตได้ ดังนั้นจึงไม่จำเป็นต้องดำเนินการใดๆ จากไคลเอ็นต์ หากการอัปเดตล้มเหลว ลูกค้าจะต้องตัดสินใจว่าจะลองอีกครั้งเมื่อใด (และหรือไม่) โดยพิจารณาจากรหัสข้อผิดพลาดโดยละเอียด ตัวอย่างเช่น ลูกค้าที่ดีอาจรับรู้ว่าแพ็คเกจ OTA บางส่วน ("diff") ล้มเหลว และลองใช้แพ็คเกจ OTA แบบเต็มแทน
ทางเลือก ลูกค้าสามารถ:
- แสดงการแจ้งเตือนที่ขอให้ผู้ใช้รีบูต หากคุณต้องการใช้นโยบายที่สนับสนุนให้ผู้ใช้อัปเดตเป็นประจำ คุณสามารถเพิ่มการแจ้งเตือนนี้ไปยังไคลเอนต์ของคุณได้ หากไคลเอ็นต์ไม่แจ้งผู้ใช้ ผู้ใช้จะได้รับการอัปเดตในครั้งถัดไปที่รีบูต (ไคลเอนต์ของ Google มีความล่าช้าที่กำหนดค่าได้ต่อการอัปเดต)
- แสดงการแจ้งเตือนที่แจ้งให้ผู้ใช้ทราบว่าพวกเขาบูตเข้าสู่ระบบปฏิบัติการเวอร์ชันใหม่หรือว่าพวกเขาคาดว่าจะทำเช่นนั้น แต่กลับไปใช้ระบบปฏิบัติการเวอร์ชันเก่าหรือไม่ (โดยปกติแล้วไคลเอ็นต์ของ Google จะไม่ทำเช่นนั้น)
ในด้านระบบ การอัปเดตระบบ A/B จะส่งผลต่อสิ่งต่อไปนี้:
- การเลือกพาร์ติชัน (สล็อต),
update_engine
daemon และการโต้ตอบของ bootloader (อธิบายไว้ด้านล่าง) - กระบวนการสร้างและการสร้างแพ็คเกจการอัปเดต OTA (อธิบายไว้ใน การนำการอัปเดต A/B ไปใช้ )
การเลือกพาร์ติชัน (ช่อง)
การอัพเดตระบบ A/B ใช้พาร์ติชั่นสองชุดที่เรียกว่า สล็อต (โดยปกติคือสล็อต A และสล็อต B) ระบบรันจากสล็อต ปัจจุบัน ในขณะที่พาร์ติชันในช่อง ที่ไม่ได้ใช้ ไม่สามารถเข้าถึงได้โดยระบบที่รันอยู่ในระหว่างการดำเนินการปกติ วิธีการนี้ทำให้การอัปเดตต้านทานข้อผิดพลาดโดยเก็บสล็อตที่ไม่ได้ใช้เป็นทางเลือกสำรอง: หากมีข้อผิดพลาดเกิดขึ้นในระหว่างหรือหลังการอัปเดตทันที ระบบสามารถย้อนกลับไปยังสล็อตเก่าและยังคงมีระบบที่ใช้งานได้ เพื่อให้บรรลุเป้าหมายนี้ ไม่ควรอัพเดตพาร์ติชั่นที่ใช้โดยสล็อต ปัจจุบัน เป็นส่วนหนึ่งของการอัพเดต OTA (รวมถึงพาร์ติชั่นที่มีสำเนาเพียงชุดเดียว)
แต่ละช่องมีคุณลักษณะ ที่สามารถบูตได้ ซึ่งระบุว่าช่องดังกล่าวมีระบบที่ถูกต้องซึ่งอุปกรณ์สามารถบู๊ตได้ สล็อตปัจจุบันสามารถบูตได้เมื่อระบบกำลังทำงาน แต่สล็อตอื่นอาจมีเวอร์ชันเก่า (ยังคงถูกต้อง) ของระบบ เวอร์ชันใหม่กว่า หรือข้อมูลที่ไม่ถูกต้อง ไม่ว่าสล็อต ปัจจุบัน จะเป็นอะไรก็ตาม มีสล็อตหนึ่งช่องที่เป็นสล็อต ที่ใช้งานอยู่ (ช่องที่ bootloader จะบู๊ตจากการบู๊ตครั้งถัดไป) หรือสล็อต ที่ต้องการ
แต่ละสล็อตยังมีคุณลักษณะ ที่สำเร็จ ซึ่งกำหนดโดยพื้นที่ผู้ใช้ ซึ่งจะเกี่ยวข้องเฉพาะในกรณีที่สล็อตนั้นสามารถบูตได้ด้วย ช่องที่ประสบความสำเร็จควรจะสามารถบูต รัน และอัปเดตตัวเองได้ สล็อตที่สามารถบู๊ตได้ซึ่งไม่ได้ทำเครื่องหมายว่าสำเร็จ (หลังจากพยายามบู๊ตหลายครั้ง) ควรถูกทำเครื่องหมายว่าไม่สามารถบู๊ตได้โดย 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
ไฟล์ dexopt A/B OTA จะถูกแบ่งระหว่าง installd
และตัวจัดการแพ็คเกจ:
-
frameworks/native/cmds/installd/
ota* ประกอบด้วยสคริปต์หลังการติดตั้ง ไบนารีสำหรับ chroot โคลน installd ที่เรียก 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
(และอาจเป็น daemons อื่นๆ) เพื่อสั่ง bootloader ว่าจะบูตจากอะไร สถานการณ์ตัวอย่างทั่วไปและสถานะที่เกี่ยวข้องมีดังต่อไปนี้:
- กรณีปกติ : ระบบกำลังทำงานจากช่องปัจจุบัน ไม่ว่าจะเป็นช่อง A หรือ B ยังไม่มีการอัพเดตใดๆ สล็อตปัจจุบันของระบบสามารถบูตได้ สำเร็จ และเป็นสล็อตที่ใช้งานอยู่
- อยู่ระหว่างดำเนินการอัปเดต : ระบบกำลังทำงานจากสล็อต B ดังนั้นสล็อต B จึงเป็นสล็อตที่สามารถบู๊ตได้ สำเร็จ และใช้งานอยู่ ช่อง A ถูกทำเครื่องหมายว่าไม่สามารถบูตได้เนื่องจากเนื้อหาของช่อง A กำลังได้รับการอัปเดตแต่ยังไม่เสร็จสมบูรณ์ การรีบูตในสถานะนี้ควรทำการบูทต่อจากสล็อต B
- ใช้การอัปเดต รอรีบูตเครื่อง : ระบบกำลังทำงานจากสล็อต B สล็อต B สามารถบู๊ตได้และสำเร็จ แต่สล็อต A ถูกทำเครื่องหมายว่าใช้งานอยู่ (และดังนั้นจึงถูกทำเครื่องหมายว่าสามารถบู๊ตได้) Slot A ยังไม่ถูกทำเครื่องหมายว่าสำเร็จ และ bootloader ควรพยายามบูตจากช่อง 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 และ Linkable Format (ELF) ควรเข้ากันได้กับเคอร์เนลเก่า (เช่น โปรแกรมใหม่ 64 บิตที่ทำงานบนเคอร์เนล 32 บิตเก่า หากสถาปัตยกรรมเปลี่ยนจากบิลด์ 32- เป็น 64 บิต) ยกเว้นในกรณีที่ตัวโหลด (
ld
) ได้รับคำสั่งให้ใช้พาธอื่นหรือสร้างไบนารีแบบคงที่ ไลบรารีจะถูกโหลดจากอิมเมจระบบเก่า ไม่ใช่อิมเมจใหม่
ตัวอย่างเช่น คุณสามารถใช้เชลล์สคริปต์เป็นโปรแกรมหลังการติดตั้งซึ่งตีความโดยเชลล์ไบนารีของระบบเก่าด้วย #!
เครื่องหมายที่ด้านบน) จากนั้นตั้งค่าเส้นทางไลบรารีจากสภาพแวดล้อมใหม่เพื่อดำเนินการโปรแกรมหลังการติดตั้งไบนารีที่ซับซ้อนมากขึ้น หรือคุณสามารถรันขั้นตอนหลังการติดตั้งจากพาร์ติชันที่มีขนาดเล็กกว่าโดยเฉพาะ เพื่อเปิดใช้งานรูปแบบระบบไฟล์ในพาร์ติชันระบบหลักที่จะอัพเดตได้โดยไม่เกิดปัญหาความเข้ากันได้แบบย้อนหลังหรือการอัพเดตขั้นบันได สิ่งนี้จะทำให้ผู้ใช้สามารถอัปเดตเป็นเวอร์ชันล่าสุดได้โดยตรงจากอิมเมจจากโรงงาน
โปรแกรมหลังการติดตั้งใหม่ถูกจำกัดโดยนโยบาย SELinux ที่กำหนดไว้ในระบบเก่า ด้วยเหตุนี้ ขั้นตอนหลังการติดตั้งจึงเหมาะสำหรับการปฏิบัติงานที่กำหนดโดยการออกแบบบนอุปกรณ์ที่กำหนดหรืองานที่ต้องใช้ความพยายามอย่างดีที่สุดอื่นๆ (เช่น การอัปเดตเฟิร์มแวร์หรือโปรแกรมโหลดบูตที่รองรับ A/B การเตรียมสำเนาฐานข้อมูลสำหรับเวอร์ชันใหม่ เป็นต้น ). ขั้นตอนหลังการติดตั้ง ไม่เหมาะ สำหรับการแก้ไขข้อบกพร่องแบบครั้งเดียวก่อนรีบูตซึ่งต้องใช้สิทธิ์ที่ไม่คาดคิด
โปรแกรมหลังการติดตั้งที่เลือกจะทำงานในบริบท postinstall
SELinux ไฟล์ทั้งหมดในพาร์ติชันที่เมาท์ใหม่จะถูกแท็กด้วย 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
ตั้งค่าสิทธิ์การเข้าถึงก่อนที่จะรีบูตอุปกรณ์ และลบไฟล์ที่แตกออกมาหลังจากที่ระบบบูทเป็นเวอร์ชันใหม่ได้สำเร็จ