本文檔介紹了 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
分區的唯讀安裝點的路徑):
若要實現此功能,請進行這些特定於裝置的變更。這是馬林的例子:
- 新增用於複製到
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 - 編輯
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 - 在檔案
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 - 在新域名註冊域名
/sepolicy/file_contexts
檔案:/system/bin/preloads_copy\.sh u:object_r:preloads_copy_exec:s0
在下列位置尋找範例 SELinux 上下文檔案: device/google/marlin/sepolicy/preloads_copy.te - 在建置時,必須將包含預先載入內容的目錄複製到
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 可以自由選擇實際的儲存庫名稱/路徑。 - 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 快取。
- 透過從根目錄執行以下命令來建立應用程式:
make ApkCacheTest
- 將應用程式安裝為特權應用程式。 (請記住,只有特權應用程式才能存取 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
- 如果需要,模擬檔案快取目錄及其內容(也需要 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"
- 測試應用程式。安裝應用程式並建立測試
file_cache
目錄後,開啟 ApkCacheTest 應用程式。它應該顯示一個檔案test.txt
及其內容。請參閱此螢幕截圖,以了解這些結果如何顯示在使用者介面中。圖 1.ApkCacheTest結果。