Язык AIDL во многом основан на языке Java. Файлы определяют контракт интерфейса, а также различные типы данных и константы, используемые в этом контракте.
Упаковка
Каждый файл AIDL начинается с дополнительного пакета, который соответствует именам пакетов в различных бэкэндах. Объявление пакета выглядит следующим образом:
package my.package;
Как и в случае с Java, файлы AIDL должны находиться в структуре папок, соответствующей их пакету. Файлы с пакетом my.package
должны находиться в папке my/package/
.
Типы
В файлах AIDL есть много мест, где можно указывать типы. Точный список типов, которые поддерживаются языком AIDL, см. в разделе Типы серверных частей AIDL .
Аннотации
Некоторые части языка AIDL поддерживают аннотации. Список аннотаций и места их применения см. в разделе Аннотации AIDL .
Импорт
Чтобы использовать типы, определенные в других интерфейсах, необходимо сначала добавить зависимости в систему сборки. В модулях cc_*
и java_*
Soong, где файлы .aidl
используются непосредственно в srcs
в сборках платформы Android, вы можете добавлять каталоги, используя поле aidl: { include_dirs: ... }
. Об импорте с помощью aidl_interface
смотрите здесь .
Импорт выглядит следующим образом:
import some.package.Foo; // explicit import
При импорте типа в тот же пакет пакет можно опустить. Однако отсутствие пакета может привести к неоднозначным ошибкам импорта, если типы указаны без пакета и помещены в глобальное пространство имен (обычно все типы должны быть помещены в пространство имен):
import Foo; // same as my.package.Foo
Определение типов
Файлы AIDL обычно определяют типы, которые используются в качестве интерфейса.
Интерфейсы
Вот пример интерфейса AIDL:
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();
}
Интерфейс определяет объект с помощью ряда методов. Методы могут быть либо oneway
( oneway void doFoo()
), либо синхронными. Если интерфейс определен как oneway
( oneway interface ITeleport {...}
), то все методы в нем неявно являются oneway
. Односторонние методы отправляются асинхронно и не могут вернуть результат. Односторонние методы из одного и того же потока в одну и ту же связующую программу также выполняются последовательно (хотя потенциально в разных потоках). Обсуждение настройки потоков см. в разделе Управление потоками серверной части AIDL .
Binder позволяет совместно использовать многие интерфейсы и объекты связывания через интерфейсы связывания. Интерфейсы AIDL часто используют обратные вызовы как часть вызовов методов, например ITeleportCallback
в предыдущем примере. Вы можете повторно использовать объекты обратного вызова между вызовами одного и того же метода или вызовами разных методов. Другое распространенное использование типов интерфейса — это возврат подинтерфейсов или объектов сеанса из таких методов, как ITeleportSession
в предыдущем примере. Такое вложение позволяет инкапсулировать различные API либо в самом API, либо в зависимости от состояния времени выполнения. Например, сеанс может представлять владение определенным ресурсом. Когда интерфейсы передаются несколько раз или возвращаются клиенту или серверу, с которого они пришли, они всегда сохраняют равенство указателей базового объекта связывания.
Методы могут иметь ноль или более аргументов. Аргументы методов могут быть in
, out
или inout
. Обсуждение того, как это влияет на типы аргументов, см. в разделе Направленность бэкендов AIDL .
Посылки
Описание того, как создавать отдельные объекты для серверной части, можно найти в AIDL .
Android 10 и более поздних версий поддерживают определения пакетов непосредственно в AIDL. Этот тип посылок называется структурированным. Дополнительную информацию о том, как структурированный и стабильный AIDL связаны в компиляторе AIDL и нашей системе сборки, см. в разделе Структурированный и стабильный AIDL .
Например:
package my.package;
import my.package.Boo;
parcelable Baz {
@utf8InCpp String name = "baz";
Boo boo;
}
Союзы
Android 12 и более поздних версий поддерживают теговые объявления объединения. Например:
package my.package;
import my.package.FooSettings;
import my.package.BarSettings;
union Settings {
FooSettings fooSettings;
BarSettings barSettings;
@utf8InCpp String str;
int number;
}
Подробную информацию о бэкендах смотрите в разделе AIDL Backend Unions .
Перечисления
Android 11 и более поздних версий поддерживают объявления перечислений. Например:
package my.package;
enum Boo {
A = 1 * 4,
B = 3,
}
Объявления вложенных типов
Android 13 и более поздних версий поддерживают объявления вложенных типов. Например:
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
}
Константы
Пользовательские интерфейсы AIDL, фрагменты и объединения также могут содержать целочисленные и строковые константы, такие как:
const @utf8InCpp String HAPPY = ":)";
const String SAD = ":(";
const byte BYTE_ME = 1;
const int ANSWER = 6 * 7;
Постоянные выражения
Константы AIDL, размеры массивов и перечислители можно указать с помощью константных выражений. Выражения могут использовать круглые скобки для вложения операций. Значения константных выражений можно использовать с целыми значениями или значениями с плавающей запятой.
Литералы true
и false
представляют логические значения. Значения с расширением .
но без суффикса, например 3.8
, считаются двойными значениями. Значения с плавающей запятой имеют суффикс f
, например 2.4f
. Целочисленное значение с суффиксом l
или L
указывает на 64-битное длинное значение. В противном случае целочисленные значения получают наименьший сохраняющий значение знаковый тип между 8-битным (байт), 32-битным (int) и 64-битным (длинным). Таким образом, 256
считается int
, но 255 + 1
переполняется и становится byte
0
. Шестнадцатеричные значения, такие как 0x3
, сначала интерпретируются как наименьший сохраняющий значение беззнаковый тип между 32-битными и 64-битными, а затем интерпретируются повторно как беззнаковые значения. Итак, 0xffffffff
имеет значение int
-1
. Начиная с Android 13, к константам, например 3u8
, можно добавлять суффикс u8
для обозначения byte
значения. Этот суффикс важен, поскольку вычисление, такое как 0xffu8 * 3
, интерпретируется как -3
для типа byte
, тогда как 0xff * 3
— это 765
для типа int
.
Поддерживаемые операторы имеют семантику C++ и Java. Бинарные операторы в порядке от низшего к высшему приоритету имеют вид || && | ^ & == != < > <= >= << >> + - * / %
. Унарные операторы + - ! ~
.