Java层:
Frameworks/base/core/java/android/os/Parcel.java
Jni:
Frameworks/base/core/jni/android_os_Parcel.cpp
Frameworks/base/core/jni/android_os_Parcel.h
实现层:
Frameworks/base/include/binder/parcel.h和Frameworks/base/libs/binder/parcel.cpp
// ---------------------------------------------------------------------------
// 模板的偏特化和全特化,当传入_exp为false时,找不到对应的模板,编译时报错
#ifdef __cplusplus template struct CompileTimeAssert;
template<> struct CompileTimeAssert<true> {};
#define COMPILE_TIME_ASSERT(_exp) \
template class CompileTimeAssert< (_exp) >;
#endif
#define COMPILE_TIME_ASSERT_FUNCTION_SCOPE(_exp) \
CompileTimeAssert<( _exp )>();
// ---------------------------------------------------------------------------
Java层Parcel的获取
Parcel parcle = Parcel.Obtain();
mOwnsNativeParcelObject表明mNativePtr是否由当前对象分配,负责它的生命周期。
private static final int POOL_SIZE = 6;
private static final Parcel[] sOwnedPool = new Parcel[POOL_SIZE];
private static final Parcel[] sHolderPool = new Parcel[POOL_SIZE];
Parcel维护了两个Parcel对象池子,recyle时会将对象放入池子中复用。Obtain()方法为当前对象分配,所以池子为sOwnedPool,obtain(long obj)方法池子为sHolderPool。第一次调用时,池子里对象都为空,调用new Parcel(0)构造一个,再调用init方法,参数为0,调用JNI方法nativeCreate()并赋给mNativePtr,此时mOwnsNativeParcelObject为true。mNativePtr与JNI层的nativePtr相映射,register_android_os_Parcel中将相应的对象和方法相关联。
//nativeCreate()的JNI方法
static jlong android_os_Parcel_create(JNIEnv* env, jclass clazz)
{
Parcel* parcel = new Parcel();
//返回parcel的地址,此时对Java层的mNativePtr赋值
return reinterpret_cast(parcel);
}
JNI中获取Parcel
Parcel* parcel = reinterpret_cast(nativePtr);
android_os_Parcel_create方法中使用Parcel构造方法构造对象,调用initState()方法.
//Parcel的成员变量
//数据的地址
uint8_t* mData;
//当前存储数据的大小
size_t mDataSize;
//总空间容量
size_t mDataCapacity;
//当前读取的位置
mutable size_t mDataPos;
//存储的为flat_binder_object结构
//指向flat_binder_object数据地址,mObjects为__u32类型,即4字节的unsigned int,存的为各object写入时的mDataPos,
//具体可以看writeObject方法
binder_size_t* mObjects;
//flat_binder_object数目
size_t mObjectsSize;
//可存储flat_binder_object容量
size_t mObjectsCapacity;
//下一个对象的序号
mutable size_t mNextObjectHint;
从代码中可得知,Parcel整个读写全是在内存中进行,主要是通过malloc()、realloc()、memcpy()等内存操作进行,所以效率比JAVA序列化中使用外部存储器会高很多。读写时是4字节对齐的,#define PAD_SIZE_UNSAFE(s) (((s)+3)&~3)获得就是大于当前值的可以被4整除的数字,&~3保证被4整除,+3即加011,表示除0外一定会进位这样保证会大于其本身。当容量不够时,即(mDataPos+sizeof(val)) <= mDataCapacity时,调用growData扩展空间.
size_t newSize = ((mDataSize+len)*3)/2;
对于IBinder类型的数据以及FileDescriptor使用的是mObjects内存地址,调用writeObject/readObject读写,如果容量不够,也会自动扩展,即mObjectsSize > mObjectsCapacity时,会调用size_t newSize = ((mObjectsSize+2)*3)/2,每次write写入,都会调用finishWrite方法更新mDataPos和mDataSize,以便接下来的写入。对于Binder类型数据,ibinderForJavaObject方法将Java系统服务转化成sp,writeStrongBinder/readStrongBinder分别调用flatten_binder/unflatten_binder方法。读取时也同样,每read一个值,都会更新mDataPos的值,所以Parcel read/write时各数据的顺序必须一致。
//marshall将Parcel对象转为为byte数组,用的比较少,Android源码中有一些应用使用,比如Email,BatteryStatsService
// Returns the raw bytes of the parcel.
static jbyteArray android_os_Parcel_marshall(JNIEnv* env, jclass clazz, jlong nativePtr)
{
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel == NULL) {
return NULL;
}
// do not marshall if there are binder objects in the parcel
if (parcel->objectsCount())
{
jniThrowException(env, "java/lang/RuntimeException", "Tried to marshall a Parcel that contained Binder objects.");
return NULL;
}
//用于构造新Byte类型数组对象
jbyteArray ret = env->NewByteArray(parcel->dataSize());
if (ret != NULL)
{
//返回指向java数组的指针
jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
if (array != NULL)
{
memcpy(array, parcel->data(), parcel->dataSize());
env->ReleasePrimitiveArrayCritical(ret, array, 0);
}
}
return ret;
}
// Set the bytes in data to be the raw bytes of this Parcel.
static void android_os_Parcel_unmarshall(JNIEnv* env, jclass clazz, jlong nativePtr,
jbyteArray data, jint offset, jint length)
{
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel == NULL || length < 0) {
return;
}
jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(data, 0);
if (array)
{
parcel->setDataSize(length);
parcel->setDataPosition(0);
void* raw = parcel->writeInplace(length);
memcpy(raw, (array + offset), length);
env->ReleasePrimitiveArrayCritical(data, array, 0);
}
}
//Java层Binder对象转换成Native层对象
sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
{
if (obj == NULL) return NULL;
if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
JavaBBinderHolder* jbh = (JavaBBinderHolder*)
env->GetLongField(obj, gBinderOffsets.mObject);
return jbh != NULL ? jbh->get(env, obj) : NULL;
}
if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
return (IBinder*)
env->GetLongField(obj, gBinderProxyOffsets.mObject);
}
ALOGW("ibinderForJavaObject: %p is not a Binder object", obj);
return NULL;
}