ลดขนาด OTA

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

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

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

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

  • การใช้ Brotli ซึ่งเป็นอัลกอริทึมการบีบอัดแบบไม่สูญเสียรายละเอียดที่มีวัตถุประสงค์ทั่วไปสำหรับการบีบอัดเต็มรูปแบบ รูปภาพในการอัปเดตอุปกรณ์ที่ไม่ใช่ A/B Brotli สามารถปรับแต่งเพื่อเพิ่มประสิทธิภาพ การบีบอัด ในการอัปเดตขนาดใหญ่ ซึ่งประกอบด้วยบล็อกสองบล็อกขึ้นไปในระบบไฟล์ (สำหรับ เช่น system.img) ผู้ผลิตอุปกรณ์หรือพาร์ทเนอร์จะเพิ่มข้อมูลของตนเอง อัลกอริทึมการบีบอัด และสามารถใช้อัลกอริทึม การบีบอัดที่แตกต่างกันในบล็อกของ อัปเดตเดียวกันนี้
  • การใช้การบีบอัดอีกครั้งของ Puffin ซึ่งเป็นเครื่องมือแพตช์ที่กำหนดสำหรับการลดระดับ สตรีมที่จัดการฟังก์ชันการบีบอัดและความแตกต่างของฟังก์ชันการสร้างการอัปเดต A/B OTA
  • การเปลี่ยนแปลงการใช้เครื่องมือสร้างเดลต้า เช่น bsdiff ไลบรารีที่ใช้สำหรับบีบอัดแพตช์ ใน Android 9 ขึ้นไป bsdiff จะเลือกอัลกอริทึมการบีบอัดที่ให้ ผลการบีบอัดที่ดีที่สุดสำหรับแพตช์
  • การปรับปรุง update_engine ส่งผลให้ใช้หน่วยความจำน้อยลงเมื่อมีการใช้แพตช์สำหรับการอัปเดตอุปกรณ์ A/B
  • การปรับปรุงการแยกไฟล์ ZIP ขนาดใหญ่สำหรับการอัปเดต OTA แบบบล็อก โหมดใน imgdiff แยกไฟล์ APK ที่มีขนาดใหญ่เกินไปตามชื่อรายการ ซึ่งทำให้เกิดแพตช์ที่มีขนาดเล็กกว่าเมื่อเทียบกับ แยกไฟล์แบบเชิงเส้นและใช้เครื่องมือ bsdiff เพื่อบีบอัดไฟล์

ส่วนต่อไปนี้จะกล่าวถึงปัญหาต่างๆ ที่มีผลต่อขนาดการอัปเดต OTA, โซลูชัน และตัวอย่างการติดตั้งใช้งานใน AOSP

ลำดับไฟล์

ปัญหา: ระบบไฟล์ไม่รับประกันลำดับของไฟล์เมื่อมีการขอรายการ ไฟล์ในไดเรกทอรี แม้ว่ามักจะเหมือนกันสำหรับจุดชำระเงินเดียวกัน เครื่องมือ เช่น ls จะจัดเรียงผลลัพธ์โดยค่าเริ่มต้น แต่ฟังก์ชันไวลด์การ์ดที่ใช้โดยคำสั่งต่างๆ เช่น เนื่องจาก find และ make ไม่ได้จัดเรียง ก่อนที่จะใช้เครื่องมือเหล่านี้ คุณต้องจัดเรียง เอาต์พุต

วิธีแก้ปัญหา: เมื่อคุณใช้เครื่องมือ เช่น find และ make ด้วยฟังก์ชันไวลด์การ์ด ให้จัดเรียงเอาต์พุตของคำสั่งเหล่านี้ก่อนใช้ ให้พวกเขา เมื่อใช้ $(wildcard) หรือ $(shell find) ใน Android.mk ไฟล์ โปรดจัดเรียงด้วย เครื่องมือบางอย่าง เช่น Java จะจัดเรียงอินพุต ก่อนจัดเรียงไฟล์ ให้ตรวจสอบว่าเครื่องมือที่คุณใช้อยู่ยังไม่ได้ดำเนินการดังกล่าว

ตัวอย่าง: หลายอินสแตนซ์ได้รับการแก้ไขในระบบบิลด์หลักโดยใช้ ในตัว all-*-files-under ซึ่งรวมถึง all-cpp-files-under (ตามที่คำจำกัดความต่างๆ กระจายอยู่ในไฟล์อื่นๆ) โปรดดูรายละเอียดต่อไปนี้

ไดเรกทอรีบิลด์

ปัญหา: การเปลี่ยนไดเรกทอรีที่สร้างอาจทำให้เกิด ไบนารีแตกต่างกัน เส้นทางส่วนใหญ่ในบิลด์ของ Android เป็นเส้นทางแบบสัมพัทธ์ ดังนั้น ไม่มีปัญหา __FILE__ ใน C/C++ แต่สัญลักษณ์การแก้ไขข้อบกพร่องจะเข้ารหัส โดยค่าเริ่มต้น และ .note.gnu.build-id จะสร้างขึ้นจากการแฮช ไบนารีที่ดึงไว้ล่วงหน้า ดังนั้นจะเปลี่ยนไปหากสัญลักษณ์การแก้ไขข้อบกพร่องเปลี่ยนไป

