The starting point originates from the main function of the TestClient.cpp:
int Main () { < iservicemanager > sm = defaultservicemanager (); < IBinder > Binder = Sm->getservice (String16 ("service.testservice")); SP<ITestService> cs = interface_cast < Itestservice > (binder); CS-Test (); return 0 ;}
The previous article has analyzed that SM is new Bpservicemanager (new Bpbinder (0)), so Sm->getservice (...) Should look for Bpservicemanager::getservice (...), frameworks/native/libs/binder/iservicemanager.cpp:134
VirtualSp<ibinder> GetService (Conststring16& name)Const{unsigned n; for(n =0; N <5; n++) { sp <IBinder> svc = checkservice (name); //Here is the key code if(svc! = NULL)returnSvc; Alogi ("Waiting for service%s...\n", String8 (name).string()); Sleep (1); } returnNULL;} VirtualSp<ibinder> Checkservice (Conststring16& name)Const{Parcel data, reply; Data.writeinterfacetoken (Iservicemanager::getinterfacedescriptor ()); DATA.WRITESTRING16 (name); Remote ()->transact (check_service_transaction, data, &reply); returnReply.readstrongbinder (); }
Bpservicemanager::remote () returns the member variable Mremote, which was also analyzed earlier, which is the new Bpbinder (0). So remote ()->transact (...) The call is Bpbinder::transact (...),
frameworks/native/libs/binder/bpbinder.cpp:159
status_t bpbinder::transact (uint32_t code,Constparcel& data, parcel*reply, uint32_t flags) { //code=check_service_transaction, Flags=0//Once A binder has died, it'll never come back to life. if(malive) {status_t status= Ipcthreadstate::self ()Transact (MHANDLE, code, data, reply, flags); if(Status = = Dead_object) Malive =0; returnstatus; } returnDead_object;}
Ipcthreadstate::self () from the name point of view should be another factory class (the previous article encountered the processstate is so named), it is a thread monomer, each thread one copy. The specific implementation is not a table, because in the current context its transact (...) It has nothing to do with the thread monomer, we go directly into ipcthreadstate::transact (...) Function.
frameworks/native/libs/binder/ipcthreadstate.cpp:548
status_t ipcthreadstate::transact (int32_t handle, uint32_t code,Constparcel&data, Parcel*reply, uint32_t flags) { //handle=0, code=check_service_transaction, flags=0status_t err =Data.errorcheck (); Flags |= Tf_accept_fds; If_log_transactions () {textoutput::bundle _b (alog); Alog<<"bc_transaction thr"<< (void*) pthread_self () <<"/Hand"<< Handle <<"/Code"<< TypeCode (code) <<": "<< indent << data << dedent <<Endl; } if(Err = =no_error) {Log_oneway (">>>> SEND from PID%d uid%d%s", Getpid (), Getuid (), (Flags& tf_one_way) = =0?"READ REPLY":" One-off"); 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) { #if0if(Code = =4) {//RelayoutAlogi (">>>>>> calling Transaction 4"); } Else{Alogi (">>>>>> calling transaction%d", code); } #endif if (reply) { //in Checkservice (...) A non-empty reply parameter was passed to err = waitForResponse (reply); } Else{Parcel fakereply; Err= waitForResponse (&fakereply); } #if0if(Code = =4) {//RelayoutAlogi ("<<<<<< returning Transaction 4"); } Else{Alogi ("<<<<<< returning transaction%d", code); } #endifif_log_transactions () {textoutput::bundle _b (alog); Alog<<"br_reply thr"<< (void*) pthread_self () <<"/Hand"<< Handle <<": "; if(reply) Alog << indent << *reply << dedent <<Endl; ElseAlog <<"(none requested)"<<Endl; } } Else{Err=waitforresponse (null, NULL); } returnerr;}
So long, the key code has only two lines, and from the naming point it is the process of requesting and receiving replies. Let's look at the request data first.
frameworks/native/libs/binder/ipcthreadstate.cpp:904
status_t ipcthreadstate::writetransactiondata (int32_t cmd, uint32_t binderflags, int32_t handle, uint32_t code, Constparcel& data, status_t*Statusbuffer) { //Cmd=bc_transaction, Binderflags=tf_accept_fds, handle=0,//Code=check_service_transaction,Binder_transaction_data tr; tr.target.ptr = 0; /* Don ' t pass uninitialized stack data to a remote process */ Tr.target.handle = handle; Tr.code = code; Tr.flags = binderflags; Tr.cookie = 0; Tr.sender_pid = 0; Tr.sender_euid = 0; Conststatus_t err =Data.errorcheck (); if(Err = =no_error) { tr.data_size = data.ipcdatasize (); Tr.data.ptr.buffer = data.ipcdata (); Tr.offsets_size = Data.ipcobjectscount () *sizeof(binder_size_t); Tr.data.ptr.offsets = data.ipcobjects (); } Else if(statusbuffer) {tr.flags|=Tf_status_code; *statusbuffer =err; Tr.data_size=sizeof(status_t); Tr.data.ptr.buffer= reinterpret_cast<uintptr_t>(Statusbuffer); Tr.offsets_size=0; Tr.data.ptr.offsets=0; } Else { return(Mlasterror =err); } mout.writeint32 (cmd); Mout.write ( &tr, sizeof(tr)); returnNo_error;}
The function is to assemble a bunch of parameters into the binder_transaction_data structure and write into the mout. Where data is in Checkservice (...) Parcel data in the assembly:
What are Data.ipcobjectscount () *sizeof (binder_size_t) and data.ipcobjects () respectively? From the naming point, he should refer to the data of the abstract data type stored in data, obviously in the organization Checkservice when the parcel data is not abstract data type, you can not delve into it first.
Binder Learning Notes (iii) how the--binder client organizes Checkservice data