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, בהתאמה. בשעה זמן ריצה, לא משנה איזו משבצת מתעדכנת.

בדף הזה, המשבצות למטא-נתונים נקראות 'מטא-נתונים S' (מקור) ו-מטא-נתונים T (יעד). באופן דומה, נקראות מחיצות ל-system_s, vendor_t וכן הלאה.

למידע נוסף על בניית הגדרות מערכת, ראו שדרוג מכשירים.

למידע נוסף על האופן שבו מחיצות שייכות לעדכון groups, ראו לוח שינויים בהגדרות האישיות של מכשירים חדשים.

דוגמה למטא-נתונים במכשיר:

  • מכשיר לחסימה פיזית 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
      • סרגל קבוצה_ב
        • מחיצה לוגית (דינמית) vendor_b
        • מחיצה לוגית (דינמית) product_b
        • מחיצות אחרות שעודכנו על ידי הסרגל

אפשר להשתמש בכלי 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 ל-Metadata T.
    4. מיפוי המחיצות שנוספו במיפוי המכשיר כניתנות לכתיבה.
  2. להחיל את העדכון על המכשירים החסומים.
    1. במקרה הצורך, ממפים את מחיצות המקור במיפוי המכשיר לקריאה בלבד. זה הכרחי בשביל לבצע התקנה ממקור לא ידוע כי מחיצות המקור לא ממופות לפני העדכון.
    2. יש להחיל עדכון מלא או עדכון דלתא על כל המכשירים החסומים משבצת היעד.
    3. טוענים את המחיצות כדי להריץ את הסקריפט אחרי ההתקנה, ולאחר מכן לנתק את המחיצות.
  3. מבטלים את המיפוי של מחיצות היעד.

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

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

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

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