以add hidl service为例记录下hidl和binder driver的交互

以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。

 
原文地址:https://www.cnblogs.com/aspirs/p/11585592.html