Die AIDL-Sprache basiert lose auf der Java-Sprache. In den Dateien werden ein Interface-Vertrag und 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 dem Paket entspricht. Dateien mit dem Paket „my.package
“ müssen sich im Ordner „my/package/
“ befinden.
Typen
In AIDL-Dateien können an vielen Stellen Typen angegeben werden. Eine genaue Liste der Typen, die in der AIDL-Sprache unterstützt werden, finden Sie unter AIDL-Back-End-Typen.
Anmerkungen
Mehrere Teile der AIDL-Sprache unterstützen Anmerkungen. Eine Liste der Anmerkungen und ihrer Verwendungsmöglichkeiten finden Sie unter AIDL-Anmerkungen.
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 in Android-Plattform-Builds direkt unter srcs
verwendet werden, können Sie mit dem Feld aidl: { include_dirs: ... }
Verzeichnisse hinzufügen. Informationen zu Importen mit aidl_interface
finden Sie hier.
Ein Import sieht so aus:
import some.package.Foo; // explicit import
Beim Importieren eines Typs im selben Paket kann das Paket weggelassen werden. Das Auslassen des Pakets kann jedoch zu mehrdeutigen Importfehlern führen, wenn Typen ohne Paket angegeben und in den globalen Namespace eingefügt werden. Im Allgemeinen sollten alle Typen einen Namensraum 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 ist eine Beispiel-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
. Einwegmethoden werden asynchron gesendet und können kein Ergebnis zurückgeben. Einwegmethoden vom selben Thread in denselben Binder werden auch nacheinander ausgeführt (möglicherweise auf verschiedenen Threads). Weitere Informationen zum Einrichten von Threads finden Sie unter Thread-Management für AIDL-Back-Ends.
Binder ermöglicht die Freigabe vieler Schnittstellen und Binder-Objekte über Binder-Schnittstellen. In AIDL-Schnittstellen werden häufig Callbacks als Teil von Methodenaufrufen verwendet, z. B. ITeleportCallback
im vorherigen Beispiel. Sie können Rückrufobjekte zwischen Aufrufen derselben Methode oder Aufrufen verschiedener Methoden wiederverwenden. Schnittstellentypen werden auch häufig verwendet, um Subschnittstellen oder Sitzungsobjekte mit Methoden wie ITeleportSession
im vorherigen Beispiel zurückzugeben. Durch dieses Verschachtelungsmuster können verschiedene APIs entweder auf API-Ebene oder basierend auf dem Laufzeitstatus gekapselt werden. Eine Sitzung kann beispielsweise die Inhaberschaft einer bestimmten Ressource darstellen. Wenn Schnittstellen mehrmals übergeben oder an den Client oder Server zurückgegeben werden, von dem sie gekommen sind, bewahren sie immer die Zeigergleichheit des zugrunde liegenden Binderobjekts auf.
Methoden können null oder mehr Argumente haben. Argumente für Methoden können in
, out
oder inout
sein. Eine Erläuterung dazu, wie sich dies auf Argumenttypen auswirkt, finden Sie unter Richtung von AIDL-Back-Ends.
Parcelables
Eine Beschreibung zum Erstellen backendspezifischer Parcelables finden Sie unter Benutzerdefinierte Parcelables für AIDL-Backends.
Android 10 und höher unterstützen Parcelable-Definitionen direkt in AIDL. Diese Art von Parzelle wird als strukturierte Parzelle bezeichnet. Weitere Informationen dazu, wie sich strukturierte und stabile AIDL im AIDL-Compiler und in unserem Build-System unterscheiden, 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;
}
Backendspezifische Details finden Sie unter AIDL-Backend-Unions.
Aufzählungen
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 Unionen 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 mithilfe von konstanten Ausdrücken angegeben werden. In Ausdrücken können Klammern verwendet werden, um Vorgänge zu verschachteln. Konstante Ausdruckswerte können mit Ganzzahl- oder Gleitkommawerten verwendet werden.
true
- und false
-Literale stellen boolesche Werte dar. Werte mit .
, aber ohne Suffix, z. B. 3.8
, gelten als doppelte Werte. Gleitkommawerte haben das Suffix f
, z. B. 2.4f
. Ein ganzzahliger Wert mit dem Suffix l
oder L
gibt einen 64 Bit langen Wert an. Andernfalls wird für Ganzzahlwerte der kleinste Werttyp mit Vorzeichen zwischen 8-Bit (Byte), 32-Bit (int) und 64-Bit (long) verwendet. 256
wird also als int
betrachtet, aber 255 + 1
überschreitet den Grenzwert und wird zum byte
0
. 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 Wert int
-1
. Ab Android 13 kann das Suffix u8
Konstanten wie 3u8
hinzugefügt werden, um einen byte
-Wert anzugeben. Dieses Suffix ist wichtig, damit eine Berechnung wie 0xffu8 * 3
als -3
vom Typ byte
interpretiert wird, während 0xff * 3
765
vom Typ int
ist.
Die unterstützten Operatoren haben C++- und Java-Semantik. Die binären Operatoren haben folgende Priorität: || && | ^ & == != < > <= >= << >> + - * / %
. Unäre Operatoren sind + - ! ~
.