Applica le interfacce di partizione dei prodotti

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 le 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 dell'API di distribuzione per la destinazione è superiore a 29. L'applicazione forzata consente di:

  • 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.
  • Librerie JNI negli APK non raggruppati nella partizione product per collegarsi alle librerie in /product/lib o /product/lib64 (oltre alle librerie NDK).

L'applicazione delle norme non consente altri collegamenti a partizioni diverse dalla partizione product.

Applicazione forzata del tempo di creazione (Android.bp)

In Android 11, i moduli di sistema possono creare una variante dell'immagine del prodotto, oltre alle varianti di immagini di base e del fornitore. Quando l'applicazione dell'interfaccia nativa è attivata (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 file Android.bp sono disponibili per la variante del prodotto.

  • Le librerie o i file binari che specificano product_specific: true possono fare riferimento ad altre librerie che specificano product_specific: true o product_available: true nei file Android.bp.

  • Le librerie VNDK devono avere product_available: true nei file Android.bp in modo che i binari product possano collegarsi alle librerie VNDK.

La seguente tabella riassume le proprietà Android.bp utilizzate per creare varianti delle immagini.

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 principale, fornitore
product_available: true N/D core, prodotto
vendor_available: true AND product_available: true N/D core, prodotto, fornitore
system_ext_specific: true AND vendor_available: true principale, fornitore principale, fornitore
product_specific: true AND vendor_available: true core, vendor prodotto, fornitore

Applicazione del tempo di creazione (Android.mk)

Quando l'applicazione dell'interfaccia nativa è attivata, i moduli nativi installati nella partizione product hanno un tipo di collegamento 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 alle librerie al di fuori della partizione product (tuttavia, questi processi possono collegarsi alle librerie VNDK). I tentativi di violare la configurazione del collegamento di runtime causano il fallimento del processo e generano un messaggio di errore CANNOT LINK EXECUTABLE.

Applicare le 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 dell'API di spedizione per la destinazione è superiore a 29. Se l'applicazione delle norme è attivata, consente o meno 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 vendor è autorizzata a utilizzare solo API pubbliche e di sistema. Il collegamento a una libreria che utilizza API nascoste non è consentito.product Questa limitazione include il collegamento in fase di compilazione e la riflessione in fase di esecuzione.

Applicazione forzata della fase di creazione

In fase di creazione, Make and 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 una versione numerica dell'API e il campo platform_apis deve essere vuoto.

Applicazione del runtime

