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/CpuConsumer.cpp95
-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/GraphicBufferMapper.cpp11
20 files changed, 226 insertions, 121 deletions
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index a24621b..87ce5d0 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;
}
@@ -1309,23 +1307,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));
}
}
@@ -1529,11 +1515,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);
}
}
@@ -1562,6 +1557,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;
}
@@ -1641,6 +1641,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;
@@ -1675,6 +1681,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) {
@@ -1705,6 +1717,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);
@@ -1717,6 +1735,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 d2fd3b0..16b9747 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 f19b6c7..210e98e 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/CpuConsumer.cpp b/libs/gui/CpuConsumer.cpp
index cefd7f1..c541ff4 100644
--- a/libs/gui/CpuConsumer.cpp
+++ b/libs/gui/CpuConsumer.cpp
@@ -67,6 +67,34 @@ status_t CpuConsumer::setDefaultBufferFormat(uint32_t defaultFormat)
return mConsumer->setDefaultBufferFormat(defaultFormat);
}
+static bool isPossiblyYUV(PixelFormat format) {
+ switch ((int)format) {
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ case HAL_PIXEL_FORMAT_RGB_888:
+ case HAL_PIXEL_FORMAT_RGB_565:
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ case HAL_PIXEL_FORMAT_sRGB_A_8888:
+ case HAL_PIXEL_FORMAT_sRGB_X_8888:
+ case HAL_PIXEL_FORMAT_Y8:
+ case HAL_PIXEL_FORMAT_Y16:
+ case HAL_PIXEL_FORMAT_RAW16: // same as HAL_PIXEL_FORMAT_RAW_SENSOR
+ case HAL_PIXEL_FORMAT_RAW10:
+ case HAL_PIXEL_FORMAT_RAW_OPAQUE:
+ case HAL_PIXEL_FORMAT_BLOB:
+ case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
+ return false;
+
+ case HAL_PIXEL_FORMAT_YV12:
+ case HAL_PIXEL_FORMAT_YCbCr_420_888:
+ case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ case HAL_PIXEL_FORMAT_YCbCr_422_I:
+ default:
+ return true;
+ }
+}
+
status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) {
status_t err;
@@ -96,59 +124,51 @@ status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) {
void *bufferPointer = NULL;
android_ycbcr ycbcr = android_ycbcr();
- if (b.mFence.get()) {
- if (mSlots[buf].mGraphicBuffer->getPixelFormat() ==
- HAL_PIXEL_FORMAT_YCbCr_420_888) {
+ PixelFormat format = mSlots[buf].mGraphicBuffer->getPixelFormat();
+ PixelFormat flexFormat = format;
+ if (isPossiblyYUV(format)) {
+ if (b.mFence.get()) {
err = mSlots[buf].mGraphicBuffer->lockAsyncYCbCr(
GraphicBuffer::USAGE_SW_READ_OFTEN,
b.mCrop,
&ycbcr,
b.mFence->dup());
-
- if (err != OK) {
- CC_LOGE("Unable to lock YCbCr buffer for CPU reading: %s (%d)",
- strerror(-err), err);
- return err;
- }
- bufferPointer = ycbcr.y;
} else {
- err = mSlots[buf].mGraphicBuffer->lockAsync(
+ err = mSlots[buf].mGraphicBuffer->lockYCbCr(
GraphicBuffer::USAGE_SW_READ_OFTEN,
b.mCrop,
- &bufferPointer,
- b.mFence->dup());
-
- if (err != OK) {
- CC_LOGE("Unable to lock buffer for CPU reading: %s (%d)",
- strerror(-err), err);
- return err;
+ &ycbcr);
+ }
+ if (err == OK) {
+ bufferPointer = ycbcr.y;
+ flexFormat = HAL_PIXEL_FORMAT_YCbCr_420_888;
+ if (format != HAL_PIXEL_FORMAT_YCbCr_420_888) {
+ CC_LOGV("locking buffer of format %#x as flex YUV", format);
}
+ } else if (format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+ CC_LOGE("Unable to lock YCbCr buffer for CPU reading: %s (%d)",
+ strerror(-err), err);
+ return err;
}
- } else {
- if (mSlots[buf].mGraphicBuffer->getPixelFormat() ==
- HAL_PIXEL_FORMAT_YCbCr_420_888) {
- err = mSlots[buf].mGraphicBuffer->lockYCbCr(
+ }
+
+ if (bufferPointer == NULL) { // not flexible YUV
+ if (b.mFence.get()) {
+ err = mSlots[buf].mGraphicBuffer->lockAsync(
GraphicBuffer::USAGE_SW_READ_OFTEN,
b.mCrop,
- &ycbcr);
-
- if (err != OK) {
- CC_LOGE("Unable to lock YCbCr buffer for CPU reading: %s (%d)",
- strerror(-err), err);
- return err;
- }
- bufferPointer = ycbcr.y;
+ &bufferPointer,
+ b.mFence->dup());
} else {
err = mSlots[buf].mGraphicBuffer->lock(
GraphicBuffer::USAGE_SW_READ_OFTEN,
b.mCrop,
&bufferPointer);
-
- if (err != OK) {
- CC_LOGE("Unable to lock buffer for CPU reading: %s (%d)",
- strerror(-err), err);
- return err;
- }
+ }
+ if (err != OK) {
+ CC_LOGE("Unable to lock buffer for CPU reading: %s (%d)",
+ strerror(-err), err);
+ return err;
}
}
@@ -170,7 +190,8 @@ status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) {
reinterpret_cast<uint8_t*>(bufferPointer);
nativeBuffer->width = mSlots[buf].mGraphicBuffer->getWidth();
nativeBuffer->height = mSlots[buf].mGraphicBuffer->getHeight();
- nativeBuffer->format = mSlots[buf].mGraphicBuffer->getPixelFormat();
+ nativeBuffer->format = format;
+ nativeBuffer->flexFormat = flexFormat;
nativeBuffer->stride = (ycbcr.y != NULL) ?
ycbcr.ystride :
mSlots[buf].mGraphicBuffer->getStride();
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index ccafe81..318c087 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 81e8336..ebb687a 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 e95d8b6..1183d59 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 771b263..5f39905 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 c781366..96de11f 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/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp
index 320b6c0..e949b0c 100644
--- a/libs/ui/GraphicBufferMapper.cpp
+++ b/libs/ui/GraphicBufferMapper.cpp
@@ -92,6 +92,10 @@ status_t GraphicBufferMapper::lockYCbCr(buffer_handle_t handle,
ATRACE_CALL();
status_t err;
+ if (mAllocMod->lock_ycbcr == NULL) {
+ return -EINVAL; // do not log failure
+ }
+
err = mAllocMod->lock_ycbcr(mAllocMod, handle, usage,
bounds.left, bounds.top, bounds.width(), bounds.height(),
ycbcr);
@@ -139,16 +143,19 @@ status_t GraphicBufferMapper::lockAsyncYCbCr(buffer_handle_t handle,
ATRACE_CALL();
status_t err;
- if (mAllocMod->common.module_api_version >= GRALLOC_MODULE_API_VERSION_0_3) {
+ if (mAllocMod->common.module_api_version >= GRALLOC_MODULE_API_VERSION_0_3
+ && mAllocMod->lockAsync_ycbcr != NULL) {
err = mAllocMod->lockAsync_ycbcr(mAllocMod, handle, usage,
bounds.left, bounds.top, bounds.width(), bounds.height(),
ycbcr, fenceFd);
- } else {
+ } else if (mAllocMod->lock_ycbcr != NULL) {
sync_wait(fenceFd, -1);
close(fenceFd);
err = mAllocMod->lock_ycbcr(mAllocMod, handle, usage,
bounds.left, bounds.top, bounds.width(), bounds.height(),
ycbcr);
+ } else {
+ return -EINVAL; // do not log failure
}
ALOGW_IF(err, "lock(...) failed %d (%s)", err, strerror(-err));