本文說明 APK 快取解決方案的設計,方便在支援 A/B 分區的裝置上快速安裝預先載入的應用程式。
在新的A/B 分割裝置上,OEM 可以將預先載入的應用程式和熱門應用程式放在 APK 快取中,而這些快取儲存在 B 分割區 (通常為空白),不會影響任何面向使用者的資料空間。裝置上備有 APK 快取,因此新裝置或最近恢復原廠設定的裝置幾乎可以立即使用,不必從 Google Play 下載 APK 檔案。
用途
- 將預先載入的應用程式儲存在 B 分割區,加快設定速度
- 將常用應用程式儲存在 B 分割區,加快還原速度
必要條件
如要使用這項功能,裝置必須符合下列條件:
- 已安裝 Android 8.1 (O MR1) 版本
- 已實作 A/B 分區
預先載入的內容只能在首次開機時複製。這是因為在支援 A/B 系統更新的裝置上,B 分割區實際上不會儲存系統映像檔,而是預先載入內容,例如零售展示資源、OAT 檔案和 APK 快取。資源複製到 /data 分區後 (首次開機時會發生此情況),無線 (OTA) 更新會使用 B 分區下載系統映像檔的更新版本。
因此無法透過 OTA 更新 APK 快取,只能在工廠預先載入。恢復原廠設定只會影響 /data 分割區。在下載 OTA 映像檔之前,系統 B 分割區仍會保留預先載入的內容。恢復原廠設定後,系統會再次完成首次啟動程序。也就是說,如果 OTA 映像檔下載至 B 分割區,然後裝置恢復原廠設定,APK 快取功能就無法使用。
實作
方法 1:system_other 分割區的內容
優點:恢復原廠設定後,預先載入的內容不會遺失,重新啟動後會從 B 分割區複製。
缺點:需要 B 分區的空間。恢復原廠設定後,裝置需要額外時間複製預先載入的內容,因此開機時間會比較長。
為確保預先載入的內容在首次開機時複製完成,系統會呼叫 /system/bin/preloads_copy.sh
中的指令碼。指令碼會使用單一引數 (system_b
分區的唯讀掛接點路徑) 呼叫:
如要實作這項功能,請進行下列裝置專屬變更。以下是 Marlin 的範例:
- 將執行複製作業的指令碼新增至
device-common.mk
檔案 (在本例中為device/google/marlin/device-common.mk
),如下所示: 如要查看指令碼來源範例,請前往:device/google/marlin/preloads_copy.sh# 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
- 編輯
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 網域: 您可以在以下位置找到 SELinux 網域檔案範例:/device/google/marlin/+/android16-release/sepolicy/preloads_copy.tetype 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;
- 在新
檔案中註冊網域:/sepolicy/file_contexts 您可以在以下位置找到 SELinux 內容範例檔案:device/google/marlin/sepolicy/preloads_copy.te/system/bin/preloads_copy\.sh u:object_r:preloads_copy_exec:s0
- 在建構時,含有預先載入內容的目錄必須複製到
system_other
分割區: 以下是 Makefile 的變更範例,可將 APK 快取資源從供應商的 Git 存放區 (在本例中為 vendor/google_devices/marlin/preloads) 複製到 system_other 分割區的位置,裝置首次啟動時,這些資源會複製到 /data/preloads。這個指令碼會在建構時執行,準備 system_other 映像檔。它預期預先載入的內容會位於 vendor/google_devices/marlin/preloads。OEM 可自由選擇實際的存放區名稱/路徑。# 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)
- APK 快取位於
/data/preloads/file_cache
,且具有下列配置: 這是裝置上的最終目錄結構。只要最終檔案結構與上述結構相同,OEM 就能自由選擇任何實作方法。/data/preloads/file_cache/ app.package.name.1/ file1 fileN app.package.name.N/
方法 2:使用者資料中的內容 工廠刷入的圖片
這個替代方法假設預先載入的內容已包含在 /data
分區的 /data/preloads
目錄中。
優點:開箱即可使用,首次啟動時不必自訂裝置,即可複製檔案。內容已位於「/data
」分割區。
缺點:恢復原廠設定後,預載內容會遺失。雖然這對某些人來說可以接受,但對於在品質控管檢查後將裝置恢復原廠設定的原始設備製造商 (OEM) 而言,可能不一定適用。
android.content.Context
新增了 @SystemApi 方法 getPreloadsFileCache()
。這會傳回預先載入快取中應用程式特定目錄的絕對路徑。
新增了 IPackageManager.deletePreloadsFileCache
方法,可刪除預先載入的目錄,以回收所有空間。只有具有 SYSTEM_UID 的應用程式 (即系統伺服器或「設定」) 才能呼叫這個方法。
準備應用程式
只有具備權限的應用程式才能存取預先載入快取目錄。如要取得這類存取權,應用程式必須安裝在 /system/priv-app
目錄中。
驗證
- 首次啟動後,裝置的
/data/preloads/file_cache
目錄中應會包含內容。 - 如果裝置儲存空間不足,請刪除
file_cache/
目錄中的內容。
使用 ApkCacheTest 應用程式範例測試 APK 快取。
- 從根目錄執行下列指令,建構應用程式:
make ApkCacheTest
- 以具備特殊權限的應用程式身分安裝應用程式 (請注意,只有具備特殊權限的應用程式才能存取 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
- 視需要模擬檔案快取目錄及其內容 (也需要根層級權限):
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 結果。