APK को कैश मेमोरी में सेव करना

इस दस्तावेज़ में, APK कैश मेमोरी में सेव करने के समाधान के डिज़ाइन के बारे में बताया गया है. इससे, A/B पार्टीशन की सुविधा वाले डिवाइस पर पहले से लोड किए गए ऐप्लिकेशन को तेज़ी से इंस्टॉल किया जा सकता है.

OEM, प्रीलोड और लोकप्रिय ऐप्लिकेशन को APK कैश में रख सकते हैं. यह कैश, नए A/B-पार्टिशन वाले डिवाइसों के B पार्टिशन में सेव होता है. इससे उपयोगकर्ता के डेटा स्पेस पर कोई असर नहीं पड़ता. डिवाइस पर APK कैश मेमोरी उपलब्ध होने से, नए या हाल ही में फ़ैक्ट्री रीसेट किए गए डिवाइसों का इस्तेमाल तुरंत शुरू किया जा सकता है. इसके लिए, Google Play से APK फ़ाइलें डाउनलोड करने की ज़रूरत नहीं होती.

इस्तेमाल के उदाहरण

  • तेज़ी से सेटअप करने के लिए, पहले से लोड किए गए ऐप्लिकेशन को B पार्टीशन में सेव करें
  • तेज़ी से रीस्टोर करने के लिए, लोकप्रिय ऐप्लिकेशन को B पार्टीशन में सेव करें

ज़रूरी शर्तें

इस सुविधा का इस्तेमाल करने के लिए, डिवाइस में ये ज़रूरी शर्तें पूरी होनी चाहिए:

  • Android 8.1 (O MR1) रिलीज़ इंस्टॉल की गई हो
  • A/B पार्टीशन लागू किया गया

प्रीलोड किए गए कॉन्टेंट को सिर्फ़ पहली बार बूट करने के दौरान कॉपी किया जा सकता है. ऐसा इसलिए होता है, क्योंकि A/B सिस्टम अपडेट की सुविधा वाले डिवाइसों पर, B पार्टीशन में सिस्टम इमेज फ़ाइलें सेव नहीं होती हैं. इसके बजाय, इसमें पहले से लोड किया गया कॉन्टेंट सेव होता है. जैसे, खुदरा स्टोर में डेमो के लिए उपलब्ध संसाधन, ओएटी फ़ाइलें, और APK कैश. संसाधन /data पार्टीशन में कॉपी होने के बाद (यह पहली बार बूट करने पर होता है), B पार्टीशन का इस्तेमाल ओवर-द-एयर (OTA) अपडेट के लिए किया जाएगा. इससे सिस्टम इमेज के अपडेट किए गए वर्शन डाउनलोड किए जा सकेंगे.

इसलिए, ओटीए के ज़रिए APK कैश को अपडेट नहीं किया जा सकता. इसे सिर्फ़ फ़ैक्ट्री में पहले से लोड किया जा सकता है. फ़ैक्ट्री रीसेट से सिर्फ़ /data पार्टीशन पर असर पड़ता है. OTA इमेज डाउनलोड होने तक, सिस्टम B पार्टीशन में पहले से लोड किया गया कॉन्टेंट मौजूद रहता है. फ़ैक्ट्री रीसेट के बाद, सिस्टम फिर से बूट होगा. इसका मतलब है कि अगर OTA इमेज को B पार्टीशन में डाउनलोड किया जाता है और फिर डिवाइस को फ़ैक्ट्री रीसेट किया जाता है, तो APK कैशिंग की सुविधा उपलब्ध नहीं होती.

लागू करना

पहला तरीका. system_other पार्टीशन पर मौजूद कॉन्टेंट

Pro: फ़ैक्ट्री रीसेट करने के बाद, पहले से लोड किया गया कॉन्टेंट नहीं मिटता. रीबूट करने के बाद, इसे B पार्टीशन से कॉपी किया जाएगा.

नुकसान: इसके लिए, B पार्टिशन पर जगह खाली होनी चाहिए. फ़ैक्ट्री रीसेट के बाद बूट होने में ज़्यादा समय लगता है, क्योंकि पहले से लोड किए गए कॉन्टेंट को कॉपी करने में समय लगता है.

पहली बार बूट होने के दौरान प्रीलोड कॉपी करने के लिए, सिस्टम /system/bin/preloads_copy.sh में मौजूद स्क्रिप्ट को कॉल करता है. स्क्रिप्ट को एक ही आर्ग्युमेंट के साथ कॉल किया जाता है. यह आर्ग्युमेंट, system_b पार्टीशन के लिए, सिर्फ़ पढ़ने के लिए उपलब्ध माउंट पॉइंट का पाथ होता है:

