Egzekwuj interfejsy partycji produktów

Android 11 wyodrębnia partycję product, niezależnie od partycji system i vendor. W ramach tych zmian możesz teraz kontrolować dostęp partycji product do kodu natywnego i języka Java interfejs (podobny do sposobu egzekwowania zasad w przypadku witryny vendor) partycje).

Egzekwuj interfejsy natywne

Aby włączyć egzekwowanie interfejsu natywnego, ustaw PRODUCT_PRODUCT_VNDK_VERSION do: current. (Wersja jest automatycznie ustawiana na current przy dostawie poziom interfejsu API dla wartości docelowej jest wyższy niż 29). Egzekwowanie zasad umożliwia:

  • Moduły natywne na partycji product do połączenia:
    • Statycznie lub dynamicznie względem innych modułów w partycji product, która nie zawierają bibliotek statycznych, udostępnianych lub nagłówków.
    • Dynamicznie do bibliotek VNDK w partycji system.
  • Biblioteki JNI w niepakowanych plikach APK na partycji product, do której mają zostać połączone biblioteki w /product/lib lub /product/lib64 (oprócz bibliotek NDK).

Egzekwowanie nie zezwala na inne linki do partycji innych niż product partycji danych.

Egzekwowanie czasu kompilacji (Android.bp)

W Androidzie 11 moduły systemowe mogą tworzyć produkty wraz z wariantami obrazu podstawowego i dostawcy. W przypadku natywnego wymuszanie użycia interfejsu jest włączone (wartość PRODUCT_PRODUCT_VNDK_VERSION jest ustawiona na current):

  • Moduły natywne w partycji product są zamiast tego w wariancie produktu wersji podstawowej.

  • Moduły z atrybutem product_available: true w plikach Android.bp są dostępnej w wersji produktu.

  • Biblioteki i pliki binarne, które określają product_specific: true, mogą zawierać linki do innych biblioteki, które określają product_specific: true lub product_available: true w ich plikach Android.bp.

  • Biblioteki VNDK muszą zawierać w plikach Android.bp element product_available: true aby pliki binarne product mogły się łączyć z bibliotekami VNDK.

W tabeli poniżej znajdziesz podsumowanie właściwości Android.bp użytych do utworzenia obrazu wersji.

Usługi w pliku Android.bp Utworzone warianty
Przed egzekwowaniem zasad Po wyegzekwowaniu zasad
domyślnie (brak) mięśnie głębokie
(obejmuje /system, /system_ext i /product).
mięśnie głębokie
(obejmuje /system i /system_ext, ale nie /product).
system_ext_specific: true mięśnie głębokie mięśnie głębokie
product_specific: true mięśnie głębokie Produkt
vendor: true firma firma
vendor_available: true podstawowy, dostawca podstawowy, dostawca
product_available: true Nie dotyczy podstawowy, produkt
vendor_available: true ORAZ product_available: true Nie dotyczy podstawowy, produkt, dostawca
system_ext_specific: true ORAZ vendor_available: true podstawowy, dostawca podstawowy, dostawca
product_specific: true ORAZ vendor_available: true podstawowy, dostawca produkt, dostawca

Egzekwowanie czasu kompilacji (Android.mk)

Gdy wymuszanie interfejsu natywnego jest włączone, moduły natywne zainstalowane w Partycja product ma typ połączenia native:product, który może się łączyć tylko z innych modułów native:product lub native:vndk. Próba utworzenia powiązania z moduły inne niż te powodują, że system kompilacji generuje sprawdzenie typu linku. .

Egzekwowanie środowiska wykonawczego

Po włączeniu wymuszania interfejsu natywnego konfiguracja tagu łączącego dla bionikowy tag łączący nie zezwala procesom systemowym na korzystanie z bibliotek product, tworzę sekcję product dla procesów product, których nie można połączyć z poza partycją product (takie procesy mogą jednak łączyć się z VNDK). Próby naruszenia konfiguracji linku środowiska wykonawczego powodują kończy się niepowodzeniem i wygenerowanie komunikatu o błędzie CANNOT LINK EXECUTABLE.

