การอัปเดตระบบ A/B แบบเดิม หรือที่เรียกว่าการอัปเดตแบบไร้รอยต่อ จะช่วยให้มั่นใจได้ว่าระบบการบูตที่ใช้งานได้จะยังคงอยู่ในดิสก์ระหว่าง การอัปเดตผ่านอากาศ (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 การเปิดเครื่องที่ได้รับการยืนยันไม่จำเป็นต้องมีการอัปเดต 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 จะกลับไปใช้ระบบปฏิบัติการเดิมหากระบบปฏิบัติการใหม่บูตไม่สำเร็จ ดังนั้นไคลเอ็นต์จึงไม่ต้องดำเนินการใดๆ หากอัปเดตไม่สำเร็จ ไคลเอ็นต์จะต้องตัดสินใจว่าจะลองอีกครั้งเมื่อใด (และจะลองหรือไม่) โดยอิงตามรหัสข้อผิดพลาดแบบละเอียด ตัวอย่างเช่น ไคลเอ็นต์ที่ดีอาจ รับรู้ว่าแพ็กเกจ OTA บางส่วน ("diff") ทำงานไม่สำเร็จและลองใช้แพ็กเกจ OTA แบบเต็มแทน
นอกจากนี้ ลูกค้ายังเลือกดำเนินการต่อไปนี้ได้
- แสดงการแจ้งเตือนที่ขอให้ผู้ใช้รีบูต หากต้องการใช้นโยบายที่กระตุ้นให้ผู้ใช้ อัปเดตเป็นประจำ คุณสามารถเพิ่มการแจ้งเตือนนี้ลงในไคลเอ็นต์ได้ หากไคลเอ็นต์ไม่แจ้งให้ผู้ใช้ทราบ ผู้ใช้จะได้รับการอัปเดตในครั้งถัดไปที่รีบูต อยู่ดี (ไคลเอ็นต์ของ Google มีการหน่วงเวลาที่กำหนดค่าได้ต่อการอัปเดต)
- แสดงการแจ้งเตือนที่บอกผู้ใช้ว่าได้บูตเข้าสู่ระบบปฏิบัติการเวอร์ชันใหม่หรือไม่ หรือ คาดว่าจะบูตเข้าสู่ระบบปฏิบัติการเวอร์ชันใหม่แต่กลับไปใช้ระบบปฏิบัติการเวอร์ชันเก่า (โดยปกติแล้วไคลเอ็นต์ของ Google จะไม่ทำทั้ง 2 อย่าง )
ในฝั่งระบบ การอัปเดตระบบ A/B จะส่งผลต่อสิ่งต่อไปนี้
-
การเลือกพาร์ติชัน (สล็อต),
update_engine
daemon และการโต้ตอบของ Bootloader (อธิบายไว้ด้านล่าง) - กระบวนการบิลด์และการสร้างแพ็กเกจการอัปเดต OTA (อธิบายไว้ใน การใช้การอัปเดต A/B)
การเลือกพาร์ติชัน (สล็อต)
การอัปเดตระบบ A/B ใช้พาร์ติชัน 2 ชุดที่เรียกว่า สล็อต (โดยปกติคือสล็อต A และสล็อต B) ระบบจะทำงานจากสล็อตปัจจุบัน ขณะที่ระบบที่ทำงานอยู่จะไม่เข้าถึงพาร์ติชันในสล็อตที่ไม่ได้ใช้ในระหว่าง การทำงานตามปกติ แนวทางนี้ช่วยให้การอัปเดตมีความทนทานต่อข้อผิดพลาดโดยการเก็บช่องที่ไม่ได้ใช้ไว้เป็น การสำรองข้อมูล: หากเกิดข้อผิดพลาดระหว่างหรือหลังการอัปเดตทันที ระบบจะย้อนกลับไป ช่องเก่าและยังคงมีระบบที่ใช้งานได้ หากต้องการบรรลุเป้าหมายนี้ คุณควรปรับปรุงพาร์ติชันที่ใช้โดยสล็อตปัจจุบันเป็นส่วนหนึ่งของการอัปเดต OTA (รวมถึงพาร์ติชันที่มีสำเนาเพียงรายการเดียว)
แต่ละช่องจะมีแอตทริบิวต์บูตได้ซึ่งระบุว่าช่องมีระบบที่ถูกต้องซึ่งอุปกรณ์สามารถบูตได้หรือไม่ ปัจจุบันช่องดังกล่าวสามารถบูตได้เมื่อระบบ ทำงานอยู่ แต่ช่องอื่นอาจมีระบบเวอร์ชันเก่า (ยังคงถูกต้อง) เวอร์ชันใหม่กว่า หรือข้อมูลที่ไม่ถูกต้อง ไม่ว่าสล็อตปัจจุบันจะเป็นสล็อตใด จะมีสล็อตหนึ่ง ที่เป็นสล็อตที่ใช้งานอยู่ (สล็อตที่ Bootloader จะบูตจากสล็อตนั้นในการบูตครั้งถัดไป) หรือ สล็อตที่ต้องการ
แต่ละช่องยังมีแอตทริบิวต์ successful ที่ตั้งค่าโดยพื้นที่ของผู้ใช้ ซึ่งจะเกี่ยวข้อง
ก็ต่อเมื่อช่องนั้นสามารถบูตได้ด้วย สล็อตที่ใช้งานได้ควรบูต เรียกใช้ และอัปเดตตัวเองได้
Bootloader ควรทําเครื่องหมายช่องที่บูตได้ซึ่งไม่ได้ทําเครื่องหมายว่าสําเร็จ (หลังจากพยายาม
บูตจากช่องดังกล่าวหลายครั้ง) ว่าบูตไม่ได้ รวมถึงเปลี่ยนช่องที่ใช้งานอยู่เป็นช่องที่บูตได้อื่น (โดยปกติจะเป็นช่องที่ทํางานก่อนหน้าความพยายามที่จะ
บูตไปยังช่องใหม่ที่ใช้งานอยู่) รายละเอียดเฉพาะของอินเทอร์เฟซมีการกำหนดไว้ใน
boot_control.h
อัปเดต Daemon ของเครื่องมือ
การอัปเดตระบบ A/B ใช้แดมอนเบื้องหลังที่ชื่อ
update_engine
เพื่อเตรียมระบบให้บูตเข้าสู่เวอร์ชันใหม่ที่อัปเดตแล้ว โดย
daemon นี้สามารถดำเนินการต่อไปนี้ได้
- อ่านจากพาร์ติชัน A/B ของสล็อตปัจจุบันและเขียนข้อมูลไปยังพาร์ติชัน A/B ของสล็อตที่ไม่ได้ใช้ ตามที่แพ็กเกจ OTA สั่ง
- เรียกใช้
boot_control
อินเทอร์เฟซในเวิร์กโฟลว์ที่กำหนดไว้ล่วงหน้า - เรียกใช้โปรแกรมหลังการติดตั้งจากพาร์ติชันใหม่ หลังจากเขียนพาร์ติชันสล็อตที่ไม่ได้ใช้ทั้งหมดตามที่แพ็กเกจ OTA สั่ง (โปรดดูรายละเอียดที่หัวข้อ หลังการติดตั้ง)
เนื่องจาก Daemon update_engine
ไม่ได้เกี่ยวข้องกับกระบวนการบูตโดยตรง จึงมีการจำกัดสิ่งที่ทำได้ระหว่างการอัปเดตโดยนโยบายและฟีเจอร์ SELinux ในสล็อตปัจจุบัน (นโยบายและฟีเจอร์ดังกล่าวจะอัปเดตไม่ได้จนกว่าระบบจะบูตเป็นเวอร์ชันใหม่) กระบวนการอัปเดตไม่ควรแก้ไขตารางพาร์ติชัน เนื้อหาของพาร์ติชันในสล็อตปัจจุบัน หรือเนื้อหาของพาร์ติชันที่ไม่ใช่ A/B ที่ล้างข้อมูลด้วยการรีเซ็ตเป็นค่าเริ่มต้นไม่ได้ เพื่อรักษาระบบให้มีประสิทธิภาพ
อัปเดตแหล่งที่มาของเครื่องมือ
แหล่งที่มาของ update_engine
อยู่ใน
system/update_engine
ไฟล์ dexopt ของ A/B OTA จะแบ่งระหว่าง installd
กับตัวจัดการแพ็กเกจดังนี้
-
frameworks/native/cmds/installd/
ota* มีสคริปต์หลังการติดตั้ง ไบนารีสำหรับ chroot โคลน installd ที่เรียกใช้ dex2oat สคริปต์ย้ายอาร์ติแฟกต์หลัง OTA และไฟล์ 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
นอกจากบันทึกปัจจุบันแล้ว ระบบจะบันทึกบันทึกล่าสุด 5 รายการไว้ใน
/data/misc/update_engine_log/
ผู้ใช้ที่มีรหัสกลุ่ม log จะเข้าถึงบันทึกระบบไฟล์ได้
การโต้ตอบกับ Bootloader
update_engine
(และอาจเป็น daemon อื่นๆ) ใช้ boot_control
HAL เพื่อสั่งให้ Bootloader บูตจากอะไร ตัวอย่างสถานการณ์ที่พบบ่อยและสถานะที่เกี่ยวข้องมีดังนี้
- กรณีปกติ: ระบบทำงานจากสล็อตปัจจุบัน ไม่ว่าจะเป็นสล็อต A หรือ B ยังไม่มีการอัปเดตใดๆ สล็อตปัจจุบันของระบบสามารถบูตได้ สำเร็จ และเป็นสล็อตที่ใช้งานอยู่
- กำลังอัปเดต: ระบบกำลังทำงานจากสล็อต B ดังนั้นสล็อต B จึงเป็น สล็อตที่บูตได้ สำเร็จ และใช้งานอยู่ ระบบทำเครื่องหมายว่าช่อง A บูตไม่ได้เนื่องจากกำลังอัปเดตเนื้อหาของ ช่อง A แต่ยังไม่เสร็จสมบูรณ์ การรีบูตในสถานะนี้ควรดำเนินการ บูตจากสล็อต B ต่อไป
- ใช้อัปเดตแล้ว รอการรีบูต: ระบบกำลังทำงานจากสล็อต B, สล็อต B สามารถบูตได้และสำเร็จ แต่สล็อต A มีสถานะเป็นใช้งานอยู่ (และจึงมีสถานะเป็น บูตได้) ยังไม่ได้ทำเครื่องหมายว่าสล็อต 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 บนอุปกรณ์เคลื่อนที่ (GMS) หรือไคลเอ็นต์การอัปเดตอื่นๆ ก็ตาม
วงจรการอัปเดต A/B
กระบวนการอัปเดตจะเริ่มขึ้นเมื่อมีแพ็กเกจ OTA (ในโค้ดเรียกว่าเพย์โหลด) ให้ดาวน์โหลด นโยบายในอุปกรณ์อาจเลื่อนการดาวน์โหลดและการใช้เพย์โหลด ตามระดับแบตเตอรี่ กิจกรรมของผู้ใช้ สถานะการชาร์จ หรือนโยบายอื่นๆ นอกจากนี้ เนื่องจากระบบจะอัปเดตในเบื้องหลัง ผู้ใช้อาจไม่ทราบว่าระบบกำลังอัปเดต อยู่ ทั้งหมดนี้หมายความว่ากระบวนการอัปเดตอาจถูกขัดจังหวะได้ทุกเมื่อ เนื่องจากนโยบาย การรีบูตที่ไม่คาดคิด หรือการดำเนินการของผู้ใช้
หรือข้อมูลเมตาในแพ็กเกจ OTA เองจะระบุว่าอัปเดตสามารถสตรีมได้ และยังใช้แพ็กเกจเดียวกันนี้สำหรับการติดตั้งแบบไม่สตรีมได้ด้วย เซิร์ฟเวอร์อาจใช้ข้อมูลเมตาเพื่อ
แจ้งให้ไคลเอ็นต์ทราบว่ากำลังสตรีมอยู่ เพื่อให้ไคลเอ็นต์ส่งต่อ OTA ไปยัง
update_engine
ได้อย่างถูกต้อง ผู้ผลิตอุปกรณ์ที่มีเซิร์ฟเวอร์และไคลเอ็นต์ของตนเอง
สามารถเปิดใช้การอัปเดตแบบสตรีมได้โดยตรวจสอบว่าเซิร์ฟเวอร์ระบุว่าการอัปเดตเป็นการสตรีม (หรือ
ถือว่าการอัปเดตทั้งหมดเป็นการสตรีม) และไคลเอ็นต์ทําการเรียกที่ถูกต้องไปยัง
update_engine
สําหรับการสตรีม ผู้ผลิตสามารถใช้ข้อเท็จจริงที่ว่าแพ็กเกจเป็น
ของตัวแปรการสตรีมเพื่อส่งแฟล็กไปยังไคลเอ็นต์เพื่อทริกเกอร์การส่งต่อไปยังฝั่งเฟรมเวิร์ก
เป็นการสตรีม
หลังจากที่เพย์โหลดพร้อมใช้งานแล้ว กระบวนการอัปเดตจะเป็นดังนี้
ขั้นตอน | กิจกรรม |
---|---|
1 |
ระบบจะทำเครื่องหมายว่าสล็อตปัจจุบัน (หรือ "สล็อตต้นทาง") สำเร็จ (หากยังไม่ได้ทำเครื่องหมาย) ด้วย
markBootSuccessful()
|
2 |
ระบบจะทำเครื่องหมายสล็อตที่ไม่ได้ใช้ (หรือ "สล็อตเป้าหมาย") เป็นบูตไม่ได้โดยการเรียกใช้ฟังก์ชัน
setSlotAsUnbootable() ระบบจะทำเครื่องหมายช่องปัจจุบันว่าสำเร็จเสมอเมื่อ
เริ่มต้นการอัปเดตเพื่อป้องกันไม่ให้ Bootloader กลับไปใช้ช่องที่ไม่ได้ใช้
ซึ่งจะมีข้อมูลที่ไม่ถูกต้องในไม่ช้า หากระบบมาถึงจุดที่เริ่มใช้การอัปเดตได้
ระบบจะทำเครื่องหมายช่องปัจจุบันว่าสำเร็จ แม้ว่าคอมโพเนนต์หลักอื่นๆ
จะเสีย (เช่น UI ในลูปการขัดข้อง) เนื่องจากสามารถพุชซอฟต์แวร์ใหม่เพื่อแก้ไขปัญหาเหล่านี้ได้ เพย์โหลดการอัปเดตคือ Blob ที่ทึบแสงซึ่งมีวิธีการอัปเดตเป็นเวอร์ชันใหม่ เพย์โหลดการอัปเดตประกอบด้วยข้อมูลต่อไปนี้
|
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
เคอร์เนลเก่าต้องทำสิ่งต่อไปนี้ได้เพื่อให้การติดตั้งหลังการติดตั้งสำเร็จ
- เมานต์รูปแบบระบบไฟล์ใหม่ คุณจะเปลี่ยนประเภทระบบไฟล์ไม่ได้ เว้นแต่ เคอร์เนลเก่าจะรองรับประเภทระบบไฟล์นั้น รวมถึงรายละเอียดต่างๆ เช่น อัลกอริทึมการบีบอัด ที่ใช้หากใช้ระบบไฟล์ที่บีบอัด (เช่น SquashFS)
-
ทำความเข้าใจรูปแบบโปรแกรมหลังการติดตั้งของพาร์ติชันใหม่ หากใช้ไบนารี
รูปแบบที่เรียกใช้งานและลิงก์ได้ (ELF) ไบนารีดังกล่าวควรเข้ากันได้กับเคอร์เนลเก่า
(เช่น โปรแกรมใหม่ 64 บิตที่ทำงานบนเคอร์เนลเก่า 32 บิต หากสถาปัตยกรรมเปลี่ยนจาก
บิลด์ 32 บิตเป็น 64 บิต) เว้นแต่จะมีการสั่งให้โปรแกรมโหลด (
ld
) ใช้เส้นทางอื่น หรือสร้างไบนารีแบบคงที่ ระบบจะโหลดไลบรารีจากอิมเมจระบบเก่า ไม่ใช่อิมเมจใหม่
ตัวอย่างเช่น คุณอาจใช้สคริปต์เชลล์เป็นโปรแกรมหลังการติดตั้งที่ตีความโดยไบนารีเชลล์ของระบบเก่า
(โดยมีเครื่องหมาย #!
ที่ด้านบน) จากนั้นตั้งค่าเส้นทางไลบรารีจากสภาพแวดล้อมใหม่เพื่อเรียกใช้โปรแกรมหลังการติดตั้งไบนารีที่ซับซ้อนยิ่งขึ้น
หรือคุณจะเรียกใช้ขั้นตอนหลังการติดตั้งจาก
พาร์ติชันขนาดเล็กที่เจาะจงเพื่อเปิดใช้รูปแบบระบบไฟล์ในพาร์ติชันระบบหลักให้
อัปเดตได้โดยไม่ทำให้เกิดปัญหาความเข้ากันได้แบบย้อนหลังหรือการอัปเดตแบบขั้นบันได ซึ่งจะ
ช่วยให้ผู้ใช้อัปเดตเป็นเวอร์ชันล่าสุดจากอิมเมจจากโรงงานได้โดยตรง
โปรแกรมหลังการติดตั้งใหม่จะถูกจำกัดโดยนโยบาย SELinux ที่กำหนดไว้ในระบบเก่า ดังนั้น ขั้นตอนหลังการติดตั้งจึงเหมาะสําหรับการทํางานที่จําเป็นตามการออกแบบในอุปกรณ์ที่กําหนด หรือการทํางานอื่นๆ ที่พยายามทําให้ดีที่สุด ขั้นตอนหลังการติดตั้งไม่เหมาะสำหรับการแก้ไขข้อบกพร่องแบบครั้งเดียว ก่อนการรีบูตที่ต้องใช้สิทธิ์ที่ไม่คาดคิด
โปรแกรมหลังการติดตั้งที่เลือกจะทํางานใน
postinstall
บริบท SELinux ไฟล์ทั้งหมดในพาร์ติชันที่ติดตั้งใหม่จะ
มีแท็ก postinstall_file
ไม่ว่าแอตทริบิวต์ของไฟล์จะเป็นอย่างไรหลังจาก
รีบูตเข้าสู่ระบบใหม่นั้น การเปลี่ยนแปลงแอตทริบิวต์ SELinux ในระบบใหม่จะไม่
ส่งผลต่อขั้นตอนหลังการติดตั้ง หากโปรแกรมหลังการติดตั้งต้องใช้สิทธิ์เพิ่มเติม คุณต้อง
เพิ่มสิทธิ์เหล่านั้นลงในบริบทหลังการติดตั้ง
หลังรีบูต
หลังจากรีบูตแล้ว update_verifier
จะทริกเกอร์การตรวจสอบความถูกต้องโดยใช้ dm-verity
การตรวจสอบนี้จะเริ่มก่อน Zygote เพื่อหลีกเลี่ยงไม่ให้บริการ Java ทำการเปลี่ยนแปลงที่ย้อนกลับไม่ได้ ซึ่ง
จะป้องกันการย้อนกลับอย่างปลอดภัย ในกระบวนการนี้ Bootloader และเคอร์เนลอาจทริกเกอร์การรีบูตด้วยหากการเปิดเครื่องที่ได้รับการยืนยันหรือ dm-verity ตรวจพบความเสียหาย หลังจากตรวจสอบเสร็จสมบูรณ์
update_verifier
จะทำเครื่องหมายว่าการบูตสำเร็จ
update_verifier
จะอ่านเฉพาะบล็อกที่ระบุไว้ใน
/data/ota_package/care_map.txt
ซึ่งรวมอยู่ในแพ็กเกจ A/B OTA เมื่อ
ใช้โค้ด AOSP ไคลเอ็นต์การอัปเดตระบบ Java เช่น GmsCore จะแตกไฟล์
care_map.txt
ตั้งค่าสิทธิ์การเข้าถึงก่อนรีบูตอุปกรณ์ และ
ลบไฟล์ที่แตกออกมาหลังจากที่ระบบบูตเข้าสู่เวอร์ชันใหม่ได้สำเร็จ