Android Framework P4 - ServiceManager 进程
ServiceManager 进程
// /system/core/rootdir/init.rc service servicemanager /system/bin/servicemanager class core user system group system critical onrestart restart healthd onrestart restart zygote onrestart restart media onrestart restart surfaceflinger onrestart restart drm// /frameworks/native/cmds/servicemanager/service_manager.cintmain(intargc,char**argv){structbinder_state*bs;bs=binder_open(128*1024);if(!bs){ALOGE("failed to open binder driver\n");return-1;}if(binder_become_context_manager(bs)){ALOGE("cannot become context manager (%s)\n",strerror(errno));return-1;}selinux_enabled=is_selinux_enabled();sehandle=selinux_android_service_context_handle();selinux_status_open(true);if(selinux_enabled>0){if(sehandle==NULL){ALOGE("SELinux: Failed to acquire sehandle. Aborting.\n");abort();}if(getcon(&service_manager_context)!=0){ALOGE("SELinux: Failed to acquire service_manager context. Aborting.\n");abort();}}unionselinux_callback cb;cb.func_audit=audit_callback;selinux_set_callback(SELINUX_CB_AUDIT,cb);cb.func_log=selinux_log_callback;selinux_set_callback(SELINUX_CB_LOG,cb);binder_loop(bs,svcmgr_handler);return0;}// /frameworks/native/cmds/servicemanager/binder.cstructbinder_state*binder_open(size_tmapsize){structbinder_state*bs;structbinder_versionvers;bs=malloc(sizeof(*bs));if(!bs){errno=ENOMEM;returnNULL;}bs->fd=open("/dev/binder",O_RDWR);if(bs->fd<0){fprintf(stderr,"binder: cannot open device (%s)\n",strerror(errno));gotofail_open;}if((ioctl(bs->fd,BINDER_VERSION,&vers)==-1)||(vers.protocol_version!=BINDER_CURRENT_PROTOCOL_VERSION)){fprintf(stderr,"binder: kernel driver version (%d) differs from user space version (%d)\n",vers.protocol_version,BINDER_CURRENT_PROTOCOL_VERSION);gotofail_open;}bs->mapsize=mapsize;bs->mapped=mmap(NULL,mapsize,PROT_READ,MAP_PRIVATE,bs->fd,0);if(bs->mapped==MAP_FAILED){fprintf(stderr,"binder: cannot map device (%s)\n",strerror(errno));gotofail_map;}returnbs;fail_map:close(bs->fd);fail_open:free(bs);returnNULL;}// /frameworks/native/cmds/servicemanager/binder.cintbinder_become_context_manager(structbinder_state*bs){returnioctl(bs->fd,BINDER_SET_CONTEXT_MGR,0);}// /frameworks/native/cmds/servicemanager/binder.cvoidbinder_loop(structbinder_state*bs,binder_handler func){intres;structbinder_write_readbwr;uint32_treadbuf[32];bwr.write_size=0;bwr.write_consumed=0;bwr.write_buffer=0;readbuf[0]=BC_ENTER_LOOPER;binder_write(bs,readbuf,sizeof(uint32_t));for(;;){bwr.read_size=sizeof(readbuf);bwr.read_consumed=0;bwr.read_buffer=(uintptr_t)readbuf;res=ioctl(bs->fd,BINDER_WRITE_READ,&bwr);if(res<0){ALOGE("binder_loop: ioctl failed (%s)\n",strerror(errno));break;}res=binder_parse(bs,0,(uintptr_t)readbuf,bwr.read_consumed,func);if(res==0){ALOGE("binder_loop: unexpected reply?!\n");break;}if(res<0){ALOGE("binder_loop: io error %d %s\n",res,strerror(errno));break;}}}// /frameworks/native/cmds/servicemanager/binder.cintbinder_parse(structbinder_state*bs,structbinder_io*bio,uintptr_tptr,size_tsize,binder_handler func){intr=1;uintptr_tend=ptr+(uintptr_t)size;while(ptr<end){uint32_tcmd=*(uint32_t*)ptr;ptr+=sizeof(uint32_t);#ifTRACEfprintf(stderr,"%s:\n",cmd_name(cmd));#endifswitch(cmd){caseBR_NOOP:break;caseBR_TRANSACTION_COMPLETE:break;caseBR_INCREFS:caseBR_ACQUIRE:caseBR_RELEASE:caseBR_DECREFS:#ifTRACEfprintf(stderr," %p, %p\n",(void*)ptr,(void*)(ptr+sizeof(void*)));#endifptr+=sizeof(structbinder_ptr_cookie);break;caseBR_TRANSACTION:{structbinder_transaction_data*txn=(structbinder_transaction_data*)ptr;if((end-ptr)<sizeof(*txn)){ALOGE("parse: txn too small!\n");return-1;}binder_dump_txn(txn);if(func){unsignedrdata[256/4];structbinder_iomsg;structbinder_ioreply;intres;bio_init(&reply,rdata,sizeof(rdata),4);bio_init_from_txn(&msg,txn);res=func(bs,txn,&msg,&reply);binder_send_reply(bs,&reply,txn->data.ptr.buffer,res);}ptr+=sizeof(*txn);break;}caseBR_REPLY:{structbinder_transaction_data*txn=(structbinder_transaction_data*)ptr;if((end-ptr)<sizeof(*txn)){ALOGE("parse: reply too small!\n");return-1;}binder_dump_txn(txn);if(bio){bio_init_from_txn(bio,txn);bio=0;}else{/* todo FREE BUFFER */}ptr+=sizeof(*txn);r=0;break;}caseBR_DEAD_BINDER:{structbinder_death*death=(structbinder_death*)(uintptr_t)*(binder_uintptr_t*)ptr;ptr+=sizeof(binder_uintptr_t);death->func(bs,death->ptr);break;}caseBR_FAILED_REPLY:r=-1;break;caseBR_DEAD_REPLY:r=-1;break;default:ALOGE("parse: OOPS %d\n",cmd);return-1;}}returnr;}// /frameworks/native/cmds/servicemanager/service_manager.cintsvcmgr_handler(structbinder_state*bs,structbinder_transaction_data*txn,structbinder_io*msg,structbinder_io*reply){structsvcinfo*si;uint16_t*s;size_tlen;uint32_thandle;uint32_tstrict_policy;intallow_isolated;//ALOGI("target=%p code=%d pid=%d uid=%d\n",// (void*) txn->target.ptr, txn->code, txn->sender_pid, txn->sender_euid);if(txn->target.ptr!=BINDER_SERVICE_MANAGER)return-1;if(txn->code==PING_TRANSACTION)return0;// Equivalent to Parcel::enforceInterface(), reading the RPC// header with the strict mode policy mask and the interface name.// Note that we ignore the strict_policy and don't propagate it// further (since we do no outbound RPCs anyway).strict_policy=bio_get_uint32(msg);s=bio_get_string16(msg,&len);if(s==NULL){return-1;}if((len!=(sizeof(svcmgr_id)/2))||memcmp(svcmgr_id,s,sizeof(svcmgr_id))){fprintf(stderr,"invalid id %s\n",str8(s,len));return-1;}if(sehandle&&selinux_status_updated()>0){structselabel_handle*tmp_sehandle=selinux_android_service_context_handle();if(tmp_sehandle){selabel_close(sehandle);sehandle=tmp_sehandle;}}switch(txn->code){caseSVC_MGR_GET_SERVICE:caseSVC_MGR_CHECK_SERVICE:s=bio_get_string16(msg,&len);if(s==NULL){return-1;}handle=do_find_service(bs,s,len,txn->sender_euid,txn->sender_pid);if(!handle)break;bio_put_ref(reply,handle);return0;caseSVC_MGR_ADD_SERVICE:s=bio_get_string16(msg,&len);if(s==NULL){return-1;}handle=bio_get_ref(msg);allow_isolated=bio_get_uint32(msg)?1:0;if(do_add_service(bs,s,len,handle,txn->sender_euid,allow_isolated,txn->sender_pid))return-1;break;caseSVC_MGR_LIST_SERVICES:{uint32_tn=bio_get_uint32(msg);if(!svc_can_list(txn->sender_pid)){ALOGE("list_service() uid=%d - PERMISSION DENIED\n",txn->sender_euid);return-1;}si=svclist;while((n-->0)&&si)si=si->next;if(si){bio_put_string16(reply,si->name);return0;}return-1;}default:ALOGE("unknown code %d\n",txn->code);return-1;}bio_put_uint32(reply,0);return0;}// /frameworks/native/cmds/servicemanager/service_manager.cintdo_add_service(structbinder_state*bs,constuint16_t*s,size_tlen,uint32_thandle,uid_tuid,intallow_isolated,pid_tspid){structsvcinfo*si;//ALOGI("add_service('%s',%x,%s) uid=%d\n", str8(s, len), handle,// allow_isolated ? "allow_isolated" : "!allow_isolated", uid);if(!handle||(len==0)||(len>127))return-1;if(!svc_can_register(s,len,spid)){ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n",str8(s,len),handle,uid);return-1;}si=find_svc(s,len);if(si){if(si->handle){ALOGE("add_service('%s',%x) uid=%d - ALREADY REGISTERED, OVERRIDE\n",str8(s,len),handle,uid);svcinfo_death(bs,si);}si->handle=handle;}else{si=malloc(sizeof(*si)+(len+1)*sizeof(uint16_t));if(!si){ALOGE("add_service('%s',%x) uid=%d - OUT OF MEMORY\n",str8(s,len),handle,uid);return-1;}si->handle=handle;si->len=len;memcpy(si->name,s,(len+1)*sizeof(uint16_t));si->name[len]='\0';si->death.func=(void*)svcinfo_death;si->death.ptr=si;si->allow_isolated=allow_isolated;si->next=svclist;svclist=si;}binder_acquire(bs,handle);binder_link_to_death(bs,handle,&si->death);return0;}binder_open(128*1024):打开 Binder 驱动open("/dev/binder", O_RDWR):打开/dev/binder检查驱动版本:
ioctl(bs->fd, BINDER_VERSION, &vers)获取驱动版本,vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION对比版本mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0):内存映射return bs:返回句柄
binder_become_context_manager(bs):成为上下文管理器,固定编号 0binder_loop(bs, svcmgr_handler):进入 Binder 循环,处理所有请求binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func):解析数据switch(cmd):处理业务
