ลดขนาด OTA

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

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

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

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

  • การใช้ ZSTD ซึ่งเป็นอัลกอริทึมการบีบอัดแบบไม่สูญเสียข้อมูลแบบอเนกประสงค์สำหรับรูปภาพแบบเต็ม ในการอัปเดตอุปกรณ์ที่ไม่ใช่ A/B ZSTD สามารถปรับแต่งเพื่อให้อัตราส่วนการบีบอัดสูงขึ้น ได้โดยการเพิ่มระดับการบีบอัด ระดับการบีบอัดจะตั้งค่าในระหว่างเวลาสร้าง OTA และตั้งค่าได้โดยส่งแฟล็ก --vabc_compression_param=zstd,$COMPRESSION_LEVEL
  • การเพิ่มขนาดหน้าต่างการบีบอัดที่ใช้ระหว่าง OTA คุณตั้งค่าขนาดหน้าต่างการบีบอัดสูงสุด ได้โดยการปรับแต่งพารามิเตอร์บิลด์ในไฟล์ .mk ของอุปกรณ์ ตัวแปรนี้ ตั้งค่าเป็น PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR := 262144
  • การใช้การบีบอัดซ้ำของ Puffin ซึ่งเป็นเครื่องมือแก้ไขที่แน่นอนสำหรับสตรีม deflate ซึ่งจัดการฟังก์ชันการบีบอัดและฟังก์ชัน diff สำหรับการสร้างการอัปเดต OTA แบบ A/B
  • การเปลี่ยนแปลงการใช้เครื่องมือสร้างเดลต้า เช่น วิธีใช้ไลบรารี bsdiff ในการบีบอัดแพตช์ ใน Android 9 ขึ้นไป เครื่องมือ bsdiff จะเลือกอัลกอริทึมการบีบอัดที่จะให้ ผลลัพธ์การบีบอัดที่ดีที่สุดสำหรับแพตช์
  • การปรับปรุง update_engine ส่งผลให้ใช้หน่วยความจำน้อยลงเมื่อใช้แพตช์สำหรับการอัปเดตอุปกรณ์ A/B

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

ลำดับไฟล์

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

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

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

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

ปัญหา: การเปลี่ยนไดเรกทอรีที่สร้างสิ่งต่างๆ อาจทำให้ไบนารีแตกต่างกัน เส้นทางส่วนใหญ่ในการสร้าง Android เป็นเส้นทางแบบสัมพัทธ์ ดังนั้น __FILE__ ใน C/C++ จึงไม่ใช่ปัญหา อย่างไรก็ตาม สัญลักษณ์การแก้ไขข้อบกพร่องจะเข้ารหัสเส้นทางแบบเต็ม โดยค่าเริ่มต้น และ .note.gnu.build-id จะสร้างขึ้นจากการแฮช ไบนารีที่ยังไม่ได้ลบ ดังนั้น .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/+/android16-release/tools/ziptime/) จะรีเซ็ตการประทับเวลาปกติในส่วนหัวของไฟล์ ZIP โปรดดูรายละเอียดใน ไฟล์ README

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

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

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

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

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

ตัวอย่าง

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

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

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

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

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

วิธีแก้ปัญหา/ตัวอย่าง: ต้องมีการเปลี่ยนแปลงในเครื่องมือบิลด์ต่อไปนี้

  • ผู้สร้างไฟล์ NOTICE เราได้เปลี่ยนผู้สร้างไฟล์ NOTICE เพื่อสร้าง คอลเล็กชัน NOTICE ที่ทำซ้ำได้ ดู CL ได้ที่ https://android.googlesource.com/platform/build/+/8ae4984c2c8009e7a08e2a76b1762c2837ad4f64
  • ชุดคอมไพเลอร์ Java สำหรับ Android (Jack) Toolchain ของ Jack ต้องได้รับการอัปเดตเพื่อ จัดการการเปลี่ยนแปลงเป็นครั้งคราวในการจัดลำดับตัวสร้างที่สร้างขึ้น เพิ่มตัวช่วยเข้าถึงที่กำหนดได้สำหรับ ตัวสร้างลงใน Toolchain ดังนี้ https://android.googlesource.com/toolchain/jack/+/056a5425b3ef57935206c19ecb198a89221ca64b
  • คอมไพเลอร์ ART AOT (dex2oat) ไบนารีของคอมไพเลอร์ ART ได้รับการอัปเดตที่ เพิ่มตัวเลือกในการสร้างอิมเมจที่กำหนดได้: https://android.googlesource.com/platform/art/+/ace0dc1dd5480ad458e622085e51583653853fb9
  • ไฟล์ libpac.so (V8) การสร้างแต่ละครั้งจะสร้างไฟล์ /system/lib/libpac.so ที่แตกต่างกันเนื่องจากสแนปชอต V8 จะเปลี่ยนไปในแต่ละการสร้าง วิธีแก้ปัญหาคือการนำสแนปชอตออก https://android.googlesource.com/platform/external/v8/+/e537f38c36600fd0f3026adba6b3f4cbcee1fb29
  • ไฟล์การเพิ่มประสิทธิภาพล่วงหน้าของแอปพลิเคชัน (.odex) ไฟล์ pre-dexopt (.odex) มี Padding ที่ไม่ได้เริ่มต้นในระบบ 64 บิต เราได้แก้ไขแล้วที่ https://android.googlesource.com/platform/art/+/34ed3afc41820c72a3c0ab9770be66b6668aa029

ใช้เครื่องมือเปรียบเทียบบิลด์

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

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

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

target_files_diff.py dir1 dir2

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

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

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

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

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