Annotationen in AIDL

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

Die Syntax ähnelt der von Java:

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

Hier ist AnnotationName der Name der Annotation und AidlEntity eine AIDL-Entität wie interface Foo, void method() oder int arg. Eine Anmerkung wird an die darauffolgende Entität angehängt.

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

@AnnotationName AidlEntity

Diese Annotationen sind nicht mit den Java-Annotationen identisch, sehen aber sehr ähnlich aus. Nutzer können keine benutzerdefinierten AIDL-Annotationen definieren. Alle Annotationen sind vordefiniert. Einige Annotationen wirken sich nur auf ein bestimmtes Back-End aus und sind in anderen Back-Ends nicht funktionsfähig. Sie haben unterschiedliche Einschränkungen, an die sie angehängt werden können.

Hier ist die Liste der vordefinierten AIDL-Annotationen:

Anmerkungen In 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

Nullwerte zulässig

nullable gibt an, dass der Wert der annotierten Entität nicht angegeben werden darf.

Diese Annotation kann nur an Methodenrückgabetypen, Methodenparameter und geparste 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;
}

An primitive Typen können keine Anmerkungen angehängt werden. Folgendes ist ein Fehler.

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

Diese Annotation ist für das Java-Back-End managementfrei. Das liegt daran, dass in Java alle nicht primitiven Typen durch einen Verweis übergeben werden, der null sein kann.

Im CPP-Back-End wird @nullable T unter Android 11 oder niedriger std::unique_ptr<T> und in Android 12 oder höher std::optional<T> zugeordnet.

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

Bei einem listenähnlichen Typ L wie T[] oder List<T> wird @nullable L std::optional<std::vector<std::optional<T>>> (oder std::unique_ptr<std::vector<std::unique_ptr<T>>> im Fall des CPP-Back-Ends für Android 11 oder niedriger) zugeordnet.

Für diese Zuordnung gibt es eine Ausnahme. Wenn T IBinder oder eine AIDL-Schnittstelle ist, ist @nullable kein Vorgang. Mit anderen Worten, sowohl @nullable IBinder als auch IBinder sind gleichermaßen android::sp<IBinder> zugeordnet, was bereits Null-Zulässigkeit ist, da es ein starker Zeiger ist (CPP-Lesevorgänge erzwingen weiterhin Null-Zulässigkeit, aber der Typ ist weiterhin android::sp<IBinder>).

Ab Android 13 kann @nullable(heap=true) für Pakete verwendet werden, um rekursive Typen zu modellieren. @nullable(heap=true) kann nicht mit Methodenparametern oder Rückgabetypen verwendet werden. Wenn das Feld damit annotiert wird, wird es einem Heap-zugewiesenen Verweis std::unique_ptr<T> in den CPP-/NDK-Back-Ends zugeordnet. @nullable(heap=true) ist im Java-Back-End managementfrei.

utf8InCpp

utf8InCpp deklariert, dass ein String für das CPP-Back-End im UTF8-Format dargestellt wird. Wie der Name schon sagt, ist die Annotation eine Nulloperation für andere Back-Ends. Insbesondere ist String im Java-Back-End immer UTF16 und im NDK-Back-End UTF8.

Diese Annotation kann überall dort angehängt werden, wo der Typ String verwendet werden kann, einschließlich Rückgabewerten, Parametern, konstanten Deklarationen und Paketfeldern.

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

Das Vorhandensein der Annotation utf8InCpp hat keinen Einfluss auf die Art und Weise, wie Strings über das Kabel übertragen werden. Strings werden immer als UTF16 über das Kabel übertragen. Ein mit utf8InCpp annotierter String wird vor der Übertragung in UTF16 konvertiert. Wenn ein String empfangen wird, wird er von UTF16 in UTF8 konvertiert, wenn er als utf8InCpp annotiert war.

vintfStabilität

VintfStability deklariert, dass ein benutzerdefinierter Typ (Schnittstelle, Paket und Enum) in allen System- und Anbieterdomains verwendet werden kann. Weitere Informationen zur Interoperabilität zwischen Systemanbietern finden Sie unter AIDL für HALs.

Durch die Annotation wird die Signatur des Typs nicht geändert. Wenn sie jedoch festgelegt wird, wird die Instanz des Typs als stabil markiert, damit sie zwischen den Anbieter- und Systemprozessen übertragen werden kann.

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

@VintfStability
interface IFoo {
    ....
}

@VintfStability
parcelable Data {
    ....
}

@VintfStability
enum Type {
    ....
}

Wird ein Typ mit VintfStability annotiert, sollten alle anderen Typen, auf die im Typ verwiesen wird, ebenfalls entsprechend annotiert werden. Im folgenden Beispiel sollten sowohl Data als auch IBar 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 {...}

Außerdem können die AIDL-Dateien, die mit VintfStability annotierte Typen definieren, nur mit dem Soong-Modultyp aidl_interface erstellt werden, wobei das Attribut stability auf "vintf" gesetzt ist.

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

Nicht unterstützte App-Nutzung

