In the previous article has encountered parcel, from the name to know that he is responsible for data packaging. In Checkservice's request/response system, parcel only packaged basic data types, such as Int32, String16 ... The latter is also used to package the abstract data type Flat_binder_object, which is slightly more complicated, so it is necessary to take it out for a separate study. We are from Parcel::writeinterfacetoken (...) After that, its layer invocation relationships are as follows, in the Frameworks/native/libs/binder/parcel.cpp file, with the number of rows and function names:
582 writeinterfacetoken (...) 748 Parcel::writeint32 (int32_t val)1149 Parcel::writealigned (Val)
All of the basic data types are packaged at last by writealigned (...). Implementation, its internal logic is also very simple,
frameworks/native/libs/binder/parcel.cpp:1149
template<classT>status_t parcel::writealigned (t val) {Compile_time_assert_function_scope (Pad_size_unsafe (sizeof(T)) = =sizeof(T)); if((mdatapos+sizeof(Val)) <=mdatacapacity) {restart_write:*reinterpret_cast<t*> (Mdata+mdatapos) = Val;//Append Val to Mdata returnFinishwrite (sizeof(Val)); } status_t Err= Growdata (sizeof(Val));//If the mdata space is not enough, the first expansion if(Err = = No_error)GotoRestart_write; returnerr;}
Mdata is a memory stack, Writexxx writes the data to the stack, if the mdata space is not enough, first to mdata expansion, and the original data moved to a new space, and then write the new data to the stack.
Parcel::writestrongbinder (...) The logic is more complex, and its invocation relationship is as follows:
Frameworks/native/libs/binder/parcel.cpp
872 Parcel::writestrongbinder (const sp<ibinder>& val)205 Parcel::flatten_ Binder (const/*proc*/, constout = this)
See Flatten_binder (...), frameworks/native/libs/binder/parcel.cpp:205
status_t Flatten_binder (Constsp<processstate>&/*proc*/, Constsp<ibinder>& Binder, parcel* out) {Flat_binder_object obj; Obj.flags=0x7f|Flat_binder_flag_accepts_fds; if(Binder! =NULL) {IBinder*local = binder->Localbinder (); if(!local) {//Remote type Binder encapsulation logicBpbinder *proxy = binder->Remotebinder (); if(Proxy = =NULL) {Aloge ("NULL proxy"); } Constint32_t handle = proxy? Proxy->handle ():0; Obj.type=Binder_type_handle; Obj.binder=0;/*Don ' t pass uninitialized stack data to a remote process*/Obj.handle=handle; Obj.cookie=0; } Else{//local type Binder wrapper logicObj.type =Binder_type_binder; Obj.binder= Reinterpret_cast<uintptr_t> (local->getweakrefs ()); Obj.cookie= reinterpret_cast<uintptr_t> (local); } } Else{Obj.type=Binder_type_binder; Obj.binder=0; Obj.cookie=0; } returnFinish_flatten_binder (binder, obj, out);}
It does different data encapsulation based on the type of binder that is passed in, and in frameworks/native/include/binder/ibinder.h:139, you can see that IBinder declares two virtual functions:
class Public Virtual refbase{public: ... Virtual bbinder* Localbinder (); Virtual bpbinder* Remotebinder (); ...};
And the default implementation is defined in FRAMEWORKS/NATIVE/LIBS/BINDER/BINDER.CPP:47:
bbinder* Ibinder::localbinder () { return NULL;} Bpbinder* ibinder::remotebinder () { return NULL;}
Flat_binder_object This data structure in the Binder study Note (iv)--servicemanager How to respond to Checkservice request ServiceManager How to organize reply data, It is defined in external/kernel-headers/original/uapi/linux/binder.h:57. The data for the different binder packages is as follows:
Then Flatten_binder (...) Call Finish_flatten_binder (...), frameworks/native/libs/binder/parcel.cpp:199
Static status_t finish_flatten_binder ( const/*binder*/const out ) { returnoutfalse);}
Continue calling WriteObject (...), frameworks/native/libs/binder/parcel.cpp:1035
status_t Parcel::writeobject (Constflat_binder_object& Val,BOOLnullmetadata) { Const BOOLEnoughdata = (mdatapos+sizeof(Val)) <=mdatacapacity; Const BOOLEnoughobjects = Mobjectssize <mobjectscapacity; if(Enoughdata &&enoughobjects) {restart_write://If there is enough space, he appends the Flat_binder_object entity assembled in front to the Mdata*reinterpret_cast<flat_binder_object*> (Mdata+mdatapos) =Val; ...if(Nullmetadata | | Val.binder! =0) { //mobjects record the offset position of each flat_binder_object appended to the MdataMobjects[mobjectssize] =Mdatapos; Acquire_object (Processstate::self (), Val, This, &mopenashmemsize); Mobjectssize++; } returnFinishwrite (sizeof(Flat_binder_object)); } ...}
Summary: Parcel The data area is divided into two parts: Mdata and Mobjects , all data is appended to the mdata, whether it is the underlying data type or the object entity , Mobjects . is an offset array that records all stored in the Mdata Flat_binder_object in the the offset of the entity. The Parcel data model is as follows:
Binder Learning Note (v) how does--parcel package data?