Anmerkungen in AIDL

AIDL unterstützt Annotationen, die dem AIDL-Compiler zusätzliche Informationen über das annotierte Element liefern, was sich auch auf den generierten Stub-Code auswirkt.

Die Syntax ähnelt der von Java:

@AnnotationName(argument1=value, argument2=value) AidlEntity

Hier ist AnnotationName der Name der Anmerkung und AidlEntity ist eine AIDL-Entität wie interface Foo , void method() oder int arg . Der darauf folgenden Entität wird eine Anmerkung beigefügt.

Bei einigen Anmerkungen können Argumente in Klammern gesetzt werden, wie oben gezeigt. Anmerkungen, die kein Argument haben, benötigen keine Klammern. Zum Beispiel:

@AnnotationName AidlEntity

Diese Annotationen sind nicht mit den Java-Annotationen identisch, obwohl sie sehr ähnlich aussehen. Benutzer können keine benutzerdefinierten AIDL-Anmerkungen definieren; Die Anmerkungen sind alle vordefiniert. Einige Anmerkungen betreffen nur ein bestimmtes Backend und sind in anderen Backends nicht aktiv. Sie haben unterschiedliche Einschränkungen, an die sie angehängt werden können.

Nachfolgend finden Sie die Liste der vordefinierten AIDL-Anmerkungen:

Anmerkungen In der Android-Version hinzugefügt
nullable 7
utf8InCpp 7
VintfStability 11
UnsupportedAppUsage 10
Hide 11
Backing 11
NdkOnlyStableParcelable 14
JavaOnlyStableParcelable 11
JavaDerive 12
JavaPassthrough 12
FixedSize 12
Descriptor 12

nullbar

nullable erklärt, dass der Wert der mit Anmerkungen versehenen Entität möglicherweise nicht bereitgestellt wird.

Diese Anmerkung kann nur an Methodenrückgabetypen, Methodenparameter und parzellierbare Felder angehängt werden.

interface IFoo {
    // method return types
    @nullable Data method();

    // method parameters
    void method2(in @nullable Data d);
}

parcelable Data {
    // parcelable fields
    @nullable Data d;
}

Anmerkungen können nicht an primitive Typen angehängt werden. Folgendes ist ein Fehler.

void method(in @nullable int a); // int is a primitive type

Diese Anmerkung gilt nicht für das Java-Backend. Dies liegt daran, dass in Java alle nicht-primitiven Typen als Referenz übergeben werden, was null sein kann.

Im CPP-Backend wird @nullable T in Android 11 oder niedriger auf std::unique_ptr<T> und in Android 12 oder höher auf std::optional<T> abgebildet.

Im NDK-Backend wird @nullable T immer std::optional<T> zugeordnet.

Für einen listenähnlichen Typ L wie T[] oder List<T> wird @nullable L auf std::optional<std::vector<std::optional<T>>> (oder std::unique_ptr<std::vector<std::unique_ptr<T>>> im Fall des CPP-Backends für Android 11 oder niedriger).

Für diese Zuordnung gibt es eine Ausnahme. Wenn T ein IBinder oder eine AIDL-Schnittstelle ist, ist @nullable no-op. Mit anderen Worten: Sowohl @nullable IBinder als auch IBinder werden gleichermaßen auf android::sp<IBinder> abgebildet, was bereits nullbar ist, da es sich um einen starken Zeiger handelt (CPP-Lesevorgänge erzwingen weiterhin NULL-Zulässigkeit, aber der Typ ist immer noch android::sp<IBinder> ).

Ab Android 13 kann @nullable(heap=true) für parzellierbare Felder verwendet werden, um rekursive Typen zu modellieren. @nullable(heap=true) kann nicht mit Methodenparametern oder Rückgabetypen verwendet werden. Wenn es damit annotiert wird, wird das Feld einer Heap-zugewiesenen Referenz std::unique_ptr<T> in den CPP/NDK-Backends zugeordnet. @nullable(heap=true) ist im Java-Backend no-op.

utf8InCpp

utf8InCpp deklariert, dass ein String im UTF8-Format für das CPP-Backend dargestellt wird. Wie der Name schon sagt, ist die Annotation für andere Backends ein No-Op. Insbesondere ist String im Java-Backend immer UTF16 und im NDK-Backend UTF8.

Diese Anmerkung kann überall dort angehängt werden, wo der String Typ verwendet werden kann, einschließlich Rückgabewerten, Parametern, Konstantendeklarationen und parzellierbaren Feldern.

Für das CPP-Backend @utf8InCpp String in AIDL std::string zugeordnet, während String ohne die Annotation android::String16 zugeordnet wird, wobei UTF16 verwendet wird.

