במסמך הזה מתואר עיצוב של פתרון לשמירת 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). מחיצת המערכת B עדיין מכילה את התוכן שנטען מראש עד להורדת קובץ האימג' של ה-OTA. אחרי איפוס להגדרות המקוריות, המערכת תעבור שוב את תהליך האתחול הראשון. כלומר, אחסון במטמון של קובצי 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/+/android16-release/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
- בזמן הבנייה, צריך להעתיק את הספרייה עם התוכן שנטען מראש למחיצה
system_other
: זוהי דוגמה לשינוי בקובץ Makefile שמאפשר להעתיק משאבי מטמון של קובצי APK ממאגר Git של הספק (במקרה שלנו, vendor/google_devices/marlin/preloads) למיקום במחיצה system_other שיועתק מאוחר יותר אל /data/preloads כשהמכשיר יופעל בפעם הראשונה. הסקריפט הזה פועל בזמן הבנייה כדי להכין את התמונה system_other. היא מצפה שתוכן שנטען מראש יהיה זמין ב-vendor/google_devices/marlin/preloads. יצרן ציוד מקורי (OEM) יכול לבחור את השם או הנתיב של המאגר בפועל.# 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
.
חיסרון: התוכן שנטען מראש יימחק אחרי איפוס להגדרות המקוריות. יכול להיות שזה מקובל על חלק מהיצרנים, אבל לא תמיד זה מתאים ליצרני ציוד מקורי (OEM) שמבצעים איפוס להגדרות המפעל במכשירים אחרי בדיקות בקרת איכות.
נוספה שיטה חדשה של @SystemApi, getPreloadsFileCache()
, אל android.content.Context
. היא מחזירה נתיב מוחלט לספרייה ספציפית לאפליקציה במטמון שנטען מראש.
נוספה שיטה חדשה, IPackageManager.deletePreloadsFileCache
, שמאפשרת למחוק את ספריית הטעינות מראש כדי לפנות את כל המקום. אפשר להפעיל את ה-method רק באפליקציות עם SYSTEM_UID, כלומר בשרת המערכת או בהגדרות.
הכנת האפליקציה
רק לאפליקציות עם הרשאות מיוחדות יש גישה לספריית המטמון של הטעינות מראש. כדי לקבל גישה כזו, צריך להתקין את האפליקציות בספרייה /system/priv-app
.
אימות
- אחרי ההפעלה הראשונה, אמור להיות תוכן בספרייה
/data/preloads/file_cache
במכשיר. - אם נפח האחסון במכשיר נמוך, התוכן בספרייה
file_cache/
יימחק.
אפשר להשתמש באפליקציה לדוגמה ApkCacheTest כדי לבדוק את מטמון ה-APK.
- מריצים את הפקודה הבאה מהספרייה הבסיסית כדי ליצור את האפליקציה:
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.