इस सुविधा को लागू करने के लिए, डिवाइस के हिसाब से ये बदलाव करें. Marlin का उदाहरण यहां दिया गया है:

  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. फ़ाइल preloads_copy.te में नया SELinux डोमेन तय करें:
    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/+/android16-release/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 में किए गए बदलाव का उदाहरण है. इससे, वेंडर की Git रिपॉज़िटरी (हमारे मामले में यह vendor/google_devices/marlin/preloads थी) से APK कैश संसाधनों को system_other पार्टीशन पर कॉपी किया जा सकता है. बाद में, जब डिवाइस पहली बार बूट होगा, तब इन्हें /data/preloads पर कॉपी किया जाएगा. यह स्क्रिप्ट, सिस्टम_अदर इमेज तैयार करने के लिए, बिल्ड टाइम पर चलती है. यह वेंडर/google_devices/marlin/preloads में प्रीलोड किए गए कॉन्टेंट के उपलब्ध होने की उम्मीद करता है. ओईएम के पास, रिपॉज़िटरी का असली नाम/पाथ चुनने का विकल्प होता है.
  6. APK कैश /data/preloads/file_cache में मौजूद होता है और इसका लेआउट इस तरह होता है:
    /data/preloads/file_cache/
        app.package.name.1/
              file1
              fileN
        app.package.name.N/
    
    यह डिवाइसों पर फ़ाइनल डायरेक्ट्री स्ट्रक्चर है. ओईएम के पास, लागू करने का कोई भी तरीका चुनने का विकल्प होता है. हालांकि, फ़ाइनल फ़ाइल का स्ट्रक्चर ऊपर बताए गए स्ट्रक्चर जैसा होना चाहिए.

दूसरा तरीका. उपयोगकर्ता के डेटा पर मौजूद कॉन्टेंट फ़ैक्ट्री में फ़्लैश की गई इमेज

इस वैकल्पिक तरीके में यह माना जाता है कि प्रीलोड किया गया कॉन्टेंट, /data पार्टीशन पर मौजूद /data/preloads डायरेक्ट्री में पहले से शामिल है.

फ़ायदा: यह सुविधा तुरंत काम करती है. पहली बार बूट करने पर, फ़ाइलों को कॉपी करने के लिए डिवाइस को पसंद के मुताबिक बनाने की ज़रूरत नहीं होती. यह कॉन्टेंट, /data पार्टीशन में पहले से मौजूद है.

नुकसान: फ़ैक्ट्री रीसेट करने के बाद, प्रीलोड किया गया कॉन्टेंट मिट जाता है. कुछ लोगों के लिए यह तरीका ठीक हो सकता है. हालांकि, यह उन ओईएम के लिए हमेशा काम नहीं करता जो क्वालिटी कंट्रोल की जांच करने के बाद, डिवाइसों को फ़ैक्ट्री रीसेट करते हैं.

android.content.Context में एक नया @SystemApi तरीका, getPreloadsFileCache(), जोड़ा गया है. यह प्रीलोड की गई कैश मेमोरी में, ऐप्लिकेशन के हिसाब से तय की गई डायरेक्ट्री का पूरा पाथ दिखाता है.

IPackageManager.deletePreloadsFileCache नाम का एक नया तरीका जोड़ा गया है. इसकी मदद से, प्रीलोड डायरेक्ट्री को मिटाया जा सकता है, ताकि पूरा स्पेस वापस पाया जा सके. इस तरीके को सिर्फ़ SYSTEM_UID वाले ऐप्लिकेशन कॉल कर सकते हैं. जैसे, सिस्टम सर्वर या सेटिंग.

ऐप्लिकेशन तैयार करना

सिर्फ़ खास ऐप्लिकेशन, प्रीलोड की गई कैश मेमोरी वाली डायरेक्ट्री को ऐक्सेस कर सकते हैं. इसके लिए, ऐप्लिकेशन को /system/priv-app डायरेक्ट्री में इंस्टॉल किया जाना चाहिए.

Validation

  • पहली बार बूट करने के बाद, डिवाइस में /data/preloads/file_cache डायरेक्ट्री में कॉन्टेंट होना चाहिए.
  • अगर डिवाइस में स्टोरेज कम है, तो file_cache/ डायरेक्ट्री में मौजूद कॉन्टेंट को मिटा देना चाहिए.

APK कैश की जांच करने के लिए, ApkCacheTest ऐप्लिकेशन के उदाहरण का इस्तेमाल करें.

  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. ऐप्लिकेशन की जांच करें. ऐप्लिकेशन इंस्टॉल करने और टेस्ट file_cache डायरेक्ट्री बनाने के बाद, ApkCacheTest ऐप्लिकेशन खोलें. इसमें एक फ़ाइल test.txt और उसका कॉन्टेंट दिखना चाहिए. यूज़र इंटरफ़ेस में ये नतीजे कैसे दिखते हैं, यह देखने के लिए यह स्क्रीनशॉट देखें.

    पहली इमेज. ApkCacheTest के नतीजे.