ذخیره APK

این سند طراحی یک راه حل ذخیره APK را برای نصب سریع برنامه های از پیش بارگذاری شده در دستگاهی که از پارتیشن های A/B پشتیبانی می کند، توضیح می دهد.

OEM ها می توانند پیش بارگذاری ها و برنامه های محبوب را در حافظه پنهان APK ذخیره شده در پارتیشن B عمدتاً خالی در دستگاه های جدید پارتیشن بندی شده A/B بدون تأثیر بر فضای داده رو به روی کاربر قرار دهند. با در دسترس داشتن حافظه پنهان APK در دستگاه، دستگاه های جدید یا اخیراً تنظیم مجدد کارخانه تقریباً بلافاصله آماده استفاده می شوند، بدون نیاز به دانلود فایل های APK از Google Play.

موارد استفاده کنید

  • برای راه اندازی سریعتر، برنامه های از پیش بارگذاری شده را در پارتیشن B ذخیره کنید
  • برای بازیابی سریعتر برنامه های محبوب را در پارتیشن B ذخیره کنید

پیش نیازها

برای استفاده از این ویژگی، دستگاه به موارد زیر نیاز دارد:

  • نسخه اندروید 8.1 (O MR1) نصب شده است
  • پارتیشن A/B پیاده سازی شد

محتوای از پیش بارگذاری شده فقط در اولین بوت قابل کپی است. این به این دلیل است که در دستگاه‌هایی که از به‌روزرسانی‌های سیستم A/B پشتیبانی می‌کنند، پارتیشن B در واقع فایل‌های تصویری سیستم را ذخیره نمی‌کند، بلکه محتوای از پیش بارگذاری‌شده مانند منابع نمایشی خرده‌فروشی، فایل‌های OAT و حافظه پنهان APK را ذخیره می‌کند. پس از کپی شدن منابع در پارتیشن /data (این اتفاق در اولین راه‌اندازی رخ می‌دهد)، پارتیشن B توسط به‌روزرسانی‌های هوایی (OTA) برای دانلود نسخه‌های به‌روز شده تصویر سیستم استفاده می‌شود.

بنابراین، کش APK را نمی توان از طریق OTA به روز کرد. فقط در یک کارخانه می توان آن را از قبل بارگذاری کرد. بازنشانی کارخانه فقط بر پارتیشن /data تأثیر می گذارد. تا زمانی که تصویر OTA دانلود نشود، پارتیشن سیستم B همچنان محتوای از پیش بارگذاری شده را دارد. پس از بازنشانی به تنظیمات کارخانه، سیستم دوباره بوت اول را انجام می دهد. این بدان معناست که اگر تصویر OTA در پارتیشن B دانلود شود و سپس دستگاه به حالت کارخانه بازنشانی شود، ذخیره APK در دسترس نیست.

پیاده سازی

رویکرد 1. مطالب در پارتیشن system_other

حرفه ای : محتوای از پیش بارگذاری شده پس از تنظیم مجدد کارخانه از بین نمی رود - پس از راه اندازی مجدد از پارتیشن B کپی می شود.

Con : به فضای روی پارتیشن B نیاز دارد. راه‌اندازی پس از بازنشانی کارخانه به زمان بیشتری برای کپی کردن محتوای از پیش بارگذاری شده نیاز دارد.

برای اینکه پیش بارگذاری ها در اولین بوت کپی شوند، سیستم یک اسکریپت را در /system/bin/preloads_copy.sh فراخوانی می کند. اسکریپت با یک آرگومان واحد فراخوانی می شود (مسیر به نقطه نصب فقط خواندنی برای پارتیشن system_b ):

