במסמך הזה מתוארת תכנון של פתרון אחסון במטמון של קובצי APK להתקנה מהירה של אפליקציות שהועמסו מראש במכשיר שתומך במחיצות A/B.
יצרני ציוד מקורי יכולים להציב אפליקציות פופולריות ואפליקציות שהועלו מראש במטמון ה-APK שמאוחסן במחיצה B, שבדרך כלל ריקה, במכשירים חדשים עם מחיצה A/B, בלי להשפיע על מרחב הנתונים שגלוי למשתמשים. כשיש במכשיר מטמון של חבילות APK, מכשירים חדשים או מכשירים שהוחזרו לאחרונה להגדרות המקוריות מוכנים לשימוש כמעט באופן מיידי, בלי צורך להוריד קובצי APK מ-Google Play.
תרחישים לדוגמה
- אחסון אפליקציות שהוגדרו מראש במחיצה B כדי לזרז את ההגדרה
- אחסון אפליקציות פופולריות במחיצה B לצורך שחזור מהיר יותר
דרישות מוקדמות
כדי להשתמש בתכונה הזו, המכשיר צריך:
- גרסת Android 8.1 (O MR1) מותקנת
- מחיצה מסוג A/B הוטמעה
אפשר להעתיק תוכן טעון מראש רק במהלך ההפעלה הראשונה. הסיבה לכך היא שבמכשירים שתומכים בעדכוני מערכת מסוג A/B, המחיצה B לא מאחסנת קובצי אימג' של מערכת, אלא תוכן טעון מראש כמו משאבי הדגמה לקמעונאים, קובצי OAT ומטמון ה-APK. אחרי שהמשאבים יועתקו למחיצה /data (הדבר קורה בהפעלה הראשונה), מחיצה B תשמש לעדכונים אוויריים (OTA) להורדת גרסאות מעודכנות של קובץ האימג' של המערכת.
לכן, לא ניתן לעדכן את המטמון של קובץ ה-APK באמצעות OTA, אלא רק לטעון אותו מראש במפעל. איפוס להגדרות המקוריות משפיע רק על המחיצה /data. עד להורדת קובץ האימג' ב-OTA, התוכן שהוטען מראש עדיין נמצא במחיצה B של המערכת. אחרי האיפוס להגדרות המקוריות, המערכת תעבור שוב את ההפעלה הראשונה. כלומר, האחסון במטמון של קובצי APK לא זמין אם קובץ האימג' של ה-OTA מוריד למחיצה B, ואז המכשיר מאופס להגדרות המקוריות.
הטמעה
גישה 1. תוכן במחיצה system_other
יתרון: התוכן שהורדתם מראש לא יימחק אחרי איפוס להגדרות המקוריות – הוא יועתק מהמחיצה B אחרי הפעלה מחדש.
חסרון: נדרש מקום במחיצה B. כדי להפעיל את המכשיר אחרי איפוס להגדרות המקוריות, נדרש זמן נוסף להעתקת התוכן שהוכן מראש.
כדי שהקבצים שנטענו מראש יועתקו במהלך האתחול הראשון, המערכת מפעילה סקריפט ב-/system/bin/preloads_copy.sh
. קוראים לסקריפט עם ארגומנט יחיד (הנתיב לנקודת הטעינה לקריאה בלבד של המחיצה system_b
):
כדי להטמיע את התכונה הזו, צריך לבצע את השינויים האלה שספציפיים למכשיר. הנה דוגמה מ-Marlin:
- מוסיפים את הסקריפט שמבצע את ההעתקה לקובץ
device-common.mk
(במקרה הזה,device/google/marlin/device-common.mk
), כך: מקור לדוגמה של סקריפט: device/google/marlin/preloads_copy.sh# Script that copies preloads directory from system_other to data partition PRODUCT_COPY_FILES += \ device/google/marlin/preloads_copy.sh:system/bin/preloads_copy.sh
- עורכים את הקובץ
init.common.rc
כדי שיצור את הספרייה/data/preloads
ואת תיקיות המשנה הנדרשות: מקור לדוגמה של קובץmkdir /data/preloads 0775 system system
mkdir /data/preloads/media 0775 system system
mkdir /data/preloads/demo 0775 system system
init
נמצא בכתובת: device/google/marlin/init.common.rc - מגדירים דומיין SELinux חדש בקובץ
preloads_copy.te
: קובץ דוגמאות של דומיין SELinux נמצא בכתובת: /device/google/marlin/+/main/sepolicy/preloads_copy.tetype preloads_copy, domain, coredomain; type preloads_copy_exec, exec_type, vendor_file_type, file_type; init_daemon_domain(preloads_copy) allow preloads_copy shell_exec:file rx_file_perms; allow preloads_copy toolbox_exec:file rx_file_perms; allow preloads_copy preloads_data_file:dir create_dir_perms; allow preloads_copy preloads_data_file:file create_file_perms; allow preloads_copy preloads_media_file:dir create_dir_perms; allow preloads_copy preloads_media_file:file create_file_perms; # Allow to copy from /postinstall allow preloads_copy system_file:dir r_dir_perms;
- רושמים את הדומיין בקובץ
חדש:/sepolicy/file_contexts קובץ לדוגמה של הקשרים של SELinux נמצא בכתובת: device/google/marlin/sepolicy/preloads_copy.te/system/bin/preloads_copy\.sh u:object_r:preloads_copy_exec:s0
- בזמן ה-build, צריך להעתיק את הספרייה עם התוכן שהוטען מראש למחיצה
system_other
: זוהי דוגמה לשינוי ב-Makefile שמאפשר להעתיק משאבי מטמון של APK ממאגר ה-Git של הספק (במקרה שלנו, זה היה vendor/google_devices/marlin/preloads) למיקום במחיצה system_other, שיועתק מאוחר יותר אל /data/preloads כשהמכשיר יופעל בפעם הראשונה. הסקריפט הזה פועל בזמן ה-build כדי להכין את קובץ האימג' system_other. התוכן שנטען מראש אמור להיות זמין בכתובת vendor/google_devices/marlin/preloads. יצרני הציוד המקורי יכולים לבחור את השם או הנתיב של המאגר בפועל.# Copy contents of preloads directory to system_other partition PRODUCT_COPY_FILES += \ $(call find-copy-subdir-files,*,vendor/google_devices/marlin/preloads,system_other/preloads)
- המטמון של קובצי ה-APK נמצא ב-
/data/preloads/file_cache
, והוא בפריסה הבאה: זהו מבנה הספרייה הסופי במכשירים. יצרני ציוד מקורי יכולים לבחור כל גישה להטמעה, כל עוד מבנה הקובץ הסופי משקף את המבנה שמתואר למעלה./data/preloads/file_cache/ app.package.name.1/ file1 fileN app.package.name.N/
גישה 2. תוכן בתמונה של נתוני משתמשים שעבר פלאש במפעל
הגישה החלופית הזו מבוססת על ההנחה שהתוכן שהוטען מראש כבר נכלל בספרייה /data/preloads
במחיצה /data
.
יתרון: פועלת מתוך האריזה – אין צורך לבצע התאמות אישיות במכשיר כדי להעתיק קבצים בהפעלה הראשונה. התוכן כבר נמצא במחיצה /data
.
חסרון: התוכן שהורדתם מראש יימחק אחרי איפוס להגדרות המקוריות. יכול להיות שזה יתאים לחלק מהאנשים, אבל זה לא תמיד מתאים ליצרני ציוד מקורי שמאפסים את המכשירים להגדרות המקוריות אחרי בדיקות בקרת איכות.
נוספה שיטה חדשה של @SystemApi, getPreloadsFileCache()
, ל-android.content.Context
. הפונקציה מחזירה נתיב מוחלט לספרייה ספציפית לאפליקציה במטמון שהוטען מראש.
הוספנו שיטה חדשה, IPackageManager.deletePreloadsFileCache
, שמאפשרת למחוק את ספריית הטעינה המקדימה כדי לפנות את כל האחסון. רק אפליקציות עם SYSTEM_UID יכולות להפעיל את השיטה, כלומר שרת המערכת או אפליקציית ההגדרות.
הכנת האפליקציה
רק אפליקציות עם הרשאות יכולות לגשת לספריית המטמון של פריטים שהועלו מראש. כדי לקבל גישה כזו, צריך להתקין את האפליקציות בספרייה /system/priv-app
.
אימות
- אחרי ההפעלה הראשונה, צריך להיות תוכן בספרייה
/data/preloads/file_cache
במכשיר. - אם במכשיר נגמר נפח האחסון, צריך למחוק את התוכן בתיקייה
file_cache/
.
משתמשים באפליקציית הדוגמה ApkCacheTest כדי לבדוק את המטמון של קובצי ה-APK.
- מריצים את הפקודה הבאה מהספרייה ברמה הבסיסית (root) כדי ליצור את האפליקציה:
make ApkCacheTest
- מתקינים את האפליקציה כאפליקציה בעלת הרשאות. (חשוב לזכור שרק אפליקציות בעלות הרשאות יכולות לגשת למטמון ה-APK).
לשם כך נדרש מכשיר עם הרשאות בסיס:
adb root && adb remount
adb shell mkdir /system/priv-app/ApkCacheTest
adb push $ANDROID_PRODUCT_OUT/data/app/ApkCacheTest/ApkCacheTest.apk /system/priv-app/ApkCacheTest/
adb shell stop && adb shell start
- אם צריך, אפשר לדמות את ספריית המטמון של הקבצים ואת התוכן שלה (נדרשות גם הרשאות root):
adb shell mkdir -p /data/preloads/file_cache/com.android.apkcachetest
adb shell restorecon -r /data/preloads
adb shell "echo "Test File" > /data/preloads/file_cache/com.android.apkcachetest/test.txt"
- בודקים את האפליקציה. אחרי התקנת האפליקציה ויצירת ספריית הבדיקה
file_cache
, פותחים את האפליקציה ApkCacheTest. אמור להופיע קובץ אחדtest.txt
והתוכן שלו. בצילום המסך הזה אפשר לראות איך התוצאות האלה מופיעות בממשק המשתמש.
איור 1. תוצאות הבדיקה של ApkCacheTest.