הטמעת מחיצות דינמיות

חלוקה דינמית למחיצות (partitioning) מוטמעת באמצעות מיפוי המכשירים ל-dm-לינארי בליבה (kernel) של Linux. המחיצה super מכילה מטא-נתונים שבהם מפורטים השמות וטווחי החסימה של כל מחיצה דינמית בתוך super. בשלב הראשון init: מתבצע ניתוח ואימות של המטא-נתונים, ומכשירי בלוקים וירטואליים נוצרים שמייצגים כל מחיצה דינמית.

כשמחילים OTA, מחיצות דינמיות נוצרות באופן אוטומטי, שונתה או נמחקה לפי הצורך. במכשירי A/B יש שני עותקים של את המטא-נתונים, והשינויים יחולו רק על העותק שמייצג את משבצת היעד.

מכיוון שמחיצות דינמיות מוטמעות במרחב המשתמשים, יש צורך במחיצות תוכנת האתחול לא יכולה להיות דינמית. לדוגמה, boot, הפרמטרים dtbo ו-vbmeta נקראים על ידי תוכנת האתחול, וגם ולכן הן חייבות להישאר כמחיצות פיזיות.

כל מחיצה דינמית יכולה להשתייך לקבוצת עדכון. האלה מגבילות את המקום המקסימלי שמחיצות בקבוצה זו יכולות לצרוך. לדוגמה, system ו-vendor יכולים להשתייך אל קבוצה שמגבילה את הגודל הכולל של system ו- vendor.

הטמעת מחיצות דינמיות במכשירים חדשים

בקטע הזה מוסבר איך להטמיע מחיצות דינמיות במכשירים חדשים ההשקה עם Android 10 ואילך. לעדכון מכשירים קיימים, מידע נוסף זמין במאמר שדרוג של Android מכשירים.

שינויים במחיצות

במכשירים שמושקים עם Android 10, יש ליצור מחיצה בשם super. super מחיצה מטפלת בחרי A/B באופן פנימי, כך שמכשירי A/B לא הנפרדות בין מחיצות super_a ו-super_b. כל מחיצות AOSP לקריאה בלבד שלא משמשות את תוכנת האתחול להיות דינמית וצריך להסיר אותה מטבלת המחיצות של GUID (GPT). מחיצות ספציפיות לספק לא חייבות להיות דינמיות וניתן למקם אותן ב-GPT.

כדי להעריך את הגודל של super, צריך להוסיף את המידות של מחיצות שנמחקו מה-GPT. במכשירי A/B, ההגדרה הזו לכלול את הגודל של שני המקומות. איור 1 מוצג דוגמה לטבלת מחיצות לפני ואחרי ההמרה לדינמית מחיצות.

פריסת טבלת מחיצות
איור 1. פריסה חדשה של טבלת מחיצות פיזית המרה למחיצות דינמיות

המחיצות הדינמיות הנתמכות הן:

  • מערכת
  • ספק
  • מוצר
  • הרחבה למערכת
  • ODM

במכשירים שמושקים עם Android 10, אפשרות בשורת הפקודה בליבה (kernel) androidboot.super_partition חייב להיות ריק, כך שהפקודה syspro השדה ro.boot.super_partition ריק.

יישור מחיצות

יכול להיות שהמודול של מיפוי המכשירים יפעל פחות ביעילות אם המחיצה super לא מיושרת כראוי. המחיצה של super חייבת להיות מותאמת לערך המינימלי של קלט/פלט (I/O) גודל הבקשה כפי שנקבע בשכבת הבלוק. כברירת מחדל, לבנות מערכת (דרך lpmake, שיוצר את תמונת מחיצה super), מניחה שיישור של 1 MiB מספיק לכל חלוקה דינמית. עם זאת, הספקים חשוב לוודא שהמחיצה super מיושרת כמו שצריך.

אפשר לקבוע את גודל הבקשה המינימלי של מכשיר חסום לפי אנחנו בודקים את sysfs. לדוגמה:

# ls -l /dev/block/by-name/super
lrwxrwxrwx 1 root root 16 1970-04-05 01:41 /dev/block/by-name/super -> /dev/block/sda17
# cat /sys/block/sda/queue/minimum_io_size
786432

