Android 11 separa la partizione product, rendendola indipendente dalle partizioni system e vendor. Nell'ambito di queste modifiche, ora puoi controllare l'accesso della partizione product alle interfacce native e Java (in modo simile al funzionamento dell'applicazione forzata dell'interfaccia per le partizioni vendor).
Applicare forzatamente le interfacce native
Per attivare l'applicazione forzata dell'interfaccia nativa, imposta PRODUCT_PRODUCT_VNDK_VERSION su current. (La versione viene impostata automaticamente su current quando il livello API di spedizione per la destinazione è maggiore di 29.) L'applicazione forzata consente:
- I moduli nativi nella partizione
productda collegare:- Staticamente o dinamicamente ad altri moduli nella partizione
productche includono librerie statiche, condivise o di intestazione. - Dinamicamente alle librerie VNDK nella partizione
system.
- Staticamente o dinamicamente ad altri moduli nella partizione
- Le librerie JNI negli APK separati nella partizione
productda collegare alle librerie in/product/libo/product/lib64(oltre alle librerie NDK).
L'applicazione forzata non consente altri link a partizioni diverse dalla partizione product.
Applicazione forzata in fase di compilazione (Android.bp)
In Android 11, i moduli di sistema possono creare una variante dell'immagine del prodotto oltre alle varianti dell'immagine principale e del fornitore. Quando l'applicazione forzata dell'interfaccia nativa è attivata (PRODUCT_PRODUCT_VNDK_VERSION è impostato su current):
I moduli nativi nella partizione
productsi trovano nella variante del prodotto anziché nella variante principale.I moduli con
product_available: truenei fileAndroid.bpsono disponibili per la variante del prodotto.Le librerie o i file binari che specificano
product_specific: truepossono essere collegati ad altre librerie che specificanoproduct_specific: trueoproduct_available: truenei fileAndroid.bp.Le librerie VNDK devono avere
product_available: truenei fileAndroid.bpin modo che i file binariproductpossano essere collegati alle librerie VNDK.
La tabella seguente riassume le proprietà Android.bp utilizzate per creare le varianti dell'immagine.
| Proprietà in Android.bp | Varianti create | |
|---|---|---|
| Prima dell'applicazione forzata | Dopo l'applicazione forzata | |
| default (nessuna) | core
(include /system, /system_ext e
/product) |
core
(include /system e /system_ext, ma non
/product) |
system_ext_specific: true |
core | core |
product_specific: true |
core | product |
vendor: true |
vendor | vendor |
vendor_available: true |
core, vendor | core, vendor |
product_available: true |
N/D | core, product |
vendor_available: true AND product_available:
true |
N/D | core, product, vendor |
system_ext_specific: true AND vendor_available:
true |
core, vendor | core, vendor |
product_specific: true AND vendor_available:
true |
core, vendor | product, vendor |
Applicazione forzata in fase di build (Android.mk)
Quando l'applicazione forzata dell'interfaccia nativa è attivata, i moduli nativi installati nella
product partizione hanno un tipo di link native:product che può essere collegato solo a
altri native:product o native:vndk moduli. Se tenti di collegare altri moduli, il sistema di compilazione genera un errore di controllo del tipo di link.
Applicazione forzata in fase di runtime
Quando l'applicazione forzata dell'interfaccia nativa è attivata, la configurazione del linker per il linker bionico non consente ai processi di sistema di utilizzare le librerie product, creando una sezione product per i processi product che non possono essere collegati a librerie esterne alla partizione product (tuttavia, questi processi possono essere collegati alle librerie VNDK). I tentativi di violare la configurazione del link di runtime causano l'errore del processo e generano un messaggio di errore CANNOT LINK EXECUTABLE.
Applicare forzatamente le interfacce Java
Per attivare l'applicazione forzata dell'interfaccia Java, imposta PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE su true. (Il valore viene impostato automaticamente su true quando il livello API di spedizione per la destinazione è maggiore di 29.) Quando è attivata, l'applicazione forzata consente o non consente il seguente accesso:
| API | /system | /system_ext | /product | /vendor | /data |
|---|---|---|---|---|---|
| API pubblica | |||||
| @SystemApi | |||||
| API @hide |
Come nella partizione vendor, un'app o una libreria Java nella partizione product può utilizzare solo le API pubbliche e di sistema; non è consentito il collegamento a una libreria che utilizza API nascoste. Questa limitazione include il collegamento in fase di build e la reflection in fase di runtime.
Applicazione forzata in fase di build
In fase di compilazione, Make e Soong verificano che i moduli Java nella partizione product non utilizzino API nascoste controllando i campi platform_apis e sdk_version. Il sdk_version delle app nella partizione product deve
essere compilato con current, system_current o la versione numerica dell'API, mentre
il campo platform_apis deve essere vuoto.
Applicazione forzata in fase di runtime
Il runtime di Android verifica che le app nella partizione product non utilizzino API nascoste, inclusa la reflection. Per maggiori dettagli, consulta Limitazioni delle
interfacce non SDK.
Attivare l'applicazione forzata dell'interfaccia del prodotto
Segui i passaggi descritti in questa sezione per attivare l'applicazione forzata dell'interfaccia del prodotto.
| Passaggio | Attività | Obbligatorio |
|---|---|---|
| 1 | Definisci il tuo makefile di sistema che specifica i pacchetti per la
system partizione, quindi imposta il controllo dei requisiti del percorso degli artefatti
in device.mk (per impedire l'installazione di moduli non di sistema
nella system partizione). |
N |
| 2 | Libera spazio nella lista consentita. | N |
| 3 | Applica forzatamente le interfacce native e identifica gli errori di link di runtime (può essere eseguito in parallelo con l'applicazione forzata di Java). | Y |
| 4 | Applica forzatamente le interfacce Java e verifica il comportamento di runtime (può essere eseguito in parallelo con l'applicazione forzata nativa). | Y |
| 5 | Controlla i comportamenti di runtime. | Y |
| 6 | Aggiorna device.mk con l'applicazione forzata dell'interfaccia del prodotto. |
Y |
Passaggio 1: crea il makefile e attiva il controllo del percorso degli artefatti
In questo passaggio definisci il makefile system.
Crea un makefile che definisca i pacchetti per la partizione
system. Ad esempio, crea un fileoem_system.mkcon i seguenti contenuti:$(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),)Nel file
device.mk, eredita il makefile comune per la partizionesysteme attiva il controllo dei requisiti del percorso degli artefatti. Ad esempio:$(call inherit-product, $(SRC_TARGET_DIR)/product/oem_system.mk) # Enable artifact path requirements checking PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := strict
Informazioni sui requisiti del percorso degli artefatti
Quando PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS è impostato su true o strict, il sistema di compilazione impedisce l'installazione dei pacchetti definiti in altri makefile nei percorsi definiti in require-artifacts-in-path e impedisce l'installazione degli artefatti dei pacchetti definiti nel makefile corrente al di fuori dei percorsi definiti in require-artifacts-in-path.
Nell'esempio precedente, con PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS impostato su
strict, i makefile esterni a oem_system.mk non possono includere moduli installati nella partizione root o system. Per includere questi moduli, devi definirli nel file oem_system.mk stesso o in un makefile incluso.
I tentativi di installare i moduli nei percorsi non consentiti causano interruzioni della build. Per risolvere le interruzioni, esegui una delle seguenti operazioni:
Opzione 1: includi il modulo di sistema nei makefile inclusi in
oem_system.mk. In questo modo, il requisito del percorso degli artefatti viene soddisfatto (poiché i moduli ora esistono in un makefile incluso) e quindi consente l'installazione nell'insieme di percorsi in `require-artifacts-in-path.Opzione 2: installa i moduli nella partizione
system_extoproduct(e non installare i moduli nella partizionesystem).Opzione 3: aggiungi i moduli a
PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST. In questo modo vengono elencati i moduli consentiti da installare.
Passaggio 2: svuota la lista consentita
In questo passaggio, rendi PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST
vuoto in modo che tutti i dispositivi che condividono oem_system.mk possano condividere anche una singola immagine system. Per svuotare la lista consentita, sposta tutti i moduli nell'elenco nella
system_ext o product partizione oppure aggiungili ai system make files. Questo passaggio è facoltativo perché la definizione di un'immagine system comune non è obbligatoria per attivare l'applicazione forzata dell'interfaccia del prodotto. Tuttavia, svuotare la lista consentita è
utile per definire il system limite con system_ext.
Passaggio 3: applica forzatamente le interfacce native
In questo passaggio, imposta PRODUCT_PRODUCT_VNDK_VERSION := current, quindi cerca e risolvi gli errori di build e di runtime. Per controllare l'avvio e i log del dispositivo e trovare e correggere gli errori di link di runtime:
Imposta
PRODUCT_PRODUCT_VNDK_VERSION := current.Crea il dispositivo e cerca gli errori di build. È probabile che si verifichino alcune interruzioni della build per le varianti del prodotto o le varianti principali mancanti. Le interruzioni comuni includono:
- Qualsiasi modulo
hidl_interfaceconproduct_specific: truenon sarà disponibile per i moduli di sistema. Per risolvere il problema, sostituisciproduct_specific: trueconsystem_ext_specific: true. - I moduli potrebbero non avere la variante del prodotto richiesta per i moduli del prodotto. Per risolvere il problema, rendi il modulo disponibile per la partizione
productimpostandoproduct_available: trueoppure sposta il modulo nella partizioneproductimpostandoproduct_specific: true.
- Qualsiasi modulo
Risolvi gli errori di build e assicurati che la build del dispositivo venga eseguita correttamente.
Flash l'immagine e cerca gli errori di runtime nell'avvio e nei log del dispositivo.
- Se il tag
linkerdi un log di uno scenario di test mostra un messaggioCANNOT LINK EXECUTABLE, significa che nel file make manca una dipendenza (e non è stata acquisita in fase di tempo di compilazione). - Per controllarlo dal sistema di compilazione, aggiungi la libreria richiesta al campo
shared_libs:orequired:.
- Se il tag
Risolvi le dipendenze mancanti seguendo le indicazioni riportate sopra.
Passaggio 4: applica forzatamente le interfacce Java
In questo passaggio, imposta PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true, quindi cerca e correggi gli errori di build risultanti. Cerca due tipi specifici di errori:
Errori di tipo di link. Questo errore indica che un'app è collegata a moduli Java con un
sdk_versionpiù ampio. Per risolvere il problema, puoi ampliare l'sdk_versiondell'app o limitare l'sdk_versiondella libreria. Esempio di errore: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.Errori di simboli. Questo errore indica che non è possibile trovare un simbolo perché si trova in un'API nascosta. Per risolvere il problema, utilizza un'API visibile (non nascosta) o trova un'alternativa. Esempio di errore:
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
Passaggio 5: controlla i comportamenti di runtime
In questo passaggio, verifica che i comportamenti di runtime siano quelli previsti. Per le app di cui è possibile eseguire il debug, puoi monitorare l'utilizzo delle API nascoste tramite il log utilizzando StrictMode.detectNonSdkApiUsage (che genera un log quando l'app utilizza un'API nascosta). In alternativa, puoi utilizzare lo strumento di analisi statica
veridex
per ottenere il tipo di utilizzo (collegamento o reflection),
il livello di limitazione e lo stack di chiamate.
Sintassi di Veridex:
./art/tools/veridex/appcompat.sh --dex-file={apk file}Esempio di risultato di 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;
Per maggiori dettagli sull'utilizzo di veridex, consulta Testare utilizzando lo strumento veridex.
Passaggio 6: aggiorna device.mk
Dopo aver corretto tutti gli errori di build e di runtime e aver verificato che i comportamenti di runtime siano quelli previsti, imposta quanto segue in device.mk:
PRODUCT_PRODUCT_VNDK_VERSION := currentPRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true