Buforowanie APK

W tym dokumencie opisano projekt rozwiązania do buforowania plików APK umożliwiającego szybką instalację wstępnie załadowanych aplikacji na urządzeniu obsługującym partycje A/B.

Producenci OEM mogą umieszczać wstępnie załadowane aplikacje i popularne aplikacje w pamięci podręcznej APK przechowywanej na przeważnie pustej partycji B na nowych urządzeniach z partycjami A/B bez wpływu na jakąkolwiek przestrzeń danych dostępną dla użytkownika. Dzięki dostępności pamięci podręcznej APK na urządzeniu nowe lub niedawno zresetowane urządzenia są gotowe do użycia niemal natychmiast, bez konieczności pobierania plików APK z Google Play.

Przypadków użycia

  • Przechowuj wstępnie załadowane aplikacje na partycji B, aby przyspieszyć konfigurację
  • Przechowuj popularne aplikacje na partycji B, aby przyspieszyć ich przywracanie

Warunki wstępne

Aby móc korzystać z tej funkcji, urządzenie potrzebuje:

  • Zainstalowana wersja Androida 8.1 (O MR1).
  • Zaimplementowano partycję A/B

Wstępnie załadowaną zawartość można skopiować tylko podczas pierwszego uruchomienia. Dzieje się tak, ponieważ na urządzeniach obsługujących aktualizacje systemu A/B partycja B w rzeczywistości nie przechowuje plików obrazu systemu, ale zamiast tego wstępnie załadowaną zawartość, taką jak zasoby demonstracyjne detaliczne, pliki OAT i pamięć podręczna APK. Po skopiowaniu zasobów na partycję /data (dzieje się to przy pierwszym uruchomieniu), partycja B będzie używana przez aktualizacje bezprzewodowe (OTA) do pobierania zaktualizowanych wersji obrazu systemu.

Dlatego nie można zaktualizować pamięci podręcznej APK przez OTA; można go wstępnie załadować tylko fabrycznie. Przywrócenie ustawień fabrycznych dotyczy tylko partycji /data. Partycja systemowa B nadal zawiera wstępnie załadowaną zawartość do czasu pobrania obrazu OTA. Po przywróceniu ustawień fabrycznych system ponownie przejdzie przez pierwsze uruchomienie. Oznacza to, że buforowanie APK nie jest dostępne, jeśli obraz OTA zostanie pobrany na partycję B, a następnie urządzenie zostanie zresetowane do ustawień fabrycznych.

Realizacja

Podejście 1. Zawartość na innej partycji systemowej

Pro : Wstępnie załadowana zawartość nie zostaje utracona po przywróceniu ustawień fabrycznych – zostanie skopiowana z partycji B po ponownym uruchomieniu.

Wada : Wymaga miejsca na partycji B. Uruchomienie po przywróceniu ustawień fabrycznych wymaga dodatkowego czasu na skopiowanie wstępnie załadowanej zawartości.

Aby wstępne załadowania zostały skopiowane podczas pierwszego uruchomienia, system wywołuje skrypt w /system/bin/preloads_copy.sh . Skrypt jest wywoływany z pojedynczym argumentem (ścieżka do punktu podłączenia tylko do odczytu dla partycji system_b ):