Egzekwuj interfejsy Java

Aby włączyć wymuszanie korzystania z interfejsu Java, ustaw PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE do true. (Wartość to jest automatycznie ustawiana na true, gdy poziom interfejsu API dostawy dla miejsca docelowego to więcej niż 29). Gdy ta opcja jest włączona, wymuszanie zezwala lub nie zezwala na: access:

Interfejs API /system /system_ext /product /vendor /data
Publiczny interfejs API
@SystemApi
@hide API

Na przykład w przypadku partycji vendor, aplikacja lub biblioteka Java w interfejsie product partycja może używać tylko publicznych i systemowych interfejsów API; z linkiem do biblioteki używający ukrytych interfejsów API jest niedozwolone. To ograniczenie obejmuje możliwość łączenia na etapie kompilacji czas i refleksję w czasie działania.

Egzekwowanie czasu kompilacji

Podczas kompilacji narzędzia Marka i Soong sprawdzają, czy moduły Javy w product nie używają ukrytych interfejsów API przez sprawdzenie platform_apis i sdk_version pól. Element sdk_version aplikacji w partycji product musi być wypełnione wartościami current, system_current lub numeryczną wersją interfejsu API oraz pole platform_apis musi być puste.

Egzekwowanie środowiska wykonawczego

Środowisko wykonawcze Androida sprawdza, czy aplikacje na partycji product nie używają do ukrytych interfejsów API, w tym do interfejsu Reflection. Szczegółowe informacje znajdziesz w sekcji Ograniczenia spoza pakietu SDK .

Włącz egzekwowanie zasad w interfejsie usługi

Aby włączyć egzekwowanie zasad w interfejsie usługi, wykonaj czynności opisane w tej sekcji.

Krok Zadanie Wymagane
1 Zdefiniuj własny plik marki systemu, który określa pakiety dla system partycji, a następnie ustaw sprawdzanie wymagań dotyczących ścieżki artefaktów w device.mk (aby zapobiec instalowaniu modułów niesystemowych na partycję system). N
2 Wyczyść listę dozwolonych. N
3 Wymuszaj natywne interfejsy i wykrywaj błędy połączenia w środowisku wykonawczym (może działać w równolegle z egzekwowaniem zasad Java). Y
4 Wymuszaj interfejsy Java i sprawdź działanie środowiska wykonawczego (może działać równolegle) z wymogiem natywnym). Y
5 Sprawdź działanie środowiska wykonawczego. Y
6 Zaktualizuj zasadę device.mk dotyczącą egzekwowania zasad w interfejsie usługi. Y

Krok 1. Utwórz plik Makefile i włącz sprawdzanie ścieżki artefaktów

W tym kroku definiujesz plik Makefile system.

  1. Utwórz plik Makefile, który definiuje pakiety partycji system. Dla: utwórz na przykład plik oem_system.mk z tymi elementami:

    $(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_system.mk)
    $(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_system.mk)
    
    # Applications
    PRODUCT_PACKAGES += \
        CommonSystemApp1 \
        CommonSystemApp2 \
        CommonSystemApp3 \
    
    # Binaries
    PRODUCT_PACKAGES += \
        CommonSystemBin1 \
        CommonSystemBin2 \
        CommonSystemBin3 \
    
    # Libraries
    PRODUCT_PACKAGES += \
        CommonSystemLib1 \
        CommonSystemLib2 \
        CommonSystemLib3 \
    
    PRODUCT_SYSTEM_NAME := oem_system
    PRODUCT_SYSTEM_BRAND := Android
    PRODUCT_SYSTEM_MANUFACTURER := Android
    PRODUCT_SYSTEM_MODEL := oem_system
    PRODUCT_SYSTEM_DEVICE := generic
    
    # For system-as-root devices, system.img should be mounted at /, so we
    # include ROOT here.
    _my_paths := \
     $(TARGET_COPY_OUT_ROOT)/ \
     $(TARGET_COPY_OUT_SYSTEM)/ \
    
    $(call require-artifacts-in-path, $(_my_paths),)
    
  2. W pliku device.mk odziedzicz wspólny plik „makefile” dla system. partycjonować i włączyć sprawdzanie wymagań dotyczących ścieżki artefaktów. Na przykład:

    $(call inherit-product, $(SRC_TARGET_DIR)/product/oem_system.mk)
    
    # Enable artifact path requirements checking
    PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := strict
    