برای پیاده سازی این ویژگی، این تغییرات خاص دستگاه را انجام دهید. در اینجا یک مثال از مارلین است:

  1. اسکریپتی را که کپی را انجام می دهد به فایل device-common.mk اضافه کنید (در این مورد، device/google/marlin/device-common.mk )، مانند این:
    # 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
    
    منبع اسکریپت نمونه را در: device/google/marlin بیابید /preloads_copy.sh
  2. فایل 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 بیابید
  3. یک دامنه SELinux جدید در فایل preloads_copy.te تعریف کنید:
    type 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;
    
    نمونه فایل دامنه SELinux را در: /device/google/marlin/+/main/sepolicy/preloads_copy.te بیابید
  4. دامنه را در یک دامنه جدید ثبت کنید فایل /sepolicy/file_contexts :
    /system/bin/preloads_copy\.sh     u:object_r:preloads_copy_exec:s0
    
    نمونه فایل متنی SELinux را در: device/google/marlin/sepolicy/preloads_copy.te بیابید
  5. در زمان ساخت، دایرکتوری با محتوای از پیش بارگذاری شده باید در پارتیشن system_other کپی شود:
    # 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)
    
    این نمونه ای از تغییر در Makefile است که امکان کپی کردن منابع حافظه پنهان APK از مخزن Git فروشنده را فراهم می کند (در مورد ما فروشنده/google_devices/ بود. marlin/preloads) به مکان روی پارتیشن system_other که بعداً وقتی دستگاه برای اولین بار بوت می شود در /data/preloads کپی می شود. این اسکریپت در زمان ساخت اجرا می شود تا تصویر system_other آماده شود. انتظار دارد محتوای از پیش بارگذاری شده در vendor/google_devices/marlin/preloads در دسترس باشد. OEM در انتخاب نام/مسیر مخزن واقعی آزاد است.
  6. حافظه پنهان APK در /data/preloads/file_cache قرار دارد و دارای طرح‌بندی زیر است:
    /data/preloads/file_cache/
        app.package.name.1/
              file1
              fileN
        app.package.name.N/
    
    این ساختار فهرست نهایی در دستگاه‌ها است. OEM ها در انتخاب هر رویکرد پیاده سازی آزاد هستند تا زمانی که ساختار فایل نهایی همان چیزی که در بالا توضیح داده شد تکرار کند.

رویکرد 2. محتوای موجود در تصویر اطلاعات کاربر در کارخانه فلش شد

این رویکرد جایگزین فرض می‌کند که محتوای از پیش بارگذاری شده از قبل در فهرست /data/preloads در پارتیشن /data گنجانده شده است.

حرفه ای : خارج از جعبه کار می کند - نیازی به سفارشی سازی دستگاه برای کپی فایل ها در اولین بوت نیست. محتوا در حال حاضر در پارتیشن /data است.

Con : محتوای از پیش بارگذاری شده پس از بازنشانی به تنظیمات کارخانه از بین می رود. اگرچه این ممکن است برای برخی قابل قبول باشد، اما ممکن است همیشه برای OEM هایی که پس از انجام بازرسی های کنترل کیفیت، دستگاه ها را به حالت کارخانه بازنشانی می کنند، کارساز نباشد.

یک روش جدید @SystemApi، getPreloadsFileCache() به android.content.Context اضافه شد. یک مسیر مطلق را به دایرکتوری مخصوص برنامه در حافظه پنهان از پیش بارگذاری شده برمی گرداند.

روش جدیدی به IPackageManager.deletePreloadsFileCache اضافه شد که به حذف فهرست پیش‌بارگذاری‌ها اجازه می‌دهد تا تمام فضا را بازیابی کنید. این روش را فقط می‌توان توسط برنامه‌های دارای SYSTEM_UID، یعنی سرور سیستم یا تنظیمات فراخوانی کرد.

آماده سازی اپلیکیشن

فقط برنامه های دارای امتیاز می توانند به دایرکتوری کش پیش بارگیری دسترسی داشته باشند. برای این دسترسی، برنامه ها باید در پوشه /system/priv-app نصب شوند.

اعتبار سنجی

  • پس از اولین بوت، دستگاه باید محتوایی در پوشه /data/preloads/file_cache داشته باشد.
  • اگر فضای ذخیره‌سازی دستگاه کم است، محتوای موجود در فهرست file_cache/ باید حذف شود.

از برنامه ApkCacheTest مثال برای آزمایش کش APK استفاده کنید.

  1. برنامه را با اجرای این دستور از دایرکتوری ریشه بسازید:
    make ApkCacheTest
    
  2. برنامه را به عنوان یک برنامه ممتاز نصب کنید. (به یاد داشته باشید، فقط برنامه‌های دارای امتیاز می‌توانند به حافظه پنهان 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
    
  3. دایرکتوری کش فایل و محتوای آن را در صورت نیاز شبیه سازی کنید (همچنین به حقوق ریشه نیاز دارد):
    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"
    
  4. برنامه را تست کنید. پس از نصب برنامه و ایجاد دایرکتوری test file_cache ، برنامه ApkCacheTest را باز کنید. باید یک فایل test.txt و محتویات آن را نشان دهد. برای مشاهده نحوه نمایش این نتایج در رابط کاربری، این اسکرین شات را ببینید.

    شکل 1. نتایج ApkCacheTest