ลดขนาด OTA

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

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

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

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

  • การใช้ ZSTD ซึ่งเป็นอัลกอริทึมการบีบอัดแบบไม่สูญเสียข้อมูลสำหรับวัตถุประสงค์ทั่วไปสำหรับรูปภาพขนาดเต็มในการอัปเดตอุปกรณ์ที่ไม่ใช่ A/B ZSTD สามารถปรับแต่งให้อัตราส่วนการบีบอัดสูงขึ้นได้โดยการเพิ่มความเข้มงวดในการบีบอัด ระดับการบีบอัดจะตั้งค่าในระหว่างการสร้าง OTA และสามารถตั้งค่าได้โดยส่ง Flag --vabc_compression_param=zstd,$COMPRESSION_LEVEL
  • การเพิ่มขนาดกรอบเวลาการบีบอัดที่ใช้ระหว่าง OTA คุณตั้งค่าขนาดกรอบเวลาการบีบอัดสูงสุดได้โดยการกําหนดค่าพารามิเตอร์การสร้างในไฟล์ .mk ของอุปกรณ์ ตัวแปรนี้ตั้งค่าเป็น PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR := 262144
  • การใช้การบีบอัดซ้ำของ Puffin ซึ่งเป็นเครื่องมือการปะแก้แบบกำหนดได้สำหรับสตรีม deflate ที่จัดการฟังก์ชันการบีบอัดและ Diff เพื่อสร้างการอัปเดต OTA ของ A/B
  • การเปลี่ยนแปลงการใช้งานเครื่องมือสร้าง Delta เช่น วิธีใช้ไลบรารีเพื่อบีบอัดแพตช์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 (เนื่องจากคําจํากัดความหลายรายการกระจายอยู่ในไฟล์ Make อื่นๆ) ดูรายละเอียดได้ที่หัวข้อต่อไปนี้

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

ปัญหา: การเปลี่ยนไดเรกทอรีที่ใช้สร้างสิ่งต่างๆ อาจทําให้ไฟล์ไบนารีแตกต่างกัน เส้นทางส่วนใหญ่ในบิลด์ 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

ตัวอย่าง

เปิดใช้การคํานวณ Verity ในอุปกรณ์

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

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

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

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

วิธีแก้ปัญหา/ตัวอย่าง: จำเป็นต้องทำการเปลี่ยนแปลงในเครื่องมือสร้างต่อไปนี้

  • เครื่องมือสร้างไฟล์ประกาศ เครื่องมือสร้างไฟล์ประกาศมีการเปลี่ยนแปลงเพื่อสร้างคอลเล็กชันประกาศที่ซ้ำกันได้ โปรดดู CL: https://android.googlesource.com/platform/build/+/8ae4984c2c8009e7a08e2a76b1762c2837ad4f64
  • Java Android Compiler Kit (Jack) เครื่องมือทางเทคนิคของ Jack จำเป็นต้องมีการอัปเดตเพื่อจัดการกับการเปลี่ยนแปลงที่เกิดขึ้นเป็นครั้งคราวในลําดับการสร้างที่สร้างขึ้น เพิ่มตัวรับค่าแบบกำหนดให้กับตัวสร้างลงในชุดเครื่องมือ https://android.googlesource.com/toolchain/jack/+/056a5425b3ef57935206c19ecb198a89221ca64b
  • คอมไพเลอร์ AOT ของ ART (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
  • ไฟล์การแยกไฟล์ Pre-Dexopt (.odex) ของแอปพลิเคชัน ไฟล์ก่อนการ Dexopt (.odex) มีการเพิ่มพื้นที่ว่างที่ไม่ได้เริ่มต้นในระบบ 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 จะส่งผลต่อเวลาอัปเดตเนื่องจากมี I/O มากขึ้นเนื่องจากการย้ายบล็อก

Google ได้ขยายmake_ext4fsเครื่องมือสำหรับการรักษาการจัดสรรบล็อกให้สอดคล้องกันในบิลด์ต่างๆ เพื่อแก้ไขปัญหานี้ใน Android 7.0 เครื่องมือ make_ext4fs ยอมรับ Flag -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 โดยตรง