源码位置

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;}

更多相关文章

  1. 浅谈Java中Collections.sort对List排序的两种方法
  2. 类和 Json对象
  3. Python list sort方法的具体使用
  4. python list.sort()根据多个关键字排序的方法实现
  5. android上一些方法的区别和用法的注意事项
  6. android实现字体闪烁动画的方法
  7. Android(安卓)Wifi模块分析(三)
  8. Android中dispatchDraw分析
  9. Android四大基本组件介绍与生命周期

随机推荐

  1. App跨平台开发方案与抉择
  2. 使用android studio 版本合并遇到的问题
  3. Google送Nexus One手机啦,大家快去收邮件
  4. Android与WebView的插件管理机制
  5. Android:EditText属性大全
  6. Android(安卓)Studio项目构建时遇到的常
  7. [Ionic 2从入门到精通] 9.3 在Mac或者PC
  8. Android(安卓)XML解析学习——创建XML
  9. Android(安卓)4.0.1 模拟器内核 最新下载
  10. Android获取ROOT权限的通用方法