W tym dokumencie opisujemy projekt rozwiązania do buforowania plików APK, które umożliwia szybkie instalowanie wstępnie załadowanych aplikacji na urządzeniu obsługującym partycje A/B.
Producenci OEM mogą umieszczać wstępnie załadowane i popularne aplikacje w pamięci podręcznej APK przechowywanej w głównie pustej partycji B na nowych urządzeniach z partycjami A/B bez wpływu na przestrzeń danych widoczną dla użytkownika. Dzięki temu, że na urządzeniu jest dostępna pamięć podręczna APK, nowe urządzenia lub te, które zostały niedawno przywrócone do ustawień fabrycznych, 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 w partycji B w celu szybszego przywracania
Wymagania wstępne
Aby korzystać z tej funkcji, urządzenie musi:
- zainstalowana wersja Androida 8.1 (O MR1),
- Wdrożono partycję A/B
Wstępnie załadowane treści można skopiować 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 wstępnie załadowane treści, takie jak zasoby wersji demonstracyjnej, pliki OAT i pamięć podręczna APK. Po skopiowaniu zasobów do partycji /data (co następuje przy pierwszym uruchomieniu) partycja B będzie używana przez aktualizacje bezprzewodowe (OTA) do pobierania zaktualizowanych wersji obrazu systemu.
Dlatego pamięci podręcznej APK nie można zaktualizować za pomocą OTA. Można ją wstępnie załadować tylko w fabryce. Przywracanie ustawień fabrycznych dotyczy tylko partycji /data. Partycja B systemu nadal zawiera wstępnie załadowane treści, dopóki nie zostanie pobrany obraz OTA. Po przywróceniu ustawień fabrycznych system ponownie przejdzie przez pierwszy rozruch. Oznacza to, że buforowanie plików APK nie jest dostępne, jeśli obraz OTA zostanie pobrany do partycji B, a następnie urządzenie zostanie przywrócone do ustawień fabrycznych.
Implementacja
Sposób 1. Treści na partycji system_other
Zaleta: wstępnie załadowane treści nie zostaną utracone po przywróceniu urządzenia do 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 wstępnie załadowanych treści.
Aby podczas pierwszego uruchomienia skopiować wstępnie załadowane aplikacje, system wywołuje skrypt w /system/bin/preloads_copy.sh
. Skrypt jest wywoływany z jednym argumentem (ścieżką do punktu montowania tylko do odczytu dla partycji system_b
):
Aby wdrożyć tę funkcję, wprowadź te zmiany dotyczące urządzenia. Oto przykład z Marlina:
- Dodaj skrypt, który wykonuje kopiowanie, do pliku
device-common.mk
(w tym przypadkudevice/google/marlin/device-common.mk
) w ten sposób: Przykładowy skrypt znajdziesz w tym miejscu: 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
- Zmodyfikuj plik
init.common.rc
, aby utworzyć wymagany katalog/data/preloads
i podkatalogi: Przykład źródła plikumkdir /data/preloads 0775 system system
mkdir /data/preloads/media 0775 system system
mkdir /data/preloads/demo 0775 system system
init
znajdziesz w tym miejscu: device/google/marlin/init.common.rc - Zdefiniuj nową domenę SELinux w pliku
preloads_copy.te
: Przykładowy plik domeny SELinux znajdziesz tutaj: /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;
- Zarejestruj domenę w nowym pliku
:/sepolicy/file_contexts Przykład pliku kontekstów SELinux znajdziesz tutaj: 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 przykład zmiany w pliku Makefile, która umożliwia kopiowanie zasobów pamięci podręcznej APK z repozytorium Git dostawcy (w naszym przypadku było to vendor/google_devices/marlin/preloads) do lokalizacji na partycji system_other, która zostanie później skopiowana do /data/preloads, gdy urządzenie uruchomi się po raz pierwszy. Ten skrypt jest uruchamiany w czasie kompilacji, aby przygotować obraz system_other. Oczekuje, że wstępnie załadowane treści będą dostępne w folderze vendor/google_devices/marlin/preloads. OEM może wybrać rzeczywistą 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 APK znajduje się w
/data/preloads/file_cache
i ma ten układ: To jest ostateczna struktura katalogów na urządzeniach. Producenci OEM mogą wybrać dowolne podejście do wdrożenia, o ile końcowa struktura pliku będzie zgodna z opisaną powyżej./data/preloads/file_cache/ app.package.name.1/ file1 fileN app.package.name.N/
Sposób 2. Treści na danych użytkownika obraz wgrany w fabryce
To alternatywne podejście zakłada, że wstępnie załadowane treści są już zawarte w katalogu /data/preloads
na partycji /data
.
Zaleta: działa od razu po wyjęciu z pudełka – nie trzeba dostosowywać urządzenia, aby skopiować pliki przy pierwszym uruchomieniu. Treści znajdują się już w podziale /data
.
Wada: po przywróceniu ustawień fabrycznych wstępnie załadowane treści zostaną utracone. Chociaż w niektórych przypadkach może to być dopuszczalne, nie zawsze sprawdza się w przypadku producentów OEM, którzy po kontroli jakości przywracają urządzenia do ustawień fabrycznych.
Do interfejsu android.content.Context
dodano nową metodę @SystemApi: getPreloadsFileCache()
. Zwraca ścieżkę bezwzględną do katalogu specyficznego dla aplikacji w wstępnie załadowanej pamięci podręcznej.
Dodaliśmy nową metodę IPackageManager.deletePreloadsFileCache
, która umożliwia usunięcie katalogu wstępnego wczytywania, aby odzyskać całą przestrzeń. Metoda może być wywoływana tylko przez aplikacje z identyfikatorem SYSTEM_UID, czyli serwer systemowy lub Ustawienia.
Przygotowanie aplikacji
Dostęp do katalogu pamięci podręcznej wstępnego wczytywania mają tylko aplikacje z uprawnieniami. Aby uzyskać taki dostęp, aplikacje muszą być zainstalowane w katalogu /system/priv-app
.
Weryfikacja
- Po pierwszym uruchomieniu urządzenia w katalogu
/data/preloads/file_cache
powinny znajdować się treści. - Jeśli na urządzeniu zaczyna brakować miejsca, zawartość katalogu
file_cache/
musi zostać usunięta.
Do testowania pamięci podręcznej APK użyj przykładowej aplikacji ApkCacheTest.
- Skompiluj aplikację, uruchamiając to polecenie w katalogu głównym:
make ApkCacheTest
- Zainstaluj aplikację jako aplikację uprzywilejowaną. (Pamiętaj, że tylko aplikacje uprzywilejowane mają dostęp do pamięci podręcznej APK).
Wymaga to urządzenia z dostępem do roota:
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
- W razie potrzeby symuluj 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.apkcachetest
adb shell restorecon -r /data/preloads
adb shell "echo "Test File" > /data/preloads/file_cache/com.android.apkcachetest/test.txt"
- Przetestuj aplikację. Po zainstalowaniu aplikacji i utworzeniu katalogu testowego
file_cache
otwórz aplikację ApkCacheTest. Powinien się w niej wyświetlić 1 pliktest.txt
i jego zawartość. Na tym zrzucie ekranu możesz zobaczyć, jak te wyniki wyglądają w interfejsie.
Rysunek 1. Wyniki testu ApkCacheTest.