上一篇文章中我们讨论了如何向系统注册Service。本篇文章我们将讨论如何使用这个已注册的系统Service。

在本系列文章的第一篇中,客户端应用程序使用如下两条语句取得了ExampleService代理对象的引用。

view plain copy to clipboard print ?
  1. sp<IServiceManager>sm=defaultServiceManager();
  2. binder=sm->getService(String16("byn.example"));

第一句我们之前已经详细解释过了,全局函数defaultServiceManager()返回的是ServiceManager代理对象的引用。第二句话以ExampleService的方法名为参数调用getService()方法,返回的是ExampleService代理对象的引用。这个过程和上一篇文章介绍的addService的过程是非常类似的,这里就不详细展开了。

客户应用程序获得了ExampleService代理对象的引用之后,通过如下语句调用服务:

view plain copy to clipboard print ?
  1. data.writeInt32(getpid());
  2. data.writeInt32(n);
  3. binder->transact(0,data,&reply);

第一句话写入当前进程的进程ID,这里只是为了输出log用,没有实际意义;

第二句话写入参数n;

最后一句话调用ExampleService代理对象的transact方法发送请求。第一个参数0是请求代码(code),如果一个服务提供了多个API接口,那么服务器端就通过这个参数区分调用的是哪一个API;第二个参数打包后的调用参数;最后一个参数保存返回值。因为ExampleService代理对象继承自BpBinder,所以这里调用的是BpBinder::transact()方法,进而调用IPCThreadState::transact()方法。这个过程在上一篇文章中已经介绍过。

现在我们重点剖析一下服务器端的情况。

服务器端在向系统注册服务之后,首先调用ProcessState::self()->startThreadPool()方法启动一个线程池;然后调用IPCThreadState::self()->joinThreadPool()方法进入一个无限循环,等待其它进程的服务请求。我们看一下joinThreadPool方法的源代码:

view plain copy to clipboard print ?
  1. //File:frameworks/base/libs/binder/IPCThreadState.cpp
  2. voidIPCThreadState::joinThreadPool(boolisMain)
  3. {
  4. LOG_THREADPOOL("****THREAD%p(PID%d)ISJOININGTHETHREADPOOL/n",(void*)pthread_self(),getpid());
  5. mOut.writeInt32(isMain?BC_ENTER_LOOPER:BC_REGISTER_LOOPER);
  6. status_tresult;
  7. do{
  8. int32_tcmd;
  9. //Whenwe'veclearedtheincomingcommandqueue,processanypendingderefs
  10. if(mIn.dataPosition()>=mIn.dataSize()){
  11. size_tnumPending=mPendingWeakDerefs.size();
  12. if(numPending>0){
  13. for(size_ti=0;i<numPending;i++){
  14. RefBase::weakref_type*refs=mPendingWeakDerefs[i];
  15. refs->decWeak(mProcess.get());
  16. }
  17. mPendingWeakDerefs.clear();
  18. }
  19. numPending=mPendingStrongDerefs.size();
  20. if(numPending>0){
  21. for(size_ti=0;i<numPending;i++){
  22. BBinder*obj=mPendingStrongDerefs[i];
  23. obj->decStrong(mProcess.get());
  24. }
  25. mPendingStrongDerefs.clear();
  26. }
  27. }
  28. //nowgetthenextcommandtobeprocessed,waitingifnecessary
  29. result=talkWithDriver();
  30. if(result>=NO_ERROR){
  31. size_tIN=mIn.dataAvail();
  32. if(IN<sizeof(int32_t))continue;
  33. cmd=mIn.readInt32();
  34. IF_LOG_COMMANDS(){
  35. alog<<"Processingtop-levelCommand:"
  36. <<getReturnString(cmd)<<endl;
  37. }
  38. result=executeCommand(cmd);
  39. }
  40. //Afterexecutingthecommand,ensurethatthethreadisreturnedtothe
  41. //defaultcgroupandprioritybeforerejoiningthepool.Thisisafailsafe
  42. //incasethecommandimplementationfailedtoproperlyrestorethethread's
  43. //schedulingparametersuponcompletion.
  44. intmy_id;
  45. #ifdefHAVE_GETTID
  46. my_id=gettid();
  47. #else
  48. my_id=getpid();
  49. #endif
  50. if(!set_sched_policy(my_id,SP_FOREGROUND)){
  51. //success;resetthepriorityaswell
  52. setpriority(PRIO_PROCESS,my_id,ANDROID_PRIORITY_NORMAL);
  53. }
  54. //Letthisthreadexitthethreadpoolifitisnolonger
  55. //neededanditisnotthemainprocessthread.
  56. if(result==TIMED_OUT&&!isMain){
  57. break;
  58. }
  59. }while(result!=-ECONNREFUSED&&result!=-EBADF);
  60. LOG_THREADPOOL("****THREAD%p(PID%d)ISLEAVINGTHETHREADPOOLerr=%p/n",
  61. (void*)pthread_self(),getpid(),(void*)result);
  62. mOut.writeInt32(BC_EXIT_LOOPER);
  63. talkWithDriver(false);
  64. }

