美文网首页
Android Binder(二)

Android Binder(二)

作者: 简静空 | 来源:发表于2019-03-19 16:03 被阅读0次

    MediaPlayerService

    继续分析 MediaPlayerService::instantiate()

    void MediaPlayerService::instantiate() {
        defaultServiceManager()->addService(
                String16("media.player"), new MediaPlayerService());
    }
    

    从前文已经知道defaultServiceManager()返回了BpServiceManager对象,那么就看看这个对象里面的addService函数(位于文件IServiceManager.cpp)

    virtual status_t addService(const String16& name, const sp<IBinder>& service,
                bool allowIsolated)
        {
            Parcel data, reply;
            data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
            data.writeString16(name);
            data.writeStrongBinder(service);
            data.writeInt32(allowIsolated ? 1 : 0);
            status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
            return err == NO_ERROR ? reply.readExceptionCode() : err;
        }
    

    Parcel 在这里承担了载体的责任,数据在打包后传递给了BpBinder的transact

    remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
    
    status_t BpBinder::transact(
        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
    {
        // 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了,那就来看看这个IPCThreadState吧; 这里用到了多线程私有数据,关于具体用法可以查看参考文章,此处不再赘述

    IPCThreadState

    IPCThreadState* IPCThreadState::self()
    {
        if (gHaveTLS) {
    restart:
            const pthread_key_t k = gTLS;
            IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
            if (st) return st;
            return new IPCThreadState;
        }
        
        if (gShutdown) {
            ALOGW("Calling IPCThreadState::self() during shutdown is dangerous, expect a crash.\n");
            return NULL;
        }
        
        pthread_mutex_lock(&gTLSMutex);
        if (!gHaveTLS) {
            int key_create_value = pthread_key_create(&gTLS, threadDestructor);
            if (key_create_value != 0) {
                pthread_mutex_unlock(&gTLSMutex);
                ALOGW("IPCThreadState::self() unable to create TLS key, expect a crash: %s\n",
                        strerror(key_create_value));
                return NULL;
            }
            gHaveTLS = true;
        }
        pthread_mutex_unlock(&gTLSMutex);
        goto restart;
    }
    

    我们可以看到,在self函数中返回了IPCThreadState对象

    IPCThreadState::IPCThreadState()
        : mProcess(ProcessState::self()),
          mMyThreadId(gettid()),
          mStrictModePolicy(0),
          mLastTransactionBinderFlags(0)
    {
        //构造函数中,把自己设置到线程的本地存储中去
        pthread_setspecific(gTLS, this);
        clearCaller();
        //mIn和mOut是两个parcel; mIn是用来接受Binder数据的,mOut是用来发送Binder数据的
        mIn.setDataCapacity(256);
        mOut.setDataCapacity(256);
    }
    

    接下来就可以继续去看transact了

    status_t IPCThreadState::transact(int32_t handle,
                                      uint32_t code, const Parcel& data,
                                      Parcel* reply, uint32_t flags)
    {
        status_t err = data.errorCheck();
    
        flags |= TF_ACCEPT_FDS;
        ......
        if (err == NO_ERROR) {
            //发送函数, BC_TRANSACTION是应用程序向binder发送消息的消息码,binder回复的消息则是以BR开头
            err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
        }
        
        if (err != NO_ERROR) {
            if (reply) reply->setError(err);
            return (mLastError = err);
        }
        
        if ((flags & TF_ONE_WAY) == 0) {
            if (reply) {
                //等待结果的函数
                err = waitForResponse(reply);
            } else {
                Parcel fakeReply;
                err = waitForResponse(&fakeReply);
            }
        ......
        return err;
    }
    
    

    binder发送

    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 tr;
    
        tr.target.ptr = 0; /* Don't pass uninitialized stack data to a remote process */
        tr.target.handle = handle;    // 这里是0, 表示的就是ServiceManager
        tr.code = code;
        tr.flags = binderFlags;
        tr.cookie = 0;
        tr.sender_pid = 0;
        tr.sender_euid = 0;
        
        const status_t err = data.errorCheck();
        if (err == NO_ERROR) {
            tr.data_size = data.ipcDataSize();
            tr.data.ptr.buffer = data.ipcData();
            tr.offsets_size = data.ipcObjectsCount()*sizeof(binder_size_t);
            tr.data.ptr.offsets = data.ipcObjects();
        } else if (statusBuffer) {
            tr.flags |= TF_STATUS_CODE;
            *statusBuffer = err;
            tr.data_size = sizeof(status_t);
            tr.data.ptr.buffer = reinterpret_cast<uintptr_t>(statusBuffer);
            tr.offsets_size = 0;
            tr.data.ptr.offsets = 0;
        } else {
            return (mLastError = err);
        }
        
        //将命令写到mOut, 但没有在这里发送出去
        mOut.writeInt32(cmd);
        mOut.write(&tr, sizeof(tr));
        
        return NO_ERROR;
    }
    

    binder接收

    接下来再继续看看binder的等待接收函数

    status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
    {
        uint32_t cmd;
        int32_t err;
    
        while (1) {
            if ((err=talkWithDriver()) < NO_ERROR) break;
            err = mIn.errorCheck();
            if (err < NO_ERROR) break;
            if (mIn.dataAvail() == 0) continue;
            
            cmd = (uint32_t)mIn.readInt32();
            ......
            switch (cmd) {
            case BR_TRANSACTION_COMPLETE:
                if (!reply && !acquireResult) goto finish;
                break;
            ......
            default:
                err = executeCommand(cmd);
                if (err != NO_ERROR) goto finish;
                break;
            }
        }
    
    finish:
        if (err != NO_ERROR) {
            if (acquireResult) *acquireResult = err;
            if (reply) reply->setError(err);
            mLastError = err;
        }
        return err;
    }
    

    函数有点长,慢慢来看,首先在循环中调用了talkWithDriver(), 猜测就是将mOut里的数据发送出去了,然后通过mIn读取返回的cmd数值,然后根据cmd数值进行不同的处理;
    那么先来看看这个talkWithDriver函数

    status_t IPCThreadState::talkWithDriver(bool doReceive)
    {
        if (mProcess->mDriverFD <= 0) {
            return -EBADF;
        }
        
        binder_write_read bwr;    //和驱动通讯的结构体
        
        // Is the read buffer empty?
        const bool needRead = mIn.dataPosition() >= mIn.dataSize();
        
        // We don't want to write anything if we are still reading
        // from data left in the input buffer and the caller
        // has requested to read the next data.
        const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;
        
        bwr.write_size = outAvail;
        bwr.write_buffer = (uintptr_t)mOut.data();    //将mOut的数据填充进去,然后传递给Binder
    
        // This is what we'll read.
        if (doReceive && needRead) {
            bwr.read_size = mIn.dataCapacity();
            bwr.read_buffer = (uintptr_t)mIn.data();    //mIn的存储空间也传递给驱动了,用来保存返回的数值
        } else {
            bwr.read_size = 0;
            bwr.read_buffer = 0;
        }
    
        IF_LOG_COMMANDS() {
            TextOutput::Bundle _b(alog);
            if (outAvail != 0) {
                alog << "Sending commands to driver: " << indent;
                const void* cmds = (const void*)bwr.write_buffer;
                const void* end = ((const uint8_t*)cmds)+bwr.write_size;
                alog << HexDump(cmds, bwr.write_size) << endl;
                while (cmds < end) cmds = printCommand(alog, cmds);
                alog << dedent;
            }
            alog << "Size of receive buffer: " << bwr.read_size
                << ", needRead: " << needRead << ", doReceive: " << doReceive << endl;
        }
        
        // Return immediately if there is nothing to do.
        if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;
    
        bwr.write_consumed = 0;
        bwr.read_consumed = 0;
        status_t err;
        do {
            IF_LOG_COMMANDS() {
                alog << "About to read/write, write size = " << mOut.dataSize() << endl;
            }
    #if defined(__ANDROID__)
            //到这里就可以看到了,和binder驱动通讯使用的就是ioctl
            if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
                err = NO_ERROR;
            else
                err = -errno;
    #else
            err = INVALID_OPERATION;
    #endif
           ......
    }
    

    从这个函数看下来,我们就可以知道了,talkWithDriver将我们之前保存的mOut传递给了驱动,驱动处理后会将返回信息写入到mIn
    现在已经发送了数据过去了,那么我们如何处理返回的数据呢,我们继续看下executeCommand

    status_t IPCThreadState::executeCommand(int32_t cmd)
    {
        BBinder* obj;
        RefBase::weakref_type* refs;
        status_t result = NO_ERROR;
        
        switch ((uint32_t)cmd) {
        case BR_ERROR:
            result = mIn.readInt32();
            break;
        case BR_TRANSACTION:
            {
                binder_transaction_data tr;
                //到这里其实已经获取到所有的返回信息了,接下里就是根据具体的返回信息去处理业务了
                result = mIn.read(&tr, sizeof(tr));   
                ......
        
        case BR_DEAD_BINDER:  //收到这个就是挂掉了
            {
                BpBinder *proxy = (BpBinder*)mIn.readPointer();
                proxy->sendObituary();
                mOut.writeInt32(BC_DEAD_BINDER_DONE);
                mOut.writePointer((uintptr_t)proxy);
            } break;
        default:
            printf("*** BAD COMMAND %d received from Binder driver\n", cmd);
            result = UNKNOWN_ERROR;
            break;
        }
    
        if (result != NO_ERROR) {
            mLastError = result;
        }
        
        return result;
    }
    

    参考:

    1. 多线程私有数据pthread_key_create

    2.Android进程间通信(IPC)机制Binder简要介绍和学习计划

    上文:
    Android Binder(一)

    相关文章

      网友评论

          本文标题:Android Binder(二)

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