การอัปเดตระบบ A/B (ไม่มีรอยต่อ)

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

การอัปเดตระบบ A/B หรือที่เรียกว่าการอัปเดตแบบไม่มีสะดุด ช่วยให้มั่นใจว่าระบบการบูตที่ใช้งานได้จะยังคงอยู่บนดิสก์ระหว่างการ อัปเดตแบบ over-the-air (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 Verified Boot ไม่ต้องการการอัปเดต 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 จะย้อนกลับไปใช้ OS เก่าหาก OS ใหม่ไม่สามารถบู๊ตได้ ดังนั้นจึงไม่จำเป็นต้องดำเนินการใดๆ จากไคลเอ็นต์ หากการอัปเดตล้มเหลว ไคลเอ็นต์จำเป็นต้องตัดสินใจว่าจะลองอีกครั้งเมื่อใด (และหรือไม่) ตามรหัสข้อผิดพลาดโดยละเอียด ตัวอย่างเช่น ลูกค้าที่ดีสามารถรับรู้ได้ว่าแพ็คเกจ OTA บางส่วน ("diff") ล้มเหลวและลองใช้แพ็คเกจ OTA แบบเต็มแทน

ลูกค้าสามารถ:

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

ทางฝั่งระบบ การอัปเดตระบบ A/B จะมีผลดังต่อไปนี้:

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

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

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

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

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

อัพเดทเดมอนเครื่องยนต์

การอัปเดตระบบ A/B ใช้ดีมอนพื้นหลังที่เรียกว่า update_engine เพื่อเตรียมระบบให้บูตเข้าสู่เวอร์ชันใหม่ที่ได้รับการอัปเดต daemon นี้สามารถดำเนินการดังต่อไปนี้:

  • อ่านจากพาร์ติชั่น A/B ของสล็อตปัจจุบัน และเขียนข้อมูลใดๆ ไปยังพาร์ติชั่น A/B ของสล็อตที่ไม่ได้ใช้ตามคำแนะนำของแพ็คเกจ OTA
  • เรียกใช้อินเทอร์เฟซ boot_control ในเวิร์กโฟลว์ที่กำหนดไว้ล่วงหน้า
  • รันโปรแกรม หลังการติดตั้ง จากพาร์ติชั่น ใหม่ หลังจากเขียนพาร์ติชั่นสล็อตที่ไม่ได้ใช้ทั้งหมด ตามคำแนะนำของแพ็คเกจ OTA (สำหรับรายละเอียด โปรดดู หลังการติดตั้ง )

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

อัปเดตแหล่งที่มาของเครื่องยนต์

แหล่งที่มาของ update_engine อยู่ใน system/update_engine ไฟล์ A/B OTA dexopt ถูกแยกระหว่าง installd และ package manager:

สำหรับตัวอย่างการทำงาน โปรดดูที่ /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 . นอกจากบันทึกปัจจุบันแล้ว รายการบันทึกล่าสุดห้ารายการยังถูกบันทึกภายใต้ /data/misc/update_engine_log/ ผู้ใช้ที่มี ID กลุ่ม บันทึก จะสามารถเข้าถึงบันทึกของระบบไฟล์ได้

การโต้ตอบของ Bootloader

boot_control HAL ถูกใช้โดย update_engine (และอาจเป็นภูตอื่น ๆ ) เพื่อสั่ง bootloader ว่าควรบูตจากอะไร สถานการณ์ตัวอย่างทั่วไปและสถานะที่เกี่ยวข้องมีดังต่อไปนี้:

  • กรณีปกติ : ระบบกำลังทำงานจากช่องปัจจุบัน ไม่ว่าจะเป็นช่อง A หรือ B ยังไม่มีการอัปเดตใดๆ สล็อตปัจจุบันของระบบสามารถบู๊ตได้ สำเร็จ และสล็อตที่ใช้งานอยู่
  • กำลังอัปเดต : ระบบกำลังทำงานจากสล็อต B ดังนั้นสล็อต B จึงเป็นสล็อตที่สามารถบู๊ตได้ สำเร็จ และใช้งานอยู่ สล็อต A ถูกทำเครื่องหมายว่าไม่สามารถบูตได้ เนื่องจากเนื้อหาของสล็อต A กำลังได้รับการอัปเดตแต่ยังไม่เสร็จสมบูรณ์ การรีบูตในสถานะนี้ควรทำการบูทต่อจากสล็อต B
  • ใช้การอัปเดต การรีบูตที่รอดำเนิน การ : ระบบกำลังทำงานจากสล็อต B สล็อต B สามารถบู๊ตได้และประสบความสำเร็จ แต่สล็อต A ถูกทำเครื่องหมายว่าใช้งานได้ (และดังนั้นจึงถูกทำเครื่องหมายว่าบู๊ตได้) สล็อต A ยังไม่ถูกทำเครื่องหมายว่าสำเร็จ และจำนวนครั้งในการพยายามบูตจากสล็อต 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 Services (GMS) หรือไคลเอ็นต์การอัปเดตอื่นๆ

ชีวิตของการอัปเดต A/B

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

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

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

ขั้นตอน กิจกรรม
1 ช่องปัจจุบัน (หรือ "ช่องต้นทาง") ถูกทำเครื่องหมายว่าสำเร็จ (หากยังไม่ได้ทำเครื่องหมาย) ด้วย markBootSuccessful()
2 ช่องที่ไม่ได้ใช้ (หรือ "ช่องเป้าหมาย") ถูกทำเครื่องหมายว่าไม่สามารถบูตได้โดยการเรียกใช้ฟังก์ชัน setSlotAsUnbootable() สล็อตปัจจุบันจะถูกทำเครื่องหมายว่าสำเร็จในตอนเริ่มต้นของการอัปเดตเสมอ เพื่อป้องกันไม่ให้ bootloader ถอยกลับไปยังสล็อตที่ไม่ได้ใช้ ซึ่งจะมีข้อมูลที่ไม่ถูกต้องในเร็วๆ นี้ หากระบบมาถึงจุดที่เริ่มใช้การอัปเดตได้ ช่องปัจจุบันจะถูกทำเครื่องหมายว่าสำเร็จแม้ว่าส่วนประกอบหลักอื่นๆ จะเสียหาย (เช่น 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 คำสั่ง /postinstall_mount/usr/bin/postinstall ถูกดำเนินการ

เพื่อให้การติดตั้งสำเร็จ เคอร์เนลเก่าจะต้องสามารถ:

  • เมานต์รูปแบบระบบไฟล์ใหม่ ประเภทระบบไฟล์ไม่สามารถเปลี่ยนแปลงได้ เว้นแต่จะมีการรองรับในเคอร์เนลเก่า รวมถึงรายละเอียดต่างๆ เช่น อัลกอริธึมการบีบอัดที่ใช้หากใช้ระบบไฟล์ที่บีบอัด (เช่น SquashFS)
  • ทำความเข้าใจรูปแบบโปรแกรมหลังการติดตั้งของพาร์ติชันใหม่ หากใช้ไบนารี Executable and Linkable Format (ELF) ก็ควรเข้ากันได้กับเคอร์เนลเก่า (เช่น โปรแกรมใหม่ 64 บิตที่ทำงานบนเคอร์เนล 32 บิตแบบเก่า หากสถาปัตยกรรมเปลี่ยนจากบิลด์ 32- เป็น 64 บิต) เว้นแต่ว่าตัวโหลด ( ld ) จะได้รับคำสั่งให้ใช้พาธอื่นหรือสร้างไบนารีแบบสแตติก ไลบรารีจะถูกโหลดจากอิมเมจระบบเก่าและไม่ใช่อิมเมจใหม่

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

โปรแกรมหลังการติดตั้งใหม่ถูกจำกัดโดยนโยบาย SELinux ที่กำหนดไว้ในระบบเก่า ดังนั้น ขั้นตอนหลังการติดตั้งจึงเหมาะสำหรับการทำงานที่ต้องการโดยการออกแบบบนอุปกรณ์ที่กำหนดหรืองานอื่นๆ ที่มีความพยายามสูงสุด (เช่น การอัปเดตเฟิร์มแวร์หรือโปรแกรมโหลดบูตที่รองรับ A/B การเตรียมสำเนาของฐานข้อมูลสำหรับเวอร์ชันใหม่ เป็นต้น ). ขั้นตอนหลังการติดตั้ง ไม่เหมาะ สำหรับการแก้ไขจุดบกพร่องแบบครั้งเดียวก่อนรีบูตซึ่งต้องใช้สิทธิ์ที่ไม่คาดฝัน

โปรแกรมหลังการติดตั้งที่เลือกทำงานในบริบท postinstall หลังการติดตั้ง ไฟล์ทั้งหมดในพาร์ติชั่นที่เมาท์ใหม่จะถูกแท็กด้วย postinstall_file โดยไม่คำนึงถึงคุณลักษณะของพวกเขาหลังจากรีบูตระบบใหม่นั้น การเปลี่ยนแปลงแอตทริบิวต์ SELinux ในระบบใหม่จะไม่ส่งผลต่อขั้นตอนหลังการติดตั้ง หากโปรแกรมหลังการติดตั้งต้องการการอนุญาตพิเศษ จะต้องเพิ่มการอนุญาตเหล่านั้นในบริบทหลังการติดตั้ง

หลังจากรีบูต

หลังจากรีบูตแล้ว update_verifier จะทริกเกอร์การตรวจสอบความสมบูรณ์โดยใช้ dm-verity การตรวจสอบนี้เริ่มต้นก่อนไซโกตเพื่อหลีกเลี่ยงบริการ Java ที่ทำการเปลี่ยนแปลงที่ไม่สามารถย้อนกลับได้ซึ่งจะป้องกันการย้อนกลับอย่างปลอดภัย ในระหว่างกระบวนการนี้ bootloader และเคอร์เนลอาจทริกเกอร์การรีบูตหากการบู๊ตที่ตรวจสอบแล้วหรือ dm-verity ตรวจพบความเสียหาย หลังจากการตรวจสอบเสร็จสิ้น update_verifier จะทำเครื่องหมายการบูตสำเร็จ

update_verifier จะอ่านเฉพาะบล็อกที่ระบุไว้ใน /data/ota_package/care_map.txt ซึ่งรวมอยู่ในแพ็คเกจ A/B OTA เมื่อใช้รหัส AOSP ไคลเอ็นต์การอัปเดตระบบ Java เช่น GmsCore จะ care_map.txt ตั้งค่าการอนุญาตการเข้าถึงก่อนที่จะรีบูตอุปกรณ์ และลบไฟล์ที่แยกออกมาหลังจากที่ระบบบู๊ตเป็นเวอร์ชันใหม่ได้สำเร็จ