Android 11 odłącza partycję product
, dzięki czemu staje się 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 (co działa podobnie do wymuszania interfejsu w przypadku partycji vendor
).
Wymuś interfejsy natywne
Aby włączyć natywny interfejs, ustaw wartość PRODUCT_PRODUCT_VNDK_VERSION
na current
. (wersja jest automatycznie ustawiana na current
, gdy poziom interfejsu Shipping API dla celu jest większy niż 29). Egzekwowanie umożliwia:
- Natywne moduły w partycji
product
, które chcesz połączyć:- Statycznie lub dynamicznie do innych modułów w partycji
product
, które obejmują biblioteki statyczne, współdzielone lub nagłówkowe. - Dynamicznie do bibliotek VNDK na partycji
system
.
- Statycznie lub dynamicznie do innych modułów w partycji
- biblioteki JNI w niespakowanych plikach APK na partycji
product
, aby połączyć je z bibliotekami w folderze/product/lib
lub/product/lib64
(oprócz bibliotek NDK);
Zespół ds. egzekwowania zasad nie zezwala na inne linki do partycji niż partycja product
.
Egzekwowanie w czasie kompilacji (Android.bp)
W Androidzie 11 moduły systemowe mogą tworzyć warianty obrazów produktów oprócz podstawowych i wariantów obrazów dostawcy. Gdy jest włączone egzekwowanie interfejsu natywnego (opcja PRODUCT_PRODUCT_VNDK_VERSION
ma wartość current
):
Natywne moduły w podziale
product
znajdują się w wersji produktu, a nie w wersji podstawowej.Moduły z wartością
product_available: true
w plikuAndroid.bp
są dostępne dla wariantu produktu.Biblioteki lub pliki binarne, które podają
product_specific: true
, mogą zawierać linki do innych bibliotek, które podająproduct_specific: true
lubproduct_available: true
w plikachAndroid.bp
.Biblioteki VNDK muszą zawierać
product_available: true
w plikachAndroid.bp
, aby pliki binarneproduct
mogły się łączyć z bibliotekami VNDK.
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 warianty | |
---|---|---|
Przed egzekwowaniem | Po egzekwowaniu | |
domyślnie (brak) | podstawowe: (w tym /system , /system_ext i /product ); |
podstawowe
(obejmuje /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 | core, product, vendor |
system_ext_specific: true ORAZ vendor_available:
true |
core, vendor | core, vendor |
product_specific: true ORAZ vendor_available:
true |
core, vendor | produkt, dostawca |
Egzekwowanie w czasie kompilacji (Android.mk)
Gdy włączone jest egzekwowanie natywnych interfejsów, natywny moduł zainstalowany w partycji product
ma typ linku native:product
, który może wskazywać tylko inne moduły native:product
lub native:vndk
. Próba połączenia z innymi modułami spowoduje wygenerowanie przez system kompilacji błędu sprawdzania typu linku.
Egzekwowanie w czasie działania
Gdy włączone jest wymuszanie natywnego interfejsu, konfiguracja linkera dla binarnego linkera nie zezwala procesom systemowym na korzystanie z bibliotek product
. Tworzy ona sekcję product
dla procesów product
, które nie mogą łączyć się z bibliotekami spoza partycji product
(takie procesy mogą jednak łączyć się z bibliotekami VNDK). Próby naruszenia konfiguracji linku w czasie wykonywania powodują niepowodzenie procesu i generowanie komunikatu o błędzie CANNOT LINK EXECUTABLE
.
Wymuszanie interfejsów Java
Aby włączyć wymuszanie interfejsu Java, ustaw parametr PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE
na true
. (wartość jest automatycznie ustawiana na true
, gdy poziom interfejsu API dostawy dla celu jest większy niż 29). Po włączeniu egzekwowanie umożliwia zezwolenie lub odmowę zezwolenia na te rodzaje dostępu:
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. Łączenie z biblioteką, która korzysta z ukrytych interfejsów API, jest niedozwolone. Ta restrykcja obejmuje łączenie w czasie kompilacji i odwoływanie się do obiektów w czasie wykonywania.
Egzekwowanie czasu kompilacji
W momencie kompilacji Make i Soong sprawdzają, czy moduły Java w partycji product
nie używają ukrytych interfejsów API. Sprawdzają to, czy pola platform_apis
i sdk_version
są zaznaczone. Wartość sdk_version
aplikacji w partycji product
musi być równa current
, system_current
lub numerycznej wersji interfejsu API, a pole platform_apis
musi być puste.
Egzekwowanie w czasie działania
Środowisko uruchomieniowe Androida sprawdza, czy aplikacje na partycji product
nie korzystają z ukrytych interfejsów API, w tym z odzwierania. Szczegółowe informacje znajdziesz w artykule Ograniczenia interfejsów innych niż SDK.
Włączanie egzekwowania interfejsu
Aby włączyć egzekwowanie interfejsu produktu, wykonaj czynności opisane w tej sekcji.
Krok | Zadanie | Wymagane |
---|---|---|
1 | Zdefiniuj własny plik make systemu, który określa pakiety dla partycji system , a następnie ustaw sprawdzanie wymagań ścieżki artefaktów w device.mk (aby zapobiec instalowaniu modułów niesystemowych na partycji system ). |
N |
2 | Oczyść listę dozwolonych. | N |
3 | Wymuszanie interfejsów natywnych i identyfikowanie błędów linkowania w czasie wykonywania (można uruchamiać równolegle z wymuszaniem w Javi). | Y |
4 | Wymuszanie interfejsów Java i weryfikowanie zachowania w czasie działania (można uruchamiać równolegle z natywnym wymuszaniem). | Y |
5 | Sprawdź zachowanie podczas działania. | Y |
6 | Zaktualizuj device.mk , aby wymusić interfejs produktu. |
Y |
Krok 1. Utwórz makefile i włącz sprawdzanie ścieżki artefaktu
W tym kroku zdefiniujesz plik make system
.
Utwórz plik makefile, który definiuje pakiety dla partycji
system
. Na przykład utwórz plikoem_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),)
W pliku
device.mk
odziedzicz wspólny plik make dla partycjisystem
i włącz sprawdzanie wymagań dotyczących ścieżki artefaktu. 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 parametr PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS
ma wartość true
lub strict
, system kompilacji uniemożliwia instalowanie pakietów zdefiniowanych w innych plikach makefile na ścieżkach zdefiniowanych w require-artifacts-in-path
oraz uniemożliwia instalowanie artefaktów z pakietów zdefiniowanych w bieżącym pliku makefile poza ścieżkami zdefiniowanymi w require-artifacts-in-path
.
W powyższym przykładzie, gdy parametr PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS
ma wartość strict
, makefiles spoza oem_system.mk
nie mogą zawierać modułów zainstalowanych w partycji root
ani system
. Aby uwzględnić te moduły, musisz je zdefiniować w pliku oem_system.mk
lub w załączonym pliku makefile.
Próby instalacji modułów w niedozwolonych ścieżkach powodują przerwy w kompilacji. Aby naprawić przerwy, wykonaj jedną z tych czynności:
Opcja 1: dołącz moduł systemowy do plików make dołączonych w
oem_system.mk
. Dzięki temu spełnione są wymagania dotyczące ścieżki artefaktu (ponieważ moduły znajdują się teraz w załączonym pliku makefile), co umożliwia instalację na zestawie ścieżek w pliku require-artifacts-in-path.Opcja 2. Zainstaluj moduły w partycji
system_ext
lubproduct
(nie instaluj modułów w partycjisystem
).Opcja 3. Dodaj moduły do
PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST
. Lista dozwolonych modułów do zainstalowania.
Krok 2. Opróżnij listę dozwolonych
W tym kroku ustawiasz PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST
na pusty, aby wszystkie urządzenia udostępniające oem_system.mk
mogły też udostępniać jeden obraz system
. Aby opróżnić listę dozwolonych, przenieś wszystkie moduły z listy do partycji system_ext
lub product
albo dodaj je do plików make w folderze system
. Ten krok jest opcjonalny, ponieważ zdefiniowanie wspólnego obrazu system
nie jest wymagane do wdrożenia egzekwowania interfejsu produktu. Opróżnienie listy dozwolonych jest jednak przydatne do określenia granicy system
za pomocą system_ext
.
Krok 3. Wymuś stosowanie interfejsów natywnych
Na tym etapie ustawiasz PRODUCT_PRODUCT_VNDK_VERSION := current
, a potem sprawdzasz i naprawiasz błędy kompilacji i czasu wykonywania. Aby sprawdzić rozruch urządzenia i logi oraz znaleźć i naprawić błędy łączenia w czasie wykonywania:
Ustaw
PRODUCT_PRODUCT_VNDK_VERSION := current
.Utwórz urządzenie i sprawdź, czy nie ma błędów. Prawdopodobnie zobaczysz kilka przerw w kompilacji z powodu braku wersji produktu lub wersji głównych. Typowe przerwy:
- Moduł
hidl_interface
, który ma wartośćproduct_specific: true
, nie będzie dostępny dla modułów systemowych. Aby to naprawić, zastąpproduct_specific: true
kodemsystem_ext_specific: true
. - Moduł może nie mieć wersji produktu wymaganej dla modułów produktów. Aby to naprawić, udostępnij ten moduł partycji
product
, ustawiając wartośćproduct_available: true
, lub przenieś moduł do partycjiproduct
, ustawiając wartośćproduct_specific: true
.
- Moduł
Rozwiąż błędy kompilacji i upewnij się, że kompilacja urządzenia zakończyła się sukcesem.
Wgraj obraz i sprawdź, czy podczas uruchamiania i w dziennikach nie występują błędy czasu działania.
- Jeśli tag
linker
z logu testowego zawiera komunikatCANNOT LINK EXECUTABLE
, w pliku make brakuje zależności (nie został on uwzględniony podczas kompilacji). - Aby sprawdzić to w systemie kompilacji, dodaj wymaganą bibliotekę do pola
shared_libs:
lubrequired:
.
- Jeśli tag
Rozwiąż problem z brakami zależności, korzystając z podanych wyżej wskazówek.
Krok 4. Wymuś interfejsy Java
W tym kroku skonfigurujesz PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true
, a potem znajdziesz i naprawisz błędy kompilacji. Poszukaj 2 konkretnych typów błędów:
Błędy typu połączenia. Ten błąd wskazuje, że aplikacja zawiera linki do modułów Java, które mają szerszy
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 wskazuje, ż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ź alternatywę. 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ź zachowanie w czasie wykonywania
Na tym etapie sprawdzasz, czy działanie aplikacji jest zgodne z oczekiwaniami. W przypadku aplikacji, które można debugować, możesz monitorować użycie ukrytego interfejsu API, korzystając z pliku StrictMode.detectNonSdkApiUsage
(generuje on plik dziennika, gdy aplikacja używa ukrytego interfejsu API). Możesz też użyć narzędzia do analizy statycznej veridex, aby uzyskać informacje o typie użycia (linkowaniu lub odbiciu), poziomie ograniczeń i zbiorze 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 używaniu narzędzia veridex znajdziesz w artykule Testowanie za pomocą narzędzia veridex.
Krok 6. Zaktualizuj plik device.mk
Po naprawieniu wszystkich błędów kompilacji i błędów w czasie wykonywania oraz sprawdzeniu, czy zachowanie w czasie wykonywania jest zgodne z oczekiwaniami, ustaw w pliku device.mk
te wartości:
PRODUCT_PRODUCT_VNDK_VERSION := current
PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true