现在的位置: 首页 > 综合 > 正文

探索Android中的Parcel机制(上)

2013年08月23日 ⁄ 综合 ⁄ 共 17081字 ⁄ 字号 评论关闭

http://blog.csdn.net/caowenbin/article/details/6532217

一.先从Serialize说起

         我们都知道JAVA中的Serialize机制,译成串行化、序列化……,其作用是能将数据对象存入字节流当中,在需要时重新生成对象。主要应用是利用外部存储设备保存对象状态,以及通过网络传输对象等。

 

二.Android中的新的序列化机制

         在Android系统中,定位为针对内存受限的设备,因此对性能要求更高,另外系统中采用了新的IPC(进程间通信)机制,必然要求使用性能更出色的对象传输方式。在这样的环境下,Parcel被设计出来,其定位就是轻量级的高效的对象序列化和反序列化机制。

 

三.Parcel类的背后

         在Framework中有parcel类,源码路径是:

Frameworks/base/core/java/android/os/Parcel.java

典型的源码片断如下:

 

 

  1. /** 
  2.  * Write an integer value into the parcel at the current dataPosition(), 
  3.  * growing dataCapacity() if needed. 
  4.  */  
  5. public final native void writeInt(int val);  
  6.   
  7. /** 
  8.  * Write a long integer value into the parcel at the current dataPosition(), 
  9.  * growing dataCapacity() if needed. 
  10.  */  
  11. public final native void writeLong(long val);  

  

 

         从中我们看到,从这个源程序文件中我们看不到真正的功能是如何实现的,必须透过JNI往下走了。于是,Frameworks/base/core/jni/android_util_Binder.cpp中找到了线索

 

  1. static void android_os_Parcel_writeInt(JNIEnv* env, jobject clazz, jint val)  
  2. {  
  3.     Parcel* parcel = parcelForJavaObject(env, clazz);  
  4.     if (parcel != NULL) {  
  5.         const status_t err = parcel->writeInt32(val);  
  6.         if (err != NO_ERROR) {  
  7.             jniThrowException(env, "java/lang/OutOfMemoryError", NULL);  
  8.         }  
  9.     }  
  10. }  
  11.   
  12. static void android_os_Parcel_writeLong(JNIEnv* env, jobject clazz, jlong val)  
  13. {  
  14.     Parcel* parcel = parcelForJavaObject(env, clazz);  
  15.     if (parcel != NULL) {  
  16.         const status_t err = parcel->writeInt64(val);  
  17.         if (err != NO_ERROR) {  
  18.             jniThrowException(env, "java/lang/OutOfMemoryError", NULL);  
  19.         }  
  20.     }  
  21. }  

  

         从这里我们可以得到的信息是函数的实现依赖于Parcel指针,因此还需要找到Parcel的类定义,注意,这里的类已经是用C++语言实现的了。

         找到Frameworks/base/include/binder/parcel.h和Frameworks/base/libs/binder/parcel.cpp。终于找到了最终的实现代码了。

         有兴趣的朋友可以自己读一下,不难理解,这里把基本的思路总结一下:

1.       整个读写全是在内存中进行,主要是通过malloc()、realloc()、memcpy()等内存操作进行,所以效率比JAVA序列化中使用外部存储器会高很多;

2.       读写时是4字节对齐的,可以看到#define PAD_SIZE(s) (((s)+3)&~3)这句宏定义就是在做这件事情;

3.       如果预分配的空间不够时newSize = ((mDataSize+len)*3)/2;会一次多分配50%;

4.       对于普通数据,使用的是mData内存地址,对于IBinder类型的数据以及FileDescriptor使用的是mObjects内存地址。后者是通过flatten_binder()和unflatten_binder()实现的,目的是反序列化时读出的对象就是原对象而不用重新new一个新对象。

 

