Durchsetzung von Produktpartitionsschnittstellen

Android 11 entbündelt die product und macht sie unabhängig von den system und vendor . Im Rahmen dieser Änderungen können Sie jetzt den Zugriff der product auf native und Java-Schnittstellen steuern (ähnlich wie die Schnittstellendurchsetzung für vendor funktioniert).

Durchsetzung nativer Schnittstellen

Um die Durchsetzung der nativen Schnittstelle zu aktivieren, setzen Sie PRODUCT_PRODUCT_VNDK_VERSION auf current . (Die Version wird automatisch auf current gesetzt, wenn die Versand-API-Ebene für das Ziel größer als 29 ist.) Durch die Durchsetzung ist Folgendes möglich:

  • Native Module in der product zum Verknüpfen:
    • Statisch oder dynamisch zu anderen Modulen in der product , die statische, gemeinsam genutzte oder Header-Bibliotheken enthalten.
    • Dynamisch zu VNDK-Bibliotheken in der system .
  • JNI-Bibliotheken in entbündelten APKs in der product zur Verknüpfung mit Bibliotheken in /product/lib oder /product/lib64 (dies gilt zusätzlich zu den NDK-Bibliotheken).

Die Durchsetzung lässt keine anderen Links zu anderen Partitionen als der product zu.

Durchsetzung der Build-Zeit (Android.bp)

In Android 11 können Systemmodule zusätzlich zu Kern- und Anbieter-Image-Varianten auch eine Produkt-Image-Variante erstellen. Wenn die Durchsetzung der nativen Schnittstelle aktiviert ist ( PRODUCT_PRODUCT_VNDK_VERSION ist auf current gesetzt):

  • Native Module in der product befinden sich in der Produktvariante und nicht in der Kernvariante.

  • Module mit product_available: true in ihren Android.bp Dateien sind für die Produktvariante verfügbar.

  • Bibliotheken oder Binärdateien, die product_specific: true angeben, können auf andere Bibliotheken verweisen, die product_specific: true oder product_available: true in ihren Android.bp Dateien angeben.

  • VNDK-Bibliotheken müssen product_available: true in ihren Android.bp Dateien haben, damit product mit VNDK-Bibliotheken verknüpft werden können.

Die folgende Tabelle fasst die Android.bp Eigenschaften zusammen, die zum Erstellen von Bildvarianten verwendet werden.

Eigenschaften in Android.bp Varianten erstellt
Vor der Durchsetzung Nach der Durchsetzung
Standard (keine) Kern

(einschließlich /system , /system_ext und /product )

Kern

(Enthält /system und /system_ext , aber nicht /product )

system_ext_specific: true Kern Kern
product_specific: true Kern Produkt
vendor: true Verkäufer Verkäufer
vendor_available: true Kern, Anbieter Kern, Anbieter
product_available: true N / A Kernprodukt
vendor_available: true UND product_available: true N / A Kern, Produkt, Anbieter
system_ext_specific: true UND vendor_available: true Kern, Anbieter Kern, Anbieter
product_specific: true UND vendor_available: true Kern, Anbieter Produkt, Anbieter

Durchsetzung der Build-Zeit (Android.mk)

Wenn die Erzwingung der nativen Schnittstelle aktiviert ist, verfügen die auf der product installierten nativen Module über einen native:product Linktyp, der nur mit anderen native:product oder native:vndk Modulen verknüpft werden kann. Der Versuch, eine Verbindung zu anderen Modulen als diesen herzustellen, führt dazu, dass das Build-System einen Fehler bei der Überprüfung des Verbindungstyps generiert.

Laufzeitdurchsetzung

Wenn die Durchsetzung der nativen Schnittstelle aktiviert ist, erlaubt die Linkerkonfiguration für den bionischen Linker nicht, dass Systemprozesse product verwenden, wodurch ein product für die product erstellt wird, die keine Verknüpfung zu Bibliotheken außerhalb der product erstellen können (solche Prozesse können dies jedoch). Link zu VNDK-Bibliotheken). Versuche, die Laufzeit-Link-Konfiguration zu verletzen, führen dazu, dass der Prozess fehlschlägt und die Fehlermeldung CANNOT LINK EXECUTABLE generiert wird.

Durchsetzung von Java-Schnittstellen

Um die Durchsetzung der Java-Schnittstelle zu aktivieren, setzen Sie PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE auf true . (Der Wert wird automatisch auf true gesetzt, wenn die Versand-API-Ebene für das Ziel größer als 29 ist.) Wenn aktiviert, erlaubt/verbietet die Durchsetzung den folgenden Zugriff.