在joinThreadPool()方法中,通过调用talkWithDriver方法与binder设备进行通信,通常Service进程会阻塞在这里;一旦客户请求到来,该方法返回,并调用后面的executeCommand()方法进行处理。我们看一下executeCommand()方法的源代码:

view plain copy to clipboard print ?
  1. //File:frameworks/base/libs/binder/IPCThreadState.cpp
  2. status_tIPCThreadState::executeCommand(int32_tcmd)
  3. {
  4. BBinder*obj;
  5. RefBase::weakref_type*refs;
  6. status_tresult=NO_ERROR;
  7. switch(cmd){
  8. caseBR_ERROR:
  9. result=mIn.readInt32();
  10. break;
  11. caseBR_OK:
  12. break;
  13. caseBR_ACQUIRE:
  14. refs=(RefBase::weakref_type*)mIn.readInt32();
  15. obj=(BBinder*)mIn.readInt32();
  16. LOG_ASSERT(refs->refBase()==obj,
  17. "BR_ACQUIRE:object%pdoesnotmatchcookie%p(expected%p)",
  18. refs,obj,refs->refBase());
  19. obj->incStrong(mProcess.get());
  20. IF_LOG_REMOTEREFS(){
  21. LOG_REMOTEREFS("BR_ACQUIREfromdriveron%p",obj);
  22. obj->printRefs();
  23. }
  24. mOut.writeInt32(BC_ACQUIRE_DONE);
  25. mOut.writeInt32((int32_t)refs);
  26. mOut.writeInt32((int32_t)obj);
  27. break;
  28. caseBR_RELEASE:
  29. refs=(RefBase::weakref_type*)mIn.readInt32();
  30. obj=(BBinder*)mIn.readInt32();
  31. LOG_ASSERT(refs->refBase()==obj,
  32. "BR_RELEASE:object%pdoesnotmatchcookie%p(expected%p)",
  33. refs,obj,refs->refBase());
  34. IF_LOG_REMOTEREFS(){
  35. LOG_REMOTEREFS("BR_RELEASEfromdriveron%p",obj);
  36. obj->printRefs();
  37. }
  38. mPendingStrongDerefs.push(obj);
  39. break;
  40. caseBR_INCREFS:
  41. refs=(RefBase::weakref_type*)mIn.readInt32();
  42. obj=(BBinder*)mIn.readInt32();
  43. refs->incWeak(mProcess.get());
  44. mOut.writeInt32(BC_INCREFS_DONE);
  45. mOut.writeInt32((int32_t)refs);
  46. mOut.writeInt32((int32_t)obj);
  47. break;
  48. caseBR_DECREFS:
  49. refs=(RefBase::weakref_type*)mIn.readInt32();
  50. obj=(BBinder*)mIn.readInt32();
  51. //NOTE:Thisassertionisnotvalid,becausetheobjectmayno
  52. //longerexist(thusthe(BBinder*)castaboveresultinginadifferent
  53. //memoryaddress).
  54. //LOG_ASSERT(refs->refBase()==obj,
  55. //"BR_DECREFS:object%pdoesnotmatchcookie%p(expected%p)",
  56. //refs,obj,refs->refBase());
  57. mPendingWeakDerefs.push(refs);
  58. break;
  59. caseBR_ATTEMPT_ACQUIRE:
  60. refs=(RefBase::weakref_type*)mIn.readInt32();
  61. obj=(BBinder*)mIn.readInt32();
  62. {
  63. constboolsuccess=refs->attemptIncStrong(mProcess.get());
  64. LOG_ASSERT(success&&refs->refBase()==obj,
  65. "BR_ATTEMPT_ACQUIRE:object%pdoesnotmatchcookie%p(expected%p)",
  66. refs,obj,refs->refBase());
  67. mOut.writeInt32(BC_ACQUIRE_RESULT);
  68. mOut.writeInt32((int32_t)success);
  69. }
  70. break;
  71. caseBR_TRANSACTION:
  72. {
  73. binder_transaction_datatr;
  74. result=mIn.read(&tr,sizeof(tr));
  75. LOG_ASSERT(result==NO_ERROR,
  76. "NotenoughcommanddataforbrTRANSACTION");
  77. if(result!=NO_ERROR)break;
  78. Parcelbuffer;
  79. buffer.ipcSetDataReference(
  80. reinterpret_cast<constuint8_t*>(tr.data.ptr.buffer),
  81. tr.data_size,
  82. reinterpret_cast<constsize_t*>(tr.data.ptr.offsets),
  83. tr.offsets_size/sizeof(size_t),freeBuffer,this);
  84. constpid_torigPid=mCallingPid;
  85. constuid_torigUid=mCallingUid;
  86. mCallingPid=tr.sender_pid;
  87. mCallingUid=tr.sender_euid;
  88. //LOGI(">>>>TRANSACTfrompid%duid%d/n",mCallingPid,mCallingUid);
  89. Parcelreply;
  90. IF_LOG_TRANSACTIONS(){
  91. TextOutput::Bundle_b(alog);
  92. alog<<"BR_TRANSACTIONthr"<<(void*)pthread_self()
  93. <<"/obj"<<tr.target.ptr<<"/code"
  94. <<TypeCode(tr.code)<<":"<<indent<<buffer
  95. <<dedent<<endl
  96. <<"Dataaddr="
  97. <<reinterpret_cast<constuint8_t*>(tr.data.ptr.buffer)
  98. <<",offsetsaddr="
  99. <<reinterpret_cast<constsize_t*>(tr.data.ptr.offsets)<<endl;
  100. }
  101. if(tr.target.ptr){
  102. sp<BBinder>b((BBinder*)tr.cookie);
  103. conststatus_terror=b->transact(tr.code,buffer,&reply,0);
  104. if(error<NO_ERROR)reply.setError(error);
  105. }else{
  106. conststatus_terror=the_context_object->transact(tr.code,buffer,&reply,0);
  107. if(error<NO_ERROR)reply.setError(error);
  108. }
  109. //LOGI("<<<<TRANSACTfrompid%drestorepid%duid%d/n",
  110. //mCallingPid,origPid,origUid);
  111. if((tr.flags&TF_ONE_WAY)==0){
  112. LOG_ONEWAY("Sendingreplyto%d!",mCallingPid);
  113. sendReply(reply,0);
  114. }else{
  115. LOG_ONEWAY("NOTsendingreplyto%d!",mCallingPid);
  116. }
  117. mCallingPid=origPid;
  118. mCallingUid=origUid;
  119. IF_LOG_TRANSACTIONS(){
  120. TextOutput::Bundle_b(alog);
  121. alog<<"BC_REPLYthr"<<(void*)pthread_self()<<"/obj"
  122. <<tr.target.ptr<<":"<<indent<<reply<<dedent<<endl;
  123. }
  124. }
  125. break;
  126. caseBR_DEAD_BINDER:
  127. {
  128. BpBinder*proxy=(BpBinder*)mIn.readInt32();
  129. proxy->sendObituary();
  130. mOut.writeInt32(BC_DEAD_BINDER_DONE);
  131. mOut.writeInt32((int32_t)proxy);
  132. }break;
  133. caseBR_CLEAR_DEATH_NOTIFICATION_DONE:
  134. {
  135. BpBinder*proxy=(BpBinder*)mIn.readInt32();
  136. proxy->getWeakRefs()->decWeak(proxy);
  137. }break;
  138. caseBR_FINISHED:
  139. result=TIMED_OUT;
  140. break;
  141. caseBR_NOOP:
  142. break;
  143. caseBR_SPAWN_LOOPER:
  144. mProcess->spawnPooledThread(false);
  145. break;
  146. default:
  147. printf("***BADCOMMAND%dreceivedfromBinderdriver/n",cmd);
  148. result=UNKNOWN_ERROR;
  149. break;
  150. }
  151. if(result!=NO_ERROR){
  152. mLastError=result;
  153. }
  154. returnresult;
  155. }

