Die AIDL-Sprache basiert lose auf der Java-Sprache. In den Dateien wird ein Schnittstellenvertrag sowie verschiedene Datentypen und Konstanten angegeben, die in diesem Vertrag verwendet werden.
Paket
Jede AIDL-Datei beginnt mit einem optionalen Paket, das den Paketnamen in verschiedenen Back-Ends entspricht. Eine Paketdeklaration sieht so aus:
package my.package;
Ähnlich wie bei Java müssen sich AIDL-Dateien in einer Ordnerstruktur befinden, die ihrem Paket entspricht. Dateien mit dem Paket my.package müssen sich im Ordner my/package/ befinden.
Typen
In AIDL-Dateien gibt es viele Stellen, an denen Typen angegeben werden können. Eine genaue Liste der in der AIDL-Sprache unterstützten Typen finden Sie unter AIDL-Back-End-Typen.
Annotationen
Mehrere Teile der AIDL-Sprache unterstützen Annotationen. Eine Liste der Annotationen und der Stellen, an denen sie angewendet werden können, finden Sie unter AIDL-Annotationen.
Importe
Wenn Sie Typen verwenden möchten, die in anderen Schnittstellen definiert sind, müssen Sie zuerst Abhängigkeiten im Build-System hinzufügen. In cc_*\- und java_*-Soong-Modulen, in denen .aidl-Dateien direkt unter srcs in Android-Plattform-Builds verwendet werden, können Sie Verzeichnisse mit dem Feld aidl: { include_dirs: ... } hinzufügen. Informationen zu Importen mit
aidl_interface finden Sie
hier.
Ein Import sieht so aus:
import some.package.Foo; // explicit import
Wenn Sie einen Typ im selben Paket importieren, kann das Paket weggelassen werden. Wenn Sie das Paket weglassen, kann es jedoch zu mehrdeutigen Importfehlern kommen, wenn Typen ohne Paket angegeben und in den globalen Namespace eingefügt werden (im Allgemeinen sollten alle Typen einen Namespace haben):
import Foo; // same as my.package.Foo
Typen definieren
In AIDL-Dateien werden in der Regel Typen definiert, die als Schnittstelle verwendet werden.
Schnittstellen
Hier ein Beispiel für eine AIDL-Schnittstelle:
interface ITeleport {
// Location defined elsewhere
void teleport(Location baz, float speed);
String getName();
// ITeleportCallback defined elsewhere
void methodWithCallback(ITeleportCallback callback);
// ITeleportSession defined elsewhere
ITeleportSession getASubInterface();
}
Eine Schnittstelle definiert ein Objekt mit einer Reihe von Methoden. Methoden können entweder
oneway (oneway void doFoo()) oder synchron sein. Wenn eine Schnittstelle als
oneway (oneway interface ITeleport {...}) definiert ist, sind alle Methoden darin
implizit oneway. Oneway-Methoden werden asynchron gesendet und können kein Ergebnis zurückgeben. Oneway-Methoden vom selben Thread zum selben Binder werden auch seriell ausgeführt (möglicherweise in verschiedenen Threads). Informationen zum Einrichten von Threads finden Sie unter Threadverwaltung für AIDL-Back-Ends.
Mit Binder können viele Schnittstellen und Binder-Objekte über Binder-Schnittstellen freigegeben werden. AIDL-Schnittstellen verwenden häufig Callbacks als Teil von Methodenaufrufen, z. B. mit ITeleportCallback im vorherigen Beispiel. Sie können Callback-Objekte zwischen Aufrufen derselben Methode oder Aufrufen verschiedener Methoden wiederverwenden. Eine weitere häufige Verwendung von Schnittstellentypen besteht darin, dass Unter-Schnittstellen oder Sitzungsobjekte von Methoden zurückgegeben werden, z. B. mit ITeleportSession im vorherigen Beispiel. Durch diese Verschachtelung können verschiedene APIs entweder auf API-Ebene oder basierend auf dem Laufzeitstatus gekapselt werden. Eine Sitzung kann beispielsweise das Eigentum an einer bestimmten Ressource darstellen. Wenn Schnittstellen mehrmals übergeben oder an den Client oder Server zurückgegeben werden, von dem sie stammen, behalten sie immer die Zeigergleichheit des zugrunde liegenden Binder-Objekts bei.
Methoden können null oder mehr Argumente haben. Argumente für Methoden können
in, out oder inout sein. Informationen dazu, wie sich dies auf Argumenttypen auswirkt,
finden Sie unter
Richtung für AIDL-Back-Ends.
Parcelables
Eine Beschreibung zum Erstellen von Back-End-spezifischen Parcelables finden Sie unter Benutzerdefinierte Parcelables für AIDL-Back-Ends.
Android 10 und höher unterstützen Parcelable-Definitionen direkt in AIDL. Diese Art von Parcelable wird als strukturiertes Parcelable bezeichnet. Weitere Informationen zum Zusammenhang zwischen strukturiertem und stabilem AIDL im AIDL-Compiler und unserem Build-System finden Sie unter Strukturiertes und stabiles AIDL.
Beispiel:
package my.package;
import my.package.Boo;
parcelable Baz {
@utf8InCpp String name = "baz";
Boo boo;
}
Gewerkschaften
Android 12 und höher unterstützen getaggte Union-Deklarationen. Beispiel:
package my.package;
import my.package.FooSettings;
import my.package.BarSettings;
union Settings {
FooSettings fooSettings;
BarSettings barSettings;
@utf8InCpp String str;
int number;
}
Back-End-spezifische Details finden Sie unter Unions für AIDL-Back-Ends.
Enums
Android 11 und höher unterstützen Enum-Deklarationen. Beispiel:
package my.package;
enum Boo {
A = 1 * 4,
B = 3,
}
Verschachtelte Typdeklarationen
Android 13 und höher unterstützen verschachtelte Typdeklarationen. Beispiel:
package my.package;
import my.package.Baz;
interface IFoo {
void doFoo(Baz.Nested nested); // defined in my/package/Baz.aidl
void doBar(Bar bar); // defined below
parcelable Bar { ... } // nested type definition
}
Konstanten
Benutzerdefinierte AIDL-Schnittstellen, Parcelables und Unions können auch Ganzzahl- und Stringkonstanten enthalten, z. B.:
const @utf8InCpp String HAPPY = ":)";
const String SAD = ":(";
const byte BYTE_ME = 1;
const int ANSWER = 6 * 7;
Konstante Ausdrücke
AIDL-Konstanten, Arraygrößen und Enumeratoren können mit konstanten Ausdrücken angegeben werden. Ausdrücke können Klammern verwenden, um Operationen zu verschachteln. Konstante Ausdruckswerte können mit Ganzzahl- oder Gleitkommawerten verwendet werden.
true und false sind Literale für boolesche Werte. Werte mit einem . aber
ohne Suffix, z. B. 3.8, werden als Double-Werte betrachtet. Gleitkommawerte haben das f Suffix, z. B. 2.4f. Eine Ganzzahl mit dem l oder
L Suffix gibt einen 64-Bit-Long-Wert an. Andernfalls erhalten Ganzzahlwerte den kleinsten werterhaltenden vorzeichenbehafteten Typ zwischen 8 Bit (Byte), 32 Bit (Int) und 64 Bit (Long). 256 wird also als int betrachtet, aber 255 + 1 führt zu einem Überlauf und wird als byte 0 betrachtet. Hexadezimalwerte wie 0x3 werden zuerst als kleinster werterhaltender vorzeichenloser Typ zwischen 32 Bit und 64 Bit interpretiert und dann als vorzeichenlose Werte neu interpretiert. 0xffffffff hat also den int-Wert -1. Ab Android 13 kann das Suffix u8 zu Konstanten hinzugefügt werden
, z. B. 3u8, um einen byte Wert darzustellen. Dieses Suffix ist wichtig, damit eine Berechnung wie 0xffu8 * 3 als -3 mit dem Typ byte interpretiert wird, während 0xff * 3 765 mit dem Typ int ist.
Unterstützte Operatoren haben C++- und Java-Semantik. In der Reihenfolge von der niedrigsten zur
höchsten Priorität sind die binären Operatoren
|| && | ^ & == != < > <= >= << >> + - * / %. Unäre Operatoren sind + - ! ~.