API /System /system_ext /Produkt /Verkäufer /Daten
Öffentliche API
@SystemApi
@hide-API

Wie in der vendor darf eine App oder eine Java-Bibliothek in der product nur öffentliche und System-APIs verwenden; Das Verknüpfen mit einer Bibliothek, die versteckte APIs verwendet, ist nicht zulässig. Diese Einschränkung umfasst die Verknüpfung zur Erstellungszeit und die Reflexion zur Laufzeit.

Durchsetzung der Bauzeit

Zur Erstellungszeit stellen Make und Soong sicher, dass Java-Module in der product keine versteckten APIs verwenden, indem sie die Felder platform_apis “ und sdk_version überprüfen. Die sdk_version der Apps in der product muss mit current , system_current oder numerischen Version der API gefüllt sein und das Feld platform_apis muss leer sein.

Durchsetzung der Laufzeit

Die Android-Laufzeit überprüft, ob Apps in der product keine versteckten APIs, einschließlich Reflektion, verwenden. Einzelheiten finden Sie unter Einschränkungen für Nicht-SDK-Schnittstellen .

Durchsetzung der Produktschnittstelle aktivieren

Führen Sie die Schritte in diesem Abschnitt aus, um die Durchsetzung der Produktschnittstelle zu aktivieren.

Schritt Aufgabe Erforderlich
1 Definieren Sie Ihr eigenes System-Makefile, das die Pakete für die system angibt, und legen Sie dann die Artefaktpfad-Anforderungsprüfung in der device.mk fest (um zu verhindern, dass Nicht-Systemmodule auf der system installiert werden). N
2 Bereinigen Sie die Zulassungsliste. N
3 Erzwingen Sie native Schnittstellen und identifizieren Sie Laufzeitverbindungsfehler (kann parallel zur Java-Erzwingung ausgeführt werden). Y
4 Erzwingen Sie Java-Schnittstellen und überprüfen Sie das Laufzeitverhalten (kann parallel zur nativen Durchsetzung ausgeführt werden). Y
5 Überprüfen Sie das Laufzeitverhalten. Y
6 Aktualisieren Sie device.mk mit der Durchsetzung der Produktschnittstelle. Y

Schritt 1: Makefile erstellen und Artefaktpfadprüfung aktivieren

