W tym dokumencie opisujemy projekt rozwiązania do buforowania plików APK, które umożliwia szybką instalację preinstalowanych aplikacji na urządzeniu obsługującym partycje A/B.
Producenci OEM mogą umieszczać preinstalowane i popularne aplikacje w pamięci podręcznej plików APK przechowywanej na prawie pustej partycji B na nowych urządzeniach z partycjami A/B bez wpływu na przestrzeń danych użytkownika. Dzięki pamięci podręcznej plików APK dostępnej na urządzeniu nowe lub niedawno przywrócone do ustawień fabrycznych urządzenia są gotowe do użycia niemal natychmiast, bez konieczności pobierania plików APK z Google Play.
Przypadki użycia
- Przechowywanie preinstalowanych aplikacji na partycji B w celu szybszej konfiguracji
- Przechowywanie popularnych aplikacji na partycji B w celu szybszego przywracania
Wymagania wstępne
Aby korzystać z tej funkcji, urządzenie musi mieć:
- zainstalowaną wersję Androida 8.1 (O MR1),
- wdrożoną partycję A/B.
Preinstalowane treści można kopiować tylko podczas pierwszego uruchomienia. Dzieje się tak, ponieważ na urządzeniach obsługujących aktualizacje systemu A/B partycja B nie przechowuje plików obrazu systemu, ale preinstalowane treści, takie jak zasoby trybu demo dla sklepów, pliki OAT i pamięć podręczna plików APK. Po skopiowaniu zasobów na partycję /data (co następuje podczas pierwszego uruchomienia) partycja B będzie używana przez aktualizacje OTA do pobierania zaktualizowanych wersji obrazu systemu.
Dlatego pamięci podręcznej plików APK nie można aktualizować przez OTA. Można ją preinstalować tylko w fabryce. Przywracanie ustawień fabrycznych wpływa tylko na partycję /data. Partycja systemowa B nadal zawiera preinstalowane treści, dopóki nie zostanie pobrany obraz OTA. Po przywróceniu ustawień fabrycznych system ponownie przejdzie przez pierwsze uruchomienie. Oznacza to, że buforowanie plików APK nie jest dostępne, jeśli obraz OTA zostanie pobrany na partycję B, a następnie urządzenie zostanie przywrócone do ustawień fabrycznych.
Implementacja
Sposób nr 1. Treści na partycji system_other
Zaleta: preinstalowane treści nie są tracone po przywróceniu ustawień fabrycznych – po ponownym uruchomieniu zostaną skopiowane z partycji B.
Wada: wymaga miejsca na partycji B. Uruchomienie po przywróceniu ustawień fabrycznych wymaga dodatkowego czasu na skopiowanie preinstalowanych treści.
Aby preinstalowane treści zostały skopiowane podczas pierwszego uruchomienia, system wywołuje skrypt w /system/bin/preloads_copy.sh. Skrypt jest wywoływany z 1 argumentem (ścieżką do punktu podłączania tylko do odczytu dla partycji system_b):
Aby wdrożyć tę funkcję, wprowadź te zmiany specyficzne dla urządzenia. Oto przykład z Marlina:
- Dodaj skrypt, który wykonuje kopiowanie, do
device-common.mkpliku (w tym przypadkudevice/google/marlin/device-common.mk): Źródło przykładowego skryptu znajdziesz w: 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 - Edytuj plik
init.common.rc, aby utworzyć niezbędny/data/preloadskatalog i podkatalogi: Źródło przykładowego plikumkdir /data/preloads 0775 system systemmkdir /data/preloads/media 0775 system systemmkdir /data/preloads/demo 0775 system systeminitznajdziesz w: device/google/marlin/init.common.rc - Zdefiniuj nową domenę SELinux w pliku
preloads_copy.te: Przykładowy plik domeny SELinux znajdziesz w: /device/google/marlin/+/android17-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;
- Zarejestruj domenę w nowym pliku
:/sepolicy/file_contexts Przykładowy plik kontekstów SELinux znajdziesz w: device/google/marlin/sepolicy/preloads_copy.te/system/bin/preloads_copy\.sh u:object_r:preloads_copy_exec:s0
- Podczas kompilacji katalog z preinstalowanymi treściami musi zostać skopiowany na partycję
system_other: To jest przykład zmiany w pliku Makefile, która umożliwia kopiowanie zasobów pamięci podręcznej plików APK z repozytorium Git dostawcy (w naszym przypadku vendor/google_devices/marlin/preloads) do lokalizacji na partycji system_other, która zostanie później skopiowana do /data/preloads podczas pierwszego uruchomienia urządzenia. Ten skrypt jest uruchamiany podczas kompilacji w celu przygotowania obrazu system_other. Oczekuje, że preinstalowane treści będą dostępne w vendor/google_devices/marlin/preloads. Producent OEM może wybrać dowolną nazwę lub ścieżkę repozytorium.# 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) - Pamięć podręczna plików APK znajduje się w
/data/preloads/file_cachei ma ten układ: To jest ostateczna struktura katalogów na urządzeniach. Producenci OEM mogą wybrać dowolny sposób implementacji, o ile ostateczna struktura plików będzie zgodna z opisaną powyżej./data/preloads/file_cache/ app.package.name.1/ file1 fileN app.package.name.N/
Sposób nr 2. Treści na obrazie danych użytkownika wgranym w fabryce
To alternatywne podejście zakłada, że preinstalowane treści są już zawarte w
katalogu /data/preloads na partycji /data.
Zaleta: działa od razu – nie trzeba wprowadzać żadnych dostosowań urządzenia
, aby kopiować pliki podczas pierwszego uruchomienia. Treści są już na partycji /data.
Wada: preinstalowane treści są tracone po przywróceniu ustawień fabrycznych. Choć dla niektórych może to być akceptowalne, nie zawsze będzie to odpowiednie dla producentów OEM, którzy przywracają ustawienia fabryczne po przeprowadzeniu kontroli jakości.
Do android.content.Context dodano nową metodę @SystemApi: getPreloadsFileCache(). Zwraca ona bezwzględną ścieżkę do katalogu specyficznego dla aplikacji w preinstalowanej pamięci podręcznej.
Dodano nową metodę IPackageManager.deletePreloadsFileCache, która umożliwia usunięcie katalogu preinstalowanych treści, aby odzyskać całą przestrzeń. Metodę tę mogą wywoływać tylko aplikacje z SYSTEM_UID, czyli serwer systemowy lub Ustawienia.
Przygotowanie aplikacji
Dostęp do katalogu pamięci podręcznej preinstalowanych treści mają tylko aplikacje z uprawnieniami. Aby uzyskać
dostęp, aplikacje muszą być zainstalowane w katalogu /system/priv-app.
Weryfikacja
- Po pierwszym uruchomieniu urządzenie powinno mieć treści w katalogu
/data/preloads/file_cache. - Jeśli na urządzeniu zabraknie miejsca, treści w katalogu
file_cache/muszą zostać usunięte.
Do testowania pamięci podręcznej plików APK użyj przykładowej aplikacji ApkCacheTest.
- Skompiluj aplikację, uruchamiając to polecenie w katalogu głównym:
make ApkCacheTest - Zainstaluj aplikację jako aplikację z uprawnieniami. (Pamiętaj, że tylko aplikacje z uprawnieniami mogą mieć dostęp do pamięci podręcznej plików APK).
Wymaga to urządzenia z dostępem do roota:
adb root && adb remountadb shell mkdir /system/priv-app/ApkCacheTestadb push $ANDROID_PRODUCT_OUT/data/app/ApkCacheTest/ApkCacheTest.apk /system/priv-app/ApkCacheTest/adb shell stop && adb shell start - W razie potrzeby zasymuluj katalog pamięci podręcznej plików i jego zawartość (wymaga to też uprawnień roota):
adb shell mkdir -p /data/preloads/file_cache/com.android.apkcachetestadb shell restorecon -r /data/preloadsadb shell "echo "Test File" > /data/preloads/file_cache/com.android.apkcachetest/test.txt" - Przetestuj aplikację. Po zainstalowaniu aplikacji i utworzeniu testowego katalogu
file_cacheotwórz aplikację ApkCacheTest. Powinien się w niej wyświetlić pliktest.txti jego zawartość. Na tym zrzucie ekranu możesz zobaczyć, jak te wyniki wyglądają w interfejsie.
Rysunek 1. Wyniki ApkCacheTest.