Android Audio Subsystem - get_audio_flinger - 02

来源:互联网 发布:mac safari 插件管理 编辑:程序博客网 时间:2024/05/19 23:24

 

 

 

AudioSystem::get_audio_flinger()  continue…

 

1.    IPCThreadState::transact()

Frameworks/native/libs/binder/IPCThreadState.cpp

 

status_tIPCThreadState::transact(int32_t handle,

                                  uint32_tcode, const Parcel& data,

                                  Parcel*reply, uint32_t flags)

{

    status_t err = data.errorCheck();

 

    flags |= TF_ACCEPT_FDS;

 

    IF_LOG_TRANSACTIONS() {

        TextOutput::Bundle _b(alog);

        alog << "BC_TRANSACTION thr" << (void*)pthread_self() << " / hand "

            << handle << " /code " << TypeCode(code) << ": "

            << indent << data<< dedent << endl;

    }

   

    if (err == NO_ERROR) {

        LOG_ONEWAY(">>>> SENDfrom pid %d uid %d %s", getpid(), getuid(),

            (flags & TF_ONE_WAY) == 0 ?"READ REPLY" : "ONE WAY");

       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 0

        if (code == 4) { // relayout

           ALOGI(">>>>>> CALLING transaction 4");

        } else {

            ALOGI(">>>>>>CALLING transaction %d", code);

        }

        #endif

        if (reply) {

           err =waitForResponse(reply);

        } else {

            Parcel fakeReply;

            err =waitForResponse(&fakeReply);

        }

        #if 0

        if (code == 4) { // relayout

           ALOGI("<<<<<< RETURNING transaction 4");

        } else {

           ALOGI("<<<<<< RETURNING transaction %d",code);

        }

        #endif

       

        IF_LOG_TRANSACTIONS() {

            TextOutput::Bundle _b(alog);

            alog << "BR_REPLY thr" << (void*)pthread_self() << " / hand "

                << handle <<": ";

            if (reply) alog << indent<< *reply << dedent << endl;

            else alog << "(nonerequested)" << endl;

        }

    } else {

        err = waitForResponse(NULL, NULL);

    }

   

    return err;

}

 

status_tIPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,

    int32_t handle, uint32_t code, constParcel& data, status_t* statusBuffer)

{

    binder_transaction_data tr;

 

//handle = 0code=  CHECK_SERVICE_TRANSACTIONcmd = BC_TRANSACTION

 

   tr.target.handle =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(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 = statusBuffer;

        tr.offsets_size = 0;

        tr.data.ptr.offsets = NULL;

    } else {

        return (mLastError = err);

    }

   

    mOut.writeInt32(cmd);

    mOut.write(&tr, sizeof(tr));

   

    return NO_ERROR;

}

 

status_tIPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)

{

    int32_t cmd;

    int32_t err;

 

    while (1) {

 

//这儿读数据from binder设备;写数据 into binder设备

//即与binder设备进行通讯

 

       if((err=talkWithDriver()) < NO_ERROR) break;

        err = mIn.errorCheck();

        if (err < NO_ERROR) break;

        if (mIn.dataAvail() == 0) continue;

       

        cmd = mIn.readInt32();

       

        IF_LOG_COMMANDS() {

            alog << "ProcessingwaitForResponse Command: "

                << getReturnString(cmd)<< endl;

        }

 

        switch (cmd) {

        case BR_TRANSACTION_COMPLETE:

            if (!reply &&!acquireResult) goto finish;

            break;

       

        case BR_DEAD_REPLY:

            err = DEAD_OBJECT;

            goto finish;

 

        case BR_FAILED_REPLY:

            err = FAILED_TRANSACTION;

            goto finish;

       

        case BR_ACQUIRE_RESULT:

            {

                ALOG_ASSERT(acquireResult !=NULL, "Unexpected brACQUIRE_RESULT");

                const int32_t result =mIn.readInt32();

                if (!acquireResult) continue;

                *acquireResult = result ?NO_ERROR : INVALID_OPERATION;

            }

            goto finish;

       

        case BR_REPLY:

            {

                binder_transaction_data tr;

                err = mIn.read(&tr,sizeof(tr));

                ALOG_ASSERT(err == NO_ERROR,"Not enough command data for brREPLY");

                if (err != NO_ERROR) gotofinish;

 

                if (reply) {

                    if ((tr.flags &TF_STATUS_CODE) == 0) {

                       reply->ipcSetDataReference(

                           reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),

                            tr.data_size,

                           reinterpret_cast<const size_t*>(tr.data.ptr.offsets),

                           tr.offsets_size/sizeof(size_t),

                            freeBuffer, this);

                    } else {

                        err =*static_cast<const status_t*>(tr.data.ptr.buffer);

                        freeBuffer(NULL,

                           reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),

                            tr.data_size,

                           reinterpret_cast<const size_t*>(tr.data.ptr.offsets),

                           tr.offsets_size/sizeof(size_t), this);

                    }

                } else {

                    freeBuffer(NULL,

                       reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),

                        tr.data_size,

                       reinterpret_cast<const size_t*>(tr.data.ptr.offsets),

                       tr.offsets_size/sizeof(size_t), this);

                    continue;

                }

            }

            goto finish;

 

        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;

}

 

 

 