好了,这就是Parcel背后的动作,全是在一块内存里进行读写操作,就不啰嗦了,把parcel的代码贴在这供没有源码的朋友参考吧。接下来我会用一个小DEMO演示一下Parcel类在应用程序中的使用,详见《探索Android中的Parcel机制(下)》。

 

  1. /* 
  2.  * Copyright (C) 2005 The Android Open Source Project 
  3.  * 
  4.  * Licensed under the Apache License, Version 2.0 (the "License"); 
  5.  * you may not use this file except in compliance with the License. 
  6.  * You may obtain a copy of the License at 
  7.  * 
  8.  *      http://www.apache.org/licenses/LICENSE-2.0 
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software 
  11.  * distributed under the License is distributed on an "AS IS" BASIS, 
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  13.  * See the License for the specific language governing permissions and 
  14.  * limitations under the License. 
  15.  */  
  16.   
  17. #ifndef ANDROID_PARCEL_H  
  18. #define ANDROID_PARCEL_H  
  19.   
  20. #include <cutils/native_handle.h>  
  21. #include <utils/Errors.h>  
  22. #include <utils/RefBase.h>  
  23. #include <utils/String16.h>  
  24. #include <utils/Vector.h>  
  25.   
  26. // ---------------------------------------------------------------------------  
  27. namespace android {  
  28.   
  29. class IBinder;  
  30. class ProcessState;  
  31. class String8;  
  32. class TextOutput;  
  33. class Flattenable;  
  34.   
  35. struct flat_binder_object;  // defined in support_p/binder_module.h  
  36.   
  37. class Parcel  
  38. {  
  39. public:  
  40.                         Parcel();  
  41.                         ~Parcel();  
  42.       
  43.     const uint8_t*      data() const;  
  44.     size_t              dataSize() const;  
  45.     size_t              dataAvail() const;  
  46.     size_t              dataPosition() const;  
  47.     size_t              dataCapacity() const;  
  48.       
  49.     status_t            setDataSize(size_t size);  
  50.     void                setDataPosition(size_t pos) const;  
  51.     status_t            setDataCapacity(size_t size);  
  52.       
  53.     status_t            setData(const uint8_t* buffer, size_t len);  
  54.   
  55.     status_t            appendFrom(Parcel *parcel, size_t start, size_t len);  
  56.   
  57.     bool                hasFileDescriptors() const;  
  58.   
  59.     status_t            writeInterfaceToken(const String16& interface);  
  60.     bool                enforceInterface(const String16& interface) const;  
  61.     bool                checkInterface(IBinder*) const;      
  62.   
  63.     void                freeData();  
  64.   
  65.     const size_t*       objects() const;  
  66.     size_t              objectsCount() const;  
  67.       
  68.     status_t            errorCheck() const;  
  69.     void                setError(status_t err);  
  70.       
  71.     status_t            write(const void* data, size_t len);  
  72.     void*               writeInplace(size_t len);  
  73.     status_t            writeUnpadded(const void* data, size_t len);  
  74.     status_t            writeInt32(int32_t val);  
  75.     status_t            writeInt64(int64_t val);  
  76.     status_t            writeFloat(float val);  
  77.     status_t            writeDouble(double val);  
  78.     status_t            writeIntPtr(intptr_t val);  
  79.     status_t            writeCString(const char* str);  
  80.     status_t            writeString8(const String8& str);  
  81.     status_t            writeString16(const String16& str);  
  82.     status_t            writeString16(const char16_t* str, size_t len);  
  83.     status_t            writeStrongBinder(const sp<IBinder>& val);  
  84.     status_t            writeWeakBinder(const wp<IBinder>& val);  
  85.     status_t            write(const Flattenable& val);  
  86.   
  87.     // Place a native_handle into the parcel (the native_handle's file-  
  88.     // descriptors are dup'ed, so it is safe to delete the native_handle  
  89.     // when this function returns).   
  90.     // Doesn't take ownership of the native_handle.  
  91.     status_t            writeNativeHandle(const native_handle* handle);  
  92.       
  93.     // Place a file descriptor into the parcel.  The given fd must remain  
  94.     // valid for the lifetime of the parcel.  
  95.     status_t            writeFileDescriptor(int fd);  
  96.       
  97.     // Place a file descriptor into the parcel.  A dup of the fd is made, which  
  98.     // will be closed once the parcel is destroyed.  
  99.     status_t            writeDupFileDescriptor(int fd);  
  100.       
  101.     status_t            writeObject(const flat_binder_object& val, bool nullMetaData);  
  102.   
  103.     void                remove(size_t start, size_t amt);  
  104.       
  105.     status_t            read(void* outData, size_t len) const;  
  106.     const void*         readInplace(size_t len) const;  
  107.     int32_t             readInt32() const;  
  108.     status_t            readInt32(int32_t *pArg) const;  
  109.     int64_t             readInt64() const;  
  110.     status_t            readInt64(int64_t *pArg) const;  
  111.     float               readFloat() const;  
  112.     status_t            readFloat(float *pArg) const;  
  113.     double              readDouble() const;  
  114.     status_t            readDouble(double *pArg) const;  
  115.     intptr_t            readIntPtr() const;  
  116.     status_t            readIntPtr(intptr_t *pArg) const;  
  117.   
  118.     const char*         readCString() const;  
  119.     String8             readString8() const;  
  120.     String16            readString16() const;  
  121.     const char16_t*     readString16Inplace(size_t* outLen) const;  
  122.     sp<IBinder>         readStrongBinder() const;  
  123.     wp<IBinder>         readWeakBinder() const;  
  124.     status_t            read(Flattenable& val) const;  
  125.       
  126.     // Retrieve native_handle from the parcel. This returns a copy of the  
  127.     // parcel's native_handle (the caller takes ownership). The caller  
  128.     // must free the native_handle with native_handle_close() and   
  129.     // native_handle_delete().  
  130.     native_handle*     readNativeHandle() const;  
  131.   
  132.       
  133.     // Retrieve a file descriptor from the parcel.  This returns the raw fd  
  134.     // in the parcel, which you do not own -- use dup() to get your own copy.  
  135.     int                 readFileDescriptor() const;  
  136.       
  137.     const flat_binder_object* readObject(bool nullMetaData) const;  
  138.   
  139.     // Explicitly close all file descriptors in the parcel.  
  140.     void                closeFileDescriptors();  
  141.       
  142.     typedef void        (*release_func)(Parcel* parcel,  
  143.                                         const uint8_t* data, size_t dataSize,  
  144.                                         const size_t* objects, size_t objectsSize,  
  145.                                         void* cookie);  
  146.                           
  147.     const uint8_t*      ipcData() const;  
  148.     size_t              ipcDataSize() const;  
  149.     const size_t*       ipcObjects() const;  
  150.     size_t              ipcObjectsCount() const;  
  151.     void                ipcSetDataReference(const uint8_t* data, size_t dataSize,  
  152.                                             const size_t* objects, size_t objectsCount,  
  153.                                             release_func relFunc, void* relCookie);  
  154.       
  155.     void                print(TextOutput& to, uint32_t flags = 0) const;  
  156.           
  157. private:  
  158.                         Parcel(const Parcel& o);  
  159.     Parcel&             operator=(const Parcel& o);  
  160.       
  161.     status_t            finishWrite(size_t len);  
  162.     void                releaseObjects();  
  163.     void                acquireObjects();  
  164.     status_t            growData(size_t len);  
  165.     status_t            restartWrite(size_t desired);  
  166.     status_t            continueWrite(size_t desired);  
  167.     void                freeDataNoInit();  
  168.     void                initState();  
  169.     void                scanForFds() const;  
  170.                           
  171.     template<class T>  
  172.     status_t            readAligned(T *pArg) const;  
  173.   
  174.     template<class T>   T readAligned() const;  
  175.   
  176.     template<class T>  
  177.     status_t            writeAligned(T val);  
  178.   
  179.     status_t            mError;  
  180.     uint8_t*            mData;  
  181.     size_t              mDataSize;  
  182.     size_t              mDataCapacity;  
  183.     mutable size_t      mDataPos;  
  184.     size_t*             mObjects;  
  185.     size_t              mObjectsSize;  
  186.     size_t              mObjectsCapacity;  
  187.     mutable size_t      mNextObjectHint;  
  188.   
  189.     mutable bool        mFdsKnown;  
  190.     mutable bool        mHasFds;  
  191.       
  192.     release_func        mOwner;  
  193.     void*               mOwnerCookie;  
  194. };  
  195.   
  196. // ---------------------------------------------------------------------------  
  197.   
  198. inline TextOutput& operator<<(TextOutput& to, const Parcel& parcel)  
  199. {  
  200.     parcel.print(to);  
  201.     return to;  
  202. }  
  203.   
  204. // ---------------------------------------------------------------------------  
  205.   
  206. // Generic acquire and release of objects.  
  207. void acquire_object(const sp<ProcessState>& proc,  
  208.                     const flat_binder_object& obj, const void* who);  
  209. void release_object(const sp<ProcessState>& proc,  
  210.                     const flat_binder_object& obj, const void* who);  
  211.   
  212. void flatten_binder(const sp<ProcessState>& proc,  
  213.                     const sp<IBinder>& binder, flat_binder_object* out);  
  214. void flatten_binder(const sp<ProcessState>& proc,  
  215.                     const wp<IBinder>& binder, flat_binder_object* out);  
  216. status_t unflatten_binder(const sp<ProcessState>& proc,  
  217.                           const flat_binder_object& flat, sp<IBinder>* out);  
  218. status_t unflatten_binder(const sp<ProcessState>& proc,  
  219.                           const flat_binder_object& flat, wp<IBinder>* out);  
  220.   
  221. }; // namespace android  
  222.   
  223. // ---------------------------------------------------------------------------  
  224.   
  225. #endif // ANDROID_PARCEL_H  

 

  1. /* 
  2.  * Copyright (C) 2005 The Android Open Source Project 
  3.  * 
  4.  * Licensed under the Apache License, Version 2.0 (the "License"); 
  5.  * you may not use this file except in compliance with the License. 
  6.  * You may obtain a copy of the License at 
  7.  * 
  8.  *      http://www.apache.org/licenses/LICENSE-2.0 
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software 
  11.  * distributed under the License is distributed on an "AS IS" BASIS, 
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  13.  * See the License for the specific language governing permissions and 
  14.  * limitations under the License. 
  15.  */  
  16.   
  17. #define LOG_TAG "Parcel"  
  18. //#define LOG_NDEBUG 0  
  19.   
  20. #include <binder/Parcel.h>  
  21.   
  22. #include <binder/Binder.h>  
  23. #include <binder/BpBinder.h>  
  24. #include <utils/Debug.h>  
  25. #include <binder/ProcessState.h>  
  26. #include <utils/Log.h>  
  27. #include <utils/String8.h>  
  28. #include <utils/String16.h>  
  29. #include <utils/TextOutput.h>  
  30. #include <utils/misc.h>  
  31. #include <utils/Flattenable.h>  
  32.   
  33. #include <private/binder/binder_module.h>  
  34.   
  35. #include <stdio.h>  
  36. #include <stdlib.h>  
  37. #include <stdint.h>  
  38.   
  39. #ifndef INT32_MAX  
  40. #define INT32_MAX ((int32_t)(2147483647))  
  41. #endif  
  42.   
  43. #define LOG_REFS(...)  
  44. //#define LOG_REFS(...) LOG(LOG_DEBUG, "Parcel", __VA_ARGS__)  
  45.   
  46. // ---------------------------------------------------------------------------  
  47.   
  48. #define PAD_SIZE(s) (((s)+3)&~3)  
  49.   
  50. // XXX This can be made public if we want to provide  
  51. // support for typed data.  
  52. struct small_flat_data  
  53. {  
  54.     uint32_t type;  
  55.     uint32_t data;  
  56. };  
  57.   
  58. namespace android {  
  59.   
  60. void acquire_object(const sp<ProcessState>& proc,  
  61.     const flat_binder_object& obj, const void* who)  
  62. {  
  63.     switch (obj.type) {  
  64.         case BINDER_TYPE_BINDER:  
  65.             if (obj.binder) {  
  66.                 LOG_REFS("Parcel %p acquiring reference on local %p", who, obj.cookie);  
  67.                 static_cast<IBinder*>(obj.cookie)->incStrong(who);  
  68.             }  
  69.             return;  
  70.         case BINDER_TYPE_WEAK_BINDER:  
  71.             if (obj.binder)  
  72.                 static_cast<RefBase::weakref_type*>(obj.binder)->incWeak(who);  
  73.             return;  
  74.         case BINDER_TYPE_HANDLE: {  
  75.             const sp<IBinder> b = proc->getStrongProxyForHandle(obj.handle);  
  76.             if (b != NULL) {  
  77.                 LOG_REFS("Parcel %p acquiring reference on remote %p", who, b.get());  
  78.                 b->incStrong(who);  
  79.             }  
  80.             return;  
  81.         }  
  82.         case BINDER_TYPE_WEAK_HANDLE: {  
  83.             const wp<IBinder> b = proc->getWeakProxyForHandle(obj.handle);  
  84.             if (b != NULL) b.get_refs()->incWeak(who);  
  85.             return;  
  86.         }  
  87.         case BINDER_TYPE_FD: {  
  88.             // intentionally blank -- nothing to do to acquire this, but we do  
  89.             // recognize it as a legitimate object type.  
  90.             return;  
  91.         }  
  92.     }  
  93.   
  94.     LOGD("Invalid object type 0x%08lx", obj.type);  
  95. }  
  96.   
  97. void release_object(const sp<ProcessState>& proc,  
  98.     const flat_binder_object& obj, const void* who)  
  99. {  
  100.     switch (obj.type) {  
  101.         case BINDER_TYPE_BINDER:  
  102.             if (obj.binder) {  
  103.                 LOG_REFS("Parcel %p releasing reference on local %p", who, obj.cookie);  
  104.                 static_cast<IBinder*>(obj.cookie)->decStrong(who);  
  105.             }  
  106.             return;  
  107.         case BINDER_TYPE_WEAK_BINDER:  
  108.             if (obj.binder)  
  109.                 static_cast<RefBase::weakref_type*>(obj.binder)->decWeak(who);  
  110.             return;  
  111.         case BINDER_TYPE_HANDLE: {  
  112.             const sp<IBinder> b = proc->getStrongProxyForHandle(obj.handle);  
  113.             if (b != NULL) {  
  114.                 LOG_REFS("Parcel %p releasing reference on remote %p", who, b.get());  
  115.                 b->decStrong(who);  
  116.             }  
  117.             return;  
  118.         }  
  119.         case BINDER_TYPE_WEAK_HANDLE: {  
  120.             const wp<IBinder> b = proc->getWeakProxyForHandle(obj.handle);  
  121.             if (b != NULL) b.get_refs()->decWeak(who);  
  122.             return;  
  123.         }  
  124.         case BINDER_TYPE_FD: {  
  125.             if (obj.cookie != (void*)0) close(obj.handle);  
  126.             return;  
  127.         }  
  128.     }  
  129.   
  130.     LOGE("Invalid object type 0x%08lx", obj.type);  
  131. }  
  132.   
  133. inline static status_t finish_flatten_binder(  
  134.     const sp<IBinder>& binder, const flat_binder_object& flat, Parcel* out)  
  135. {  
  136.     return out->writeObject(flat, false);  
  137. }  
  138.   
  139. status_t flatten_binder(const sp<ProcessState>& proc,  
  140.     const sp<IBinder>& binder, Parcel* out)  
  141. {  
  142.     flat_binder_object obj;  
  143.       
  144.     obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;  
  145.     if (binder != NULL) {  
  146.         IBinder *local = binder->localBinder();  
  147.         if (!local) {  
  148.             BpBinder *proxy = binder->remoteBinder();  
  149.             if (proxy == NULL) {  
  150.                 LOGE("null proxy");  
  151.             }  
  152.             const int32_t handle = proxy ? proxy->handle() : 0;  
  153.             obj.type = BINDER_TYPE_HANDLE;  
  154.             obj.handle = handle;  
  155.             obj.cookie = NULL;  
  156.         } else {  
  157.             obj.type = BINDER_TYPE_BINDER;  
  158.             obj.binder = local->getWeakRefs();  
  159.             obj.cookie = local;  
  160.         }  
  161.     } else {  
  162.         obj.type = BINDER_TYPE_BINDER;  
  163.         obj.binder = NULL;  
  164.         obj.cookie = NULL;  
  165.     }  
  166.       
  167.     return finish_flatten_binder(binder, obj, out);  
  168. }  
  169.   
  170. status_t flatten_binder(const sp<ProcessState>& proc,  
  171.     const wp<IBinder>& binder, Parcel* out)  
  172. {  
  173.     flat_binder_object obj;  
  174.       
  175.     obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;  
  176.     if (binder != NULL) {  
  177.         sp<IBinder> real = binder.promote();  
  178.         if (real != NULL) {  
  179.             IBinder *local = real->localBinder();  
  180.             if (!local) {  
  181.                 BpBinder *proxy = real->remoteBinder();  

抱歉!评论已关闭.