OTA למכשירי A/B ללא מחיצות דינמיות

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
        • מחיצות אחרות שעודכנו על ידי הסרגל
    • מטא-נתונים 1 (לא בשימוש)
  • מכשיר לחסימה פיזית system_b
    • מטא-נתונים 0 (לא בשימוש)
    • מטא-נתונים 1
      • קבוצה foo_b
        • מחיצה לוגית (דינמית) system_b
        • מחיצה לוגית (דינמית) product_services_b
        • מחיצות אחרות שעודכנו על ידי Foo
      • קבוצה bar_b
        • מחיצה לוגית (דינמית) vendor_b
        • מחיצה לוגית (דינמית) product_b
        • מחיצות אחרות שעודכנו על ידי Bar

אפשר להשתמש בכלי lpdump בקטע system/extras/partition_tools כדי לדגום את המטא-נתונים במכשיר. לדוגמה:

lpdump --slot 0 /dev/block/by-name/system_a
lpdump --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

עדכונים עתידיים לאחר השדרוג

לאחר עדכון התיקון, לקוח ה-OTA מעודכן כדי לעבוד עם ומחיצות דינמיות. מידות המחיצות של המקור לא מתרחשות אף פעם למחיצות פיזיות ספציפיות.

עדכון תהליך באמצעות חבילת עדכון רגילה

  1. אתחול המטא-נתונים של המחיצה super.
    1. ליצור מטא-נתונים חדשים M מ-מטא-נתונים על S (מטא-נתונים של מקור). לדוגמה, אם מטא-נתונים S משתמשים ב-[system_s, vendor_s, product_s] כבלוק אז המטא-נתונים החדשים בפורמט M משתמשים ב-[system_t, vendor_t, product_t] כבלוק מכשירים. כל הקבוצות והמחיצות נמחקות ב-M.
    2. מוסיפים קבוצות יעד ומחיצות בהתאם השדה dynamic_partition_metadata בעדכון . הגודל של כל מחיצה ניתן למצוא ב new_partition_info
    3. כתיבת M למטא-נתונים T.
    4. מיפוי המחיצות שנוספו במיפוי המכשיר כניתנות לכתיבה.
  2. להחיל את העדכון על המכשירים החסומים.
    1. במידת הצורך, ממפים את המחיצות של המקור בממפה של המכשיר בתור קריאה בלבד. זה הכרחי בשביל לבצע התקנה ממקור לא ידוע כי מחיצות המקור לא ממופות לפני העדכון.
    2. יש להחיל עדכון מלא או עדכון דלתא על כל המכשירים החסומים משבצת היעד.
    3. מחברים את המחיצות כדי להריץ את הסקריפט שלאחר ההתקנה, ואז מנתקים את המחיצות.
  3. מבטלים את המיפוי של מחיצות היעד.

תהליך העדכון באמצעות חבילת עדכון ל-retrofit

אם חבילת העדכון של החזרה הוחלה על מכשיר שכבר מפעילה מחיצות דינמיות, לקוח ה-OTA מחיל את קובץ אחד (super.img) ישירות במכשירים עם חסימה. תהליך העדכון דומה לעדכון של ציוד משומש. פרטים נוספים זמינים במאמר התאמה לאחור של עדכון.

לדוגמה, נניח את הפרטים הבאים:

  • חריץ A הוא החריץ הפעיל.
  • system_a מכיל את המטא-נתונים הפעילים במיקום 0.
  • system_a, vendor_a וגם product_a משמשים כמכשירי חסימה.

כשלקוח OTA מקבל חבילת עדכון לשדרוג מכשירים קיימים, היא חלה על 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 מצטברים למכשירים מחדש, העדכונים אם ה-build הבסיסי מגדיר PRODUCT_USE_DYNAMIC_PARTITIONS והקבוצה PRODUCT_RETROFIT_DYNAMIC_PARTITIONS.

  • אם המשתנים לא מוגדרים בגרסה הבסיסית, מדובר בעדכון למערכות קיימות. חבילת העדכון מכילה את הקובץ המפוצל super.img ומשביתה את השלב שלאחר ההתקנה.
  • אם המשתנים מוגדרים ב-build הבסיסי, זהו עדכון רגיל עם מחיצות דינמיות. חבילת העדכון מכילה את התמונות של המחיצות הלוגיות (הדינמיות). לאחר ההתקנה, ניתן להפעיל אותו.

OTA מלא

נוצרות שתי חבילות OTA מלאות למכשירים לתיקון מכשירים.

  • $(PRODUCT)-ota-retrofit-$(TAG).zip תמיד מכיל פיצול של super.img והשבתת השלב לאחר ההתקנה לעדכון התקנה.
    • הוא נוצר עם ארגומנט נוסף --retrofit_dynamic_partitions לסקריפט ota_from_target_files.
    • אפשר להחיל אותו על כל הגרסאות הבנויות.
  • $(PRODUCT)-ota-$(TAG).zip מכיל תמונות לוגיות עבור בעדכונים עתידיים.
    • יש להחיל את ההגדרה הזו רק על גרסאות build שבהן מופעלות מחיצות דינמיות. בהמשך מוסבר איך אנחנו אוכפים את המדיניות הזו.

דחיית עדכון שלא השתנה לגבי גרסאות build ישנות

יש להחיל את חבילת ה-OTA הרגילה המלאה רק על גרסאות build עם מחיצות דינמיות מופעלות. אם שרת ה-OTA מוגדר בצורה שגויה ומעביר את החבילות האלה למכשירים עם Android מגרסה 9 ומטה, המכשירים לא יוכלו להפעיל את עצמם. לקוח OTA ב-Android 9 וב- נמוכה יותר לא יכולה להבחין בין חבילת OTA לתיקונים חבילת 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 כשלב לאחר ההתקנה ומסרב לעדכון.