status_tIPCThreadState::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 weare still reading

    // from data left in the input buffer andthe caller

    // has requested to read the next data.

    const size_t outAvail = (!doReceive ||needRead) ? mOut.dataSize() : 0;

   

    bwr.write_size = outAvail;

    bwr.write_buffer = (long unsignedint)mOut.data();

 

    // This is what we'll read.

    if (doReceive && needRead) {

        bwr.read_size = mIn.dataCapacity();

        bwr.read_buffer = (long unsignedint)mIn.data();

    } else {

        bwr.read_size = 0;

        bwr.read_buffer = 0;

    }

 

    IF_LOG_COMMANDS() {

        TextOutput::Bundle _b(alog);

        if (outAvail != 0) {

            alog << "Sendingcommands to driver: " << indent;

            const void* cmds = (constvoid*)bwr.write_buffer;

            const void* end = ((constuint8_t*)cmds)+bwr.write_size;

            alog << HexDump(cmds, bwr.write_size)<< endl;

            while (cmds < end) cmds =printCommand(alog, cmds);

            alog << dedent;

        }

        alog << "Size of receivebuffer: " << bwr.read_size

            << ", needRead: "<< needRead << ", doReceive: " << doReceive<< endl;

    }

   

    // Return immediately if there is nothingto 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 toread/write, write size = " << mOut.dataSize() << endl;

        }

#ifdefined(HAVE_ANDROID_OS)

       if(ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)

            err = NO_ERROR;

        else

            err = -errno;

#else

        err = INVALID_OPERATION;

#endif

        if (mProcess->mDriverFD <= 0) {

            err = -EBADF;

        }

        IF_LOG_COMMANDS() {

            alog << "Finishedread/write, write size = " << mOut.dataSize() << endl;

        }

    } while (err == -EINTR);

 

    IF_LOG_COMMANDS() {

        alog << "Our err: "<< (void*)err << ", write consumed: "

            << bwr.write_consumed<< " (of " << mOut.dataSize()

                    << "), readconsumed: " << bwr.read_consumed << endl;

    }

 

    if (err >= NO_ERROR) {

        if (bwr.write_consumed > 0) {

            if (bwr.write_consumed <(ssize_t)mOut.dataSize())

                mOut.remove(0,bwr.write_consumed);

            else

                mOut.setDataSize(0);

        }

        if (bwr.read_consumed > 0) {

            mIn.setDataSize(bwr.read_consumed);

            mIn.setDataPosition(0);

        }

        IF_LOG_COMMANDS() {

            TextOutput::Bundle _b(alog);

            alog << "Remaining datasize: " << mOut.dataSize() << endl;

            alog << "Receivedcommands from driver: " << indent;

            const void* cmds = mIn.data();

            const void* end = mIn.data() +mIn.dataSize();

            alog << HexDump(cmds,mIn.dataSize()) << endl;

            while (cmds < end) cmds =printReturnCommand(alog, cmds);

            alog << dedent;

        }

        return NO_ERROR;

    }

   

    return err;

}

 

 

2.     binder_loop()

Frameworks/native/cmds/servicemanager/binder.c

voidbinder_loop(struct binder_state *bs, binder_handler func)

