Android 11 rozdziela partycję product
, dzięki czemu jest ona niezależna od partycji system
i vendor
. W ramach tych zmian możesz teraz kontrolować dostęp partycji product
do interfejsów natywnych i Java (podobnie jak w przypadku egzekwowania interfejsów w partycjach vendor
).
Wymuszanie interfejsów natywnych
Aby włączyć wymuszanie interfejsu natywnego, ustaw wartość PRODUCT_PRODUCT_VNDK_VERSION
na current
. (Wersja jest automatycznie ustawiana na current
, gdy poziom interfejsu Shipping API dla miejsca docelowego jest większy niż 29). Egzekwowanie umożliwia:
- Moduły natywne w partycji
product
do połączenia:- statycznie lub dynamicznie do innych modułów w
product
, które zawierają biblioteki statyczne, współdzielone lub nagłówkowe; - dynamicznie do bibliotek VNDK w
system
.
- statycznie lub dynamicznie do innych modułów w
- biblioteki JNI w niezapakowanych plikach APK w partycji
product
, które mają być połączone z bibliotekami w partycjach/product/lib
lub/product/lib64
(oprócz bibliotek NDK);
Egzekwowanie zasad nie zezwala na inne linki do partycji niż partycja product
.
Wymuszanie czasu kompilacji (Android.bp)
W Androidzie 11 moduły systemowe mogą tworzyć wariant obrazu produktu oprócz wariantów obrazu podstawowego i wariantów obrazu dostawcy. Gdy wymuszanie interfejsu natywnego jest włączone (PRODUCT_PRODUCT_VNDK_VERSION
ma wartość current
):
Moduły natywne w podziale
product
znajdują się w wersji produktu, a nie w wersji podstawowej.Moduły z
product_available: true
w plikachAndroid.bp
są dostępne dla wersji produktu.Biblioteki lub pliki binarne, które określają
product_specific: true
, mogą się łączyć z innymi bibliotekami, które określająproduct_specific: true
lubproduct_available: true
w swoich plikachAndroid.bp
.Biblioteki VNDK muszą mieć w swoich plikach
Android.bp
wartośćproduct_available: true
, aby pliki binarneproduct
mogły się z nimi łączyć.
W tabeli poniżej znajdziesz podsumowanie właściwości Android.bp
używanych do tworzenia wariantów obrazu.
Właściwości w pliku Android.bp | Utworzone wersje | |
---|---|---|
Przed egzekwowaniem | Po egzekwowaniu | |
domyślny (brak) | podstawowe
(zawiera /system , /system_ext i /product ) |
core
(zawiera /system i /system_ext , ale nie /product ) |
system_ext_specific: true |
core | core |
product_specific: true |
core | iloczyn |
vendor: true |
firma | firma |
vendor_available: true |
core, vendor | core, vendor |
product_available: true |
Nie dotyczy | core, product |
vendor_available: true ORAZ product_available:
true |
Nie dotyczy | podstawowy, produkt, dostawca |
system_ext_specific: true ORAZ vendor_available:
true |
core, vendor | core, vendor |
product_specific: true ORAZ vendor_available:
true |
core, vendor | produkt, dostawca |
Wymuszanie czasu kompilacji (Android.mk)
Gdy wymuszanie interfejsu natywnego jest włączone, moduły natywne zainstalowane w partycji
product
mają typ linku native:product
, który może prowadzić tylko do innych modułów native:product
lub native:vndk
. Próba połączenia z innymi modułami powoduje wygenerowanie przez system kompilacji błędu sprawdzania typu połączenia.
Wymuszanie w środowisku wykonawczym
Gdy wymuszanie interfejsu natywnego jest włączone, konfiguracja linkera dla linkera bionic nie zezwala procesom systemowym na używanie bibliotek product
, tworząc sekcję product
dla procesów product
, które nie mogą łączyć się z bibliotekami poza partycją product
(jednak takie procesy mogą łączyć się z bibliotekami VNDK). Próby naruszenia konfiguracji linku w czasie działania powodują niepowodzenie procesu i wygenerowanie komunikatu o błędzie CANNOT LINK EXECUTABLE
.
Wymuszanie interfejsów Java
Aby włączyć wymuszanie interfejsu Java, ustaw wartość
PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE
na true
. (Wartość jest automatycznie ustawiana na true
, gdy poziom interfejsu API dostawy dla miejsca docelowego jest większy niż 29). Gdy egzekwowanie jest włączone, zezwala na dostęp w tych przypadkach:
Interfejs API | /system | /system_ext | /product | /vendor | /data |
---|---|---|---|---|---|
Publiczny interfejs API | |||||
@SystemApi | |||||
@hide API |
Podobnie jak w przypadku partycji vendor
, aplikacja lub biblioteka Java w partycji product
może używać tylko publicznych i systemowych interfejsów API. Nie można łączyć się z biblioteką, która używa ukrytych interfejsów API. Ograniczenie to obejmuje łączenie w czasie kompilacji i odzwierciedlanie w czasie działania.
Wymuszanie weryfikacji dwuetapowej w czasie tworzenia kompilacji
Podczas kompilacji systemy Make i Soong sprawdzają, czy moduły Java w product
nie używają ukrytych interfejsów API. W tym celu sprawdzają pola platform_apis
i sdk_version
. Pole sdk_version
aplikacji w sekcji product
musi zawierać wartość current
, system_current
lub numeryczną wersję interfejsu API, a pole platform_apis
musi być puste.
Wymuszanie w środowisku wykonawczym
Środowisko wykonawcze Androida sprawdza, czy aplikacje w partycji product
nie korzystają z ukrytych interfejsów API, w tym z odbicia. Szczegółowe informacje znajdziesz w sekcji Ograniczenia dotyczące interfejsów innych niż SDK.
Włączanie wymuszania interfejsu produktu
Aby włączyć egzekwowanie interfejsu usługi, wykonaj czynności opisane w tej sekcji.
Krok | Zadanie | Wymagane |
---|---|---|
1 | Zdefiniuj własny plik makefile systemu, który określa pakiety dla partycji system , a następnie ustaw w pliku device.mk sprawdzanie ścieżki artefaktów (aby zapobiec instalowaniu modułów niesystemowych na partycji system ). |
N |
2 | Wyczyść listę dozwolonych. | N |
3 | Wymuszanie interfejsów natywnych i wykrywanie błędów łączenia w czasie działania (może działać równolegle z wymuszaniem w przypadku Javy). | Y |
4 | Wymuszanie interfejsów Java i weryfikowanie zachowania w czasie działania (może działać równolegle z wymuszaniem natywnym). | Y |
5 | Sprawdzanie zachowań podczas działania. | Y |
6 | Aktualizacja device.mk z wymuszaniem interfejsu produktu. |
Y |
Krok 1. Utwórz plik makefile i włącz sprawdzanie ścieżki artefaktu
W tym kroku zdefiniujesz plik system
makefile.
Utwórz plik makefile, który definiuje pakiety dla partycji
system
. Na przykład utwórz plikoem_system.mk
o tej zawartości:$(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),)
W pliku
device.mk
dziedzicz wspólny plik makefile dla partycjisystem
i włącz sprawdzanie wymagań dotyczących ścieżki artefaktu. 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 artefaktu
Gdy wartość PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS
jest ustawiona na true
lub strict
, system kompilacji uniemożliwia instalowanie pakietów zdefiniowanych w innych plikach makefile w ścieżkach zdefiniowanych w require-artifacts-in-path
i uniemożliwia instalowanie pakietów zdefiniowanych w bieżącym pliku makefile w artefaktach poza ścieżkami zdefiniowanymi w require-artifacts-in-path
.
W powyższym przykładzie, gdy zmienna PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS
ma wartość strict
, pliki makefile poza oem_system.mk
nie mogą zawierać modułów zainstalowanych w partycjach root
ani system
. Aby uwzględnić te moduły, musisz zdefiniować je w samym pliku oem_system.mk
lub w dołączonym pliku makefile.
Próby instalacji modułów w niedozwolonych ścieżkach powodują przerwanie kompilacji. Aby naprawić podziały, wykonaj jedną z tych czynności:
Opcja 1. Dołącz moduł systemowy do plików makefile znajdujących się w
oem_system.mk
. Dzięki temu wymaganie dotyczące ścieżki artefaktu jest spełnione (ponieważ moduły znajdują się teraz w dołączonym pliku makefile), co umożliwia instalację w zbiorze ścieżek w `require-artifacts-in-path`.Opcja 2. Zainstaluj moduły na partycji
system_ext
lubproduct
(i nie instaluj modułów na partycjisystem
).Opcja 3. Dodaj moduły do
PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST
. Zawiera listę modułów, które można zainstalować.
Krok 2. Opróżnij listę dozwolonych
W tym kroku usuń PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST
, aby wszystkie urządzenia udostępniające oem_system.mk
mogły też udostępniać pojedynczy obraz system
. Aby opróżnić listę dozwolonych, przenieś dowolne moduły z listy do partycji system_ext
lub product
albo dodaj je do system
make files. Ten krok jest opcjonalny, ponieważ zdefiniowanie wspólnego obrazu system
nie jest wymagane do włączenia egzekwowania zasad dotyczących interfejsu produktu. Opróżnienie listy dozwolonych jest jednak przydatne do określania granicy system
za pomocą system_ext
.
Krok 3. Wymuszanie interfejsów natywnych
W tym kroku ustawiasz PRODUCT_PRODUCT_VNDK_VERSION := current
, a następnie szukasz błędów kompilacji i błędów środowiska wykonawczego oraz je rozwiązujesz. Aby sprawdzić uruchamianie urządzenia i dzienniki oraz znaleźć i naprawić błędy łączenia w czasie działania:
Ustaw
PRODUCT_PRODUCT_VNDK_VERSION := current
.Zbuduj urządzenie i poszukaj błędów kompilacji. Prawdopodobnie zobaczysz kilka błędów kompilacji z powodu brakujących wersji produktu lub wersji podstawowych. Typowe przerwy to:
- Żaden moduł
hidl_interface
, który maproduct_specific: true
, nie będzie dostępny w przypadku modułów systemowych. Aby to naprawić, zastąpproduct_specific: true
kodemsystem_ext_specific: true
. - W modułach może brakować wersji produktu wymaganej w modułach produktów. Aby rozwiązać ten problem, udostępnij moduł partycji
product
, ustawiając wartośćproduct_available: true
, lub przenieś moduł do partycjiproduct
, ustawiając wartośćproduct_specific: true
.
- Żaden moduł
Napraw błędy kompilacji i sprawdź, czy urządzenie zostało prawidłowo skompilowane.
Wgraj obraz i sprawdź, czy podczas uruchamiania urządzenia i w dziennikach nie występują błędy czasu działania.
- Jeśli tag
linker
z logu przypadku testowego zawiera komunikatCANNOT LINK EXECUTABLE
, oznacza to, że w pliku make brakuje zależności (i nie została ona zarejestrowana w czasie kompilacji). - Aby sprawdzić to w systemie kompilacji, dodaj wymaganą bibliotekę do pola
shared_libs:
lubrequired:
.
- Jeśli tag
Rozwiąż problem z brakującymi zależnościami, korzystając z podanych wyżej wskazówek.
Krok 4. Wymuszanie interfejsów Javy
W tym kroku ustawisz PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true
, a następnie znajdziesz i naprawisz wynikające z tego błędy kompilacji. Wyszukaj 2 rodzaje błędów:
Błędy typu linku Ten błąd oznacza, że aplikacja zawiera linki do modułów Java, które mają szerszy zakres
sdk_version
. Aby to naprawić, możesz rozszerzyćsdk_version
aplikacji lub ograniczyć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ż znajduje się on w ukrytym interfejsie API. Aby rozwiązać ten problem, użyj widocznego (nieukrytego) interfejsu API lub znajdź alternatywne rozwiązanie. 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ź zachowania w czasie działania
Na tym etapie sprawdzisz, czy działanie w czasie działania jest zgodne z oczekiwaniami. W przypadku aplikacji, które można debugować, możesz monitorować użycie ukrytych interfejsów API za pomocą logu, korzystając z funkcji StrictMode.detectNonSdkApiUsage
(która generuje log, gdy aplikacja używa ukrytego interfejsu API). Możesz też użyć narzędzia do analizy statycznej veridex, aby uzyskać informacje o rodzaju użycia (łączenie lub odbicie), poziomie ograniczeń i stosie wywołań.
Składnia Veridex:
./art/tools/veridex/appcompat.sh --dex-file={apk file}
Przykładowy wynik weryfikacji:
#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 narzędzia veridex znajdziesz w artykule Testowanie za pomocą narzędzia veridex.
Krok 6. Zaktualizuj plik device.mk
Po usunięciu wszystkich błędów kompilacji i błędów czasu działania oraz sprawdzeniu, czy zachowania w czasie działania są zgodne z oczekiwaniami, ustaw w device.mk
te wartości:
PRODUCT_PRODUCT_VNDK_VERSION := current
PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true