匿名binder就是没有向servicemanager提交注册的binder。
对于已经建立好Binder通信的Client和server,server可以将一个Binder的引用传递给client,client可以通过这个引用来访问server。
那么这种匿名的访问是怎么建立起来的?在server被唤醒后为什么可以通过target-ptr找到bbinder呢?
答案就在第一次返回这个Binder的引用的时候,binder驱动保存了这个Binder实体的各种数据,创建了节点。
以surfaceflinger调用createConnection返回IsurfaceComposerClient为例:
-
status_t BnSurfaceComposer::onTransact(
-
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-
{
-
switch(code) {
-
case CREATE_CONNECTION: {
-
CHECK_INTERFACE(ISurfaceComposer, data, reply);
-
sp b = createConnection()->asBinder();
-
reply->writeStrongBinder(b);
-
-
-
}
实际就是往reply中存入了一个BBinder实体。
我们进一步看下,parcel.cpp:
-
status_t Parcel::writeStrongBinder(const sp& val)
-
{
-
return flatten_binder(ProcessState::self(), val, this);
-
}
也就是:
-
status_t flatten_binder(const sp& proc,
-
const sp& binder, Parcel* out)
-
{
-
flat_binder_object obj;
-
-
obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
-
if (binder != NULL) {
-
IBinder *local = binder->localBinder();
-
if (!local) {
-
BpBinder *proxy = binder->remoteBinder();
-
if (proxy == NULL) {
-
LOGE("null proxy");
-
}
-
const int32_t handle = proxy ? proxy->handle() : 0;
-
obj.type = BINDER_TYPE_HANDLE;
-
obj.handle = handle;
-
obj.cookie = NULL;
-
} else {
-
obj.type = BINDER_TYPE_BINDER;
-
obj.binder = local->getWeakRefs();
-
obj.cookie = local;
-
}
-
} else {
-
obj.type = BINDER_TYPE_BINDER;
-
obj.binder = NULL;
-
obj.cookie = NULL;
-
}
-
-
return finish_flatten_binder(binder, obj, out);
-
}
接下来,回到IPCThreadState::executeCommand中,会sendreply,将刚刚返回的数据传回给binder驱动。
通过talkwithdriver----ioctrl---进入内核空间---也就是binder_ioctl中。
流程大略是binder_ioctl-----binder_thread_write------binder_transaction
在binder_transaction中会对传入的binder_transaction_data进行解析,打包成binder_transaction
-
static void binder_transaction(struct binder_proc *proc,
-
struct binder_thread *thread,
-
struct binder_transaction_data *tr, int reply)
-
{
-
-
-
-
fp = (struct flat_binder_object *)(t->buffer->data + *offp);
-
switch (fp->type) {
-
case BINDER_TYPE_BINDER:
-
case BINDER_TYPE_WEAK_BINDER: {
-
struct binder_ref *ref;
-
struct binder_node *node = binder_get_node(proc, fp->binder);
-
if (node == NULL) {
-
node = binder_new_node(proc, fp->binder, fp->cookie);
-
if (node == NULL) {
-
return_error = BR_FAILED_REPLY;
-
goto err_binder_new_node_failed;
-
}
-
node->min_priority = fp->flags & FLAT_BINDER_FLAG_PRIORITY_MASK;
-
node->accept_fds = !!(fp->flags & FLAT_BINDER_FLAG_ACCEPTS_FDS);
-
}
-
if (fp->cookie != node->cookie) {
-
binder_user_error("binder: %d:%d sending u%p "
-
"node %d, cookie mismatch %p != %p\n",
-
proc->pid, thread->pid,
-
fp->binder, node->debug_id,
-
fp->cookie, node->cookie);
-
goto err_binder_get_ref_for_node_failed;
-
}
-
ref = binder_get_ref_for_node(target_proc, node);
-
if (ref == NULL) {
-
return_error = BR_FAILED_REPLY;
-
goto err_binder_get_ref_for_node_failed;
-
}
-
if (fp->type == BINDER_TYPE_BINDER)
-
fp->type = BINDER_TYPE_HANDLE;
-
else
-
fp->type = BINDER_TYPE_WEAK_HANDLE;
-
fp->handle = ref->desc;
-
binder_inc_ref(ref, fp->type == BINDER_TYPE_HANDLE,
-
&thread->todo);
-
-
binder_debug(BINDER_DEBUG_TRANSACTION,
-
" node %d u%p -> ref %d desc %d\n",
-
node->debug_id, node->ptr, ref->debug_id,
-
ref->desc);
-
} break;
-
-
-
-
}
在上述函数中,如果是第一次调用这个,binder驱动做的事里,最关键的是,在目标创建了这个BBinder的实体节点。
总的来说,在建立好Binder通信的连接(基于实名注册的Binder)后,server可以传递Binder对象的引用给client,大致的过程是:
server将Binder对象写入parcel,接着通过ioctrl和binder驱动通信,bidner驱动会对传入的对象进行检查,如果发
现传入的type是binder,则会在当前进程(server对应的proc)查找是否有这个节点,如果没有就用传入的Binder实体在user空间
指针和cookie(通常是BBinder本身)构造一个新的node,接着得到Binder实体的引用,存放在transaction_data中等待
client去获取。
client拿到Binder的引用后,就可以通过这个BpBinder和server的BBinder进行通信了,和实名注册的Binder是一样的,不再赘述。