{

    int res;

    struct binder_write_read bwr;

    unsigned readbuf[32];

 

    bwr.write_size = 0;

    bwr.write_consumed = 0;

    bwr.write_buffer = 0;

   

    readbuf[0] = BC_ENTER_LOOPER;

    binder_write(bs, readbuf,sizeof(unsigned));

 

    for (;;) {

        bwr.read_size = sizeof(readbuf);

        bwr.read_consumed = 0;

        bwr.read_buffer = (unsigned) readbuf;

 

       res =ioctl(bs->fd, BINDER_WRITE_READ, &bwr);

 

        if (res < 0) {

            ALOGE("binder_loop: ioctlfailed (%s)\n", strerror(errno));

            break;

        }

 

       res =binder_parse(bs, 0, readbuf, bwr.read_consumed, func);

        if (res == 0) {

            ALOGE("binder_loop: unexpectedreply?!\n");

            break;

        }

        if (res < 0) {

            ALOGE("binder_loop: io error%d %s\n", res, strerror(errno));

            break;

        }

    }

}

 

 

intbinder_parse(struct binder_state *bs, struct binder_io *bio,

                 uint32_t *ptr, uint32_t size,binder_handler func)

{

    int r = 1;

    uint32_t *end = ptr + (size / 4);

 

    while (ptr < end) {

        uint32_t cmd = *ptr++;

#if TRACE

        fprintf(stderr,"%s:\n",cmd_name(cmd));

#endif

        switch(cmd) {

        case BR_NOOP:

            break;

        case BR_TRANSACTION_COMPLETE:

            break;

        case BR_INCREFS:

        case BR_ACQUIRE:

        case BR_RELEASE:

        case BR_DECREFS:

#if TRACE

            fprintf(stderr,"  %08x %08x\n", ptr[0], ptr[1]);

#endif

            ptr += 2;

            break;

        case BR_TRANSACTION: {

            struct binder_txn *txn = (void *)ptr;

            if ((end - ptr) * sizeof(uint32_t)< sizeof(struct binder_txn)) {

                ALOGE("parse: txn toosmall!\n");

                return -1;

            }

            binder_dump_txn(txn);

            if (func) {

                unsigned rdata[256/4];

                struct binder_io msg;

                struct binder_io reply;

                int res;

 

                bio_init(&reply, rdata,sizeof(rdata), 4);

                bio_init_from_txn(&msg,txn);

//这儿 func就是

// frameworks/native/cmds/servicemanager/service_manager.c

//中的svcmgr_handler

//service_manager中有如下代码

// int main(int argc, char **argv)

// {

//   structbinder_state *bs;

//   void *svcmgr =BINDER_SERVICE_MANAGER;

 

//   bs =binder_open(128*1024);

 

 //   if (binder_become_context_manager(bs)) {

 //       ALOGE("cannot become contextmanager (%s)\n", strerror(errno));

 //       return -1;

 //   }

 

//   svcmgr_handle =svcmgr;

//   binder_loop(bs,svcmgr_handler);

//   return 0;

// }

               res =func(bs, txn, &msg, &reply);

               binder_send_reply(bs, &reply, txn->data, res);

            }

            ptr += sizeof(*txn) /sizeof(uint32_t);

            break;

        }

        case BR_REPLY: {

            struct binder_txn *txn = (void*)ptr;

            if ((end - ptr) * sizeof(uint32_t)< sizeof(struct binder_txn)) {

                ALOGE("parse: reply toosmall!\n");

                return -1;

            }

            binder_dump_txn(txn);

            if (bio) {

                bio_init_from_txn(bio, txn);

                bio = 0;

            } else {

                    /* todo FREE BUFFER */

            }

            ptr += (sizeof(*txn) /sizeof(uint32_t));

            r = 0;

            break;

        }

        case BR_DEAD_BINDER: {

            struct binder_death *death =(void*) *ptr++;

            death->func(bs, death->ptr);

            break;

        }

        case BR_FAILED_REPLY:

            r = -1;

            break;

        case BR_DEAD_REPLY:

            r = -1;

            break;

        default:

            ALOGE("parse: OOPS %d\n",cmd);

            return -1;

        }

    }

 

    return r;

}

 

 

