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

การเปลี่ยนแปลงเหล่านี้จะบันทึกสําเนาบันทึก 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 ให้เลือกแพตช์ต่อไปนี้

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