Android 10 תומך במחיצות דינמיות, מערכת חלוקה למחיצות במרחב המשתמש שיכולה ליצור, לשנות את הגודל ולמחוק מחיצות במהלך עדכונים דרך האוויר (OTA).
בדף הזה מוסבר איך לקוחות OTA משנים את הגודל של מחיצות דינמיות במהלך עדכון למכשירי A/B שהושקו ללא תמיכה במחיצות דינמיות, ואיך לקוחות OTA משדרגים ל-Android 10.
רקע
במהלך עדכון של מכשיר A/B לתמיכה במחיצות דינמיות, טבלת המחיצות GUID (GPT) במכשיר נשמרת, כך שאין מחיצת super במכשיר. המטא-נתונים מאוחסנים ב-system_a וב-system_b, אבל אפשר לשנות את ההגדרה הזו באמצעות שינוי של BOARD_SUPER_PARTITION_METADATA_DEVICE.
בכל אחד ממכשירי הבלוק יש שתי משבצות מטא-נתונים. משתמשים רק במשבצת מטא-נתונים אחת בכל מכשיר בלוק. לדוגמה, מטא-נתונים 0 ב-system_a ומטא-נתונים 1 ב-system_b מתאימים למחיצות במשבצות A ו-B, בהתאמה. בזמן הריצה, לא משנה איזה מיקום מתעדכן.
בדף הזה, משבצות המטא-נתונים נקראות Metadata S (מקור) ו-Metadata T (יעד). באופן דומה, המחיצות נקראות system_s, vendor_t וכן הלאה.
מידע נוסף על הגדרות של מערכת ה-build זמין במאמר שדרוג מכשירים.
מידע נוסף על הקשר בין מחיצות לבין קבוצות עדכון זמין במאמר שינויים בהגדרות של לוחות למכשירים חדשים.
דוגמה למטא-נתונים במכשיר:
- מכשיר בלוק פיזי
system_a- מטא-נתונים 0
- קבוצה
foo_a- מחיצה לוגית (דינמית)
system_a - מחיצה לוגית (דינמית)
product_services_a - מחיצות אחרות שעודכנו על ידי Foo
- מחיצה לוגית (דינמית)
- קבוצה
bar_a- מחיצה לוגית (דינמית)
vendor_a - מחיצה לוגית (דינמית)
product_a - מחיצות אחרות שעודכנו על ידי Bar
- מחיצה לוגית (דינמית)
- קבוצה
- מטא-נתונים 1 (לא בשימוש)
- מטא-נתונים 0
- מכשיר בלוק פיזי
system_b- מטא-נתונים 0 (לא בשימוש)
- מטא-נתונים 1
- Group foo_b
- מחיצה לוגית (דינמית)
system_b - מחיצה לוגית (דינמית)
product_services_b - מחיצות אחרות שעודכנו על ידי Foo
- מחיצה לוגית (דינמית)
- Group bar_b
- מחיצה לוגית (דינמית)
vendor_b - מחיצה לוגית (דינמית)
product_b - מחיצות אחרות שעודכנו על ידי Bar
- מחיצה לוגית (דינמית)
- Group foo_b
אתם יכולים להשתמש בכלי lpdump בקטע system/extras/partition_tools כדי להעביר את המטא-נתונים למכשיר. לדוגמה:
lpdump --slot 0 /dev/block/by-name/system_alpdump --slot 1 /dev/block/by-name/system_b
התאמת עדכון
במכשירים עם Android מגרסה 9 ומטה, לקוח ה-OTA במכשיר לא תומך במיפוי מחיצות דינמיות לפני העדכון. נוצרת קבוצה נוספת של תיקונים כדי שאפשר יהיה להחיל את המיפוי ישירות על המחיצות הפיזיות הקיימות.
מחולל ה-OTA יוצר את קובץ super.img הסופי שמכיל את התוכן של כל המחיצות הדינמיות, ואז מפצל את קובץ האימג' לכמה קובצי אימג' שתואמים לגדלים של התקני הבלוק הפיזיים שמתאימים למערכת, לספק וכו'. השמות של התמונות האלה הם super_system.img, super_vendor.img וכן הלאה.
לקוח ה-OTA מחיל את התמונות האלה על המחיצות הפיזיות, ולא על התמונות של המחיצות הלוגיות (הדינמיות).
מכיוון שלקוח ה-OTA לא יודע איך למפות מחיצות דינמיות, כל השלבים שלאחר ההתקנה מושבתים אוטומטית עבור המחיצות האלה כשחבילת העדכון נוצרת. פרטים נוספים מופיעים במאמר בנושא הגדרת אפליקציות אחרי ההתקנה.
תהליך העדכון זהה לזה שב-Android 9.
לפני העדכון:
ro.boot.dynamic_partitions= ro.boot.dynamic_partitions_retrofit=
אחרי העדכון:
ro.boot.dynamic_partitions=true ro.boot.dynamic_partitions_retrofit=true
עדכונים עתידיים אחרי התאמה
אחרי עדכון ה-retrofit, לקוח ה-OTA מתעדכן כדי לפעול עם מחיצות דינמיות. הגבולות של מחיצות המקור אף פעם לא חופפים לגבולות של מחיצות פיזיות של היעד.
תהליך העדכון באמצעות חבילת עדכון רגילה
- מאתחלים את המטא-נתונים של המחיצה
super.-
יצירת מטא-נתונים חדשים M ממטא-נתונים S (מטא-נתונים של המקור).
לדוגמה, אם מטא-נתונים S משתמשים ב-[
system_s,vendor_s,product_s] כמכשירי חסימה, אז המטא-נתונים החדשים M משתמשים ב-[system_t,vendor_t,product_t] כמכשירי חסימה. כל הקבוצות והמחיצות נמחקות ב-M. -
מוסיפים קבוצות יעד ומחיצות בהתאם לשדה
dynamic_partition_metadataבמניפסט העדכון. אפשר לראות את הגודל של כל מחיצה ב-new_partition_info. - כותבים M במטא-נתונים T.
- ממפים את המחיצות שנוספו ב-device mapper כניתנות לכתיבה.
-
יצירת מטא-נתונים חדשים M ממטא-נתונים S (מטא-נתונים של המקור).
לדוגמה, אם מטא-נתונים S משתמשים ב-[
- מחילים את העדכון על המכשירים החסומים.
- במידת הצורך, ממפים את מחיצות המקור בממפה המכשיר כקריאה בלבד. הפעולה הזו נדרשת להעברה צדדית כי המחיצות של המקור לא ממופות לפני העדכון.
- החלת עדכון מלא או עדכון דלתא על כל מכשירי הבלוק בחריץ היעד.
- מבצעים Mount למחיצות כדי להריץ את הסקריפט אחרי ההתקנה, ואז מבטלים את ה-Mount של המחיצות.
- מבטלים את המיפוי של מחיצות היעד.
תהליך העדכון באמצעות חבילת עדכון רטרו
אם חבילת העדכון של ה-retrofit מוחלת על מכשיר שכבר מופעלות בו מחיצות דינמיות, לקוח ה-OTA מחיל את קובץ הפיצול super.img ישירות על מכשירי הבלוק. תהליך העדכון דומה לעדכון רטרופיט. פרטים נוספים זמינים במאמר בנושא התקנת עדכון רטרואקטיבי.
לדוגמה, נניח את הפרטים הבאים:
- חריץ A הוא החריץ הפעיל.
-
system_aמכיל את המטא-נתונים הפעילים במשבצת 0. -
האפליקציות
system_a,vendor_aוגםproduct_aמשמשות כהתקני בלוקים.
כשלקוח OTA מקבל חבילת עדכון של retrofit, הוא מחיל את super_system.img על system_b פיזי, את super_vendor.img על vendor_b פיזי ואת super_product.img על product_b פיזי.
התקן הבלוקים הפיזי system_b מכיל את המטא-נתונים הנכונים למיפוי הלוגי system_b, vendor_b ו-product_b בזמן האתחול.
יצירת חבילות עדכון
עדכון OTA מצטבר
כשיוצרים עדכוני OTA מצטברים למכשירים ששודרגו, העדכונים תלויים בהגדרות PRODUCT_USE_DYNAMIC_PARTITIONS ו-PRODUCT_RETROFIT_DYNAMIC_PARTITIONS בגרסת הבסיס.
-
אם בגרסת הבסיס לא מוגדרים המשתנים, זהו עדכון רטרופיטינג. חבילת העדכון מכילה את הקובץ split
super.imgומשביתה את השלב שאחרי ההתקנה. - אם בבניית הבסיס מוגדרים המשתנים, זה זהה לעדכון רגיל עם מחיצות דינמיות. חבילת העדכון מכילה את התמונות של מחיצות לוגיות (דינמיות). אפשר להפעיל את שלב ההתקנה.
Full OTA
שתי חבילות OTA מלאות נוצרות למכשירים ששודרגו.
-
$(PRODUCT)-ota-retrofit-$(TAG).zipתמיד מכיל את הפיצולsuper.imgומשבית את השלב שאחרי ההתקנה לעדכון רטרואקטיבי.-
הוא נוצר עם ארגומנט נוסף
--retrofit_dynamic_partitionsלסקריפטota_from_target_files. - אפשר להחיל אותו על כל הגרסאות.
-
הוא נוצר עם ארגומנט נוסף
-
$(PRODUCT)-ota-$(TAG).zipמכיל תמונות לוגיות לעדכונים עתידיים.- ההגדרה הזו חלה רק על גרסאות build שמופעלות בהן מחיצות דינמיות. פרטים נוספים על אכיפת ההגדרה הזו מופיעים בהמשך.
דחיית עדכון שלא מתאים לבנייה ישנה
חבילת ה-OTA המלאה הרגילה חלה רק על גרסאות build שמופעלות בהן מחיצות דינמיות. אם שרת ה-OTA מוגדר בצורה שגויה והוא דוחף את החבילות האלה למכשירים עם Android 9 או גרסה מוקדמת יותר, המכשירים לא יפעלו. לקוח ה-OTA ב-Android 9 ובגרסאות קודמות לא יכול להבדיל בין חבילת OTA של retrofit לבין חבילת OTA מלאה רגילה, ולכן הלקוח לא ידחה את החבילה המלאה.
כדי למנוע מהמכשיר לקבל את חבילת ה-OTA המלאה, אפשר לדרוש שלב אחרי ההתקנה כדי לבדוק את הגדרת המכשיר הקיימת. לדוגמה:
device/device_name/dynamic_partitions/check_dynamic_partitions
#!/system/bin/sh DP_PROPERTY_NAME="ro.boot.dynamic_partitions" DP_RETROFIT_PROPERTY_NAME="ro.boot.dynamic_partitions_retrofit" DP_PROPERTY=$(getprop ${DP_PROPERTY_NAME}) DP_RETROFIT_PROPERTY=$(getprop ${DP_RETROFIT_PROPERTY_NAME}) if [ "${DP_PROPERTY}" != "true" ] || [ "${DP_RETROFIT_PROPERTY}" != "true" ] ; then echo "Error: applied non-retrofit update on build without dynamic" \ "partitions." echo "${DP_PROPERTY_NAME}=${DP_PROPERTY}" echo "${DP_RETROFIT_PROPERTY_NAME}=${DP_RETROFIT_PROPERTY}" exit 1 fi
device/device_name/dynamic_partitions/Android.mk
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE:= check_dynamic_partitions LOCAL_MODULE_TAGS := optional LOCAL_MODULE_CLASS := EXECUTABLES LOCAL_SRC_FILES := check_dynamic_partitions LOCAL_PRODUCT_MODULE := true include $(BUILD_PREBUILT)
device/device_name/device.mk
PRODUCT_PACKAGES += check_dynamic_partitions # OPTIONAL=false so that the error in check_dynamic_partitions will be # propagated to OTA client. AB_OTA_POSTINSTALL_CONFIG += \ RUN_POSTINSTALL_product=true \ POSTINSTALL_PATH_product=bin/check_dynamic_partitions \ FILESYSTEM_TYPE_product=ext4 \ POSTINSTALL_OPTIONAL_product=false \
כשחבילת OTA רגילה מוחלת על מכשיר שלא מופעלות בו מחיצות דינמיות, לקוח ה-OTA מפעיל את check_dynamic_partitions כשלב אחרי ההתקנה ודוחה את העדכון.