2021-11-17 AIDL

AIDL 概览

Android 接口定义语言 (AIDL) 是一款可供用户用来抽象化 IPC 的工具。以在 .aidl 文件中指定的接口为例,各种构建系统都会使用 aidl 二进制文件构造 C++ 或 Java 绑定,以便跨进程使用该接口(无论其运行时环境或位数如何)。

AIDL 可以在 Android 中的任何进程之间使用:在平台组件之间使用或在应用之间使用均可。但是,AIDL 绝不能用作应用的 API。例如,可以使用 AIDL 在平台中实现 SDK API,但 SDK API Surface 绝不能直接包含 AIDL API。在 APEX(从 Android 10 开始)或 HAL(从 Android 11 开始)等单独更新的平台组件之间使用 AIDL 时,必须使用称为稳定的 AIDL的版本控制系统。

示例

以下是一个 AIDL 接口示例:

package my.package;

import my.package.Baz; // defined elsewhere

interface IFoo {
    void doFoo(Baz baz); // synchronous method
    oneway void doFoo(int a); // async method
}

Android 10 及更高版本支持 parcelable 声明。例如:

 package my.package;

import my.package.Boo;

parcelable Baz {
    @utf8InCpp String name = "baz";
    Boo boo;
}

Android 11 及更高版本支持枚举声明。例如:

package my.package;

enum Boo {
    A = 1 * 4,
    B = 3,
}

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 T(AOSP 实验版)及更高版本支持嵌套类型声明。 例如:

package my.package;

import my.package.Baz;

interface IFoo {
    void doFoo(Baz.Nested nested);  // defined my/package/Baz.aidl
    void doBar(Bar bar);            // defined below

    parcelable Bar { ... }          // union/enum types can be nested, while
                                    // an interface can't.
}

服务器进程注册接口并提供对它的调用,客户端进程则调用这些接口。在许多情况下,进程既是客户端又是服务器,因为它可能会引用多个接口。如需详细了解可供您用来使用这些接口的各种运行时环境,请参阅 AIDL 后端。这些类型声明与给定语言中的类声明完全相同,但可以跨进程工作。

工作原理

AIDL 使用 Binder 内核驱动程序进行调用。当您发出调用时,系统会将方法标识符和所有对象打包到某个缓冲区中,然后将其复制到某个远程进程,该进程中有一个 Binder 线程正在等待读取数据。Binder 线程收到某个事务的数据后,该线程会在本地进程中查找原生桩对象,然后此类会解压缩数据并调用本地接口对象。此本地接口对象正是服务器进程所创建和注册的对象。当在同一进程和同一后端中进行调用时,不存在代理对象,因此直接调用即可,无需执行任何打包或解压缩操作。

与设备上的服务互动

Android 具有一些命令,可供您用来与设备上的服务互动。请尝试输入:

    adb shell dumpsys --help # listing and dumping services
    adb shell service --help # sending commands to services for testing

你可能感兴趣的:(2021-11-17 AIDL)