การอัปเดตระบบ A/B (แบบราบรื่น)

การอัปเดตระบบ 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 กับตัวจัดการแพ็กเกจดังนี้

ดูตัวอย่างที่ใช้งานได้ที่ /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 ให้เลือกแพตช์ต่อไปนี้

ต้องใช้แพตช์เหล่านี้เพื่อรองรับการอัปเดต A/B แบบสตรีมใน Android 7.1 ขึ้นไป ไม่ว่าจะใช้ บริการ Google บนอุปกรณ์เคลื่อนที่ (GMS) หรือไคลเอ็นต์การอัปเดตอื่นๆ ก็ตาม

วงจรการอัปเดต A/B

กระบวนการอัปเดตจะเริ่มขึ้นเมื่อมีแพ็กเกจ OTA (ในโค้ดเรียกว่าเพย์โหลด) ให้ดาวน์โหลด นโยบายในอุปกรณ์อาจเลื่อนการดาวน์โหลดและการใช้เพย์โหลด ตามระดับแบตเตอรี่ กิจกรรมของผู้ใช้ สถานะการชาร์จ หรือนโยบายอื่นๆ นอกจากนี้ เนื่องจากระบบจะอัปเดตในเบื้องหลัง ผู้ใช้อาจไม่ทราบว่าระบบกำลังอัปเดต อยู่ ทั้งหมดนี้หมายความว่ากระบวนการอัปเดตอาจถูกขัดจังหวะได้ทุกเมื่อ เนื่องจากนโยบาย การรีบูตที่ไม่คาดคิด หรือการดำเนินการของผู้ใช้

หรือข้อมูลเมตาในแพ็กเกจ OTA เองจะระบุว่าอัปเดตสามารถสตรีมได้ และยังใช้แพ็กเกจเดียวกันนี้สำหรับการติดตั้งแบบไม่สตรีมได้ด้วย เซิร์ฟเวอร์อาจใช้ข้อมูลเมตาเพื่อ แจ้งให้ไคลเอ็นต์ทราบว่ากำลังสตรีมอยู่ เพื่อให้ไคลเอ็นต์ส่งต่อ OTA ไปยัง update_engine ได้อย่างถูกต้อง ผู้ผลิตอุปกรณ์ที่มีเซิร์ฟเวอร์และไคลเอ็นต์ของตนเอง สามารถเปิดใช้การอัปเดตแบบสตรีมได้โดยตรวจสอบว่าเซิร์ฟเวอร์ระบุว่าการอัปเดตเป็นการสตรีม (หรือ ถือว่าการอัปเดตทั้งหมดเป็นการสตรีม) และไคลเอ็นต์ทําการเรียกที่ถูกต้องไปยัง update_engineสําหรับการสตรีม ผู้ผลิตสามารถใช้ข้อเท็จจริงที่ว่าแพ็กเกจเป็น ของตัวแปรการสตรีมเพื่อส่งแฟล็กไปยังไคลเอ็นต์เพื่อทริกเกอร์การส่งต่อไปยังฝั่งเฟรมเวิร์ก เป็นการสตรีม

หลังจากที่เพย์โหลดพร้อมใช้งานแล้ว กระบวนการอัปเดตจะเป็นดังนี้

ขั้นตอน กิจกรรม
1 ระบบจะทำเครื่องหมายว่าสล็อตปัจจุบัน (หรือ "สล็อตต้นทาง") สำเร็จ (หากยังไม่ได้ทำเครื่องหมาย) ด้วย markBootSuccessful()
2 ระบบจะทำเครื่องหมายสล็อตที่ไม่ได้ใช้ (หรือ "สล็อตเป้าหมาย") เป็นบูตไม่ได้โดยการเรียกใช้ฟังก์ชัน setSlotAsUnbootable() ระบบจะทำเครื่องหมายช่องปัจจุบันว่าสำเร็จเสมอเมื่อ เริ่มต้นการอัปเดตเพื่อป้องกันไม่ให้ Bootloader กลับไปใช้ช่องที่ไม่ได้ใช้ ซึ่งจะมีข้อมูลที่ไม่ถูกต้องในไม่ช้า หากระบบมาถึงจุดที่เริ่มใช้การอัปเดตได้ ระบบจะทำเครื่องหมายช่องปัจจุบันว่าสำเร็จ แม้ว่าคอมโพเนนต์หลักอื่นๆ จะเสีย (เช่น UI ในลูปการขัดข้อง) เนื่องจากสามารถพุชซอฟต์แวร์ใหม่เพื่อแก้ไขปัญหาเหล่านี้ได้

เพย์โหลดการอัปเดตคือ Blob ที่ทึบแสงซึ่งมีวิธีการอัปเดตเป็นเวอร์ชันใหม่ เพย์โหลดการอัปเดตประกอบด้วยข้อมูลต่อไปนี้
  • ข้อมูลเมตา เพย์โหลดการอัปเดตส่วนเล็กๆ ที่ค่อนข้างเล็ก ซึ่งก็คือข้อมูลเมตา มีรายการการดำเนินการเพื่อสร้างและยืนยันเวอร์ชันใหม่ในสล็อตเป้าหมาย ตัวอย่างเช่น การดำเนินการอาจคลายการบีบอัด Blob บางรายการและเขียนลงใน บล็อกที่เฉพาะเจาะจงในพาร์ติชันเป้าหมาย หรืออ่านจากพาร์ติชันต้นทาง ใช้แพตช์ไบนารี และเขียนลงในบล็อกบางรายการในพาร์ติชันเป้าหมาย
  • ข้อมูลเพิ่มเติม ข้อมูลเพิ่มเติมที่เชื่อมโยงกับการดำเนินการประกอบด้วย 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 ตั้งค่าสิทธิ์การเข้าถึงก่อนรีบูตอุปกรณ์ และ ลบไฟล์ที่แตกออกมาหลังจากที่ระบบบูตเข้าสู่เวอร์ชันใหม่ได้สำเร็จ