Aby zaimplementować tę funkcję, wprowadź zmiany specyficzne dla urządzenia. Oto przykład od Marlina:

  1. Dodaj skrypt, który wykona kopiowanie do pliku device-common.mk (w tym przypadku device/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
    
    Znajdź przykładowe źródło skryptu pod adresem: urządzenie/google/marlin /preloads_copy.sh
  2. Edytuj plik init.common.rc , aby utworzyć niezbędny katalog /data/preloads i podkatalogi:
    mkdir /data/preloads 0775 system system
    mkdir /data/preloads/media 0775 system system
    mkdir /data/preloads/demo 0775 system system
    
    Znajdź przykładowe źródło pliku init pod adresem: urządzenie/google/marlin/init.common.rc
  3. 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;
    
    Znajdź przykładowy plik domeny SELinux pod adresem: /device/google/marlin/+/main/sepolicy/preloads_copy.te
  4. Zarejestruj domenę w nowym /sepolicy/file_contexts plik:
    /system/bin/preloads_copy\.sh     u:object_r:preloads_copy_exec:s0
    
    Znajdź przykładowy plik kontekstów SELinux pod adresem: urządzenie/google/marlin/sepolicy/preloads_copy.te
  5. W czasie kompilacji katalog z wstępnie załadowaną zawartością musi zostać skopiowany na inną 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)
    
    To jest 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ł to sprzedawca/google_devices/ marlin/preloads) do lokalizacji na innej partycji systemowej, która zostanie później skopiowana do /data/preloads przy pierwszym uruchomieniu urządzenia. Ten skrypt jest uruchamiany w czasie kompilacji w celu przygotowania obrazu system_other. Oczekuje, że wstępnie załadowana zawartość będzie dostępna w dostawcy/google_devices/marlin/preloads. OEM może wybrać rzeczywistą nazwę/ścieżkę repozytorium.
  6. Pamięć podręczna APK znajduje się w /data/preloads/file_cache i ma następujący układ:
    /data/preloads/file_cache/
        app.package.name.1/
              file1
              fileN
        app.package.name.N/
    
    To jest ostateczna struktura katalogów na urządzeniach. Producenci OEM mogą wybrać dowolne podejście do implementacji, pod warunkiem, że ostateczna struktura plików będzie replikować tę opisaną powyżej.

Podejście 2. Treść obrazu danych użytkownika została flashowana fabrycznie

To alternatywne podejście zakłada, że ​​wstępnie załadowana zawartość jest już zawarta w katalogu /data/preloads na partycji /data .

Pro : Działa od razu po wyjęciu z pudełka — nie ma potrzeby dostosowywania urządzenia, aby kopiować pliki przy pierwszym uruchomieniu. Treść znajduje się już na partycji /data .

Wada : Wstępnie załadowana zawartość zostaje utracona po przywróceniu ustawień fabrycznych. Chociaż może to być akceptowalne dla niektórych, nie zawsze może działać w przypadku producentów OEM, którzy przywracają urządzenia do ustawień fabrycznych po przeprowadzeniu kontroli kontroli jakości.

Do android.content.Context dodano nową metodę @SystemApi, getPreloadsFileCache() . Zwraca bezwzględną ścieżkę do katalogu specyficznego dla aplikacji we wstępnie załadowanej pamięci podręcznej.

Dodano nową metodę IPackageManager.deletePreloadsFileCache , która umożliwia usunięcie katalogu preloads w celu odzyskania całego miejsca. Metodę mogą wywołać tylko aplikacje posiadające SYSTEM_UID, czyli serwer systemowy lub Ustawienia.

Przygotowanie aplikacji

Tylko uprzywilejowane aplikacje mogą uzyskać dostęp do katalogu pamięci podręcznej wstępnego ładowania. Aby uzyskać taki dostęp, aplikacje muszą być zainstalowane w katalogu /system/priv-app .

Walidacja

  • Po pierwszym uruchomieniu urządzenie powinno mieć zawartość w katalogu /data/preloads/file_cache .
  • Jeśli w urządzeniu zaczyna brakować miejsca, zawartość katalogu file_cache/ musi zostać usunięta.

Użyj przykładowej aplikacji ApkCacheTest do testowania pamięci podręcznej APK.

  1. Zbuduj aplikację, uruchamiając to polecenie z katalogu głównego:
    make ApkCacheTest
    
  2. Zainstaluj aplikację jako aplikację uprzywilejowaną. (Pamiętaj, że tylko uprzywilejowane aplikacje mogą uzyskać dostęp do pamięci podręcznej APK). Wymaga to zrootowanego urządzenia:
    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
    
  3. W razie potrzeby symuluj katalog pamięci podręcznej plików i jego zawartość (wymaga to również 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"
    
  4. Przetestuj aplikację. Po zainstalowaniu aplikacji i utworzeniu testowego katalogu file_cache otwórz aplikację ApkCacheTest. Powinien pokazać jeden plik test.txt i jego zawartość. Zobacz ten zrzut ekranu, aby zobaczyć, jak te wyniki pojawiają się w interfejsie użytkownika.

    Rysunek 1. Wyniki testu ApkCacheTest