summaryrefslogtreecommitdiffstats
path: root/libs
diff options
context:
space:
mode:
Diffstat (limited to 'libs')
-rw-r--r--libs/binder/Parcel.cpp101
-rw-r--r--libs/binder/Static.cpp2
-rw-r--r--libs/binder/TextOutput.cpp4
-rw-r--r--libs/gui/BufferItem.cpp2
-rw-r--r--libs/gui/BufferQueue.cpp5
-rw-r--r--libs/gui/BufferQueueProducer.cpp61
-rw-r--r--libs/gui/ConsumerBase.cpp4
-rw-r--r--libs/gui/GLConsumer.cpp6
-rw-r--r--libs/gui/IConsumerListener.cpp20
-rw-r--r--libs/gui/ISurfaceComposer.cpp14
-rw-r--r--libs/gui/LayerState.cpp8
-rw-r--r--libs/gui/StreamSplitter.cpp2
-rw-r--r--libs/gui/tests/BufferQueue_test.cpp2
-rw-r--r--libs/gui/tests/DisconnectWaiter.h2
-rw-r--r--libs/gui/tests/FrameWaiter.h2
-rw-r--r--libs/gui/tests/IGraphicBufferProducer_test.cpp2
-rw-r--r--libs/gui/tests/StreamSplitter_test.cpp2
-rw-r--r--libs/gui/tests/SurfaceTextureGLThreadToGL.h2
-rw-r--r--libs/ui/GraphicBuffer.cpp17
19 files changed, 175 insertions, 83 deletions
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 99e539c..c613fe7 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -26,7 +26,6 @@
#include <binder/TextOutput.h>
#include <errno.h>
-#include <utils/CallStack.h>
#include <utils/Debug.h>
#include <utils/Log.h>
#include <utils/String8.h>
@@ -36,8 +35,8 @@
#include <cutils/ashmem.h>
#include <private/binder/binder_module.h>
+#include <private/binder/Static.h>
-#include <fcntl.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
@@ -50,6 +49,8 @@
#define LOG_REFS(...)
//#define LOG_REFS(...) ALOG(LOG_DEBUG, "Parcel", __VA_ARGS__)
+#define LOG_ALLOC(...)
+//#define LOG_ALLOC(...) ALOG(LOG_DEBUG, "Parcel", __VA_ARGS__)
// ---------------------------------------------------------------------------
@@ -74,6 +75,10 @@ struct small_flat_data
namespace android {
+static pthread_mutex_t gParcelGlobalAllocSizeLock = PTHREAD_MUTEX_INITIALIZER;
+static size_t gParcelGlobalAllocSize = 0;
+static size_t gParcelGlobalAllocCount = 0;
+
void acquire_object(const sp<ProcessState>& proc,
const flat_binder_object& obj, const void* who)
{
@@ -293,12 +298,28 @@ status_t unflatten_binder(const sp<ProcessState>& proc,
Parcel::Parcel()
{
+ LOG_ALLOC("Parcel %p: constructing", this);
initState();
}
Parcel::~Parcel()
{
freeDataNoInit();
+ LOG_ALLOC("Parcel %p: destroyed", this);
+}
+
+size_t Parcel::getGlobalAllocSize() {
+ pthread_mutex_lock(&gParcelGlobalAllocSizeLock);
+ size_t size = gParcelGlobalAllocSize;
+ pthread_mutex_unlock(&gParcelGlobalAllocSizeLock);
+ return size;
+}
+
+size_t Parcel::getGlobalAllocCount() {
+ pthread_mutex_lock(&gParcelGlobalAllocSizeLock);
+ size_t count = gParcelGlobalAllocCount;
+ pthread_mutex_unlock(&gParcelGlobalAllocSizeLock);
+ return count;
}
const uint8_t* Parcel::data() const
@@ -768,29 +789,6 @@ status_t Parcel::writeFileDescriptor(int fd, bool takeOwnership)
status_t Parcel::writeDupFileDescriptor(int fd)
{
int dupFd = dup(fd);
-
- { // Temporary extra debug validation for b/17477219: a Parcel recipient is
- // getting a positive but invalid fd unexpectedly. Trying to track down
- // where it's coming from.
- int dupErrno = dupFd < 0 ? errno : 0;
- int fdFlags = fcntl(fd, F_GETFD);
- int fdFlagsErrno = fdFlags == -1 ? errno : 0;
- int dupFlags = fcntl(dupFd, F_GETFD);
- int dupFlagsErrno = dupFlags == -1 ? errno : 0;
- if (dupFd < 0 || fdFlags == -1 || dupFlags == -1) {
- ALOGE("Parcel::writeDupFileDescriptor failed:\n"
- " fd=%d flags=%d err=%d(%s)\n"
- " dupFd=%d dupErr=%d(%s) flags=%d err=%d(%s)",
- fd, fdFlags, fdFlagsErrno, strerror(fdFlagsErrno),
- dupFd, dupErrno, strerror(dupErrno),
- dupFlags, dupFlagsErrno, strerror(dupFlagsErrno));
- if (fd < 0 || fdFlags == -1) {
- CallStack(LOG_TAG);
- }
- return -errno;
- }
- }
-
if (dupFd < 0) {
return -errno;
}
@@ -1305,23 +1303,11 @@ status_t Parcel::read(FlattenableHelperInterface& val) const
status_t err = NO_ERROR;
for (size_t i=0 ; i<fd_count && err==NO_ERROR ; i++) {
- int oldfd = this->readFileDescriptor();
- fds[i] = dup(oldfd);
+ fds[i] = dup(this->readFileDescriptor());
if (fds[i] < 0) {
- int dupErrno = errno;
err = BAD_VALUE;
- int flags = fcntl(oldfd, F_GETFD);
- int fcntlErrno = errno;
- const flat_binder_object* flat = readObject(true);
- ALOGE("dup failed in Parcel::read, fd %zu of %zu\n"
- " dup(%d) = %d [errno: %d (%s)]\n"
- " fcntl(%d, F_GETFD) = %d [errno: %d (%s)]\n"
- " flat %p type %d",
- i, fd_count,
- oldfd, fds[i], dupErrno, strerror(dupErrno),
- oldfd, flags, fcntlErrno, strerror(fcntlErrno),
- flat, flat ? flat->type : 0);
- CallStack(LOG_TAG);
+ ALOGE("dup() failed in Parcel::read, i is %zu, fds[i] is %d, fd_count is %zu, error: %s",
+ i, fds[i], fd_count, strerror(errno));
}
}
@@ -1525,11 +1511,20 @@ void Parcel::freeData()
void Parcel::freeDataNoInit()
{
if (mOwner) {
+ LOG_ALLOC("Parcel %p: freeing other owner data", this);
//ALOGI("Freeing data ref of %p (pid=%d)", this, getpid());
mOwner(this, mData, mDataSize, mObjects, mObjectsSize, mOwnerCookie);
} else {
+ LOG_ALLOC("Parcel %p: freeing allocated data", this);
releaseObjects();
- if (mData) free(mData);
+ if (mData) {
+ LOG_ALLOC("Parcel %p: freeing with %zu capacity", this, mDataCapacity);
+ pthread_mutex_lock(&gParcelGlobalAllocSizeLock);
+ gParcelGlobalAllocSize -= mDataCapacity;
+ gParcelGlobalAllocCount--;
+ pthread_mutex_unlock(&gParcelGlobalAllocSizeLock);
+ free(mData);
+ }
if (mObjects) free(mObjects);
}
}
@@ -1558,6 +1553,11 @@ status_t Parcel::restartWrite(size_t desired)
releaseObjects();
if (data) {
+ LOG_ALLOC("Parcel %p: restart from %zu to %zu capacity", this, mDataCapacity, desired);
+ pthread_mutex_lock(&gParcelGlobalAllocSizeLock);
+ gParcelGlobalAllocSize += desired;
+ gParcelGlobalAllocSize -= mDataCapacity;
+ pthread_mutex_unlock(&gParcelGlobalAllocSizeLock);
mData = data;
mDataCapacity = desired;
}
@@ -1637,6 +1637,12 @@ status_t Parcel::continueWrite(size_t desired)
mOwner(this, mData, mDataSize, mObjects, mObjectsSize, mOwnerCookie);
mOwner = NULL;
+ LOG_ALLOC("Parcel %p: taking ownership of %zu capacity", this, desired);
+ pthread_mutex_lock(&gParcelGlobalAllocSizeLock);
+ gParcelGlobalAllocSize += desired;
+ gParcelGlobalAllocCount++;
+ pthread_mutex_unlock(&gParcelGlobalAllocSizeLock);
+
mData = data;
mObjects = objects;
mDataSize = (mDataSize < desired) ? mDataSize : desired;
@@ -1671,6 +1677,12 @@ status_t Parcel::continueWrite(size_t desired)
if (desired > mDataCapacity) {
uint8_t* data = (uint8_t*)realloc(mData, desired);
if (data) {
+ LOG_ALLOC("Parcel %p: continue from %zu to %zu capacity", this, mDataCapacity,
+ desired);
+ pthread_mutex_lock(&gParcelGlobalAllocSizeLock);
+ gParcelGlobalAllocSize += desired;
+ gParcelGlobalAllocSize -= mDataCapacity;
+ pthread_mutex_unlock(&gParcelGlobalAllocSizeLock);
mData = data;
mDataCapacity = desired;
} else if (desired > mDataCapacity) {
@@ -1701,6 +1713,12 @@ status_t Parcel::continueWrite(size_t desired)
ALOGE("continueWrite: %zu/%p/%zu/%zu", mDataCapacity, mObjects, mObjectsCapacity, desired);
}
+ LOG_ALLOC("Parcel %p: allocating with %zu capacity", this, desired);
+ pthread_mutex_lock(&gParcelGlobalAllocSizeLock);
+ gParcelGlobalAllocSize += desired;
+ gParcelGlobalAllocCount++;
+ pthread_mutex_unlock(&gParcelGlobalAllocSizeLock);
+
mData = data;
mDataSize = mDataPos = 0;
ALOGV("continueWrite Setting data size of %p to %zu", this, mDataSize);
@@ -1713,6 +1731,7 @@ status_t Parcel::continueWrite(size_t desired)
void Parcel::initState()
{
+ LOG_ALLOC("Parcel %p: initState", this);
mError = NO_ERROR;
mData = 0;
mDataSize = 0;
diff --git a/libs/binder/Static.cpp b/libs/binder/Static.cpp
index 2062692..cd9509f 100644
--- a/libs/binder/Static.cpp
+++ b/libs/binder/Static.cpp
@@ -90,7 +90,7 @@ public:
static LibBinderIPCtStatics gIPCStatics;
-// ------------ ServiceManager.cpp
+// ------------ IServiceManager.cpp
Mutex gDefaultServiceManagerLock;
sp<IServiceManager> gDefaultServiceManager;
diff --git a/libs/binder/TextOutput.cpp b/libs/binder/TextOutput.cpp
index db3e858..2ed5188 100644
--- a/libs/binder/TextOutput.cpp
+++ b/libs/binder/TextOutput.cpp
@@ -116,8 +116,8 @@ TextOutput& operator<<(TextOutput& to, double val)
TextOutput& operator<<(TextOutput& to, const void* val)
{
- char buf[16];
- sprintf(buf, "%p", val);
+ char buf[32];
+ snprintf(buf, sizeof(buf), "%p", val);
to.print(buf, strlen(buf));
return to;
}
diff --git a/libs/gui/BufferItem.cpp b/libs/gui/BufferItem.cpp
index d3fa43e..e6fc791 100644
--- a/libs/gui/BufferItem.cpp
+++ b/libs/gui/BufferItem.cpp
@@ -36,6 +36,8 @@ BufferItem::BufferItem() :
mCrop.makeInvalid();
}
+BufferItem::~BufferItem() {}
+
BufferItem::operator IGraphicBufferConsumer::BufferItem() const {
IGraphicBufferConsumer::BufferItem bufferItem;
bufferItem.mGraphicBuffer = mGraphicBuffer;
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index c49a886..61fd8c4 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -31,10 +31,11 @@ BufferQueue::ProxyConsumerListener::ProxyConsumerListener(
BufferQueue::ProxyConsumerListener::~ProxyConsumerListener() {}
-void BufferQueue::ProxyConsumerListener::onFrameAvailable() {
+void BufferQueue::ProxyConsumerListener::onFrameAvailable(
+ const android::BufferItem& item) {
sp<ConsumerListener> listener(mConsumerListener.promote());
if (listener != NULL) {
- listener->onFrameAvailable();
+ listener->onFrameAvailable(item);
}
}
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index f9f4734..bf9c84d 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -38,7 +38,12 @@ BufferQueueProducer::BufferQueueProducer(const sp<BufferQueueCore>& core) :
mCore(core),
mSlots(core->mSlots),
mConsumerName(),
- mStickyTransform(0) {}
+ mStickyTransform(0),
+ mLastQueueBufferFence(Fence::NO_FENCE),
+ mCallbackMutex(),
+ mNextCallbackTicket(0),
+ mCurrentCallbackTicket(0),
+ mCallbackCondition() {}
BufferQueueProducer::~BufferQueueProducer() {}
@@ -522,12 +527,7 @@ status_t BufferQueueProducer::queueBuffer(int slot,
if (fence == NULL) {
BQ_LOGE("queueBuffer: fence is NULL");
- // Temporary workaround for b/17946343: soldier-on instead of returning an error. This
- // prevents the client from dying, at the risk of visible corruption due to hwcomposer
- // reading the buffer before the producer is done rendering it. Unless the buffer is the
- // last frame of an animation, the corruption will be transient.
- fence = Fence::NO_FENCE;
- // return BAD_VALUE;
+ return BAD_VALUE;
}
switch (scalingMode) {
@@ -541,7 +541,10 @@ status_t BufferQueueProducer::queueBuffer(int slot,
return BAD_VALUE;
}
- sp<IConsumerListener> listener;
+ sp<IConsumerListener> frameAvailableListener;
+ sp<IConsumerListener> frameReplacedListener;
+ int callbackTicket = 0;
+ BufferItem item;
{ // Autolock scope
Mutex::Autolock lock(mCore->mMutex);
@@ -597,7 +600,6 @@ status_t BufferQueueProducer::queueBuffer(int slot,
++mCore->mFrameCounter;
mSlots[slot].mFrameNumber = mCore->mFrameCounter;
- BufferItem item;
item.mAcquireCalled = mSlots[slot].mAcquireCalled;
item.mGraphicBuffer = mSlots[slot].mGraphicBuffer;
item.mCrop = crop;
@@ -618,7 +620,7 @@ status_t BufferQueueProducer::queueBuffer(int slot,
// When the queue is empty, we can ignore mDequeueBufferCannotBlock
// and simply queue this buffer
mCore->mQueue.push_back(item);
- listener = mCore->mConsumerListener;
+ frameAvailableListener = mCore->mConsumerListener;
} else {
// When the queue is not empty, we need to look at the front buffer
// state to see if we need to replace it
@@ -634,9 +636,10 @@ status_t BufferQueueProducer::queueBuffer(int slot,
}
// Overwrite the droppable buffer with the incoming one
*front = item;
+ frameReplacedListener = mCore->mConsumerListener;
} else {
mCore->mQueue.push_back(item);
- listener = mCore->mConsumerListener;
+ frameAvailableListener = mCore->mConsumerListener;
}
}
@@ -647,11 +650,41 @@ status_t BufferQueueProducer::queueBuffer(int slot,
mCore->mTransformHint, mCore->mQueue.size());
ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size());
+
+ // Take a ticket for the callback functions
+ callbackTicket = mNextCallbackTicket++;
} // Autolock scope
- // Call back without lock held
- if (listener != NULL) {
- listener->onFrameAvailable();
+ // Wait without lock held
+ if (mCore->mConnectedApi == NATIVE_WINDOW_API_EGL) {
+ // Waiting here allows for two full buffers to be queued but not a
+ // third. In the event that frames take varying time, this makes a
+ // small trade-off in favor of latency rather than throughput.
+ mLastQueueBufferFence->waitForever("Throttling EGL Production");
+ mLastQueueBufferFence = fence;
+ }
+
+ // Don't send the GraphicBuffer through the callback, and don't send
+ // the slot number, since the consumer shouldn't need it
+ item.mGraphicBuffer.clear();
+ item.mSlot = BufferItem::INVALID_BUFFER_SLOT;
+
+ // Call back without the main BufferQueue lock held, but with the callback
+ // lock held so we can ensure that callbacks occur in order
+ {
+ Mutex::Autolock lock(mCallbackMutex);
+ while (callbackTicket != mCurrentCallbackTicket) {
+ mCallbackCondition.wait(mCallbackMutex);
+ }
+
+ if (frameAvailableListener != NULL) {
+ frameAvailableListener->onFrameAvailable(item);
+ } else if (frameReplacedListener != NULL) {
+ frameReplacedListener->onFrameReplaced(item);
+ }
+
+ ++mCurrentCallbackTicket;
+ mCallbackCondition.broadcast();
}
return NO_ERROR;
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index e476c9a..95f5507 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -98,7 +98,7 @@ void ConsumerBase::freeBufferLocked(int slotIndex) {
mSlots[slotIndex].mFrameNumber = 0;
}
-void ConsumerBase::onFrameAvailable() {
+void ConsumerBase::onFrameAvailable(const BufferItem& item) {
CB_LOGV("onFrameAvailable");
sp<FrameAvailableListener> listener;
@@ -109,7 +109,7 @@ void ConsumerBase::onFrameAvailable() {
if (listener != NULL) {
CB_LOGV("actually calling onFrameAvailable");
- listener->onFrameAvailable();
+ listener->onFrameAvailable(item);
}
}
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index 6ba2ef8..b886c5b 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -505,7 +505,7 @@ status_t GLConsumer::checkAndUpdateEglStateLocked(bool contextCheck) {
if (mEglDisplay == EGL_NO_DISPLAY) {
mEglDisplay = dpy;
}
- if (mEglContext == EGL_NO_DISPLAY) {
+ if (mEglContext == EGL_NO_CONTEXT) {
mEglContext = ctx;
}
}
@@ -1065,6 +1065,7 @@ GLConsumer::EglImage::~EglImage() {
if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
ALOGE("~EglImage: eglDestroyImageKHR failed");
}
+ eglTerminate(mEglDisplay);
}
}
@@ -1079,6 +1080,7 @@ status_t GLConsumer::EglImage::createIfNeeded(EGLDisplay eglDisplay,
if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
ALOGE("createIfNeeded: eglDestroyImageKHR failed");
}
+ eglTerminate(mEglDisplay);
mEglImage = EGL_NO_IMAGE_KHR;
mEglDisplay = EGL_NO_DISPLAY;
}
@@ -1129,11 +1131,13 @@ EGLImageKHR GLConsumer::EglImage::createImage(EGLDisplay dpy,
// removes this restriction if there is hardware that can support it.
attrs[2] = EGL_NONE;
}
+ eglInitialize(dpy, 0, 0);
EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
if (image == EGL_NO_IMAGE_KHR) {
EGLint error = eglGetError();
ALOGE("error creating EGLImage: %#x", error);
+ eglTerminate(dpy);
}
return image;
}
diff --git a/libs/gui/IConsumerListener.cpp b/libs/gui/IConsumerListener.cpp
index 4ccf0ac..409dfe4 100644
--- a/libs/gui/IConsumerListener.cpp
+++ b/libs/gui/IConsumerListener.cpp
@@ -21,6 +21,7 @@
#include <binder/Parcel.h>
#include <gui/IConsumerListener.h>
+#include <gui/BufferItem.h>
// ---------------------------------------------------------------------------
namespace android {
@@ -39,9 +40,10 @@ public:
: BpInterface<IConsumerListener>(impl) {
}
- virtual void onFrameAvailable() {
+ virtual void onFrameAvailable(const BufferItem& item) {
Parcel data, reply;
data.writeInterfaceToken(IConsumerListener::getInterfaceDescriptor());
+ data.write(item);
remote()->transact(ON_FRAME_AVAILABLE, data, &reply, IBinder::FLAG_ONEWAY);
}
@@ -66,18 +68,20 @@ status_t BnConsumerListener::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code) {
- case ON_FRAME_AVAILABLE:
+ case ON_FRAME_AVAILABLE: {
CHECK_INTERFACE(IConsumerListener, data, reply);
- onFrameAvailable();
- return NO_ERROR;
- case ON_BUFFER_RELEASED:
+ BufferItem item;
+ data.read(item);
+ onFrameAvailable(item);
+ return NO_ERROR; }
+ case ON_BUFFER_RELEASED: {
CHECK_INTERFACE(IConsumerListener, data, reply);
onBuffersReleased();
- return NO_ERROR;
- case ON_SIDEBAND_STREAM_CHANGED:
+ return NO_ERROR; }
+ case ON_SIDEBAND_STREAM_CHANGED: {
CHECK_INTERFACE(IConsumerListener, data, reply);
onSidebandStreamChanged();
- return NO_ERROR;
+ return NO_ERROR; }
}
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 669755a..bc4baa3 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -312,19 +312,29 @@ status_t BnSurfaceComposer::onTransact(
case SET_TRANSACTION_STATE: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
size_t count = data.readInt32();
+ if (count > data.dataSize()) {
+ return BAD_VALUE;
+ }
ComposerState s;
Vector<ComposerState> state;
state.setCapacity(count);
for (size_t i=0 ; i<count ; i++) {
- s.read(data);
+ if (s.read(data) == BAD_VALUE) {
+ return BAD_VALUE;
+ }
state.add(s);
}
count = data.readInt32();
+ if (count > data.dataSize()) {
+ return BAD_VALUE;
+ }
DisplayState d;
Vector<DisplayState> displays;
displays.setCapacity(count);
for (size_t i=0 ; i<count ; i++) {
- d.read(data);
+ if (d.read(data) == BAD_VALUE) {
+ return BAD_VALUE;
+ }
displays.add(d);
}
uint32_t flags = data.readInt32();
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index dcdcdf2..ccf8b78 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -55,8 +55,12 @@ status_t layer_state_t::read(const Parcel& input)
alpha = input.readFloat();
flags = input.readInt32();
mask = input.readInt32();
- matrix = *reinterpret_cast<layer_state_t::matrix22_t const *>(
- input.readInplace(sizeof(layer_state_t::matrix22_t)));
+ const void* matrix_data = input.readInplace(sizeof(layer_state_t::matrix22_t));
+ if (matrix_data) {
+ matrix = *reinterpret_cast<layer_state_t::matrix22_t const *>(matrix_data);
+ } else {
+ return BAD_VALUE;
+ }
input.read(crop);
input.read(transparentRegion);
return NO_ERROR;
diff --git a/libs/gui/StreamSplitter.cpp b/libs/gui/StreamSplitter.cpp
index 2fd09eb..25e6cab 100644
--- a/libs/gui/StreamSplitter.cpp
+++ b/libs/gui/StreamSplitter.cpp
@@ -98,7 +98,7 @@ void StreamSplitter::setName(const String8 &name) {
mInput->setConsumerName(name);
}
-void StreamSplitter::onFrameAvailable() {
+void StreamSplitter::onFrameAvailable(const BufferItem& /* item */) {
ATRACE_CALL();
Mutex::Autolock lock(mMutex);
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index 5cccc9b..838ad90 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -67,7 +67,7 @@ protected:
};
struct DummyConsumer : public BnConsumerListener {
- virtual void onFrameAvailable() {}
+ virtual void onFrameAvailable(const BufferItem& /* item */) {}
virtual void onBuffersReleased() {}
virtual void onSidebandStreamChanged() {}
};
diff --git a/libs/gui/tests/DisconnectWaiter.h b/libs/gui/tests/DisconnectWaiter.h
index 56e96c2..6e6915b 100644
--- a/libs/gui/tests/DisconnectWaiter.h
+++ b/libs/gui/tests/DisconnectWaiter.h
@@ -44,7 +44,7 @@ public:
mPendingFrames--;
}
- virtual void onFrameAvailable() {
+ virtual void onFrameAvailable(const BufferItem& /* item */) {
Mutex::Autolock lock(mMutex);
mPendingFrames++;
mFrameCondition.signal();
diff --git a/libs/gui/tests/FrameWaiter.h b/libs/gui/tests/FrameWaiter.h
index bdedba6..f78fa00 100644
--- a/libs/gui/tests/FrameWaiter.h
+++ b/libs/gui/tests/FrameWaiter.h
@@ -35,7 +35,7 @@ public:
mPendingFrames--;
}
- virtual void onFrameAvailable() {
+ virtual void onFrameAvailable(const BufferItem& /* item */) {
Mutex::Autolock lock(mMutex);
mPendingFrames++;
mCondition.signal();
diff --git a/libs/gui/tests/IGraphicBufferProducer_test.cpp b/libs/gui/tests/IGraphicBufferProducer_test.cpp
index aadfe61..8d5fd8f 100644
--- a/libs/gui/tests/IGraphicBufferProducer_test.cpp
+++ b/libs/gui/tests/IGraphicBufferProducer_test.cpp
@@ -65,7 +65,7 @@ const sp<Fence> QUEUE_BUFFER_INPUT_FENCE = Fence::NO_FENCE;
}; // namespace anonymous
struct DummyConsumer : public BnConsumerListener {
- virtual void onFrameAvailable() {}
+ virtual void onFrameAvailable(const BufferItem& /* item */) {}
virtual void onBuffersReleased() {}
virtual void onSidebandStreamChanged() {}
};
diff --git a/libs/gui/tests/StreamSplitter_test.cpp b/libs/gui/tests/StreamSplitter_test.cpp
index 32ec90d..4e63a6f 100644
--- a/libs/gui/tests/StreamSplitter_test.cpp
+++ b/libs/gui/tests/StreamSplitter_test.cpp
@@ -46,7 +46,7 @@ protected:
};
struct DummyListener : public BnConsumerListener {
- virtual void onFrameAvailable() {}
+ virtual void onFrameAvailable(const BufferItem& /* item */) {}
virtual void onBuffersReleased() {}
virtual void onSidebandStreamChanged() {}
};
diff --git a/libs/gui/tests/SurfaceTextureGLThreadToGL.h b/libs/gui/tests/SurfaceTextureGLThreadToGL.h
index 6410516..14e42ac 100644
--- a/libs/gui/tests/SurfaceTextureGLThreadToGL.h
+++ b/libs/gui/tests/SurfaceTextureGLThreadToGL.h
@@ -130,7 +130,7 @@ protected:
}
// This should be called by GLConsumer on the producer thread.
- virtual void onFrameAvailable() {
+ virtual void onFrameAvailable(const BufferItem& /* item */) {
Mutex::Autolock lock(mMutex);
ALOGV("+onFrameAvailable");
mFrameAvailable = true;
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 9b0bd60..e768f13 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -310,10 +310,19 @@ status_t GraphicBuffer::unflatten(
const size_t numFds = buf[8];
const size_t numInts = buf[9];
+ const size_t maxNumber = UINT_MAX / sizeof(int);
+ if (numFds >= maxNumber || numInts >= (maxNumber - 10)) {
+ width = height = stride = format = usage = 0;
+ handle = NULL;
+ ALOGE("unflatten: numFds or numInts is too large: %d, %d",
+ numFds, numInts);
+ return BAD_VALUE;
+ }
+
const size_t sizeNeeded = (10 + numInts) * sizeof(int);
if (size < sizeNeeded) return NO_MEMORY;
- size_t fdCountNeeded = 0;
+ size_t fdCountNeeded = numFds;
if (count < fdCountNeeded) return NO_MEMORY;
if (handle) {
@@ -328,6 +337,12 @@ status_t GraphicBuffer::unflatten(
format = buf[4];
usage = buf[5];
native_handle* h = native_handle_create(numFds, numInts);
+ if (!h) {
+ width = height = stride = format = usage = 0;
+ handle = NULL;
+ ALOGE("unflatten: native_handle_create failed");
+ return NO_MEMORY;
+ }
memcpy(h->data, fds, numFds*sizeof(int));
memcpy(h->data + numFds, &buf[10], numInts*sizeof(int));
handle = h;