Anmerkungen in AIDL

AIDL unterstützt Annotationen, die dem AIDL-Compiler zusätzliche Informationen über das annotierte Element geben, 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 Annotation und AidlEntity ist eine AIDL-Entität wie interface Foo , void method() oder int arg . Eine Anmerkung wird an die nachfolgende Entität angehängt.

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

@AnnotationName AidlEntity

Diese Anmerkungen sind nicht mit den Java-Anmerkungen identisch, obwohl sie sehr ähnlich aussehen. Benutzer können keine benutzerdefinierten AIDL-Anmerkungen definieren; Die Anmerkungen sind alle vordefiniert. Einige Anmerkungen wirken sich nur auf ein bestimmtes Backend aus und sind in anderen Backends no-op. Sie haben unterschiedliche Beschränkungen, an denen sie angebracht werden können.

Unten ist 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
JavaOnlyStableParcelable 11
JavaDerive 12
JavaPassthrough 12
FixedSize 12
Descriptor 12

nullable

nullable deklariert, dass der Wert der annotierten Entität nicht bereitgestellt werden darf.

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 ist für das Java-Back-End no-op. Dies liegt daran, dass in Java alle nicht primitiven Typen als Referenz übergeben werden, die null sein könnte.

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

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 std::optional<std::vector<std::optional<T>>> (oder std::unique_ptr<std::vector<std::unique_ptr<T>>> im Falle des CPP-Backends für Android 11 oder niedriger).

Es gibt eine Ausnahme von dieser Zuordnung. Wenn T IBinder oder eine AIDL-Schnittstelle ist, ist @nullable no-op. Mit anderen Worten, sowohl @nullable IBinder als IBinder werden gleichermaßen auf android::sp<IBinder> , was bereits nullable ist, weil es ein starker Zeiger ist (CPP-Lesevorgänge erzwingen immer noch die Nullfähigkeit, 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 in den CPP/NDK-Backends einer Heap-zugewiesenen Referenz std::unique_ptr<T> 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 ein No-Op für andere Backends. 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 wird @utf8InCpp String in AIDL std::string zugeordnet, während String ohne die Anmerkung android::String16 wird, wo UTF16 verwendet wird.

Beachten Sie, dass das Vorhandensein der Annotation utf8InCpp die Art und Weise, wie Zeichenfolgen über das Kabel übertragen werden, nicht ändert. Strings werden immer als UTF16 über die Leitung ü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 kommentiert wurde.

VintfStabilität

VintfStability deklariert, dass ein benutzerdefinierter Typ (Schnittstelle, Paketierbar und Enum) über die System- und Anbieterdomänen hinweg verwendet werden kann. Weitere Informationen zur Interoperabilität zwischen Systemanbietern finden Sie unter AIDL für HALs .

Die Anmerkung ändert die Signatur des Typs nicht, aber wenn sie gesetzt ist, wird die Instanz des Typs als stabil markiert, damit sie die Anbieter- und Systemprozesse durchlaufen kann.

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

@VintfStability
interface IFoo {
    ....
}

@VintfStability
parcelable Data {
    ....
}

@VintfStability
enum Type {
    ....
}

Wenn ein Typ mit VintfStability kommentiert wird, sollte jeder andere Typ, auf den im Typ verwiesen wird, auch als solcher kommentiert werden. Im folgenden Beispiel sollten Data und IBar beide mit VintfStability kommentiert 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 kommentierte Typen definieren, nur mit dem aidl_interface Soong erstellt werden, wobei die Eigenschaft " stability " auf "vintf" .

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

Nicht unterstützte App-Nutzung

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

Die UnsupportedAppUsage -Annotation wirkt sich nicht auf das Verhalten des generierten Codes aus. Die Annotation annotiert lediglich die generierte Java-Klasse 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 -Anmerkung gibt den Speichertyp eines AIDL-Aufzählungstyps an.

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

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

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

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

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

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

JavaOnlyStableParcelable

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

Stable AIDL erfordert, dass alle benutzerdefinierten Typen stabil sind. Für Parcelables erfordert die Stabilität, dass ihre Felder explizit in der AIDL-Quelldatei beschrieben sind.

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 nur deklariert) war, kann es nicht referenziert 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 Parcelable, auf das Sie verweisen, bereits sicher als Teil des Android SDK verfügbar ist.

@JavaOnlyStableParcelable
parcelable Data;

parcelable AnotherData {
    Data d; // OK
}

JavaAbgeleitet

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

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

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

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

JavaDefault

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

JavaPassthrough

JavaPassthrough die generierte Java-API mit einer beliebigen Java-Annotation versehen 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 auftritt, wird er nicht vom AIDL-Compiler, sondern vom Java-Compiler abgefangen.

Diese Anmerkung kann an jede AIDL-Entität angehängt werden. Diese Anmerkung ist ein No-Op für Nicht-Java-Back-Ends.

Feste Größe

FixedSize markiert ein strukturiertes Paket als feste Größe. Nach der Markierung dürfen dem Parcelable keine neuen Felder hinzugefügt werden. Alle Felder der Parcelable müssen ebenfalls Typen mit fester Größe sein, einschließlich primitiver Typen, Aufzählungen, Arrays mit fester Größe und andere Parcelables, die mit FixedSize gekennzeichnet sind.

Dies bietet keine Garantie für unterschiedliche Bitness und sollte nicht für die Kommunikation mit gemischter Bitness verwendet werden.

Beschreibung

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 -Anmerkung fehlt, wäre der Descriptor android.foo.IHello .

Dies ist nützlich, um eine bereits veröffentlichte Schnittstelle umzubenennen. Wenn Sie den Deskriptor der umbenannten Schnittstelle mit dem Deskriptor der Schnittstelle vor der Umbenennung identisch machen, 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-Buildsystem weiß, dass AIDL-APIs keine SDK-APIs sind.

@veraltet in Kommentaren

Der AIDL-Compiler erkennt @deprecated in Kommentaren als Tag, um eine AIDL-Entität zu identifizieren, 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 Attribut, sodass der Client-Code 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.