אפשר לוודא שההתאמה של המחיצה super באופן דומה:

# cat /sys/block/sda/sda17/alignment_offset

קיזוז היישור חייב להיות 0.

שינויים בהגדרות המכשיר

כדי להפעיל חלוקה דינמית למחיצות, מוסיפים את הדגל הבא ב- device.mk:

PRODUCT_USE_DYNAMIC_PARTITIONS := true

שינויים בהגדרות של הלוח

צריך להגדיר את גודל המחיצה super:

BOARD_SUPER_PARTITION_SIZE := <size-in-bytes>

במכשירי A/B, מערכת ה-build תקפיץ הודעת שגיאה אם הגודל הכולל מתמונות מחיצות דינמיות הן יותר ממחצית super גודל המחיצה.

ניתן להגדיר את רשימת המחיצות הדינמיות באופן הבא. עבור מכשירים שמשתמשים בקבוצות עדכון, צריך לפרט את הקבוצות משתנה BOARD_SUPER_PARTITION_GROUPS. כל שם קבוצה לאחר מכן יש BOARD_group_SIZE ו-BOARD_group_PARTITION_LIST. עבור מכשירי A/B, הגודל המקסימלי של קבוצה צריך לכסות רק אחד. משבצת, מפני ששמות הקבוצות מצורפים באופן פנימי.

הנה מכשיר לדוגמה שמכניס את כל המחיצות לקבוצה שנקרא example_dynamic_partitions:

BOARD_SUPER_PARTITION_GROUPS := example_dynamic_partitions
BOARD_EXAMPLE_DYNAMIC_PARTITIONS_SIZE := 6442450944
BOARD_EXAMPLE_DYNAMIC_PARTITIONS_PARTITION_LIST := system vendor product

הנה מכשיר לדוגמה שמציב שירותי מערכת ומוצרים בתוך group_foo וגם vendor, product ו-odm ב-group_bar:

BOARD_SUPER_PARTITION_GROUPS := group_foo group_bar
BOARD_GROUP_FOO_SIZE := 4831838208
BOARD_GROUP_FOO_PARTITION_LIST := system product_services
BOARD_GROUP_BAR_SIZE := 1610612736
BOARD_GROUP_BAR_PARTITION_LIST := vendor product odm
  • עבור מכשירי השקה וירטואליים של A/B, סכום הגדלים המקסימליים של כל הקבוצות צריך להיות לכל היותר:
    BOARD_SUPER_PARTITION_SIZE – תקורה
    למידע נוסף, ראו הטמעת A/B וירטואלי.
  • עבור מכשירי A/B שמופעלים, הסכום של הגדלים המקסימליים של כל הקבוצות צריך להיות:
    BOARD_SUPER_PARTITION_SIZE / 2 – תקורה
  • עבור מכשירים שהם לא מכשירי A/B ומכשירי A/B שעברו תיקון, הסכום המקסימלי הגודל של כל הקבוצות חייב להיות:
    BOARD_SUPER_PARTITION_SIZE – תקורה
  • בזמן ה-build, סכום התמונות של כל מחיצה בקבוצת עדכון לא יכולה לחרוג מהגודל המקסימלי של הקבוצה.
  • תקורה נדרשת בחישוב כדי להביא בחשבון מטא-נתונים, התאמות וכו'. תקורה סבירה היא 4MiB, אבל יכול לבחור תקורה גדולה יותר לפי הצורך של המכשיר.

גודל מחיצות דינמיות

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

לתמונות ext4 לקריאה בלבד, מערכת ה-build מקצה באופן אוטומטי את הגודל המינימלי אם לא צוין גודל מחיצה בתוך הקוד. מתאימה את התמונה כך שבמערכת הקבצים יש שטח בלתי מנוצל ככל האפשר. כך אפשר לוודא שהמכשיר לא מבזבז מקום שאפשר להשתמש בו עבור אפליקציות OTA.

בנוסף, אפשר לדחוס עוד יותר תמונות ext4 על ידי הפעלת בלוקים ביטול כפילויות ברמה. כדי להפעיל את האפשרות הזאת, צריך להשתמש בהגדרות הבאות:

BOARD_EXT4_SHARE_DUP_BLOCKS := true

