AIDL 语言大致基于 Java 语言。文件指定接口协定以及此协定中使用的各种数据类型和常量。
软件包
每个 AIDL 文件都以一个可选软件包开头,该软件包对应于各种后端中的软件包名称。软件包声明如下所示
package my.package;
与 Java 类似,AIDL 文件必须位于与其软件包匹配的文件夹结构中。带有软件包 my.package
的文件必须位于文件夹 my/package/
中。
类型
在 AIDL 文件中,有很多地方可以指定类型。如需 AIDL 语言中支持的类型确切列表,请参阅 AIDL 后端类型。
注解
AIDL 语言的多个部分支持注解。如需注解列表及其可应用的位置,请参阅 AIDL 注解。
导入
要使用在其他接口中定义的类型,您必须先在构建系统中添加依赖项。在 cc_*
和 java_*
Soong 模块中,如果 .aidl
文件直接在 Android 平台构建中的 srcs
下使用,您可以添加使用字段 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
。Oneway
方法是异步调度的,无法返回结果。从同一线程到同一 binder 的单向方法也按顺序执行(尽管可能在不同的线程上)。如需讨论如何设置线程,请参阅 AIDL 后端线程管理。
Binder 允许通过 Binder 接口共享许多接口和 Binder 对象。AIDL 接口经常在方法调用中采用回调,例如前面示例中的 ITeleportCallback
。您可以在对同一方法或不同方法的调用之间重用回调对象。接口类型的另一种常见用途是用于从方法返回的子接口或会话对象,例如前面示例中的 ITeleportSession
。这种嵌套允许在 API 或基于运行时状态封装不同的 API。例如,会话可以表示特定资源的所有权。当接口多次传递或从它们来自的客户端或服务器返回时,它们始终保持底层 Binder 对象的指针相等性。
方法可以有零个或多个参数。方法的参数可以是 in
、out
或 inout
。有关这如何影响参数类型的讨论,请参阅 AIDL backends directionality。
Parcelables
有关如何创建特定于后端的 Parcelable 的描述,请参阅 AIDL backends custom parcelables。
Android 10 及更高版本支持直接在 AIDL 中定义 Parcelable。这种类型的 Parcelable 称为结构化 Parcelable。有关结构化 AIDL 和稳定 AIDL 如何在 AIDL 编译器和我们的构建系统中关联的更多信息,请参阅 Structured versus stable AIDL。
例如
package my.package;
import my.package.Boo;
parcelable Baz {
@utf8InCpp String name = "baz";
Boo boo;
}
Unions
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 Backends Unions。
Enums
Android 11 及更高版本支持枚举声明。例如
package my.package;
enum Boo {
A = 1 * 4,
B = 3,
}
Nested Type Declarations
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
}
Constants
自定义 AIDL 接口、Parcelable 和 Unions 也可以包含整数和字符串常量,例如
const @utf8InCpp String HAPPY = ":)";
const String SAD = ":(";
const byte BYTE_ME = 1;
const int ANSWER = 6 * 7;
Constant expressions
AIDL 常量、数组大小和枚举器可以使用常量表达式指定。表达式可以使用括号来嵌套运算。常量表达式值可以与整数值或浮点值一起使用。
true
和 false
字面量表示布尔值。带有 .
但没有后缀的值(例如 3.8
)被视为 double 值。浮点值带有 f
后缀,例如 2.4f
。带有 l
或 L
后缀的整数值表示 64 位 long 值。否则,整数值会获得 8 位(byte)、32 位(int)和 64 位(long)之间最小的保留值的有符号类型。因此,256
被视为 int
,但 255 + 1
溢出为 byte
0
。十六进制值(例如 0x3
)首先被解释为 32 位和 64 位之间最小的保留值的无符号类型,然后重新解释为无符号值。因此,0xffffffff
的 int
值为 -1
。从 Android 13 开始,可以将后缀 u8
添加到常量,例如 3u8
,以表示 byte
值。此后缀很重要,这样像 0xffu8 * 3
这样的计算会被解释为类型为 byte
的 -3
,而 0xff * 3
是类型为 int
的 765
。
支持的运算符具有 C++ 和 Java 语义。按照从最低到最高的优先级顺序,二元运算符为 || && | ^ & == != < > <= >= << >> + - * / %
。一元运算符为 + - ! ~
。