이 문서에서는 A/B 파티션을 지원하는 기기에 미리 로드된 앱을 빠르게 설치할 수 있도록 APK 캐싱 솔루션 설계를 설명합니다.
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(무선) 업데이트에 사용됩니다.
따라서 APK 캐시는 OTA를 통해 업데이트할 수 없고 공장에서만 미리 로드할 수 있습니다. 초기화는 /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
)에 추가합니다. 예를 들어 다음과 같습니다.# 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에서 찾을 수 있습니다. - 필요한
/data/preloads
디렉터리 및 하위 디렉터리를 만들도록init.common.rc
파일을 수정합니다.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/+/master/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)
이는 공급업체 Git 저장소(이 경우에는 vendor/google_devices/marlin/preloads)의 APK 캐시 리소스를 나중에 기기 첫 부팅 시 /data/preloads로 복사할 system_other 파티션의 위치로 복사하도록 허용하는 Makefile 내 변경을 보여주는 예입니다. 이 스크립트는 system_other 이미지를 준비하기 위해 빌드 시 실행됩니다. 미리 로드된 콘텐츠는 vendor/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
에 추가되었습니다. 미리 로드된 캐시의 애플리케이션별 디렉터리의 절대 경로를 반환합니다.
preloads 디렉터리를 삭제하여 모든 공간을 회수할 수 있는 IPackageManager.deletePreloadsFileCache
라는 새로운 메서드가 추가되었습니다. 이 메서드는 SYSTEM_UID 즉, 시스템 서버 또는 설정이 있는 앱에서만 호출할 수 있습니다.
앱 준비
권한이 있는 애플리케이션만 preloads 캐시 디렉터리에 액세스할 수 있습니다. 이와 같이 액세스하려면 앱을 /system/priv-app
디렉터리에 설치해야 합니다.
유효성 검사
- 처음 부팅한 후 콘텐츠는 기기의
/data/preloads/file_cache
디렉터리에 있습니다. - 기기의 저장용량이 부족하면
file_cache/
디렉터리의 콘텐츠를 삭제해야 합니다.
APK 캐시 테스트에는 예제 ApkCacheTest 앱을 사용합니다.
- 루트 디렉터리에서 다음 명령어를 실행하여 앱을 빌드합니다.
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 결과