אם הקצאה אוטומטית של גודל מינימלי של מחיצות היא לא רצויה, יש שתי דרכים לשלוט בגודל המחיצה. אפשר לציין שטח פנוי מינימלי עם BOARD_partitionIMAGE_PARTITION_RESERVED_SIZE, או שאפשר לציין BOARD_partitionIMAGE_PARTITION_SIZE לאילוץ מחיצות דינמיות לגודל ספציפי. אף אחת מהאפשרויות האלה אלא אם יש בכך צורך.

לדוגמה:

BOARD_PRODUCTIMAGE_PARTITION_RESERVED_SIZE := 52428800

הפעולה הזו מאלצת את מערכת הקבצים ב-product.img 50MiB של נפח אחסון שלא נוצל.

שינויי מערכת ברמה הבסיסית (root)

במכשירים שמושקים עם Android 10 אסור להשתמש במערכת בתור הרמה הבסיסית (root).

מכשירים עם מחיצות דינמיות (בין אם מדובר בהשקה עם מחיצות חוזרות או בהתקנה מחדש) מחיצות דינמיות) לא יכולים להשתמש במערכת כשורש. הליבה של Linux לא יכולה פירוש של המחיצה super ולכן לא ניתן לטעון system עצמו. הטעינה של system בוצעה עכשיו על ידי init שלב ראשון, שנמצא ברדיסק.

לא להגדיר את BOARD_BUILD_SYSTEM_ROOT_IMAGE. לחשבון ב-Android 10, הדגל BOARD_BUILD_SYSTEM_ROOT_IMAGE משמש רק לצורך להבחין אם המערכת נטענת על ידי הליבה או באמצעות שלב ראשון: init ב-ramdisk.

מתבצעת הגדרה של BOARD_BUILD_SYSTEM_ROOT_IMAGE לערך true גורמת לשגיאת build PRODUCT_USE_DYNAMIC_PARTITIONS הוא גם true.

כשהערך של BOARD_USES_RECOVERY_AS_BOOT מוגדר כ-True, הפונקציה קובץ האימג' לשחזור בנוי כ-אתחול.img, ומכיל את Ramdisk. בעבר, תוכנת האתחול השתמשה בליבה (kernel) של skip_initramfs פרמטר של שורת הפקודה כדי להחליט באיזה מצב לבצע הפעלה. עבור מכשירי Android 10, אסור לתוכנת האתחול לעבור skip_initramfs לשורת הפקודה בליבה (kernel). במקום זאת, תוכנת אתחול צריך לעבור את androidboot.force_normal_boot=1 כדי לדלג על שלב השחזור ומפעילים את מכשיר Android הרגיל. מכשירים שמושקים עם Android 12 ואילך, חייבים להשתמש ב-אתחול תצורה כדי להעביר את androidboot.force_normal_boot=1.

שינויים בהגדרות של AVB

בזמן השימוש ב-Android הפעלה מאומתת 2.0 אם המכשיר לא משתמש במחיצה משורשרת שמתארים את התיאורים, לא צריך לשנות שום דבר. אם משתמשים בשרשרת עם זאת, ואחת מהמחיצות המאומתות היא דינמית, אז נחוצים שינויים.

דוגמה להגדרה של מכשיר שמשורשר vbmeta עבור system וגם vendor מחיצות.

BOARD_AVB_SYSTEM_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
BOARD_AVB_SYSTEM_ALGORITHM := SHA256_RSA2048
BOARD_AVB_SYSTEM_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
BOARD_AVB_SYSTEM_ROLLBACK_INDEX_LOCATION := 1

BOARD_AVB_VENDOR_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
BOARD_AVB_VENDOR_ALGORITHM := SHA256_RSA2048
BOARD_AVB_VENDOR_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
BOARD_AVB_VENDOR_ROLLBACK_INDEX_LOCATION := 1