In diesem Schritt definieren Sie das system -Makefile.

  1. Erstellen Sie ein Makefile, das die Pakete für die system definiert. Erstellen Sie beispielsweise eine oem_system.mk Datei mit Folgendem:

    $(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. Erben Sie in der Datei device.mk das gemeinsame Makefile für die system und aktivieren Sie die Überprüfung der Artefaktpfadanforderungen. Zum Beispiel:

    $(call inherit-product, $(SRC_TARGET_DIR)/product/oem_system.mk)
    
    # Enable artifact path requirements checking
    PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := strict
    

Informationen zu den Anforderungen an den Artefaktpfad

Wenn PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS auf true oder strict gesetzt ist, verhindert das Build-System, dass in anderen Makefiles definierte Pakete auf den in require-artifacts-in-path definierten Pfaden installiert werden , und verhindert, dass im aktuellen Makefile definierte Pakete Artefakte außerhalb der in require-artifacts-in-path -artifacts-in-path definierten Pfade installieren. require-artifacts-in-path .

Im obigen Beispiel können Makefiles außerhalb oem_system.mk , wenn PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS auf strict gesetzt ist, keine Module enthalten, die auf der root oder system installiert sind. Um diese Module einzubinden, müssen Sie sie entweder in der Datei oem_system.mk selbst oder in einem enthaltenen Makefile definieren. Versuche, Module auf unzulässigen Pfaden zu installieren, führen zu Build-Unterbrechungen. Um Unterbrechungen zu beheben, führen Sie einen der folgenden Schritte aus:

  • Option 1: Binden Sie das Systemmodul in die Makefiles ein, die in oem_system.mk enthalten sind. Dadurch wird die Anforderung an den Artefaktpfad erfüllt (da die Module jetzt in einem enthaltenen Makefile vorhanden sind) und somit die Installation in den Pfaden in „require-artifacts-in-path“ ermöglicht.

  • Option 2: Module auf der system_ext oder product installieren (und keine Module auf der system installieren).

  • Option 3: Module zur PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST hinzufügen. Hier werden die zulässigen Module aufgeführt, die installiert werden dürfen.

Schritt 2: Leeren Sie die Zulassungsliste

In diesem Schritt machen Sie PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST leer, sodass alle Geräte, die oem_system.mk gemeinsam nutzen, auch ein einzelnes system gemeinsam nutzen können. Um die Liste der zulässigen Module zu leeren, verschieben Sie alle Module in der Liste in die system_ext oder product oder fügen Sie sie den system Make-Dateien hinzu. Dieser Schritt ist optional, da die Definition eines gemeinsamen system nicht erforderlich ist, um die Durchsetzung der Produktschnittstelle zu ermöglichen. Das Leeren der erlaubten Liste ist jedoch hilfreich, um die system mit system_ext zu definieren.

Schritt 3: Erzwingen Sie native Schnittstellen

In diesem Schritt legen Sie PRODUCT_PRODUCT_VNDK_VERSION := current fest, suchen dann nach Build- und Laufzeitfehlern und beheben diese. So überprüfen Sie den Gerätestart und die Protokolle und finden und beheben Fehler bei der Laufzeitverknüpfung:

  1. Legen Sie PRODUCT_PRODUCT_VNDK_VERSION := current fest.

  2. Bauen Sie das Gerät und suchen Sie nach Baufehlern. Es wird wahrscheinlich zu einigen Build-Unterbrechungen aufgrund fehlender Produktvarianten oder Kernvarianten kommen. Zu den häufigsten Pausen gehören:

    • Jedes hidl_interface Modul mit product_specific: true ist für Systemmodule nicht verfügbar. Um das Problem zu beheben, ersetzen Sie product_specific: true durch system_ext_specfic: true .
    • Den Modulen fehlt möglicherweise die für Produktmodule erforderliche Produktvariante. Um das Problem zu beheben, machen Sie das Modul für die product verfügbar, indem Sie product_available: true festlegen, oder verschieben Sie das Modul in die product , indem Sie product_specific: true festlegen.
  3. Beheben Sie Buildfehler und stellen Sie sicher, dass das Gerät erfolgreich erstellt wird.

  4. Flashen Sie das Image und suchen Sie nach Laufzeitfehlern im Gerätestart und in den Protokollen.

    • Wenn das linker Tag aus einem Testfallprotokoll die Meldung CANNOT LINK EXECUTABLE anzeigt, fehlt in der Make-Datei eine Abhängigkeit (und sie wurde zur Erstellungszeit nicht erfasst).
    • Um es vom Build-System aus zu überprüfen, fügen Sie die erforderliche Bibliothek zum Feld shared_libs: oder required: hinzu.
  5. Beheben Sie die fehlenden Abhängigkeiten mithilfe der oben angegebenen Anleitung.

Schritt 4: Java-Schnittstellen erzwingen

In diesem Schritt legen Sie PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true fest und suchen und beheben dann resultierende Buildfehler. Suchen Sie nach zwei spezifischen Arten von Fehlern:

  • Fehler beim Linktyp. Dieser Fehler weist darauf hin, dass eine App auf Java-Module verweist, die über eine umfassendere sdk_version verfügen. Um das Problem zu beheben, können Sie die sdk_version der App erweitern oder die sdk_version der Bibliothek einschränken. Beispielfehler:

    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.
    
  • Symbolfehler. Dieser Fehler weist darauf hin, dass ein Symbol nicht gefunden werden kann, weil es sich in einer versteckten API befindet. Um das Problem zu beheben, verwenden Sie eine sichtbare (nicht ausgeblendete) API oder suchen Sie nach einer Alternative. Beispielfehler:

    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
    

Schritt 5: Laufzeitverhalten prüfen

In diesem Schritt überprüfen Sie, ob das Laufzeitverhalten den Erwartungen entspricht. Bei Apps, die debuggbar sind, können Sie die Nutzung versteckter APIs mithilfe eines Protokolls StrictMode.detectNonSdkApiUsage überwachen (wodurch ein Protokoll generiert wird, wenn die App eine versteckte API verwendet). Alternativ können Sie das statische Analysetool von Veridex verwenden, um die Art der Nutzung (Verknüpfung oder Reflektion), die Einschränkungsstufe und den Aufrufstapel abzurufen.

  • Veridex-Syntax:

    ./art/tools/veridex/appcompat.sh --dex-file={apk file}
    
  • Beispiel für ein Veridex-Ergebnis:

    #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;
    

Einzelheiten zur Verwendung von Veridex finden Sie unter Testen mit dem Veridex-Tool .

Schritt 6: Aktualisieren Sie device.mk

Nachdem Sie alle Build- und Laufzeitfehler behoben und überprüft haben, ob das Laufzeitverhalten den Erwartungen entspricht, legen Sie Folgendes in device.mk fest:

  • PRODUCT_PRODUCT_VNDK_VERSION := current
  • PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true