美文网首页
HIDL 与 binder 调用流程分析

HIDL 与 binder 调用流程分析

作者: Little熊猫 | 来源:发表于2018-05-31 08:18 被阅读0次

    1 hwservice启动过程与binder驱动的关系

    int main() {
        configureRpcThreadpool(1, true /* callerWillJoin */);
    
        ServiceManager *manager = new ServiceManager();
    
        if (!manager->add(serviceName, manager)) {
            ALOGE("Failed to register hwservicemanager with itself.");
        }
    
        TokenManager *tokenManager = new TokenManager();
    
        if (!manager->add(serviceName, tokenManager)) {
            ALOGE("Failed to register ITokenManager with hwservicemanager.");
        }
    
        // Tell IPCThreadState we're the service manager
        sp<BnHwServiceManager> service = new BnHwServiceManager(manager);
        IPCThreadState::self()->setTheContextObject(service);
        // Then tell the kernel
        ProcessState::self()->becomeContextManager(nullptr, nullptr);
    
        int rc = property_set("hwservicemanager.ready", "true");
        if (rc) {
            ALOGE("Failed to set \"hwservicemanager.ready\" (error %d). "\
                  "HAL services will not start!\n", rc);
        }
    
        joinRpcThreadpool();
    
        return 0;
    

    第一步:

    IPCThreadState::self()->setTheContextObject(service);
    IPCThreadState::IPCThreadState()
    : mProcess(ProcessState::self()),
    调用open_driver,主要打开 /dev/hwbinder
    int fd = open("/dev/hwbinder", O_RDWR | O_CLOEXEC);

    DEFAULT_BINDER_VM_SIZE 默认mm空间是1M
    mVMStart = mmap(0, mMmapSize, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);

    驱动部分的binder_open 主要是分配binder_proc 和 binder_device通过file的private_data指向proc接口。他们之间的映射关系如下:


    binder_open.png

    mmap建立,调用binder_mmap操作
    主要操作是

    static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
    {
        vma->vm_flags = (vma->vm_flags | VM_DONTCOPY) & ~VM_MAYWRITE;
        vma->vm_ops = &binder_vm_ops;
        vma->vm_private_data = proc;
        ret = binder_alloc_mmap_handler(&proc->alloc, vma);
    

    binder_alloc_mmap_hander主要是分配page,初始化alloc结构,分配一个binder_buffer并初始化,添加到alloc->buffers队列中,相应的结构体创建如下:


    binder_mmap.png

    第二步:

    becomeContextManager 调用

    status_t result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &dummy);
    

    binder_ioctl执行开始binder_get_thread 将当前thread 的pid号绑定到一个binder_thread中,然后插入到proc的rb tree中


    binder_thread.png

    在binder driver内部的ioctl使用binder_ioctl_set_ctx_mgr函数如下:
    主要操作是分配binder_node,将他插入到proc下的红黑树中
    在new_node = binder_new_node(proc, NULL); 中fp为NULL因此node里面的cookie ptr 都为0


    binder_becomecontext.png

    2 添加service

    接下来就是要添加service到hwservice中去
    先看下注册的接口如下:

    ::android::status_t ILight::registerAsService(const std::string &serviceName) {
    ::android::hardware::details::onRegistration("android.hardware.light@2.0", "ILight", serviceName);

    const ::android::sp<::android::hidl::manager::V1_0::IServiceManager> sm
            = ::android::hardware::defaultServiceManager();
    if (sm == nullptr) {
        return ::android::INVALID_OPERATION;
    }
    ::android::hardware::Return<bool> ret = sm->add(serviceName.c_str(), this);
    return ret.isOk() && ret ? ::android::OK : ::android::UNKNOWN_ERROR;
    

    }

    第一步:

    调用defaultServiceManager拿到BpHwServiceManager

    sp<IServiceManager1_1> defaultServiceManager1_1() {
        {
    
                details::gDefaultServiceManager =
                        fromBinder<IServiceManager1_1, BpHwServiceManager, BnHwServiceManager>(
                            ProcessState::self()->getContextObject(nullptr));
        return details::gDefaultServiceManager;
    }
    

    ProcessState::self()->getContextObject(nullptr) 执行流程如下:

    sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
    {
        return getStrongProxyForHandle(0);
    }
    sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
    {
     b = new BpHwBinder(handle);
                e->binder = b;
                if (b) e->refs = b->getWeakRefs();
                result = b;
    }
    

    fromBinder最终返回new BpHwServiceManager(BpHwBinder);
    这里面在BpHwBinder创建的过程中,往mOut添加命令OBJECT_LIFETIME_WEAK,在后面的tranct执行时先被执行

    BpHwBinder::BpHwBinder(int32_t handle)
        : mHandle(handle)
        , mAlive(1)
        , mObitsSent(0)
        , mObituaries(NULL)
    {
        ALOGV("Creating BpHwBinder %p handle %d\n", this, mHandle);
    
        extendObjectLifetime(OBJECT_LIFETIME_WEAK);
        IPCThreadState::self()->incWeakHandle(handle);
    }
    void IPCThreadState::incWeakHandle(int32_t handle)
    {
        LOG_REMOTEREFS("IPCThreadState::incWeakHandle(%d)\n", handle);
        mOut.writeInt32(BC_INCREFS);
        mOut.writeInt32(handle);
    }
    

    具体到驱动是
    如果handle为0 说明是同servicemanager通信,

    if (increment && !target) {
        struct binder_node *ctx_mgr_node;
        mutex_lock(&context->context_mgr_node_lock);
        ctx_mgr_node = context->binder_context_mgr_node;
        if (ctx_mgr_node)
                ret = binder_inc_ref_for_node(
                                proc, ctx_mgr_node,
                                strong, NULL, &rdata);
    
        mutex_unlock(&context->context_mgr_node_lock);
    }
    if (ret)
        ret = binder_update_ref_for_handle(
            proc, target, increment, strong,
            &rdata);
    

    牵扯到ref node,得从proc说起,binder_proc有四个rb tree分别是
    1 以node 为key binder_ref组成的rb tree
    2 以desc为key,也就是handle,binder_ref组成的rb tree
    3 node结构体组成的 rb_tree node->ptr为key
    4 threads组成的 rb tree


    binder_procs.png

    其实就是对node 和 binder_ref_data 相应的计数器进行加减

    struct binder_node {
        int internal_strong_refs;
        int local_weak_refs;
        int local_strong_refs;
    }
    struct binder_ref_data {
        int debug_id;
        uint32_t desc;
        int strong;
        int weak;
    };
    
    

    第二步 调用BpHwServiceManager->add(serviceName.c_str(), this);添加service

    BpHwServiceManager::_hidl_add(
            ::android::sp<::android::hardware::IBinder> _hidl_binder = ::android::hardware::toBinder<
                    ::android::hidl::base::V1_0::IBase>(service);
            if (_hidl_binder.get() != nullptr) {
                _hidl_err = _hidl_data.writeStrongBinder(_hidl_binder);
    
    

    其中service为ILight,通过toBinder new一个return new BnHwLight(static_cast<ILight *>(iIntf));,用它来初始化flat_binder_object

    status_t flatten_binder(const sp<ProcessState>& /*proc*/,
        const sp<IBinder>& binder, Parcel* out)
    {
        if (binder != NULL) {
            sp<IBinder> real = binder.promote();
            if (real != NULL) {
                IBinder *local = real->localBinder();
                if (!local) {
                    obj.hdr.type = BINDER_TYPE_WEAK_BINDER;
                    obj.binder = reinterpret_cast<uintptr_t>(binder.get_refs());
                    obj.cookie = reinterpret_cast<uintptr_t>(binder.unsafe_get());
    
    

    BINDER_TYPE_WEAK_BINDER 命令是在驱动中的binder_translate_binder

            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);
                if (ret < 0) {
                    return_error = BR_FAILED_REPLY;
                    return_error_param = ret;
                    return_error_line = __LINE__;
                    goto err_translate_failed;
                }
            } break;
    

    分配一个node给这个binder的service,并创建ref指向这个node,分别插入到proc中的两个ref红黑树中

    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;
        }
    

    其实就是在HIDL_server处创建对应的binder_node和binder_ref,binder_node的cookie执行bnHWBase结构。


    HIDL_Server.png

    Parcel填写完毕后调用
    _hidl_err = ::android::hardware::IInterface::asBinder(_hidl_this)->transact(2 /* add */, _hidl_data, &_hidl_reply);
    最终调用BpHwBinder::transact

    status_t BpHwBinder::transact(
        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags, TransactCallback /*callback*/)
    {
        // Once a binder has died, it will never come back to life.
        if (mAlive) {
            status_t status = IPCThreadState::self()->transact(
                mHandle, code, data, reply, flags);
            if (status == DEAD_OBJECT) mAlive = 0;
            return status;
        }
    
        return DEAD_OBJECT;
    }
    

    IPCThreadState::transact 执行流程

     err = writeTransactionData(BC_TRANSACTION_SG, flags, handle, code, data, NULL);
            if (reply) {
                err = waitForResponse(reply);
            } else {
                Parcel fakeReply;
                err = waitForResponse(&fakeReply);
            }
    

    writeTransactionData 填写mOut

    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_sg tr_sg;
        /* Don't pass uninitialized stack data to a remote process */
        tr_sg.transaction_data.target.ptr = 0;
        tr_sg.transaction_data.target.handle = handle;
        tr_sg.transaction_data.code = code;
        tr_sg.transaction_data.flags = binderFlags;
        tr_sg.transaction_data.cookie = 0;
        tr_sg.transaction_data.sender_pid = 0;
        tr_sg.transaction_data.sender_euid = 0;
    
        const status_t err = data.errorCheck();
        if (err == NO_ERROR) {
            tr_sg.transaction_data.data_size = data.ipcDataSize();
            tr_sg.transaction_data.data.ptr.buffer = data.ipcData();
            tr_sg.transaction_data.offsets_size = data.ipcObjectsCount()*sizeof(binder_size_t);
            tr_sg.transaction_data.data.ptr.offsets = data.ipcObjects();
            tr_sg.buffers_size = data.ipcBufferSize();
        } else if (statusBuffer) {
            tr_sg.transaction_data.flags |= TF_STATUS_CODE;
            *statusBuffer = err;
            tr_sg.transaction_data.data_size = sizeof(status_t);
            tr_sg.transaction_data.data.ptr.buffer = reinterpret_cast<uintptr_t>(statusBuffer);
            tr_sg.transaction_data.offsets_size = 0;
            tr_sg.transaction_data.data.ptr.offsets = 0;
            tr_sg.buffers_size = 0;
        } else {
            return (mLastError = err);
        }
    
        mOut.writeInt32(cmd);
        mOut.write(&tr_sg, sizeof(tr_sg));
    
        return NO_ERROR;
    
    

    waitForResponse 开始调用talkWithDriver 填写binder_write_read bwr,调用 ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0

    status_t IPCThreadState::talkWithDriver(bool doReceive)
    {
        bwr.write_size = outAvail;
        bwr.write_buffer = (uintptr_t)mOut.data();
        bwr.write_consumed = 0;
        bwr.read_consumed = 0;
    
            if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
                err = NO_ERROR;
            else
                err = -errno;
    

    这里牵扯到驱动的BINDER_WRITE_READ
    binder_write_read 结构体结构如下:

    struct binder_write_read {
        binder_size_t       write_size; /* bytes to write */
        binder_size_t       write_consumed; /* bytes consumed by driver */
        binder_uintptr_t    write_buffer;
        binder_size_t       read_size;  /* bytes to read */
        binder_size_t       read_consumed;  /* bytes consumed by driver */
        binder_uintptr_t    read_buffer;
    };
    
    static int binder_ioctl_write_read(struct file *filp,
                    unsigned int cmd, unsigned long arg,
                    struct binder_thread *thread)
    {
        if (copy_from_user(&bwr, ubuf, sizeof(bwr))) {
            ret = -EFAULT;
            goto out;
        }   //第一次从bp端将binder_write_read copy到内核
    
        if (bwr.write_size > 0) {
            ret = binder_thread_write(proc, thread,  //此处写数据
                          bwr.write_buffer,
                          bwr.write_size,
                          &bwr.write_consumed);
    
    具体到
    static int binder_thread_write(struct binder_proc *proc,
                struct binder_thread *thread,
                binder_uintptr_t binder_buffer, size_t size,
                binder_size_t *consumed)
    {
            case BC_TRANSACTION_SG:
            case BC_REPLY_SG: {
                struct binder_transaction_data_sg tr;
    
                if (copy_from_user(&tr, ptr, sizeof(tr)))
                    return -EFAULT;
                ptr += sizeof(tr);
                binder_transaction(proc, thread, &tr.transaction_data,
                           cmd == BC_REPLY_SG, tr.buffers_size);
                break;
            }
    

    write过程主要是填写binder_transaction,copy buffer,最后通过binder_translate_handle将binder_transaction传递给目标thread, binder_transaction结构如下:

    struct binder_transaction {
        int debug_id;
        struct binder_work work;
        struct binder_thread *from;   //写thread
        struct binder_transaction *from_parent;  //
        struct binder_proc *to_proc;  // 这里是hwservice 的proc
        struct binder_thread *to_thread;  // hwservice 的thread结构
        struct binder_transaction *to_parent;  // 
        unsigned need_reply:1;
        /* unsigned is_dead:1; */   /* not used at the moment */
    
        struct binder_buffer *buffer;   //这里牵扯到一次copy从user到kernel 分配buffer
        unsigned int    code;
        unsigned int    flags;
        struct binder_priority  priority;
        struct binder_priority  saved_priority;
        bool    set_priority_called;
        kuid_t  sender_euid;
        /**
         * @lock:  protects @from, @to_proc, and @to_thread
         *
         * @from, @to_proc, and @to_thread can be set to NULL
         * during thread teardown
         */
        spinlock_t lock;
    };
    
            case BINDER_TYPE_HANDLE:
            case BINDER_TYPE_WEAK_HANDLE: {
                struct flat_binder_object *fp;
    
                fp = to_flat_binder_object(hdr);
                ret = binder_translate_handle(fp, t, thread);
                if (ret < 0) {
                    return_error = BR_FAILED_REPLY;
                    return_error_param = ret;
                    return_error_line = __LINE__;
                    goto err_translate_failed;
                }
            } break;
    上面通过binder_translate_handle 得到handle 和cookie并赋值
    struct flat_binder_object {
        struct binder_object_header hdr;
        __u32               flags;
    
        /* 8 bytes of data. */
        union {
            binder_uintptr_t    binder; /* local object */
            __u32           handle; /* remote object */
        };
    
        /* extra data associated with local object */
        binder_uintptr_t    cookie;
    };
    

    最重要的一部就是 binder_proc_transaction
    将binder_transaction 添加到thread->todo list上去,最终唤醒hwservice,这样完成了写的操作。

            binder_enqueue_work_ilocked(&t->work, &target_thread->todo);
            binder_inner_proc_unlock(target_proc);
            wake_up_interruptible_sync(&target_thread->wait);
    
    binder_write.png

    当hwservice完成service的添加之后,binder_write,添加到thread->todo list中,唤醒register_service线程,这时register_service应该阻塞在read中。
    binder_ioctl_write_read中完成write后,阻塞在read中,等待read返回

    static int binder_ioctl_write_read(struct file *filp,
                    unsigned int cmd, unsigned long arg,
                    struct binder_thread *thread)
        if (bwr.write_size > 0) {
            ret = binder_thread_write(proc, thread,
                          bwr.write_buffer,
                          bwr.write_size,
                          &bwr.write_consumed);
            trace_binder_write_done(ret);
            if (ret < 0) {
                bwr.read_consumed = 0;
                if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
                    ret = -EFAULT;
                goto out;
            }
        }
        if (bwr.read_size > 0) {
            ret = binder_thread_read(proc, thread, bwr.read_buffer,
                         bwr.read_size,
                         &bwr.read_consumed,
                         filp->f_flags & O_NONBLOCK);
            trace_binder_read_done(ret);
            binder_inner_proc_lock(proc);
            if (!binder_worklist_empty_ilocked(&proc->todo))
                binder_wakeup_proc_ilocked(proc);
            binder_inner_proc_unlock(proc);
            if (ret < 0) {
                if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
                    ret = -EFAULT;
                goto out;
            }
        }
    

    binder_thread_read 将当前进程挂到thread->wait中去,等待唤醒

    static int binder_wait_for_work(struct binder_thread *thread,
                    bool do_proc_work)
    {
        DEFINE_WAIT(wait);
        struct binder_proc *proc = thread->proc;
        int ret = 0;
    
        freezer_do_not_count();
        binder_inner_proc_lock(proc);
        for (;;) {
            prepare_to_wait(&thread->wait, &wait, TASK_INTERRUPTIBLE);
            if (binder_has_work_ilocked(thread, do_proc_work))
                break;
            if (do_proc_work)
                list_add(&thread->waiting_thread_node,
                     &proc->waiting_threads);
            binder_inner_proc_unlock(proc);
            schedule();
            binder_inner_proc_lock(proc);
            list_del_init(&thread->waiting_thread_node);
            if (signal_pending(current)) {
                ret = -ERESTARTSYS;
                break;
            }
        }
        finish_wait(&thread->wait, &wait);
        binder_inner_proc_unlock(proc);
        freezer_count();
    
        return ret;
    
    

    第三步 hwservice 添加server

    此时hwservice也是阻塞在binder_read中,在被register线程唤醒后,拿到binder_transaction

            w = binder_dequeue_work_head_ilocked(list);
    
            switch (w->type) {
            case BINDER_WORK_TRANSACTION: {
                binder_inner_proc_unlock(proc);
                t = container_of(w, struct binder_transaction, work);
            } break;
    

    得到binder_transaction 将,完成其他参数的赋值

            t->buffer->allow_user_free = 1;
            if (cmd == BR_TRANSACTION && !(t->flags & TF_ONE_WAY)) {
                binder_inner_proc_lock(thread->proc);
                t->to_parent = thread->transaction_stack;
                t->to_thread = thread;
                thread->transaction_stack = t;
                binder_inner_proc_unlock(thread->proc);
    

    然后建立了如下的图,hwservice的transaction_stack也是执行这个binder_transaction


    binder_read.png

    然后根据binder_transaction初始化binder_transaction_data

    struct binder_transaction_data {
        /* The first two are only used for bcTRANSACTION and brTRANSACTION,
         * identifying the target and contents of the transaction.
         */
        union {
            /* target descriptor of command transaction */
            __u32   handle;
            /* target descriptor of return transaction */
            binder_uintptr_t ptr;
        } target;
        binder_uintptr_t    cookie; /* target object cookie */
        __u32       code;       /* transaction command */
    
        /* General information about the transaction. */
        __u32           flags;
        pid_t       sender_pid;
        uid_t       sender_euid;
        binder_size_t   data_size;  /* number of bytes of data */
        binder_size_t   offsets_size;   /* number of bytes of offsets */
    
        /* If this transaction is inline, the data immediately
         * follows here; otherwise, it ends with a pointer to
         * the data buffer.
         */
        union {
            struct {
                /* transaction data */
                binder_uintptr_t    buffer;
                /* offsets from buffer to flat_binder_object structs */
                binder_uintptr_t    offsets;
            } ptr;
            __u8    buf[8];
        } data;
    };
    
                tr.target.ptr = target_node->ptr;
                tr.cookie =  target_node->cookie;
            tr.code = t->code;
            tr.flags = t->flags;
            tr.data_size = t->buffer->data_size;
            tr.offsets_size = t->buffer->offsets_size;
            tr.data.ptr.buffer = (binder_uintptr_t)
                ((uintptr_t)t->buffer->data +
                binder_alloc_get_user_buffer_offset(&proc->alloc));
            tr.data.ptr.offsets = tr.data.ptr.buffer +
                        ALIGN(t->buffer->data_size,
                            sizeof(void *));
            ptr += sizeof(uint32_t);
            if (copy_to_user(ptr, &tr, sizeof(tr))) {
                if (t_from)
                    binder_thread_dec_tmpref(t_from);
    

    最后将数据返回给read线程,也就是hwservice
    if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {
    ret = -EFAULT;
    goto out;
    在hwservice的线程的用户态,将binder_transaction_data读出

                if (tr.target.ptr) { //普通的HIDL server走这个分支
                    // We only have a weak reference on the target object, so we must first try to
                    // safely acquire a strong reference before doing anything else with it.
                    if (reinterpret_cast<RefBase::weakref_type*>(
                            tr.target.ptr)->attemptIncStrong(this)) {
                        error = reinterpret_cast<BHwBinder*>(tr.cookie)->transact(tr.code, buffer,
                                &reply, tr.flags, reply_callback);
                        reinterpret_cast<BHwBinder*>(tr.cookie)->decStrong(this);
                    } else {
                        error = UNKNOWN_TRANSACTION;
                    }
    
                } else {
                    error = mContextObject->transact(tr.code, buffer, &reply, tr.flags, reply_callback);  //hwservice调用
                }
    
    

    其实调用的是BnHwServiceManager::onTransact

    ::android::status_t BnHwServiceManager::onTransact(
            uint32_t _hidl_code,
            const ::android::hardware::Parcel &_hidl_data,
            ::android::hardware::Parcel *_hidl_reply,
            uint32_t _hidl_flags,
            TransactCallback _hidl_cb) {
        ::android::status_t _hidl_err = ::android::OK;
    switch (_hidl_code) {
            case 1 /* get */:
            {
                bool _hidl_is_oneway = _hidl_flags & 1 /* oneway */;
                if (_hidl_is_oneway != false) {
                    return ::android::UNKNOWN_ERROR;
                }
    
                _hidl_err = ::android::hidl::manager::V1_0::BnHwServiceManager::_hidl_get(this, _hidl_data, _hidl_reply, _hidl_cb);
                break;
            }
    
            case 2 /* add */:
            {
                bool _hidl_is_oneway = _hidl_flags & 1 /* oneway */;
                if (_hidl_is_oneway != false) {
                    return ::android::UNKNOWN_ERROR;
                }
    
                _hidl_err = ::android::hidl::manager::V1_0::BnHwServiceManager::_hidl_add(this, _hidl_data, _hidl_reply, _hidl_cb);
                break;
            }
    
            case 3 /* getTransport */:
            {
                bool _hidl_is_oneway = _hidl_flags & 1 /* oneway */;
                if (_hidl_is_oneway != false) {
                    return ::android::UNKNOWN_ERROR;
                }
    
                _hidl_err = ::android::hidl::manager::V1_0::BnHwServiceManager::_hidl_getTransport(this, _hidl_data, _hidl_reply, _hidl_cb);
                break;
            }
    
            case 4 /* list */:
            {
                bool _hidl_is_oneway = _hidl_flags & 1 /* oneway */;
                if (_hidl_is_oneway != false) {
                    return ::android::UNKNOWN_ERROR;
                }
    
                _hidl_err = ::android::hidl::manager::V1_0::BnHwServiceManager::_hidl_list(this, _hidl_data, _hidl_reply, _hidl_cb);
                break;
            }
    
            case 5 /* listByInterface */:
            {
                bool _hidl_is_oneway = _hidl_flags & 1 /* oneway */;
                if (_hidl_is_oneway != false) {
                    return ::android::UNKNOWN_ERROR;
                }
    
                _hidl_err = ::android::hidl::manager::V1_0::BnHwServiceManager::_hidl_listByInterface(this, _hidl_data, _hidl_reply, _hidl_cb);
                break;
            }
    
            case 6 /* registerForNotifications */:
            {
                bool _hidl_is_oneway = _hidl_flags & 1 /* oneway */;
                if (_hidl_is_oneway != false) {
                    return ::android::UNKNOWN_ERROR;
                }
    
                _hidl_err = ::android::hidl::manager::V1_0::BnHwServiceManager::_hidl_registerForNotifications(this, _hidl_data, _hidl_reply, _hidl_cb);
                break;
            }
    
            case 7 /* debugDump */:
            {
                bool _hidl_is_oneway = _hidl_flags & 1 /* oneway */;
                if (_hidl_is_oneway != false) {
                    return ::android::UNKNOWN_ERROR;
                }
    
                _hidl_err = ::android::hidl::manager::V1_0::BnHwServiceManager::_hidl_debugDump(this, _hidl_data, _hidl_reply, _hidl_cb);
                break;
            }
    
            case 8 /* registerPassthroughClient */:
            {
                bool _hidl_is_oneway = _hidl_flags & 1 /* oneway */;
                if (_hidl_is_oneway != false) {
                    return ::android::UNKNOWN_ERROR;
                }
    
                _hidl_err = ::android::hidl::manager::V1_0::BnHwServiceManager::_hidl_registerPassthroughClient(this, _hidl_data, _hidl_reply, _hidl_cb);
                break;
            }
    
            default:
            {
                return ::android::hidl::base::V1_0::BnHwBase::onTransact(
                        _hidl_code, _hidl_data, _hidl_reply, _hidl_flags, _hidl_cb);
            }
        }
    
        if (_hidl_err == ::android::UNEXPECTED_NULL) {
            _hidl_err = ::android::hardware::writeToParcel(
                    ::android::hardware::Status::fromExceptionCode(::android::hardware::Status::EX_NULL_POINTER),
                    _hidl_reply);
        }return _hidl_err;
    }
    

    在完成service的添加后,返回register线程调用结果

                if ((tr.flags & TF_ONE_WAY) == 0) {
                    if (!reply_sent) {
                        // Should have been a reply but there wasn't, so there
                        // must have been an error instead.
                        reply.setError(error);
                        sendReply(reply, 0);
                    } else {
    status_t IPCThreadState::sendReply(const Parcel& reply, uint32_t flags)
    {
        status_t err;
        status_t statusBuffer;
        err = writeTransactionData(BC_REPLY_SG, flags, -1, 0, reply, &statusBuffer);
        if (err < NO_ERROR) return err;
    
        return waitForResponse(NULL, NULL);
    }
    
    

    具体到驱动里

            case BC_TRANSACTION_SG:
            case BC_REPLY_SG: {
                struct binder_transaction_data_sg tr;
    
                if (copy_from_user(&tr, ptr, sizeof(tr)))
                    return -EFAULT;
                ptr += sizeof(tr);
                binder_transaction(proc, thread, &tr.transaction_data,
                           cmd == BC_REPLY_SG, tr.buffers_size);
                break;
            }
    

    binder_transaction调用reply为true,拿到binder_transaction从而得到target_thread和target_proc

    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)
        if (reply) {
            binder_inner_proc_lock(proc);
            in_reply_to = thread->transaction_stack;
    
    

    剩下的与第二步相同,传输到register的todo中,唤醒,返回到register线程用户带,得到注册结果

    第四步 client 调用getservice

    4.1 注册到hwservice的IBinder

    ::android::status_t ILight::registerAsService(const std::string &serviceName) {
        ::android::hardware::details::onRegistration("android.hardware.light@2.0", "ILight", serviceName);
    
        const ::android::sp<::android::hidl::manager::V1_0::IServiceManager> sm
                = ::android::hardware::defaultServiceManager();
        if (sm == nullptr) {
            return ::android::INVALID_OPERATION;
        }
        ::android::hardware::Return<bool> ret = sm->add(serviceName.c_str(), this);
        return ret.isOk() && ret ? ::android::OK : ::android::UNKNOWN_ERROR;
    }
    

    注册的是 ILight其中isRemote()返回false

            ::android::sp<::android::hardware::IBinder> _hidl_binder = ::android::hardware::toBinder<
                    ::android::hidl::base::V1_0::IBase>(service);
            if (_hidl_binder.get() != nullptr) {
                _hidl_err = _hidl_data.writeStrongBinder(_hidl_binder);
    

    toBinder就根据ILight new一个BnHwLight,返回的父类IBinder指向BnHwLight

            ::android::sp<::android::hardware::IBinder> _hidl_binder = ::android::hardware::toBinder<
                    ::android::hidl::base::V1_0::IBase>(service);
            if (_hidl_binder.get() != nullptr) {
                _hidl_err = _hidl_data.writeStrongBinder(_hidl_binder);
    

    经过驱动的传输后,返回给上层处理的是 BINDER_TYPE_HANDLE 和binder_refs的键值

        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;
    
    

    在BnHwServiceManager::_hidl_add 读出来的

            ::android::sp<::android::hardware::IBinder> _hidl_binder;
            _hidl_err = _hidl_data.readNullableStrongBinder(&_hidl_binder);
    
     service = ::android::hardware::fromBinder<::android::hidl::base::V1_0::IBase,::android::hidl::base::V1_0::BpHwBase,::android::hidl::base::V1_0::BnHwBase>(_hidl_binder);
    
    readNullableStrongBinder 将cookie付给_hidl_binder
    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:
                case BINDER_TYPE_WEAK_HANDLE:
                    *out = proc->getWeakProxyForHandle(flat->handle);
                    return finish_unflatten_binder(
                        static_cast<BpHwBinder*>(out->unsafe_get()), *flat, in);
    

    根据handle new出一个BpHwBinder
    fromBinder localBinder为null,new BpHwBase(BpHwBinder),从而添加到hwservice中去的是bpHwBase
    bool _hidl_out_success = static_cast<IServiceManager>(_hidl_this->getImpl().get())->add(name, service);

    4.2 getservice 过程

    hwservice在拿到对应的BpHwBase结构后

     BnHwServiceManager::_hidl_get
    {
            ::android::sp<::android::hardware::IBinder> _hidl_binder = ::android::hardware::toBinder<
                    ::android::hidl::base::V1_0::IBase>(_hidl_out_service);
            if (_hidl_binder.get() != nullptr) {
                _hidl_err = _hidl_reply->writeStrongBinder(_hidl_binder);
    }
    

    toBinder得到的是填写的flat->handle,在writeStrongBinder时然会给的是handle值

    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;
    

    BINDER_TYPE_HANDLE传输到驱动中

            case BINDER_TYPE_WEAK_HANDLE: {
                struct flat_binder_object *fp;
    
                fp = to_flat_binder_object(hdr);
                ret = binder_translate_handle(fp, t, thread);
    
    static int binder_translate_handle(struct flat_binder_object *fp,
                       struct binder_transaction *t,
                       struct binder_thread *thread)
        if (node->proc == target_proc) {  //这两个不相等,为Node分配binder_ref
        } else {
            int ret;
            struct binder_ref_data dest_rdata;
    
            binder_node_unlock(node);
            ret = binder_inc_ref_for_node(target_proc, node,
                    fp->hdr.type == BINDER_TYPE_HANDLE,
                    NULL, &dest_rdata);
            if (ret)
                goto done;
    
            fp->binder = 0;
            fp->handle = dest_rdata.desc;
            fp->cookie = 0;
            trace_binder_transaction_ref_to_ref(t, node, &src_rdata,
                                &dest_rdata);
    
    

    这样返回给用户层的是新分配和绑定号的handle,驱动传输完成后的结构如下,这样通过bp的handler可以跟HIDL_service的node通信了

    binder_register.png
    ::android::hardware::Return<::android::sp<::android::hidl::base::V1_0::IBase>> BpHwServiceManager::_hidl_get
    
            ::android::sp<::android::hardware::IBinder> _hidl_binder;
            _hidl_err = _hidl_reply.readNullableStrongBinder(&_hidl_binder);
            if (_hidl_err != ::android::OK) { goto _hidl_error; }
    
               case BINDER_TYPE_HANDLE:
                    *out = proc->getStrongProxyForHandle(flat->handle);
                    return finish_unflatten_binder(
                        static_cast<BpHwBinder*>(out->get()), *flat, in);
    

    通过getStrongProxyForHandle 根据handle new出新的BpHwBinder

    sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
    {
        sp<IBinder> result;
    
        AutoMutex _l(mLock);
    
        handle_entry* e = lookupHandleLocked(handle);
    
        if (e != NULL) {
            // We need to create a new BpHwBinder if there isn't currently one, OR we
            // are unable to acquire a weak reference on this current one.  See comment
            // in getWeakProxyForHandle() for more info about this.
            IBinder* b = e->binder;
            if (b == NULL || !e->refs->attemptIncWeak(this)) {
                b = new BpHwBinder(handle);
    

    五总结

    1)Hidl service
    在HIDL_SEVICE侧注册node,并将node->proc指向target_proc也就是hwservice的proc
    writeStrongBinder
    BINDER_TYPE_WEAK_BINDER

    2)在驱动执行完成后返回给hwservice的是分配一个binder_ref的handle
    ret = binder_inc_ref_for_node(target_proc, node,
    fp->hdr.type == BINDER_TYPE_BINDER,
    &thread->todo, &rdata);

    3)在hwservice拿到这个handle后注册一个 通过new BpHwBase(BpHwBinder)

    4)hidl_client通过get操作

    5)hwservice writeStrongBinder 到驱动调用BINDER_TYPE_WEAK_HANDLE,将 sendReply(reply, 0);
    还是使用binder_write,只不过这次在hid_client分配binder_ref 指向node,这样返回给hidl_client的是cliet端的handle

    6)hidl_client拿到这个handle后注册bphwbinder

    网上找了图,这个图介绍的比价清晰。


    binder.png

    相关文章

      网友评论

          本文标题:HIDL 与 binder 调用流程分析

          本文链接:https://www.haomeiwen.com/subject/kgmfsftx.html