Die Annotation UnsupportedAppUsage zeigt an, dass der annotierte AIDL-Typ Teil der Nicht-SDK-Schnittstelle ist, auf die Legacy-Anwendungen Zugriff haben. Weitere Informationen zu den ausgeblendeten APIs finden Sie unter Einschränkungen bei Nicht-SDK-Schnittstellen.

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

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

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

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

Rückenlehnen

Die Annotation Backing gibt den Speichertyp eines AIDL-Enum-Typs an.

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

Im CPP-Back-End gibt dies eine C++-Enum-Klasse vom Typ int32_t aus.

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

Wenn die Annotation weggelassen wird, wird davon ausgegangen, dass type byte ist, was int8_t für das CPP-Back-End zugeordnet ist.

Das Argument type kann nur auf die folgenden ganzzahligen Typen festgelegt werden:

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

NdkOnlyStableParcelable

NdkOnlyStableParcelable kennzeichnet eine Paketdeklaration (keine Definition) als stabil, damit von anderen stabilen AIDL-Typen darauf verwiesen werden kann. Dies entspricht JavaOnlyStableParcelable, allerdings markiert NdkOnlyStableParcelable eine Parzellendeklaration als stabil für das NDK-Back-End und nicht für Java.

So verwenden Sie dieses Paket:

  • Sie müssen ndk_header angeben.
  • Sie benötigen eine NDK-Bibliothek, die das Parcelable angibt, und die Bibliothek muss in die Bibliothek kompiliert werden. Verwenden Sie beispielsweise im zentralen Build-System eines cc_*-Moduls static_libs oder shared_libs. Fügen Sie für aidl_interface die Bibliothek unter additional_shared_libraries in Android.bp hinzu.

JavaOnlyStableParcelable

JavaOnlyStableParcelable kennzeichnet eine Paketdeklaration (keine Definition) als stabil, damit von anderen stabilen AIDL-Typen darauf verwiesen werden kann.

Für den stabilen AIDL müssen alle benutzerdefinierten Typen stabil sein. Für die Stabilität von Paketen müssen 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 das Paket unstrukturiert (oder gerade deklariert) war, kann nicht darauf verwiesen werden.

parcelable Data; // Data is NOT a structured parcelable

parcelable AnotherData {
    Data d; // Error
}

Mit JavaOnlyStableParcelable können Sie die Prüfung überschreiben, wenn das Paket, auf das Sie verweisen, bereits als Teil des Android SDK sicher verfügbar ist.

@JavaOnlyStableParcelable
parcelable Data;

parcelable AnotherData {
    Data d; // OK
}

JavaDerive

JavaDerive generiert automatisch Methoden für Pakettypen im Java-Back-End.

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

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

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

JavaStandard

JavaDefault, das in Android 13 hinzugefügt wurde, steuert, ob die Unterstützung für die standardmäßige Implementierungsversionsverwaltung (für setDefaultImpl) generiert wird. Diese Unterstützung wird nicht mehr standardmäßig generiert, um Speicherplatz zu sparen.

JavaPassthrough

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

Die folgenden Annotationen 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 ein.

Der Wert des Parameters annotation wird direkt ausgegeben. Der AIDL-Compiler berücksichtigt den Wert des Parameters nicht. Ein Syntaxfehler auf Java-Ebene wird nicht vom AIDL-Compiler, sondern vom Java-Compiler abgefangen.

Diese Annotation kann an jede AIDL-Entität angehängt werden. Diese Annotation ist bei Nicht-Java-Back-Ends ein Leerbefehl.

Feste Größe

FixedSize kennzeichnet ein strukturiertes Flurstück als feste Größe. Nach dem Markieren können dem Paket keine neuen Felder mehr hinzugefügt werden. Alle Felder des Pakets müssen auch Typen mit fester Größe haben, einschließlich primitiver Typen, Enums, Arrays mit fester Größe und anderer Parzellen, die mit FixedSize gekennzeichnet sind.

Dies bietet keine Garantie für verschiedene Bits und sollte nicht für eine Kommunikation mit gemischter Bitqualität verwendet werden.

Beschreibung

Descriptor gibt zwangsweise den Schnittstellendeskriptor einer Schnittstelle an.

package android.foo;

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

Der Deskriptor dieser Schnittstelle ist android.bar.IWorld. Wenn die Annotation Descriptor fehlt, lautet der Deskriptor android.foo.IHello.

Dies ist hilfreich, wenn Sie eine bereits veröffentlichte Schnittstelle umbenennen möchten. Wenn Sie vor der Umbenennung den Deskriptor der umbenannten Schnittstelle mit dem Deskriptor der Schnittstelle identisch machen, können die beiden Schnittstellen miteinander kommunizieren.

In Kommentaren @ausblenden

Der AIDL-Compiler erkennt @hide in Kommentaren und übergibt ihn an die Java-Ausgabe, damit Metalava verarbeitet werden kann. Dieser Kommentar sorgt dafür, dass das Android-Build-System erkennt, dass AIDL APIs keine SDK APIs sind.

@eingestellt in Kommentaren

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

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

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