דף זה מתאר שינויים שנוספו ל-AOSP כדי לצמצם שינויים מיותרים בקבצים בין בנייה. מיישמי מכשירים שמתחזקים מערכות בנייה משלהם יכולים להשתמש במידע זה כמדריך לצמצום גודל העדכונים האויר-האוויר (OTA) שלהם.
עדכוני OTA של Android מכילים מדי פעם קבצים שהשתנו שאינם תואמים לשינויי קוד. הם למעשה בונים חפצי מערכת. זה יכול להתרחש כאשר אותו קוד, שנבנה בזמנים שונים, מספריות שונות, או במכונות שונות מייצר מספר רב של קבצים שהשתנו. עודף קבצים כזה מגדיל את גודלו של תיקון OTA, ומקשה לקבוע איזה קוד השתנה.
כדי להפוך את התוכן של OTA לשקוף יותר, AOSP כולל שינויי מערכת בנייה שנועדו להקטין את גודל תיקוני OTA. שינויים מיותרים בקבצים בין רכיבי בנייה בוטלו, ורק קבצים הקשורים לתיקון כלולים בעדכוני OTA. AOSP כולל גם כלי build diff , המסנן שינויים נפוצים הקשורים ל-build כדי לספק הבדל קובץ בנייה נקי יותר, וכלי מיפוי בלוקים , שעוזר לך לשמור על עקביות בהקצאת בלוקים.
מערכת בנייה יכולה ליצור תיקונים גדולים שלא לצורך בכמה דרכים. כדי למתן את זה, באנדרואיד 8.0 ואילך, הוטמעו תכונות חדשות כדי להפחית את גודל התיקון עבור כל הבדל קובץ. שיפורים שהקטינו את גדלי החבילות של עדכון OTA כוללים את הדברים הבאים:
- שימוש ב- Brotli , אלגוריתם דחיסה גנרי ללא אובדן לתמונות מלאות בעדכוני מכשיר שאינם A/B. ניתן להתאים אישית את Brotli כדי לייעל את הדחיסה. בעדכונים גדולים יותר המורכבים משני בלוקים או יותר במערכת הקבצים (לדוגמה,
system.img
), יצרני מכשירים או שותפים יכולים להוסיף אלגוריתמי דחיסה משלהם, ויכולים להשתמש באלגוריתמי דחיסה שונים על בלוקים שונים של אותו עדכון. - שימוש בדחיסה מחדש של Puffin , כלי תיקון דטרמיניסטי להוצאת זרמים, המטפל בפונקציות הדחיסה וההבדל ליצירת עדכון A/B OTA.
- שינויים בשימוש בכלי דור דלתא, כגון אופן השימוש בספריית
bsdiff
לדחיסת תיקונים. באנדרואיד 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
(כפי שמספר הגדרות נפרסו בקבצי makefile אחרים). לפרטים, עיין בפרטים הבאים:
- 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 build הם נתיבים יחסיים ולכן __FILE__
ב-C/C++ אינו מהווה בעיה. עם זאת, סמלי ניפוי הבאגים מקודדים את שם הנתיב המלא כברירת מחדל, וה- .note.gnu.build-id
נוצר מ-hashing הבינארי המופשט מראש, כך שהוא ישתנה אם סמלי ניפוי הבאגים ישתנו.
פתרון: AOSP הופך כעת נתיבי ניפוי באגים ליחסיים. לפרטים, עיין ב-CL: https://android.googlesource.com/platform/build/+/6a66a887baadc9eb3d0d60e26f748b8453e27a02 .
חותמות זמן
בעיה: חותמות זמן בפלט ה-build גורמות לשינויים מיותרים בקבצים. סביר להניח שזה יקרה במקומות הבאים:
-
__DATE__/__TIME__/__TIMESTAMP__
בקוד C או C++. - חותמות זמן מוטמעות בארכיונים מבוססי zip.
פתרונות/דוגמאות: כדי להסיר חותמות זמן מפלט ה-build, השתמש בהוראות המפורטות להלן ב -__DATE__/__TIME__/__TIMESTAMP__ ב-C/C++. וחותמות זמן מוטבעות בארכיונים .
__DATE__/__TIME__/__TIMESTAMP__ ב-C/C++
פקודות מאקרו אלו תמיד מייצרות פלטים שונים עבור בנייה שונה, אז אל תשתמש בהן. להלן מספר אפשרויות לביטול פקודות המאקרו הללו:
- תזיזו אותם. לדוגמא, עיין בכתובת https://android.googlesource.com/platform/system/core/+/30622bbb209db187f6851e4cf0cdaa147c2fca9f .
- כדי לזהות באופן ייחודי את הבינארי הפועל, קרא את ה-build-id מהכותרת ELF.
- כדי לדעת מתי מערכת ההפעלה נבנתה, קרא את
ro.build.date
(זה עובד לכל דבר מלבד בנייה מצטברת, שאולי לא תעדכן את התאריך הזה). לדוגמא, עיין בכתובת https://android.googlesource.com/platform/external/libchrome/+/8b7977eccc94f6b3a3896cd13b4aeacbfa1e0f84 .
חותמות זמן מוטמעות בארכיונים (מיקוד, צנצנת)
אנדרואיד 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 עדיין יהיה שונה.
פתרון: הסר את מספר ה-build ממחרוזת גרסת ה-APK.
דוגמאות:
- https://android.googlesource.com/platform/packages/apps/Camera2/+/5e0f4cf699a4c7c95e2c38ae3babe6f20c258d27
- https://android.googlesource.com/platform/build/+/d75d893da8f97a5c7781142aaa7a16cf1dbb669c
אפשר חישוב אמת במכשיר
אם dm-verity מופעל במכשיר שלך, אז כלי OTA קולטים אוטומטית את תצורת ה-Verity שלך ומפעילים חישוב אמת במכשיר. זה מאפשר לחשב בלוקים של אמת במכשירי אנדרואיד, במקום להיות מאוחסנים כבייטים גולמיים בחבילת ה-OTA שלך. בלוקים של Verity יכולים להשתמש בכ-16MB עבור מחיצה של 2GB.
עם זאת, אימות המחשוב במכשיר יכול לקחת זמן רב. באופן ספציפי, קוד תיקון השגיאות העברה יכול להימשך זמן רב. במכשירי פיקסל, זה נוטה לקחת עד 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 דרשה עדכון כדי לטפל בשינויים מזדמנים בהזמנת הבנאים שנוצרה. לשרשרת הכלים נוספו אביזרים דטרמיניסטים עבור בנאים: https://android.googlesource.com/toolchain/jack/+/056a5425b3ef57935206c19ecb198a89221ca64b .
- מהדר ART AOT (dex2oat) . הבינארי מהדר ART קיבל עדכון שהוסיף אפשרות ליצור תמונה דטרמיניסטית: https://android.googlesource.com/platform/art/+/ace0dc1dd5480ad458e622085e51583653853fb9 .
- הקובץ libpac.so (V8) . כל build יוצר קובץ
/system/lib/libpac.so
שונה מכיוון שתמונת המצב של V8 משתנה עבור כל build. הפתרון היה להסיר את תמונת המצב: https://android.googlesource.com/platform/external/v8/+/e537f38c36600fd0f3026adba6b3f4cbcee1fb29 . - קבצי Pre-dexopt (.odex) של יישומים . קבצי Pre-dexopt (.odex) הכילו ריפוד לא מאותחל במערכות 64 סיביות. זה תוקן: https://android.googlesource.com/platform/art/+/34ed3afc41820c72a3c0ab9770be66b6668aa029 .
השתמש בכלי build diff
במקרים בהם לא ניתן לבטל שינויים בקבצים הקשורים ל-build, AOSP כולל כלי build diff, target_files_diff.py
לשימוש בהשוואה בין שתי חבילות קבצים. כלי זה מבצע הבדל רקורסיבי בין שני בניינים, למעט שינויים נפוצים הקשורים ל-build, כגון
- שינויים צפויים בפלט ה-build (לדוגמה, עקב שינוי מספר build).
- שינויים עקב בעיות ידועות במערכת הבנייה הנוכחית.
כדי להשתמש בכלי build diff, הפעל את הפקודה הבאה:
target_files_diff.py dir1 dir2
dir1
ו- dir2
הן ספריות בסיס המכילות את קובצי היעד שחולצו עבור כל build.
שמור על הקצאת בלוקים עקבית
עבור קובץ נתון, למרות שהתוכן שלו נשאר זהה בין שני בנייה, ייתכן שהבלוקים בפועל שמכילים את הנתונים השתנו. כתוצאה מכך, על המעדכן לבצע I/O מיותר כדי להזיז את הבלוקים לעדכון OTA.
בעדכון Virtual A/B OTA, I/O מיותר יכול להגדיל במידה ניכרת את שטח האחסון הדרוש לאחסון תמונת המצב של העתק-על-כתיבה. בעדכון OTA שאינו A/B, הזזת הבלוקים לעדכון OTA תורמת לזמן העדכון מכיוון שיש יותר I/O עקב מהלכי חסימה.
כדי לטפל בבעיה זו, ב-Android 7.0 Google הרחיבה את הכלי make_ext4fs
לשמירה על עקביות של הקצאת בלוקים בין ה-builds. הכלי 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 על ידי אי הכללת עדכונים עבור אפליקציות שמקבלות עדכונים דרך חנויות אפליקציות. חבילות APK מהוות לרוב חלק משמעותי ממחיצות שונות במכשיר. הכללת הגרסאות העדכניות ביותר של אפליקציות שמתעדכנות על ידי חנויות אפליקציות בעדכון OTA עשויה להשפיע בגודל גדול על חבילות OTA, ולספק מעט תועלת למשתמש. בזמן שמשתמשים יקבלו חבילת OTA, ייתכן שכבר יש להם את האפליקציה המעודכנת, או גרסה חדשה אפילו יותר, שהתקבלה ישירות מחנויות האפליקציות.