AIDL unterstützt Anmerkungen, die dem AIDL-Compiler zusätzliche Informationen zum annotierten 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 Anmerkung und AidlEntity
ist eine AIDL-Entität wie interface Foo
, void method()
oder int arg
. Eine Anmerkung ist der Entität zugeordnet, die ihr folgt.
Einige Anmerkungen können Argumente in den Klammern haben, wie oben gezeigt. Bei Anmerkungen ohne Argument sind keine Klammern erforderlich. Beispiel:
@AnnotationName AidlEntity
Diese Anmerkungen sind nicht mit den Java-Anmerkungen identisch, obwohl sie sehr ähnlich aussehen. Nutzer können keine benutzerdefinierten AIDL-Anmerkungen definieren. Die Anmerkungen sind alle vordefiniert. Einige Anmerkungen wirken sich nur auf ein bestimmtes Backend aus und haben in anderen Backends keine Auswirkungen. Für sie gelten unterschiedliche Einschränkungen, wo sie angebracht werden können.
Hier ist eine 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 |
nullable
nullable
gibt an, dass der Wert der annotierten Entität möglicherweise nicht angegeben 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. Das folgende ist ein Fehler.
void method(in @nullable int a); // int is a primitive type
Diese Anmerkung hat für das Java-Backend keine Auswirkungen. Das liegt daran, dass in Java alle nicht primitiven Typen per Verweis übergeben werden, was null
sein könnte.
Im CPP-Backend wird @nullable T
unter Android 11 oder niedriger mit std::unique_ptr<T>
und unter Android 12 oder höher mit std::optional<T>
abgeglichen.
Im NDK-Backend wird @nullable T
immer std::optional<T>
zugeordnet.
Im Rust-Backend wird @nullable T
immer Option<T>
zugeordnet.
Bei einem 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) abgebildet.
Es gibt jedoch eine Ausnahme von dieser Zuordnung. Wenn T
IBinder
oder eine AIDL-Schnittstelle ist, ist @nullable
für alle Back-Ends außer Rust eine No-Op. Mit anderen Worten: Sowohl @nullable IBinder
als auch IBinder
werden gleichermaßen auf android::sp<IBinder>
abgebildet, das bereits nullable ist, da es sich um einen starken Pointer handelt. Bei C++-Lesevorgängen wird weiterhin die Nullableness erzwungen, der Typ ist jedoch weiterhin android::sp<IBinder>
. In Rust sind diese Typen nur dann nullable
, wenn sie mit @nullable
annotiert sind. Sie werden Option<T>
zugeordnet, wenn sie kommentiert sind.
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 das Feld damit annotiert ist, wird es in den CPP/NDK-Backends einer heap-allozierten Referenz std::unique_ptr<T>
zugeordnet. @nullable(heap=true)
ist im Java-Backend eine Null-Operation.
utf8InCpp
utf8InCpp
gibt an, dass ein String
im UTF-8-Format für das CPP-Backend dargestellt wird. Wie der Name schon sagt, hat die Anmerkung für andere Back-Ends keine Auswirkungen.
Im Java-Backend ist String
immer UTF-16 und im NDK-Backend UTF-8.
Diese Anmerkung kann überall angebracht werden, wo der Typ String
verwendet werden kann, einschließlich Rückgabewerten, Parametern, Konstantendeklarationen und Parcelable-Feldern.
Für das CPP-Backend wird @utf8InCpp String
in AIDL std::string
zugeordnet, während String
ohne Anmerkung android::String16
zugeordnet wird, wenn UTF-16 verwendet wird.
Die Existenz der Anmerkung utf8InCpp
ändert nichts daran, wie Strings über die Leitung übertragen werden. Strings werden immer als UTF-16 übertragen. Ein mit utf8InCpp
annotierter String wird vor der Übertragung in UTF-16 konvertiert. Wenn ein String empfangen wird, wird er von UTF-16 in UTF-8 konvertiert, wenn er als utf8InCpp
gekennzeichnet wurde.
VintfStability
VintfStability
deklariert, dass ein benutzerdefinierter Typ (interface, 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 Anmerkung ändert nicht die Signatur des Typs. Wenn sie jedoch festgelegt ist, wird die Instanz des Typs als stabil gekennzeichnet, sodass sie über die Anbieter- und Systemprozesse hinweg ü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
gekennzeichnet sein.
@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 Typen mit VintfStability
annotieren, nur mit dem Soong-Modultyp aidl_interface
erstellt werden, wobei die Eigenschaft stability
auf "vintf"
festgelegt ist.
aidl_interface {
name: "my_interface",
srcs: [...],
stability: "vintf",
}
UnsupportedAppUsage
Die Anmerkung UnsupportedAppUsage
gibt an, dass der annotierte AIDL-Typ Teil der Nicht-SDK-Benutzeroberfläche ist, die für ältere Apps zugänglich war.
Weitere Informationen zu den ausgeblendeten APIs finden Sie unter Einschränkungen für Nicht-SDK-Schnittstellen.
Die UnsupportedAppUsage
-Anmerkung hat keine Auswirkungen auf das Verhalten des generierten Codes. Die Annotation fügt nur der generierten Java-Klasse die Java-Anmerkung mit demselben Namen hinzu.
// in AIDL
@UnsupportedAppUsage
interface IFoo {...}
// in Java
@android.compat.annotation.UnsupportedAppUsage
public interface IFoo {...}
Für andere Back-Ends ist dies nicht erforderlich.
Unterlage
Die Anmerkung Backing
gibt den Speichertyp eines AIDL-Enumtyps an.
@Backing(type="int")
enum Color { RED, BLUE, }
Im CPP-Backend wird dadurch eine C++-Enum-Klasse vom Typ int32_t
generiert.
enum class Color : int32_t {
RED = 0,
BLUE = 1,
}
Wird die Anmerkung weggelassen, wird für type
byte
angenommen, was für das CPP-Backend zu int8_t
führt.
Das Argument type
kann nur auf die folgenden Ganzzahltypen 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. Das ist ähnlich wie JavaOnlyStableParcelable
, aber NdkOnlyStableParcelable
kennzeichnet eine Parcelable-Deklaration als stabil für das NDK-Backend anstelle von Java.
So verwenden Sie diese Parcelable:
- Sie müssen
ndk_header
angeben. - Sie benötigen eine NDK-Bibliothek, in der das Parcelable angegeben ist, und die Bibliothek muss in die Bibliothek kompiliert werden. Verwenden Sie beispielsweise im Kern-Build-System eines
cc_*
-Modulsstatic_libs
odershared_libs
. Fügen Sie füraidl_interface
die Bibliothek unteradditional_shared_libraries
inAndroid.bp
hinzu.
JavaOnlyStableParcelable
JavaOnlyStableParcelable
kennzeichnet eine Parcelable-Deklaration (nicht Definition) als stabil, sodass darauf von anderen stabilen AIDL-Typen verwiesen werden kann.
Für stabile AIDL-Dateien müssen alle benutzerdefinierten Typen stabil sein. Damit Parcelable-Objekte stabil sind, müssen ihre Felder in der AIDL-Quelldatei explizit 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 Parcelable unstrukturiert (oder nur deklariert) war, kann es nicht referenziert 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, 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 paketbare 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=true
generiert die Methodenequals
undhashCode
.toString=true
generiert die MethodetoString
, die den Namen des Typs und der Felder ausgibt. Beispiel:Data{number: 42, str: foo}
JavaDefault
JavaDefault
, in Android 13 hinzugefügt, steuert, ob die Standardimplementierung für die Versionsverwaltung generiert wird (für setDefaultImpl
). 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 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 Parameters annotation
wird direkt gesendet. 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 Anmerkung kann an jede AIDL-Entität angehängt werden. Diese Anmerkung hat für Nicht-Java-Backends keine Auswirkungen.
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=true
Clone=true
Ord=true
PartialOrd=true
Eq=true
PartialEq=true
Hash=true
Erklärungen zu diesen Traits finden Sie unter https://doc.rust-lang.org.
FixedSize
FixedSize
kennzeichnet ein strukturiertes Parcelable als feste Größe. Nach dem Markieren können dem Parcelable keine neuen Felder hinzugefügt werden. Alle Felder des Parcelable-Objekts müssen auch Typen mit fester Größe sein, einschließlich primitiver Typen, Enumerationen, Arrays mit fester Größe und anderer Parcelable-Objekte, die mit FixedSize
gekennzeichnet sind.
Dies bietet keine Garantie für unterschiedliche Bitbreiten und sollte bei der Kommunikation mit gemischten Bitbreiten nicht verwendet werden.
Beschreibung
Descriptor
gibt den Interface-Descriptor einer Schnittstelle erzwungen an.
package android.foo;
@Descriptor(value="android.bar.IWorld")
interface IHello {...}
Der Descriptor dieser Schnittstelle ist android.bar.IWorld
. Wenn die Anmerkung Descriptor
fehlt, lautet der Deskriptor android.foo.IHello
.
Dies ist nützlich, um eine bereits veröffentlichte Benutzeroberfläche umzubenennen. Wenn der Deskriptor der umbenannten Schnittstelle mit dem Deskriptor der Schnittstelle vor der Umbenennung übereinstimmt, können die beiden Schnittstellen miteinander kommunizieren.
@hide in comments
Der AIDL-Compiler erkennt @hide
in Kommentaren und gibt es an die Java-Ausgabe weiter, damit es von Metalava übernommen werden kann. Dieser Kommentar sorgt dafür, dass das Android-Build-System weiß, dass AIDL-APIs keine SDK-APIs sind.
@deprecated in comments
Der AIDL-Compiler erkennt @deprecated
in Kommentaren als Tag, um eine AIDL-Entität zu identifizieren, die nicht mehr verwendet werden soll.
interface IFoo {
/** @deprecated use bar() instead */
void foo();
void bar();
}
Jedes Backend kennzeichnet eingestellte Entitäten mit einer backendspezifischen Anmerkung oder einem backendspezifischen Attribut, damit im Clientcode eine Warnung ausgegeben wird, wenn auf eingestellte Entitäten verwiesen wird. Beispielsweise werden die Anmerkung @Deprecated
und das Tag @deprecated
an den generierten Java-Code angehängt.