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 分割區實際上並不會儲存系統映像文件,而是預先載入的內容,例如零售演示資源、OAT 檔案和 APK 快取。將資源複製到 /data 分割區後(首次啟動時會發生這種情況),無線 (OTA) 更新將使用 B 分割區來下載系統映像的更新版本。

因此APK快取無法透過OTA更新;它只能在工廠預先加載。恢復出廠設定僅影響 /data 分割區。在下載 OTA 映像之前,系統 B 分割區仍具有預先載入的內容。恢復出廠設定後,系統將再次進行首次啟動。這表示如果 OTA 映像下載到 B 分割區,然後裝置恢復原廠設置,則 APK 快取不可用。

執行

方法1.system_other分區上的內容

優點:預先載入的內容在恢復原廠設定後不會遺失 - 重新啟動後將從 B 分割區複製。

缺點:需要 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. 在檔案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 中的變更範例,允許從供應商的Git 儲存庫複製APK 快取資源(在我們的範例中為vendor/google_devices /) marlin/preloads) 到 system_other 分區上的位置,稍後在裝置首次啟動時將其複製到 /data/preloads。該腳本在建置時運行以準備 system_other 映像。它期望預先載入的內容在供應商/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分割區上的/data/preloads目錄中。

優點:開箱即用 - 無需進行裝置自訂即可在首次啟動時複製檔案。內容已位於/data分割區上。

缺點:恢復出廠設定後預先載入的內容會遺失。雖然這對某些人來說可能是可以接受的,但對於在進行品質控制檢查後對設備進行出廠重置的 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 快取。)這需要 root 裝置:
    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. 如果需要,模擬檔案快取目錄及其內容(也需要 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"
    
  4. 測試應用程式。安裝應用程式並建立測試file_cache目錄後,開啟 ApkCacheTest 應用程式。它應該顯示一個檔案test.txt及其內容。請參閱此螢幕截圖,以了解這些結果如何顯示在使用者介面中。

    圖 1. ApkCacheTest 結果