接上一篇:http://blog.csdn.net/cs_lht/article/details/8160968
我们看一下MediaPlayerService是如何把自已添加到ServiceManager中的。
代码路径:framework/base/media/libmediaplayerservice/MediaPlayerService.cpp
void MediaPlayerService::instantiate() { defaultServiceManager()->addService( String16("media.player"), new MediaPlayerService()); }
defaultServiceManager是怎么来的,在上一篇已讲解了,它返回的就是BpServiceManger,对吧?
那我们看BpServiceManager的addService是怎么工作的,它是如何把MediaPlayerService添加到ServiceManager中的。
ServiceManager在这儿要特别的说明一下,它并没有继承BnServiceManager,而是由ServiceManager这个可执行程序所代替:
frameworks/base/cmds/servicemanager/service_manager.c
virtual status_t addService(const String16& name, const sp<IBinder>& service) { Parcel data, reply; data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());//android.so.IServicemanger data.writeString16(name); data.writeStrongBinder(service); status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply); return err == NO_ERROR ? reply.readInt32() : err; }这段代码的核心代码就是,remote->transact, 通过上一篇的学习,大家都知道到哪儿去看代码了吧,没错就是frameworks/base/libs/binder/BpBinder.cpp。
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::self() { if (gHaveTLS) { restart: const pthread_key_t k = gTLS; IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k); if (st) return st; return new IPCThreadState; } //省略后面部分代码 }
pthread_getspecific是从线程空间获取存储的对象,如果返回的为空,那么就创建一个IPCThreadState对象。
我们来看看PICThreadState的构造函数:
IPCThreadState::IPCThreadState() : mProcess(ProcessState::self()), mMyThreadId(androidGetTid()) { pthread_setspecific(gTLS, this); clearCaller(); mIn.setDataCapacity(256); mOut.setDataCapacity(256); }这构造函数中把自已加到了线程空间中,目的是为了线程内的对象共享,mIn是接收来自Binder驱动的数据,mOut是用来存储发往Binder驱动的数据。
好了,我们再来看一下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_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(">>>> SEND from 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 (reply) { err = waitForResponse(reply); } else { Parcel fakeReply; err = waitForResponse(&fakeReply); } 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 << "(none requested)" << endl; } } else { err = waitForResponse(NULL, NULL); } return err; }
writeTransactionData是把要传给Binder驱动的数据写到mOut中去,另外注意BC_TRANSACTION这命令,它会由Binder驱动直接执行。
接着看一下waitForResponse,这个从函数命可以知道它是等待Binder的反馈。
status_t IPCThreadState::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 << "Processing waitForResponse 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: { LOG_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)); LOG_ASSERT(err == NO_ERROR, "Not enough command data for brREPLY"); if (err != NO_ERROR) goto finish; 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; } }这个函数的代码全部贴出来,但是这里面的内容太重要了。
if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)这就是真正与Binder驱动沟通的地方,注意bwr,它是一个专门与Binder沟通的结构体binder_write_read。
struct binder_write_read { signed long write_size; signed long write_consumed; unsigned long write_buffer; signed long read_size; signed long read_consumed; unsigned long read_buffer; };里面包含了write和read部分的变量,所以它可以用于向Binder传递数据,也可以用于Binder传递返回的数据。
至于Driver是如何处理这现命令的,我们会另起一篇Blog来分析。
所以在talkWithDriver的最后就把bwr里面Binder返回的数据又写入到了mIn变量里,然后返回到waitForRespons。
在这儿我们先猜测一下,如果Drvier返回的command是BR_TRANSACTION_COMPLETE,那么addService ServiceManager客服端代码就分析完了。
接着,我们要分析Driver是如何找到ServiceManager,ServiceManager是如何等待Drvier的召唤的,如何保存这些Server的对象的,Driver又是返回给ServiceManager的客户端的。