3.     svcmgr_handler()

frameworks/native/cmds/servicemanager/service_manager.c

intmain(int argc, char **argv)

{

    struct binder_state *bs;

    void *svcmgr = BINDER_SERVICE_MANAGER;

 

    bs = binder_open(128*1024);

 

    if (binder_become_context_manager(bs)) {

        ALOGE("cannot become contextmanager (%s)\n", strerror(errno));

        return -1;

    }

 

    svcmgr_handle = svcmgr;

    binder_loop(bs, svcmgr_handler);

    return 0;

}

 

intsvcmgr_handler(struct binder_state *bs,

                   struct binder_txn *txn,

                   struct binder_io *msg,

                   struct binder_io *reply)

{

    struct svcinfo *si;

    uint16_t *s;

    unsigned len;

    void *ptr;

    uint32_t strict_policy;

    int allow_isolated;

 

//    ALOGI("target=%p code=%d pid=%duid=%d\n",

//         txn->target, txn->code,txn->sender_pid, txn->sender_euid);

 

    if (txn->target != svcmgr_handle)

        return -1;

 

    // Equivalent toParcel::enforceInterface(), reading the RPC

    // header with the strict mode policy maskand the interface name.

    // Note that we ignore the strict_policyand don't propagate it

    // further (since we do no outbound RPCsanyway).

    strict_policy = bio_get_uint32(msg);

    s = bio_get_string16(msg, &len);

    if ((len != (sizeof(svcmgr_id) / 2)) ||

        memcmp(svcmgr_id, s,sizeof(svcmgr_id))) {

        fprintf(stderr,"invalid id%s\n", str8(s));

        return -1;

    }

 

    switch(txn->code) {

    case SVC_MGR_GET_SERVICE:

    case SVC_MGR_CHECK_SERVICE:

        s = bio_get_string16(msg, &len);

       ptr =do_find_service(bs, s, len, txn->sender_euid);

        if (!ptr)

            break;

       bio_put_ref(reply, ptr);

        return 0;

 

    case SVC_MGR_ADD_SERVICE:

        s = bio_get_string16(msg, &len);

        ptr = bio_get_ref(msg);

        allow_isolated = bio_get_uint32(msg) ?1 : 0;

        if (do_add_service(bs, s, len, ptr,txn->sender_euid, allow_isolated))

            return -1;

        break;

 

    case SVC_MGR_LIST_SERVICES: {

        unsigned n = bio_get_uint32(msg);

 

        si = svclist;

        while ((n-- > 0) && si)

            si = si->next;

        if (si) {

            bio_put_string16(reply,si->name);

            return 0;

        }

        return -1;

    }

    default:

        ALOGE("unknown code %d\n",txn->code);

        return -1;

    }

 

    bio_put_uint32(reply, 0);

    return 0;

}

 

void*do_find_service(struct binder_state *bs, uint16_t *s, unsigned len, unsigneduid)

{

    struct svcinfo *si;

    si = find_svc(s, len);

 

//    ALOGI("check_service('%s') ptr =%p\n", str8(s), si ? si->ptr : 0);

    if (si && si->ptr) {

        if (!si->allow_isolated) {

            // If this service doesn't allowaccess from isolated processes,

            // then check the uid to see if itis isolated.

            unsigned appid = uid % AID_USER;

            if (appid >= AID_ISOLATED_START&& appid <= AID_ISOLATED_END) {

                return 0;

            }

        }

//这个就是XXXServieBiner实体,对于Audio应该是AudioFlinger ?

        return si->ptr;  

    } else {

        return 0;

    }

}

 

4.     bio_put_ref

frameworks/native/cmds/servicemanager/binder.c

//   Binder实体写入reply

void bio_put_ref(structbinder_io *bio, void *ptr)

{

    struct binder_object *obj;

 

    if (ptr)

        obj = bio_alloc_obj(bio);

    else

        obj = bio_alloc(bio, sizeof(*obj));

 

    if (!obj)

        return;

 

    obj->flags = 0x7f |FLAT_BINDER_FLAG_ACCEPTS_FDS;

    obj->type = BINDER_TYPE_HANDLE;

    obj->pointer =ptr;

    obj->cookie = 0;

}

 