Il runtime di Android verifica che le app nella partizione product non utilizzino API nascoste, inclusa la riflessione. Per maggiori dettagli, consulta Limitazioni relative 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 file makefile di sistema che specifica i pacchetti per la partizione system, quindi imposta il controllo dei requisiti del percorso degli elementi nell'device.mk (per impedire l'installazione di moduli non di sistema nella partizione system). N
2 Ripulisci l'elenco consentito. N
3 Applica le interfacce native e identifica gli errori di collegamento del runtime (può essere eseguito in parallelo con l'applicazione forzata di 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 di runtime. Y
6 Aggiorna device.mk con l'applicazione dell'interfaccia di prodotto. Y

Passaggio 1: crea il file makefile e abilita il controllo del percorso dell'elemento

In questo passaggio, definisci il file makefile system.

  1. Crea un file makefile che definisce i pacchetti per la partizione system. Ad esempio, crea un file oem_system.mk con quanto segue:

    $(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. Nel file device.mk, eredita il file makefile comune per la partizione system e abilita il controllo dei requisiti del percorso dell'elemento. 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 relativi al percorso dell'elemento

Quando PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS è impostato su true o strict, il sistema di compilazione impedisce l'installazione dei pacchetti definiti in altri file make nei percorsi definiti in require-artifacts-in-path e impedisce ai pacchetti definiti nel file make corrente di installare elementi al di fuori dei percorsi definiti in require-artifacts-in-path.

Nell'esempio precedente, con PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS impostato su strict, i file make esterni a oem_system.mk non possono includere i moduli installati nella partizione root o system. Per includere questi moduli, devi definirli nel file oem_system.mk stesso o in un file make incluso. I tentativi di installare moduli in percorsi non consentiti causano interruzioni della build. Per correggere le interruzioni, esegui una delle seguenti operazioni:

  • Opzione 1: includi il modulo di sistema nei file make inclusi in oem_system.mk. In questo modo, il requisito del percorso dell'elemento è soddisfatto (poiché i moduli ora esistono in un file make incluso) e consente l'installazione nell'insieme di percorsi in "require-artifacts-in-path".

  • Opzione 2: installa i moduli nella partizione system_ext o product (e non nella partizione system).

  • Opzione 3: aggiungi moduli al PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST. Questo elenco elenca i moduli consentiti da installare.

Passaggio 2: svuota l'elenco consentito

In questo passaggio, imposti PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST vuoto in modo che tutti i dispositivi che condividono oem_system.mk possano condividere anche una singola system immagine. Per svuotare l'elenco consentito, sposta i moduli nell'elenco nella partizione system_ext o product oppure aggiungili ai file di creazione system. Questo passaggio è facoltativo perché la definizione di un'immagine system comune non è obbligatoria per attivare l'applicazione dell'interfaccia del prodotto. Tuttavia, svuotare l'elenco consentito è utile per definire il confine di system con system_ext.

Passaggio 3: applica le interfacce native

In questo passaggio, imposti PRODUCT_PRODUCT_VNDK_VERSION := current, poi cerchi gli errori di compilazione e di runtime e li risolvi. Per controllare l'avvio del dispositivo e i log e trovare e correggere gli errori di collegamento del runtime:

  1. Imposta PRODUCT_PRODUCT_VNDK_VERSION := current.

  2. Esegui la build del dispositivo e cerca eventuali errori di compilazione. È probabile che vengano visualizzate alcune interruzioni della compilazione per le varianti di prodotto o le varianti principali mancanti. Le interruzioni più comuni includono:

    • Qualsiasi modulo hidl_interface che contenga product_specific: true non sarà disponibile per i moduli di sistema. Per risolvere il problema, sostituisci product_specific: true con system_ext_specific: true.
    • Nei moduli potrebbe mancare la variante del prodotto richiesta per i moduli del prodotto. Per risolvere il problema, rendi il modulo disponibile per la partizione product impostando product_available: true o sposta il modulo nella partizione product impostando product_specific: true.
  3. Risolvi gli errori di compilazione e assicurati che la compilazione del dispositivo venga eseguita correttamente.

  4. Esegui il flashing dell'immagine e cerca gli errori di runtime nell'avvio e nei log del dispositivo.

    • Se il tag linker di un log del caso di test mostra un messaggio CANNOT LINK EXECUTABLE, nel file make manca una dipendenza (che non è stata acquisita al momento della compilazione).
    • Per controllarlo dal sistema di compilazione, aggiungi la libreria richiesta al shared_libs: o al campo required:.
  5. Risolvi le dipendenze mancanti seguendo le indicazioni riportate sopra.

Passaggio 4: applica le interfacce Java

In questo passaggio dovrai impostare PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true, quindi trovare e correggere gli errori di compilazione risultanti. Cerca due tipi specifici di errori:

  • Errori relativi al tipo di link. Questo errore indica che un'app si collega a moduli Java con un sdk_version più ampio. Per risolvere il problema, puoi ampliare il valore sdk_version dell'app o limitare i 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 relativi ai 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 verificherai che i comportamenti di runtime siano quelli previsti. Per le app debugging, puoi monitorare l'utilizzo delle API nascoste tramite i 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 limitazione e la pila di chiamate.

  • Sintassi Veridex:

    ./art/tools/veridex/appcompat.sh --dex-file={apk file}
  • Esempio di risultato 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 Eseguire il test utilizzando lo strumento Veridex.

Passaggio 6: aggiorna device.mk

Dopo aver corretto tutti gli errori di compilazione e di runtime e aver verificato che i comportamenti di runtime siano come previsti, imposta quanto segue in device.mk:

  • PRODUCT_PRODUCT_VNDK_VERSION := current
  • PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true