接上一篇: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;
}
}
这个函数的代码全部贴出来,但是这里面的内容太重要了。
第一个函数可能就让你觉得发现了通往Binder的大道了talkWithDriver()
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的客户端的。