בתצורה זו, תוכנת האתחול מצפה למצוא קובץ vbmeta footer בסוף system וגם vendor מחיצות. מפני שהמחיצות האלה כבר לא גלויות לתוכנת האתחול (הוא נמצא ב-super), נדרשים שינויים.

  • הוספה של vbmeta_system וגם vbmeta_vendor מחיצות לטבלת המחיצות של המכשיר. למכשירי A/B, יש להוסיף vbmeta_system_a, vbmeta_system_b vbmeta_vendor_a ו-vbmeta_vendor_b. אם המיקום לאחר הוספת אחת או יותר מהמחיצות, הן צריכות להיות באותו גודל כמחיצה vbmeta.
  • משנים את השמות של דגלי ההגדרה על ידי הוספת VBMETA_ ו- לציין על אילו מחיצות מתבצעת השרשרת:
    BOARD_AVB_VBMETA_SYSTEM := system
    BOARD_AVB_VBMETA_SYSTEM_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
    BOARD_AVB_VBMETA_SYSTEM_ALGORITHM := SHA256_RSA2048
    BOARD_AVB_VBMETA_SYSTEM_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
    BOARD_AVB_VBMETA_SYSTEM_ROLLBACK_INDEX_LOCATION := 1
    
    BOARD_AVB_VBMETA_VENDOR := vendor
    BOARD_AVB_VBMETA_VENDOR_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
    BOARD_AVB_VBMETA_VENDOR_ALGORITHM := SHA256_RSA2048
    BOARD_AVB_VBMETA_VENDOR_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
    BOARD_AVB_VBMETA_VENDOR_ROLLBACK_INDEX_LOCATION := 1
    

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

שינויים בתוכנת האתחול מסוג AVB

אם תוכנת האתחול הטמיעה את libavb, כוללים את התיקונים הבאים:

אם משתמשים במחיצות בשרשרת, צריך להוסיף תיקון נוסף:

  • 49936b4c0109411fdd38bd4ba3a32a01c40439a9 — libavb: Support vbmeta blobs בתחילת חלוקה."

שינויים בשורת הפקודה בליבה (Kernel)

יש להוסיף פרמטר חדש, androidboot.boot_devices לשורת הפקודה של הליבה. משמש את init כדי: הפעלת קישורים סימבוליים של /dev/block/by-name. הוא צריך להיות רכיב הנתיב של המכשיר לקישור הסמלי לפי שם שנוצר על ידי ueventd, כלומר /dev/block/platform/device-path/by-name/partition-name. מכשירים שמותקנת בהם מערכת ההפעלה Android בגרסה 12 ואילך חייבים להשתמש ב- הגדרת האתחול כדי להעביר את androidboot.boot_devices אל init.

לדוגמה, אם הקישור הסמלי של מחיצת-על לפי שם הוא /dev/block/platform/soc/100000.ufshc/by-name/super, אפשר להוסיף את פרמטר שורת הפקודה לקובץ BoardConfig.mk בתור ככה:

BOARD_KERNEL_CMDLINE += androidboot.boot_devices=soc/100000.ufshc
אפשר להוסיף את הפרמטר verificationconfig לקובץ BoardConfig.mk באופן הבא:
BOARD_BOOTCONFIG += androidboot.boot_devices=soc/100000.ufshc

שינויים ב-fstab

שכבות-העל של עץ המכשיר ועץ המכשיר לא יכולות להכיל fstab רשומות. משתמשים בקובץ fstab שיהיה חלק מ-ramdisk.

צריך לבצע שינויים בקובץ fstab למחיצות לוגיות:

  • שדה הדגלים fs_mgr חייב לכלול את הדגל logical והדגל first_stage_mount, שמופיע ב- Android 10, שמציין שהמחיצה צריך לטעון אותם בשלב הראשון.
  • ייתכן שהמחיצה avb=vbmeta partition name בתור הדגל fs_mgr ואז הנתון vbmeta שצוין המחיצה הופעלה על ידי שלב ראשון init לפני מנסה לטעון מכשירים.
  • השדה dev חייב להיות שם המחיצה.

רשומות fstab הבאות מגדירות את המערכת, הספק והמוצר כלוגיות מחיצות תואמות לכללים שלמעלה.

#<dev>  <mnt_point> <type>  <mnt_flags options> <fs_mgr_flags>
system   /system     ext4    ro,barrier=1        wait,slotselect,avb=vbmeta,logical,first_stage_mount
vendor   /vendor     ext4    ro,barrier=1        wait,slotselect,avb,logical,first_stage_mount
product  /product    ext4    ro,barrier=1        wait,slotselect,avb,logical,first_stage_mount

