หน้านี้อธิบายการเปลี่ยนแปลงที่เพิ่มลงใน 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
(ตามที่คำจำกัดความต่างๆ กระจายอยู่ในไฟล์อื่นๆ)
โปรดดูรายละเอียดต่อไปนี้
- https://android.googlesource.com/platform/build/+/4d66adfd0e6d599d8502007e4ea9aaf82e95569f
- https://android.googlesource.com/platform/build/+/379f9f9cec4fe1c66b6d60a6c19fecb81b9eb410
- https://android.googlesource.com/platform/build/+/7c3e3f8314eec2c053012dd97d2ae649ebeb5653
- https://android.googlesource.com/platform/build/+/5c64b4e81c1331cab56d8a8c201f26bb263b630c
ไดเรกทอรีบิลด์
ปัญหา: การเปลี่ยนไดเรกทอรีที่สร้างอาจทำให้เกิด
ไบนารีแตกต่างกัน เส้นทางส่วนใหญ่ในบิลด์ของ 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++
มาโครเหล่านี้จะสร้างเอาต์พุตที่แตกต่างกันสำหรับบิลด์ต่างๆ เสมอ ดังนั้นอย่าใช้มาโคร ที่นี่ เป็นตัวเลือกสองสามอย่างในการกำจัดมาโครเหล่านี้
- นำออก ตัวอย่างเช่น อ้างถึง https://android.googlesource.com/platform/system/core/+/30622bbb209db187f6851e4cf0cdaa147c2fca9f
- หากต้องการระบุไบนารีที่ทำงานอยู่โดยเฉพาะ ให้อ่านรหัสบิลด์จากส่วนหัว ELF
-
หากต้องการทราบว่าระบบปฏิบัติการนี้สร้างขึ้นเมื่อใด โปรดอ่าน
ro.build.date
(ใช้ได้กับ ทั้งหมดยกเว้นบิลด์ส่วนเพิ่ม ซึ่งอาจไม่อัปเดตในวันที่นี้) ตัวอย่างเช่น โปรดอ้างอิง ถึง https://android.googlesource.com/platform/external/libchrome/+/8b7977eccc94f6b3a3896cd13b4aeacbfa1e0f84
การประทับเวลาแบบฝังในที่เก็บถาวร (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
ตัวอย่าง
- https://android.googlesource.com/platform/packages/apps/camera2/+/5e0f4cf699a4c7c95e2c38ae3babe6f20c258d27
- https://android.googlesource.com/platform/build/+/d75d893da8f97a5c7781142aaa7a16cf1dbb669c
เปิดใช้การคำนวณยืนยันความถูกต้องในอุปกรณ์
หากเป็น 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 นี้จะไม่มีผล
เครื่องมือสร้างที่สอดคล้อง
ปัญหา: เครื่องมือที่สร้างไฟล์ที่ติดตั้งไว้จะต้องมีความสอดคล้องกัน ( ควรสร้างเอาต์พุตเดียวกันเสมอ)
โซลูชัน/ตัวอย่าง: ต้องมีการเปลี่ยนแปลงในเครื่องมือสร้างต่อไปนี้
- เครื่องมือสร้างไฟล์ประกาศ มีการเปลี่ยนแปลงเครื่องมือสร้างไฟล์ NOTICE เป็นสร้าง คอลเล็กชัน NOTICE ที่ทำซ้ำได้ โปรดดู CL: https://android.googlesource.com/platform/build/+/8ae4984c2c8009e7a08e2a76b1762c2837ad4f64
- Java Android Compiler Kit (Jack) Jack Toolchain ต้องอัปเดตเป็น จัดการการเปลี่ยนแปลงลำดับของตัวสร้างที่สร้างขึ้นเป็นครั้งคราว ตัวเข้าถึงเชิงกำหนดสำหรับ มีการเพิ่มเครื่องมือสร้างลงใน Toolchain https://android.googlesource.com/toolchain/jack/+/056a5425b3ef57935206c19ecb198a89221ca64b
- ART AOT compiler (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) ของแอปพลิเคชัน ไฟล์ Pre-dexopt (.odex) มีระยะห่างจากขอบที่ไม่ได้เริ่มต้นในระบบ 64 บิต มีการแก้ไขดังนี้ https://android.googlesource.com/platform/art/+/34ed3afc41820c72a3c0ab9770be66b6668aa029
ใช้เครื่องมือความแตกต่างของบิลด์
สำหรับกรณีที่ไม่สามารถกำจัดการเปลี่ยนแปลงไฟล์ที่เกี่ยวข้องกับบิลด์ได้ 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 โดยตรง