עדכוני מערכת דינמיים

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

דרישות ליבה (kernel)

צפייה הטמעה של מחיצות דינמיות לדרישות הליבה.

בנוסף, ה-DSU מסתמך על תכונת הליבה (kernel) של מיפוי המכשיר (dm-verity) כדי לאמת את תמונת המערכת של Android. צריך להפעיל את הליבה הבאה הגדרות:

  • CONFIG_DM_VERITY=y
  • CONFIG_DM_VERITY_FEC=y

דרישות לגבי מחיצות

החל מגרסה 11 של Android, ל-DSU נדרש /data מחיצה לשימוש במערכת הקבצים F2FS או ext4. F2FS מספקת ביצועים טובים יותר מומלץ, אבל ההבדל אמור להיות מזערי.

כמה דוגמאות של משך הזמן לעדכון מערכת דינמי ב-Pixel המכשיר:

  • באמצעות F2FS:
    • 109s, משתמש 8G, מערכת 867M, סוג מערכת קבצים: F2FS: הצפנה=aes-256-xts:aes-256-cts
    • 104s, משתמש 8G, מערכת 867M, סוג מערכת הקבצים: F2FS: encryption=ice
  • שימוש ב-ext4:
    • 135s, משתמש 8G, מערכת 867M, סוג מערכת קבצים: ext4: הצפנה=aes-256-xts:aes-256-cts

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

המחיצה metadata (16MB ומעלה) נדרשת לאחסון נתונים הקשורים לתמונות המותקנות. צריך לטעון אותו במהלך הטעינה בשלב הראשון.

המחיצה userdata חייבת להשתמש במערכת הקבצים F2FS או ext4. כשמשתמשים ב-F2FS, לכלול את כל התיקונים שקשורים ל-F2FS שזמינים ב ליבה (kernel) נפוצה של Android.

ה-DSU פותח ונבדק באמצעות ליבה/Common 4.9. מומלץ להשתמש ב- ליבה (kernel) 4.9 ואילך לתכונה הזו.

התנהגות HAL של הספק

חלל/ת

HAL של האריגה מספק מספר קבוע של משבצות לאחסון מפתחות משתמש. ה-DSU צורכת שני חריצים נוספים למפתחות. אם ליצרן ציוד מקורי יש HAL של אריגה, הוא צריך מספיק מקום ליצירת קובץ אימג' גנרי של מערכת (GSI) ותמונת מארח.

שומר שער HAL

צוות Gatekeeper HAL צריך תומכים בערכי USER_ID גדולים, מכיוון שה-GSI קיזוז UID ל-HAL על ידי +1000000.

אימות ההפעלה

אם רוצים לתמוך באתחול של תמונות GSI למפתחים במצב 'נעול' ללא השבתה הפעלה מאומתת, כולל מפתחות GSI למפתחים על ידי הוספת השורה הבאה לקובץ device/<device_name>/device.mk:

$(call inherit-product, $(SRC_TARGET_DIR)/product/developer_gsi_keys.mk)

הגנה מפני החזרה למצב קודם

כשמשתמשים ב-DSU, תמונת מערכת Android שהורדתם חייבת להיות חדשה יותר את קובץ האימג' הנוכחי של המערכת במכשיר. כדי לעשות זאת, משווים בין תיקון האבטחה ברמות הפעלה מאומתת של Android (AVB) מתאר מאפיין AVB בשתי תמונות המערכת: Prop: com.android.build.system.security_patch -> '2019-04-05'.

במכשירים שלא משתמשים ב-AVB, יש לשים את רמת תיקון האבטחה של המערכת הנוכחית את התמונה לתוך ה-cmdline או האתחול באמצעות תוכנת האתחול: androidboot.system.security_patch=2019-04-05

דרישות החומרה

כשמפעילים מכונת DSU, מוקצים שני קבצים זמניים:

  • מחיצה לוגית לאחסון של GSI.img (1~1.5 G)
  • מחיצת /data ריקה בנפח 8GB היא ארגז החול להפעלת GSI

מומלץ לשריין לפחות 10GB של נפח אחסון פנוי לפני שמפעילים DSU מכונה. DSU תומך גם בהקצאה מכרטיס SD. כאשר כרטיס SD כיום, היא נמצאת בעדיפות הגבוהה ביותר להקצאה. התמיכה בכרטיס SD היא קריטי למכשירים בעלי מתח נמוך יותר, שייתכן שאין להם מספיק נפח אחסון פנימי. אם יש כרטיס SD, צריך לוודא שהוא לא הופעל. DSU לא תומך כרטיסי SD שאימצו.