这里,函数会根据一系列枚举值作相应的处理。在binder协议中:

BR_XXX等宏为BinderDriverReturnProtocol,表示Binder驱动返回协议。
BC_XXX等宏为BinderDriverCommandProtocol,表示Binder驱动命令协议。

因为这里是收到命令请求后要做相应的处理,所以这里的宏都是以BR开头的。这里会走到BR_TRANSACTION这个分支,调用BBinder的transact()方法做处理(b->transact(tr.code, buffer, &reply, 0))。我们看一下BBinder::transact()方法的源代码:

view plain copy to clipboard print ?
  1. //File:frameworks/base/libs/binder/binder.cpp
  2. status_tBBinder::transact(
  3. uint32_tcode,constParcel&data,Parcel*reply,uint32_tflags)
  4. {
  5. data.setDataPosition(0);
  6. status_terr=NO_ERROR;
  7. switch(code){
  8. casePING_TRANSACTION:
  9. reply->writeInt32(pingBinder());
  10. break;
  11. default:
  12. err=onTransact(code,data,reply,flags);
  13. break;
  14. }
  15. if(reply!=NULL){
  16. reply->setDataPosition(0);
  17. }
  18. returnerr;
  19. }

我们看到调用的是虚函数onTransact()。因为ExampleService类继承自BBinder类,并改写了onTransact()方法,所以这里会调用到ExampleService::onTransact()方法。

