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 = 0,code= CHECK_SERVICE_TRANSACTION,cmd = 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;
}
}
//这个就是XXXServie的Biner实体,对于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对象)