diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h index 33b2f0050..877b17c2d 100644 --- a/include/binder/Parcel.h +++ b/include/binder/Parcel.h @@ -22,10 +22,12 @@ #include #include #include +#include // --------------------------------------------------------------------------- namespace android { +template class LightFlattenable; class Flattenable; class IBinder; class IPCThreadState; @@ -102,6 +104,10 @@ public: status_t writeWeakBinder(const wp& val); status_t write(const Flattenable& val); + template + status_t write(const LightFlattenable& val); + + // Place a native_handle into the parcel (the native_handle's file- // descriptors are dup'ed, so it is safe to delete the native_handle // when this function returns). @@ -153,6 +159,9 @@ public: wp readWeakBinder() const; status_t read(Flattenable& val) const; + template + status_t read(LightFlattenable& val) const; + // Like Parcel.java's readExceptionCode(). Reads the first int32 // off of a Parcel's header, returning 0 or the negative error // code on exceptions, but also deals with skipping over rich @@ -267,6 +276,40 @@ public: // --------------------------------------------------------------------------- +template +status_t Parcel::write(const LightFlattenable& val) { + size_t size(val.getSize()); + if (!val.isFixedSize()) { + status_t err = writeInt32(size); + if (err != NO_ERROR) { + return err; + } + } + void* buffer = writeInplace(size); + return buffer == NULL ? NO_MEMORY : + val.flatten(buffer); +} + +template +status_t Parcel::read(LightFlattenable& val) const { + size_t size; + if (val.isFixedSize()) { + size = val.getSize(); + } else { + int32_t s; + status_t err = readInt32(&s); + if (err != NO_ERROR) { + return err; + } + size = s; + } + void const* buffer = readInplace(size); + return buffer == NULL ? NO_MEMORY : + val.unflatten(buffer, size); +} + +// --------------------------------------------------------------------------- + inline TextOutput& operator<<(TextOutput& to, const Parcel& parcel) { parcel.print(to); diff --git a/include/gui/Sensor.h b/include/gui/Sensor.h index e59757a43..2af2307bd 100644 --- a/include/gui/Sensor.h +++ b/include/gui/Sensor.h @@ -41,7 +41,7 @@ class Parcel; // ---------------------------------------------------------------------------- -class Sensor : public ASensor, public Flattenable +class Sensor : public ASensor, public LightFlattenable { public: enum { @@ -54,7 +54,7 @@ public: Sensor(); Sensor(struct sensor_t const* hwSensor); - virtual ~Sensor(); + ~Sensor(); const String8& getName() const; const String8& getVendor() const; @@ -68,13 +68,11 @@ public: nsecs_t getMinDelayNs() const; int32_t getVersion() const; - // 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); + // LightFlattenable protocol + inline bool isFixedSize() const { return false; } + size_t getSize() const; + status_t flatten(void* buffer) const; + status_t unflatten(void const* buffer, size_t size); private: String8 mName; diff --git a/include/ui/Point.h b/include/ui/Point.h index 1653120a6..1d7f64d30 100644 --- a/include/ui/Point.h +++ b/include/ui/Point.h @@ -17,11 +17,12 @@ #ifndef ANDROID_UI_POINT #define ANDROID_UI_POINT +#include #include namespace android { -class Point +class Point : public LightFlattenablePod { public: int x; diff --git a/include/ui/Rect.h b/include/ui/Rect.h index c2c2675e3..47d37b6d3 100644 --- a/include/ui/Rect.h +++ b/include/ui/Rect.h @@ -17,6 +17,7 @@ #ifndef ANDROID_UI_RECT #define ANDROID_UI_RECT +#include #include #include @@ -24,7 +25,7 @@ namespace android { -class Rect : public ARect +class Rect : public ARect, public LightFlattenablePod { public: typedef ARect::value_type value_type; diff --git a/include/ui/Region.h b/include/ui/Region.h index f242f18eb..f0819af3a 100644 --- a/include/ui/Region.h +++ b/include/ui/Region.h @@ -23,6 +23,7 @@ #include #include +#include namespace android { // --------------------------------------------------------------------------- @@ -30,13 +31,12 @@ namespace android { class String8; // --------------------------------------------------------------------------- -class Region +class Region : public LightFlattenable { public: Region(); Region(const Region& rhs); explicit Region(const Rect& rhs); - explicit Region(const void* buffer); ~Region(); Region& operator = (const Region& rhs); @@ -122,12 +122,10 @@ public: // be sorted in Y and X and must not make the region invalid. void addRectUnchecked(int l, int t, int r, int b); - // flatten/unflatten a region to/from a raw buffer - ssize_t write(void* buffer, size_t size) const; - static ssize_t writeEmpty(void* buffer, size_t size); - - ssize_t read(const void* buffer); - static bool isEmpty(void* buffer); + inline bool isFixedSize() const { return false; } + size_t getSize() const; + status_t flatten(void* buffer) const; + status_t unflatten(void const* buffer, size_t size); void dump(String8& out, const char* what, uint32_t flags=0) const; void dump(const char* what, uint32_t flags=0) const; diff --git a/include/utils/Flattenable.h b/include/utils/Flattenable.h index 852be3b6a..e40d289de 100644 --- a/include/utils/Flattenable.h +++ b/include/utils/Flattenable.h @@ -24,6 +24,11 @@ namespace android { +/* + * The Flattenable interface allows an object to serialize itself out + * to a byte-buffer and an array of file descriptors. + */ + class Flattenable { public: @@ -56,6 +61,73 @@ protected: }; +/* + * LightFlattenable is a protocol allowing object to serialize themselves out + * to a byte-buffer. + * + * LightFlattenable objects must implement this protocol. + * + * LightFlattenable doesn't require the object to be virtual. + */ +template +class LightFlattenable { +public: + // returns whether this object always flatten into the same size. + // for efficiency, this should always be inline. + inline bool isFixedSize() const; + + // returns size in bytes of the flattened object. must be a constant. + inline size_t getSize() const; + + // flattens the object into buffer. + inline status_t flatten(void* buffer) const; + + // unflattens the object from buffer of given size. + inline status_t unflatten(void const* buffer, size_t size); +}; + +template +inline bool LightFlattenable::isFixedSize() const { + return static_cast(this)->T::isFixedSize(); +} +template +inline size_t LightFlattenable::getSize() const { + return static_cast(this)->T::getSize(); +} +template +inline status_t LightFlattenable::flatten(void* buffer) const { + return static_cast(this)->T::flatten(buffer); +} +template +inline status_t LightFlattenable::unflatten(void const* buffer, size_t size) { + return static_cast(this)->T::unflatten(buffer, size); +} + +/* + * LightFlattenablePod is an implementation of the LightFlattenable protocol + * for POD (plain-old-data) objects. + */ +template +class LightFlattenablePod : public LightFlattenable { +public: + inline bool isFixedSize() const { + return true; + } + + inline size_t getSize() const { + return sizeof(T); + } + inline status_t flatten(void* buffer) const { + *reinterpret_cast(buffer) = *static_cast(this); + return NO_ERROR; + } + inline status_t unflatten(void const* buffer, size_t) { + *static_cast(this) = *reinterpret_cast(buffer); + return NO_ERROR; + } +}; + + }; // namespace android diff --git a/libs/gui/ISensorServer.cpp b/libs/gui/ISensorServer.cpp index 71110925d..0b76f3788 100644 --- a/libs/gui/ISensorServer.cpp +++ b/libs/gui/ISensorServer.cpp @@ -55,7 +55,7 @@ public: int32_t n = reply.readInt32(); v.setCapacity(n); while (n--) { - reply.read(static_cast(s)); + reply.read(s); v.add(s); } return v; @@ -84,7 +84,7 @@ status_t BnSensorServer::onTransact( size_t n = v.size(); reply->writeInt32(n); for (size_t i=0 ; iwrite(static_cast(v[i])); + reply->write(v[i]); } return NO_ERROR; } break; diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 07f62c40e..e2604f8e2 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -26,14 +26,7 @@ status_t layer_state_t::write(Parcel& output) const { status_t err; - size_t len = transparentRegion.write(NULL, 0); - err = output.writeInt32(len); - if (err < NO_ERROR) return err; - - void* buf = output.writeInplace(len); - if (buf == NULL) return NO_MEMORY; - - err = transparentRegion.write(buf, len); + err = output.write(transparentRegion); if (err < NO_ERROR) return err; // NOTE: regions are at the end of the structure @@ -46,11 +39,8 @@ status_t layer_state_t::write(Parcel& output) const status_t layer_state_t::read(const Parcel& input) { status_t err; - size_t len = input.readInt32(); - void const* buf = input.readInplace(len); - if (buf == NULL) return NO_MEMORY; - err = transparentRegion.read(buf); + err = input.read(transparentRegion); if (err < NO_ERROR) return err; // NOTE: regions are at the end of the structure @@ -77,8 +67,8 @@ status_t DisplayState::write(Parcel& output) const { output.writeInt32(what); output.writeInt32(layerStack); output.writeInt32(orientation); - memcpy(output.writeInplace(sizeof(Rect)), &viewport, sizeof(Rect)); - memcpy(output.writeInplace(sizeof(Rect)), &frame, sizeof(Rect)); + output.write(viewport); + output.write(frame); return NO_ERROR; } @@ -88,8 +78,8 @@ status_t DisplayState::read(const Parcel& input) { what = input.readInt32(); layerStack = input.readInt32(); orientation = input.readInt32(); - memcpy(&viewport, input.readInplace(sizeof(Rect)), sizeof(Rect)); - memcpy(&frame, input.readInplace(sizeof(Rect)), sizeof(Rect)); + input.read(viewport); + input.read(frame); return NO_ERROR; } diff --git a/libs/gui/Sensor.cpp b/libs/gui/Sensor.cpp index 5cc76b4cd..c52a88f12 100644 --- a/libs/gui/Sensor.cpp +++ b/libs/gui/Sensor.cpp @@ -98,7 +98,7 @@ int32_t Sensor::getVersion() const { return mVersion; } -size_t Sensor::getFlattenedSize() const +size_t Sensor::getSize() const { return sizeof(int32_t) + ((mName.length() + 3) & ~3) + sizeof(int32_t) + ((mVendor.length() + 3) & ~3) + @@ -107,11 +107,6 @@ size_t Sensor::getFlattenedSize() const sizeof(int32_t); } -size_t Sensor::getFdCount() const -{ - return 0; -} - static inline size_t write(void* buffer, size_t offset, const String8& value) { memcpy(static_cast(buffer) + offset, value.string(), value.length()); @@ -130,12 +125,8 @@ size_t write(void* buffer, size_t offset, int32_t value) { return sizeof(int32_t); } -status_t Sensor::flatten(void* buffer, size_t size, - int fds[], size_t count) const +status_t Sensor::flatten(void* buffer) const { - if (size < Sensor::getFlattenedSize()) - return -ENOMEM; - size_t offset = 0; offset += write(buffer, offset, int32_t(mName.length())); offset += write(buffer, offset, mName); @@ -149,7 +140,6 @@ status_t Sensor::flatten(void* buffer, size_t size, offset += write(buffer, offset, mResolution); offset += write(buffer, offset, mPower); offset += write(buffer, offset, mMinDelay); - return NO_ERROR; } @@ -171,8 +161,7 @@ size_t read(void const* buffer, size_t offset, int32_t* value) { return sizeof(int32_t); } -status_t Sensor::unflatten(void const* buffer, size_t size, - int fds[], size_t count) +status_t Sensor::unflatten(void const* buffer, size_t size) { int32_t len; size_t offset = 0; @@ -188,7 +177,6 @@ status_t Sensor::unflatten(void const* buffer, size_t size, offset += read(buffer, offset, &mResolution); offset += read(buffer, offset, &mPower); offset += read(buffer, offset, &mMinDelay); - return NO_ERROR; } diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp index 2c7cdf076..a3d8b01b8 100644 --- a/libs/ui/Region.cpp +++ b/libs/ui/Region.cpp @@ -66,12 +66,6 @@ Region::Region(const Rect& rhs) { } -Region::Region(const void* buffer) -{ - status_t err = read(buffer); - ALOGE_IF(err<0, "error %s reading Region from buffer", strerror(err)); -} - Region::~Region() { } @@ -561,55 +555,33 @@ void Region::translate(Region& dst, const Region& reg, int dx, int dy) // ---------------------------------------------------------------------------- -ssize_t Region::write(void* buffer, size_t size) const -{ -#if VALIDATE_REGIONS - validate(*this, "write(buffer)"); -#endif - const size_t count = mStorage.size(); - const size_t sizeNeeded = sizeof(int32_t) + (1+count)*sizeof(Rect); - if (buffer != NULL) { - if (sizeNeeded > size) return NO_MEMORY; - int32_t* const p = static_cast(buffer); - *p = count; - memcpy(p+1, &mBounds, sizeof(Rect)); - if (count) { - memcpy(p+5, mStorage.array(), count*sizeof(Rect)); +size_t Region::getSize() const { + return (mStorage.size() + 1) * sizeof(Rect); +} + +status_t Region::flatten(void* buffer) const { + Rect* rects = reinterpret_cast(buffer); + *rects++ = mBounds; + memcpy(rects, mStorage.array(), mStorage.size() * sizeof(Rect)); + return NO_ERROR; +} + +status_t Region::unflatten(void const* buffer, size_t size) { + mStorage.clear(); + if (size >= sizeof(Rect)) { + Rect const* rects = reinterpret_cast(buffer); + mBounds = *rects++; + size -= sizeof(Rect); + size_t count = size / sizeof(Rect); + if (count > 0) { + ssize_t err = mStorage.insertAt(0, count); + if (err < 0) { + return status_t(err); + } + memcpy(mStorage.editArray(), rects, count*sizeof(Rect)); } } - return ssize_t(sizeNeeded); -} - -ssize_t Region::read(const void* buffer) -{ - int32_t const* const p = static_cast(buffer); - const size_t count = *p; - memcpy(&mBounds, p+1, sizeof(Rect)); - mStorage.clear(); - if (count) { - mStorage.insertAt(0, count); - memcpy(mStorage.editArray(), p+5, count*sizeof(Rect)); - } -#if VALIDATE_REGIONS - validate(*this, "read(buffer)"); -#endif - return ssize_t(sizeof(int32_t) + (1+count)*sizeof(Rect)); -} - -ssize_t Region::writeEmpty(void* buffer, size_t size) -{ - const size_t sizeNeeded = sizeof(int32_t) + sizeof(Rect); - if (sizeNeeded > size) return NO_MEMORY; - int32_t* const p = static_cast(buffer); - memset(p, 0, sizeNeeded); - return ssize_t(sizeNeeded); -} - -bool Region::isEmpty(void* buffer) -{ - int32_t const* const p = static_cast(buffer); - Rect const* const b = reinterpret_cast(p+1); - return b->isEmpty(); + return NO_ERROR; } // ----------------------------------------------------------------------------