การอัปเดตระบบ 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 จะส่งผลต่อสิ่งต่อไปนี้

  • การเลือกพาร์ติชัน (สล็อต), Daemon update_engine และการโต้ตอบของ Bootloader (อธิบายไว้ด้านล่าง)
  • กระบวนการบิลด์และการสร้างแพ็กเกจการอัปเดต OTA (อธิบายไว้ใน การใช้การอัปเดต A/B)

การเลือกพาร์ติชัน (สล็อต)

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

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

แต่ละช่องยังมีแอตทริบิวต์ successful ที่กำหนดโดยพื้นที่ของผู้ใช้ ซึ่งจะเกี่ยวข้อง ก็ต่อเมื่อช่องนั้นสามารถบูตได้ด้วย สล็อตที่ใช้งานได้ควรบูต เรียกใช้ และอัปเดต ตัวเองได้ Bootloader ควรทำเครื่องหมายสล็อตที่บูตได้ซึ่งไม่ได้ทำเครื่องหมายว่าสำเร็จ (หลังจากพยายามบูตจากสล็อตนั้นหลายครั้ง) ว่าบูตไม่ได้ รวมถึงเปลี่ยนสล็อตที่ใช้งานอยู่เป็นสล็อตที่บูตได้อีกสล็อตหนึ่ง (โดยปกติจะเป็นสล็อตที่ทำงานก่อนหน้าความพยายามที่จะบูตเข้าสู่สล็อตใหม่ที่ใช้งานอยู่) รายละเอียดเฉพาะของอินเทอร์เฟซจะกำหนดไว้ใน boot_control.h

อัปเดต Daemon ของเครื่องมือ

การอัปเดตระบบแบบ A/B ใช้ Daemon เบื้องหลังที่ชื่อ 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 ให้เลือกแพตช์ต่อไปนี้

ต้องใช้แพตช์เหล่านี้เพื่อรองรับการอัปเดต A/B แบบสตรีมใน Android 7.1 ขึ้นไป ไม่ว่าจะใช้ บริการ Google Mobile (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)
  • ทำความเข้าใจรูปแบบโปรแกรมหลังการติดตั้งของพาร์ติชันใหม่ หากใช้ไบนารี 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 ซึ่งรวมอยู่ในแพ็กเกจ A/B OTA เมื่อ ใช้โค้ด AOSP ไคลเอ็นต์การอัปเดตระบบ Java เช่น GmsCore จะแตกไฟล์ care_map.txt ตั้งค่าสิทธิ์การเข้าถึงก่อนรีบูตอุปกรณ์ และ ลบไฟล์ที่แตกออกมาหลังจากที่ระบบบูตเข้าสู่เวอร์ชันใหม่ได้สำเร็จ