Wymagania dotyczące ścieżki artefaktów

Gdy PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS ma wartość true lub strict, system kompilacji uniemożliwia instalowanie pakietów zdefiniowanych w innych plikach Makefiles ścieżki określone w funkcji require-artifacts-in-path oraz blokują pakiety zdefiniowane w bieżącym pliku programu Makefile, aby możliwe było instalowanie artefaktów poza ścieżkami. zdefiniowaną w require-artifacts-in-path.

W przykładzie powyżej, gdy PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS ma wartość strict, plik Makefiles poza oem_system.mk nie może zawierać modułów zainstalowanych w partycję root lub system. Aby je dołączyć, musisz: i określ je w samym pliku oem_system.mk lub w dołączonym pliku Makefile. Próby instalacji modułów na niedozwolonych ścieżkach powodują przerwy w kompilacji. Do naprawienia przerwach, wykonaj jedną z tych czynności:

  • Opcja 1. Dodaj moduł systemowy do plików programu Maker oem_system.mk Pozwala to spełnić wymaganie dotyczące ścieżki artefaktów (jako znajdują się teraz w dołączonym pliku Makefile), można więc zainstalować go w zestawu ścieżek w kolumnie „require-artifacts-in-path”.

  • Opcja 2. Zainstaluj moduły na partycji system_ext lub product (oraz nie instaluj modułów na partycji system).

  • Opcja 3. Dodaj moduły do PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST Ta lista zawiera dozwolone moduły do instalacji.

Krok 2. Opróżnij listę dozwolonych

W tym kroku: PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST puste, aby wszystkie urządzenia współużytkujące oem_system.mk również mogły współużytkować jeden system . Aby opróżnić listę dozwolonych, przenieś wszystkie moduły z listy do system_ext lub product partycji lub dodaj je do system, aby utworzyć pliki. Ten Ten krok jest opcjonalny, ponieważ zdefiniowanie wspólnego obrazu system nie jest wymagane do włączyć egzekwowanie zasad w interfejsie usługi. Jednak opróżnianie listy dozwolonych pomocne przy wyznaczaniu granicy system za pomocą system_ext.

Krok 3. Wymuszaj interfejsy natywne

W tym kroku ustawisz PRODUCT_PRODUCT_VNDK_VERSION := current, a potem sprawdź, w przypadku błędów kompilacji i czasu działania. Aby sprawdzić ustawienia rozruchu urządzenia i dzienniki oraz znaleźć i naprawić błędy połączenia w środowisku wykonawczym:

  1. Ustaw PRODUCT_PRODUCT_VNDK_VERSION := current.

  2. Zbuduj urządzenie i poszukaj błędów kompilacji. Najprawdopodobniej zobaczysz w przypadku brakujących wersji produktu lub podstawowych wersji. Częste przerwy uwzględnij:

    • Żaden moduł hidl_interface zawierający product_specific: true nie zostanie dostępne dla modułów systemowych. Aby to naprawić, zastąp product_specific: true dzięki system_ext_specific: true.
    • W modułach może brakować wersji produktu wymaganej dla produktu modułów. Aby rozwiązać ten problem, udostępnij ten moduł partycji product przez ustawienie product_available: true lub przenieś moduł do product partycjonowanie według ustawienia product_specific: true.
  3. Napraw błędy kompilacji i upewnij się, że urządzenie działa prawidłowo.

  4. Wczytaj obraz i poszukaj błędów czasu działania w plikach rozruchowych urządzenia i dziennikach.

    • Jeśli tag linker z dziennika przypadku testowego zawiera CANNOT LINK EXECUTABLE oznacza, że plik makijaż nie ma zależności (i nie został przechwycony czas kompilacji).
    • Aby sprawdzić ją w systemie kompilacji, dodaj wymaganą bibliotekę do Pole shared_libs: lub required:.
  5. Rozwiąż brakujące zależności, korzystając z podanych wyżej wskazówek.

