APK कैश मेमोरी

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

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

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

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

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

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

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

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

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

लागू करना

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

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

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

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

इस सुविधा को लागू करने के लिए, डिवाइस के हिसाब से ये बदलाव करें. 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/+/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 रिपॉज़िटरी (हमारे मामले में, यह vendor/google_devices/marlin/preloads था) से system_other partition पर कॉपी करने की अनुमति मिलती है. बाद में, डिवाइस के पहली बार बूट होने पर, इन्हें /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, लागू करने का कोई भी तरीका चुन सकते हैं. हालांकि, यह ज़रूरी है कि फ़ाइल का आखिरी स्ट्रक्चर, ऊपर बताए गए स्ट्रक्चर जैसा ही हो.

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

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

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

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

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

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

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

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

पुष्टि करें

  • डिवाइस को पहली बार बूट करने के बाद, /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 के नतीजे.