一. 概述
众所周知AIDL并不是所有的数据类型都可以传输。
可以传输的类型包括:
1.原生类型 2.String 3. CharSequence 4. List 5.Map 6. Binder 7. Parcelable
容器类 parcelable传输的时候会分解成成员,数组item的方式,传输完成后再进行组装。那Binder类数据是怎么传输的呢?
二. 接口定义
interface IMyAidlInterface {void testBinder(IBinder binderData);
}public interface IMyAidlInterface extends android.os.IInterface{private static class Proxy implements com.zxx.sample.IMyAidlInterface{public void testBinder(android.os.IBinder binderData) throws android.os.RemoteException{android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();try {_data.writeInterfaceToken(DESCRIPTOR);_data.writeStrongBinder(binderData);boolean _status = mRemote.transact(Stub.TRANSACTION_testBinder, _data, _reply, 0);_reply.readException();}finally {_reply.recycle();_data.recycle();}}}}
三. 数据传输流程
总结:通过aidl传递binder对象的时候,binder对象会被包装成flat_binder_object对象然后序列化到parcel类中,当调用IPCThreadState::transact后数据会被写入到binder_transaction_data中,随后调用IPCThreadState::talkwithdriver,binder_transaction_data被写入到binder_write_read后发送到binder驱动
四. binder层数据传输
拿到传输的数据后会依次读取出传输的binder对象,并进行转换如果是bbinder对象(BINDER_TYPE_BINDER),则转换成bpbinder
binder.cstatic void binder_transaction(struct binder_proc *proc,struct binder_thread *thread,struct binder_transaction_data *tr, int reply,binder_size_t extra_buffers_size){
.
.
.
for (buffer_offset = off_start_offset; buffer_offset < off_end_offset;buffer_offset += sizeof(binder_size_t)) {struct binder_object_header *hdr;size_t object_size;struct binder_object object;binder_size_t object_offset;binder_size_t copy_size;.
.
.
hdr = &object.hdr;off_min = object_offset + object_size;switch (hdr->type) {case BINDER_TYPE_BINDER:case BINDER_TYPE_WEAK_BINDER: {struct flat_binder_object *fp;fp = to_flat_binder_object(hdr);ret = binder_translate_binder(fp, t, thread);...case BINDER_TYPE_HANDLE:case BINDER_TYPE_WEAK_HANDLE: {struct flat_binder_object *fp;fp = to_flat_binder_object(hdr);ret = binder_translate_handle(fp, t, thread);if (ret < 0 ||...}
binder_translate_binder会调用到 binder_get_ref_for_node_olocked,如果binder没有对应的binder_ref节点则会 在红黑树(根据desc排序)分配一个空闲的节点(如果有的话,如果没有则插入到红黑树的尾端)并分配值给desc,这个desc就是我们在framework层获取到的bpBinder的handle值
binder.cstatic struct binder_ref *binder_get_ref_for_node_olocked(struct binder_proc *proc,struct binder_node *node,struct binder_ref *new_ref)
{...new_ref->data.desc = (node == context->binder_context_mgr_node) ? 0 : 1;for (n = rb_first(&proc->refs_by_desc); n != NULL; n = rb_next(n)) {ref = rb_entry(n, struct binder_ref, rb_node_desc);if (ref->data.desc > new_ref->data.desc)break;new_ref->data.desc = ref->data.desc + 1;}}