การอัปเดตระบบ 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
จะบอกให้บูตโหลดเดอร์บูตเข้าสู่ระบบปฏิบัติการใหม่ในการรีบูตครั้งถัดไป บูตโหลดเดอร์จะกลับไปใช้ระบบปฏิบัติการเดิมหากระบบปฏิบัติการใหม่บูตไม่สำเร็จ ดังนั้นไคลเอ็นต์จึงไม่ต้องดำเนินการใดๆ หากอัปเดตไม่สำเร็จ ลูกค้าจะต้องตัดสินใจว่าควรลองอีกครั้งเมื่อใด (และควรลองหรือไม่) โดยอิงตามรหัสข้อผิดพลาดแบบละเอียด ตัวอย่างเช่น ไคลเอ็นต์ที่ดีอาจรับรู้ได้ว่าแพ็กเกจ OTA บางส่วน ("diff") ดำเนินการไม่สำเร็จ และลองใช้แพ็กเกจ OTA แบบเต็มแทน
ลูกค้าจะทำสิ่งต่อไปนี้ได้ (ไม่บังคับ)
- แสดงการแจ้งเตือนเพื่อขอให้ผู้ใช้รีบูต หากต้องการใช้นโยบายที่แนะนำให้ผู้ใช้อัปเดตเป็นประจำ คุณสามารถเพิ่มการแจ้งเตือนนี้ลงในไคลเอ็นต์ได้ หากไคลเอ็นต์ไม่แสดงข้อความแจ้งให้ผู้ใช้ทราบ ผู้ใช้จะได้รับอัปเดตในครั้งถัดไปที่รีบูต (ไคลเอ็นต์ของ Google มีการหน่วงเวลาที่กำหนดค่าได้ต่อการอัปเดตแต่ละครั้ง)
- แสดงการแจ้งเตือนที่บอกให้ผู้ใช้ทราบว่าได้บูตเข้าสู่ระบบปฏิบัติการเวอร์ชันใหม่แล้วหรือควรจะบูตเข้าสู่ระบบปฏิบัติการเวอร์ชันใหม่แต่กลับเข้าสู่ระบบปฏิบัติการเวอร์ชันเก่า (โดยทั่วไปไคลเอ็นต์ของ Google จะไม่ดำเนินการใดๆ เลย)
ในด้านระบบ การอัปเดตระบบ A/B จะส่งผลต่อสิ่งต่อไปนี้
-
การเลือกพาร์ติชัน (สล็อต), ไดแอม่อน
update_engine
และการโต้ตอบของบูตโหลดเดอร์ (อธิบายไว้ด้านล่าง) - กระบวนการสร้างและการสร้างแพ็กเกจอัปเดต OTA (อธิบายไว้ในการใช้การอัปเดต A/B)
การเลือกพาร์ติชัน (สล็อต)
การอัปเดตระบบ A/B ใช้พาร์ติชัน 2 ชุดที่เรียกว่าสล็อต (ปกติคือสล็อต ก และสล็อต ข) ระบบจะทำงานจากสล็อตปัจจุบัน ขณะที่ระบบที่ทำงานอยู่จะไม่เข้าถึงพาร์ติชันในสล็อตที่ไม่ได้ใช้ในระหว่างการทํางานตามปกติ แนวทางนี้ทำให้การอัปเดตมีความผิดพลาดน้อยลงโดยเก็บสล็อตที่ไม่ได้ใช้ไว้เป็นตัวเลือกสำรอง: หากเกิดข้อผิดพลาดระหว่างหรือทันทีหลังจากการอัปเดต ระบบจะย้อนกลับไปยังสล็อตเดิมและทำให้ระบบทำงานต่อไปได้ หากต้องการบรรลุเป้าหมายนี้ ไม่ควรอัปเดตพาร์ติชันที่ใช้โดยสล็อตปัจจุบันเป็นส่วนหนึ่งของการอัปเดต OTA (รวมถึงพาร์ติชันที่มีสำเนาเพียงรายการเดียว)
แต่ละช่องมีแอตทริบิวต์บูตได้ซึ่งระบุว่าช่องมีระบบที่ถูกต้องซึ่งอุปกรณ์จะบูตได้หรือไม่ สล็อตปัจจุบันจะบูตได้เมื่อระบบทำงานอยู่ แต่สล็อตอื่นอาจมีระบบเวอร์ชันเก่า (ยังคงถูกต้อง) เวอร์ชันใหม่ หรือข้อมูลที่ไม่ถูกต้อง ไม่ว่าสล็อตปัจจุบันจะเป็นสล็อตใด จะมีสล็อตหนึ่งเป็นสล็อตที่ใช้งานอยู่ (สล็อตที่บูตโหลดเดอร์จะบูตจากในการบูตครั้งถัดไป) หรือสล็อตที่ต้องการ
แต่ละช่องยังมีแอตทริบิวต์สำเร็จที่กำหนดโดยพื้นที่ผู้ใช้ด้วย ซึ่งจะเกี่ยวข้องก็ต่อเมื่อช่องนั้นบูตได้เช่นกัน สล็อตที่ดำเนินการสำเร็จควรบูต ทำงาน และอัปเดตได้เอง บูตโหลดเดอร์ควรทำเครื่องหมายช่องที่บูตได้ซึ่งไม่ได้ระบุว่าสำเร็จ (หลังจากพยายามบูตจากช่องดังกล่าวหลายครั้ง) ว่าบูตไม่ได้ รวมถึงเปลี่ยนช่องที่ใช้งานอยู่เป็นช่องอื่นที่บูตได้ (โดยปกติจะเป็นช่องที่ทำงานอยู่ทันทีก่อนที่จะพยายามบูตเข้าสู่ช่องใหม่ที่ใช้งานอยู่) รายละเอียดที่เฉพาะเจาะจงของอินเทอร์เฟซจะระบุไว้ใน
boot_control.h
อัปเดตโปรแกรมเดรัมเครื่องยนต์
การอัปเดตระบบ A/B ใช้เดรัมในเบื้องหลังที่เรียกว่า update_engine
เพื่อเตรียมระบบให้บูตเป็นเวอร์ชันใหม่ที่ได้รับการอัปเดต ซึ่งสามารถดําเนินการต่อไปนี้ได้
- อ่านจากพาร์ติชัน A/B ของช่องปัจจุบันและเขียนข้อมูลไปยังพาร์ติชัน A/B ของช่องที่ไม่ได้ใช้งานตามวิธีการของแพ็กเกจ OTA
- เรียกใช้อินเทอร์เฟซ
boot_control
ในเวิร์กโฟลว์ที่กําหนดไว้ล่วงหน้า - เรียกใช้โปรแกรมหลังการติดตั้งจากพาร์ติชันใหม่หลังจากเขียนพาร์ติชันสล็อตที่ไม่ได้ใช้ทั้งหมดตามที่แพ็กเกจ OTA ระบุ (โปรดดูรายละเอียดที่หัวข้อหลังการติดตั้ง)
เนื่องจากเดรัมน์ update_engine
ไม่ได้เกี่ยวข้องกับกระบวนการบูตโดยตรง การดำเนินการที่ทำได้ในระหว่างการอัปเดตจึงถูกจำกัดโดยนโยบายและฟีเจอร์ SELinux ในช่องปัจจุบัน (นโยบายและฟีเจอร์ดังกล่าวจะอัปเดตไม่ได้จนกว่าระบบจะบูตเป็นเวอร์ชันใหม่) กระบวนการอัปเดตไม่ควรแก้ไขตารางพาร์ติชัน เนื้อหาของพาร์ติชันในช่องปัจจุบัน หรือเนื้อหาของพาร์ติชันที่ไม่ใช่ A/B ซึ่งล้างข้อมูลด้วยรีเซ็ตเป็นค่าเริ่มต้นไม่ได้ เพื่อรักษาระบบให้มีประสิทธิภาพ
อัปเดตแหล่งที่มาของเครื่องมือค้นหา
แหล่งที่มา update_engine
อยู่ใน system/update_engine
ไฟล์ dexopt ของ OTA แบบ A/B จะแบ่งระหว่าง 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
แสดงในระบบไฟล์ ให้แก้ไขการเปลี่ยนแปลงต่อไปนี้ในบิลด์
- การเปลี่ยนแปลง 486618
- การเปลี่ยนแปลง 529080
- การเปลี่ยนแปลง 529081
- การเปลี่ยนแปลง 534660
- การเปลี่ยนแปลง 594637
การเปลี่ยนแปลงเหล่านี้จะบันทึกสําเนาบันทึก update_engine
ล่าสุดลงใน /data/misc/update_engine_log/update_engine.YEAR-TIME
นอกจากบันทึกปัจจุบันแล้ว ระบบจะบันทึกบันทึกล่าสุด 5 รายการไว้ในส่วน /data/misc/update_engine_log/
ผู้ใช้ที่มีรหัสกลุ่ม log จะเข้าถึงบันทึกของระบบไฟล์ได้
การโต้ตอบกับ Bootloader
update_engine
(และอาจมีเดมอนอื่นๆ) ใช้ boot_control
HAL เพื่อสั่งให้บูตโหลดเดอร์ทราบว่าจะบูตจากอะไร ตัวอย่างสถานการณ์ทั่วไปและสถานะที่เชื่อมโยงกันมีดังนี้
- กรณีปกติ: ระบบทำงานจากช่องปัจจุบัน ซึ่งอาจเป็นช่อง A หรือ B ยังไม่มีการใช้การอัปเดต สล็อตปัจจุบันของระบบสามารถบูตได้ ดำเนินการสำเร็จ และเป็นสล็อตที่ใช้งานอยู่
- กำลังอัปเดต: ระบบทำงานจากสล็อต B ดังนั้นสล็อต B จึงบูตได้ อัปเดตสำเร็จ และทำงานอยู่ มีการทําเครื่องหมายให้สล็อต A เป็น "ไม่สามารถบูตได้" เนื่องจากระบบกําลังอัปเดตเนื้อหาของสล็อต A แต่ยังไม่เสร็จสมบูรณ์ การรีบูตในสถานะนี้ควรบูตจากช่อง B ต่อ
- อัปเดตแล้ว รอการรีบูต: ระบบทำงานจากสล็อต B, สล็อต B สามารถบูตได้และดำเนินการสำเร็จ แต่สล็อต A มีสถานะเป็น "ใช้งานอยู่" (จึงมีสถานะเป็น "บูตได้") ช่อง A ยังไม่ได้รับการระบุว่า "สำเร็จ" และบูตโหลดเดอร์ควรพยายามบูตจากช่อง A เป็นจำนวนหนึ่ง
-
ระบบรีบูตเป็นอัปเดตใหม่: ระบบทำงานจากสล็อต A เป็นครั้งแรก สล็อต B ยังบูตได้และดำเนินการสำเร็จ ขณะที่สล็อต A บูตได้เท่านั้น และยังคงทำงานอยู่แต่ไม่สำเร็จ เดมอนสเปซผู้ใช้
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
สําหรับสตรีมมิงอย่างถูกต้อง ผู้ผลิตสามารถใช้ข้อเท็จจริงที่ว่าแพ็กเกจเป็นตัวแปรสตรีมมิงเพื่อส่ง Flag ไปยังไคลเอ็นต์เพื่อทริกเกอร์การส่งต่อไปยังฝั่งเฟรมเวิร์กแบบสตรีมมิง
หลังจากมีเพย์โหลดแล้ว กระบวนการอัปเดตมีดังนี้
ขั้นตอน | กิจกรรม |
---|---|
1 |
ช่องปัจจุบัน (หรือ "ช่องต้นทาง") ได้รับการทําเครื่องหมายว่าสําเร็จ (หากยังไม่ได้ทําเครื่องหมาย) ด้วย markBootSuccessful()
|
2 |
สล็อตที่ไม่ได้ใช้ (หรือ "สล็อตเป้าหมาย") จะทำเครื่องหมายว่าไม่สามารถบูตได้โดยการเรียกใช้ฟังก์ชัน
setSlotAsUnbootable() ระบบจะทําเครื่องหมายช่องปัจจุบันว่า "สําเร็จ" เสมอเมื่อเริ่มต้นการอัปเดตเพื่อป้องกันไม่ให้โปรแกรมโหลดบูตกลับไปใช้ช่องที่ไม่ได้ใช้งาน ซึ่งจะมีข้อมูลที่ไม่ถูกต้องในไม่ช้า หากระบบมาถึงจุดที่เริ่มใช้การอัปเดตได้ ระบบจะทําเครื่องหมายให้ช่องปัจจุบันว่า "สําเร็จ" แม้ว่าคอมโพเนนต์หลักอื่นๆ จะใช้งานไม่ได้ (เช่น 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)
-
ทำความเข้าใจรูปแบบโปรแกรมหลังการติดตั้งของพาร์ติชันใหม่ หากใช้ไบนารีรูปแบบ Executable and Linkable Format (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
ซึ่งรวมอยู่ในแพ็กเกจ OTA แบบ A/B เมื่อใช้โค้ด AOSP ไคลเอ็นต์การอัปเดตระบบ Java เช่น GmsCore จะแตกไฟล์ care_map.txt
, ตั้งค่าสิทธิ์เข้าถึงก่อนรีบูตอุปกรณ์ และลบไฟล์ที่แตกหลังจากระบบบูตเข้าสู่เวอร์ชันใหม่ได้สําเร็จ