Beachten Sie, dass das Vorhandensein der utf8InCpp Annotation die Art und Weise, wie Zeichenfolgen über die Leitung übertragen werden, nicht ändert. Zeichenfolgen werden immer als UTF16 über die Leitung übertragen. Eine utf8InCpp annotierte Zeichenfolge wird vor der Übertragung in UTF16 konvertiert. Wenn eine Zeichenfolge empfangen wird, wird sie von UTF16 in UTF8 konvertiert, wenn sie als utf8InCpp annotiert wurde.

VintfStability

VintfStability erklärt, dass ein benutzerdefinierter Typ (Interface, Parcelable und Enum) im gesamten System und in den Anbieterdomänen verwendet werden kann. Weitere Informationen zur System-Anbieter-Interoperabilität finden Sie unter AIDL für HALs .

Die Annotation ändert die Signatur des Typs nicht, aber wenn sie festgelegt ist, wird die Instanz des Typs als stabil markiert, sodass sie über die Anbieter- und Systemprozesse hinweg übertragen werden kann.

Die Annotation kann nur an benutzerdefinierte Typdeklarationen angehängt werden, wie unten gezeigt:

@VintfStability
interface IFoo {
    ....
}

@VintfStability
parcelable Data {
    ....
}

@VintfStability
enum Type {
    ....
}

Wenn ein Typ mit VintfStability annotiert wird, sollte jeder andere Typ, auf den im Typ verwiesen wird, ebenfalls als solcher annotiert werden. Im folgenden Beispiel sollten Data und IBar beide mit VintfStability annotiert werden.

@VintfStability
interface IFoo {
    void doSomething(in IBar b); // references IBar
    void doAnother(in Data d); // references Data
}

@VintfStability // required
interface IBar {...}

@VintfStability // required
parcelable Data {...}

Darüber hinaus können die AIDL-Dateien, die mit VintfStability annotierte Typen definieren, nur mit dem Modultyp „ aidl_interface Soong“ erstellt werden, wobei die stability auf "vintf" gesetzt ist.

aidl_interface {
    name: "my_interface",
    srcs: [...],
    stability: "vintf",
}

Nicht unterstützte App-Nutzung

Die Annotation UnsupportedAppUsage gibt an, dass der annotierte AIDL-Typ Teil der Nicht-SDK-Schnittstelle ist, auf die ältere Apps zugreifen konnten. Weitere Informationen zu den versteckten APIs finden Sie unter Einschränkungen für Nicht-SDK-Schnittstellen .

Die UnsupportedAppUsage Annotation hat keinen Einfluss auf das Verhalten des generierten Codes. Die Annotation annotiert die generierte Java-Klasse lediglich mit der gleichnamigen Java-Annotation.

// in AIDL
@UnsupportedAppUsage
interface IFoo {...}

// in Java
@android.compat.annotation.UnsupportedAppUsage
public interface IFoo {...}

Dies ist ein No-Op für Nicht-Java-Backends.

Unterstützung

Die Backing Annotation gibt den Speichertyp eines AIDL-Enumerationstyps an.

@Backing(type="int")
enum Color { RED, BLUE, }

Im CPP-Backend gibt das Obige eine C++-Enum-Klasse vom Typ int32_t aus.

enum class Color : int32_t {
    RED = 0,
    BLUE = 1,
}

Wenn die Annotation weggelassen wird, wird angenommen, dass der type byte ist, der für das CPP-Backend auf int8_t abgebildet wird.

Das type kann nur auf die folgenden Integraltypen festgelegt werden:

  • byte (8 Bit breit)
  • int (32-Bit breit)
  • long (64-Bit breit)

NdkOnlyStableParcelable

NdkOnlyStableParcelable markiert eine parzellierbare Deklaration (keine Definition) als stabil, sodass von anderen stabilen AIDL-Typen darauf verwiesen werden kann. Dies ist wie JavaOnlyStableParcelable , aber NdkOnlyStableParcelable markiert eine parzellierbare Deklaration als stabil für das NDK-Backend statt für Java.

Um dieses Paket zu verwenden: * Sie müssen ndk_header angeben. * Sie müssen über eine NDK-Bibliothek verfügen, die das Parcelable angibt, und die Bibliothek muss in die Bibliothek kompiliert werden. Verwenden Sie beispielsweise im Core-Build-System auf einem cc_* -Modul static_libs oder shared_libs . Fügen Sie für aidl_interface die Bibliothek unter additional_shared_libraries in Android.bp hinzu.

JavaOnlyStableParcelable

JavaOnlyStableParcelable markiert eine parzellierbare Deklaration (keine Definition) als stabil, sodass von anderen stabilen AIDL-Typen darauf verwiesen werden kann.

Stabiles AIDL erfordert, dass alle benutzerdefinierten Typen stabil sind. Für die Stabilität von Parcelables ist es erforderlich, dass die Felder explizit in der AIDL-Quelldatei beschrieben werden.

