Stub与Proxy代码生成
AIDL Java backend 先加载并校验文档,再计算输出路径,最后由 Java generator 和 CodeWriter 生成文件;Stub/Proxy 只是 backend 输出,不是 parser 阶段直接拼接的模板。
本文承接 AIDL编译器原理、Stub与Proxy代码分析 和 AIDL语法详解。本文聚焦 generator owner、输出路径、Java AST 和生成约束,不展开每个 Parcel 类型的全部模板。
1. 生成入口
1.1 Java分支
源码文件:system/tools/aidl/aidl.cpp
if (lang == Options::Language::JAVA) {
if (defined_type->AsUnstructuredParcelable() != nullptr) {
success = true;
if (!options.OutputDir().empty()) {
io_delegate.GetCodeWriter(output_file_name)->Close();
}
} else {
java::GenerateJava(output_file_name, options,
typenames, *defined_type,
io_delegate);
success = true;
}
}Java backend 对 structured interface/parcelable 生成代码;legacy unstructured parcelable 可能只产生空输出文件,不应把成功等同于有 Java class 内容。
1.2 输出路径
GetOutputFilePath 根据 package、定义类型和 output dir 计算目标文件;dependency file 记录输入和 import。输出路径、依赖文件和 writer 失败属于生成阶段错误,不是 grammar 错误。
2. Java生成器
2.1 GenerateJava
源码文件:system/tools/aidl/generate_java.cpp
namespace android::aidl::java {
bool GenerateJava(const std::string& output_file,
const Options& options,
AidlTypenames* typenames,
const AidlDefinedType& defined_type,
const IoDelegate& io_delegate) {
CodeWriterPtr writer =
io_delegate.GetCodeWriter(output_file);
if (!writer) return false;
CodeGeneratorContext context(
options, typenames, defined_type, writer);
return context.Generate();
}
}generator 接收已解析的 AidlDefinedType,不重新读取 grammar。CodeGeneratorContext 负责 Java 类型映射、接口/parcelable 分支、注解和输出写入。
2.2 Java AST
源码文件:system/tools/aidl/ast_java.cpp
Java AST 把 AIDL 节点转换成 Java package、type、method、field 和 annotation 表达。它是生成器中间结构,既不是原始 grammar AST,也不是最终文本。
3. Stub输出
3.1 类型职责
生成 Stub 通常继承 Binder 并实现接口,提供 DESCRIPTOR、asInterface、asBinder 和 onTransact。编译器根据 interface members 产生 transaction constants 和方法分支。
3.2 解包顺序
真实 IServiceCallback:
源码文件:frameworks/native/libs/binder/aidl/android/os/IServiceCallback.aidl
oneway interface IServiceCallback {
void onRegistration(@utf8InCpp String name, IBinder binder);
}Stub 生成的 onTransact 必须按声明顺序检查 token,再读取 String 和 IBinder,最后调用 onRegistration。参数顺序是 schema 的直接消费者。
3.3 标准分支
Stub 对 INTERFACE_TRANSACTION 返回 descriptor;业务 code 执行解包和方法调用;oneway 不写 reply。unknown code 由生成基类或父类处理,具体结果取决于 generator 版本和接口基类。
4. Proxy输出
4.1 发送顺序
生成 Proxy 保存远程 IBinder。以 IServiceCallback 为例,业务方法需要 obtain Parcel、写 token、写 name、写 Binder、调用 transact 并 finally recycle data。oneway 的 reply 为 null,flags 包含 FLAG_ONEWAY。
4.2 异常策略
同步方法通常 readException;oneway 没有同步异常 Parcel。生成器根据 method oneway 属性选择 flags 和 reply 代码。
5. CodeWriter
源码文件:system/tools/aidl/code_writer.cpp
CodeWriter 负责打开目标、写文本、写依赖文件并报告 IO 错误。它不决定 transaction code,也不检查 Parcelable 类型是否可跨 backend;这些职责在 semantic validation 和 generator context。
生成输出是编译输入,不是运行时证明:Java 编译、ServiceManager 注册、权限和线程池仍需后续阶段。
6. 测试边界
6.1 Golden输出
源码文件:system/tools/aidl/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ITestService.java
golden output 将生成 Java 文件与预期文本比较,覆盖 Stub/Proxy、Parcelable、enum、数组和异常路径的稳定输出。它证明 generator 输出变化可被发现,不代表所有 backend 共用相同代码。
6.2 Generator测试
源码文件:system/tools/aidl/ast_java_unittest.cpp
测试 Java AST 类型、命名和注解映射;code_writer_unittest.cpp 覆盖 writer 输出/错误。它们分别验证中间结构和文件写入,不替代端到端 aidl 命令。
rg -n "GenerateJava|CodeGeneratorContext|Java" system/tools/aidl/generate_java.cpp system/tools/aidl/aidl.cpp system/tools/aidl/ast_java.cpp
rg -n "CodeWriter|GetCodeWriter|dependency" system/tools/aidl/code_writer.cpp
rg -n "ITestService|golden_output|Java" system/tools/aidl/tests system/tools/aidl/*unittest.cpp排查生成 Stub/Proxy 异常时,先确认输入 AST/semantic validation,再看 Java AST 映射、输出路径和 CodeWriter,最后检查 transaction code、Parcel 顺序和 oneway flags。