วิธีแก้ไข: ตอนนี้ AOSP ทำให้เส้นทางการแก้ไขข้อบกพร่องสัมพันธ์กันแล้ว โปรดดูรายละเอียดใน CL https://android.googlesource.com/platform/build/+/6a66a887baadc9eb3d0d60e26f748b8453e27a02

การประทับเวลา

ปัญหา: การประทับเวลาในเอาต์พุตของบิลด์ทำให้เกิดการเปลี่ยนแปลงไฟล์โดยไม่จำเป็น โดยกรณีนี้อาจเกิดขึ้นในพื้นที่ต่อไปนี้

  • __DATE__/__TIME__/__TIMESTAMP__ มาโครในโค้ด C หรือ C++
  • การประทับเวลาที่ฝังในที่เก็บถาวรแบบ Zip

โซลูชัน/ตัวอย่าง: หากต้องการนำการประทับเวลาออกจากเอาต์พุตของบิลด์ ให้ใช้เมธอด ตามคำแนะนำด้านล่างใน __DATE__/__TIME__/__TIMESTAMP__ ใน C/C++ และ การประทับเวลาที่ฝังในที่เก็บถาวร

__DATE__/__TIME__/__TIMESTAMP__ ใน C/C++

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

การประทับเวลาแบบฝังในที่เก็บถาวร (zip, jar)

Android 7.0 แก้ไขปัญหาการประทับเวลาที่ฝังไว้ในที่เก็บถาวรแบบ Zip ด้วยการเพิ่ม -X สำหรับการใช้งานทั้งหมดของคำสั่ง zip การดำเนินการนี้ได้นำ UID/GID ของ และสร้างการประทับเวลา Unix แบบขยายจากไฟล์ ZIP

เครื่องมือใหม่ ziptime (อยู่ที่ /platform/build/+/main/tools/ziptime/) รีเซ็ตการประทับเวลาปกติในส่วนหัว ZIP ดูรายละเอียดได้ที่ ไฟล์ README

เครื่องมือ signapk จะกำหนดการประทับเวลาสำหรับไฟล์ APK ที่อาจแตกต่างกันไปโดยขึ้นอยู่กับ เขตเวลาของเซิร์ฟเวอร์ โปรดดูรายละเอียดใน CL https://android.googlesource.com/platform/build/+/6c41036bcf35fe39162b50d27533f0f3bfab3028

สตริงเวอร์ชัน

ปัญหา: สตริงเวอร์ชัน APK มักจะมี BUILD_NUMBER ต่อท้าย ในเวอร์ชันฮาร์ดโค้ด แม้ว่าจะไม่มีการเปลี่ยนแปลงอื่นใน APK ซึ่งทำให้ APK ก็ยังคงแตกต่างกัน

วิธีแก้ไข: นำหมายเลขบิลด์ออกจากสตริงเวอร์ชัน APK

ตัวอย่าง

เปิดใช้การคำนวณยืนยันความถูกต้องในอุปกรณ์

หากเป็น dm-verity บนอุปกรณ์ จากนั้นเครื่องมือ OTA จะกำหนดค่าการยืนยันโดยอัตโนมัติและ เปิดใช้การคำนวณความถูกต้องในอุปกรณ์ การดำเนินการนี้ช่วยให้สามารถคำนวณการบล็อกเวอร์ชันจริงใน Android อุปกรณ์ต่างๆ แทนการจัดเก็บเป็นไบต์ดิบในแพ็กเกจ OTA การบล็อกรายละเอียดที่ใช้ได้ ประมาณ 16 MB สำหรับพาร์ติชัน 2 GB

อย่างไรก็ตาม ความถูกต้องของการประมวลผลในอุปกรณ์อาจใช้เวลานาน โดยเฉพาะอย่างยิ่ง รหัสการแก้ไขข้อผิดพลาดอาจใช้เวลานาน โดยอุปกรณ์ Pixel มักจะใช้เวลาไม่เกิน 10 นาที แต่อาจใช้เวลานานกว่านั้นในอุปกรณ์ระดับโลว์เอนด์ หากคุณต้องการปิดใช้เวอร์ชันจริงในอุปกรณ์ โดยอัตโนมัติได้ แต่ยังเปิดใช้ dm-verity ก็ทำได้โดยการส่งผ่าน --disable_fec_computationไปยังเครื่องมือota_from_target_filesเมื่อ การสร้างการอัปเดต OTA แฟล็กนี้จะปิดใช้การคำนวณเวอร์ชันในอุปกรณ์ระหว่างการอัปเดต OTA ช่วยลดเวลาการติดตั้ง OTA แต่จะทำให้แพ็กเกจ OTA เพิ่มขึ้น ถ้าอุปกรณ์ของคุณไม่ เปิดใช้งาน dm-verity การส่งผ่าน Flag นี้จะไม่มีผล

เครื่องมือสร้างที่สอดคล้อง

