בעזרת Dynamic System Updates (DSU) אפשר ליצור תמונת מערכת של Android שמשתמשים יכולים להוריד מהאינטרנט ולנסות בלי סיכון לפגיעה בתמונת המערכת הנוכחית. במסמך הזה מוסבר איך לתמוך ב-DSU.
דרישות ליבה
מידע על דרישות הליבה מופיע במאמר בנושא הטמעה של חלוקה דינמית.
בנוסף, DSU מסתמך על תכונת הליבה device-mapper-verity (dm-verity) כדי לאמת את קובץ האימג' של מערכת Android. לכן, צריך להפעיל את הגדרות הליבה הבאות:
CONFIG_DM_VERITY=y
CONFIG_DM_VERITY_FEC=y
דרישות לגבי מחיצות
החל מ-Android 11, כדי להשתמש ב-DSU, המחיצה /data
צריכה להשתמש במערכת הקבצים F2FS או ext4. F2FS מספק ביצועים טובים יותר ומומלץ, אבל ההבדל לא אמור להיות משמעותי.
הנה כמה דוגמאות לזמן שלוקח לעדכן את המערכת באופן דינמי במכשיר Pixel:
- שימוש ב-F2FS:
- 109s, 8G user, 867M system, file system type: F2FS: encryption=aes-256-xts:aes-256-cts
- 104s, 8G user, 867M system, file system type: F2FS: encryption=ice
- שימוש ב-ext4:
- 135s, 8G user, 867M system, file system type: ext4: encryption=aes-256-xts:aes-256-cts
אם הפעולה נמשכת הרבה יותר זמן בפלטפורמה שלכם, כדאי לבדוק אם דגל ההרכבה מכיל דגל שגורם לכתיבה של 'סנכרון', או שאתם יכולים לציין במפורש דגל 'אסינכרוני' כדי לשפר את הביצועים.
מחיצת metadata
(בגודל 16 MB או יותר) נדרשת לאחסון נתונים שקשורים לתמונות המותקנות. צריך להרכיב אותו במהלך ההרכבה בשלב הראשון.
המחיצה userdata
חייבת להשתמש במערכת הקבצים F2FS או ext4. כשמשתמשים ב-F2FS, צריך לכלול את כל תיקוני ה-F2FS שזמינים בליבת Android המשותפת.
הכלי DSU פותח ונבדק עם ליבת מערכת ההפעלה (kernel) גרסה 4.9. מומלץ להשתמש בגרסה 4.9 ומעלה של ליבת המערכת כדי להשתמש בתכונה הזו.
התנהגות של שכבת הפשטת חומרה של ספק
Weaver HAL
שכבת ה-HAL של Weaver מספקת מספר קבוע של משבצות לאחסון מפתחות משתמשים. ה-DSU תופס שני חריצים נוספים למפתחות. אם ליצרן ציוד מקורי יש weaver HAL, צריך להיות לו מספיק משבצות לתמונת מערכת גנרית (GSI) ולתמונת מארח.
Gatekeeper HAL
Gatekeeper HAL צריך לתמוך בערכים גדולים של USER_ID
, כי GSI מוסיף 1,000,000 ל-UIDs ב-HAL.
אימות האתחול
אם רוצים לתמוך באתחול של תמונות 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, צריך להזין את רמת תיקון האבטחה של תמונת המערכת הנוכחית בשורת הפקודה של הליבה או בקובץ bootconfig באמצעות תוכנת האתחול:
androidboot.system.security_patch=2019-04-05
.
דרישות חומרה
כשמפעילים מופע של DSU, מוקצים שני קבצים זמניים:
- מחיצה לוגית לאחסון
GSI.img
(1~1.5 G) - מחיצת
/data
ריקה בגודל 8 GB כארגז חול להרצת ה-GSI
מומלץ להקצות לפחות 10 GB של שטח פנוי לפני שמפעילים מופע של 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 של המערכת, אי אפשר ליצור את האפליקציה באמצעות ה-API הרגיל של ערכת ה-SDK ואי אפשר לפרסם אותה ב-Google Play. מטרת האפליקציה הזו היא:
- אחזור רשימת תמונות וכתובת ה-URL התואמת באמצעות סכימה שהוגדרה על ידי הספק.
- התאמת התמונות ברשימה למכשיר והצגת תמונות תואמות לבחירת המשתמש.
כך מפעילים את
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 בלחיצה אחת, שהוא חזית קדמית בהגדרות למפתחים.
איור 1. הפעלת טעינת ה-DSU
כשהמפתח לוחץ על הלחצן DSU Loader, הוא מאחזר מהאינטרנט מתאר DSU JSON שהוגדר מראש ומציג את כל התמונות הרלוונטיות בתפריט הצף. בוחרים תמונה כדי להתחיל בהתקנת DSU, וההתקדמות מוצגת בסרגל ההתראות.
איור 2. התקדמות ההתקנה של תמונת DSU
כברירת מחדל, טוען ה-DSU טוען מתאר JSON שמכיל את תמונות ה-GSI. בקטעים הבאים מוסבר איך ליצור חבילות DSU חתומות על ידי יצרן ציוד מקורי (OEM) ואיך לטעון אותן מטוען ה-DSU.
מתג feature flag
תכונת ה-DSU נמצאת ב-settings_dynamic_android
feature flag. לפני שמשתמשים ב-DSU, צריך לוודא שדגל התכונה המתאים מופעל.
איור 3. הפעלת מתג feature flag
יכול להיות שממשק המשתמש של feature flag לא יהיה זמין במכשיר שמופעלת בו גרסת משתמש. במקרה כזה, משתמשים בפקודה adb
במקום:
$ adb shell setprop persist.sys.fflag.override.settings_dynamic_system 1
ספק מארח תמונות מערכת ב-GCE (אופציונלי)
אחד ממיקומי האחסון האפשריים של קובצי האימג' של המערכת הוא דלי Google Compute Engine (GCE). האדמין של הגרסה משתמש בGCP Storage Console כדי להוסיף, למחוק או לשנות את תמונת המערכת שפורסמה.
התמונות צריכות להיות בגישה ציבורית, כמו שמוצג כאן:
איור 4. גישה ציבורית ב-GCE
ההליך להפיכת פריט לציבורי זמין במסמכי התיעוד של Google Cloud.
קובץ ZIP של DSU עם כמה מחיצות
החל מ-Android 11, ל-DSU יכולות להיות יותר ממחיצה אחת. לדוגמה, הוא יכול להכיל product.img
בנוסף ל-system.img
. כשהמכשיר מופעל, השלב הראשון init
מזהה את מחיצות ה-DSU המותקנות ומחליף באופן זמני את המחיצה במכשיר, כשה-DSU המותקן מופעל. חבילת ה-DSU עשויה להכיל מחיצה שאין לה מחיצה תואמת במכשיר.
איור 5. תהליך DSU עם כמה מחיצות
DSU חתום על ידי OEM
כדי לוודא שכל התמונות שמופעלות במכשיר אושרו על ידי יצרן המכשיר, צריך לחתום על כל התמונות בחבילת DSU. לדוגמה, נניח שיש חבילת DSU שמכילה שתי תמונות של מחיצות כמו בדוגמה הבאה:
dsu.zip {
- system.img
- product.img
}
הקובץ system.img
והקובץ product.img
חייבים להיות חתומים באמצעות מפתח ה-OEM לפני שמכניסים אותם לקובץ ה-ZIP. השיטה המקובלת היא להשתמש באלגוריתם אסימטרי, למשל RSA, שבו המפתח הסודי משמש לחתימה על החבילה והמפתח הציבורי משמש לאימות שלה. ה-ramdisk בשלב הראשון חייב לכלול את המפתח הציבורי של ההתאמה, למשל /avb/*.avbpubkey
. אם המכשיר כבר תומך ב-AVB, די בהליך החתימה הקיים. בקטעים הבאים מוסבר תהליך החתימה, ומוצג המיקום של המפתח הציבורי של AVB שמשמש לאימות התמונות בחבילת ה-DSU.
קובץ תיאור JSON של DSU
קובץ ה-JSON של ה-DSU מתאר חבילות 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.איור 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
או גדול ממנו. הבדיקה הזו משמשת למניעת אתחול של תמונת GSI של Android 10 במכשיר ספק של Android 11, שלא נתמך כרגע. מותר להפעיל תמונת GSI של Android 11 במכשיר Android 10.
vndk
הוא מערך אופציונלי שמציין את כל ה-VNDK שנכללים בחבילת ה-DSU. אם מציינים את המאפיין הזה, טוען ה-DSU בודק אם המספר שחולץ ממאפיין המערכתro.vndk.version
נכלל.
ביטול מפתחות DSU לצורך אבטחה
במקרים נדירים מאוד שבהם זוג מפתחות RSA שמשמש לחתימה על תמונות DSU נפרץ, צריך לעדכן את ה-ramdisk בהקדם האפשרי כדי להסיר את המפתח שנפרץ. בנוסף לעדכון מחיצת האתחול, אפשר לחסום מפתחות שנפרצו באמצעות רשימת ביטול מפתחות DSU (רשימה שחורה של מפתחות) מכתובת URL של HTTPS.
רשימת הביטולים של מפתחות DSU מכילה רשימה של מפתחות ציבוריים של AVB שבוטלו. במהלך ההתקנה של DSU, המפתחות הציבוריים בתוך תמונות ה-DSU מאומתים באמצעות רשימת הביטולים. אם התמונות מכילות מפתח ציבורי שבוטל, תהליך ההתקנה של DSU ייפסק.
כתובת ה-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. אפשר להוסיף מחרוזת משאבים זו ולהתאים אותה אישית, כך שיצרני ציוד מקורי (OEM) שמשתמשים בתכונת ה-DSU יוכלו לספק ולתחזק רשימה שחורה משלהם של מפתחות. כך יצרן ה-OEM יכול לחסום מפתחות ציבוריים מסוימים בלי לעדכן את תמונת ה-ramdisk של המכשיר.
הפורמט של רשימת הביטולים הוא:
{
"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 של המפתח שבוטל, בפורמט שמתואר בקטע יצירת המפתח הציבורי של AVB. -
status
מציין את סטטוס הביטול של המפתח. בשלב הזה, הערך הנתמך היחיד הואREVOKED
. -
reason
היא מחרוזת אופציונלית שמתארת את הסיבה לביטול.
הליכים של DSU
בקטע הזה מוסבר איך לבצע כמה תהליכי הגדרה של DSU.
יצירת זוג מפתחות חדש
משתמשים בפקודה openssl
כדי ליצור זוג מפתחות RSA פרטיים/ציבוריים בפורמט .pem
(לדוגמה, בגודל 2048 ביט):
$ openssl genrsa -out oem_cert_pri.pem 2048
$ openssl rsa -in oem_cert_pri.pem -pubout -out oem_cert_pub.pem
יכול להיות שהמפתח הפרטי לא נגיש, והוא נשמר רק במודול אבטחה לחומרה (HSM). במקרה כזה, יכול להיות שיהיה אישור מפתח ציבורי מסוג x509 זמין אחרי יצירת המפתח. בקטע הוספת המפתח הציבורי של ההתאמה ל-ramdisk מוסבר איך ליצור את המפתח הציבורי של AVB מאישור x509.
כדי להמיר אישור x509 לפורמט PEM:
$ openssl x509 -pubkey -noout -in oem_cert_pub.x509.pem > oem_cert_pub.pem
אפשר לדלג על השלב הזה אם האישור כבר נמצא בקובץ PEM.
הוספה של המפתח הציבורי של ההתאמה ל-ramdisk
צריך להציב את oem_cert.avbpubkey
מתחת ל-/avb/*.avbpubkey
כדי לאמת את חבילת ה-DSU החתומה. קודם ממירים את המפתח הציבורי בפורמט PEM לפורמט המפתח הציבורי של AVB:
$ avbtool extract_public_key --key oem_cert_pub.pem --output oem_cert.avbpubkey
לאחר מכן, כוללים את המפתח הציבורי ב-ramdisk של השלב הראשון באמצעות השלבים הבאים.
מוסיפים מודול מוכן מראש כדי להעתיק את
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)
הגדרת יעד droidcore כתלוי ב-
oem_cert.avbpubkey
שנוסף:droidcore: oem_cert.avbpubkey
יצירת מאפיין של מפתח ציבורי של 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 שלהם. לדוגמה, יצרן ציוד מקורי יכול לספק מטא-נתונים בפורמט JSON שכוללים GSI וגם תמונות קנייניות של יצרן הציוד המקורי, כמו בדוגמה הבאה:
{
"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.
איור 7. שרשור של מטא-נתונים שפורסמו של DSU