Binder调用源码地图
“Binder 是 Android 的 IPC 机制”只能作为名词解释,不能作为源码阅读路线。真正需要回答的问题是:客户端拿到的 IBinder 从哪里来,一次 transact() 如何变成驱动命令,服务进程的哪个线程收到它,reply 又怎样回到原调用线程。
本文面向已经掌握 Java/C++ 方法调用、JNI 基本概念、Linux 文件描述符和 AIDL 接口形状的读者。文章选择 ServiceManager.getService("activity") 作为服务发现入口,再选择一个同步 Binder 事务走通 Java、JNI、libbinder、内核驱动和服务端分发;不展开 oneway 队列、死亡通知、完整 Parcel 类型系统、线程池上限和 SELinux 策略,它们分别由后续文章负责。
读完后,读者应能:
- 区分本地 Binder、远程 BinderProxy、native BpBinder 和内核 binder_ref;
- 从 BinderProxy.transact() 追到 BINDER_WRITE_READ 和 BC_TRANSACTION;
- 从 BR_TRANSACTION 找回服务端 BBinder/Java Binder.onTransact(),再解释同步 reply 的返回路径;
- 根据 DEAD_OBJECT、BR_FAILED_REPLY、服务未找到和服务线程未注册等现象选择源码入口。
1. 问题边界
Binder 文章常把“拿服务”和“调用服务”混为一条大图。它们在源码里是两个相邻但不同的入口:
- ServiceManager.getService(name) 先通过 context manager 查询名字到 Binder 引用的映射。
- 得到 IBinder 后,具体 AIDL 方法才调用 transact(code, data, reply, flags)。
服务发现的 owner 是 ServiceManager;一次业务事务的 owner 是客户端 Binder 对象、驱动事务和服务端 Binder 对象。
| 位置 | 对象 | 主要状态 | 不能替代 |
|---|---|---|---|
| 客户端 Java | BinderProxy | native mObject、handle、死亡状态 | 服务端 Java Binder |
| 客户端 native | BpBinder | handle、mAlive、引用与事务入口 | 内核 binder_ref |
| 服务端 native/Java | BBinder/JavaBBinderExt | 本地对象、cookie、onTransact | 客户端代理 |
handle 是客户端进程中的描述符,不能直接当成服务端对象地址;服务端的 binder_node 才保存本地对象指针和 cookie。内核负责在两者之间建立引用关系。
2. 服务发现
源码文件:frameworks/base/core/java/android/os/ServiceManager.java
相关函数:getIServiceManager()、getService()、rawGetService()
private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
}
sServiceManager = ServiceManagerNative
.asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
return sServiceManager;
}
public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name);
if (service != null) {
return service;
} else {
return Binder.allowBlocking(rawGetService(name));
}
} catch (RemoteException e) {
Log.e(TAG, "error in getService", e);
}
return null;
}
private static IBinder rawGetService(String name) throws RemoteException {
return getIServiceManager().getService2(name).getServiceWithMetadata().service;
}首次查询先获得 context object,再把它解释为 IServiceManager 接口;目标服务查询是另一次 Binder 调用。sCache 命中时不会再次跨进程查询,这也是排查“第一次慢、后续快”时必须先看缓存分支的原因。
源码文件:frameworks/base/core/java/com/android/internal/os/BinderInternal.java
public static final native IBinder getContextObject();源码文件:frameworks/base/core/jni/android_util_Binder.cpp
相关函数:android_os_BinderInternal_getContextObject()
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
return javaObjectForIBinder(env, b);
}源码文件:frameworks/native/libs/binder/ProcessState.cpp
相关函数:getContextObject()、getStrongProxyForHandle()
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
sp<IBinder> context = getStrongProxyForHandle(0);
if (context) {
internal::Stability::markCompilationUnit(context.get());
} else {
ALOGW("Not able to get context object on %s.", mDriverName.c_str());
}
return context;
}handle 0 是 context manager 的特殊引用,不是所有服务的 handle。javaObjectForIBinder() 决定返回 Java BinderProxy 还是已有本地 Java 对象,后续 Java 接口调用才会落到正确的代理类型。
3. 代理形成
源码文件:frameworks/base/core/java/android/os/BinderProxy.java
相关函数:transact()、transactNative()
public boolean transact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");
boolean warnOnBlocking = mWarnOnBlocking;
if (warnOnBlocking && ((flags & FLAG_ONEWAY) == 0)
&& Binder.sWarnOnBlockingOnCurrentThread.get()) {
mWarnOnBlocking = false;
warnOnBlocking = false;
}
final boolean result = transactNative(code, data, reply, flags);
return result;
}
public native boolean transactNative(int code, Parcel data, Parcel reply, int flags);Java 层先检查 Parcel 大小,处理阻塞告警、事务监听器、AppOps 和 trace,再进入 JNI。上面的 片段只保留与调用方向有关的分支。transact() 返回 true 不等于业务方法返回 true;同步 调用的返回数据仍由 reply Parcel 承载。
源码文件:frameworks/base/core/jni/android_util_Binder.cpp
相关函数:android_os_BinderProxy_transact()
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
jint code, jobject dataObj, jobject replyObj, jint flags)
{
Parcel* data = parcelForJavaObject(env, dataObj);
if (data == NULL) return JNI_FALSE;
Parcel* reply = parcelForJavaObject(env, replyObj);
if (reply == NULL && replyObj != NULL) return JNI_FALSE;
IBinder* target = getBPNativeData(env, obj)->mObject.get();
if (target == NULL) {
jniThrowException(env, "java/lang/IllegalStateException",
"Binder has been finalized!");
return JNI_FALSE;
}
status_t err = target->transact(code, *data, reply, flags);
if (err == NO_ERROR) return JNI_TRUE;
signalExceptionForError(env, err);
return JNI_FALSE;
}这里的 target 是 native BpBinder,不是 Java BinderProxy 自身。JNI 只负责把 Java Parcel 和对象字段转换成 native 对象,并将 status_t 映射成 Java 层结果或异常。
源码文件:frameworks/native/libs/binder/BpBinder.cpp
相关函数:BpBinder::transact()
status_t BpBinder::transact(uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags) {
if (mAlive) {
status_t status;
if (isRpcBinder()) {
status = rpcSession()->transact(
sp<IBinder>::fromExisting(this), code, data, reply, flags);
} else {
status = IPCThreadState::self()->transact(
binderHandle(), code, data, reply, flags);
}
if (status == DEAD_OBJECT) mAlive = 0;
return status;
}
return DEAD_OBJECT;
}Android 17 的 BpBinder 同时保留 kernel Binder 和 RPC 分支;本文只继续 kernel Binder 分支。mAlive 是代理侧的快速状态,不是内核引用的全部生命周期。
4. 事务封装
源码文件:frameworks/native/libs/binder/IPCThreadState.cpp
相关函数:transact()、writeTransactionData()
status_t IPCThreadState::transact(int32_t handle, uint32_t code,
const Parcel& data, Parcel* reply, uint32_t flags) {
flags |= TF_ACCEPT_FDS;
status_t err = writeTransactionData(
BC_TRANSACTION, flags, handle, code, data, nullptr);
if (err != NO_ERROR) {
if (reply) reply->setError(err);
return (mLastError = err);
}
if ((flags & TF_ONE_WAY) == 0) {
if (reply) {
err = waitForResponse(reply);
} else {
Parcel fakeReply;
err = waitForResponse(&fakeReply);
}
} else {
err = waitForResponse(nullptr, nullptr);
}
return err;
}同步和 oneway 的分叉在这里出现:同步调用发送 BC_TRANSACTION 后等待 reply;oneway 不需要业务 reply,但仍会通过驱动处理完成或失败命令。
源码文件:frameworks/native/libs/binder/IPCThreadState.cpp
相关函数:writeTransactionData()
status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
int32_t handle, uint32_t code, const Parcel& data,
status_t* statusBuffer) {
binder_transaction_data tr;
tr.target.ptr = 0;
tr.target.handle = handle;
tr.code = code;
tr.flags = binderFlags;
tr.cookie = 0;
tr.sender_pid = 0;
tr.sender_euid = 0;
tr.data_size = data.ipcDataSize();
tr.data.ptr.buffer = data.ipcData();
tr.offsets_size = data.ipcObjectsCount() * sizeof(binder_size_t);
tr.data.ptr.offsets = data.ipcObjects();
mOut.writeInt32(cmd);
mOut.write(&tr, sizeof(tr));
return NO_ERROR;
}mOut 是当前 Binder 线程准备交给驱动的命令缓冲区;binder_transaction_data 携带目标 handle、接口 code、flags、数据地址和对象偏移数组。
源码文件:kernel/common/include/uapi/linux/android/binder.h
struct binder_write_read {
binder_size_t write_size;
binder_size_t write_consumed;
binder_uintptr_t write_buffer;
binder_size_t read_size;
binder_size_t read_consumed;
binder_uintptr_t read_buffer;
};
struct binder_transaction_data {
union { binder_uintptr_t ptr; binder_uint32_t handle; } target;
binder_uintptr_t cookie;
binder_uint32_t code;
binder_uint32_t flags;
pid_t sender_pid;
uid_t sender_euid;
binder_size_t data_size;
binder_size_t offsets_size;
union {
struct { binder_uintptr_t buffer; binder_uintptr_t offsets; } ptr;
uint8_t buf[8];
} data;
};5. 驱动入队
源码文件:kernel/common/drivers/android/binder.c
相关函数:binder_ioctl()、binder_ioctl_write_read()
static long binder_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg) {
int ret;
struct binder_proc *proc = filp->private_data;
struct binder_thread *thread;
thread = binder_get_thread(proc);
if (thread == NULL) {
ret = -ENOMEM;
goto err;
}
switch (cmd) {
case BINDER_WRITE_READ:
ret = binder_ioctl_write_read(filp, arg, thread);
if (ret)
goto err;
break;
}
err:
return ret;
}BINDER_WRITE_READ 同时承载用户态写命令和读回命令。驱动先为调用进程找到 binder_proc,再为当前线程找到 binder_thread;同一个文件描述符不等于一个 Binder 线程。
源码文件:kernel/common/drivers/android/binder.c
相关函数:binder_thread_write()、binder_transaction()
case BC_TRANSACTION:
case BC_REPLY: {
struct binder_transaction_data tr;
if (copy_from_user(&tr, ptr, sizeof(tr)))
return -EFAULT;
ptr += sizeof(tr);
binder_transaction(proc, thread, &tr, cmd == BC_REPLY, 0);
break;
}驱动把 BC_TRANSACTION 和 BC_REPLY 都送入 binder_transaction(),区别由 reply 参数和当前线程的事务栈决定。一次同步调用在客户端先创建事务;服务端回复时,驱动通过服务线程的 transaction_stack 找回等待中的父事务。
源码文件:kernel/common/drivers/android/binder.c
相关函数:binder_transaction()
static void binder_transaction(struct binder_proc *proc,
struct binder_thread *thread, struct binder_transaction_data *tr,
int reply, binder_size_t extra_buffers_size) {
struct binder_transaction *t;
struct binder_proc *target_proc = NULL;
struct binder_thread *target_thread = NULL;
struct binder_node *target_node = NULL;
t = kzalloc(sizeof(*t), GFP_KERNEL);
if (!t) {
return;
}
// 根据 target.handle / target.ptr 找目标进程、线程和 node
// 为目标进程分配 binder_buffer 并转换对象
}对于远程代理发出的调用,tr.target.handle 在客户端引用树中解析为目标 binder_node;目标进程、目标线程和事务 buffer 都由驱动决定。用户态 BpBinder 不直接知道服务线程的 TID,也不能绕过驱动把 C++ 指针交给另一进程。
源码文件:kernel/common/drivers/android/binder.c
t->buffer = binder_alloc_new_buf(&target_proc->alloc,
tr->data_size, tr->offsets_size, extra_buffers_size,
!reply && (t->flags & TF_ONE_WAY));
if (IS_ERR(t->buffer)) {
return_error = PTR_ERR(t->buffer) == -ESRCH
? BR_DEAD_REPLY : BR_FAILED_REPLY;
goto err_binder_alloc_buf_failed;
}
t->buffer->debug_id = t->debug_id;
t->buffer->transaction = t;
t->buffer->target_node = target_node;buffer 属于目标进程的 binder_alloc,不是发送方 Parcel 的永久存储。内存不足、目标地址空间已清除或对象偏移非法都会在这里改变事务结果。
6. 服务线程
源码文件:kernel/common/drivers/android/binder.c
相关函数:binder_thread_read()、binder_wait_for_work()
static int binder_thread_read(struct binder_proc *proc,
struct binder_thread *thread, binder_uintptr_t binder_buffer,
size_t size, binder_size_t *consumed, int non_block) {
int wait_for_proc_work;
binder_inner_proc_lock(proc);
wait_for_proc_work = binder_available_for_proc_work_ilocked(thread);
binder_inner_proc_unlock(proc);
thread->looper |= BINDER_LOOPER_STATE_WAITING;
if (non_block) {
if (!binder_has_work(thread, wait_for_proc_work)) {
return -EAGAIN;
}
} else {
binder_wait_for_work(thread, wait_for_proc_work);
}
// 从 thread->todo 或 proc->todo 生成 BR_TRANSACTION/BR_REPLY
}服务线程主动通过 BINDER_WRITE_READ 的 read 部分等待,驱动将可执行事务编码成 BR_TRANSACTION 写入该线程的用户缓冲区;用户态再读取并调用 IPCThreadState::executeCommand()。
源码文件:kernel/common/drivers/android/binder.c
if (t->buffer->target_node) {
struct binder_node *target_node = t->buffer->target_node;
trd->target.ptr = target_node->ptr;
trd->cookie = target_node->cookie;
cmd = BR_TRANSACTION;
} else {
trd->target.ptr = 0;
trd->cookie = 0;
cmd = BR_REPLY;
}
trd->code = t->code;
trd->flags = t->flags;
trd->data_size = t->buffer->data_size;
trd->offsets_size = t->buffer->offsets_size;target.ptr/cookie 让服务端 native 层找回本地对象;没有 target_node 时,驱动把它编码成 BR_REPLY。同步事务会压入服务线程的 transaction_stack,oneway 或 reply 则有不同的释放时机。
源码文件:frameworks/native/libs/binder/IPCThreadState.cpp
相关函数:executeCommand()
case BR_TRANSACTION_SEC_CTX:
case BR_TRANSACTION: {
binder_transaction_data_secctx tr_secctx;
binder_transaction_data& tr = tr_secctx.transaction_data;
result = mIn.read(&tr, sizeof(tr));
Parcel buffer;
buffer.ipcSetDataReference(
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size / sizeof(binder_size_t), freeBuffer);
if (tr.target.ptr) {
BBinder* binder = reinterpret_cast<BBinder*>(tr.cookie);
error = doTransactBinder(binder, tr.code, buffer, &reply, tr.flags);
} else {
error = doTransactBinder(the_context_object.get(),
tr.code, buffer, &reply, tr.flags);
}
}服务端分发使用 cookie 找到 BBinder,而不是重新通过 handle 查询。
7. Java落点
源码文件:frameworks/base/core/jni/android_util_Binder.cpp
相关类型:JavaBBinderExt、JavaBBinderHolder
class JavaBBinderExt : public android::internal::JavaBBinderBase {
public:
JavaBBinderExt(JNIEnv* env, jobject object)
: JavaBBinderBase(env, object) {}
status_t onTransact(uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags = 0) override {
JNIEnv* env = javavm_to_jnienv(mVM);
IPCThreadState* thread_state = IPCThreadState::self();
const int32_t strict_policy_before = thread_state->getStrictModePolicy();
jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);
if (env->ExceptionCheck()) {
res = JNI_FALSE;
}
if (thread_state->getStrictModePolicy() != strict_policy_before) {
set_dalvik_blockguard_policy(env, strict_policy_before);
}
return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION;
}
};Java Binder 对象通过 JavaBBinderExt 变成 native BBinder;驱动保存的是 native node 的 ptr/cookie,不是 Java 对象地址。
源码文件:frameworks/base/core/java/android/os/Binder.java
相关函数:execTransact()、execTransactInternal()、onTransact()
private boolean execTransact(int code, long dataObj, long replyObj, int flags) {
Parcel data = Parcel.obtain(dataObj);
Parcel reply = Parcel.obtain(replyObj);
try {
final int callingUid = Binder.getCallingUid();
return execTransactInternal(code, data, reply, flags, callingUid);
} finally {
reply.recycle();
data.recycle();
}
}
private boolean execTransactInternal(int code, Parcel data, Parcel reply,
int flags, int callingUid) {
return onTransact(code, data, reply, flags);
}生成的 AIDL Stub 通常覆写 onTransact(),先校验接口 token,再读 Parcel、调用实现、写入 reply。Binder 基类负责把 native buffer 变成 Java Parcel 并在 finally 中回收。
8. 回复收束
源码文件:frameworks/native/libs/binder/IPCThreadState.cpp
相关函数:sendReply()、waitForResponse()
status_t IPCThreadState::sendReply(const Parcel& reply, uint32_t flags) {
status_t statusBuffer;
status_t err = writeTransactionData(
BC_REPLY, flags, -1, 0, reply, &statusBuffer);
if (err < NO_ERROR) return err;
return waitForResponse(nullptr, nullptr);
}服务线程把 reply 写成 BC_REPLY,驱动依据当前事务栈找到客户端等待的线程,并为客户端生成 BR_REPLY。
源码文件:frameworks/native/libs/binder/IPCThreadState.cpp
status_t IPCThreadState::waitForResponse(Parcel* reply,
status_t* acquireResult) {
while (true) {
status_t err = talkWithDriver();
if (err < NO_ERROR) return err;
if (mIn.dataAvail() == 0) continue;
uint32_t cmd = static_cast<uint32_t>(mIn.readInt32());
switch (cmd) {
case BR_TRANSACTION_COMPLETE:
if (!reply && !acquireResult) return NO_ERROR;
break;
case BR_REPLY:
// 读取 binder_transaction_data,填充 reply
goto finish;
case BR_DEAD_REPLY:
return DEAD_OBJECT;
}
}
finish:
return NO_ERROR;
}BR_TRANSACTION_COMPLETE 只说明驱动接受了发送命令;同步业务结果要等 BR_REPLY。
源码文件:frameworks/native/libs/binder/IPCThreadState.cpp
相关函数:talkWithDriver()
binder_write_read bwr;
const bool needRead = mIn.dataPosition() >= mIn.dataSize();
const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;
bwr.write_size = outAvail;
bwr.write_buffer = reinterpret_cast<uintptr_t>(mOut.data());
bwr.read_size = doReceive && needRead ? mIn.dataCapacity() : 0;
bwr.read_buffer = doReceive && needRead
? reinterpret_cast<uintptr_t>(mIn.data()) : 0;
status_t err = ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr);Binder 的“写请求、阻塞等 reply”不是两个必然分离的系统调用,而是通过一个 binder_write_read 结构把待写命令和待读数据同时交给驱动。
9. 失败变化
服务不存在
ServiceManager.getService() 缓存未命中时调用 rawGetService();服务名不存在可能返回 null,调用方随后可能抛出自己的 ServiceNotFoundException。这条路径尚未进入 BinderProxy.transact(),不应从 transaction log 反查。
代理已死亡
BpBinder::transact() 在 mAlive == false 时直接返回 DEAD_OBJECT;即使此前 handle 曾经对应一个服务,代理也不会因服务重启自动重新绑定。Java 层通常把它映射成 RemoteException 或其子类,恢复策略属于 ServiceManager/调用方,而不是 Binder 驱动自动完成。
buffer失败
驱动在 binder_alloc_new_buf() 失败时区分目标已死亡、空间不足和内存分配失败,分别生成 BR_DEAD_REPLY 或 BR_FAILED_REPLY 等结果。此时服务端不会执行 onTransact();如果只看客户端“方法没有返回”,必须把失败位置前移到驱动 buffer 分配和对象转换。
服务线程退出
服务线程需要通过 joinThreadPool() 或等价路径持续读驱动;如果没有线程读取,事务可以已经进入目标进程 todo,但不会进入 executeCommand()。这与服务对象不存在不同:前者可能有 node 和进程,但缺少活跃消费者。
| 分支 | 请求方等待 | 服务端 reply | 适合的定位问题 |
|---|---|---|---|
| 同步 | waitForResponse(reply) | BC_REPLY/BR_REPLY | 方法结果、服务阻塞、reply 失败 |
| oneway | 不等待业务 reply | 不发送业务 reply | 异步排队、服务线程消费、冻结状态 |
10. 测试输入
源码文件:frameworks/native/libs/binder/tests/binderLibTest.cpp
相关测试:BinderLibTest.NopTransaction、BinderLibTest.NopTransactionOneway、BinderLibTest.AddServer
TEST_F(BinderLibTest, NopTransaction) {
Parcel data, reply;
EXPECT_THAT(m_server->transact(
BINDER_LIB_TEST_NOP_TRANSACTION, data, &reply),
StatusEq(NO_ERROR));
}
TEST_F(BinderLibTest, NopTransactionOneway) {
Parcel data, reply;
EXPECT_THAT(m_server->transact(
BINDER_LIB_TEST_NOP_TRANSACTION, data, &reply, TF_ONE_WAY),
StatusEq(NO_ERROR));
}测试先启动独立 server,再获取 Binder 引用;两条测试都构造 data/reply Parcel,分别用普通 flags 和 TF_ONE_WAY 调用并断言 NO_ERROR。它能说明两种事务入口的基本往返,不能证明 具体服务的权限、延迟、线程数或所有 Parcel 对象转换。
源码文件:frameworks/base/core/tests/coretests/src/android/os/BinderProxyTest.java
相关测试:BinderProxyTest.testNoListener、BinderProxyTest.testListener、 BinderProxyTest.testSessionPropagated
这些测试通过 ActivityManager 的真实 Binder 调用检查代理监听器的开始/结束计数和 session 传递。它们能说明 Java 代理的观测边界,不能替代 native 驱动往返测试。
11. 阅读边界
本文主线证明的是:
- context manager handle 0 如何变成 Java 服务管理代理;
- Java BinderProxy 如何经 JNI 找到 native BpBinder;
- BpBinder → IPCThreadState → BINDER_WRITE_READ → binder_transaction 的同步请求路径;
- 驱动如何把 BR_TRANSACTION 交给服务线程,再由 BBinder/Java Binder 执行;
- BC_REPLY → BR_REPLY 如何回到原调用线程,以及失败在哪些边界提前终止。
以下问题留给后续文章:
- binder_open、binder_mmap 和 allocator 页管理;
- binder_node、binder_ref 和对象引用计数;
- 完整 Parcel 对象转换和 FD 传递;
- ServiceManager 注册、死亡通知和 lazy service;
- 线程池、嵌套调用和事务耗尽。
作为前置复习,可以回看 消息机制总览 理解服务线程收到事务后如何把工作转交给 Handler;下一篇 Binder 文章将从驱动打开和 binder_proc 创建继续向下展开。
12. 复查任务
选一个真实系统服务,例如 activity,完成下面的只读任务:
- 从 ServiceManager.getService("activity") 标出缓存分支、context object 和 getService2()。
- 在 BinderProxy.transact() 标出 Java → JNI → BpBinder 的三个对象转换。
- 在 IPCThreadState::writeTransactionData() 记录 handle、code、flags、data size 和 offsets。
- 在驱动 binder_transaction() 找到目标进程、目标 node 和 buffer 分配。
- 在 binder_thread_read() 和 executeCommand(BR_TRANSACTION) 找到服务线程的消费者。
- 在 waitForResponse() 区分 BR_TRANSACTION_COMPLETE、BR_REPLY 和 BR_DEAD_REPLY。
如果这条路径中任何一步只能说“Binder 把数据传过去了”,就回到该步骤的 owner 和状态字段:Binder 的难点不在组件数量,而在同一个事务状态先后由 Java 对象、native 线程、内核 proc/thread、目标 buffer 和服务对象分别持有。
13. 地图使用法
本文是导航文章,不承担每个子系统的完整机制证明。阅读时先用 ServiceManager.getService 确认名称到 handle 的边界,再用 BpBinder::transact 进入一次具体事务;当问题转向 allocator、死亡通知、线程池或 SELinux 时,应停止沿本图扩展,转入对应专题。这样可以避免把一张跨层地图误当成所有实现细节的替代品。
源码块中的 handle、code、flags 和 data size 是跨层追踪的四个锚点:调用方写入它们,驱动据此选择 node/thread/buffer,服务端 Stub 消费它们,reply 再沿 transaction stack 返回。读者可在每层记录这四个值,验证自己没有在对象层级之间跳步。