Krok 4. Wymuszaj interfejsy Java

W tym kroku ustawisz PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true, a potem odszukaj i napraw wynikowe błędy kompilacji. Zwróć uwagę na 2 rodzaje błędów:

  • Błędy typu linku. Ten błąd oznacza, że aplikacja łączy się z modułami Java które mają szerszy zakres sdk_version. Aby rozwiązać ten problem, możesz rozszerzyć sdk_version lub ogranicz do sdk_version biblioteki. Przykładowy błąd:

    error: frameworks/base/packages/SystemUI/Android.bp:138:1: module "SystemUI" variant "android_common": compiles against system API, but dependency "telephony-common" is compiling against private API.Adjust sdk_version: property of the source or target module so that target module is built with the same or smaller API set than the source.
    
  • Błędy symboli. Ten błąd oznacza, że nie można znaleźć symbolu, ponieważ w ukrytym interfejsie API. Aby rozwiązać ten problem, użyj widocznego (nieukrytego) interfejsu API lub znajdź . Przykładowy błąd:

    frameworks/opt/net/voip/src/java/com/android/server/sip/SipSessionGroup.java:1051: error: cannot find symbol
                ProxyAuthenticate proxyAuth = (ProxyAuthenticate)response.getHeader(
                                               ^
      symbol:   class ProxyAuthenticate
      location: class SipSessionGroup.SipSessionImpl
    

Krok 5. Sprawdź działanie środowiska wykonawczego

W tym kroku sprawdzisz, czy środowisko wykonawcze działa prawidłowo. W przypadku aplikacji, które można śledzić ukryte wykorzystanie interfejsu API, logując StrictMode.detectNonSdkApiUsage (który generuje dziennik, gdy aplikacja używa ukryty interfejs API). Ewentualnie możesz użyć atrybutu veridex narzędzia do analizy statycznej, aby poznać jego rodzaj (tworzenie linków lub odczuć), poziom ograniczenia czy stos wywołań.

  • Składnia Veridex:

    ./art/tools/veridex/appcompat.sh --dex-file={apk file}
    
  • Przykładowy wynik w formacie Veridex:

    #1: Linking greylist-max-o Landroid/animation/AnimationHandler;-><init>()V use(s):
           Lcom/android/systemui/pip/phone/PipMotionHelper;-><init>(Landroid/content/Context;Landroid/app/IActivityManager;Landroid/app/IActivityTaskManager;Lcom/android/systemui/pip/phone/PipMenuActivityController;Lcom/android/internal/policy/PipSnapAlgorithm;Lcom/android/systemui/statusbar/FlingAnimationUtils;)V
    
    #1332: Reflection greylist Landroid/app/Activity;->mMainThread use(s):
           Landroidx/core/app/ActivityRecreator;->getMainThreadField()Ljava/lang/reflect/Field;
    

Szczegółowe informacje o korzystaniu z Veridex znajdziesz w sekcji Testowanie z użyciem tej funkcji .

Krok 6. Zaktualizuj plik device.mk

Po naprawieniu wszystkich błędów kompilacji i czasu działania oraz sprawdzeniu tego środowiska wykonawczego zachowanie jest zgodne z oczekiwaniami, ustaw w device.mk te elementy:

  • PRODUCT_PRODUCT_VNDK_VERSION := current
  • PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true