Android 10 תומך במחיצות דינמיות, מערכת מחיצות במרחב המשתמש שאפשר ליצור בה מחיצות, לשנות את הגודל שלהן ולהשמיד אותן במהלך עדכונים אופליין (OTA).
בדף הזה מוסבר איך לקוחות OTA משנים את הגודל של מחיצות דינמיות במהלך עדכון במכשירים שאינם A/B.
במכשירים שאינם A/B, עדכון ה-OTA למחיצות דינמיות מוחל באמצעות updater
בתוך חבילת העדכון.
עדכון של מכשירי ההשקה
הקטע הזה רלוונטי למכשירים ללא A/B שמופעלים עם תמיכה במחיצות דינמיות. המכשירים האלה משודרגים מ-Android 10 לגרסאות מתקדמות יותר.
יצירת חבילות עדכון
חבילות עדכון OTA נוצרות על ידי הסקריפט ota_from_target_files
, שנמצא בקטע build/make/tools/releasetools
. כברירת מחדל, הסקריפט יוצר חבילה שמעדכנת את המחיצות system
ו-vendor
. אם יש עוד מחיצות דינמיות, כמו product
, product_services
או odm
, צריך ליצור את העדכונים שלהן בקוד ספציפי למכשיר.
כדי ליצור עדכונים, מטמיעים את FullOTA_GetBlockDifferences()
ואת IncrementalOTA_GetBlockDifferences()
במודול Python המורחב. שתי הפונקציות האלה מחזירות רשימה של אובייקטים מסוג BlockDifference
, שבכל אחד מהם מתוארת תיקון העדכון שייושם על מחיצה. אסור לשנות באופן ידני את המחיצות שמוחזרות על ידי שתי הפונקציות האלה או לאמת אותן במקום אחר, למשל ב-*_InstallBegin()
או ב-*_InstallEnd()
.
דוגמה ליצירת עדכון:
# device/yoyodyne/tardis/releasetools.py import os from common import BlockDifference, EmptyImage, GetUserImage # The joined list of user image partitions of source and target builds. # - Items should be added to the list if new dynamic partitions are added. # - Items should not be removed from the list even if dynamic partitions are # deleted. When generating an incremental OTA package, this script needs to # know that an image is present in source build but not in target build. USERIMAGE_PARTITIONS = [ "product", "odm", ] def GetUserImages(input_tmp, input_zip): return {partition: GetUserImage(partition, input_tmp, input_zip) for partition in USERIMAGE_PARTITIONS if os.path.exists(os.path.join(input_tmp, "IMAGES", partition + ".img"))} def FullOTA_GetBlockDifferences(info): images = GetUserImages(info.input_tmp, info.input_zip) return [BlockDifference(partition, image) for partition, image in images.items()] def IncrementalOTA_GetBlockDifferences(info): source_images = GetUserImages(info.source_tmp, info.source_zip) target_images = GetUserImages(info.target_tmp, info.target_zip) # Use EmptyImage() as a placeholder for partitions that will be deleted. for partition in source_images: target_images.setdefault(partition, EmptyImage()) # Use source_images.get() because new partitions are not in source_images. return [BlockDifference(partition, target_image, source_images.get(partition)) for partition, target_image in target_images.items()]
תהליך עדכון
מאחורי הקלעים, הפונקציות הבאות מתווספות לסקריפט של edify:
unmap_partition(name)
- מבטלים את המיפוי של המחיצה אם היא ממופה, אחרת לא עושים כלום.
- מחזירה את המחרוזת
t
אם הפעולה בוצעה בהצלחה, או מחרוזת ריקה אם הפעולה נכשלה.
map_partition(name)
- ממפים את המחיצה, אם היא עדיין לא ממופה.
- הפונקציה מחזירה את הנתיב המוחלט של מכשיר החסימה הממופה בהצלחה, או מחרוזת ריקה במקרה של כשל.
update_dynamic_partitions(op_list)
- יש להחיל את רשימת הפעולות הנתונה על מטא-נתונים של מחיצות דינמיות, ולבטל את המיפוי של מחיצות במקרה הצורך.
-
מחזירים את הערך
t
אם הפעולה בוצעה בהצלחה, או מחרוזת ריקה אם הפעולה נכשלה.
הארגומנט op_list
ל-update_dynamic_partitions
מפנה לקובץ בחבילת העדכון. כל שורה בקובץ מציינת פעולה. אם אחת מהפעולות תיכשל, update_dynamic_partitions
תחזיר מחרוזת ריקה באופן מיידי. הפעולות הן:
resize partition-name size
- מבטלים את המיפוי של המחיצה ומגדילים את הגודל שלה ל-size.
remove partition_name
- מבטלים את המיפוי של המחיצה ומסירים אותה.
add partition-name group-name
- הוספת מחיצה חדשה לקבוצה שצוינה.
- ביטול הפעולה אם הקבוצה לא קיימת או אם המחיצה כבר קיימת.
move partition-name group-name
- מעבירים את המחיצה לקבוצה שצוינה.
- אם הקבוצה או המחיצה לא קיימים, צריך לבטל את הפעולה.
-
add_group group-name maximum-size
- מוסיפים קבוצה עם השם הרצוי והגודל המקסימלי.
- אם הקבוצה כבר קיימת, צריך לבטל את הפעולה.
- אם הערך של maximum_size הוא 0, המשמעות היא שאין מגבלות גודל על המחיצות בקבוצה. נדרשת בדיקה נוספת כדי לוודא שהמחיצות בקבוצה לא חורגות מהמקום הזמין במכשיר.
-
resize_group group-name maximum-size
- שינוי הגודל של הקבוצה לגודל המקסימלי שצוין.
- אם הקבוצה לא קיימת, צריך לבטל את הפעולה.
- אם הערך של maximum_size הוא 0, המשמעות היא שאין מגבלות גודל על המחיצות בקבוצה. נדרשת בדיקה נוספת כדי לוודא שהמחיצות בקבוצה לא חורגות מהמקום הזמין במכשיר.
remove_group group-name
- להסיר את הקבוצה.
- ביטול אם יש מחיצות בקבוצה.
remove_all_groups
- מבטלים את המיפוי של כל המחיצות ממיפוי המכשיר.
- מסירים את כל המחיצות והקבוצות.
OTA מצטבר
עדכוני OTA מצטברים פועלים לפי הלוגיקה הבאה:
- כיווץ מחיצות/מחיקת מחיצות/העברת מחיצות מחוץ לקבוצה (כדי שיהיה מספיק מקום לכיווץ הקבוצות)
- לצמצם קבוצות (כדי שיהיה מספיק מקום להגדלת הקבוצות)
- הרחבת הקבוצות (כדי שיהיה לנו מספיק מקום להרחיב או להוסיף מחיצות)
- הגדלת המחיצות, הוספת מחיצות או העברת מחיצות לקבוצה חדשה
בפירוט, הערך update-script
נוצר לפי הלוגיקה הבאה:
for each shrinking partition: block_image_update(map_partition(name), …) update_dynamic_partitions(op_list) for each growing / adding partition: block_image_update(map_partition(name), …)
קובץ op_list
של update_dynamic_partitions
נוצר לפי הלוגיקה הבאה:
for each deleting partition: remove for each partition that changes groups: move to "default" for each shrinking partition: resize for each shrinking / removing group: resize_group / remove_group for each growing / adding group: resize_group / add_group for each adding partition: add for each growing / adding partition: resize for each partition that changes groups: move to target group
OTA מלא
עדכוני OTA מלאים מבוססים על הלוגיקה הבאה:
- מחיקת כל הקבוצות והמחיצות הקיימות
- צירוף קבוצות
- הוספת מחיצות
באופן מפורט, update-script
נוצר עם הלוגיקה
הבאה:
update_dynamic_partitions(op_list) for each adding partition: block_image_update(map_partition(name), …)
הקובץ op_list
של update_dynamic_partitions
נוצר עם הלוגיקה הבאה:
remove_all_groups for each adding group: add_group for each adding partition: add for each adding partition: resize