AIDL 语言

AIDL 语言大致上基于 Java 语言。文件会指定接口协定以及此协定中使用的各种数据类型和常量。

软件包

每个 AIDL 文件都以一个可选软件包开头,该软件包与各个后端中的软件包名称相对应。软件包声明如下所示:

    package my.package;

与 Java 类似,AIDL 文件必须位于与其软件包匹配的文件夹结构中。包含软件包 my.package 的文件必须位于 my/package/ 文件夹中。

类型

在 AIDL 文件中,可以在许多位置指定类型。如需查看 AIDL 语言所支持类型的确切列表,请参阅 AIDL 后端类型

注释

AIDL 语言的多个部分均支持注解。如需查看注解列表以及可以应用它们的位置,请参阅 AIDL 注解

导入

如需使用其他接口中定义的类型,必须先在构建系统中添加依赖项。在 cc_*java_* Soong 模块中,.aidl 文件会直接在 Android 平台 build 中的 srcs 下使用,您可以使用 aidl: { include_dirs: ... } 这一字段添加目录。如需使用 aidl_interface 导入,请参阅此处

导入过程如下所示:

    import some.package.Foo;  // explicit import

导入同一软件包中的类型时,软件包可以省略。不过,如果在未指定软件包的情况下指定类型并放入全局命名空间(通常所有类型都应设定命名空间),则省略软件包可能会导致不明确的导入错误:

    import Foo;  // same as my.package.Foo

定义类型

AIDL 文件一般会定义用作接口的类型。

接口

以下是一个 AIDL 接口示例:

    interface ITeleport {
        void teleport(Location baz, float speed);
        String getName();
    }

接口通过一系列方法定义对象。方法可以是 oneway (oneway void doFoo()),也可以是同步方法。如果某个接口被定义为 oneway (oneway interface ITeleport {...}),则该接口中的所有方法都隐式地带上 oneway。oneway 方法会异步调度,并且无法返回结果。同一线程到同一 binder 的单向方法也会按顺序执行(但可能会在不同线程上执行)。如需查看有关如何设置线程的讨论,请参阅 AIDL 后端线程管理

方法可以有零个或多个参数。方法的参数可以是 inoutinout。如需查看有关这会如何影响参数类型的讨论,请参阅 AIDL 后端方向性

Parcelable

如需了解如何创建特定于后端的 Parcelable,请参阅 AIDL 后端自定义 Parcelable

Android 10 及更高版本支持直接使用 AIDL 进行 Parcelable 定义。这种类型的 Parcelable 称为结构化 Parcelable。如需详细了解结构化 AIDL 和稳定的 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;
    }

枚举

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 接口、Parcelable 和联合体还可以包含整数和字符串常量,例如:

    const @utf8InCpp String HAPPY = ":)";
    const String SAD = ":(";
    const byte BYTE_ME = 1;
    const int ANSWER = 6 * 7;

常量表达式

您可以使用常量表达式指定 AIDL 常量、数组大小和枚举器。表达式可以使用括号来嵌套运算。常量表达式值可与整数或浮点值搭配使用。

truefalse 字面量表示布尔值。包含 . 但没有后缀的值(例如 3.8)会被视为双精度值。浮点值具有 f 后缀,例如 2.4f。以 lL 为后缀的整数值表示 64 位长的值。否则,整数值会获得 8 位(字节)、32 位(整型)和 64 位(长整型)之间的最小值保留有符号类型。因此,256 被视为 int,但 255 + 1 溢出为 byte 0。十六进制值(例如 0x3)首先被解析为 32 位到 64 位之间的最小值保留无符号类型,然后再重新解析为无符号值。因此,0xffffffffint 值为 -1。从 Android 13 开始,可以将后缀 u8 添加到常量中(例如 3u8),以表示 byte 值。此后缀非常重要,因此 0xffu8 * 3 计算解释为 -3(类型为 byte),而 0xff * 3 解释为 765(类型为 int)。

支持的运算符具有 C++ 和 Java 语义。按照优先级从低到高的顺序,二元运算符为 || && | ^ & == != < > <= >= << >> + - * / %,一元运算符为 + - ! ~