מעתיקים את קובץ fstab ל-ramdisk בשלב הראשון.

שינויים ב-SELinux

יש לסמן את התקן החסימה של מחיצות-על עם התווית super_block_device לדוגמה, אם הקישור הסמלי של מחיצת-על לפי שם הוא /dev/block/platform/soc/100000.ufshc/by-name/super, צריך להוסיף את השורה הבאה אל file_contexts:

/dev/block/platform/soc/10000\.ufshc/by-name/super   u:object_r:super_block_device:s0

אתחול מהיר

תוכנת האתחול (או כל כלי מהבהב שלא כולל מרחב משתמשים) לא מבין מחיצות דינמיות, כך שהוא לא יכול להבהב אותן. כדי לפתור את הבעיה, מכשירים חייב להשתמש ביישום של פרוטוקול אתחול מהיר (fastboot) במרחב המשתמש, שנקרא אתחול מהיר (fastbootd).

מידע נוסף על אופן הטמעת התכונהfastbootd זמין במאמר העברת Fastboot to User Space.

טעינה מחדש של adb

למפתחים שמשתמשים בגרסאות build של AI או ניפוי באגים שקשורים למשתמשים: adb remount שימושי מאוד לאיטרציה מהירה. מחיצות דינמיות יוצרות בעיה עבור adb remount כי כבר אין בחינם את השטח בתוך כל מערכת קבצים. כדי לפתור את הבעיה, המכשירים יכולים להפעיל שכבת-על. כל עוד יש מקום פנוי בתוך מחיצת-העל, adb remount יוצר באופן אוטומטי דינמיקה זמנית ומשימוש בשכבות-על לכתיבה. המחיצה הזמנית היא בשם scratch, לכן אל תשתמשו בשם הזה מחיצות.

למידע נוסף על הפעלה של שכבות-על, ראו שכבות-על README ב-AOSP.

שדרוג מכשירי Android

אם משדרגים מכשיר ל-Android 10, אם אתם רוצים לכלול תמיכה במחיצות דינמיות ב-OTA, אתם לא צריכים לשנות את טבלת המחיצות המובנית. עוד חלק מההגדרות האישיות נדרש.

שינויים בהגדרות המכשיר

כדי לתקן את החלוקה הדינמית למחיצות, צריך להוסיף את הדגלים הבאים ב- device.mk:

PRODUCT_USE_DYNAMIC_PARTITIONS := true
PRODUCT_RETROFIT_DYNAMIC_PARTITIONS := true

שינויים בהגדרות של הלוח

צריך להגדיר את משתני הלוח הבאים:

  • הגדרת BOARD_SUPER_PARTITION_BLOCK_DEVICES לרשימת המכשירים החסימה שנמצאים בשימוש לאחסון היקפים של מחיצות דינמיות. זוהי רשימת השמות של מקורות פיזיים קיימים. המחיצות במכשיר.
  • הגדרת המידות של BOARD_SUPER_PARTITION_partition_DEVICE_SIZE של כל התקן בלוקים ב-BOARD_SUPER_PARTITION_BLOCK_DEVICES, בהתאמה. זו רשימת הגדלים של המחיצות הפיזיות הקיימות במכשיר. בדרך כלל BOARD_partitionIMAGE_PARTITION_SIZE בלוח קיים הגדרות אישיות.
  • ביטול ההגדרה של BOARD_partitionIMAGE_PARTITION_SIZE קיים לכולם מחיצות ב-BOARD_SUPER_PARTITION_BLOCK_DEVICES.
  • הגדרת BOARD_SUPER_PARTITION_SIZE לסכום של BOARD_SUPER_PARTITION_partition_DEVICE_SIZE.
  • מגדירים את BOARD_SUPER_PARTITION_METADATA_DEVICE למכשיר הבלוק שבו מטא-נתונים של מחיצות דינמיות מאוחסנים. חייב להיות אחד מ- BOARD_SUPER_PARTITION_BLOCK_DEVICES בדרך כלל, ברירת המחדל היא system
  • הגדרה של BOARD_SUPER_PARTITION_GROUPS, BOARD_group_SIZE, וגם BOARD_group_PARTITION_LIST, בהתאמה. צפייה שינויים בהגדרות של הלוח במכשירים חדשים אפשר לקבל פרטים נוספים.

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