view plain copy to clipboard print ?
  1. status_tExampleService::onTransact(uint32_tcode,constParcel&data,Parcel*reply,uint32_tflags)
  2. {
  3. switch(code)
  4. {
  5. case0:{
  6. pid_tpid=data.readInt32();
  7. intnum=data.readInt32();
  8. num=num+100;
  9. reply->writeInt32(num);
  10. returnNO_ERROR;
  11. }
  12. break;
  13. default:
  14. returnBBinder::onTransact(code,data,reply,flags);
  15. }
  16. }

看到这里首先根据请求代码作相应的处理。还记得我们发送请求时用的是代码0,所以这里会走到"case0"这个分支。程序先顺序读出两个参数:进程ID和被加数,将被加数加上100之后返回。至此,服务器端完成了客户端的服务请求。

我们将总共四篇文章涉及到的主要类用下面的类图作一总结:

说明:

1. Android系统使用binder机制实现进程间通信(IPC),这里主要涉及到以下几个类:

1.1 IBinder是Android系统对binder机制的抽象,任何一个向系统注册的Service都必须继承IBinder接口(如:ExampleService继承BBinder,而BBinder继承IBinder)

1.2 IInterface我们在这一系列文章里没有过多涉及。它的目的是进一步抽象binder机制。比如要使用我们的ExampleService,客户端应用程序必须显式调用IPCThreadState::transaction()方法,对用户来说还是不太友好。如果我们定义一个新的类IExampleServiceInterface继承Interface,在这个类中定义add100()接口,ExampleService的代理对象也拥有该接口,那么客户端应用程序直接调用代理对象的add100()方法就好了,这样做对用户更友好。比如ServiceManager就是这样实现的(IServiceManager继承IInterface)。客户端调用的是addService接口而不是transaction方法。

1.3 ProcessState类是一个singleton类型,每个进程只能创建一个实例,它的作用是管理当前进程中的所有Service代理对象(BpBinder对象)。任何一个使用binder机制的进程都必须创建一个该类的实例。

1.4 IPCThreadState类是processState类的友元类,它的作用是封装对binder设备的I/O操作。客户端通过调用它的transact()方法完成发送请求;服务器端调用他的joinThreadState()方法等待客户端的服务请求。

2. Android的binder机制本质上是Proxy模式的一个具体实现。

3. ServiceManager是整个Android系统的Service管理员,任何一个系统Service首先要向它注册才能提供服务。注册时,首先要获得它的代理对象(BpServiceManager),然后通过调用它的addService()方法完成注册。客户端通过调用它的getService()获取系统服务的代理兑现。ServiceManager在系统中始终对应句柄0。

4. 客户端通过调用IPCThreadState的transaction方法发送请求;服务器端通过改写BBinder的onTransaction()方法实现接受请求。

(全文完)

更多相关文章

  1. Android对View的onMeasure方法理解
  2. Android开发环境的搭建方法
  3. android email 邮件转发 附件不能转发问题的解决
  4. android中onClick事件的实现
  5. C调用Java
  6. Android(安卓)RxHttp在实战中的运用
  7. Android(安卓)Audio代码分析=Audio Strategy
  8. android中判断sim卡状态和读取联系人资料的方法
  9. android网络通信

随机推荐

  1. android 中的 openGL引擎的移植
  2. Android 如何去除Launcher上默认的google
  3. 学习android之布局
  4. android 预装第三方apk的方法(非system p
  5. Android笔记四 虚拟机Dalvik、Android各
  6. Android之View基础总结(View的事件体系一)
  7. 国内Android开发技术大牛推介
  8. ROS(indigo) turtlebot2 + android一些有
  9. Android面试题整理--1
  10. adroid之Sqlite篇