以add hidl service为例记录下hidl和binder driver的交互。
BpHwServiceManager::_hidl_add()
在BpHwServiceManager::_hidl_add()里有call Parcel的writeStrongBinder(),这个函数会call到flatten_binder(),这时是走这个函数的标红的else case,注意下这个else里的obj.binder的赋值,这里会赋值为一个RefBase.cpp里定义的weakref_impl *mRefs指针。
status_t flatten_binder(const sp<ProcessState>& /*proc*/, const sp<IBinder>& binder, Parcel* out) { flat_binder_object obj; if (binder != NULL) { BHwBinder *local = binder->localBinder(); if (!local) { BpHwBinder *proxy = binder->remoteBinder(); if (proxy == NULL) { ALOGE("null proxy"); } const int32_t handle = proxy ? proxy->handle() : 0; obj.hdr.type = BINDER_TYPE_HANDLE; obj.flags = FLAT_BINDER_FLAG_ACCEPTS_FDS; obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */ obj.handle = handle; obj.cookie = 0; } else { // Get policy and convert it int policy = local->getMinSchedulingPolicy(); int priority = local->getMinSchedulingPriority(); obj.flags = priority & FLAT_BINDER_FLAG_PRIORITY_MASK; obj.flags |= FLAT_BINDER_FLAG_ACCEPTS_FDS | FLAT_BINDER_FLAG_INHERIT_RT; obj.flags |= (policy & 3) << FLAT_BINDER_FLAG_SCHEDPOLICY_SHIFT; obj.hdr.type = BINDER_TYPE_BINDER; obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs()); obj.cookie = reinterpret_cast<uintptr_t>(local); } } else { obj.hdr.type = BINDER_TYPE_BINDER; obj.binder = 0; obj.cookie = 0; } return finish_flatten_binder(binder, obj, out); }
在BpHwServiceManager::_hidl_add()中,然后有call transact(),即是call的BpHwBinder::tranact(),注意这里transact()的mHandle参数,这个mHandle是hwservicemanager的BpHwBinder对象里的mHandle,对于hwservicemanager,mHandle是0.
然后会call到IPCTthreadState::transact(),在这个函数中,会将transaction_data.target.handle复制为这个mHandle,这里的target.handle表示发送给的target的handle,即表示发送给hwservicemanager。
binder driver
接下来看下binder driver的处理。
drivers/android/binder.c(linux-4.9)
这时会call到binder_transaction(),因为target.handle为0,所以会走else case。
static void binder_transaction(struct binder_proc *proc,
struct binder_thread *thread,
struct binder_transaction_data *tr, int reply)
if (tr->target.handle) {
struct binder_ref *ref;
ref = binder_get_ref(proc, tr->target.handle);
if (ref == NULL) {
binder_user_error("%d:%d got transaction to invalid handle
",
proc->pid, thread->pid);
return_error = BR_FAILED_REPLY;
goto err_invalid_target_handle;
}
target_node = ref->node;
} else {
target_node = binder_context_mgr_node;
if (target_node == NULL) {
return_error = BR_DEAD_REPLY;
goto err_no_context_mgr_node;
}
}
继续binder_transaction(),在copy_from_user后,会走到如下的地方(hdr->type为BINDER_TYPE_BINDER),看下binder_translate_binder(),这个函数里的fp为flat_binder_object,fp->binder即是在Parcel.cpp里flatten_binder()函数里设置的weakref_impl指针。根据fp->binder去get node,这时是get不到的,所以call binder_new_node去创建一个node,比如在register omx hidl service时,这里应该就是为omx去创建node。后面会call binder_inc_ref_for_node(),这个函数会call到binder_get_ref_for_node_olocked()
switch (hdr->type) { case BINDER_TYPE_BINDER: case BINDER_TYPE_WEAK_BINDER: { struct flat_binder_object *fp; fp = to_flat_binder_object(hdr); ret = binder_translate_binder(fp, t, thread);
static int binder_translate_binder(struct flat_binder_object *fp, struct binder_transaction *t, struct binder_thread *thread) { struct binder_node *node; struct binder_proc *proc = thread->proc; struct binder_proc *target_proc = t->to_proc; struct binder_ref_data rdata; int ret = 0; node = binder_get_node(proc, fp->binder); if (!node) { node = binder_new_node(proc, fp); if (!node) return -ENOMEM; } if (fp->cookie != node->cookie) { binder_user_error("%d:%d sending u%016llx node %d, cookie mismatch %016llx != %016llx ", proc->pid, thread->pid, (u64)fp->binder, node->debug_id, (u64)fp->cookie, (u64)node->cookie); ret = -EINVAL; goto done; } if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) { ret = -EPERM; goto done; } ret = binder_inc_ref_for_node(target_proc, node, fp->hdr.type == BINDER_TYPE_BINDER, &thread->todo, &rdata); if (ret) goto done; if (fp->hdr.type == BINDER_TYPE_BINDER) fp->hdr.type = BINDER_TYPE_HANDLE; else fp->hdr.type = BINDER_TYPE_WEAK_HANDLE; fp->binder = 0; fp->handle = rdata.desc; fp->cookie = 0; trace_binder_transaction_node_to_ref(t, node, &rdata); binder_debug(BINDER_DEBUG_TRANSACTION, " node %d u%016llx -> ref %d desc %d ", node->debug_id, (u64)node->ptr, rdata.debug_id, rdata.desc); done: binder_put_node(node); return ret; }
注意下binder_get_ref_for_node_olocked里的如下标红的语句,这个语句确定的desc很关键,它将成为omx hidl service的handle。
static struct binder_ref *binder_get_ref_for_node_olocked( struct binder_proc *proc, struct binder_node *node, struct binder_ref *new_ref) { for (n = rb_first(&proc->refs_by_desc); n != NULL; n = rb_next(n)) { ref = rb_entry(n, struct binder_ref, rb_node_desc); if (ref->data.desc > new_ref->data.desc) break; new_ref->data.desc = ref->data.desc + 1; }
call binder_inc_ref_for_node是为了创建一个binder_ref,在这个函数之后,将fp->handle复制为这个new_ref的data.desc。
注意在binder_translate_binder()函数中,有判断hdr->type,看它是否为BINDER_TYPE_BINDER,若是,则修改为BINDER_TYPE_HANDLE。
继续binder_transaction(),在call完binder_translate_binder()后,会call binder_proc_transaction(t, target_proc, target_thread)将上面设置好的binder_transaction t发送给hwservicemanager进程。
后面就会call到 hwservicemanager的BnHwServiceManger::_on_transact(),继而call到BnHwServiceManager::_hidl_add(),在这个函数中,call _hidl_data->readNullableStrongBinder(),这个函数会call到unflatten_binder(),这时因为在binder driver中,有将hdr->type从BINDER_GYPE_BINDER改为BINDER_TYPE_HANDLE,所以这时会走BINDER_TYPE_HANDLE case。所以会call getStrongProxyForHandle(flat->handle),这里的flat->handle就是在binder driver里为hidl service进程确定的desc。所以在getStrongProxyForHandle()里,会根据这个handle创建一个BpHwBinder对象(BpHwBinder里的mHandle会被赋值为这个handle),这里创建的BpHwBinder即为在registerAsService时为注册的hidl service创建的。
status_t unflatten_binder(const sp<ProcessState>& proc, const Parcel& in, sp<IBinder>* out) { const flat_binder_object* flat = in.readObject<flat_binder_object>(); if (flat) { switch (flat->hdr.type) { case BINDER_TYPE_BINDER: *out = reinterpret_cast<IBinder*>(flat->cookie); return finish_unflatten_binder(NULL, *flat, in); case BINDER_TYPE_HANDLE: *out = proc->getStrongProxyForHandle(flat->handle); return finish_unflatten_binder( static_cast<BpHwBinder*>(out->get()), *flat, in); } } return BAD_TYPE; }
继续BnHwServiceManager::_hidl_add(),通过readStrongProxyForHandle()得到一个BpHwBinder对象后,接下来会创建一个BpHwBase对象,而这个BpHwBinder对象会保存在这个BpHwBase对象里。然后将这个BpHwBase对象注册进去。
后面在getService时,会先拿到这个BpHwBase对象,而这个BpHwBase对象中有目标hidl service的BpHwBinder对象。以sp<IOmx> omx = IOmx::getService(); omx->allocateNode();为例,在IOmx::getService()后拿到一个BpHwOmx,在BpHwOmx::_hidl_allocateNode()函数中,通过::android::hardware::IInterface::asBinder(_hidl_this)就会拿到Omx hidl service的BpHwBinder对象,然后通过这个BpHwBinder对象的transact()函数向omx server发起allocate node的请求。而在call BpHwBinder::transact()时,会将mHandle作为参数,表示transact的target是这个handle表示的hidl server(这个handle会传给binder driver),这里的话表示target是omx server。