חזיתות זמינות

אפשר להפעיל DSU באמצעות adb, אפליקציה של OEM, או באמצעות טוען ה-DSU בלחיצה אחת (ב- Android מגרסה 11 ואילך).

הפעלת DSU באמצעות adb

כדי להפעיל DSU באמצעות adb, מזינים את הפקודות הבאות:

$ simg2img out/target/product/.../system.img system.raw
$ gzip -c system.raw > system.raw.gz
$ adb push system.raw.gz /storage/emulated/0/Download
$ adb shell am start-activity \
-n com.android.dynsystem/com.android.dynsystem.VerificationActivity  \
-a android.os.image.action.START_INSTALL    \
-d file:///storage/emulated/0/Download/system.raw.gz  \
--el KEY_SYSTEM_SIZE $(du -b system.raw|cut -f1)  \
--el KEY_USERDATA_SIZE 8589934592

הפעלת DSU באמצעות אפליקציה

נקודת הכניסה הראשית ל-DSU היא android.os.image.DynamicSystemClient.java API:

public class DynamicSystemClient {


...
...

     /**
     * Start installing DynamicSystem from URL with default userdata size.
     *
     * @param systemUrl A network URL or a file URL to system image.
     * @param systemSize size of system image.
     */
    public void start(String systemUrl, long systemSize) {
        start(systemUrl, systemSize, DEFAULT_USERDATA_SIZE);
    }

עליך להתקין את האפליקציה הזו מראש בחבילה או במכשיר. כי DynamicSystemClient הוא ממשק API של המערכת, לא ניתן לפתח את האפליקציה באמצעות SDK API ולא ניתן לפרסם אותו ב-Google Play. מטרת האפליקציה הזו:

  1. מאחזרים רשימת תמונות ואת כתובת ה-URL התואמת באמצעות סכימה שהוגדרה על ידי הספק.
  2. התאמת התמונות שברשימה לעומת המכשיר עצמו, והצגת תמונות תואמות שהמשתמש יכול לבחור.
  3. הפעלת DynamicSystemClient.start באופן הבא:

    DynamicSystemClient aot = new DynamicSystemClient(...)
       aot.start(
            ...URL of the selected image...,
            ...uncompressed size of the selected image...);
    
    

כתובת ה-URL מפנה לקובץ תמונת מערכת שאינו גמיש (gzip), ואז אפשר ליצור אותו באמצעות הפקודות הבאות:

$ simg2img ${OUT}/system.img ${OUT}/system.raw
$ gzip ${OUT}/system.raw
$ ls ${OUT}/system.raw.gz

שם הקובץ צריך להיות בפורמט הבא:

<android version>.<lunch name>.<user defined title>.raw.gz

לדוגמה:

