背景
在继续深入理解Binder
机制前,我们很有必要对Parcel
进行学习。
一、Parcel 为何物?
Parcel翻译过来是"包裹"的意思,其实就是个智能化数据容器。它提供了一种能力:将各种类型的数据
或对象的引用
在A进程中打包,经过Binder机制
实现跨进程的传递,然后在B进程中解包出来。作为数据的载体,Parcel
自动帮你完成打包、解压的过程。
Parcel 进程A打包的数据,和进程B得到数据是同一个份吗
-
如果打包的是数据本身,那么肯定不是。数据在内存中存储,A进程的内存空进和B进程的内存空进肯定不想通的。因此,数据或者引用肯定不是A进程的数据或引用,传入A进程的地址肯定不可行。
-
如果是同一个进程中使用Parcel,也会把数据Student先拆解,拷贝到Parcel的内存中,然后从parcel的内存中根据各个字段,再恢复创建另一个对象Student。再回收Parcel容器的内存。因此,同一个进程不建议使用parcel,内存浪费、效率低。
-
如果是不同进程,进程A把数据Student先拆解,拷贝到Parcel的内存中。然后再把Parcel内存中的数据拷贝到内核空间,释放Parcel内存。 进程B从内核空间直接读取数据,得到一个进程B中的parcel对象,从parcel对象中根据各个字段再恢复创建一个Student对象。此时,student对象就在B进程了。看起来好像是A进程的student对象传递到了进程B。
-
二、Parcel支持的传递数据类型
2.1 基本类型
private static native void nativeWriteByteArray(long nativePtr, byte[] b, int offset, int len);
private static native void nativeWriteBlob(long nativePtr, byte[] b, int offset, int len);
@FastNative
private static native void nativeWriteInt(long nativePtr, int val);
@FastNative
private static native void nativeWriteLong(long nativePtr, long val);
@FastNative
private static native void nativeWriteFloat(long nativePtr, float val);
@FastNative
private static native void nativeWriteDouble(long nativePtr, double val);
static native void nativeWriteString(long nativePtr, String val);
支持int、string、float、double
等基本数据类型的读写。
2.2 Parcelables
/**
* Flatten the name of the class of the Parcelable and its contents
* into the parcel.
public final void writeParcelable(Parcelable p, int parcelableFlags) {
if (p == null) {
writeString(null);
return;
}
writeParcelableCreator(p);
//writeToParcel()把自定义对象的数据写入parcel中
p.writeToParcel(this, parcelableFlags);
}
支持实现了parcelable
接口的自定义对象的写入。如:intent、student
等。
/**
* Read and return a new Parcelable from the parcel. The given class loader
* will be used to load any enclosed Parcelables. If it is null, the default
* class loader will be used.
*/
// 创建一个新的自定义对象
@SuppressWarnings("unchecked")
public final <T extends Parcelable> T readParcelable(ClassLoader loader) {
Parcelable.Creator<?> creator = readParcelableCreator(loader);
if (creator == null) {
return null;
}
if (creator instanceof Parcelable.ClassLoaderCreator<?>) {
Parcelable.ClassLoaderCreator<?> classLoaderCreator =
(Parcelable.ClassLoaderCreator<?>) creator;
return (T) classLoaderCreator.createFromParcel(this, loader);
}
//注意,这里得到的自定义对象跟写入的不是同一个了。
return (T) creator.createFromParcel(this);
}
创建并返回一个新的自定义对象。
2.3 Bundles
/**
* Flatten a Bundle into the parcel at the current dataPosition(),
* growing dataCapacity() if needed.
*/
public final void writeBundle(Bundle val) {
if (val == null) {
writeInt(-1);
return;
}
val.writeToParcel(this, 0);
}
/**
* Read and return a new Bundle object from the parcel at the current
* dataPosition(), using the given class loader to initialize the class
* loader of the Bundle for later retrieval of Parcelable objects.
* Returns null if the previously written Bundle object was null.
*/
public final Bundle readBundle(ClassLoader loader) {
int length = readInt();
if (length < 0) {
if (Bundle.DEBUG) Log.d(TAG, "null bundle: length=" + length);
return null;
}
final Bundle bundle = new Bundle(this, length);
if (loader != null) {
bundle.setClassLoader(loader);
}
return bundle;
}
支持Bundle
对象的读写。
与parcelable有什么关系?
答: Bundle
本质上就是一个parcelable
对象。特点是封装了键值对的数据读写,一定程度上优化了读写效率,提升了性能。
2.4 Active object
什么是Active object?
答:我们一般存入到Parcel
的是数据的本身,而Active object
则是写入一个特殊的标志token
,这个token
引用了原数据对象。
当从Parcel
中恢复这个对象时,我们可以不用重新实例化这个对象,而是通过得到一个handle值
。通过handle
值则可以直接操作原来需要写入的对象。
那么哪些对象属于Active object呢?
答: IBinder
对象和FileDescriptor
对象。
/**
* Write an object into the parcel at the current dataPosition(),
* growing dataCapacity() if needed.
*/
public final void writeStrongBinder(IBinder val) {
nativeWriteStrongBinder(mNativePtr, val);
}
/**
* Read an object from the parcel at the current dataPosition().
*/
public final IBinder readStrongBinder() {
return nativeReadStrongBinder(mNativePtr);
}
支持IBinder
对象的读写。
/**
* Write a FileDescriptor into the parcel at the current dataPosition(),
* growing dataCapacity() if needed.
*
* <p class="caution">The file descriptor will not be closed, which may
* result in file descriptor leaks when objects are returned from Binder
* calls. Use {@link ParcelFileDescriptor#writeToParcel} instead, which
* accepts contextual flags and will close the original file descriptor
* if {@link Parcelable#PARCELABLE_WRITE_RETURN_VALUE} is set.</p>
*/
public final void writeFileDescriptor(FileDescriptor val) {
updateNativeSize(nativeWriteFileDescriptor(mNativePtr, val));
}
/**
* Read a FileDescriptor from the parcel at the current dataPosition().
*/
public final ParcelFileDescriptor readFileDescriptor() {
FileDescriptor fd = nativeReadFileDescriptor(mNativePtr);
return fd != null ? new ParcelFileDescriptor(fd) : null;
}
支持fd
对象的读写。
2.5 Untyped container
支持java
容器类的存取。如 如map、list
等。
* {@link #writeArray(Object[])}, {@link #readArray(ClassLoader)},
* {@link #writeList(List)}, {@link #readList(List, ClassLoader)},
* {@link #readArrayList(ClassLoader)},
* {@link #writeMap(Map)}, {@link #readMap(Map, ClassLoader)},
* {@link #writeSparseArray(SparseArray)},
* {@link #readSparseArray(ClassLoader)}.
而以上接口的本质是通过循环集合,内部调用writeValue(Object)
和readValue(ClassLoader)
来实现。
如:
public final void writeMap(Map val) {
writeMapInternal((Map<String, Object>) val);
}
/* package */ void writeMapInternal(Map<String,Object> val) {
if (val == null) {
writeInt(-1);
return;
}
Set<Map.Entry<String,Object>> entries = val.entrySet();
writeInt(entries.size());
for (Map.Entry<String,Object> e : entries) {
writeValue(e.getKey());
writeValue(e.getValue());
}
}
内部都是通过调用 writeValue()
:
public final void writeValue(Object v) {
if (v == null) {
writeInt(VAL_NULL);
} else if (v instanceof String) {
writeInt(VAL_STRING);
writeString((String) v);
} else if (v instanceof Integer) {
writeInt(VAL_INTEGER);
writeInt((Integer) v);
} else if (v instanceof Map) {
writeInt(VAL_MAP);
writeMap((Map) v);
} else if (v instanceof Bundle) {
// Must be before Parcelable
writeInt(VAL_BUNDLE);
writeBundle((Bundle) v);
} else if (v instanceof PersistableBundle) {
writeInt(VAL_PERSISTABLEBUNDLE);
writePersistableBundle((PersistableBundle) v);
} else if (v instanceof Parcelable) {
// IMPOTANT: cases for classes that implement Parcelable must
// come before the Parcelable case, so that their specific VAL_*
// types will be written.
writeInt(VAL_PARCELABLE);
writeParcelable((Parcelable) v, 0);
} else if (v instanceof Short) {
writeInt(VAL_SHORT);
writeInt(((Short) v).intValue());
} else if (v instanceof Long) {
writeInt(VAL_LONG);
writeLong((Long) v);
} else if (v instanceof Float) {
writeInt(VAL_FLOAT);
writeFloat((Float) v);
} else if (v instanceof Double) {
writeInt(VAL_DOUBLE);
writeDouble((Double) v);
} else if (v instanceof Boolean) {
writeInt(VAL_BOOLEAN);
writeInt((Boolean) v ? 1 : 0);
} else if (v instanceof CharSequence) {
// Must be after String
writeInt(VAL_CHARSEQUENCE);
writeCharSequence((CharSequence) v);
} else if (v instanceof List) {
writeInt(VAL_LIST);
writeList((List) v);
} else if (v instanceof SparseArray) {
writeInt(VAL_SPARSEARRAY);
writeSparseArray((SparseArray) v);
} else if (v instanceof boolean[]) {
writeInt(VAL_BOOLEANARRAY);
writeBooleanArray((boolean[]) v);
} else if (v instanceof byte[]) {
writeInt(VAL_BYTEARRAY);
writeByteArray((byte[]) v);
} else if (v instanceof String[]) {
writeInt(VAL_STRINGARRAY);
writeStringArray((String[]) v);
} else if (v instanceof CharSequence[]) {
// Must be after String[] and before Object[]
writeInt(VAL_CHARSEQUENCEARRAY);
writeCharSequenceArray((CharSequence[]) v);
} else if (v instanceof IBinder) {
writeInt(VAL_IBINDER);
writeStrongBinder((IBinder) v);
} else if (v instanceof Parcelable[]) {
writeInt(VAL_PARCELABLEARRAY);
writeParcelableArray((Parcelable[]) v, 0);
} else if (v instanceof int[]) {
writeInt(VAL_INTARRAY);
writeIntArray((int[]) v);
} else if (v instanceof long[]) {
writeInt(VAL_LONGARRAY);
writeLongArray((long[]) v);
} else if (v instanceof Byte) {
writeInt(VAL_BYTE);
writeInt((Byte) v);
} else if (v instanceof Size) {
writeInt(VAL_SIZE);
writeSize((Size) v);
} else if (v instanceof SizeF) {
writeInt(VAL_SIZEF);
writeSizeF((SizeF) v);
} else if (v instanceof double[]) {
writeInt(VAL_DOUBLEARRAY);
writeDoubleArray((double[]) v);
} else {
Class<?> clazz = v.getClass();
if (clazz.isArray() && clazz.getComponentType() == Object.class) {
// Only pure Object[] are written here, Other arrays of non-primitive types are
// handled by serialization as this does not record the component type.
writeInt(VAL_OBJECTARRAY);
writeArray((Object[]) v);
} else if (v instanceof Serializable) {
// Must be last
writeInt(VAL_SERIALIZABLE);
writeSerializable((Serializable) v);
} else {
throw new RuntimeException("Parcel: unable to marshal value " + v);
}
}
}
writeValue()
内部定义了支持的object
类型,根据不同类型调用不同接口来实现序列化。
三、Parcel 传递过程
3.1 一些疑问:
parcel
初始化的时候,并没有分配内存,而是动态分配内存。那么分配内存所在空间是指? A进程空间?
答:是的,在进程A创建肯定是进程A的空间中。
- 那么parcel有没有数据大小限制? 最大是多少?
答:有的,总大小是Integer最大值。跨进程通信报限制错误,是因为进程间缓冲区有大小限制导致。如1M-8k。
- 读取数据的顺序必须要和写入数据的顺序一致,这样才能正确的获取的数据?
答:是的。因为Parcel
会根据顺序读取。内部有一个位置指针。
3.2 Parcel的创建
3.2.1 obtain()
Parcel都是通过obtain()
方法来获取对象的。
static protected final Parcel obtain(long obj) {
// 系统会缓存池(就是一个数组),大小为POOL_SIZE=6。
final Parcel[] pool = sHolderPool;
synchronized (pool) {
Parcel p;
for (int i=0; i<POOL_SIZE; i++) {
p = pool[i];
if (p != null) {
pool[i] = null; // 置空,表示已经被占用
if (DEBUG_RECYCLE) {
p.mStack = new RuntimeException();
}
p.init(obj);
return p;
}
}
}
//池中全部为空,没有可用的parcel,则创建一个新的parcel对象
return new Parcel(obj);
}
3.2.2 init()
Parcel的构造方法:
private Parcel(long nativePtr) {
if (DEBUG_RECYCLE) {
mStack = new RuntimeException();
}
//Log.i(TAG, "Initializing obj=0x" + Integer.toHexString(obj), mStack);
//初始化 nativePtr 表示是native层的 parcel 对象
init(nativePtr);
}
继续看init(nativePtr)
,其中nativePtr
表示是native
层的 parcel 对象。
private void init(long nativePtr) {
if (nativePtr != 0) {
//没有native parcel的指针
mNativePtr = nativePtr;
mOwnsNativeParcelObject = false;
} else {
// 拥有native parcel的指针,走该分支
mNativePtr = nativeCreate();
mOwnsNativeParcelObject = true;
}
}
调用的是jni
层:
// jni 方法
private static native long nativeCreate();
3.2.3 nativeCreate(native层)
继续看jni
方法。
483 static jlong android_os_Parcel_create(JNIEnv* env, jclass clazz)
484 {
// 创建c++ parcel对象
485 Parcel* parcel = new Parcel();
// 强转为long值,返回引用给java层
486 return reinterpret_cast<jlong>(parcel);
487 }
3.2.4 reinterpret_cast
这个方法非常重要。可以把一个c++对象
解释转换为一个long型的值
。后续在根据这个long值
再强转回为原来的c++的对象
。因此,java层
只要持有这个long型值,即可与c++层
联系起来了。
继续看native
层的 Parcel()
对象:
3.2.4 Parcel::initState
352 Parcel::Parcel()
353 {
354 LOG_ALLOC("Parcel %p: constructing", this);
355 initState();
356 }
void Parcel::initState()
2913 {
2914 LOG_ALLOC("Parcel %p: initState", this);
2915 mError = NO_ERROR;
2916 mData = nullptr;
2917 mDataSize = 0;
2918 mDataCapacity = 0;
2919 mDataPos = 0;
2920 ALOGV("initState Setting data size of %p to %zu", this, mDataSize);
2921 ALOGV("initState Setting data pos of %p to %zu", this, mDataPos);
2922 mObjects = nullptr;
2923 mObjectsSize = 0;
2924 mObjectsCapacity = 0;
2925 mNextObjectHint = 0;
2926 mObjectsSorted = false;
2927 mHasFds = false;
2928 mFdsKnown = true;
2929 mAllowFds = true;
2930 mOwner = nullptr;
2931 mOpenAshmemSize = 0;
2932 mWorkSourceRequestHeaderPosition = 0;
2933 mRequestHeaderPresent = false;
2934
2935 // racing multiple init leads only to multiple identical write
2936 if (gMaxFds == 0) {
2937 struct rlimit result;
2938 if (!getrlimit(RLIMIT_NOFILE, &result)) {
2939 gMaxFds = (size_t)result.rlim_cur;
2940 //ALOGI("parcel fd limit set to %zu", gMaxFds);
2941 } else {
2942 ALOGW("Unable to getrlimit: %s", strerror(errno));
2943 gMaxFds = 1024;
2944 }
2945 }
2946 }
从以上可以看出,这里只是初始化了一些成员变量,如parcel的大小、容量、开始位置等信息。
注意,此时Parcel是没有分配内存的。Parcel是在存入数据的时候,动态分配内存的。
四、数据读写过程
4.1 基本数据的写
以 writeFloat()和readFloat()
为例。
4.1.1 nativeWriteFloat()
public final void writeFloat(float val) {
nativeWriteFloat(mNativePtr, val);
}
传入nativePtr
指针,调用的是jni方法,那我们看看native层的方法:
static void android_os_Parcel_writeFloat(JNIEnv* env, jclass clazz, jlong nativePtr, jfloat val)
255 {
// 根据java层的指针强转为c++层的Parcel对象
256 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
257 if (parcel != NULL) {
//
258 const status_t err = parcel->writeFloat(val);
259 if (err != NO_ERROR) {
260 signalExceptionForError(env, clazz, err);
261 }
262 }
263 }
继续看Parcel的 writeFloat()
:
4.1.2 writeFloat()
status_t Parcel::writeFloat(float val)
1060 {
1061 return writeAligned(val);
1062 }
1063
template<class T>
1680 status_t Parcel::writeAligned(T val) {
1681 COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE_UNSAFE(sizeof(T)) == sizeof(T));
1682 //如果在当前的位置mDataPos+插入值val的大小,还没有超过parcel的容量,那么直接插入val
1683 if ((mDataPos+sizeof(val)) <= mDataCapacity) {
1684 restart_write: // 在当前位置插入val
1685 *reinterpret_cast<T*>(mData+mDataPos) = val;
//完成插入,更新mDataPos位置。结束
1686 return finishWrite(sizeof(val));
1687 }
1688 //如果超过容量,则自动扩容
1689 status_t err = growData(sizeof(val));
//扩容成功,再次把val值插入到parcel中
1690 if (err == NO_ERROR) goto restart_write;
1691 return err;
1692 }
1693
4.1.3 growData()
status_t Parcel::growData(size_t len)
2681 {
2682 if (len > INT32_MAX) {
2683 // don't accept size_t values which may have come from an
2684 // inadvertent conversion from a negative int.
2685 return BAD_VALUE;
2686 }
2687
2688 size_t newSize = ((mDataSize+len)*3)/2; //1.5 倍扩容
2689 return (newSize <= mDataSize)
2690 ? (status_t) NO_MEMORY
2691 : continueWrite(newSize);
2692 }
4.1.4 continueWrite()
...
// This is the first data. Easy!
//调用malloc函数,分配内存
2885 uint8_t* data = (uint8_t*)malloc(desired);
2886 if (!data) {
2887 mError = NO_MEMORY;
2888 return NO_MEMORY;
2889 }
2890
2891 if(!(mDataCapacity == 0 && mObjects == nullptr
2892 && mObjectsCapacity == 0)) {
2893 ALOGE("continueWrite: %zu/%p/%zu/%zu", mDataCapacity, mObjects, mObjectsCapacity, desired);
2894 }
2895
2896 LOG_ALLOC("Parcel %p: allocating with %zu capacity", this, desired);
2897 pthread_mutex_lock(&gParcelGlobalAllocSizeLock);
2898 gParcelGlobalAllocSize += desired;
2899 gParcelGlobalAllocCount++;
2900 pthread_mutex_unlock(&gParcelGlobalAllocSizeLock);
2901
2902 mData = data;
2903 mDataSize = mDataPos = 0;
2904 ALOGV("continueWrite Setting data size of %p to %zu", this, mDataSize);
2905 ALOGV("continueWrite Setting data pos of %p to %zu", this, mDataPos);
2906 mDataCapacity = desired;
2907 }
可以发现,内部是通过malloc()
函数完成内存分配的。至此,完成了数据的写入操作。
那数据是如何读取的呢?
4.2 基本数据的读过程
4.2.1 nativeReadFloat()
private static native float nativeReadFloat(long nativePtr);
static jfloat android_os_Parcel_readFloat(jlong nativePtr)
430 { //同理,根据long值,得到parcel对象
431 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
432 if (parcel != NULL) {
433 return parcel->readFloat();
434 }
435 return 0;
436 }
看parcel的 readFloat()
:
float Parcel::readFloat() const
1953 {
1954 return readAligned<float>();
1955 }
4.2.2 readAligned()
status_t Parcel::readAligned(T *pArg) const {
1648 COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE_UNSAFE(sizeof(T)) == sizeof(T));
1649
1650 if ((mDataPos+sizeof(T)) <= mDataSize) {
1651 if (mObjectsSize > 0) {
从当前位置读取一个float类型的数据
1652 status_t err = validateReadData(mDataPos + sizeof(T));
1653 if(err != NO_ERROR) {
1654 // Still increment the data position by the expected length
1655 mDataPos += sizeof(T);
1656 return err;
1657 }
1658 }
1659
1660 const void* data = mData+mDataPos;
1661 mDataPos += sizeof(T);
1662 *pArg = *reinterpret_cast<const T*>(data);
1663 return NO_ERROR;
1664 } else {
1665 return NOT_ENOUGH_DATA;
1666 }
1667 }
内部会根据插入的顺序,根据前位置mDataPos
和 数据大小
,读取一个float
类型的数据。
注意,读取数据的顺序和插入数据的顺序必须一致,否则会读取失败。
4.3 Ative Object对象的写过程
4.3.1 nativeWriteStrongBinder()
static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
299 {
300 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
301 if (parcel != NULL) {
302 const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
303 if (err != NO_ERROR) {
304 signalExceptionForError(env, clazz, err);
305 }
306 }
307 }
4.3.2 ibinderForJavaObject()
sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
707 {
708 if (obj == NULL) return NULL;
709
710 // Instance of Binder?
711 if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
712 JavaBBinderHolder* jbh = (JavaBBinderHolder*)
713 env->GetLongField(obj, gBinderOffsets.mObject);
714 return jbh->get(env, obj);
715 }
716
717 // Instance of BinderProxy?
718 if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
719 return getBPNativeData(env, obj)->mObject;
720 }
721
722 ALOGW("ibinderForJavaObject: %p is not a Binder object", obj);
723 return NULL;
724 }
根据java的binder对象得到native层对应的binder对象:
- 如果是
Binder.java
对象(一般为服务端的xxxservice.java),那么就得到一个JavaBBinder.cpp
对象,其实就是BBinder对象。 - 如果是
BinderProxy.java
对象,那么就得到BpBinder.cpp
对象。
4.3.3 writeStrongBinder()
传入的是一个IBinder 对象。
status_t Parcel::writeStrongBinder(const sp<IBinder>& val)
1135 { // val是binder对象, this是parcel对象,此时为写入
1136 return flatten_binder(ProcessState::self(), val, this);
1137 }
1138
status_t flatten_binder(const sp<ProcessState>& /*proc*/,
205 const sp<IBinder>& binder, Parcel* out)
206 {
207 flat_binder_object obj; // 构造无障碍 flat_binder_object对象
208
209 if (IPCThreadState::self()->backgroundSchedulingDisabled()) {
210 /* minimum priority for all nodes is nice 0 */
211 obj.flags = FLAT_BINDER_FLAG_ACCEPTS_FDS;
212 } else {
213 /* minimum priority for all nodes is MAX_NICE(19) */
214 obj.flags = 0x13 | FLAT_BINDER_FLAG_ACCEPTS_FDS;
215 }
216
217 if (binder != nullptr) {
218 BBinder *local = binder->localBinder();
219 if (!local) {
//不是本地的binder,那么使用远端binder的代理
220 BpBinder *proxy = binder->remoteBinder();
221 if (proxy == nullptr) {
222 ALOGE("null proxy");
223 }
224 const int32_t handle = proxy ? proxy->handle() : 0;
225 obj.hdr.type = BINDER_TYPE_HANDLE; //存入类型为handle
226 obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */
227 obj.handle = handle; //存入handle值
228 obj.cookie = 0;
229 } else {
//本地binder,存入
230 if (local->isRequestingSid()) {
231 obj.flags |= FLAT_BINDER_FLAG_TXN_SECURITY_CTX;
232 }
233 obj.hdr.type = BINDER_TYPE_BINDER; // 类型为binder
234 obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs()); //存入弱引用
// 把本地的binder对象存入到obj的cookies中
235 obj.cookie = reinterpret_cast<uintptr_t>(local);
236 }
237 } else {
238 obj.hdr.type = BINDER_TYPE_BINDER;
239 obj.binder = 0;
240 obj.cookie = 0;
241 }
242
243 return finish_flatten_binder(binder, obj, out);
244 }
245
4.3.4 finish_flatten_binder()
inline static status_t finish_flatten_binder(
199 const sp<IBinder>& /*binder*/, const flat_binder_object& flat, Parcel* out)
200 {
201 return out->writeObject(flat, false);
202 }
费劲心思把IBinder
对象转换成了flat_binder_object
对象,直接写入到parcel中:
4.3.5 writeObject()
status_t Parcel::writeObject(const flat_binder_object& val, bool nullMetaData)
1371 {
1372 const bool enoughData = (mDataPos+sizeof(val)) <= mDataCapacity;
1373 const bool enoughObjects = mObjectsSize < mObjectsCapacity;
1374 if (enoughData && enoughObjects) { //如果parcel中内存足够,则直接存入
//存入val: flat_binder_object
1375 restart_write:
1376 *reinterpret_cast<flat_binder_object*>(mData+mDataPos) = val;
1377
1378 // remember if it's a file descriptor
1379 if (val.hdr.type == BINDER_TYPE_FD) {
1380 if (!mAllowFds) {
1381 // fail before modifying our object index
1382 return FDS_NOT_ALLOWED;
1383 }
1384 mHasFds = mFdsKnown = true;
1385 }
1386
1387 // Need to write meta-data?
1388 if (nullMetaData || val.binder != 0) {
1389 mObjects[mObjectsSize] = mDataPos;
1390 acquire_object(ProcessState::self(), val, this, &mOpenAshmemSize);
1391 mObjectsSize++;
1392 }
1393
1394 return finishWrite(sizeof(flat_binder_object));
1395 }
1396
1397 if (!enoughData) {
//如果parcel中内存不够,则扩容
1398 const status_t err = growData(sizeof(val));
1399 if (err != NO_ERROR) return err;
1400 }
1401 if (!enoughObjects) {
1402 size_t newSize = ((mObjectsSize+2)*3)/2;
1403 if (newSize*sizeof(binder_size_t) < mObjectsSize) return NO_MEMORY; // overflow //溢出
1404 binder_size_t* objects = (binder_size_t*)realloc(mObjects, newSize*sizeof(binder_size_t));
1405 if (objects == nullptr) return NO_MEMORY;
1406 mObjects = objects;
1407 mObjectsCapacity = newSize;
1408 }
1409
1410 goto restart_write; // 扩容后,继续写入
1411 }
1412
至此,我们把一个binder
对象转换成了一个flat_binder_object
的对象,写入到parcel
中(而不是直接写入binder
对象本身)。
binder对象
的读取过程:
4.4 Ative Object对象的读过程
4.4.1 nativeReadStrongBinder()
private static native IBinder nativeReadStrongBinder(long nativePtr);
static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr)
462 {
463 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
464 if (parcel != NULL) {
465 return javaObjectForIBinder(env, parcel->readStrongBinder());
466 }
467 return NULL;
468 }
469
4.4.2 parcel->readStrongBinder()
sp<IBinder> Parcel::readStrongBinder() const
2214 {
2215 sp<IBinder> val;
2216 // Note that a lot of code in Android reads binders by hand with this
2217 // method, and that code has historically been ok with getting nullptr
2218 // back (while ignoring error codes).
2219 readNullableStrongBinder(&val);
2220 return val;
2221 }
4.4.3 unflatten_binder()
status_t Parcel::readNullableStrongBinder(sp<IBinder>* val) const
2209 {
2210 return unflatten_binder(ProcessState::self(), *this, val);
2211 }
status_t unflatten_binder(const sp<ProcessState>& proc,
303 const Parcel& in, sp<IBinder>* out)
304 {// 从parcel中获得 flat_binder_object 对象
305 const flat_binder_object* flat = in.readObject(false);
306
307 if (flat) {
308 switch (flat->hdr.type) {
309 case BINDER_TYPE_BINDER:
//从cookies中强转回得到一个IBinder对象
310 *out = reinterpret_cast<IBinder*>(flat->cookie);
311 return finish_unflatten_binder(nullptr, *flat, in);
312 case BINDER_TYPE_HANDLE:
//从flat的handle得到一个 IBinder代理
313 *out = proc->getStrongProxyForHandle(flat->handle);
314 return finish_unflatten_binder(
315 static_cast<BpBinder*>(out->get()), *flat, in);
316 }
317 }
318 return BAD_TYPE;
319 }
此时,由于是客户端从SM
中获取服务端的Service代理对象
,因此走的是BINDER_TYPE_HANDLE
分支。得到一个BpBinder
对象。具体过程,可参考getService流程。
4.4.4 readObject()
const flat_binder_object* Parcel::readObject(bool nullMetaData) const
2460 {
2461 const size_t DPOS = mDataPos;
2462 if ((DPOS+sizeof(flat_binder_object)) <= mDataSize) {
// 从parcel当前位置,强转得到一个flat 对象:obj
2463 const flat_binder_object* obj
2464 = reinterpret_cast<const flat_binder_object*>(mData+DPOS);
2465 mDataPos = DPOS + sizeof(flat_binder_object);
2466 if (!nullMetaData && (obj->cookie == 0 && obj->binder == 0)) {
2467 // When transferring a NULL object, we don't write it into
2468 // the object list, so we don't want to check for it when
2469 // reading.
2470 ALOGV("readObject Setting data pos of %p to %zu", this, mDataPos);
2471 return obj;
2472 }
2473
2474 ...
2517 return nullptr;
2518 }
4.4.5 proc->getStrongProxyForHandle()
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
260 {
261 sp<IBinder> result;
262
263 AutoMutex _l(mLock);
264
265 handle_entry* e = lookupHandleLocked(handle);
266
267 if (e != nullptr) {
268 // We need to create a new BpBinder if there isn't currently one, OR we
269 // are unable to acquire a weak reference on this current one. See comment
270 // in getWeakProxyForHandle() for more info about this.
271 IBinder* b = e->binder;
272 if (b == nullptr || !e->refs->attemptIncWeak(this)) {
273 ...
300 b = BpBinder::create(handle);
301 e->binder = b;
302 if (b) e->refs = b->getWeakRefs();
303 result = b;
304 } else {
305 // This little bit of nastyness is to allow us to add a primary
306 // reference to the remote proxy when this team doesn't have one
307 // but another team is sending the handle to us.
308 result.force_set(b);
309 e->refs->decWeak(this);
310 }
311 }
312
313 return result;
314 }
根据handle
创建一个bpBinder
对象。
4.4.6 finish_unflatten_binder()
inline static status_t finish_unflatten_binder(
296 BpBinder* /*proxy*/, const flat_binder_object& /*flat*/,
297 const Parcel& /*in*/)
298 {
299 return NO_ERROR;
300 }
这里,啥事都没做,直接返回code。
4.4.7 javaObjectForIBinder()
jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
666 {
667 if (val == NULL) return NULL;
668
669 if (val->checkSubclass(&gBinderOffsets)) {
670 // It's a JavaBBinder created by ibinderForJavaObject. Already has Java object.
671 jobject object = static_cast<JavaBBinder*>(val.get())->object();
672 LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object);
673 return object;
674 }
675
676 BinderProxyNativeData* nativeData = new BinderProxyNativeData();
677 nativeData->mOrgue = new DeathRecipientList;
678 nativeData->mObject = val;
679 //通过反射,构造了BinderProxy.java类,其中的nativeData指向了BpBinder.cpp对象
680 jobject object = env->CallStaticObjectMethod(gBinderProxyOffsets.mClass,
681 gBinderProxyOffsets.mGetInstance, (jlong) nativeData, (jlong) val.get());
682 if (env->ExceptionCheck()) {
683 // In the exception case, getInstance still took ownership of nativeData.
684 return NULL;
685 }
686 BinderProxyNativeData* actualNativeData = getBPNativeData(env, object);
687 if (actualNativeData == nativeData) {
688 // Created a new Proxy
689 uint32_t numProxies = gNumProxies.fetch_add(1, std::memory_order_relaxed);
690 uint32_t numLastWarned = gProxiesWarned.load(std::memory_order_relaxed);
691 if (numProxies >= numLastWarned + PROXY_WARN_INTERVAL) {
692 // Multiple threads can get here, make sure only one of them gets to
693 // update the warn counter.
694 if (gProxiesWarned.compare_exchange_strong(numLastWarned,
695 numLastWarned + PROXY_WARN_INTERVAL, std::memory_order_relaxed)) {
696 ALOGW("Unexpectedly many live BinderProxies: %d\n", numProxies);
697 }
698 }
699 } else {
700 delete nativeData;
701 }
702
703 return object;
704 }
通过反射,构造了BinderProxy.java
对象,其中的nativeData
成员指向了BpBinder.cpp
对象。至此,java层就得到一个IBinder
对象。
4.5 总结
经过以上的分析,我们有了一个基本的认识,不管什么类型的数据,我们通过parcel
提供的接口就能轻松实现数据的序列化和反序列化。而这种序列化的过程是基于内存的。
五、Parcel与Serializable区别
Parcel:
- 基于内存中的序列化
- 把对象拆解,再组装,效率更高
- 不适合序列化到文件和网络
- 对写入数据的和读取数据有顺序要一致,否则会失败
- 一般情况下用于跨进程,当然也可以在同一个进程(
不推荐
)
Serializable:
- 基于网络、文件的序列化。 直接转成二进制,占用内存小。
- 当然也可以基于内存,不过有缺点:但是临时变量多,内存碎片化,导致频繁gc