Android Binder Mechanism (3) -- 如何向系统注册Service

    在这篇文章中,我们将深入剖析一下如何向系统注册Service。

 

    在第一篇文章的例子中,ExampleService通过如下语句向系统注册服务。

// File: ExampleService.cpp int r = defaultServiceManager()->addService(String16("byn.example"), new ExampleService());

    在上一篇文章中,我们已经知道通过调用defaultServiceManager()全局函数可以获得当前进程的ServiceManager代理对象的引用。在深入剖析addService()方法之前,让我们先了解一下ServiceManager是如何启动的。首先来看一下它的源代码:

// File: frameworks/base/cmds/servicemanager/service_manager.c int main(int argc, char **argv) { struct binder_state *bs; void *svcmgr = BINDER_SERVICE_MANAGER; bs = binder_open(128*1024); if (binder_become_context_manager(bs)) { LOGE("cannot become context manager (%s)/n", strerror(errno)); return -1; } svcmgr_handle = svcmgr; binder_loop(bs, svcmgr_handler); return 0; }

    ServiceManager本身是一个系统进程,是Android核心程序。从它的main函数来看,它首先调用binder_open()函数打开binder设备(/dev/binder),接着调用binder_become_context_manager()函数,将自己变为系统服务的“管理员”。我们看一下binder_become_context_manager()函数的源代码:

// File: frameworks/base/cmds/servicemanager/service_manager.c int binder_become_context_manager(struct binder_state *bs) { return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0); }

    可以看到以BINDER_SET_CONTEXT_MGR为参数进行ioctl系统调用,就可以将自身设置成系统服务的“管理员”,即ServiceManager。

    最后,ServiceManager调用binder_loop进入到循环状态,并提供了一个回调函数svcmgr_handler(),等待用户的请求。

 

    现在让我们剖析一下向系统注册Service的过程吧。首先,调用defaultServiceManager()全局函数获得的是ServiceManager代理对象的引用,所以这里的调用的addService方法是代理对象的方法,而不是真正的ServiceManager的addService方法。让我们看一下它的源代码:

// File: frameworks/base/libs/binder/IServiceManager.cpp class BpServiceManager : public BpInterface<IServiceManager> { public: ...... virtual status_t addService(const String16& name, const sp<IBinder>& service) { Parcel data, reply; data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); data.writeString16(name); data.writeStrongBinder(service); status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply); return err == NO_ERROR ? reply.readInt32() : err; } ...... }

    这里是以ADD_SERVICE_TRANSACTION为命令代码调用的transact()方法。因为ServiceManager代理对象BpServiceManager继承自BpBinder,所以这里调用的是BpBinder::transact(),我们看一下它的源代码:

// File: 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对象,它的作用是维护当前进程中所有对binder设备(/dev/binder)的I/O操作,也就是说一个进程要想通过binder机制与另外一个进程进行通信,最终都是要通过IPCThreadState对象来完成的。有了IPCThreadState这层封装之后,应用程序就不需要通过ioctl同binder设备直接打交道了。下面让我们来看一下IPCThreadState类的transact方法的源代码:

// File: frameworks/base/libs/binder/IPCThreadState.cpp 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()方法来完成请求,我们再看一下writeTransactionData()方法的定义:

// File: frameworks/base/libs/binder/IPCThreadState.cpp 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.handle = handle; tr.code = code; tr.flags = binderFlags; 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; }

    最终是在这里将命令和数据封装好之后写入待发送的队列(mOut.writeInt32(cmd),mOut.write(&tr, sizeof(tr)))。回到IPCThreadState类的transact()方法。writeTransactionData()方法返回之后,会通过调用waitForResponse()方法发送请求并等待返回结果。而waitForResponse()方法会调用IPCThreadState::talkWithDriver()方法发送请求并取回返回值。我们看一下talkWithDriver()方法的源代码:

// File: frameworks/base/libs/binder/IPCThreadState.cpp status_t IPCThreadState::talkWithDriver(bool doReceive) { LOG_ASSERT(mProcess->mDriverFD >= 0, "Binder driver is not opened"); 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 = (long unsigned int)mOut.data(); // This is what we'll read. if (doReceive && needRead) { bwr.read_size = mIn.dataCapacity(); bwr.read_buffer = (long unsigned int)mIn.data(); } else { bwr.read_size = 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(HAVE_ANDROID_OS) if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0) err = NO_ERROR; else err = -errno; #else err = INVALID_OPERATION; #endif IF_LOG_COMMANDS() { alog << "Finished read/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() << "), read consumed: " << 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 data size: " << mOut.dataSize() << endl; alog << "Received commands 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; }

    talkWithDriver()方法会将待发送的请求(之前已经存放在mOut对象中)封装到一个binder_write_read类型的结构体bwr中,并调用ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)完成发送请求。接下来的工作就由内核空间来完成了。此进程当前会阻塞在ioctl这里,直到有返回值返回。由此可见,通过binder机制进行的IPC通信是一个同步过程。这一点非常重要。

    客户端的程序我们暂时先分析到这里,现在让我们看看服务端在收到这一请求之后都会做哪些处理。

    前面提到,ServiceManager的main函数中注册了回调函数svcmgr_handler(),因此上面的请求通过binder设备发送到ServiceManager这一端的时候,该函数会被调用。我们看一下它的源代码:

// File: frameworks/base/cmds/servicemanager/service_manager.c int svcmgr_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; LOGI("[BYN]target=%p code=%d pid=%d uid=%d/n", txn->target, txn->code, txn->sender_pid, txn->sender_euid); if (txn->target != svcmgr_handle) return -1; 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); 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); if (do_add_service(bs, s, len, ptr, txn->sender_euid)) 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: LOGE("unknown code %d/n", txn->code); return -1; } bio_put_uint32(reply, 0); return 0; }

    由于调用的是addService服务,所以会走到SVC_MGR_ADD_SERVICE分支,调用do_add_service()函数。我们看一下它的源代码:

// File: frameworks/base/cmds/servicemanager/service_manager.c int do_add_service(struct binder_state *bs, uint16_t *s, unsigned len, void *ptr, unsigned uid) { struct svcinfo *si; // LOGI("add_service('%s',%p) uid=%d/n", str8(s), ptr, uid); if (!ptr || (len == 0) || (len > 127)) return -1; if (!svc_can_register(uid, s)) { LOGE("add_service('%s',%p) uid=%d - PERMISSION DENIED/n", str8(s), ptr, uid); return -1; } si = find_svc(s, len); if (si) { if (si->ptr) { LOGE("add_service('%s',%p) uid=%d - ALREADY REGISTERED/n", str8(s), ptr, uid); return -1; } si->ptr = ptr; } else { si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t)); if (!si) { LOGE("add_service('%s',%p) uid=%d - OUT OF MEMORY/n", str8(s), ptr, uid); return -1; } si->ptr = ptr; si->len = len; memcpy(si->name, s, (len + 1) * sizeof(uint16_t)); si->name[len] = '/0'; si->death.func = svcinfo_death; si->death.ptr = si; si->next = svclist; svclist = si; } binder_acquire(bs, ptr); binder_link_to_death(bs, ptr, &si->death); return 0; } 

    这里首先判断一下是否有权限注册服务(svc_can_register(uid, s)),如果可以的话,再判断该服务是否已经注册过;如果没有注册过的话,就构造一个svcinfo对象,并将它添加到svclist链表中。最后通知binder设备:有一个新的Service注册进来。

    服务器端返回之后,客户端被解除阻塞(ioctl系统调用),然后逐层返回,从而完成了注册服务的请求。

 

你可能感兴趣的:(android,struct,manager,service,buffer,transactions)