  • o.aosp_taimen-userdebug.2018dev.raw.gz
  • p.aosp_taimen-userdebug.2018dev.raw.gz

טוען DSU בלחיצה אחת

ב-Android 11 אנחנו משיקים את טוען ה-DSU בלחיצה אחת, הוא חזית בהגדרות המפתח.

הפעלת טוען ה-DSU

איור 1. הפעלת טוען ה-DSU

כשהמפתח לוחץ על הלחצן DSU Loader, הוא מאחזר מתאר DSU JSON מהאינטרנט ומציג את כל התמונות הרלוונטיות תפריט צף. יש לבחור תמונה כדי להתחיל את התקנת ה-DSU ואת ההתקדמות מופיעה בסרגל ההתראות.

התקדמות ההתקנה של תמונת ה-DSU

איור 2. התקדמות ההתקנה של תמונת ה-DSU

כברירת מחדל, טוען ה-DSU טוען מתאר JSON שמכיל את תמונות ה-GSI. בקטעים הבאים מוסבר איך ליצור חבילות DSU חתומות על ידי OEM (יצרן ציוד מקורי) ולטעון אותן. מטעינת ה-DSU.

סימון תכונה

תכונת ה-DSU נמצאת מתחת לסימון התכונה settings_dynamic_android. לפני באמצעות DSU, ודאו שהתכונה הניסיונית התואמת מופעלת.

הפעלת התכונה הניסיונית.

איור 3. הפעלת התכונה הניסיונית

יכול להיות שממשק המשתמש של התכונה 'דגל' לא זמין במכשיר שבו פועלת גרסת build של משתמש. לחשבון במקרה הזה, משתמשים בפקודה adb:

$ adb shell setprop persist.sys.fflag.override.settings_dynamic_system 1

תמונות של המערכת המארחת של הספק ב-GCE (אופציונלי)

אחד ממיקומי האחסון האפשריים של תמונות המערכת הוא Google קטגוריה של Compute Engine (GCE). האדמין של הגרסה משתמש מסוף האחסון של GCP אל הוספה/מחיקה/שינוי של תמונת המערכת שפורסמה.

התמונות חייבות להיות זמינות לציבור, כפי שמוצג כאן:

גישה ציבורית ב-GCE

איור 4. גישה ציבורית ב-GCE

ההליך להפיכת פריט לגלוי לכולם זמין משאבי עזרה ל-Google Cloud.

DSU מרובה מחיצות בקובץ ZIP

החל מגרסה 11 של Android, ל-DSU יכול להיות יותר מאפשרות אחת מחיצה. לדוגמה, היא יכולה להכיל product.img בנוסף system.img. כשהמכשיר מבצע אתחול, השלב הראשון init מזהה את מתקין מחיצות DSU ומחליף את המחיצה במכשיר באופן זמני, כאשר ה-DSU המותקן מופעל. חבילת ה-DSU עשויה להכיל מחיצה ש קיימת מחיצה תואמת במכשיר.

תהליך DSU עם מחיצות מרובות

איור 5. תהליך DSU עם מחיצות מרובות

DSU בחתימה של יצרן הציוד המקורי

כדי לוודא שכל התמונות שפועלות במכשיר אושרו על ידי המכשיר יצרן, כל התמונות בחבילת DSU חייבות להיות חתומות. לדוגמה, נניח שיש חבילת DSU שמכילה שתי תמונות מחיצות כמו בדוגמה הבאה:

dsu.zip {
    - system.img
    - product.img
}

ה-system.img וגם product.img חייבים להיות חתומים במפתח ה-OEM לפני שהם נשמרות בקובץ ה-ZIP. השיטה הנפוצה היא להשתמש במודל אסימטרי אלגוריתם RSA, שבו המפתח הסודי משמש לחתימה על החבילה מפתח ציבורי משמש לאימות שלו. שלב ה-ramdisk בשלב הראשון חייב לכלול את ההתאמה מפתח ציבורי, לדוגמה /avb/*.avbpubkey. אם המכשיר כבר משתמש ב-AVB, הליך החתימה הקיים יספיק. הקטעים הבאים ממחישים את תהליך חתימה ולהדגיש את המיקום של מפתח המשתמש ה-AVB שמשמש מאמתים את התמונות בחבילת ה-DSU.

מתאר JSON של DSU

מתאר DSU JSON מתאר חבילות DSU. הוא תומך בשני פרימיטיביים. קודם כול, רכיב ה-include כולל תיאורים נוספים של JSON או הפניות אוטומטיות מטען ה-DSU למיקום חדש. לדוגמה:

{
    "include": ["https://.../gsi-release/gsi-src.json"]
}

שנית, הפרמיטיבי image משמש לתיאור חבילות DSU שפורסמו. פנים החנות בפרימיטיבי של התמונה יש כמה מאפיינים:

  • המאפיינים name ו-details הם מחרוזות שמוצגות תיבת הדו-שיח שבה המשתמש יכול לבחור.

  • המאפיינים cpu_api, vndk ו-os_version משמשים בשביל ובדיקת התאימות האישית, המתוארות בקטע הבא.

  • המאפיין האופציונלי pubkey מתאר את הציבור שמתאים למפתח הסודי שמשמש לחתימה על חבילת ה-DSU. לאחר מכן, שירות ה-DSU יכול לבדוק אם למכשיר יש את המפתח ששימש לאימות חבילת ה-DSU. הפעולה הזו מונעת התקנה של DSU לא מזוהה חבילה, לדוגמה, התקנת DSU חתום על ידי OEM-A במכשיר שנוצר על ידי OEM-B.

  • המאפיין האופציונלי tos מפנה לקובץ טקסט שמתאר התנאים וההגבלות של חבילת ה-DSU המתאימה. כאשר מפתח בוחר חבילת DSU שצוין בה מאפיין התנאים וההגבלות, נפתחת תיבת דו-שיח באיור 6, עם בקשה מהמפתח לאשר את התנאים של השירות לפני התקנת חבילת ה-DSU.

    תיבת הדו-שיח &#39;תנאים והגבלות&#39;

    איור 6. תיבת הדו-שיח 'תנאים והגבלות'

הנה מתאר DSU JSON של GSI:

{
   "images":[
      {
         "name":"GSI+GMS x86",
         "os_version":"10",
         "cpu_abi": "x86",
         "details":"exp-QP1A.190711.020.C4-5928301",
         "vndk":[
            27,
            28,
            29
         ],
         "pubkey":"",
         "tos": "https://dl.google.com/developers/android/gsi/gsi-tos.txt",
         "uri":"https://.../gsi/gsi_gms_x86-exp-QP1A.190711.020.C4-5928301.zip"
      },
      {
         "name":"GSI+GMS ARM64",
         "os_version":"10",
         "cpu_abi": "arm64-v8a",
         "details":"exp-QP1A.190711.020.C4-5928301",
         "vndk":[
            27,
            28,
            29
         ],
         "pubkey":"",
         "tos": "https://dl.google.com/developers/android/gsi/gsi-tos.txt",
         "uri":"https://.../gsi/gsi_gms_arm64-exp-QP1A.190711.020.C4-5928301.zip"
      },
      {
         "name":"GSI ARM64",
         "os_version":"10",
         "cpu_abi": "arm64-v8a",
         "details":"exp-QP1A.190711.020.C4-5928301",
         "vndk":[
            27,
            28,
            29
         ],
         "pubkey":"",
         "uri":"https://.../gsi/aosp_arm64-exp-QP1A.190711.020.C4-5928301.zip"
      },
      {
         "name":"GSI x86_64",
         "os_version":"10",
         "cpu_abi": "x86_64",
         "details":"exp-QP1A.190711.020.C4-5928301",
         "vndk":[
            27,
            28,
            29
         ],
         "pubkey":"",
         "uri":"https://.../gsi/aosp_x86_64-exp-QP1A.190711.020.C4-5928301.zip"
      }
   ]
}

ניהול תאימות

כמה מאפיינים משמשים לציון התאימות בין חבילת DSU ובמכשיר המקומי:

  • cpu_api היא מחרוזת שמתארת את הארכיטקטורה של המכשיר. המאפיין הזה השדה הזה הוא חובה, ואפשר להשוות אותו למאפיין המערכת ro.product.cpu.abi. הערכים שלהם חייבים להיות זהים.

  • os_version הוא מספר שלם אופציונלי שמציין גרסת Android. עבור לדוגמה: ב-Android 10, os_version הוא 10 וגם ל-Android 11, os_version הוא 11. כשהפעולה הזו שצוין, הוא חייב להיות שווה לערך ro.system.build.version.release או גדול ממנו מאפיין מערכת. הבדיקה הזו משמשת למניעת אתחול תמונה של Android 10 GSI ב-Android 11 של המכשיר של הספק שאינו נתמך כרגע. מותר להפעיל תמונת Android 11 GSI במכשיר Android 10.

  • vndk הוא מערך אופציונלי שמציין את כל מפתחות ה-VNDK שכלולים חבילת ה-DSU. לאחר ציון הערך, טוען ה-DSU בודק אם המספר שחולץ ממאפיין המערכת ro.vndk.version כלול.

ביטול מפתחות DSU מטעמי אבטחה

במקרה הנדיר ביותר שבו זוג מפתחות ה-RSA המשמש לחתימה על תמונות ה-DSU נפרץ, יש לעדכן את ה-ramdisk בהקדם האפשרי כדי להסיר את מפתח שנפרץ. בנוסף לעדכון מחיצת האתחול, אפשר לחסום את מפתחות שנפרצו באמצעות רשימת ביטול של מפתחות DSU (רשימה שחורה של מפתחות) מ-HTTPS כתובת URL.

רשימת הביטולים של מפתחות DSU מכילה רשימה של מפתחות ציבוריים AVB שבוטלו. במהלך התקנת ה-DSU, המפתחות הציבוריים בתמונות ה-DSU מאומתים ברשימת הביטולים. אם יתברר שהתמונות מכילות תוכן ציבורי שבוטל המפתח, תהליך ההתקנה של ה-DSU נפסק.

כדי לשמור על האבטחה, כתובת ה-URL של רשימת הביטולים של המפתחות צריכה להיות כתובת URL מסוג HTTPS והוא מצוין במחרוזת המשאב:

frameworks/base/packages/DynamicSystemInstallationService/res/values/strings.xml@key_revocation_list_url

ערך המחרוזת הוא https://dl.google.com/developers/android/gsi/gsi-keyblacklist.json, שהוא רשימת ביטולים של מפתחות GSI שפורסמו על ידי Google. מחרוזת המשאב הזו יכולה להיות שכבות-על והתאמה אישית, כדי שיצרני ציוד מקורי שמאמצים את השימוש בתכונה DSU יוכלו לספק לשמור על רשימת מפתחות משלהם. הבדיקה מאפשרת ל-OEM (יצרן הציוד המקורי) לחסום מפתחות ציבוריים מסוימים בלי לעדכן את תמונת הרדיסק של המכשיר.

הפורמט של רשימת הביטולים הוא:

{
   "entries":[
      {
         "public_key":"bf14e439d1acf231095c4109f94f00fc473148e6",
         "status":"REVOKED",
         "reason":"Key revocation test key"
      },
      {
         "public_key":"d199b2f29f3dc224cca778a7544ea89470cbef46",
         "status":"REVOKED",
         "reason":"Key revocation test key"
      }
   ]
}
  • public_key הוא תקציר SHA-1 של המפתח שבוטל, בפורמט שמתואר ביצירת pubkey של AVB .
  • status מציין את סטטוס הביטול של המפתח. בשלב זה, הבדיקה היחידה הערך הנתמך הוא REVOKED.
  • reason היא מחרוזת אופציונלית שמתארת את הסיבה לביטול.

נוהלי DSU

בקטע הזה מוסבר איך לבצע כמה תהליכי הגדרה של DSU.

יצירת זוג מפתחות חדש

משתמשים בפקודה openssl כדי ליצור זוג מפתחות פרטיים/ציבוריים של RSA ב-.pem פורמט (לדוגמה, בגודל 2,048 ביט):

$ openssl genrsa -out oem_cert_pri.pem 2048
$ openssl rsa -in oem_cert_pri.pem -pubout -out oem_cert_pub.pem

ייתכן שהמפתח הפרטי לא יהיה נגיש והוא נשמר רק מודול אבטחת חומרה (HSM) במקרה כזה, יכול להיות שיהיה אישור של מפתח ציבורי מסוג x509 אחרי המפתח ליצירת תמונות, ראו הוספת ה-pubkey של ההתאמה ל-ramdisk לקבלת הוראות ליצירת מפתח ציבורי מסוג AVB מאישור x509.

כדי להמיר אישור x509 לפורמט PEM:

$ openssl x509 -pubkey -noout -in oem_cert_pub.x509.pem > oem_cert_pub.pem

אם האישור הוא כבר קובץ PEM, צריך לדלג על השלב הזה.

הוסף את מפתח החיבור (pubkey) ל-ramdisk

יש להוסיף את oem_cert.avbpubkey מתחת ל-/avb/*.avbpubkey כדי לאמת את חבילת DSU חתומה. קודם כול, ממירים את המפתח הציבורי בפורמט PEM ל-AVB ציבורי פורמט מפתח:

$ avbtool extract_public_key --key oem_cert_pub.pem --output oem_cert.avbpubkey

אחר כך כוללים את המפתח הציבורי ב-ramdisk בשלב הראשון בעזרת השלבים הבאים.

  1. צריך להוסיף מודול מוגדר מראש כדי להעתיק את avbpubkey. לדוגמה, אפשר להוסיף device/<company>/<board>/oem_cert.avbpubkey והקבוצה device/<company>/<board>/avb/Android.mk עם תוכן כמו זה:

    include $(CLEAR_VARS)
    
    LOCAL_MODULE := oem_cert.avbpubkey
    LOCAL_MODULE_CLASS := ETC
    LOCAL_SRC_FILES := $(LOCAL_MODULE)
    ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
    LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/first_stage_ramdisk/avb
    else
    LOCAL_MODULE_PATH := $(TARGET_RAMDISK_OUT)/avb
    endif
    
    include $(BUILD_PREBUILT)
    
  2. מגדירים שיעד ה-droidcore יהיה תלוי ב-oem_cert.avbpubkey שנוסף:

    droidcore: oem_cert.avbpubkey
    

יצירת מאפיין pubkey של AVB במתאר JSON

ה-oem_cert.avbpubkey הוא בפורמט בינארי של מפתח ציבורי AVB. שימוש באלגוריתם SHA-1 כדי להפוך אותו לקריא לפני שמכניסים אותו למתאר ה-JSON:

$ sha1sum oem_cert.avbpubkey | cut -f1 -d ' '
3e62f2be9d9d813ef5........866ac72a51fd20

זה יהיה התוכן של המאפיין pubkey במתאר ה-JSON.

   "images":[
      {
         ...
         "pubkey":"3e62f2be9d9d813ef5........866ac72a51fd20",
         ...
      },

חתימה על חבילת DSU

צריך להשתמש באחת מהשיטות הבאות כדי לחתום על חבילת DSU:

  • שיטה 1: שימוש חוזר בארטיפקט שנוצר באמצעות תהליך החתימה המקורי ב-AVB כדי יוצרים חבילת DSU. גישה חלופית היא לחלץ את הנתונים שכבר חתומים תמונות מחבילת ההפצה ומשתמשים בתמונות שחולצו כדי ליצור את קובץ ה-ZIP ישירות.

  • שיטה 2: משתמשים בפקודות הבאות כדי לחתום על מחיצות DSU אם המקש זמין. כל img בתוך חבילת DSU (קובץ ה-ZIP) חתום בנפרד:

    $ key_len=$(openssl rsa -in oem_cert_pri.pem -text | grep Private-Key | sed -e 's/.*(\(.*\) bit.*/\1/')
    $ for partition in system product; do
        avbtool add_hashtree_footer \
            --image ${OUT}/${partition}.img \
            --partition_name ${partition} \
            --algorithm SHA256_RSA${key_len} \
            --key oem_cert_pri.pem
    done
    

למידע נוסף על הוספת add_hashtree_footer באמצעות avbtool: באמצעות avbtool.

אימות מקומי של חבילת ה-DSU

מומלץ לאמת את כל התמונות המקומיות באמצעות מפתח ההתאמה הציבורי באמצעות הפקודות האלה:


for partition in system product; do
    avbtool verify_image --image ${OUT}/${partition}.img  --key oem_cert_pub.pem
done

הפלט הצפוי:

Verifying image dsu/system.img using key at oem_cert_pub.pem
vbmeta: Successfully verified footer and SHA256_RSA2048 vbmeta struct in dsu/system.img
: Successfully verified sha1 hashtree of dsu/system.img for image of 898494464 bytes

Verifying image dsu/product.img using key at oem_cert_pub.pem
vbmeta: Successfully verified footer and SHA256_RSA2048 vbmeta struct in dsu/product.img
: Successfully verified sha1 hashtree of dsu/product.img for image of 905830400 bytes

יצירה של חבילת DSU

הדוגמה הבאה יוצרת חבילת DSU שמכילה system.img ורכיב product.img:

dsu.zip {
    - system.img
    - product.img
}

אחרי שחתמתם על שתי התמונות, משתמשים בפקודה הבאה כדי ליצור את קובץ ה-ZIP:

$ mkdir -p dsu
$ cp ${OUT}/system.img dsu
$ cp ${OUT}/product.img dsu
$ cd dsu && zip ../dsu.zip *.img && cd -

התאמה אישית של ה-DSU בלחיצה אחת

כברירת מחדל, טוען ה-DSU מפנה למטא-נתונים של תמונות GSI, https://...google.com/.../gsi-src.json

יצרני ציוד מקורי יכולים להחליף את הרשימה על ידי הגדרת persist.sys.fflag.override.settings_dynamic_system.list שמפנה למתאר JSON משלו. לדוגמה, OEM (יצרן ציוד מקורי) יכול מספקים מטא-נתונים של JSON שכוללים את GSI וגם תמונות קנייניות של ה-OEM:

{
    "include": ["https://dl.google.com/.../gsi-src.JSON"]
    "images":[
      {
         "name":"OEM image",
         "os_version":"10",
         "cpu_abi": "arm64-v8a",
         "details":"...",
         "vndk":[
            27,
            28,
            29
         ],
         "spl":"...",
         "pubkey":"",
         "uri":"https://.../....zip"
      },

}

יכול להיות שיצרן ציוד מקורי יוכל לפרסם בשרשרת מטא-נתונים של ה-DSU שפורסמו, כפי שמוצג באיור 7.

מטא-נתונים של DSU שפורסמו ברשת

איור 7. מטא-נתונים של DSU שפורסמו ברשת