Loading include/binder/Parcel.h +17 −5 Original line number Original line Diff line number Diff line Loading @@ -60,6 +60,7 @@ public: status_t appendFrom(const Parcel *parcel, status_t appendFrom(const Parcel *parcel, size_t start, size_t len); size_t start, size_t len); bool allowFds() const; bool pushAllowFds(bool allowFds); bool pushAllowFds(bool allowFds); void restoreAllowFds(bool lastValue); void restoreAllowFds(bool lastValue); Loading Loading @@ -132,9 +133,16 @@ public: // Writes a blob to the parcel. // Writes a blob to the parcel. // If the blob is small, then it is stored in-place, otherwise it is // If the blob is small, then it is stored in-place, otherwise it is // transferred by way of an anonymous shared memory region. // transferred by way of an anonymous shared memory region. Prefer sending // immutable blobs if possible since they may be subsequently transferred between // processes without further copying whereas mutable blobs always need to be copied. // The caller should call release() on the blob after writing its contents. // The caller should call release() on the blob after writing its contents. status_t writeBlob(size_t len, WritableBlob* outBlob); status_t writeBlob(size_t len, bool mutableCopy, WritableBlob* outBlob); // Write an existing immutable blob file descriptor to the parcel. // This allows the client to send the same blob to multiple processes // as long as it keeps a dup of the blob file descriptor handy for later. status_t writeDupImmutableBlobFileDescriptor(int fd); status_t writeObject(const flat_binder_object& val, bool nullMetaData); status_t writeObject(const flat_binder_object& val, bool nullMetaData); Loading Loading @@ -270,16 +278,19 @@ private: Blob(); Blob(); ~Blob(); ~Blob(); void clear(); void release(); void release(); inline size_t size() const { return mSize; } inline size_t size() const { return mSize; } inline int fd() const { return mFd; }; inline bool isMutable() const { return mMutable; } protected: protected: void init(bool mapped, void* data, size_t size); void init(int fd, void* data, size_t size, bool isMutable); void clear(); bool mMapped; int mFd; // owned by parcel so not closed when released void* mData; void* mData; size_t mSize; size_t mSize; bool mMutable; }; }; class FlattenableHelperInterface { class FlattenableHelperInterface { Loading Loading @@ -320,6 +331,7 @@ public: friend class Parcel; friend class Parcel; public: public: inline const void* data() const { return mData; } inline const void* data() const { return mData; } inline void* mutableData() { return isMutable() ? mData : NULL; } }; }; class WritableBlob : public Blob { class WritableBlob : public Blob { Loading libs/binder/Parcel.cpp +48 −23 Original line number Original line Diff line number Diff line Loading @@ -72,9 +72,6 @@ static size_t pad_size(size_t s) { // Note: must be kept in sync with android/os/Parcel.java's EX_HAS_REPLY_HEADER // Note: must be kept in sync with android/os/Parcel.java's EX_HAS_REPLY_HEADER #define EX_HAS_REPLY_HEADER -128 #define EX_HAS_REPLY_HEADER -128 // Maximum size of a blob to transfer in-place. static const size_t IN_PLACE_BLOB_LIMIT = 40 * 1024; // XXX This can be made public if we want to provide // XXX This can be made public if we want to provide // support for typed data. // support for typed data. struct small_flat_data struct small_flat_data Loading @@ -89,6 +86,15 @@ static pthread_mutex_t gParcelGlobalAllocSizeLock = PTHREAD_MUTEX_INITIALIZER; static size_t gParcelGlobalAllocSize = 0; static size_t gParcelGlobalAllocSize = 0; static size_t gParcelGlobalAllocCount = 0; static size_t gParcelGlobalAllocCount = 0; // Maximum size of a blob to transfer in-place. static const size_t BLOB_INPLACE_LIMIT = 16 * 1024; enum { BLOB_INPLACE = 0, BLOB_ASHMEM_IMMUTABLE = 1, BLOB_ASHMEM_MUTABLE = 2, }; void acquire_object(const sp<ProcessState>& proc, void acquire_object(const sp<ProcessState>& proc, const flat_binder_object& obj, const void* who) const flat_binder_object& obj, const void* who) { { Loading Loading @@ -516,6 +522,11 @@ status_t Parcel::appendFrom(const Parcel *parcel, size_t offset, size_t len) return err; return err; } } bool Parcel::allowFds() const { return mAllowFds; } bool Parcel::pushAllowFds(bool allowFds) bool Parcel::pushAllowFds(bool allowFds) { { const bool origValue = mAllowFds; const bool origValue = mAllowFds; Loading Loading @@ -886,25 +897,24 @@ status_t Parcel::writeDupFileDescriptor(int fd) return err; return err; } } status_t Parcel::writeBlob(size_t len, WritableBlob* outBlob) status_t Parcel::writeBlob(size_t len, bool mutableCopy, WritableBlob* outBlob) { { status_t status; if (len > INT32_MAX) { if (len > INT32_MAX) { // don't accept size_t values which may have come from an // don't accept size_t values which may have come from an // inadvertent conversion from a negative int. // inadvertent conversion from a negative int. return BAD_VALUE; return BAD_VALUE; } } if (!mAllowFds || len <= IN_PLACE_BLOB_LIMIT) { status_t status; if (!mAllowFds || len <= BLOB_INPLACE_LIMIT) { ALOGV("writeBlob: write in place"); ALOGV("writeBlob: write in place"); status = writeInt32(0); status = writeInt32(BLOB_INPLACE); if (status) return status; if (status) return status; void* ptr = writeInplace(len); void* ptr = writeInplace(len); if (!ptr) return NO_MEMORY; if (!ptr) return NO_MEMORY; outBlob->init(false /*mapped*/, ptr, len); outBlob->init(-1, ptr, len, false); return NO_ERROR; return NO_ERROR; } } Loading @@ -922,15 +932,17 @@ status_t Parcel::writeBlob(size_t len, WritableBlob* outBlob) if (ptr == MAP_FAILED) { if (ptr == MAP_FAILED) { status = -errno; status = -errno; } else { } else { if (!mutableCopy) { result = ashmem_set_prot_region(fd, PROT_READ); result = ashmem_set_prot_region(fd, PROT_READ); } if (result < 0) { if (result < 0) { status = result; status = result; } else { } else { status = writeInt32(1); status = writeInt32(mutableCopy ? BLOB_ASHMEM_MUTABLE : BLOB_ASHMEM_IMMUTABLE); if (!status) { if (!status) { status = writeFileDescriptor(fd, true /*takeOwnership*/); status = writeFileDescriptor(fd, true /*takeOwnership*/); if (!status) { if (!status) { outBlob->init(true /*mapped*/, ptr, len); outBlob->init(fd, ptr, len, mutableCopy); return NO_ERROR; return NO_ERROR; } } } } Loading @@ -942,6 +954,15 @@ status_t Parcel::writeBlob(size_t len, WritableBlob* outBlob) return status; return status; } } status_t Parcel::writeDupImmutableBlobFileDescriptor(int fd) { // Must match up with what's done in writeBlob. if (!mAllowFds) return FDS_NOT_ALLOWED; status_t status = writeInt32(BLOB_ASHMEM_IMMUTABLE); if (status) return status; return writeDupFileDescriptor(fd); } status_t Parcel::write(const FlattenableHelperInterface& val) status_t Parcel::write(const FlattenableHelperInterface& val) { { status_t err; status_t err; Loading Loading @@ -1354,27 +1375,29 @@ int Parcel::readFileDescriptor() const status_t Parcel::readBlob(size_t len, ReadableBlob* outBlob) const status_t Parcel::readBlob(size_t len, ReadableBlob* outBlob) const { { int32_t useAshmem; int32_t blobType; status_t status = readInt32(&useAshmem); status_t status = readInt32(&blobType); if (status) return status; if (status) return status; if (!useAshmem) { if (blobType == BLOB_INPLACE) { ALOGV("readBlob: read in place"); ALOGV("readBlob: read in place"); const void* ptr = readInplace(len); const void* ptr = readInplace(len); if (!ptr) return BAD_VALUE; if (!ptr) return BAD_VALUE; outBlob->init(false /*mapped*/, const_cast<void*>(ptr), len); outBlob->init(-1, const_cast<void*>(ptr), len, false); return NO_ERROR; return NO_ERROR; } } ALOGV("readBlob: read from ashmem"); ALOGV("readBlob: read from ashmem"); bool isMutable = (blobType == BLOB_ASHMEM_MUTABLE); int fd = readFileDescriptor(); int fd = readFileDescriptor(); if (fd == int(BAD_TYPE)) return BAD_VALUE; if (fd == int(BAD_TYPE)) return BAD_VALUE; void* ptr = ::mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0); void* ptr = ::mmap(NULL, len, isMutable ? PROT_READ | PROT_WRITE : PROT_READ, MAP_SHARED, fd, 0); if (ptr == MAP_FAILED) return NO_MEMORY; if (ptr == MAP_FAILED) return NO_MEMORY; outBlob->init(true /*mapped*/, ptr, len); outBlob->init(fd, ptr, len, isMutable); return NO_ERROR; return NO_ERROR; } } Loading Loading @@ -1890,7 +1913,7 @@ size_t Parcel::getBlobAshmemSize() const // --- Parcel::Blob --- // --- Parcel::Blob --- Parcel::Blob::Blob() : Parcel::Blob::Blob() : mMapped(false), mData(NULL), mSize(0) { mFd(-1), mData(NULL), mSize(0), mMutable(false) { } } Parcel::Blob::~Blob() { Parcel::Blob::~Blob() { Loading @@ -1898,22 +1921,24 @@ Parcel::Blob::~Blob() { } } void Parcel::Blob::release() { void Parcel::Blob::release() { if (mMapped && mData) { if (mFd != -1 && mData) { ::munmap(mData, mSize); ::munmap(mData, mSize); } } clear(); clear(); } } void Parcel::Blob::init(bool mapped, void* data, size_t size) { void Parcel::Blob::init(int fd, void* data, size_t size, bool isMutable) { mMapped = mapped; mFd = fd; mData = data; mData = data; mSize = size; mSize = size; mMutable = isMutable; } } void Parcel::Blob::clear() { void Parcel::Blob::clear() { mMapped = false; mFd = -1; mData = NULL; mData = NULL; mSize = 0; mSize = 0; mMutable = false; } } }; // namespace android }; // namespace android Loading
include/binder/Parcel.h +17 −5 Original line number Original line Diff line number Diff line Loading @@ -60,6 +60,7 @@ public: status_t appendFrom(const Parcel *parcel, status_t appendFrom(const Parcel *parcel, size_t start, size_t len); size_t start, size_t len); bool allowFds() const; bool pushAllowFds(bool allowFds); bool pushAllowFds(bool allowFds); void restoreAllowFds(bool lastValue); void restoreAllowFds(bool lastValue); Loading Loading @@ -132,9 +133,16 @@ public: // Writes a blob to the parcel. // Writes a blob to the parcel. // If the blob is small, then it is stored in-place, otherwise it is // If the blob is small, then it is stored in-place, otherwise it is // transferred by way of an anonymous shared memory region. // transferred by way of an anonymous shared memory region. Prefer sending // immutable blobs if possible since they may be subsequently transferred between // processes without further copying whereas mutable blobs always need to be copied. // The caller should call release() on the blob after writing its contents. // The caller should call release() on the blob after writing its contents. status_t writeBlob(size_t len, WritableBlob* outBlob); status_t writeBlob(size_t len, bool mutableCopy, WritableBlob* outBlob); // Write an existing immutable blob file descriptor to the parcel. // This allows the client to send the same blob to multiple processes // as long as it keeps a dup of the blob file descriptor handy for later. status_t writeDupImmutableBlobFileDescriptor(int fd); status_t writeObject(const flat_binder_object& val, bool nullMetaData); status_t writeObject(const flat_binder_object& val, bool nullMetaData); Loading Loading @@ -270,16 +278,19 @@ private: Blob(); Blob(); ~Blob(); ~Blob(); void clear(); void release(); void release(); inline size_t size() const { return mSize; } inline size_t size() const { return mSize; } inline int fd() const { return mFd; }; inline bool isMutable() const { return mMutable; } protected: protected: void init(bool mapped, void* data, size_t size); void init(int fd, void* data, size_t size, bool isMutable); void clear(); bool mMapped; int mFd; // owned by parcel so not closed when released void* mData; void* mData; size_t mSize; size_t mSize; bool mMutable; }; }; class FlattenableHelperInterface { class FlattenableHelperInterface { Loading Loading @@ -320,6 +331,7 @@ public: friend class Parcel; friend class Parcel; public: public: inline const void* data() const { return mData; } inline const void* data() const { return mData; } inline void* mutableData() { return isMutable() ? mData : NULL; } }; }; class WritableBlob : public Blob { class WritableBlob : public Blob { Loading
libs/binder/Parcel.cpp +48 −23 Original line number Original line Diff line number Diff line Loading @@ -72,9 +72,6 @@ static size_t pad_size(size_t s) { // Note: must be kept in sync with android/os/Parcel.java's EX_HAS_REPLY_HEADER // Note: must be kept in sync with android/os/Parcel.java's EX_HAS_REPLY_HEADER #define EX_HAS_REPLY_HEADER -128 #define EX_HAS_REPLY_HEADER -128 // Maximum size of a blob to transfer in-place. static const size_t IN_PLACE_BLOB_LIMIT = 40 * 1024; // XXX This can be made public if we want to provide // XXX This can be made public if we want to provide // support for typed data. // support for typed data. struct small_flat_data struct small_flat_data Loading @@ -89,6 +86,15 @@ static pthread_mutex_t gParcelGlobalAllocSizeLock = PTHREAD_MUTEX_INITIALIZER; static size_t gParcelGlobalAllocSize = 0; static size_t gParcelGlobalAllocSize = 0; static size_t gParcelGlobalAllocCount = 0; static size_t gParcelGlobalAllocCount = 0; // Maximum size of a blob to transfer in-place. static const size_t BLOB_INPLACE_LIMIT = 16 * 1024; enum { BLOB_INPLACE = 0, BLOB_ASHMEM_IMMUTABLE = 1, BLOB_ASHMEM_MUTABLE = 2, }; void acquire_object(const sp<ProcessState>& proc, void acquire_object(const sp<ProcessState>& proc, const flat_binder_object& obj, const void* who) const flat_binder_object& obj, const void* who) { { Loading Loading @@ -516,6 +522,11 @@ status_t Parcel::appendFrom(const Parcel *parcel, size_t offset, size_t len) return err; return err; } } bool Parcel::allowFds() const { return mAllowFds; } bool Parcel::pushAllowFds(bool allowFds) bool Parcel::pushAllowFds(bool allowFds) { { const bool origValue = mAllowFds; const bool origValue = mAllowFds; Loading Loading @@ -886,25 +897,24 @@ status_t Parcel::writeDupFileDescriptor(int fd) return err; return err; } } status_t Parcel::writeBlob(size_t len, WritableBlob* outBlob) status_t Parcel::writeBlob(size_t len, bool mutableCopy, WritableBlob* outBlob) { { status_t status; if (len > INT32_MAX) { if (len > INT32_MAX) { // don't accept size_t values which may have come from an // don't accept size_t values which may have come from an // inadvertent conversion from a negative int. // inadvertent conversion from a negative int. return BAD_VALUE; return BAD_VALUE; } } if (!mAllowFds || len <= IN_PLACE_BLOB_LIMIT) { status_t status; if (!mAllowFds || len <= BLOB_INPLACE_LIMIT) { ALOGV("writeBlob: write in place"); ALOGV("writeBlob: write in place"); status = writeInt32(0); status = writeInt32(BLOB_INPLACE); if (status) return status; if (status) return status; void* ptr = writeInplace(len); void* ptr = writeInplace(len); if (!ptr) return NO_MEMORY; if (!ptr) return NO_MEMORY; outBlob->init(false /*mapped*/, ptr, len); outBlob->init(-1, ptr, len, false); return NO_ERROR; return NO_ERROR; } } Loading @@ -922,15 +932,17 @@ status_t Parcel::writeBlob(size_t len, WritableBlob* outBlob) if (ptr == MAP_FAILED) { if (ptr == MAP_FAILED) { status = -errno; status = -errno; } else { } else { if (!mutableCopy) { result = ashmem_set_prot_region(fd, PROT_READ); result = ashmem_set_prot_region(fd, PROT_READ); } if (result < 0) { if (result < 0) { status = result; status = result; } else { } else { status = writeInt32(1); status = writeInt32(mutableCopy ? BLOB_ASHMEM_MUTABLE : BLOB_ASHMEM_IMMUTABLE); if (!status) { if (!status) { status = writeFileDescriptor(fd, true /*takeOwnership*/); status = writeFileDescriptor(fd, true /*takeOwnership*/); if (!status) { if (!status) { outBlob->init(true /*mapped*/, ptr, len); outBlob->init(fd, ptr, len, mutableCopy); return NO_ERROR; return NO_ERROR; } } } } Loading @@ -942,6 +954,15 @@ status_t Parcel::writeBlob(size_t len, WritableBlob* outBlob) return status; return status; } } status_t Parcel::writeDupImmutableBlobFileDescriptor(int fd) { // Must match up with what's done in writeBlob. if (!mAllowFds) return FDS_NOT_ALLOWED; status_t status = writeInt32(BLOB_ASHMEM_IMMUTABLE); if (status) return status; return writeDupFileDescriptor(fd); } status_t Parcel::write(const FlattenableHelperInterface& val) status_t Parcel::write(const FlattenableHelperInterface& val) { { status_t err; status_t err; Loading Loading @@ -1354,27 +1375,29 @@ int Parcel::readFileDescriptor() const status_t Parcel::readBlob(size_t len, ReadableBlob* outBlob) const status_t Parcel::readBlob(size_t len, ReadableBlob* outBlob) const { { int32_t useAshmem; int32_t blobType; status_t status = readInt32(&useAshmem); status_t status = readInt32(&blobType); if (status) return status; if (status) return status; if (!useAshmem) { if (blobType == BLOB_INPLACE) { ALOGV("readBlob: read in place"); ALOGV("readBlob: read in place"); const void* ptr = readInplace(len); const void* ptr = readInplace(len); if (!ptr) return BAD_VALUE; if (!ptr) return BAD_VALUE; outBlob->init(false /*mapped*/, const_cast<void*>(ptr), len); outBlob->init(-1, const_cast<void*>(ptr), len, false); return NO_ERROR; return NO_ERROR; } } ALOGV("readBlob: read from ashmem"); ALOGV("readBlob: read from ashmem"); bool isMutable = (blobType == BLOB_ASHMEM_MUTABLE); int fd = readFileDescriptor(); int fd = readFileDescriptor(); if (fd == int(BAD_TYPE)) return BAD_VALUE; if (fd == int(BAD_TYPE)) return BAD_VALUE; void* ptr = ::mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0); void* ptr = ::mmap(NULL, len, isMutable ? PROT_READ | PROT_WRITE : PROT_READ, MAP_SHARED, fd, 0); if (ptr == MAP_FAILED) return NO_MEMORY; if (ptr == MAP_FAILED) return NO_MEMORY; outBlob->init(true /*mapped*/, ptr, len); outBlob->init(fd, ptr, len, isMutable); return NO_ERROR; return NO_ERROR; } } Loading Loading @@ -1890,7 +1913,7 @@ size_t Parcel::getBlobAshmemSize() const // --- Parcel::Blob --- // --- Parcel::Blob --- Parcel::Blob::Blob() : Parcel::Blob::Blob() : mMapped(false), mData(NULL), mSize(0) { mFd(-1), mData(NULL), mSize(0), mMutable(false) { } } Parcel::Blob::~Blob() { Parcel::Blob::~Blob() { Loading @@ -1898,22 +1921,24 @@ Parcel::Blob::~Blob() { } } void Parcel::Blob::release() { void Parcel::Blob::release() { if (mMapped && mData) { if (mFd != -1 && mData) { ::munmap(mData, mSize); ::munmap(mData, mSize); } } clear(); clear(); } } void Parcel::Blob::init(bool mapped, void* data, size_t size) { void Parcel::Blob::init(int fd, void* data, size_t size, bool isMutable) { mMapped = mapped; mFd = fd; mData = data; mData = data; mSize = size; mSize = size; mMutable = isMutable; } } void Parcel::Blob::clear() { void Parcel::Blob::clear() { mMapped = false; mFd = -1; mData = NULL; mData = NULL; mSize = 0; mSize = 0; mMutable = false; } } }; // namespace android }; // namespace android