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

来源:互联网 发布:python 测试框架 编辑:程序博客网 时间:2024/05/17 03:15

http://blog.csdn.net/baiyanning/article/details/6197715

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

 

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

[cpp] view plaincopy
  1. // File: ExampleService.cpp     
  2. int r = defaultServiceManager()->addService(String16("byn.example"), new ExampleService());   

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

[cpp] view plaincopy
  1. // File: frameworks/base/cmds/servicemanager/service_manager.c  
  2. int main(int argc, char **argv)  
  3. {  
  4.     struct binder_state *bs;  
  5.     void *svcmgr = BINDER_SERVICE_MANAGER;  
  6.   
  7.     bs = binder_open(128*1024);  
  8.   
  9.     if (binder_become_context_manager(bs)) {  
  10.         LOGE("cannot become context manager (%s)/n", strerror(errno));  
  11.         return -1;  
  12.     }  
  13.   
  14.     svcmgr_handle = svcmgr;  
  15.     binder_loop(bs, svcmgr_handler);  
  16.     return 0;  
  17. }  

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

[cpp] view plaincopy
  1. // File: frameworks/base/cmds/servicemanager/service_manager.c   
  2. int binder_become_context_manager(struct binder_state *bs)  
  3. {  
  4.     return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);  
  5. }  

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

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

 

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

[cpp] view plaincopy
  1. // File: frameworks/base/libs/binder/IServiceManager.cpp  
  2. class BpServiceManager : public BpInterface<IServiceManager>  
  3. {  
  4. public:  
  5.     ......  
  6.     virtual status_t addService(const String16& name, const sp<IBinder>& service)  
  7.     {  
  8.         Parcel data, reply;  
  9.         data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());  
  10.         data.writeString16(name);  
  11.         data.writeStrongBinder(service);  
  12.         status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);  
  13.         return err == NO_ERROR ? reply.readInt32() : err;  
  14.     }  
  15.     ......  
  16. }  

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

[cpp] view plaincopy
  1. // File: frameworks/base/libs/binder/BpBinder.cpp  
  2. status_t BpBinder::transact(  
  3.     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)  
  4. {  
  5.     // Once a binder has died, it will never come back to life.  
  6.     if (mAlive) {  
  7.         status_t status = IPCThreadState::self()->transact(  
  8.             mHandle, code, data, reply, flags);  
  9.         if (status == DEAD_OBJECT) mAlive = 0;  
  10.         return status;  
  11.     }  
  12.   
  13.     return DEAD_OBJECT;  
  14. }  

    我们看到该方法是通过调用IPCThreadState类的同名方法继续传递请求。这里需要解释一下IPCThreadState类的作用。

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

[cpp] view plaincopy
  1. // File: frameworks/base/libs/binder/IPCThreadState.cpp  
  2. status_t IPCThreadState::transact(int32_t handle,  
  3.                                   uint32_t code, const Parcel& data,  
  4.                                   Parcel* reply, uint32_t flags)  
  5. {  
  6.     status_t err = data.errorCheck();  
  7.   
  8.     flags |= TF_ACCEPT_FDS;  
  9.   
  10.     IF_LOG_TRANSACTIONS() {  
  11.         TextOutput::Bundle _b(alog);  
  12.         alog << "BC_TRANSACTION thr " << (void*)pthread_self() << " / hand "  
  13.             << handle << " / code " << TypeCode(code) << ": "  
  14.             << indent << data << dedent << endl;  
  15.     }  
  16.       
  17.     if (err == NO_ERROR) {  
  18.         LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(),  
  19.             (flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY");  
  20.         err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);  
  21.     }  
  22.       
  23.     if (err != NO_ERROR) {  
  24.         if (reply) reply->setError(err);  
  25.         return (mLastError = err);  
  26.     }  
  27.       
  28.     if ((flags & TF_ONE_WAY) == 0) {  
  29.         if (reply) {  
  30.             err = waitForResponse(reply);  
  31.         } else {  
  32.             Parcel fakeReply;  
  33.             err = waitForResponse(&fakeReply);  
  34.         }  
  35.           
  36.         IF_LOG_TRANSACTIONS() {  
  37.             TextOutput::Bundle _b(alog);  
  38.             alog << "BR_REPLY thr " << (void*)pthread_self() << " / hand "  
  39.                 << handle << ": ";  
  40.             if (reply) alog << indent << *reply << dedent << endl;  
  41.             else alog << "(none requested)" << endl;  
  42.         }  
  43.     } else {  
  44.         err = waitForResponse(NULL, NULL);  
  45.     }  
  46.       
  47.     return err;  
  48. }  

    这里调用了writeTransactionData()方法来完成请求,我们再看一下writeTransactionData()方法的定义:

[cpp] view plaincopy
  1. // File: frameworks/base/libs/binder/IPCThreadState.cpp  
  2. status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,  
  3.     int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)  
  4. {  
  5.     binder_transaction_data tr;  
  6.   
  7.     tr.target.handle = handle;  
  8.     tr.code = code;  
  9.     tr.flags = binderFlags;  
  10.       
  11.     const status_t err = data.errorCheck();  
  12.     if (err == NO_ERROR) {  
  13.         tr.data_size = data.ipcDataSize();  
  14.         tr.data.ptr.buffer = data.ipcData();  
  15.         tr.offsets_size = data.ipcObjectsCount()*sizeof(size_t);  
  16.         tr.data.ptr.offsets = data.ipcObjects();  
  17.     } else if (statusBuffer) {  
  18.         tr.flags |= TF_STATUS_CODE;  
  19.         *statusBuffer = err;  
  20.         tr.data_size = sizeof(status_t);  
  21.         tr.data.ptr.buffer = statusBuffer;  
  22.         tr.offsets_size = 0;  
  23.         tr.data.ptr.offsets = NULL;  
  24.     } else {  
  25.         return (mLastError = err);  
  26.     }  
  27.       
  28.     mOut.writeInt32(cmd);  
  29.     mOut.write(&tr, sizeof(tr));  
  30.       
  31.     return NO_ERROR;  
  32. }  

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

[cpp] view plaincopy
  1. // File: frameworks/base/libs/binder/IPCThreadState.cpp  
  2. status_t IPCThreadState::talkWithDriver(bool doReceive)  
  3. {  
  4.     LOG_ASSERT(mProcess->mDriverFD >= 0, "Binder driver is not opened");  
  5.       
  6.     binder_write_read bwr;  
  7.       
  8.     // Is the read buffer empty?  
  9.     const bool needRead = mIn.dataPosition() >= mIn.dataSize();  
  10.       
  11.     // We don't want to write anything if we are still reading  
  12.     // from data left in the input buffer and the caller  
  13.     // has requested to read the next data.  
  14.     const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;  
  15.       
  16.     bwr.write_size = outAvail;  
  17.     bwr.write_buffer = (long unsigned int)mOut.data();  
  18.   
  19.     // This is what we'll read.  
  20.     if (doReceive && needRead) {  
  21.         bwr.read_size = mIn.dataCapacity();  
  22.         bwr.read_buffer = (long unsigned int)mIn.data();  
  23.     } else {  
  24.         bwr.read_size = 0;  
  25.     }  
  26.       
  27.     IF_LOG_COMMANDS() {  
  28.         TextOutput::Bundle _b(alog);  
  29.         if (outAvail != 0) {  
  30.             alog << "Sending commands to driver: " << indent;  
  31.             const void* cmds = (const void*)bwr.write_buffer;  
  32.             const void* end = ((const uint8_t*)cmds)+bwr.write_size;  
  33.             alog << HexDump(cmds, bwr.write_size) << endl;  
  34.             while (cmds < end) cmds = printCommand(alog, cmds);  
  35.             alog << dedent;  
  36.         }  
  37.         alog << "Size of receive buffer: " << bwr.read_size  
  38.             << ", needRead: " << needRead << ", doReceive: " << doReceive << endl;  
  39.     }  
  40.       
  41.     // Return immediately if there is nothing to do.  
  42.     if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;  
  43.       
  44.     bwr.write_consumed = 0;  
  45.     bwr.read_consumed = 0;  
  46.     status_t err;  
  47.     do {  
  48.         IF_LOG_COMMANDS() {  
  49.             alog << "About to read/write, write size = " << mOut.dataSize() << endl;  
  50.         }  
  51. #if defined(HAVE_ANDROID_OS)  
  52.         if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)  
  53.             err = NO_ERROR;  
  54.         else  
  55.             err = -errno;  
  56. #else  
  57.         err = INVALID_OPERATION;  
  58. #endif  
  59.         IF_LOG_COMMANDS() {  
  60.             alog << "Finished read/write, write size = " << mOut.dataSize() << endl;  
  61.         }  
  62.     } while (err == -EINTR);  
  63.       
  64.     IF_LOG_COMMANDS() {  
  65.         alog << "Our err: " << (void*)err << ", write consumed: "  
  66.             << bwr.write_consumed << " (of " << mOut.dataSize()  
  67.             << "), read consumed: " << bwr.read_consumed << endl;  
  68.     }  
  69.   
  70.     if (err >= NO_ERROR) {  
  71.         if (bwr.write_consumed > 0) {  
  72.             if (bwr.write_consumed < (ssize_t)mOut.dataSize())  
  73.                 mOut.remove(0, bwr.write_consumed);  
  74.             else  
  75.                 mOut.setDataSize(0);  
  76.         }  
  77.         if (bwr.read_consumed > 0) {  
  78.             mIn.setDataSize(bwr.read_consumed);  
  79.             mIn.setDataPosition(0);  
  80.         }  
  81.         IF_LOG_COMMANDS() {  
  82.             TextOutput::Bundle _b(alog);  
  83.             alog << "Remaining data size: " << mOut.dataSize() << endl;  
  84.             alog << "Received commands from driver: " << indent;  
  85.             const void* cmds = mIn.data();  
  86.             const void* end = mIn.data() + mIn.dataSize();  
  87.             alog << HexDump(cmds, mIn.dataSize()) << endl;  
  88.             while (cmds < end) cmds = printReturnCommand(alog, cmds);  
  89.             alog << dedent;  
  90.         }  
  91.         return NO_ERROR;  
  92.     }  
  93.       
  94.     return err;  
  95. }  

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

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

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