5.     IPCThreadState::waitForResponse()

Frameworks/native/libs/binder/IPCThreadState.cpp

上述调用执行到talkWithDriver返回,然后进入BR_REPLY,并直接返回。(不执行executeCommand

status_tIPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)

{

    int32_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 = mIn.readInt32();

        

        IF_LOG_COMMANDS() {

            alog << "ProcessingwaitForResponse Command: "

                << getReturnString(cmd)<< endl;

        }

 

        switch (cmd) {

        case BR_TRANSACTION_COMPLETE:

            if (!reply &&!acquireResult) goto finish;

            break;

       

        case BR_DEAD_REPLY:

            err = DEAD_OBJECT;

            goto finish;

 

        case BR_FAILED_REPLY:

            err = FAILED_TRANSACTION;

            goto finish;

       

        case BR_ACQUIRE_RESULT:

            {

                ALOG_ASSERT(acquireResult !=NULL, "Unexpected brACQUIRE_RESULT");

                const int32_t result =mIn.readInt32();

                if (!acquireResult) continue;

                *acquireResult = result ?NO_ERROR : INVALID_OPERATION;

            }

            goto finish;

       

        case BR_REPLY:

            {

                binder_transaction_data tr;

                err = mIn.read(&tr,sizeof(tr));

                ALOG_ASSERT(err == NO_ERROR,"Not enough command data for brREPLY");

                if (err != NO_ERROR) gotofinish;

 

                if (reply) {

                    if ((tr.flags &TF_STATUS_CODE) == 0) { //返回码ok

                       reply->ipcSetDataReference(

                           reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),

                           tr.data_size,

                           reinterpret_cast<const size_t*>(tr.data.ptr.offsets),

                           tr.offsets_size/sizeof(size_t),

                           freeBuffer, this);

                    } else {

                        err =*static_cast<const status_t*>(tr.data.ptr.buffer);

                        freeBuffer(NULL,

                           reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),

                            tr.data_size,

                           reinterpret_cast<const size_t*>(tr.data.ptr.offsets),

                           tr.offsets_size/sizeof(size_t), this);

                    }

                } else {

                    freeBuffer(NULL,

                       reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),

                        tr.data_size,

                       reinterpret_cast<const size_t*>(tr.data.ptr.offsets),

                        tr.offsets_size/sizeof(size_t),this);

                    continue;

                }

            }

            goto finish;

 

        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;

}

 

6.  BpServiceManager::checkService()

Frameworks/native/libs/binder/IServiceManager.cpp

   virtual sp<IBinder> checkService( const String16& name) const

   {

        Parcel data, reply;

       data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());

        data.writeString16(name);

       remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);

       return reply.readStrongBinder(); 

//这儿将生成一个与BnBinder相对应的BpBinder

    }

 

7.  AudioSystem::get_audio_flinger()

Frameworks/av/media/libmedia/AudioSystem.cpp

回到最初的get_audio_flinger()函数中

constsp<IAudioFlinger>& AudioSystem::get_audio_flinger()

{

    Mutex::Autolock _l(gLock);

    if (gAudioFlinger == 0) {

        sp<IServiceManager> sm =defaultServiceManager();

        sp<IBinder> binder;

        do {

            binder =sm->getService(String16("media.audio_flinger"));

            if (binder != 0)

                break;

            ALOGW("AudioFlinger notpublished, waiting...");

            usleep(500000); // 0.5 s

        } while (true);

        if (gAudioFlingerClient == NULL) {

            gAudioFlingerClient = newAudioFlingerClient();

        } else {

            if (gAudioErrorCallback) {

                gAudioErrorCallback(NO_ERROR);

            }

        }

        binder->linkToDeath(gAudioFlingerClient);

       gAudioFlinger =interface_cast<IAudioFlinger>(binder);

       gAudioFlinger->registerClient(gAudioFlingerClient);

    }

    ALOGE_IF(gAudioFlinger==0, "noAudioFlinger!?");

 

    return gAudioFlinger;

}

 

在这儿interface_cast将调用queryLocalInterface,它返回空,因此生成了一个新的对象BpAudioFlinger,并且它的mRemote成员变量指向binder(一个BpBinder对象)

 

 

 

 

 

 

 

原创粉丝点击