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

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

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

  1. //File:ExampleService.cpp
  2. intr=defaultServiceManager()->addService(String16("byn.example"),newExampleService());

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

  1. //File:frameworks/base/cmds/servicemanager/service_manager.c
  2. intmain(intargc,char**argv)
  3. {
  4. structbinder_state*bs;
  5. void*svcmgr=BINDER_SERVICE_MANAGER;
  6. bs=binder_open(128*1024);
  7. if(binder_become_context_manager(bs)){
  8. LOGE("cannotbecomecontextmanager(%s)/n",strerror(errno));
  9. return-1;
  10. }
  11. svcmgr_handle=svcmgr;
  12. binder_loop(bs,svcmgr_handler);
  13. return0;
  14. }

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

  1. //File:frameworks/base/cmds/servicemanager/service_manager.c
  2. intbinder_become_context_manager(structbinder_state*bs)
  3. {
  4. returnioctl(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方法。让我们看一下它的源代码:

  1. //File:frameworks/base/libs/binder/IServiceManager.cpp
  2. classBpServiceManager:publicBpInterface<IServiceManager>
  3. {
  4. public:
  5. ......
  6. virtualstatus_taddService(constString16&name,constsp<IBinder>&service)
  7. {
  8. Parceldata,reply;
  9. data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
  10. data.writeString16(name);
  11. data.writeStrongBinder(service);
  12. status_terr=remote()->transact(ADD_SERVICE_TRANSACTION,data,&reply);
  13. returnerr==NO_ERROR?reply.readInt32():err;
  14. }
  15. ......
  16. }

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

  1. //File:frameworks/base/libs/binder/BpBinder.cpp
  2. status_tBpBinder::transact(
  3. uint32_tcode,constParcel&data,Parcel*reply,uint32_tflags)
  4. {
  5. //Onceabinderhasdied,itwillnevercomebacktolife.
  6. if(mAlive){
  7. status_tstatus=IPCThreadState::self()->transact(
  8. mHandle,code,data,reply,flags);
  9. if(status==DEAD_OBJECT)mAlive=0;
  10. returnstatus;
  11. }
  12. returnDEAD_OBJECT;
  13. }

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

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

  1. //File:frameworks/base/libs/binder/IPCThreadState.cpp
  2. status_tIPCThreadState::transact(int32_thandle,
  3. uint32_tcode,constParcel&data,
  4. Parcel*reply,uint32_tflags)
  5. {
  6. status_terr=data.errorCheck();
  7. flags|=TF_ACCEPT_FDS;
  8. IF_LOG_TRANSACTIONS(){
  9. TextOutput::Bundle_b(alog);
  10. alog<<"BC_TRANSACTIONthr"<<(void*)pthread_self()<<"/hand"
  11. <<handle<<"/code"<<TypeCode(code)<<":"
  12. <<indent<<data<<dedent<<endl;
  13. }
  14. if(err==NO_ERROR){
  15. LOG_ONEWAY(">>>>SENDfrompid%duid%d%s",getpid(),getuid(),
  16. (flags&TF_ONE_WAY)==0?"READREPLY":"ONEWAY");
  17. err=writeTransactionData(BC_TRANSACTION,flags,handle,code,data,NULL);
  18. }
  19. if(err!=NO_ERROR){
  20. if(reply)reply->setError(err);
  21. return(mLastError=err);
  22. }
  23. if((flags&TF_ONE_WAY)==0){
  24. if(reply){
  25. err=waitForResponse(reply);
  26. }else{
  27. ParcelfakeReply;
  28. err=waitForResponse(&fakeReply);
  29. }
  30. IF_LOG_TRANSACTIONS(){
  31. TextOutput::Bundle_b(alog);
  32. alog<<"BR_REPLYthr"<<(void*)pthread_self()<<"/hand"
  33. <<handle<<":";
  34. if(reply)alog<<indent<<*reply<<dedent<<endl;
  35. elsealog<<"(nonerequested)"<<endl;
  36. }
  37. }else{
  38. err=waitForResponse(NULL,NULL);
  39. }
  40. returnerr;
  41. }

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

  1. //File:frameworks/base/libs/binder/IPCThreadState.cpp
  2. status_tIPCThreadState::writeTransactionData(int32_tcmd,uint32_tbinderFlags,
  3. int32_thandle,uint32_tcode,constParcel&data,status_t*statusBuffer)
  4. {
  5. binder_transaction_datatr;
  6. tr.target.handle=handle;
  7. tr.code=code;
  8. tr.flags=binderFlags;
  9. conststatus_terr=data.errorCheck();
  10. if(err==NO_ERROR){
  11. tr.data_size=data.ipcDataSize();
  12. tr.data.ptr.buffer=data.ipcData();
  13. tr.offsets_size=data.ipcObjectsCount()*sizeof(size_t);
  14. tr.data.ptr.offsets=data.ipcObjects();
  15. }elseif(statusBuffer){
  16. tr.flags|=TF_STATUS_CODE;
  17. *statusBuffer=err;
  18. tr.data_size=sizeof(status_t);
  19. tr.data.ptr.buffer=statusBuffer;
  20. tr.offsets_size=0;
  21. tr.data.ptr.offsets=NULL;
  22. }else{
  23. return(mLastError=err);
  24. }
  25. mOut.writeInt32(cmd);
  26. mOut.write(&tr,sizeof(tr));
  27. returnNO_ERROR;
  28. }

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

  1. //File:frameworks/base/libs/binder/IPCThreadState.cpp
  2. status_tIPCThreadState::talkWithDriver(booldoReceive)
  3. {
  4. LOG_ASSERT(mProcess->mDriverFD>=0,"Binderdriverisnotopened");
  5. binder_write_readbwr;
  6. //Isthereadbufferempty?
  7. constboolneedRead=mIn.dataPosition()>=mIn.dataSize();
  8. //Wedon'twanttowriteanythingifwearestillreading
  9. //fromdataleftintheinputbufferandthecaller
  10. //hasrequestedtoreadthenextdata.
  11. constsize_toutAvail=(!doReceive||needRead)?mOut.dataSize():0;
  12. bwr.write_size=outAvail;
  13. bwr.write_buffer=(longunsignedint)mOut.data();
  14. //Thisiswhatwe'llread.
  15. if(doReceive&&needRead){
  16. bwr.read_size=mIn.dataCapacity();
  17. bwr.read_buffer=(longunsignedint)mIn.data();
  18. }else{
  19. bwr.read_size=0;
  20. }
  21. IF_LOG_COMMANDS(){
  22. TextOutput::Bundle_b(alog);
  23. if(outAvail!=0){
  24. alog<<"Sendingcommandstodriver:"<<indent;
  25. constvoid*cmds=(constvoid*)bwr.write_buffer;
  26. constvoid*end=((constuint8_t*)cmds)+bwr.write_size;
  27. alog<<HexDump(cmds,bwr.write_size)<<endl;
  28. while(cmds<end)cmds=printCommand(alog,cmds);
  29. alog<<dedent;
  30. }
  31. alog<<"Sizeofreceivebuffer:"<<bwr.read_size
  32. <<",needRead:"<<needRead<<",doReceive:"<<doReceive<<endl;
  33. }
  34. //Returnimmediatelyifthereisnothingtodo.
  35. if((bwr.write_size==0)&&(bwr.read_size==0))returnNO_ERROR;
  36. bwr.write_consumed=0;
  37. bwr.read_consumed=0;
  38. status_terr;
  39. do{
  40. IF_LOG_COMMANDS(){
  41. alog<<"Abouttoread/write,writesize="<<mOut.dataSize()<<endl;
  42. }
  43. #ifdefined(HAVE_ANDROID_OS)
  44. if(ioctl(mProcess->mDriverFD,BINDER_WRITE_READ,&bwr)>=0)
  45. err=NO_ERROR;
  46. else
  47. err=-errno;
  48. #else
  49. err=INVALID_OPERATION;
  50. #endif
  51. IF_LOG_COMMANDS(){
  52. alog<<"Finishedread/write,writesize="<<mOut.dataSize()<<endl;
  53. }
  54. }while(err==-EINTR);
  55. IF_LOG_COMMANDS(){
  56. alog<<"Ourerr:"<<(void*)err<<",writeconsumed:"
  57. <<bwr.write_consumed<<"(of"<<mOut.dataSize()
  58. <<"),readconsumed:"<<bwr.read_consumed<<endl;
  59. }
  60. if(err>=NO_ERROR){
  61. if(bwr.write_consumed>0){
  62. if(bwr.write_consumed<(ssize_t)mOut.dataSize())
  63. mOut.remove(0,bwr.write_consumed);
  64. else
  65. mOut.setDataSize(0);
  66. }
  67. if(bwr.read_consumed>0){
  68. mIn.setDataSize(bwr.read_consumed);
  69. mIn.setDataPosition(0);
  70. }
  71. IF_LOG_COMMANDS(){
  72. TextOutput::Bundle_b(alog);
  73. alog<<"Remainingdatasize:"<<mOut.dataSize()<<endl;
  74. alog<<"Receivedcommandsfromdriver:"<<indent;
  75. constvoid*cmds=mIn.data();
  76. constvoid*end=mIn.data()+mIn.dataSize();
  77. alog<<HexDump(cmds,mIn.dataSize())<<endl;
  78. while(cmds<end)cmds=printReturnCommand(alog,cmds);
  79. alog<<dedent;
  80. }
  81. returnNO_ERROR;
  82. }
  83. returnerr;
  84. }

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

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

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

  1. //File:frameworks/base/cmds/servicemanager/service_manager.c
  2. intsvcmgr_handler(structbinder_state*bs,
  3. structbinder_txn*txn,
  4. structbinder_io*msg,
  5. structbinder_io*reply)
  6. {
  7. structsvcinfo*si;
  8. uint16_t*s;
  9. unsignedlen;
  10. void*ptr;
  11. LOGI("[BYN]target=%pcode=%dpid=%duid=%d/n",
  12. txn->target,txn->code,txn->sender_pid,txn->sender_euid);
  13. if(txn->target!=svcmgr_handle)
  14. return-1;
  15. s=bio_get_string16(msg,&len);
  16. if((len!=(sizeof(svcmgr_id)/2))||
  17. memcmp(svcmgr_id,s,sizeof(svcmgr_id))){
  18. fprintf(stderr,"invalidid%s/n",str8(s));
  19. return-1;
  20. }
  21. switch(txn->code){
  22. caseSVC_MGR_GET_SERVICE:
  23. caseSVC_MGR_CHECK_SERVICE:
  24. s=bio_get_string16(msg,&len);
  25. ptr=do_find_service(bs,s,len);
  26. if(!ptr)
  27. break;
  28. bio_put_ref(reply,ptr);
  29. return0;
  30. caseSVC_MGR_ADD_SERVICE:
  31. s=bio_get_string16(msg,&len);
  32. ptr=bio_get_ref(msg);
  33. if(do_add_service(bs,s,len,ptr,txn->sender_euid))
  34. return-1;
  35. break;
  36. caseSVC_MGR_LIST_SERVICES:{
  37. unsignedn=bio_get_uint32(msg);
  38. si=svclist;
  39. while((n-->0)&&si)
  40. si=si->next;
  41. if(si){
  42. bio_put_string16(reply,si->name);
  43. return0;
  44. }
  45. return-1;
  46. }
  47. default:
  48. LOGE("unknowncode%d/n",txn->code);
  49. return-1;
  50. }
  51. bio_put_uint32(reply,0);
  52. return0;
  53. }

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

  1. //File:frameworks/base/cmds/servicemanager/service_manager.c
  2. intdo_add_service(structbinder_state*bs,
  3. uint16_t*s,unsignedlen,
  4. void*ptr,unsigneduid)
  5. {
  6. structsvcinfo*si;
  7. //LOGI("add_service('%s',%p)uid=%d/n",str8(s),ptr,uid);
  8. if(!ptr||(len==0)||(len>127))
  9. return-1;
  10. if(!svc_can_register(uid,s)){
  11. LOGE("add_service('%s',%p)uid=%d-PERMISSIONDENIED/n",
  12. str8(s),ptr,uid);
  13. return-1;
  14. }
  15. si=find_svc(s,len);
  16. if(si){
  17. if(si->ptr){
  18. LOGE("add_service('%s',%p)uid=%d-ALREADYREGISTERED/n",
  19. str8(s),ptr,uid);
  20. return-1;
  21. }
  22. si->ptr=ptr;
  23. }else{
  24. si=malloc(sizeof(*si)+(len+1)*sizeof(uint16_t));
  25. if(!si){
  26. LOGE("add_service('%s',%p)uid=%d-OUTOFMEMORY/n",
  27. str8(s),ptr,uid);
  28. return-1;
  29. }
  30. si->ptr=ptr;
  31. si->len=len;
  32. memcpy(si->name,s,(len+1)*sizeof(uint16_t));
  33. si->name[len]='/0';
  34. si->death.func=svcinfo_death;
  35. si->death.ptr=si;
  36. si->next=svclist;
  37. svclist=si;
  38. }
  39. binder_acquire(bs,ptr);
  40. binder_link_to_death(bs,ptr,&si->death);
  41. return0;
  42. }

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

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

你可能感兴趣的:(android)