פורמט הקונטיינר Android Pony EXpress (APEX) הושק ב-Android 10 והיא משמשת בתהליך ההתקנה של מערכת ברמה נמוכה יותר מודולים. הפורמט הזה מאפשר עדכונים של רכיבי מערכת שלא מתאימים למודל הסטנדרטי של Android. חלק מהרכיבים לדוגמה הם מקוריים שירותים וספריות, שכבות הפשטה של חומרה (HALs), סביבת זמן ריצה (ART) וספריות של כיתות.
המונח APEX יכול גם להפנות לקובץ APEX.
רקע
מערכת Android תומכת בעדכונים של מודולים שתואמים לאפליקציה הרגילה (לדוגמה, שירותים, פעילויות) באמצעות אפליקציות של מנהל התקנה (כמו באפליקציה של חנות Google Play), באמצעות מודל דומה לרכיבי מערכת הפעלה ברמה נמוכה יותר. יש את החסרונות הבאים:
- לא ניתן להשתמש במודולים המבוססים על APK בשלב מוקדם של רצף ההפעלה. החבילה הוא המאגר המרכזי של מידע על אפליקציות, והוא יכול לשמש רק התחיל במנהל הפעילות, שמוכן בשלב מאוחר יותר של את תהליך האתחול.
- פורמט ה-APK (במיוחד המניפסט) מיועד לאפליקציות ל-Android. המודולים של המערכת לא תמיד מתאימים.
עיצוב
בקטע הזה מתואר העיצוב הכללי של פורמט הקובץ APEX APEX Manager, שהוא שירות שמנהל קובצי APEX.
למידע נוסף על הסיבה לבחירת העיצוב הזה עבור APEX, ראו חלופות אפשריות במהלך הפיתוח של APEX.
פורמט APEX
זהו הפורמט של קובץ APEX.
איור 1. פורמט הקובץ APEX
ברמה העליונה, קובץ APEX הוא קובץ ZIP שבו מאוחסנים הקבצים לא דחוס ובגבולות של 4 KB.
ארבעת הקבצים בקובץ APEX הם:
apex_manifest.json
AndroidManifest.xml
apex_payload.img
apex_pubkey
הקובץ apex_manifest.json
מכיל את שם החבילה והגרסה שלו,
לזהות קובץ APEX. זהו
ApexManifest
מאגר נתונים זמני של פרוטוקול בפורמט JSON.
הקובץ AndroidManifest.xml
מאפשר לקובץ ה-APEX להשתמש בכלים שקשורים ל-APK
כגון ADB, PackageManager ואפליקציות של מנהל ההתקנה של חבילות (כמו
חנות Play). לדוגמה, קובץ ה-APEX יכול להשתמש בכלי קיים כמו aapt
כדי לבדוק מטא-נתונים בסיסיים מהקובץ. הקובץ מכיל את שם החבילה ואת
פרטי הגרסה. המידע הזה זמין בדרך כלל גם
apex_manifest.json
מומלץ להשתמש ב-apex_manifest.json
מעל AndroidManifest.xml
לקוד חדש וגם
במערכות שעוסקות ב-APEX. ייתכן שהשדה AndroidManifest.xml
מכיל עוד
מידע לטירגוט שבו יכולים להשתמש הכלים הקיימים לפרסום אפליקציות.
apex_payload.img
היא תמונה של מערכת קבצים מסוג ext4 שמגובה על ידי dm-verity. התמונה
טעונה בזמן הריצה באמצעות מכשיר לולאה חוזרת. וספציפית, עץ הגיבוב (hash)
בלוק המטא-נתונים נוצר באמצעות הספרייה libavb
. המטען הייעודי (Payload) של מערכת הקבצים
לא מנותח (כי התמונה צריכה להיות ניתנת לטעינה במקום זאת). הקבצים הרגילים הם
נכללות בקובץ apex_payload.img
.
apex_pubkey
הוא המפתח הציבורי שמשמש לחתימה על תמונת מערכת הקבצים. בזמן הריצה,
המפתח הזה מבטיח שה-APEX שהורדתם ייחתם עם אותה ישות
שחותם על אותו APEX במחיצות המובנות.
הנחיות למתן שמות ל-APEX
כדי למנוע התנגשויות בין שמות של APEX חדשים ככל שהפלטפורמה מתקדמת, יש לפעול לפי ההנחיות הבאות למתן שמות:
com.android.*
- שמור ל-AOSP APEX. לא ייחודי לשום חברה או מכשיר.
com.<companyname>.*
- שמור לחברה. עשוי להיות בשימוש במספר מכשירים מתוך האפליקציה בחברה.
com.<companyname>.<devicename>.*
- שמור ל-APEX ייחודיים למכשיר ספציפי (או לקבוצת משנה של מכשירים).
מנהל APEX
מנהל APEX (או apexd
) הוא תהליך נייטיב עצמאי שאחראי על
אימות, התקנה והסרה של קובצי APEX. התהליך הזה הושק
מוכן בשלב מוקדם ברצף האתחול. בדרך כלל קובצי APEX מותקנים מראש
במכשיר מתחת ל-/system/apex
. כברירת מחדל, מנהל APEX משתמש
אם אין עדכונים זמינים.
רצף העדכונים של APEX משתמש מחלקה PackageManager והוא מופיע בהמשך.
- מתבצעת הורדה של קובץ APEX דרך אפליקציה של מנהל התקנה של חבילה, ADB או מקור.
- מנהל החבילות מתחיל את תהליך ההתקנה. כשאנחנו מכירים הקובץ הוא APEX, מנהל החבילות מעביר את השליטה ל-APEX מנהל.
- מנהל APEX מאמת את קובץ ה-APEX.
- אם קובץ APEX מאומת, מסד הנתונים הפנימי של מנהל APEX מעודכן כדי לשקף שקובץ APEX מופעל בהפעלה הבאה.
- מבקש ההתקנה מקבל שידור לאחר שהחבילה הצליחה אימות.
- כדי להמשיך בהתקנה, צריך להפעיל מחדש את המערכת.
באתחול הבא, מנהל APEX מתחיל, קורא את מסד הנתונים הפנימי ו את הפרטים הבאים לגבי כל קובץ APEX
- מאמתת את קובץ APEX.
- יצירה של מכשיר לולאה חוזרת מקובץ ה-APEX.
- יצירת מכשיר בלוק של מיפוי מכשיר על גבי המכשיר הלולאה החוזרת.
- טוענת את מכשיר הבלוק של מיפוי המכשיר לנתיב ייחודי (לדוגמה,
/apex/name@ver
).
כשטוענים את כל קובצי ה-APEX שרשומים במסד הנתונים הפנימי, קובץ ה-APEX מספק שירות binder לרכיבי מערכת אחרים כדי לשלוח שאילתות מידע על קובצי ה-APEX המותקנים. לדוגמה, המערכת השנייה רכיבים יכולים לשלוח שאילתה על רשימת קובצי APEX המותקנים במכשיר או לשלוח שאילתה הנתיב המדויק שבו נטען APEX ספציפי, כדי שאפשר יהיה לגשת לקבצים.
קובצי APEX הם קובצי APK
קובצי APEX הם קובצי APK תקינים כי הם חתומים בארכיוני ZIP (באמצעות
סכמת חתימת APK) שמכילה קובץ AndroidManifest.xml
. כך אפשר להשתמש ב-APEX
לשימוש בתשתית של קובצי APK, כמו אפליקציה של מנהל התקנה של חבילה,
כלי החתימה, ומנהל החבילות.
הקובץ AndroidManifest.xml
שנמצא בקובץ APEX הוא מינימלי, וכולל
חבילה name
, versionCode
ו-targetSdkVersion
, minSdkVersion
אופציונלי,
ו-maxSdkVersion
לטירגוט מדויק יותר. המידע הזה מאפשר ל-APEX
קבצים שיישלחו דרך ערוצים קיימים, כמו אפליקציות של מנהל ההתקנה של חבילות
ADB.
סוגי הקבצים הנתמכים
פורמט APEX תומך בסוגי הקבצים הבאים:
- libs משותפים מותאמים
- קובצי הפעלה נייטיב
- קובצי JAR
- קובצי נתונים
- קובצי תצורה
זה לא אומר ש-APEX יכול לעדכן את כל סוגי הקבצים האלה. האם הקובץ תלוי בפלטפורמה ובמידת היציבות של ההגדרות הממשקים של סוגי הקבצים.
אפשרויות חתימה
קובצי APEX חתומים בשתי דרכים. קודם כל, apex_payload.img
(באופן ספציפי,
קובץ ה-vbmeta שמצורף לקובץ apex_payload.img
) חתום באמצעות מפתח.
לאחר מכן, כל ה-APEX נחתם באמצעות
סכמת חתימת APK גרסה 3 נעשה שימוש בשני מפתחות שונים
בתהליך הזה.
בצד המכשיר, מפתח ציבורי שתואם למפתח הפרטי שמשמש לחתימה מתאר vbmeta מותקן. מנהל APEX משתמש במפתח הציבורי כדי לאמת APEX שהתבקשו להתקין. יש לחתום על כל APEX באמצעות מפתחות שונים, ונאכפים גם בזמן ה-build וגם בזמן הריצה.
APEX במחיצות מובנות
קובצי APEX יכולים להיות ממוקמים במחיצות מובנות כמו /system
.
המחיצה כבר מעל dm-verity, כך שקובצי ה-APEX נטענים ישירות
במכשיר הלולאה החוזרת.
אם קיים APEX במחיצה מובנית, אפשר לעדכן את ה-APEX על ידי
לספק חבילת APEX עם אותו שם חבילה וערך גדול מ- או שווה ל-
לקוד גרסה. קובץ APEX החדש מאוחסן ב-/data
, ובדומה ל-APK,
הגרסה החדשה שהותקנה מאכלסת את הגרסה שכבר קיימת
מחיצה. אבל שלא כמו ב-APKs, הגרסה החדשה שהותקנה של APEX
הופעל לאחר האתחול.
דרישות ליבה (kernel)
כדי לתמוך במודולים של השורה הראשית של APEX במכשיר Android, בגרסאות הבאות של Linux נדרשות תכונות ליבה: מנהל התקן הלולאה החוזרת ו-dm-verity. הלולאה החוזרת מנהל התקן טוען את התמונה של מערכת הקבצים במודול APEX ו-dm-verity מאמת מודול APEX.
הביצועים של מנהל הלולאה החוזרת וה-dm-verity חשובים להשגת ביצועי מערכת טובים בעת השימוש במודולים של APEX.
גרסאות ליבה נתמכות
במודולים הראשיים של APEX יש תמיכה במכשירים עם גרסאות ליבה (kernel) 4.4 או גבוהה יותר. מכשירים חדשים שמושקים עם Android מגרסה 10 ואילך חייבים להשתמש בליבה (kernel) 4.9 ואילך כדי לתמוך במודולים של APEX.
תיקונים נדרשים בליבה (kernel)
תיקוני הליבה (kernel) הנדרשים לתמיכה במודולים של APEX נכללים עץ נפוץ של Android. כדי לקבל את התיקונים לתמיכה ב-APEX, צריך להשתמש בגרסה האחרונה של העץ המשותף של Android.
גרסת ליבה 4.4
הגרסה הזו נתמכת רק במכשירים ששודרגו מ-Android 9
Android 10 ורוצים לתמוך במודולים של APEX. כדי לקבל את
תיקונים נדרשים, מיזוג כלפי מטה מההסתעפות android-4.4
מומלץ. בהמשך מופיעה רשימה של התיקונים הנפרדים הנדרשים
לגרסת הליבה 4.4.
- UPSTREAM: לולאה: הוספת ioctl לשינוי גודל בלוק לוגי (4.4)
- BACKPORT: בלוק/לולאה: הגדר hw_sectors (4.4)
- UPSTREAM: לולאה: הוספת LOOP_SET_BLOCK_SIZE ב-ioctl תואם (4.4)
- Android: mnt: תיקון next_descendent (4.4)
- Android: mnt: טעינה מחדש צריכה להיעשות לעבדים של עבדים (4.4)
- ANDROID: mnt: הפצת מחדש תקינה (4.4)
- חזרה לגרסה הקודמת של 'ANDROID: dm verity: הוספת גודל מינימלי לשליפה מראש' (4.4)
- UPSTREAM: לולאה: שחרור מטמון אם משנים את קיזוז או block_size (4.4)
גרסאות ליבה 4.9/4.14/4.19
כדי לקבל את התיקונים הנדרשים לגרסאות ליבה 4.9/4.14/4.19, יש להקטין את המיזוג מ-
ההסתעפות android-common
.
האפשרויות הנדרשות להגדרת ליבה (kernel)
הרשימה הבאה מציגה את דרישות ההגדרה הבסיסית לתמיכה מודולים של APEX שהושקו ב-Android 10. הפריטים המסומנים בכוכבית (*) הן דרישות קיימות מ-Android מגרסה 9 ומטה.
(*) CONFIG_AIO=Y # AIO support (for direct I/O on loop devices)
CONFIG_BLK_DEV_LOOP=Y # for loop device support
CONFIG_BLK_DEV_LOOP_MIN_COUNT=16 # pre-create 16 loop devices
(*) CONFIG_CRYPTO_SHA1=Y # SHA1 hash for DM-verity
(*) CONFIG_CRYPTO_SHA256=Y # SHA256 hash for DM-verity
CONFIG_DM_VERITY=Y # DM-verity support
דרישות לגבי פרמטרים של שורת הפקודה בליבה (Kernel)
כדי לתמוך ב-APEX, צריך לוודא שהפרמטרים של שורת הפקודה בליבה (kernel) עומדים בדרישות הבאות דרישות:
- אין להגדיר את
loop.max_loop
- הערך של
loop.max_part
חייב להיות 8<=
בניית APEX
בקטע הזה מוסבר איך לבנות APEX באמצעות מערכת ה-build של Android.
הדוגמה הבאה היא של Android.bp
ל-APEX בשם apex.test
.
apex {
name: "apex.test",
manifest: "apex_manifest.json",
file_contexts: "file_contexts",
// libc.so and libcutils.so are included in the apex
native_shared_libs: ["libc", "libcutils"],
binaries: ["vold"],
java_libs: ["core-all"],
prebuilts: ["my_prebuilt"],
compile_multilib: "both",
key: "apex.test.key",
certificate: "platform",
}
דוגמה ל-apex_manifest.json
:
{
"name": "com.android.example.apex",
"version": 1
}
דוגמה ל-file_contexts
:
(/.*)? u:object_r:system_file:s0
/sub(/.*)? u:object_r:sub_file:s0
/sub/file3 u:object_r:file3_file:s0
סוגי קבצים ומיקומים ב-APEX
סוג הקובץ | מיקום ב-APEX |
---|---|
ספריות משותפות | /lib וגם /lib64 (/lib/arm עבור
זרוע מתורגמת ב-x86) |
קובצי הפעלה | /bin |
ספריות Java | /javalib |
מוכנים מראש | /etc |
יחסי תלות עוברים
קובצי APEX כוללים אוטומטית יחסי תלות טרנזקטיביים של Libs משותפים מקוריים
או קובצי הפעלה. לדוגמה, אם libFoo
תלוי ב-libBar
, שני ה-libs
נכללים רק כאשר libFoo
רשום בנכס native_shared_libs
.
טיפול בכמה ממשקי ABI
התקנת הנכס native_shared_libs
גם לחשבון הראשי וגם לחשבון המשני
וממשקים בינאריים של אפליקציות (ABI) של המכשיר. אם חשבון APEX מטרגט מכשירים
עם ממשק ABI יחיד (כלומר, 32 ביט בלבד או 64 ביט בלבד), רק ספריות עם
של ממשקי ה-ABI התואמים.
התקנת הנכס binaries
רק עבור ה-ABI הראשי של המכשיר
בהמשך:
- אם המכשיר הוא בגרסת 32 ביט בלבד, רק גרסת 32 ביט של הקוד הבינארי מותקנת.
- אם המכשיר הוא בגרסת 64 ביט בלבד, רק הווריאנט של 64 ביט של הקוד הבינארי מותקנת.
כדי להוסיף שליטה פרטנית בממשקי ה-ABI של הספריות והקבצים הבינאריים המקוריים,
להשתמש
multilib.[first|lib32|lib64|prefer32|both].[native_shared_libs|binaries]
נכסים.
first
: תואם לממשק ה-ABI הראשי של המכשיר. זוהי ברירת המחדל עבור בינאריים.lib32
: תואם ל-ABI של 32 ביט של המכשיר, אם נתמך.lib64
: תואם ל-ABI של המכשיר בגרסת 64 ביט, שהוא נתמך.prefer32
: תואם ל-ABI של 32 ביט של המכשיר, אם נתמך. אם אין תמיכה ב-ABI של 32 ביט, והוא תואם ל-ABI של 64 ביט.both
: תואם לשני ממשקי ה-ABI. זוהי ברירת המחדל עבורnative_shared_libraries
הנכסים java
, libraries
ו-prebuilts
עוברים ניתוח ABI.
הדוגמה הזו מיועדת למכשיר שתומך ב-32/64 ולא בהעדפה 32:
apex {
// other properties are omitted
native_shared_libs: ["libFoo"], // installed for 32 and 64
binaries: ["exec1"], // installed for 64, but not for 32
multilib: {
first: {
native_shared_libs: ["libBar"], // installed for 64, but not for 32
binaries: ["exec2"], // same as binaries without multilib.first
},
both: {
native_shared_libs: ["libBaz"], // same as native_shared_libs without multilib
binaries: ["exec3"], // installed for 32 and 64
},
prefer32: {
native_shared_libs: ["libX"], // installed for 32, but not for 64
},
lib64: {
native_shared_libs: ["libY"], // installed for 64, but not for 32
},
},
}
חתימת vbmeta
יש לחתום על כל APEX באמצעות מפתחות שונים. כשצריך מפתח חדש, יוצרים
זוג מפתחות ציבורי-פרטי ויוצרים מודול apex_key
. אפשר להשתמש בנכס key
כדי
לחתום על APEX באמצעות המפתח. המפתח הציבורי נכלל באופן אוטומטי
APEX בשם avb_pubkey
# create an rsa key pairopenssl genrsa -out foo.pem 4096
# extract the public key from the key pairavbtool extract_public_key --key foo.pem --output foo.avbpubkey
# in Android.bpapex_key { name: "apex.test.key", public_key: "foo.avbpubkey", private_key: "foo.pem", }
בדוגמה שלמעלה, השם של המפתח הציבורי (foo
) הופך למזהה של
מקש. המזהה של המפתח שמשמש לחתימה על APEX כתוב ב-APEX. בזמן הריצה,
המערכת של apexd
מאמתת את APEX באמצעות מפתח ציבורי עם אותו מזהה במכשיר.
חתימת APEX
לחתום על APEX באותה דרך שחותמים על חבילות APK. לחתום פעמיים על APEX; פעם אחת בשביל
מיני מערכת קבצים (קובץ אחד (apex_payload.img
)) ופעם אחת לכל הקובץ.
כדי לחתום על APEX ברמת הקובץ, צריך להגדיר את המאפיין certificate
באחד
שלוש הדרכים הבאות:
- לא מוגדר: אם לא הוגדר ערך, ה-APEX נחתם עם האישור שממוקם
PRODUCT_DEFAULT_DEV_CERTIFICATE
. אם לא הוגדר דגל, ברירת המחדל של הנתיב היא אלbuild/target/product/security/testkey
. <name>
: ה-APEX חתום באמצעות האישור<name>
באותו אותו לספרייה בתורPRODUCT_DEFAULT_DEV_CERTIFICATE
.:<name>
: ה-APEX חתום באמצעות האישור שמוגדר על ידי מודול סונג בשם<name>
. אפשר להגדיר את מודול האישור כך: עוקבים.
android_app_certificate {
name: "my_key_name",
certificate: "dir/cert",
// this will use dir/cert.x509.pem (the cert) and dir/cert.pk8 (the private key)
}
התקנת APEX
כדי להתקין APEX, צריך להשתמש ב-ADB.
adb install apex_file_name
adb reboot
אם הערך של supportsRebootlessUpdate
הוא true
ב-apex_manifest.json
וגם
APEX המותקן כרגע אינו בשימוש (למשל, כל שירות שהוא מכיל
הופסקה), ניתן להתקין APEX חדש ללא הפעלה מחדש עם
סימון --force-non-staged
.
adb install --force-non-staged apex_file_name
שימוש ב-APEX
לאחר ההפעלה מחדש, ה-APEX נטען ב-/apex/<apex_name>@<version>
אפשר לטעון כמה גרסאות של אותו APEX בו-זמנית.
מבין נתיבי הטעינה, הנתיב שתואם לגרסה האחרונה הוא
מוטמע ב-/apex/<apex_name>
.
לקוחות יכולים להשתמש בנתיב המחובר לקישור כדי לקרוא או להפעיל קבצים מ-APEX.
בדרך כלל משתמשים ב-APEX כך:
- OEM (יצרן ציוד מקורי) או ODM טוען מראש APEX מתחת ל-
/system/apex
כשהמכשיר נשלח. - הגישה לקבצים ב-APEX מתבצעת דרך הנתיב
/apex/<apex_name>/
. - כשמתקינים גרסה מעודכנת של APEX ב-
/data/apex
, הנתיב מצביע ל-APEX החדש לאחר האתחול.
עדכון שירות עם APEX
כדי לעדכן שירות באמצעות APEX:
סימון השירות במחיצת המערכת כניתן לעדכון. הוספת האפשרות
updatable
להגדרת השירות./system/etc/init/myservice.rc: service myservice /system/bin/myservice class core user system ... updatable
יוצרים קובץ
.rc
חדש לשירות המעודכן. שימוש באפשרותoverride
כדי להגדיר מחדש את השירות הקיים./apex/my.apex/etc/init.rc: service myservice /apex/my.apex/bin/myservice class core user system ... override
אפשר להגדיר את הגדרות השירות רק בקובץ .rc
של APEX. Action (פעולה)
טריגרים לא נתמכים ב-APEX.
אם שירות שסומן כניתן לעדכון מתחיל לפני הפעלת ה-APEX, ההפעלה מתעכבת עד להשלמת ההפעלה של APEX.
הגדרת המערכת לתמיכה בעדכוני APEX
צריך להגדיר את מאפיין המערכת הבא לערך true
כדי לתמוך בעדכונים של קובצי APEX.
<device.mk>:
PRODUCT_PROPERTY_OVERRIDES += ro.apex.updatable=true
BoardConfig.mk:
TARGET_FLATTEN_APEX := false
או פשוט
<device.mk>:
$(call inherit-product, $(SRC_TARGET_DIR)/product/updatable_apex.mk)
APEX שטוח
במכשירים מדור קודם, לפעמים לא ניתן או לא ניתן לעדכן את הגרסה הקודמת
ליבה (kernel) לתמיכה מלאה ב-APEX. לדוגמה, יכול להיות שהליבה נוצרה,
בלי CONFIG_BLK_DEV_LOOP=Y
, שהוא חיוני לטעינה של מערכת הקבצים
תמונה בתוך APEX.
APEX שטוחה הוא APEX שנוצר במיוחד, וניתן להפעיל אותו במכשירים עם
ליבה (kernel) מדור קודם. קבצים ב-APEX שטוח מותקנים ישירות בספרייה
במחיצה המובנית. לדוגמה, lib/libFoo.so
בקובץ APEX שטוח
my.apex
מותקנת אצל /system/apex/my.apex/lib/libFoo.so
.
הפעלה של APEX שטוח לא מעורבת במכשיר הלולאה. כל
הספרייה /system/apex/my.apex
מחוברת ישירות אל /apex/name@ver
.
לא ניתן לעדכן גרסאות APEX שטוחות על ידי הורדת גרסאות מעודכנות של APEX מהרשת כי לא ניתן ליישר את ה-APEX שהורדו. אפשר לעדכן אישורי APEX שטוחים רק באמצעות OTA רגיל.
APEX שטוחה היא תצורת ברירת המחדל. המשמעות היא שכל כברירת מחדל, מזהי APEX מוחלטים, אלא אם מגדירים באופן מפורש את המכשיר כדי לבנות APEX לא שטוחים כדי לתמוך בעדכוני APEX (כפי שהוסבר למעלה).
לא ניתן לשלב במכשיר APEX שטוח ולא שטוח
נתמך. נקודות APEX במכשיר צריכות להיות לא שטוחות או ללא שטוחה.
הדבר חשוב במיוחד כאשר משלוח APEX חתום מראש נוצר מראש עבור
כמו Mainline. APEX שאינם חתומים מראש (כלומר, נוצרו
המקור) צריך להיות ללא שטוח ולחתום באמצעות מפתחות מתאימים.
המכשיר צריך לקבל בירושה מupdatable_apex.mk
, כמו שמוסבר
עדכון שירות עם APEX.
APEX דחוס
ב-Android 12 ואילך יש דחיסת APEX עבור צמצום ההשפעה על האחסון של חבילות APEX שניתן לעדכן. לאחר עדכון של APEX מותקנת, למרות שהגרסה שהותקנה מראש כבר לא בשימוש, היא עדיין תופסת כמות זהה של מקום. המרחב המשותף הזה עדיין לא זמין.
דחיסת APEX ממזערת את השפעת האחסון הזו על ידי שימוש בקבוצה דחוסה מאוד
של קובצי APEX במחיצות לקריאה בלבד (כמו המחיצה /system
). במכשירי Android
מגרסה 12 ואילך משתמשים באלגוריתם DEFLATE לדחיסת ZIP.
דחיסה לא מספקת אופטימיזציה לפריטים הבאים:
רצועות אתחול APEX שנדרשות לטעינה בשלב מוקדם מאוד באתחול ברצף.
קובצי APEX שלא ניתנים לעדכון. דחיסה מועילה רק אם מותקנת גרסה מעודכנת של APEX במחיצה
/data
. רשימה מלאה של שרתי APEX שניתנים לעדכון זמינה רכיבים למערכות מודולריות הדף הזה.libs משותפים דינמיים APEX. מכיוון ש-
apexd
תמיד מפעיל את שתי הגרסאות של כאלה של APEX (שהותקנו מראש ושודרגו), דחיסת הנתונים שלהם לא מוסיפה ערך.
פורמט קובץ APEX דחוס
זהו הפורמט של קובץ APEX דחוס.
איור 2. פורמט קובץ APEX דחוס
ברמה העליונה, קובץ APEX דחוס הוא קובץ ZIP שמכיל את הקובץ המקורי קובץ apex בפורמט ללא פילטר עם רמת דחיסה של 9, ועם קבצים אחרים מאוחסנים במצב לא דחוס.
ארבעה קבצים מכילים קובץ APEX:
original_apex
: ללא ניקוז עם רמת דחיסה של 9 זהו קובץ APEX המקורי, הלא דחוס.apex_manifest.pb
: שמור בלבדAndroidManifest.xml
: שמור בלבדapex_pubkey
: שמור בלבד
הקבצים apex_manifest.pb
, AndroidManifest.xml
ו-apex_pubkey
עותקים של הקבצים התואמים שלהם ב-original_apex
.
בניית APEX דחוס
ניתן ליצור APEX דחוס באמצעות הכלי apex_compression_tool.py
שנמצא בכתובת
system/apex/tools
.
במערכת ה-build יש כמה פרמטרים שקשורים לדחיסת APEX.
ב-Android.bp
אפשר לקבוע אם קובץ APEX ניתן לדחיסה נשלט על ידי
מאפיין compressible
:
apex {
name: "apex.test",
manifest: "apex_manifest.json",
file_contexts: "file_contexts",
compressible: true,
}
דגל PRODUCT_COMPRESSED_APEX
קובע אם תמונת מערכת נוצרה
המקור חייב להכיל קובצי APEX דחוסים.
בניסויים מקומיים אפשר לאלץ build לדחוס קובצי APEX באמצעות הגדרה
OVERRIDE_PRODUCT_COMPRESSED_APEX=
עד true
.
לקובצי APEX דחוסים שנוצרו על ידי מערכת ה-build יש את התוסף .capex
.
התוסף מאפשר להבחין בקלות בין נתונים דחוסים ולא דחוסים
של קובץ APEX.
אלגוריתמים נתמכים לדחיסה
ב-Android 12 יש תמיכה רק בדחיסת נתונים מסוג deflate-zip.
הפעלה של קובץ APEX דחוס במהלך האתחול
לפני שניתן להפעיל APEX דחוס, הוא מכיל את הקובץ original_apex
דחוסה בספרייה /data/apex/decompressed
. התוצאה של
קובץ APEX דחוס מקושר לספרייה /data/apex/active
.
הדוגמה הבאה ממחישה את התהליך שמתואר למעלה.
/system/apex/com.android.foo.capex
מוגדר כ-APEX דחוס
מופעלת, עם versionCode 37.
- הקובץ
original_apex
בתוך/system/apex/com.android.foo.capex
הוא מפרקים ל/data/apex/decompressed/com.android.foo@37.apex
. - ביצוע של
restorecon /data/apex/decompressed/com.android.foo@37.apex
מוודאים שיש לו תווית SELinux נכונה. - בדיקות אימות מבוצעות בתאריך
/data/apex/decompressed/com.android.foo@37.apex
כדי לוודא את התוקף שלו:apexd
בודק את המפתח הציבורי בחבילה/data/apex/decompressed/com.android.foo@37.apex
כדי לאמת שהוא שווה לזו שמופיעה בחבילה ב-/system/apex/com.android.foo.capex
. - קיים קישור קשיח אל הקובץ
/data/apex/decompressed/com.android.foo@37.apex
הספרייה/data/apex/active/com.android.foo@37.apex
. - לוגיקת ההפעלה הרגילה לקובצי APEX לא דחוסים מתבצעת
/data/apex/active/com.android.foo@37.apex
אינטראקציה עם OTA
לקובצי APEX דחוסים יש השלכות על העברת OTA ועל האפליקציה. מאז עדכון OTA עשוי להכיל קובץ APEX דחוס עם רמת גרסה גבוהה יותר מאשר במכשיר פעיל במכשיר, יש לשריין כמות מסוימת של שטח פנוי לפני הפעלה מחדש של המכשיר כדי להחיל עדכון OTA.
כדי לתמוך במערכת OTA, apexd
חושף את שני ממשקי ה-API הבאים של binder:
calculateSizeForCompressedApex
– מחשבת את הגודל הנדרש לפתיחת דחיסה קובצי APEX בחבילת OTA. אפשר להשתמש בהרשאה הזו כדי לוודא שלמכשיר יש מספיק מקום כדי להוריד OTA.reserveSpaceForCompressedApex
- שומר מקום בדיסק לשימוש עתידי על ידיapexd
לביטול הדחיסה של קובצי APEX דחוסים בתוך חבילת ה-OTA.
במקרה של עדכון A/B OTA, apexd
ינסה לבטל דחיסה
ברקע כחלק מתרחיש OTA לאחר ההתקנה. אם ביטול הדחיסה נכשל,
apexd
מבצע את פתיחת הדחיסה במהלך האתחול שמחילה את OTA
אילו חלופות עשויות להיות התוצאה של פיתוח APEX
לפניכם כמה אפשרויות שמערכת AOSP השתמשה בהן במהלך העיצוב של קובץ APEX ולמה הן נכללו או לא נכללו.
מערכות לניהול חבילות רגילות
להפצות Linux יש מערכות לניהול חבילות כמו dpkg
ו-rpm
,
עוצמתיים, בוגרים וחזקים. עם זאת, הם לא
מתאימות ל-APEX מכיוון שהן לא יכולות להגן על החבילות לאחר
בתהליך ההתקנה. האימות מתבצע רק כאשר מתקינים חבילות.
תוקפים יכולים לשבור את התקינות של החבילות המותקנות, מבלי להבחין בהן. הדבר
רגרסיה ב-Android שבה כל רכיבי המערכת אוחסנו במצב קריאה בלבד
של מערכות קבצים שהתקינות שלהן מוגנת באמצעות dm-verity לכל קלט/פלט (I/O). כלשהו
פגיעה ברכיבי המערכת חייבת להיות אסורה או להיות גלויה,
שהמכשיר יכול לסרב לבצע את ההפעלה אם הוא נפרץ.
dm-crypt לתקינות
הקבצים בקונטיינר APEX הם ממחיצות מובנות (לדוגמה,
/system
) שמוגנות באמצעות dm-verity, כאשר כל שינוי של
הקבצים אסורים גם לאחר טעינת המחיצות. כדי לספק את
אותה רמת אבטחה לקבצים, כל הקבצים ב-APEX מאוחסנים בקובץ
קובץ אימג' שמתאים לעץ גיבוב ולמתאר vbmeta. ללא
dm-verity, APEX במחיצה /data
חשוף לגורמים לא רצויים
שמבוצעים לאחר שהוא מאומת והתקין.
למעשה, המחיצה /data
מוגנת גם באמצעות שכבות הצפנה כמו
dm-crypt. למרות שהפעולה הזו מספקת רמה מסוימת של הגנה מפני פגיעה,
המטרה העיקרית היא פרטיות, ולא שלמות. כשתוקף מקבל גישה
המחיצה /data
, לא ניתן להיות הגנה נוספת, ושוב,
רגרסיה בהשוואה לכל רכיב מערכת שנמצא במחיצה /system
.
עץ הגיבוב (hash) שבתוך קובץ APEX יחד עם dm-verity מספק
רמת הגנה על התוכן.
הפניה אוטומטית של נתיבים מ- /system אל /apex
ניתן לגשת לקבצים של רכיבי מערכת שנארזים ב-APEX דרך נתיבים חדשים כמו
/apex/<name>/lib/libfoo.so
כשהקבצים היו חלק מ/system
קטגוריה, הם היו נגישים דרך נתיבים כמו /system/lib/libfoo.so
. א'
של קובץ APEX (קובצי APEX אחרים או הפלטפורמה) חייבים להשתמש
. יכול להיות שתצטרכו לעדכן קוד קיים בגלל שינוי הנתיב.
למרות שאחת הדרכים להימנע משינוי הנתיב היא להציג את תוכן הקובץ בשכבת-על
קובץ APEX למחיצה /system
והצוות של Android החליט לא ליצור שכבת-על
קבצים במחיצה /system
, כי זה יכול להשפיע על הביצועים כמו
מספר הקבצים בשכבת-על (כנראה אפילו מוערם אחד אחרי השני)
עלייה.
אפשרות נוספת הייתה לפרוץ פונקציות גישה לקבצים כמו open
, stat
ו
readlink
, כך שנתיבים המתחילים ב-/system
הופנו אל
הנתיבים התואמים בתוך /apex
. צוות Android מחק את האפשרות הזו
כי לא ניתן לשנות את כל הפונקציות שמקבלות נתיבים.
לדוגמה, אפליקציות מסוימות מקשרות באופן סטטי ל-Bionic, שם האפליקציה שמטמיעה את הפונקציות.
במקרים כאלה, האפליקציות האלה לא יופנו לכתובת אחרת.