oneway异步接口
AIDL oneway 是接口/方法级协议:编译器要求返回 void 且没有 out/inout 参数,Java/CPP generator 发送 FLAG_ONEWAY 并省略 reply,Binder 驱动按同一 node 的异步队列串行交付。调用返回只说明提交没有立即失败,不代表远端方法已经执行完成。
本文承接 in-out-inout语义、Stub与Proxy代码生成 和 oneway异步事务队列。本文串联编译期与运行期,不重复驱动 buffer 算法。
1. AST与校验
1.1 Oneway状态
源码文件:system/tools/aidl/aidl_language.cpp
AidlMethod::AidlMethod(..., bool oneway, ...)
: oneway_(oneway),
oneway_annotation_(oneway) {}
AidlInterface::AidlInterface(..., bool oneway, ...) {
for (auto& method : GetMethods()) {
method->ApplyInterfaceOneway(oneway);
}
}interface 级 oneway 会应用到所有方法;方法级 oneway 只标记单个 AidlMethod。AST 保留 oneway 信息供 validation 和 generator 消费。
1.2 返回值限制
if (IsOneway() &&
GetType().GetName() != "void") {
AIDL_ERROR(this)
<< "oneway method cannot return a value";
return false;
}oneway 没有同步 reply,所以返回类型必须 void。该限制在 semantic validation,不是运行时丢弃返回值。
1.3 参数限制
if (IsOneway() && arg->IsOut()) {
AIDL_ERROR(this)
<< "oneway method cannot have out parameters";
return false;
}inout 包含 OUT 位,同样被拒绝。允许的参数只能沿请求方向传递。
2. Java生成
2.1 Proxy
源码文件:system/tools/aidl/generate_java_binder.cpp
if (oneway) {
flags.push_back(
"android.os.IBinder.FLAG_ONEWAY");
}
out << "mRemote.transact(..., "
<< (oneway ? "null" : "_reply")
<< ", flags);";oneway 不创建 reply Parcel,不调用 readException,也不读取返回值/out 参数;finally 只 recycle data。
2.2 Stub
if (!oneway) {
reply.writeNoException();
}
realCall();Stub 仍在 Binder 线程执行真实方法,只是不写同步 reply。Java 实现抛异常时发送方无法通过 readException 接收,异常只能在服务端日志/observer 中观察。
3. CPP生成
源码文件:system/tools/aidl/generate_cpp.cpp
if (method.IsOneway()) {
flags.push_back(
"::android::IBinder::FLAG_ONEWAY");
}
remote()->transact(code, data,
method.IsOneway() ? nullptr : &reply,
flags);CPP backend 与 Java backend 使用同一协议 flag,但类型、Parcel API 和 status 表达不同。oneway 语义来自 AIDL AST,不是某个语言独占能力。
4. 运行时语义
4.1 跨进程返回
Java IBinder 文档说明 oneway 跨进程调用立即返回,不等待 callee。驱动仍可能在提交阶段返回 DEAD_OBJECT、FAILED_TRANSACTION、FROZEN 等错误;没有业务 reply 不等于没有 transport error。
4.2 同node顺序
同一 IBinder/node 上多个 oneway 按发送顺序一次分发一个,前一个完成后才推进下一个。不同 Binder 对象、不同 node 或同步/oneway 混合不保证相同全局顺序。
4.3 本地调用
如果调用目标是同进程 Java Binder,Binder.transact() 直接调用 onTransact();FLAG_ONEWAY 不会创建驱动异步队列,方法可能同步执行并返回 false。接口设计不能用本地测试推断跨进程时序。
5. 冻结与失败
冻结目标进程时,同步事务返回错误,oneway 可在驱动中缓存并在解冻后交付;缓存内容可能过时。oneway buffer、spam detection 和 async quota 仍会限制大量异步调用。
服务端 RuntimeException 不会返回给 oneway 客户端;客户端只能通过独立 callback、状态查询或日志建立完成/失败闭环。
6. 测试边界
源码文件:frameworks/native/libs/binder/tests/binderLibTest.cpp
NopTransactionOneway 发送 TF_ONE_WAY 并断言 NO_ERROR。测试服务对 oneway 返回 UNKNOWN_ERROR,但客户端仍只观察提交结果,证明服务端业务 status 不通过 reply 返回。
同步 NopTransaction 用相同 code 但等待 reply,形成对照。测试不证明所有异步调用都低延迟,也不覆盖不同 node 的全局排序。
rg -n "IsOneway|cannot return|cannot have out" system/tools/aidl/aidl_language.cpp
rg -n "FLAG_ONEWAY|oneway|_reply" system/tools/aidl/generate_java_binder.cpp system/tools/aidl/generate_cpp.cpp
rg -n "NopTransactionOneway|TF_ONE_WAY" frameworks/native/libs/binder/tests/binderLibTest.cpp排查 oneway 事件丢失时,先区分编译器是否真的生成 FLAG_ONEWAY,再查 transport 提交、冻结/配额、node async 队列和服务端日志;如果业务需要完成结果,应设计独立 callback 或状态协议。
