Język AIDL jest luźno oparty na języku Java. Pliki określają kontrakt interfejsu oraz różne typy danych i stałe używane w tym kontrakcie.
Pakiet
Każdy plik AIDL zaczyna się od opcjonalnego pakietu, który odpowiada nazwom pakietów w różnych backendach. Deklaracja pakietu wygląda następująco:
package my.package;
Podobnie jak w Javie, pliki AIDL muszą znajdować się w strukturze folderów odpowiadającej ich pakietowi. Pliki z pakietem my.package
muszą znajdować się w folderze my/package/
.
Typy
W plikach AIDL jest wiele miejsc, w których można określić typy. Aby uzyskać dokładną listę typów obsługiwanych w języku AIDL, zobacz Typy zaplecza AIDL .
Adnotacje
Kilka części adnotacji obsługujących język AIDL. Aby zapoznać się z listą adnotacji i miejsca ich zastosowania, zobacz Adnotacje AIDL .
Import
Aby użyć typów zdefiniowanych w innych interfejsach, należy najpierw dodać zależności w systemie kompilacji. W modułach cc_*
i java_*
Soong, gdzie pliki .aidl
są używane bezpośrednio w srcs
w kompilacjach platformy Android, możesz dodawać katalogi za pomocą pola aidl: { include_dirs: ... }
. Informacje na temat importu przy użyciu aidl_interface
można znaleźć tutaj .
Import wygląda następująco:
import some.package.Foo; // explicit import
Podczas importowania typu w tym samym pakiecie pakiet można pominąć. Chociaż pominięcie pakietu może prowadzić do niejednoznacznych błędów importu, gdy typy są określone bez pakietu i umieszczone w globalnej przestrzeni nazw (zazwyczaj wszystkie typy powinny mieć przestrzeń nazw):
import Foo; // same as my.package.Foo
Definiowanie typów
Pliki AIDL ogólnie definiują typy używane jako interfejs.
Interfejsy
Oto przykładowy interfejs AIDL:
interface ITeleport {
void teleport(Location baz, float speed);
String getName();
}
Interfejs definiuje obiekt za pomocą szeregu metod. Metody mogą być oneway
( oneway void doFoo()
) lub synchroniczne. Jeśli interfejs jest zdefiniowany jako oneway
( oneway interface ITeleport {...}
), wówczas wszystkie zawarte w nim metody są domyślnie oneway
. Metody jednokierunkowe są wywoływane asynchronicznie i nie mogą zwrócić wyniku. Gwarantuje się również, że metody jednokierunkowe z tego samego wątku do tego samego spoiwa będą wykonywane szeregowo (chociaż potencjalnie w różnych wątkach). Aby zapoznać się z omówieniem konfigurowania wątków, zobacz Zarządzanie wątkami zaplecza AIDL .
Metody mogą mieć zero lub więcej argumentów. Argumenty metod mogą być in
, out
lub inout
. Aby zapoznać się z omówieniem wpływu tego na typy argumentów, zobacz Kierunkowość zaplecza AIDL .
Przesyłki
Aby uzyskać opis sposobu tworzenia pakietów specyficznych dla backendu, AIDL backends niestandardowych pakietów paczkowych .
Android 10 i nowsze obsługują definicje umożliwiające pakowanie bezpośrednio w AIDL. Ten rodzaj przesyłek paczkowanych nazywa się przesyłkami strukturalnymi. Aby uzyskać więcej informacji na temat powiązań strukturalnego i stabilnego AIDL w kompilatorze AIDL i naszym systemie kompilacji, zobacz Strukturalny i stabilny AIDL .
Na przykład:
package my.package;
import my.package.Boo;
parcelable Baz {
@utf8InCpp String name = "baz";
Boo boo;
}
Związki
Android 12 i nowsze obsługują deklaracje unii. Na przykład:
package my.package;
import my.package.FooSettings;
import my.package.BarSettings;
union Settings {
FooSettings fooSettings;
BarSettings barSettings;
@utf8InCpp String str;
int number;
}
Wyliczenia
Deklaracje wyliczeń obsługujące Androida 11 i nowsze. Na przykład:
package my.package;
enum Boo {
A = 1 * 4,
B = 3,
}
Deklaracje typów zagnieżdżonych
Android 13 i nowsze obsługują deklaracje typów zagnieżdżonych. Na przykład:
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
}
Stałe
Niestandardowe interfejsy AIDL, pakiety i unie mogą również zawierać stałe całkowite i łańcuchowe, takie jak:
const @utf8InCpp String HAPPY = ":)";
const String SAD = ":(";
const byte BYTE_ME = 1;
const int ANSWER = 6 * 7;
Wyrażenia stałe
Stałe AIDL, rozmiary tablic i moduły wyliczające można określić za pomocą wyrażeń stałych. W wyrażeniach można używać nawiasów do zagnieżdżania operacji. Wartości wyrażeń stałych można używać z wartościami całkowitymi lub zmiennoprzecinkowymi.
literały true
i false
reprezentują wartości logiczne. Wartości z .
ale bez przyrostka, takiego jak 3.8
, są uważane za wartości podwójne. Wartości zmiennoprzecinkowe mają przyrostek f
, na przykład 2.4f
. Wartość całkowita z przyrostkiem l
lub L
oznacza wartość o długości 64 bitów. W przeciwnym razie wartości całkowe uzyskują najmniejszy typ znaku zachowujący wartość między 8-bitowym (bajtem), 32-bitowym (int) i 64-bitowym (długim). Zatem 256
jest uważane za int
, ale 255 + 1
przepełnia się jako byte
0
. Wartości szesnastkowe, takie jak 0x3
, są najpierw interpretowane jako najmniejszy typ bez znaku zachowujący wartość między 32-bitowymi a 64-bitowymi, a następnie ponownie interpretowane jako wartości bez znaku. Zatem 0xffffffff
ma wartość int
-1
. Począwszy od Androida 13, do stałych, takich jak 3u8
, można dodać przyrostek u8
, aby reprezentować wartość byte
. Ten przyrostek jest ważny, ponieważ obliczenia takie jak 0xffu8 * 3
są interpretowane jako -3
w przypadku typu byte
, podczas gdy 0xff * 3
wynosi 765
w przypadku typu int
.
Obsługiwane operatory mają semantykę C++ i Java. W kolejności od najniższego do najwyższego priorytetu operatorami binarnymi są || && | ^ & == != < > <= >= << >> + - * / %
. Operatory jednoargumentowe to + - ! ~
.