[cpp] view plaincopy
  1. // File: frameworks/base/cmds/servicemanager/service_manager.c  
  2. int svcmgr_handler(struct binder_state *bs,  
  3.                    struct binder_txn *txn,  
  4.                    struct binder_io *msg,  
  5.                    struct binder_io *reply)  
  6. {  
  7.     struct svcinfo *si;  
  8.     uint16_t *s;  
  9.     unsigned len;  
  10.     void *ptr;  
  11.   
  12.     LOGI("[BYN]target=%p code=%d pid=%d uid=%d/n",  
  13.          txn->target, txn->code, txn->sender_pid, txn->sender_euid);  
  14.   
  15.     if (txn->target != svcmgr_handle)  
  16.         return -1;  
  17.   
  18.     s = bio_get_string16(msg, &len);  
  19.   
  20.     if ((len != (sizeof(svcmgr_id) / 2)) ||  
  21.         memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {  
  22.         fprintf(stderr,"invalid id %s/n", str8(s));  
  23.         return -1;  
  24.     }  
  25.   
  26.     switch(txn->code) {  
  27.     case SVC_MGR_GET_SERVICE:  
  28.     case SVC_MGR_CHECK_SERVICE:  
  29.         s = bio_get_string16(msg, &len);  
  30.         ptr = do_find_service(bs, s, len);  
  31.         if (!ptr)  
  32.             break;  
  33.         bio_put_ref(reply, ptr);  
  34.         return 0;  
  35.   
  36.     case SVC_MGR_ADD_SERVICE:  
  37.         s = bio_get_string16(msg, &len);  
  38.         ptr = bio_get_ref(msg);  
  39.         if (do_add_service(bs, s, len, ptr, txn->sender_euid))  
  40.             return -1;  
  41.         break;  
  42.   
  43.     case SVC_MGR_LIST_SERVICES: {  
  44.         unsigned n = bio_get_uint32(msg);  
  45.   
  46.         si = svclist;  
  47.         while ((n-- > 0) && si)  
  48.             si = si->next;  
  49.         if (si) {  
  50.             bio_put_string16(reply, si->name);  
  51.             return 0;  
  52.         }  
  53.         return -1;  
  54.     }  
  55.     default:  
  56.         LOGE("unknown code %d/n", txn->code);  
  57.         return -1;  
  58.     }  
  59.   
  60.     bio_put_uint32(reply, 0);  
  61.     return 0;  
  62. }  

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

[cpp] view plaincopy
  1. // File: frameworks/base/cmds/servicemanager/service_manager.c  
  2. int do_add_service(struct binder_state *bs,  
  3.                    uint16_t *s, unsigned len,  
  4.                    void *ptr, unsigned uid)  
  5. {  
  6.     struct svcinfo *si;  
  7. //    LOGI("add_service('%s',%p) uid=%d/n", str8(s), ptr, uid);  
  8.   
  9.     if (!ptr || (len == 0) || (len > 127))  
  10.         return -1;  
  11.   
  12.     if (!svc_can_register(uid, s)) {  
  13.         LOGE("add_service('%s',%p) uid=%d - PERMISSION DENIED/n",  
  14.              str8(s), ptr, uid);  
  15.         return -1;  
  16.     }  
  17.   
  18.     si = find_svc(s, len);  
  19.     if (si) {  
  20.         if (si->ptr) {  
  21.             LOGE("add_service('%s',%p) uid=%d - ALREADY REGISTERED/n",  
  22.                  str8(s), ptr, uid);  
  23.             return -1;  
  24.         }  
  25.         si->ptr = ptr;  
  26.     } else {  
  27.         si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));  
  28.         if (!si) {  
  29.             LOGE("add_service('%s',%p) uid=%d - OUT OF MEMORY/n",  
  30.                  str8(s), ptr, uid);  
  31.             return -1;  
  32.         }  
  33.         si->ptr = ptr;  
  34.         si->len = len;  
  35.         memcpy(si->name, s, (len + 1) * sizeof(uint16_t));  
  36.         si->name[len] = '/0';  
  37.         si->death.func = svcinfo_death;  
  38.         si->death.ptr = si;  
  39.         si->next = svclist;  
  40.         svclist = si;  
  41.     }  
  42.   
  43.     binder_acquire(bs, ptr);  
  44.     binder_link_to_death(bs, ptr, &si->death);  
  45.     return 0;  
  46. }  
 

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

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