APK緩存

本文檔描述了一種 APK 緩存解決方案的設計,用於在支持 A/B 分區的設備上快速安裝預加載的應用程序。

OEM 可以將預加載和流行的應用程序放在存儲在新A/B 分區設備上大部分為空的 B 分區中的 APK 緩存中,而不會影響任何面向用戶的數據空間。通過在設備上提供 APK 緩存,新的或最近恢復出廠設置的設備幾乎可以立即使用,而無需從 Google Play 下載 APK 文件。

用例

  • 將預加載的應用程序存儲在 B 分區中以加快設置速度
  • 將流行的應用程序存儲在 B 分區中以更快地恢復

先決條件

要使用此功能,設備需要:

  • 已安裝 Android 8.1 (O MR1) 版本
  • 實現了 A/B 分區

預加載的內容只能在首次啟動時復制。這是因為在支持 A/B 系統更新的設備上,B 分區實際上並不存儲系統映像文件,而是預加載了零售演示資源、OAT 文件和 APK 緩存等內容。將資源複製到 /data 分區後(這發生在首次啟動時),B 分區將被無線 (OTA) 更新用於下載系統映像的更新版本。

因此無法通過OTA更新APK緩存;它只能在工廠預裝。恢復出廠設置僅影響 /data 分區。系統 B 分區仍然有預加載的內容,直到下載 OTA 映像。恢復出廠設置後,系統將再次進行首次引導。這意味著如果將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/+/master/ 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 映像。它希望在 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分區的/data/preloads目錄中。

Pro :開箱即用 - 無需進行設備自定義即可在首次啟動時復製文件。內容已經在/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 緩存。)這需要有根設備:
    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應用程序。它應該顯示一個文件test.txt及其內容。請參閱此屏幕截圖以了解這些結果在用戶界面中的顯示方式。

    圖 1. ApkCacheTest 結果