ปัญหา: เครื่องมือที่สร้างไฟล์ที่ติดตั้งไว้จะต้องมีความสอดคล้องกัน ( ควรสร้างเอาต์พุตเดียวกันเสมอ)

โซลูชัน/ตัวอย่าง: ต้องมีการเปลี่ยนแปลงในเครื่องมือสร้างต่อไปนี้

ใช้เครื่องมือความแตกต่างของบิลด์

สำหรับกรณีที่ไม่สามารถกำจัดการเปลี่ยนแปลงไฟล์ที่เกี่ยวข้องกับบิลด์ได้ AOSP จะมี สร้างความแตกต่าง target_files_diff.py เพื่อใช้ในการเปรียบเทียบแพ็กเกจไฟล์ 2 แพ็กเกจ เครื่องมือนี้แสดงความแตกต่างที่เกิดซ้ำระหว่าง สร้าง ยกเว้นการเปลี่ยนแปลงไฟล์ที่เกี่ยวข้องกับบิลด์ที่พบบ่อย เช่น

  • การเปลี่ยนแปลงที่คาดไว้ในเอาต์พุตของบิลด์ (เช่น เนื่องจากการเปลี่ยนแปลงหมายเลขบิลด์)
  • การเปลี่ยนแปลงเนื่องจากปัญหาที่ทราบในระบบบิลด์ปัจจุบัน

หากต้องการใช้เครื่องมือความแตกต่างของบิลด์ ให้เรียกใช้คำสั่งต่อไปนี้

target_files_diff.py dir1 dir2

dir1 และ dir2 เป็นไดเรกทอรีฐานที่มีเป้าหมายที่แตกข้อมูล ไฟล์สำหรับแต่ละบิลด์

ทำให้การจัดสรรการบล็อกสอดคล้องกัน

สำหรับไฟล์หนึ่งๆ แม้ว่าเนื้อหาจะยังคงเหมือนเดิมระหว่างบิลด์ 2 รายการ แต่บล็อกจริง ที่จัดเก็บข้อมูลนั้นไว้อาจเปลี่ยนแปลงแล้ว ดังนั้น โปรแกรมอัปเดตจึงต้องดำเนินการ I/O โดยไม่จำเป็น ย้ายบล็อกไปรอบๆ เพื่ออัปเดต OTA

ในการอัปเดต OTA ทางออนไลน์ของ A/B นั้น I/O ที่ไม่จำเป็นจะช่วยเพิ่มพื้นที่เก็บข้อมูลที่ต้องใช้ได้เป็นอย่างมาก เพื่อจัดเก็บสแนปชอตแบบคัดลอกและวาง ในการอัปเดต OTA ที่ไม่ใช่ A/B การย้ายการบล็อกไปรอบๆ การอัปเดต OTA ทำให้เวลาอัปเดตมี I/O มากขึ้นเนื่องจากมีการย้ายการบล็อก

ในการแก้ปัญหานี้ Google ได้ขยายเครื่องมือ make_ext4fs ใน Android 7.0 สำหรับ ทำให้การจัดสรรการบล็อกสอดคล้องกันในทุกบิลด์ เครื่องมือ make_ext4fs ยอมรับ แฟล็ก -d base_fs ที่ไม่บังคับซึ่งพยายามจัดสรรไฟล์ไปยังบล็อกเดียวกัน เมื่อสร้างรูปภาพ ext4 คุณสามารถแตกไฟล์การแมปการบล็อก (เช่น ไฟล์แผนที่ base_fs) จากไฟล์เป้าหมายของบิลด์ก่อนหน้า ไฟล์ ZIP สำหรับแต่ละรายการ ext4 พาร์ติชัน มีไฟล์ .map อยู่ใน ไดเรกทอรี IMAGES (เช่น IMAGES/system.map สอดคล้องกับ พาร์ติชัน system) จากนั้นจะสามารถเช็คอิน base_fs ไฟล์นี้และ ระบุผ่าน PRODUCT_<partition>_BASE_FS_PATH ตามตัวอย่างนี้

  PRODUCT_SYSTEM_BASE_FS_PATH := path/to/base_fs_files/base_system.map
  PRODUCT_SYSTEM_EXT_BASE_FS_PATH := path/to/base_fs_files/base_system_ext.map
  PRODUCT_VENDOR_BASE_FS_PATH := path/to/base_fs_files/base_vendor.map
  PRODUCT_PRODUCT_BASE_FS_PATH := path/to/base_fs_files/base_product.map
  PRODUCT_ODM_BASE_FS_PATH := path/to/base_fs_files/base_odm.map

แม้ว่านี่จะไม่ช่วยลดขนาดแพ็กเกจ OTA โดยรวม แต่จะช่วยปรับปรุงการอัปเดต OTA ประสิทธิภาพการทำงานโดยลดจำนวน I/O การอัปเดต A/B ทางออนไลน์นั้นช่วยลด จำนวนพื้นที่เก็บข้อมูลที่จำเป็นต้องใช้สำหรับ OTA

หลีกเลี่ยงการอัปเดตแอป

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