进程间的数据传递是Binder机制的重要环节,负责这一任务的parcel。
如在往binder驱动写入数据,或者读取binder驱动返回的数据,都是parcel类型的。
onTransact(Parcel &data, Parcel* reply,)
parcel的原理是把进程A中的对象数据打包发到进程B,然后进程B在把这个数据拆包还原。
parcel支持的数据类型非常多,通过Parcel.h,Parcel.java可以看到原始数据类型都是可以通过parcel传递的,有其对象的读写方法。
除了原始数据类型外,原始数据类型的数组也有相应的读写方法。
对于自定义的一些对象,如果其遵循Parcelable协议,也是可以通过parcel来读取的,比如Activity的onCreate()函数中用到的Bundle就继承了Parcelable,通过Intent传递参数也是写入到Bundle中的,其对应的读写方法是:
writeParcelable(constParcelable& parcelable);
readParcelable(Parcelable*parcelable) const;
public final class Bundle extends BaseBundle implements Cloneable,Parcelable {}
不管是原始数据类型,还是继承自Parcelable的自定义对象,他们存入parcel的都是这些对象的内容,还有一种数据类型,存入parcel的是它们的特殊标志引用,这类数据通常有两种,一种是Binder,Binder除了是系统IPC的机制之外,它本身也是一个对象,对应的读写方法是:
status_t Parcel::writeStrongBinder(const sp<IBinder>& val)
sp<IBinder> Parcel::readStrongBinder() const{}
这个Bundle是java层的对象。
public final class Bundle extends BaseBundle implements Cloneable,Parcelable {}
另一种是文件描述符FileDescriptor,对应的读写方法:
status_t Parcel::writeFileDescriptor(int fd, bool takeOwnership)
int Parcel::readFileDescriptor() const{}
这两种数据类型传递后的对象仍然会基于和原对象相同的文件流进行操作。在对它们的读写过程中,对数据的处理都是以flat_binder_object这个结构体来描述的。flat_binder_object是一个可以在进程间传递的Binder对象的flattened描述符。
通过看Parcel.h中write方法的定义:
template<typenameT>
status_t Parcel::write(const Flattenable<T>& val) {
const FlattenableHelper<T> helper(val);
return write(helper);
}
通过这个方法的定义,可以看出,继承自Flattenable的类,也是可以通过parcel读写的。Flattenable协议允许一个对象序列化自己到byte缓存中和一个文件描述符的数组中,相应的继承这个Flattenable的类,要重写:
inline status_t flatten(void*& buffer, size_t& size, int*& fds,size_t& count) const;
inline status_t unflatten(void const*& buffer, size_t& size, intconst*& fds, size_t& count);
这两个方法。
GraphicBuffer就是继承Flattenable的一个实例。
class GraphicBuffer
:public ANativeObjectBase< ANativeWindowBuffer, GraphicBuffer,RefBase >, public Flattenable<GraphicBuffer>{}