AIDL unterstützt Anmerkungen, die dem AIDL-Compiler zusätzliche Informationen zum kommentierten Element geben, was sich auch auf den generierten Stub-Code auswirkt.
Die Syntax ähnelt der von Java:
@AnnotationName(argument1=value, argument2=value) AidlEntity
Dabei ist AnnotationName der Name der Annotation und AidlEntity eine AIDL-Entität wie interface Foo, void method() oder int arg. Eine Anmerkung wird der nachfolgenden Einheit zugeordnet.
Für einige Anmerkungen können Argumente in den Klammern festgelegt werden, wie im vorherigen Beispiel gezeigt. Bei Hinweisen ohne Argumente sind die Klammern nicht erforderlich. Beispiel:
@AnnotationName AidlEntity
Diese Anmerkungen sind nicht mit den Java-Anmerkungen identisch, obwohl sie ähnlich aussehen. Alle Anmerkungen sind vordefiniert und haben Einschränkungen hinsichtlich der Stellen, an denen Sie sie anbringen können. Einige Anmerkungen wirken sich nur auf ein bestimmtes Backend aus und sind in anderen Backends ein No-Op.
Hier ist die Liste der vordefinierten AIDL-Annotationen:
| Annotationen | 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 |
nullable
nullable deklariert, dass der Wert der annotierten Entität null sein kann.
Sie können diese Annotation nur an Methodenrückgabetypen, Methodenparameter und Parcelable-Felder anhängen:
interface IFoo {
// method return types
@nullable Data method();
// method parameters
void method2(in @nullable Data d);
}
parcelable Data {
// parcelable fields
@nullable Data d;
}
Annotationen können nicht an primitive Typen angehängt werden. Das Folgende ist ein Fehler:
void method(in @nullable int a); // int is a primitive type
Diese Annotation hat keine Auswirkungen auf das Java-Backend. In Java werden alle nicht primitiven Typen als Referenz übergeben, was null sein könnte.
Im CPP-Backend wird @nullable T in Android 11 oder niedriger std::unique_ptr<T> und in Android 12 oder höher std::optional<T> zugeordnet.
Im NDK-Backend wird @nullable T std::optional<T> zugeordnet.
Im Rust-Backend wird @nullable T auf Option<T> abgebildet.
Bei einem listenähnlichen Typ L wie T[] oder List<T> wird @nullable L std::optional<std::vector<std::optional<T>>> zugeordnet (oder std::unique_ptr<std::vector<std::unique_ptr<T>>> im Fall des CPP-Back-Ends für Android 11 oder niedriger).
Es gibt eine Ausnahme von dieser Zuordnung. Wenn T IBinder oder eine AIDL-Schnittstelle ist, ist @nullable ein No-Op für die Java-, CPP- und NDK-Backends. Im CPP-Backend werden beispielsweise sowohl @nullable IBinder als auch IBinder gleichermaßen android::sp<IBinder> zugeordnet. android::sp<IBinder> ist bereits null-zulässig, da es sich um einen starken Zeiger handelt. Bei CPP- und NDK-Lesevorgängen wird weiterhin die Null-Zulässigkeit erzwungen, der Typ bleibt jedoch android::sp<IBinder> oder ndk::SpAIBinder.
Im Rust-Backend werden Typen, die Default nicht implementieren (IBinder, AIDL-Schnittstellen, ParcelFileDescriptor und unstrukturierte Parcelables), je nach Kontext auf Option<T> abgebildet:
- Methodenrückgabetypen,
in-Parameter undinout-Parameter:Diese Typen sind nur dann nullable, wenn sie mit@nullableannotiert sind. Sie werden dannOption<T>zugeordnet (oderOption<&T>fürin-Parameter und&mut Option<T>fürinout-Parameter). Ohne@nullablewerden sie direktT(oder&Tund&mut T) zugeordnet. - Parcelable-Felder und
out-Parameter:Da abgeleitete Parcelables in RustDefaultundout-Parameter standardmäßig initialisiert werden, werden diese Typen immerOption<T>zugeordnet (und Arrays mit fester Größe in diesen Kontexten werden[Option<T>; N]zugeordnet, während dynamische Arrays inout-ParameternVec<Option<T>>zugeordnet werden), auch ohne@nullable. Wenn sie nicht mit@nullableannotiert sind, wird die Nicht-Null-Eigenschaft zur Laufzeit während des Parceling weiterhin erzwungen (StatusCode::UNEXPECTED_NULLwird zurückgegeben, wenn der WertNoneist).
Ab Android 13 kann @nullable(heap=true) für parcelable-Felder verwendet werden, um rekursive Typen zu modellieren. @nullable(heap=true) kann nicht mit Methodenparametern oder Rückgabetypen verwendet werden. Wenn das Feld damit annotiert ist, wird es im CPP- und NDK-Backend einer heap-zugeordneten Referenz std::unique_ptr<T> zugeordnet. @nullable(heap=true) ist im Java-Backend ein No-Op.
utf8InCpp
utf8InCpp deklariert, dass String für das CPP-Backend im UTF8-Format 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 Annotation kann überall angehängt werden, wo der Typ String verwendet werden kann, einschließlich Rückgabewerten, Parametern, Konstantendeklarationen und Parcelable-Feldern.
Im CPP-Backend wird @utf8InCpp String in AIDL std::string zugeordnet. Dabei wird String ohne die Annotation android::String16 zugeordnet, wobei UTF16 verwendet wird.
VintfStability
VintfStability deklariert, dass ein benutzerdefinierter Typ (Schnittstelle, Parcelable und Enum) system- und anbieterübergreifend verwendet werden kann. Weitere Informationen zur Interoperabilität zwischen System und Anbieter finden Sie unter AIDL für HALs.
Die Annotation ändert die Signatur des Typs nicht. Wenn sie jedoch festgelegt ist, wird die Instanz des Typs als stabil markiert, sodass sie zwischen den Anbieter- und Systemprozessen übertragen werden kann.
Die Anmerkung kann nur an benutzerdefinierte Typdeklarationen angehängt werden, wie hier gezeigt:
@VintfStability
interface IFoo {
....
}
@VintfStability
parcelable Data {
....
}
@VintfStability
enum Type {
....
}
Wenn ein Typ mit VintfStability annotiert ist, sollte jeder andere Typ, auf den im Typ verwiesen wird, ebenfalls so 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 die Eigenschaft stability auf vintf gesetzt ist:
aidl_interface {
name: "my_interface",
srcs: [...],
stability: "vintf",
}
UnsupportedAppUsage
Die Annotation UnsupportedAppUsage gibt an, dass der annotierte AIDL-Typ Teil der Nicht-SDK-Schnittstelle ist, die für Legacy-Apps zugänglich war.
Weitere Informationen zu den verborgenen APIs finden Sie unter Einschränkungen für Nicht-SDK-Schnittstellen.
Die Annotation UnsupportedAppUsage hat keine Auswirkungen auf das Verhalten des generierten Codes. Die Annotation annotiert nur die generierte Java-Klasse mit der gleichnamigen Java-Annotation:
// in AIDL
@UnsupportedAppUsage
interface IFoo {...}
// in Java
@android.compat.annotation.UnsupportedAppUsage
public interface IFoo {...}
Für Nicht-Java-Back-Ends ist dies ein No-Op.
Hinweis zur Sicherung
Mit der Annotation Backing wird der Speichertyp eines AIDL-Enum-Typs angegeben:
@Backing(type="int")
enum Color { RED, BLUE, }
Im CPP-Backend wird dadurch eine C++-Enum-Klasse vom Typ int32_t ausgegeben:
enum class Color : int32_t {
RED = 0,
BLUE = 1,
}
Wird die Anmerkung weggelassen, wird type als byte angenommen, was für das CPP-Backend int8_t entspricht.
Das Argument type kann nur auf die folgenden integralen Typen festgelegt werden:
byte(8 Bit breit)int(32 Bit breit)long(64 Bit breit)
NdkOnlyStableParcelable
NdkOnlyStableParcelable kennzeichnet eine Parcelable-Deklaration (nicht Definition) als stabil, sodass darauf von anderen stabilen AIDL-Typen verwiesen werden kann. Dies entspricht JavaOnlyStableParcelable, aber NdkOnlyStableParcelable kennzeichnet eine Parcelable-Deklaration als stabil für das NDK-Backend anstelle von Java.
So verwenden Sie dieses Parcelable:
- Sie müssen
ndk_headerangeben. - Sie benötigen eine NDK-Bibliothek, in der das Parcelable angegeben ist. Die Bibliothek muss in die Bibliothek kompiliert werden. Verwenden Sie beispielsweise im Core-Build-System für ein
cc_*-Modulstatic_libsodershared_libs. Fügen Sie füraidl_interfacedie Bibliothek unteradditional_shared_librariesinAndroid.bphinzu.
JavaOnlyStableParcelable
JavaOnlyStableParcelable kennzeichnet eine Parcelable-Deklaration (nicht Definition) als stabil, sodass darauf von anderen stabilen AIDL-Typen verwiesen werden kann.
Für stabiles AIDL müssen alle benutzerdefinierten Typen stabil sein. Bei Parcelables muss die Stabilität durch eine explizite Beschreibung der Felder in der AIDL-Quelldatei gewährleistet 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 Parcelable unstrukturiert ist (oder nur deklariert wurde), 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 Parcelable, auf das Sie verweisen, sicher als Teil des Android SDK verfügbar ist:
@JavaOnlyStableParcelable
parcelable Data;
parcelable AnotherData {
Data d; // OK
}
JavaDerive
JavaDerive generiert automatisch Methoden für Parcelable-Typen im Java-Backend:
@JavaDerive(equals = true, toString = true)
parcelable Data {
int number;
String str;
}
Für die Anmerkung sind zusätzliche Parameter erforderlich, um zu steuern, was generiert werden soll. Folgende Parameter werden unterstützt:
equals=truegeneriert die MethodenequalsundhashCode.toString=truegeneriert die MethodetoString, die den Namen des Typs und der Felder ausgibt, z. B.Data{number: 42, str: foo}.
JavaDefault (eingestellt)
JavaDefault, die in Android 13 hinzugefügt wurde, steuert, ob die Standardimplementierungsversionsverwaltung 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.
Diese Anmerkungen in AIDL:
@JavaPassthrough(annotation="@android.annotation.Alice")
@JavaPassthrough(annotation="@com.android.Alice(arg=com.android.Alice.Value.A)")
werden im generierten Java-Code zu:
@android.annotation.Alice
@com.android.Alice(arg=com.android.Alice.Value.A)
Der Wert des Parameters annotation wird direkt ausgegeben. Der AIDL-Compiler prüft den Wert des Parameters nicht. Syntaxfehler auf Java-Ebene werden nicht vom AIDL-Compiler, sondern vom Java-Compiler erkannt.
Diese Annotation kann an jede AIDL-Entität angehängt werden. Diese Annotation hat keine Auswirkungen auf Backends, die nicht auf Java basieren.
RustDerive
RustDerive implementiert automatisch Traits für generierte Rust-Typen.
Für die Anmerkung sind zusätzliche Parameter erforderlich, um zu steuern, was generiert werden soll. Folgende Parameter werden unterstützt:
Copy=trueClone=trueOrd=truePartialOrd=trueEq=truePartialEq=trueHash=true
Erläuterungen zu diesen Merkmalen finden Sie in der Rust-Dokumentation.
FixedSize
FixedSize kennzeichnet ein strukturiertes Parcelable als feste Größe. Nachdem das Parcelable markiert wurde, können Sie keine neuen Felder mehr hinzufügen. Alle Felder des Parcelable-Objekts müssen Typen mit fester Größe sein, einschließlich primitiver Typen, Enums, Arrays mit fester Größe und anderer Parcelable-Objekte, die mit FixedSize gekennzeichnet sind.
FixedSize-Objekte haben stabile Größen und Ausrichtungen im ndk-Backend.
| Typ | Größe (Byte) | Ausrichtung (Byte) |
|---|---|---|
boolean |
1 |
1 |
byte |
1 |
1 |
char |
2 |
2 |
int |
4 |
4 |
long |
8 |
8 |
float |
4 |
4 |
double |
8 |
8 |
parcelable |
Gesamtgröße aller Felder | Größte Ausrichtung aller Felder |
union |
Größte Größe aller Felder | Größte Ausrichtung aller Felder |
enum |
Größe des Sicherungstyps | Ausrichtung des Backing-Typs |
T[N] (Array mit fester Größe) |
Größe von T * N |
Abstimmung von T |
String, IBinder, FileDescriptor, ParcelFileDescriptor |
N/A |
N/A |
Deskriptor
Descriptor gibt 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 Anmerkung Descriptor fehlt, lautet der Deskriptor android.foo.IHello.
Das 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.
@hide in comments
Der AIDL-Compiler erkennt @hide in Kommentaren und gibt sie an die Java-Ausgabe weiter, damit Metalava sie aufnehmen kann. Dieser Kommentar sorgt dafür, dass das Android-Build-System erkennt, dass AIDL-APIs keine SDK-APIs sind.
@deprecated 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 kennzeichnet eingestellte Entitäten mit einer backend-spezifischen Annotation oder einem Attribut, sodass der Clientcode gewarnt wird, wenn er auf die eingestellten Entitäten verweist. Die Annotation @Deprecated und das Tag @deprecated sind beispielsweise an den generierten Java-Code angehängt.