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:# 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/preloadsi podkatalogi:mkdir /data/preloads 0775 system systemmkdir /data/preloads/media 0775 system systemmkdir /data/preloads/demo 0775 system systeminitznajdziesz w tym miejscu: device/google/marlin/init.common.rc
- Zdefiniuj nową domenę SELinux w pliku preloads_copy.te: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; 
- Zarejestruj domenę w nowym pliku /sepolicy/file_contexts /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:# 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_cachei ma ten układ:/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_cachepowinny 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 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 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.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 katalogu testowego file_cacheotwórz aplikację ApkCacheTest. Powinien się w niej wyświetlić 1 pliktest.txti jego zawartość. Na tym zrzucie ekranu możesz zobaczyć, jak te wyniki wyglądają w interfejsie.
 Rysunek 1. Wyniki testu ApkCacheTest. 