BOARD_SUPER_PARTITION_BLOCK_DEVICES := system vendor
BOARD_SUPER_PARTITION_METADATA_DEVICE := system

# Rename BOARD_SYSTEMIMAGE_PARTITION_SIZE to BOARD_SUPER_PARTITION_SYSTEM_DEVICE_SIZE.
BOARD_SUPER_PARTITION_SYSTEM_DEVICE_SIZE := <size-in-bytes>

# Rename BOARD_VENDORIMAGE_PARTITION_SIZE to BOARD_SUPER_PARTITION_VENDOR_DEVICE_SIZE
BOARD_SUPER_PARTITION_VENDOR_DEVICE_SIZE := <size-in-bytes>

# This is BOARD_SUPER_PARTITION_SYSTEM_DEVICE_SIZE + BOARD_SUPER_PARTITION_VENDOR_DEVICE_SIZE
BOARD_SUPER_PARTITION_SIZE := <size-in-bytes>

# Configuration for dynamic partitions. For example:
BOARD_SUPER_PARTITION_GROUPS := group_foo
BOARD_GROUP_FOO_SIZE := <size-in-bytes>
BOARD_GROUP_FOO_PARTITION_LIST := system vendor product

שינויים ב-SELinux

יש לסמן את המכשירים לחסימת מחיצות-על באמצעות המאפיין super_block_device_type לדוגמה, אם המכשיר כבר כולל system ו-vendor מחיצות, ברצונך להשתמש בהן כחסימה לאחסון היקפים של מחיצות דינמיות, והקישורים הסימבוליים שלהם לפי השמות מסומנים כ- system_block_device:

/dev/block/platform/soc/10000\.ufshc/by-name/system   u:object_r:system_block_device:s0
/dev/block/platform/soc/10000\.ufshc/by-name/vendor   u:object_r:system_block_device:s0

אחר כך מוסיפים את השורה הבאה אל device.te:

typeattribute system_block_device super_block_device_type;

להגדרות אחרות, ראו הטמעה מחיצות דינמיות במכשירים חדשים.

מידע נוסף על עדכוני שיפורים זמין בכתובת OTA למכשירי A/B ללא דינמי מחיצות.

קובצי אימג' של היצרן

במכשיר שמופעל עם תמיכה במחיצות דינמיות, אל תשתמשו אתחול מהיר (fastboot) של סביבת המשתמש כדי לעדכן תמונות יצרן, כי אתחול למרחב המשתמשים איטיות יותר משיטות הבהוב אחרות.

כדי לטפל בבעיה הזו, make dist בונה עכשיו תמונה אחת (super.img) שניתן להבהב ישירות מחיצה. הוא מקבץ אוטומטית את התוכן של מחיצות, כלומר הוא מכיל system.img, vendor.img וכן הלאה, בנוסף ל-super מטא-נתונים של מחיצות. את התמונה הזו אפשר לשדרג ישירות מחיצת super ללא כלים נוספים או ללא שימוש אתחול מהיר (fastbootd). אחרי ה-build, super.img ימוקם ב ${ANDROID_PRODUCT_OUT}.

עבור מכשירי A/B שמופעלים עם מחיצות דינמיות, super.img מכיל תמונות במשבצת A. לאחר ההבהוב של תמונת-על באופן ישיר, צריך לסמן את חריץ A כזמין לאתחול לפני הפעלה מחדש של במכשיר.

למכשירי תיקון, make dist יוצר קבוצה של super_*.img תמונות שניתן לשדרג ישירות אליהן המחיצות הפיזיות המתאימות. לדוגמה, make dist. יוצר את super_system.img ואת super_vendor.img כאשר BOARD_SUPER_PARTITION_BLOCK_DEVICES הוא המערכת ספק. התמונות האלה ממוקמות בתיקיית OTA ב- target_files.zip

כוונון של מכשיר מיפוי המכשיר

