Applicazione delle interfacce di partizione del prodotto

Android 11 separa la partizione product , rendendola indipendente dalle partizioni del 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'imposizione dell'interfaccia per le partizioni vendor ).

Applicazione delle interfacce native

Per abilitare 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 è maggiore di 29.) L'applicazione consente:

  • Moduli nativi nella partizione product da collegare:
    • Staticamente o dinamicamente ad altri moduli nella partizione product che includono librerie statiche, condivise o di intestazione.
    • Dinamicamente alle librerie VNDK nella partizione system .
  • Librerie JNI negli APK disaggregati nella partizione product per collegarsi alle librerie in /product/lib o /product/lib64 (in aggiunta alle librerie NDK).

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

Crea applicazione del tempo (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 del 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 collegarsi ad altre librerie che specificano product_specific: true o product_available: true nei relativi file Android.bp .

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

La tabella seguente riepiloga le proprietà Android.bp utilizzate per creare varianti di immagine.

Proprietà in Android.bp Varianti create
Prima dell'esecuzione Dopo l'esecuzione
predefinito (nessuno) nucleo

(include /system , /system_ext e /product )

nucleo

(include /system e /system_ext ma non /product )

system_ext_specific: true nucleo nucleo
product_specific: true nucleo Prodotto
vendor: true venditore venditore
vendor_available: true nucleo, venditore nucleo, venditore
product_available: true N / A prodotto principale
vendor_available: true E product_available: true N / A nucleo, prodotto, fornitore
system_ext_specific: true E vendor_available: true nucleo, venditore nucleo, venditore
product_specific: true E vendor_available: true nucleo, venditore prodotto, venditore

Crea applicazione del tempo (Android.mk)

Quando l'imposizione dell'interfaccia nativa è abilitata, 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 . Il tentativo di collegarsi a moduli diversi da questi fa sì che il sistema di compilazione generi un errore di controllo del tipo di collegamento.

Applicazione in fase di esecuzione

Quando è abilitata l'applicazione dell'interfaccia nativa, 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 collegarsi alle librerie esterne alla partizione product (tuttavia, tali processi possono collegamento 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 .

Applicazione delle interfacce Java

Per abilitare l'imposizione dell'interfaccia Java, impostare 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 abilitata, l'applicazione consente/impedisce il seguente accesso.

API /sistema /sistema_est /Prodotto /venditore /dati
API pubblica
@SystemApi
API @hide

Come nella partizione vendor , un'app o una libreria Java nella partizione product può utilizzare solo API pubbliche e di sistema; non è consentito il collegamento a una libreria che utilizza API nascoste. Questa restrizione include il collegamento in fase di compilazione e la riflessione in fase di esecuzione.

Costruisci l'applicazione del tempo

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 campo sdk_version delle app nella partizione product deve essere compilato con la versione current , system_current o numerica dell'API e il campo platform_apis deve essere vuoto.

Applicazione in fase di esecuzione

Il runtime Android verifica che le app nella partizione product non utilizzino API nascoste, inclusa la riflessione. Per maggiori dettagli, fare riferimento a Restrizioni sulle interfacce non SDK .

Abilitazione dell'applicazione dell'interfaccia del prodotto

Utilizzare i passaggi contenuti in questa sezione per abilitare l'applicazione dell'interfaccia del prodotto.

Fare un passo Compito Necessario
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 Pulisci l'elenco dei consentiti. N
3 Applica interfacce native e identifica gli errori di collegamento in fase di runtime (può essere eseguito in parallelo con l'attuazione Java). Y
4 Applica le interfacce Java e verifica il comportamento in fase di esecuzione (può essere eseguito in parallelo con l'applicazione nativa). Y
5 Controlla i comportamenti in fase di esecuzione. Y
6 Aggiorna device.mk con l'applicazione dell'interfaccia del prodotto. Y

Passaggio 1: crea il makefile e abilita il controllo del percorso degli artefatti

In questo passaggio si definisce il makefile system .

  1. Crea un 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 makefile comune per la partizione system e abilita il controllo dei requisiti del percorso dell'artefatto. Per 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 ai pacchetti definiti in altri makefile di installarsi nei percorsi definiti in require-artifacts-in-path e impedisce ai pacchetti definiti nel makefile corrente di installare artefatti 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 oem_system.mk non possono includere moduli installati nella partizione root o system . Per includere questi moduli, è necessario definirli nel file oem_system.mk stesso o in un makefile incluso. I tentativi di installare moduli su percorsi non consentiti causano interruzioni della compilazione. Per correggere le interruzioni, effettuare una delle seguenti operazioni:

  • Opzione 1: includere il modulo di sistema nei makefile inclusi in oem_system.mk . Ciò fa sì che il requisito del percorso dell'artefatto sia 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: installare i moduli nella partizione system_ext o product (e non installare i moduli nella partizione system ).

  • Opzione 3: aggiungere moduli a PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST . Elenca i moduli consentiti da installare.

Passaggio 2: svuota l'elenco consentito

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, spostare tutti i moduli nell'elenco nella partizione system_ext o product oppure aggiungerli ai file make system . Questo passaggio è facoltativo perché non è necessaria la definizione di un'immagine system comune per abilitare l'applicazione dell'interfaccia del prodotto. Tuttavia, svuotare l'elenco consentito è utile per definire il limite system con system_ext .

Passaggio 3: applicare le interfacce native

In questo passaggio imposti PRODUCT_PRODUCT_VNDK_VERSION := current , quindi cerchi gli errori di build e di runtime e li risolvi. Per controllare l'avvio e i registri del dispositivo e individuare e correggere gli errori di collegamento in runtime:

  1. Imposta PRODUCT_PRODUCT_VNDK_VERSION := current .

  2. Costruisci il dispositivo e cerca gli errori di costruzione. È probabile che vengano visualizzate alcune interruzioni di build per varianti di prodotto mancanti o varianti principali. Le pause comuni includono:

    • Qualsiasi modulo hidl_interface che abbia product_specific: true non sarà disponibile per i moduli di sistema. Per risolvere il problema, sostituire product_specific: true con system_ext_specfic: true .
    • Ai moduli potrebbe mancare la variante di prodotto richiesta per i moduli di prodotto. Per risolvere il problema, rendi il modulo disponibile nella partizione product impostando product_available: true oppure sposta il modulo nella partizione del product impostando product_specific: true .
  3. Risolvi gli errori di creazione e assicurati che il dispositivo venga creato correttamente.

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

    • Se il tag linker da un registro del test case mostra un messaggio CANNOT LINK EXECUTABLE , nel file make manca una dipendenza (e non è stato acquisito in fase di compilazione).
    • Per verificarlo dal sistema di compilazione, aggiungi la libreria richiesta al campo shared_libs: o required:
  5. Risolvi le dipendenze mancanti utilizzando le indicazioni fornite sopra.

Passaggio 4: applicare le interfacce Java

In questo passaggio imposti PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true , quindi trovi e correggi gli errori di compilazione risultanti. Cerca due tipi specifici di errori:

  • Errori nel tipo di collegamento. Questo errore indica che un'app si collega a moduli Java con una sdk_version più ampia. Per risolvere il problema, puoi ampliare sdk_version dell'app o limitare 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 nei 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: verificare i comportamenti di runtime

In questo passaggio si verifica che i comportamenti di runtime siano quelli previsti. Per le app di cui è possibile eseguire il debug, puoi monitorare l'utilizzo dell'API nascosta 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 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 dettagli sull'utilizzo di Veridex, fare riferimento a 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 quelli previsti, imposta quanto segue in device.mk :

  • PRODUCT_PRODUCT_VNDK_VERSION := current
  • PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true