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

     
  • 相关阅读:
    一个C++程序员学习C#语言
    C#入门教程笔记
    完全卸载mysql 停止服务、卸载相关程序、删除注册表
    C++结构简介
    babun,windows shell
    无限极设计以及随意移动节点(树结构)
    springboot 配置访问外部静态资源详解
    mysql8+keepalived 双主高可用搭建
    mysql 双主复制搭建
    mysql 主备搭建
  • 原文地址:https://www.cnblogs.com/aspirs/p/11585592.html
Copyright © 2020-2023  润新知