החלוקה הדינמית למחיצות (partitioning) מספקת מענה למספר כלים לא דטרמיניסטיים של מיפוי מכשירים אובייקטים. ייתכן שלא כולן ייווצרו כמצופה, ולכן עליכם לעקוב אחר כל טוענים ומעדכנים את מאפייני Android של כל המחיצות המשויכות עם והתקני האחסון הבסיסיים שלהם.

מנגנון בתוך init עוקב אחר הטעינה באופן אסינכרוני מעדכן את מאפייני Android. לא ניתן להבטיח כמה זמן נמשך האימות להיות בתקופה ספציפית, ולכן עליכם לספק מספיק זמן. לכל on property הטריגרים להגיב. המאפיינים הם dev.mnt.blk.<partition> איפה <partition> היא root, system, data, או למשל, vendor. כל נכס משויך אל שם התקן האחסון הבסיסי, כפי שמוצג בדוגמאות הבאות:

taimen:/ % getprop | grep dev.mnt.blk
[dev.mnt.blk.data]: [sda]
[dev.mnt.blk.firmware]: [sde]
[dev.mnt.blk.metadata]: [sde]
[dev.mnt.blk.persist]: [sda]
[dev.mnt.blk.root]: [dm-0]
[dev.mnt.blk.vendor]: [dm-1]

blueline:/ $ getprop | grep dev.mnt.blk
[dev.mnt.blk.data]: [dm-4]
[dev.mnt.blk.metadata]: [sda]
[dev.mnt.blk.mnt.scratch]: [sda]
[dev.mnt.blk.mnt.vendor.persist]: [sdf]
[dev.mnt.blk.product]: [dm-2]
[dev.mnt.blk.root]: [dm-0]
[dev.mnt.blk.system_ext]: [dm-3]
[dev.mnt.blk.vendor]: [dm-1]
[dev.mnt.blk.vendor.firmware_mnt]: [sda]

השפה init.rc מאפשרת לנכסי Android כחלק מהכללים, והפלטפורמה יכולה לכוונן את התקני האחסון לפי הצורך באמצעות פקודות כמו אלה:

write /sys/block/${dev.mnt.blk.root}/queue/read_ahead_kb 128
write /sys/block/${dev.mnt.blk.data}/queue/read_ahead_kb 128

אחרי שעיבוד הפקודות יתחיל בשלב init, הפונקציה הערך epoll loop הופך לפעיל והערכים מתחילים להתעדכן. אבל, לפעמים מאחר שהטריגרים של נכסים לא פעילים עד סוף init, הם לא ניתנות לשימוש בשלבי האתחול הראשוניים כדי לטפל ב-root, system או vendor. אפשר לצפות ל ברירת המחדל של הליבה read_ahead_kb כך שהיא תספיק עד סקריפטים של init.rc יכולים לבטל בearly-fs (כאשר מגוון דימוןים ומתקנים שונים מתחילים). לכן, Google ממליצה משתמשים בתכונה on property, בשילוב עם נכס שנמצא בשליטת init.rc, כמו sys.read_ahead_kb, כדי לטפל בתזמון הפעולות וכדי למנוע מרוץ תהליכים, כמו דוגמאות:

on property:dev.mnt.blk.root=* && property:sys.read_ahead_kb=*
    write /sys/block/${dev.mnt.blk.root}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048}

on property:dev.mnt.blk.system=* && property:sys.read_ahead_kb=*
    write /sys/block/${dev.mnt.blk.system}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048}

on property:dev.mnt.blk.vendor=* && property:sys.read_ahead_kb=*
    write /sys/block/${dev.mnt.blk.vendor}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048}

on property:dev.mnt.blk.product=* && property:sys.read_ahead_kb=*
    write /sys/block/${dev.mnt.blk.system_ext}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048}

on property:dev.mnt.blk.oem=* && property:sys.read_ahead_kb=*
    write /sys/block/${dev.mnt.blk.oem}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048}

on property:dev.mnt.blk.data=* && property:sys.read_ahead_kb=*
    write /sys/block/${dev.mnt.blk.data}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048}

on early-fs:
    setprop sys.read_ahead_kb ${ro.read_ahead_kb.boot:-2048}

on property:sys.boot_completed=1
   setprop sys.read_ahead_kb ${ro.read_ahead_kb.bootcomplete:-128}