在这篇文章中,我们将深入剖析一下如何向系统注册Service。
在第一篇文章的例子中,ExampleService通过如下语句向系统注册服务。
- intr=defaultServiceManager()->addService(String16("byn.example"),newExampleService());
在上一篇文章中,我们已经知道通过调用defaultServiceManager()全局函数可以获得当前进程的ServiceManager代理对象的引用。在深入剖析addService()方法之前,让我们先了解一下ServiceManager是如何启动的。首先来看一下它的源代码:
- intmain(intargc,char**argv)
- {
- structbinder_state*bs;
- void*svcmgr=BINDER_SERVICE_MANAGER;
- bs=binder_open(128*1024);
- if(binder_become_context_manager(bs)){
- LOGE("cannotbecomecontextmanager(%s)/n",strerror(errno));
- return-1;
- }
- svcmgr_handle=svcmgr;
- binder_loop(bs,svcmgr_handler);
- return0;
- }
ServiceManager本身是一个系统进程,是Android核心程序。从它的main函数来看,它首先调用binder_open()函数打开binder设备(/dev/binder),接着调用binder_become_context_manager()函数,将自己变为系统服务的“管理员”。我们看一下binder_become_context_manager()函数的源代码:
- intbinder_become_context_manager(structbinder_state*bs)
- {
- returnioctl(bs->fd,BINDER_SET_CONTEXT_MGR,0);
- }
可以看到以BINDER_SET_CONTEXT_MGR为参数进行ioctl系统调用,就可以将自身设置成系统服务的“管理员”,即ServiceManager。
最后,ServiceManager调用binder_loop进入到循环状态,并提供了一个回调函数svcmgr_handler(),等待用户的请求。
现在让我们剖析一下向系统注册Service的过程吧。首先,调用defaultServiceManager()全局函数获得的是ServiceManager代理对象的引用,所以这里的调用的addService方法是代理对象的方法,而不是真正的ServiceManager的addService方法。让我们看一下它的源代码:
- classBpServiceManager:publicBpInterface<IServiceManager>
- {
- public:
- ......
- virtualstatus_taddService(constString16&name,constsp<IBinder>&service)
- {
- Parceldata,reply;
- data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
- data.writeString16(name);
- data.writeStrongBinder(service);
- status_terr=remote()->transact(ADD_SERVICE_TRANSACTION,data,&reply);
- returnerr==NO_ERROR?reply.readInt32():err;
- }
- ......
- }
这里是以ADD_SERVICE_TRANSACTION为命令代码调用的transact()方法。因为ServiceManager代理对象BpServiceManager继承自BpBinder,所以这里调用的是BpBinder::transact(),我们看一下它的源代码:
- status_tBpBinder::transact(
- uint32_tcode,constParcel&data,Parcel*reply,uint32_tflags)
- {
- if(mAlive){
- status_tstatus=IPCThreadState::self()->transact(
- mHandle,code,data,reply,flags);
- if(status==DEAD_OBJECT)mAlive=0;
- returnstatus;
- }
- returnDEAD_OBJECT;
- }
我们看到该方法是通过调用IPCThreadState类的同名方法继续传递请求。这里需要解释一下IPCThreadState类的作用。
每个进程中有且仅有一个IPCThreadState对象,它的作用是维护当前进程中所有对binder设备(/dev/binder)的I/O操作,也就是说一个进程要想通过binder机制与另外一个进程进行通信,最终都是要通过IPCThreadState对象来完成的。有了IPCThreadState这层封装之后,应用程序就不需要通过ioctl同binder设备直接打交道了。下面让我们来看一下IPCThreadState类的transact方法的源代码:
- status_tIPCThreadState::transact(int32_thandle,
- uint32_tcode,constParcel&data,
- Parcel*reply,uint32_tflags)
- {
- status_terr=data.errorCheck();
- flags|=TF_ACCEPT_FDS;
- IF_LOG_TRANSACTIONS(){
- TextOutput::Bundle_b(alog);
- alog<<"BC_TRANSACTIONthr"<<(void*)pthread_self()<<"/hand"
- <<handle<<"/code"<<TypeCode(code)<<":"
- <<indent<<data<<dedent<<endl;
- }
- if(err==NO_ERROR){
- LOG_ONEWAY(">>>>SENDfrompid%duid%d%s",getpid(),getuid(),
- (flags&TF_ONE_WAY)==0?"READREPLY":"ONEWAY");
- 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{
- ParcelfakeReply;
- err=waitForResponse(&fakeReply);
- }
- IF_LOG_TRANSACTIONS(){
- TextOutput::Bundle_b(alog);
- alog<<"BR_REPLYthr"<<(void*)pthread_self()<<"/hand"
- <<handle<<":";
- if(reply)alog<<indent<<*reply<<dedent<<endl;
- elsealog<<"(nonerequested)"<<endl;
- }
- }else{
- err=waitForResponse(NULL,NULL);
- }
- returnerr;
- }
这里调用了writeTransactionData()方法来完成请求,我们再看一下writeTransactionData()方法的定义:
- status_tIPCThreadState::writeTransactionData(int32_tcmd,uint32_tbinderFlags,
- int32_thandle,uint32_tcode,constParcel&data,status_t*statusBuffer)
- {
- binder_transaction_datatr;
- tr.target.handle=handle;
- tr.code=code;
- tr.flags=binderFlags;
- conststatus_terr=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();
- }elseif(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));
- returnNO_ERROR;
- }
最终是在这里将命令和数据封装好之后写入待发送的队列(mOut.writeInt32(cmd),mOut.write(&tr, sizeof(tr)))。回到IPCThreadState类的transact()方法。writeTransactionData()方法返回之后,会通过调用waitForResponse()方法发送请求并等待返回结果。而waitForResponse()方法会调用IPCThreadState::talkWithDriver()方法发送请求并取回返回值。我们看一下talkWithDriver()方法的源代码:
- status_tIPCThreadState::talkWithDriver(booldoReceive)
- {
- LOG_ASSERT(mProcess->mDriverFD>=0,"Binderdriverisnotopened");
- binder_write_readbwr;
- constboolneedRead=mIn.dataPosition()>=mIn.dataSize();
- constsize_toutAvail=(!doReceive||needRead)?mOut.dataSize():0;
- bwr.write_size=outAvail;
- bwr.write_buffer=(longunsignedint)mOut.data();
- if(doReceive&&needRead){
- bwr.read_size=mIn.dataCapacity();
- bwr.read_buffer=(longunsignedint)mIn.data();
- }else{
- bwr.read_size=0;
- }
- IF_LOG_COMMANDS(){
- TextOutput::Bundle_b(alog);
- if(outAvail!=0){
- alog<<"Sendingcommandstodriver:"<<indent;
- constvoid*cmds=(constvoid*)bwr.write_buffer;
- constvoid*end=((constuint8_t*)cmds)+bwr.write_size;
- alog<<HexDump(cmds,bwr.write_size)<<endl;
- while(cmds<end)cmds=printCommand(alog,cmds);
- alog<<dedent;
- }
- alog<<"Sizeofreceivebuffer:"<<bwr.read_size
- <<",needRead:"<<needRead<<",doReceive:"<<doReceive<<endl;
- }
- if((bwr.write_size==0)&&(bwr.read_size==0))returnNO_ERROR;
- bwr.write_consumed=0;
- bwr.read_consumed=0;
- status_terr;
- do{
- IF_LOG_COMMANDS(){
- alog<<"Abouttoread/write,writesize="<<mOut.dataSize()<<endl;
- }
- #ifdefined(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<<"Finishedread/write,writesize="<<mOut.dataSize()<<endl;
- }
- }while(err==-EINTR);
- IF_LOG_COMMANDS(){
- alog<<"Ourerr:"<<(void*)err<<",writeconsumed:"
- <<bwr.write_consumed<<"(of"<<mOut.dataSize()
- <<"),readconsumed:"<<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<<"Remainingdatasize:"<<mOut.dataSize()<<endl;
- alog<<"Receivedcommandsfromdriver:"<<indent;
- constvoid*cmds=mIn.data();
- constvoid*end=mIn.data()+mIn.dataSize();
- alog<<HexDump(cmds,mIn.dataSize())<<endl;
- while(cmds<end)cmds=printReturnCommand(alog,cmds);
- alog<<dedent;
- }
- returnNO_ERROR;
- }
- returnerr;
- }
talkWithDriver()方法会将待发送的请求(之前已经存放在mOut对象中)封装到一个binder_write_read类型的结构体bwr中,并调用ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)完成发送请求。接下来的工作就由内核空间来完成了。此进程当前会阻塞在ioctl这里,直到有返回值返回。由此可见,通过binder机制进行的IPC通信是一个同步过程。这一点非常重要。
客户端的程序我们暂时先分析到这里,现在让我们看看服务端在收到这一请求之后都会做哪些处理。
前面提到,ServiceManager的main函数中注册了回调函数svcmgr_handler(),因此上面的请求通过binder设备发送到ServiceManager这一端的时候,该函数会被调用。我们看一下它的源代码:
- intsvcmgr_handler(structbinder_state*bs,
- structbinder_txn*txn,
- structbinder_io*msg,
- structbinder_io*reply)
- {
- structsvcinfo*si;
- uint16_t*s;
- unsignedlen;
- void*ptr;
- LOGI("[BYN]target=%pcode=%dpid=%duid=%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,"invalidid%s/n",str8(s));
- return-1;
- }
- switch(txn->code){
- caseSVC_MGR_GET_SERVICE:
- caseSVC_MGR_CHECK_SERVICE:
- s=bio_get_string16(msg,&len);
- ptr=do_find_service(bs,s,len);
- if(!ptr)
- break;
- bio_put_ref(reply,ptr);
- return0;
- caseSVC_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;
- caseSVC_MGR_LIST_SERVICES:{
- unsignedn=bio_get_uint32(msg);
- si=svclist;
- while((n-->0)&&si)
- si=si->next;
- if(si){
- bio_put_string16(reply,si->name);
- return0;
- }
- return-1;
- }
- default:
- LOGE("unknowncode%d/n",txn->code);
- return-1;
- }
- bio_put_uint32(reply,0);
- return0;
- }
由于调用的是addService服务,所以会走到SVC_MGR_ADD_SERVICE分支,调用do_add_service()函数。我们看一下它的源代码:
- intdo_add_service(structbinder_state*bs,
- uint16_t*s,unsignedlen,
- void*ptr,unsigneduid)
- {
- structsvcinfo*si;
- if(!ptr||(len==0)||(len>127))
- return-1;
- if(!svc_can_register(uid,s)){
- LOGE("add_service('%s',%p)uid=%d-PERMISSIONDENIED/n",
- str8(s),ptr,uid);
- return-1;
- }
- si=find_svc(s,len);
- if(si){
- if(si->ptr){
- LOGE("add_service('%s',%p)uid=%d-ALREADYREGISTERED/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-OUTOFMEMORY/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);
- return0;
- }
这里首先判断一下是否有权限注册服务(svc_can_register(uid, s)),如果可以的话,再判断该服务是否已经注册过;如果没有注册过的话,就构造一个svcinfo对象,并将它添加到svclist链表中。最后通知binder设备:有一个新的Service注册进来。
服务器端返回之后,客户端被解除阻塞(ioctl系统调用),然后逐层返回,从而完成了注册服务的请求。