parcelable Data { // Data is a structured parcelable.
    int x;
    int y;
}

parcelable AnotherData { // AnotherData is also a structured parcelable
    Data d; // OK, because Data is a structured parcelable
}

Wenn die Parzelle unstrukturiert war (oder nur deklariert wurde), kann nicht darauf verwiesen werden.

parcelable Data; // Data is NOT a structured parcelable

parcelable AnotherData {
    Data d; // Error
}

JavaOnlyStableParcelable können Sie die Prüfung außer Kraft setzen, wenn das Paket, auf das Sie verweisen, bereits sicher als Teil des Android SDK verfügbar ist.

@JavaOnlyStableParcelable
parcelable Data;

parcelable AnotherData {
    Data d; // OK
}

JavaDerive

JavaDerive generiert automatisch Methoden für parzellierbare Typen im Java-Backend.

@JavaDerive(equals = true, toString = true)
parcelable Data {
  int number;
  String str;
}

Die Annotation erfordert zusätzliche Parameter, um zu steuern, was generiert werden soll. Die unterstützten Parameter sind:

  • equals=true generiert die Methoden equals und hashCode .
  • toString=true generiert toString Methode, die den Namen des Typs und der Felder ausgibt. Zum Beispiel: Data{number: 42, str: foo}

JavaDefault

JavaDefault , hinzugefügt in Android 13, steuert, ob die Standardunterstützung für die Implementierungsversionierung generiert wird (für setDefaultImpl ). Diese Unterstützung wird aus Platzgründen nicht mehr standardmäßig generiert.

JavaPassthrough

JavaPassthrough kann die generierte Java-API mit einer beliebigen Java-Annotation annotiert werden.

Die folgenden Anmerkungen in AIDL

@JavaPassthrough(annotation="@android.annotation.Alice")
@JavaPassthrough(annotation="@com.android.Alice(arg=com.android.Alice.Value.A)")

werden

@android.annotation.Alice
@com.android.Alice(arg=com.android.Alice.Value.A)

im generierten Java-Code.

Der Wert des annotation wird direkt ausgegeben. Der AIDL-Compiler untersucht den Wert des Parameters nicht. Wenn ein Syntaxfehler auf Java-Ebene vorliegt, wird dieser nicht vom AIDL-Compiler, sondern vom Java-Compiler abgefangen.

Diese Anmerkung kann an jede AIDL-Entität angehängt werden. Diese Anmerkung gilt nicht für Nicht-Java-Backends.

Feste Größe

FixedSize markiert eine strukturierte Parzelle als feste Größe. Sobald die Parzelle markiert ist, dürfen keine neuen Felder mehr hinzugefügt werden. Alle Felder des Parcelables müssen ebenfalls Typen fester Größe sein, einschließlich primitiver Typen, Aufzählungen, Arrays fester Größe und anderer Parcelables, die mit FixedSize gekennzeichnet sind.

Dies bietet keine Garantie für verschiedene Bitness-Werte und sollte bei der Kommunikation mit gemischten Bitness-Werten nicht als verlässlich angesehen werden.

Deskriptor

Descriptor gibt zwangsweise den Schnittstellendeskriptor einer Schnittstelle an.

package android.foo;

@Descriptor(value="android.bar.IWorld")
interface IHello {...}

Der Deskriptor der obigen Schnittstelle ist android.bar.IWorld . Wenn die Descriptor Annotation fehlt, wäre der Deskriptor android.foo.IHello .

Dies ist nützlich, um eine bereits veröffentlichte Schnittstelle umzubenennen. Wenn der Deskriptor der umbenannten Schnittstelle mit dem Deskriptor der Schnittstelle vor der Umbenennung identisch ist, können die beiden Schnittstellen miteinander kommunizieren.

@in Kommentaren verstecken

Der AIDL-Compiler erkennt @hide in Kommentaren und leitet es an die Java-Ausgabe weiter, damit Metalava es abholen kann. Dieser Kommentar stellt sicher, dass das Android-Build-System weiß, dass AIDL-APIs keine SDK-APIs sind.

@deprecated in Kommentaren

Der AIDL-Compiler erkennt @deprecated in Kommentaren als Tag zur Identifizierung einer AIDL-Entität, die nicht mehr verwendet werden sollte.

interface IFoo {
  /** @deprecated use bar() instead */
  void foo();
  void bar();
}

Jedes Backend markiert veraltete Entitäten mit einer Backend-spezifischen Anmerkung/einem Backend-Attribut, sodass der Clientcode gewarnt wird, wenn er auf die veralteten Entitäten verweist. Beispielsweise werden die Annotation @Deprecated und das Tag @deprecated an den von Java generierten Code angehängt.