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

你可能感兴趣的:(Android源码学习)