diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h index 3ff95d282..7a782f569 100644 --- a/include/binder/Parcel.h +++ b/include/binder/Parcel.h @@ -27,8 +27,8 @@ // --------------------------------------------------------------------------- namespace android { +template class Flattenable; template class LightFlattenable; -class Flattenable; class IBinder; class IPCThreadState; class ProcessState; @@ -37,8 +37,7 @@ class TextOutput; struct flat_binder_object; // defined in support_p/binder_module.h -class Parcel -{ +class Parcel { public: class ReadableBlob; class WritableBlob; @@ -102,7 +101,9 @@ public: status_t writeString16(const char16_t* str, size_t len); status_t writeStrongBinder(const sp& val); status_t writeWeakBinder(const wp& val); - status_t write(const Flattenable& val); + + template + status_t write(const Flattenable& val); template status_t write(const LightFlattenable& val); @@ -157,7 +158,9 @@ public: const char16_t* readString16Inplace(size_t* outLen) const; sp readStrongBinder() const; wp readWeakBinder() const; - status_t read(Flattenable& val) const; + + template + status_t read(Flattenable& val) const; template status_t read(LightFlattenable& val) const; @@ -260,6 +263,39 @@ private: size_t mSize; }; + class FlattenableHelperInterface { + protected: + ~FlattenableHelperInterface() { } + public: + virtual size_t getFlattenedSize() const = 0; + virtual size_t getFdCount() const = 0; + virtual status_t flatten(void* buffer, size_t size, int* fds, size_t count) const = 0; + virtual status_t unflatten(void const* buffer, size_t size, int const* fds, size_t count) = 0; + }; + + template + class FlattenableHelper : public FlattenableHelperInterface { + friend class Parcel; + const Flattenable& val; + explicit FlattenableHelper(const Flattenable& val) : val(val) { } + + public: + virtual size_t getFlattenedSize() const { + return val.getFlattenedSize(); + } + virtual size_t getFdCount() const { + return val.getFdCount(); + } + virtual status_t flatten(void* buffer, size_t size, int* fds, size_t count) const { + return val.flatten(buffer, size, fds, count); + } + virtual status_t unflatten(void const* buffer, size_t size, int const* fds, size_t count) { + return const_cast&>(val).unflatten(buffer, size, fds, count); + } + }; + status_t write(const FlattenableHelperInterface& val); + status_t read(FlattenableHelperInterface& val) const; + public: class ReadableBlob : public Blob { friend class Parcel; @@ -276,9 +312,15 @@ public: // --------------------------------------------------------------------------- +template +status_t Parcel::write(const Flattenable& val) { + const FlattenableHelper helper(val); + return write(helper); +} + template status_t Parcel::write(const LightFlattenable& val) { - size_t size(val.getSize()); + size_t size(val.getFlattenedSize()); if (!val.isFixedSize()) { status_t err = writeInt32(size); if (err != NO_ERROR) { @@ -287,17 +329,24 @@ status_t Parcel::write(const LightFlattenable& val) { } if (size) { void* buffer = writeInplace(size); - return buffer == NULL ? NO_MEMORY : - val.flatten(buffer); + if (buffer == NULL) + return NO_MEMORY; + return val.flatten(buffer, size); } return NO_ERROR; } +template +status_t Parcel::read(Flattenable& val) const { + FlattenableHelper helper(val); + return read(helper); +} + template status_t Parcel::read(LightFlattenable& val) const { size_t size; if (val.isFixedSize()) { - size = val.getSize(); + size = val.getFlattenedSize(); } else { int32_t s; status_t err = readInt32(&s); diff --git a/include/gui/IGraphicBufferProducer.h b/include/gui/IGraphicBufferProducer.h index 9677962a5..033c7273c 100644 --- a/include/gui/IGraphicBufferProducer.h +++ b/include/gui/IGraphicBufferProducer.h @@ -105,7 +105,8 @@ public: // and height of the window and current transform applied to buffers, // respectively. - struct QueueBufferInput : public Flattenable { + struct QueueBufferInput : public Flattenable { + friend class Flattenable; inline QueueBufferInput(const Parcel& parcel); inline QueueBufferInput(int64_t timestamp, const Rect& crop, int scalingMode, uint32_t transform, bool async, @@ -123,13 +124,11 @@ public: *outFence = fence; } - // Flattenable interface - virtual size_t getFlattenedSize() const; - virtual size_t getFdCount() const; - virtual status_t flatten(void* buffer, size_t size, - int fds[], size_t count) const; - virtual status_t unflatten(void const* buffer, size_t size, - int fds[], size_t count); + // Flattenable protocol + size_t getFlattenedSize() const; + size_t getFdCount() const; + status_t flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const; + status_t unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count); private: int64_t timestamp; diff --git a/include/gui/Sensor.h b/include/gui/Sensor.h index 2af2307bd..91973723e 100644 --- a/include/gui/Sensor.h +++ b/include/gui/Sensor.h @@ -70,8 +70,8 @@ public: // LightFlattenable protocol inline bool isFixedSize() const { return false; } - size_t getSize() const; - status_t flatten(void* buffer) const; + size_t getFlattenedSize() const; + status_t flatten(void* buffer, size_t size) const; status_t unflatten(void const* buffer, size_t size); private: diff --git a/include/ui/Fence.h b/include/ui/Fence.h index 60156e7bb..20466b616 100644 --- a/include/ui/Fence.h +++ b/include/ui/Fence.h @@ -36,7 +36,7 @@ namespace android { // =========================================================================== class Fence - : public LightRefBase, public Flattenable + : public LightRefBase, public Flattenable { public: static const sp NO_FENCE; @@ -96,15 +96,13 @@ public: // Flattenable interface size_t getFlattenedSize() const; size_t getFdCount() const; - status_t flatten(void* buffer, size_t size, - int fds[], size_t count) const; - status_t unflatten(void const* buffer, size_t size, - int fds[], size_t count); + status_t flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const; + status_t unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count); private: // Only allow instantiation using ref counting. friend class LightRefBase; - virtual ~Fence(); + ~Fence(); // Disallow copying Fence(const Fence& rhs); diff --git a/include/ui/GraphicBuffer.h b/include/ui/GraphicBuffer.h index e5ad1e0af..8184b7d9f 100644 --- a/include/ui/GraphicBuffer.h +++ b/include/ui/GraphicBuffer.h @@ -39,8 +39,9 @@ class GraphicBufferMapper; class GraphicBuffer : public ANativeObjectBase< ANativeWindowBuffer, GraphicBuffer, RefBase >, - public Flattenable + public Flattenable { + friend class Flattenable; public: enum { @@ -106,7 +107,7 @@ public: static void dumpAllocationsToSystemLog(); private: - virtual ~GraphicBuffer(); + ~GraphicBuffer(); enum { ownNone = 0, @@ -136,13 +137,11 @@ private: void free_handle(); - // Flattenable interface + // Flattenable protocol size_t getFlattenedSize() const; size_t getFdCount() const; - status_t flatten(void* buffer, size_t size, - int fds[], size_t count) const; - status_t unflatten(void const* buffer, size_t size, - int fds[], size_t count); + status_t flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const; + status_t unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count); GraphicBufferMapper& mBufferMapper; diff --git a/include/ui/Region.h b/include/ui/Region.h index ce91f3b69..d906dbbb0 100644 --- a/include/ui/Region.h +++ b/include/ui/Region.h @@ -136,8 +136,8 @@ public: void addRectUnchecked(int l, int t, int r, int b); inline bool isFixedSize() const { return false; } - size_t getSize() const; - status_t flatten(void* buffer) const; + size_t getFlattenedSize() const; + status_t flatten(void* buffer, size_t size) const; status_t unflatten(void const* buffer, size_t size); void dump(String8& out, const char* what, uint32_t flags=0) const; diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp index 359742c04..7a5919f43 100644 --- a/libs/binder/Parcel.cpp +++ b/libs/binder/Parcel.cpp @@ -798,13 +798,13 @@ status_t Parcel::writeBlob(size_t len, WritableBlob* outBlob) return status; } -status_t Parcel::write(const Flattenable& val) +status_t Parcel::write(const FlattenableHelperInterface& val) { status_t err; // size if needed - size_t len = val.getFlattenedSize(); - size_t fd_count = val.getFdCount(); + const size_t len = val.getFlattenedSize(); + const size_t fd_count = val.getFdCount(); err = this->writeInt32(len); if (err) return err; @@ -813,7 +813,7 @@ status_t Parcel::write(const Flattenable& val) if (err) return err; // payload - void* buf = this->writeInplace(PAD_SIZE(len)); + void* const buf = this->writeInplace(PAD_SIZE(len)); if (buf == NULL) return BAD_VALUE; @@ -1174,14 +1174,14 @@ status_t Parcel::readBlob(size_t len, ReadableBlob* outBlob) const return NO_ERROR; } -status_t Parcel::read(Flattenable& val) const +status_t Parcel::read(FlattenableHelperInterface& val) const { // size const size_t len = this->readInt32(); const size_t fd_count = this->readInt32(); // payload - void const* buf = this->readInplace(PAD_SIZE(len)); + void const* const buf = this->readInplace(PAD_SIZE(len)); if (buf == NULL) return BAD_VALUE; diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp index 2e561dfc2..48b28708f 100644 --- a/libs/gui/IGraphicBufferProducer.cpp +++ b/libs/gui/IGraphicBufferProducer.cpp @@ -270,8 +270,7 @@ IGraphicBufferProducer::QueueBufferInput::QueueBufferInput(const Parcel& parcel) parcel.read(*this); } -size_t IGraphicBufferProducer::QueueBufferInput::getFlattenedSize() const -{ +size_t IGraphicBufferProducer::QueueBufferInput::getFlattenedSize() const { return sizeof(timestamp) + sizeof(crop) + sizeof(scalingMode) @@ -280,38 +279,46 @@ size_t IGraphicBufferProducer::QueueBufferInput::getFlattenedSize() const + fence->getFlattenedSize(); } -size_t IGraphicBufferProducer::QueueBufferInput::getFdCount() const -{ +size_t IGraphicBufferProducer::QueueBufferInput::getFdCount() const { return fence->getFdCount(); } -status_t IGraphicBufferProducer::QueueBufferInput::flatten(void* buffer, size_t size, - int fds[], size_t count) const +status_t IGraphicBufferProducer::QueueBufferInput::flatten( + void*& buffer, size_t& size, int*& fds, size_t& count) const { - status_t err = NO_ERROR; - char* p = (char*)buffer; - memcpy(p, ×tamp, sizeof(timestamp)); p += sizeof(timestamp); - memcpy(p, &crop, sizeof(crop)); p += sizeof(crop); - memcpy(p, &scalingMode, sizeof(scalingMode)); p += sizeof(scalingMode); - memcpy(p, &transform, sizeof(transform)); p += sizeof(transform); - memcpy(p, &async, sizeof(async)); p += sizeof(async); - err = fence->flatten(p, size - (p - (char*)buffer), fds, count); - return err; + if (size < getFlattenedSize()) { + return NO_MEMORY; + } + FlattenableUtils::write(buffer, size, timestamp); + FlattenableUtils::write(buffer, size, crop); + FlattenableUtils::write(buffer, size, scalingMode); + FlattenableUtils::write(buffer, size, transform); + FlattenableUtils::write(buffer, size, async); + return fence->flatten(buffer, size, fds, count); } -status_t IGraphicBufferProducer::QueueBufferInput::unflatten(void const* buffer, - size_t size, int fds[], size_t count) +status_t IGraphicBufferProducer::QueueBufferInput::unflatten( + void const*& buffer, size_t& size, int const*& fds, size_t& count) { - status_t err = NO_ERROR; - const char* p = (const char*)buffer; - memcpy(×tamp, p, sizeof(timestamp)); p += sizeof(timestamp); - memcpy(&crop, p, sizeof(crop)); p += sizeof(crop); - memcpy(&scalingMode, p, sizeof(scalingMode)); p += sizeof(scalingMode); - memcpy(&transform, p, sizeof(transform)); p += sizeof(transform); - memcpy(&async, p, sizeof(async)); p += sizeof(async); + size_t minNeeded = + sizeof(timestamp) + + sizeof(crop) + + sizeof(scalingMode) + + sizeof(transform) + + sizeof(async); + + if (size < minNeeded) { + return NO_MEMORY; + } + + FlattenableUtils::read(buffer, size, timestamp); + FlattenableUtils::read(buffer, size, crop); + FlattenableUtils::read(buffer, size, scalingMode); + FlattenableUtils::read(buffer, size, transform); + FlattenableUtils::read(buffer, size, async); + fence = new Fence(); - err = fence->unflatten(p, size - (p - (const char*)buffer), fds, count); - return err; + return fence->unflatten(buffer, size, fds, count); } }; // namespace android diff --git a/libs/gui/Sensor.cpp b/libs/gui/Sensor.cpp index c52a88f12..d84c370a1 100644 --- a/libs/gui/Sensor.cpp +++ b/libs/gui/Sensor.cpp @@ -98,85 +98,85 @@ int32_t Sensor::getVersion() const { return mVersion; } -size_t Sensor::getSize() const +size_t Sensor::getFlattenedSize() const { - return sizeof(int32_t) + ((mName.length() + 3) & ~3) + - sizeof(int32_t) + ((mVendor.length() + 3) & ~3) + + size_t fixedSize = sizeof(int32_t) * 3 + sizeof(float) * 4 + sizeof(int32_t); + + size_t variableSize = + sizeof(int32_t) + FlattenableUtils::align<4>(mName.length()) + + sizeof(int32_t) + FlattenableUtils::align<4>(mVendor.length()); + + return fixedSize + variableSize; } -static inline -size_t write(void* buffer, size_t offset, const String8& value) { - memcpy(static_cast(buffer) + offset, value.string(), value.length()); - return (value.length() + 3) & ~3; -} +status_t Sensor::flatten(void* buffer, size_t size) const { + if (size < getFlattenedSize()) { + return NO_MEMORY; + } -static inline -size_t write(void* buffer, size_t offset, float value) { - *reinterpret_cast(static_cast(buffer) + offset) = value; - return sizeof(float); -} + FlattenableUtils::write(buffer, size, mName.length()); + memcpy(static_cast(buffer), mName.string(), mName.length()); + FlattenableUtils::advance(buffer, size, FlattenableUtils::align<4>(mName.length())); -static inline -size_t write(void* buffer, size_t offset, int32_t value) { - *reinterpret_cast(static_cast(buffer) + offset) = value; - return sizeof(int32_t); -} + FlattenableUtils::write(buffer, size, mVendor.length()); + memcpy(static_cast(buffer), mVendor.string(), mVendor.length()); + FlattenableUtils::advance(buffer, size, FlattenableUtils::align<4>(mVendor.length())); -status_t Sensor::flatten(void* buffer) const -{ - size_t offset = 0; - offset += write(buffer, offset, int32_t(mName.length())); - offset += write(buffer, offset, mName); - offset += write(buffer, offset, int32_t(mVendor.length())); - offset += write(buffer, offset, mVendor); - offset += write(buffer, offset, mVersion); - offset += write(buffer, offset, mHandle); - offset += write(buffer, offset, mType); - offset += write(buffer, offset, mMinValue); - offset += write(buffer, offset, mMaxValue); - offset += write(buffer, offset, mResolution); - offset += write(buffer, offset, mPower); - offset += write(buffer, offset, mMinDelay); + FlattenableUtils::write(buffer, size, mVersion); + FlattenableUtils::write(buffer, size, mHandle); + FlattenableUtils::write(buffer, size, mType); + FlattenableUtils::write(buffer, size, mMinValue); + FlattenableUtils::write(buffer, size, mMaxValue); + FlattenableUtils::write(buffer, size, mResolution); + FlattenableUtils::write(buffer, size, mPower); + FlattenableUtils::write(buffer, size, mMinDelay); return NO_ERROR; } -static inline -size_t read(void const* buffer, size_t offset, String8* value, int32_t len) { - value->setTo(static_cast(buffer) + offset, len); - return (len + 3) & ~3; -} +status_t Sensor::unflatten(void const* buffer, size_t size) { + size_t len; -static inline -size_t read(void const* buffer, size_t offset, float* value) { - *value = *reinterpret_cast(static_cast(buffer) + offset); - return sizeof(float); -} + if (size < sizeof(size_t)) { + return NO_MEMORY; + } + FlattenableUtils::read(buffer, size, len); + if (size < len) { + return NO_MEMORY; + } + mName.setTo(static_cast(buffer), len); + FlattenableUtils::advance(buffer, size, FlattenableUtils::align<4>(len)); -static inline -size_t read(void const* buffer, size_t offset, int32_t* value) { - *value = *reinterpret_cast(static_cast(buffer) + offset); - return sizeof(int32_t); -} -status_t Sensor::unflatten(void const* buffer, size_t size) -{ - int32_t len; - size_t offset = 0; - offset += read(buffer, offset, &len); - offset += read(buffer, offset, &mName, len); - offset += read(buffer, offset, &len); - offset += read(buffer, offset, &mVendor, len); - offset += read(buffer, offset, &mVersion); - offset += read(buffer, offset, &mHandle); - offset += read(buffer, offset, &mType); - offset += read(buffer, offset, &mMinValue); - offset += read(buffer, offset, &mMaxValue); - offset += read(buffer, offset, &mResolution); - offset += read(buffer, offset, &mPower); - offset += read(buffer, offset, &mMinDelay); + if (size < sizeof(size_t)) { + return NO_MEMORY; + } + FlattenableUtils::read(buffer, size, len); + if (size < len) { + return NO_MEMORY; + } + mVendor.setTo(static_cast(buffer), len); + FlattenableUtils::advance(buffer, size, FlattenableUtils::align<4>(len)); + + size_t fixedSize = + sizeof(int32_t) * 3 + + sizeof(float) * 4 + + sizeof(int32_t); + + if (size < fixedSize) { + return NO_MEMORY; + } + + FlattenableUtils::read(buffer, size, mVersion); + FlattenableUtils::read(buffer, size, mHandle); + FlattenableUtils::read(buffer, size, mType); + FlattenableUtils::read(buffer, size, mMinValue); + FlattenableUtils::read(buffer, size, mMaxValue); + FlattenableUtils::read(buffer, size, mResolution); + FlattenableUtils::read(buffer, size, mPower); + FlattenableUtils::read(buffer, size, mMinDelay); return NO_ERROR; } diff --git a/libs/ui/Fence.cpp b/libs/ui/Fence.cpp index 464ee86c8..93ec0ce61 100644 --- a/libs/ui/Fence.cpp +++ b/libs/ui/Fence.cpp @@ -127,37 +127,49 @@ nsecs_t Fence::getSignalTime() const { } size_t Fence::getFlattenedSize() const { - return 0; + return 1; } size_t Fence::getFdCount() const { return isValid() ? 1 : 0; } -status_t Fence::flatten(void* buffer, size_t size, int fds[], - size_t count) const { - if (size != getFlattenedSize() || count != getFdCount()) { - return BAD_VALUE; +status_t Fence::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const { + if (size < getFlattenedSize() || count < getFdCount()) { + return NO_MEMORY; } - + FlattenableUtils::write(buffer, size, getFdCount()); if (isValid()) { - fds[0] = mFenceFd; + *fds++ = mFenceFd; + count--; } return NO_ERROR; } -status_t Fence::unflatten(void const* buffer, size_t size, int fds[], - size_t count) { - if (size != 0 || (count != 0 && count != 1)) { - return BAD_VALUE; - } +status_t Fence::unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count) { if (mFenceFd != -1) { // Don't unflatten if we already have a valid fd. return INVALID_OPERATION; } - if (count == 1) { - mFenceFd = fds[0]; + if (size < 1) { + return NO_MEMORY; + } + + size_t numFds; + FlattenableUtils::read(buffer, size, numFds); + + if (numFds > 1) { + return BAD_VALUE; + } + + if (count < numFds) { + return NO_MEMORY; + } + + if (numFds) { + mFenceFd = *fds++; + count--; } return NO_ERROR; diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp index 580788d0e..1f273e264 100644 --- a/libs/ui/GraphicBuffer.cpp +++ b/libs/ui/GraphicBuffer.cpp @@ -209,9 +209,7 @@ size_t GraphicBuffer::getFdCount() const { return handle ? handle->numFds : 0; } -status_t GraphicBuffer::flatten(void* buffer, size_t size, - int fds[], size_t count) const -{ +status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const { size_t sizeNeeded = GraphicBuffer::getFlattenedSize(); if (size < sizeNeeded) return NO_MEMORY; @@ -236,12 +234,16 @@ status_t GraphicBuffer::flatten(void* buffer, size_t size, memcpy(&buf[8], h->data + h->numFds, h->numInts*sizeof(int)); } + buffer = reinterpret_cast(static_cast(buffer) + sizeNeeded); + size -= sizeNeeded; + fds += handle->numFds; + count -= handle->numFds; + return NO_ERROR; } -status_t GraphicBuffer::unflatten(void const* buffer, size_t size, - int fds[], size_t count) -{ +status_t GraphicBuffer::unflatten( + void const*& buffer, size_t& size, int const*& fds, size_t& count) { if (size < 8*sizeof(int)) return NO_MEMORY; int const* buf = static_cast(buffer); @@ -287,6 +289,11 @@ status_t GraphicBuffer::unflatten(void const* buffer, size_t size, } } + buffer = reinterpret_cast(static_cast(buffer) + sizeNeeded); + size -= sizeNeeded; + fds += numFds; + count -= numFds; + return NO_ERROR; } diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp index 623f8edac..e5abcf5c8 100644 --- a/libs/ui/Region.cpp +++ b/libs/ui/Region.cpp @@ -715,14 +715,17 @@ void Region::translate(Region& dst, const Region& reg, int dx, int dy) // ---------------------------------------------------------------------------- -size_t Region::getSize() const { +size_t Region::getFlattenedSize() const { return mStorage.size() * sizeof(Rect); } -status_t Region::flatten(void* buffer) const { +status_t Region::flatten(void* buffer, size_t size) const { #if VALIDATE_REGIONS validate(*this, "Region::flatten"); #endif + if (size < mStorage.size() * sizeof(Rect)) { + return NO_MEMORY; + } Rect* rects = reinterpret_cast(buffer); memcpy(rects, mStorage.array(), mStorage.size() * sizeof(Rect)); return NO_ERROR; diff --git a/opengl/libs/EGL/egl_cache.cpp b/opengl/libs/EGL/egl_cache.cpp index 1607267bf..b0798a109 100644 --- a/opengl/libs/EGL/egl_cache.cpp +++ b/opengl/libs/EGL/egl_cache.cpp @@ -253,8 +253,7 @@ void egl_cache_t::saveBlobCacheLocked() { return; } - status_t err = mBlobCache->flatten(buf + headerSize, cacheSize, NULL, - 0); + status_t err = mBlobCache->flatten(buf + headerSize, cacheSize); if (err != OK) { ALOGE("error writing cache contents: %s (%d)", strerror(-err), -err); @@ -335,8 +334,7 @@ void egl_cache_t::loadBlobCacheLocked() { return; } - status_t err = mBlobCache->unflatten(buf + headerSize, cacheSize, NULL, - 0); + status_t err = mBlobCache->unflatten(buf + headerSize, cacheSize); if (err != OK) { ALOGE("error reading cache contents: %s (%d)", strerror(-err), -err);