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 delle interfacce per le partizioni vendor
).
Applica interfacce native
Per attivare l'applicazione 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 è superiore a 29.) L'applicazione forzata consente:
- Moduli nativi nella partizione
product
da collegare:- In modo statico o dinamico ad altri moduli nella partizione
product
che includono librerie statiche, condivise o di intestazione. - In modo dinamico alle librerie VNDK nella partizione
system
.
- In modo statico o dinamico ad altri moduli nella partizione
- Librerie JNI negli APK non raggruppati nella partizione
product
a cui collegarsi librerie in/product/lib
o/product/lib64
(oltre alle librerie NDK).
L'applicazione non consente altri collegamenti a partizioni diverse dalla partizione product
.
Applicazione forzata del tempo di build (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
dell'interfaccia nativa è abilitata (PRODUCT_PRODUCT_VNDK_VERSION
è impostato su
current
):
I moduli nativi nella partizione
product
si trovano nella variante di prodotto anziché nella variante principale.I moduli con
product_available: true
nei fileAndroid.bp
sono disponibili per la variante del prodotto.Le librerie o i binari che specificano
product_specific: true
possono collegarsi ad altre librerie che specificanoproduct_specific: true
oproduct_available: true
nei relativi fileAndroid.bp
.Le librerie VNDK devono avere
product_available: true
nei fileAndroid.bp
in modo che i binariproduct
possano collegarsi alle librerie VNDK.
La seguente tabella riassume le proprietà Android.bp
utilizzate per creare varianti
dell'immagine.
Proprietà in Android.bp | Varianti create | |
---|---|---|
Prima dell'applicazione | Dopo l'applicazione | |
predefinito (nessuno) | core
(include /system , /system_ext e
/product ) |
core
(include /system e /system_ext ma non
/product ) |
system_ext_specific: true |
nucleo | nucleo |
product_specific: true |
nucleo | prodotto |
vendor: true |
fornitore | fornitore |
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 | prodotto, fornitore |
Applicazione forzata al momento della build (Android.mk)
Quando l'applicazione dell'interfaccia nativa è attivata, i moduli nativi installati nella
partizione product
hanno un tipo di link native:product
che può collegarsi solo ad altri moduli native:product
o native:vndk
. Se provi a collegarti a moduli diversi da questi, il sistema di compilazione genera un errore di controllo del tipo di link.
Applicazione di runtime
Quando l'applicazione dell'interfaccia nativa è attivata, la configurazione del linker per il
linker bionic non consente ai processi di sistema di utilizzare le librerie product
,
creando una sezione product
per i processi product
che non possono collegarsi a
librerie esterne alla partizione product
(tuttavia, questi processi possono collegarsi a
librerie VNDK). I tentativi di violare la configurazione del collegamento runtime causano
l'interruzione del processo e la generazione di un messaggio di errore CANNOT LINK EXECUTABLE
.
Applica interfacce Java
Per attivare l'applicazione 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.) Se l'opzione è abilitata, l'applicazione consente o non consente il seguente
accesso:
API | /system | /system_ext | /product | /vendor | /data |
---|---|---|---|---|---|
API pubblica | |||||
@SystemApi | |||||
@hide API |
Come nella partizione vendor
, un'app o una libreria Java nella partizione product
può utilizzare solo API pubbliche e di sistema; il collegamento a una libreria
che utilizza API nascoste non è consentito. Questa limitazione include il collegamento in fase di compilazione 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 e
il campo platform_apis
deve essere vuoto.
Applicazione di runtime
Android Runtime verifica che le app nella partizione product
non utilizzino
API nascoste, inclusa la reflection. Per i dettagli, consulta Limitazioni
alle interfacce
non SDK.
Attivare l'applicazione dell'interfaccia del prodotto
Segui i passaggi descritti in questa sezione per attivare l'applicazione dell'interfaccia del prodotto.
Passaggio | Attività | Obbligatorio |
---|---|---|
1 | Definisci il tuo makefile di sistema che specifica i pacchetti per la partizione system , quindi imposta il controllo dei requisiti del percorso degli artefatti in device.mk (per impedire l'installazione di moduli non di sistema nella partizione system ). |
N |
2 | Esegui la pulizia della lista consentita. | N |
3 | Applica interfacce native e identifica errori di collegamento di runtime (può essere eseguito in parallelo con l'applicazione Java). | Y |
4 | Applica le interfacce Java e verifica il comportamento del runtime (può essere eseguito in parallelo con l'applicazione nativa). | Y |
5 | Controlla i comportamenti del runtime. | Y |
6 | Aggiornamento di device.mk con l'applicazione dell'interfaccia del prodotto. |
Y |
Passaggio 1: crea il makefile e attiva il controllo del percorso dell'artefatto
In questo passaggio, definisci il makefile system
.
Crea un makefile che definisca i pacchetti per la partizione
system
. Ad esempio, crea un fileoem_system.mk
con 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 partizionesystem
e attiva il controllo dei requisiti del percorso dell'artefatto. 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 dell'artefatto
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 moduli in percorsi non consentiti causano interruzioni della build. Per correggere
le interruzioni, procedi in uno dei seguenti modi:
Opzione 1: includi il modulo di sistema nei makefile inclusi in
oem_system.mk
. In questo modo, il requisito del percorso dell'artefatto viene soddisfatto (poiché i moduli ora esistono in un makefile incluso) e quindi consente l'installazione nel set di percorsi in "require-artifacts-in-path".Opzione 2: installa i moduli nella partizione
system_ext
oproduct
(e non installarli nella partizionesystem
).Opzione 3: aggiungi moduli al
PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST
. Elenca 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 l'elenco consentito, sposta i moduli nell'elenco nella partizione
system_ext
o product
oppure aggiungili a system
per creare file. Questo passaggio è facoltativo perché la definizione di un'immagine system
comune non è necessaria per attivare l'applicazione dell'interfaccia del prodotto. Tuttavia, svuotare la lista consentita è
utile per definire il confine system
con system_ext
.
Passaggio 3: applica le interfacce native
In questo passaggio, imposta PRODUCT_PRODUCT_VNDK_VERSION := current
, quindi cerca
gli errori di compilazione e runtime e risolvili. Per controllare l'avvio e i log del dispositivo
e trovare e correggere gli errori di collegamento in fase di runtime:
Imposta
PRODUCT_PRODUCT_VNDK_VERSION := current
.Crea il dispositivo e cerca eventuali errori di build. È probabile che si verifichino alcuni errori di build per le varianti di prodotto o le varianti principali mancanti. Le pause più comuni includono:
- Qualsiasi modulo
hidl_interface
che haproduct_specific: true
non sarà disponibile per i moduli di sistema. Per risolvere il problema, sostituisciproduct_specific: true
consystem_ext_specific: true
. - Nei moduli potrebbe mancare la variante del prodotto richiesta per i moduli
del prodotto. Per risolvere il problema, rendi disponibile il modulo per la partizione
product
impostandoproduct_available: true
o sposta il modulo nella partizioneproduct
impostandoproduct_specific: true
.
- Qualsiasi modulo
Risolvi gli errori di build e assicurati che la build del dispositivo venga eseguita correttamente.
Carica l'immagine e cerca errori di runtime nell'avvio e nei log del dispositivo.
- Se il tag
linker
del log di uno scenario di test mostra un messaggioCANNOT LINK EXECUTABLE
, il file make non contiene una dipendenza (e non è stato acquisito in fase di compilazione). - Per verificarlo 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 le interfacce Java
In questo passaggio, imposta PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true
,
quindi trova e correggi gli errori di build risultanti. Cerca due tipi specifici di errori:
Errori relativi al tipo di collegamento. Questo errore indica che un'app si collega a moduli Java che hanno un
sdk_version
più ampio. Per risolvere il problema, puoi ampliare l'sdk_version
dell'app o limitare l'sdk_version
della libreria. Errore di esempio: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. Errore di esempio:
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, verifichi che i comportamenti di runtime siano quelli previsti. Per le app di cui è possibile eseguire il debug, puoi monitorare l'utilizzo di API nascoste tramite 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 riflessione),
il livello di restrizione e lo stack di chiamate.
Sintassi di Veridex:
./art/tools/veridex/appcompat.sh --dex-file={apk file}
Risultato di esempio 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 informazioni dettagliate 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 := current
PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true