Android(安卓)Parcel源码笔记
源码位置
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;}
更多相关文章
- 浅谈Java中Collections.sort对List排序的两种方法
- 类和 Json对象
- Python list sort方法的具体使用
- python list.sort()根据多个关键字排序的方法实现
- android上一些方法的区别和用法的注意事项
- android实现字体闪烁动画的方法
- Android(安卓)Wifi模块分析(三)
- Android中dispatchDraw分析
- Android四大基本组件介绍与生命周期