diff options
Diffstat (limited to 'libs')
-rw-r--r-- | libs/binder/Parcel.cpp | 101 | ||||
-rw-r--r-- | libs/binder/Static.cpp | 2 | ||||
-rw-r--r-- | libs/binder/TextOutput.cpp | 4 | ||||
-rw-r--r-- | libs/gui/BufferItem.cpp | 2 | ||||
-rw-r--r-- | libs/gui/BufferQueue.cpp | 5 | ||||
-rw-r--r-- | libs/gui/BufferQueueProducer.cpp | 61 | ||||
-rw-r--r-- | libs/gui/ConsumerBase.cpp | 4 | ||||
-rw-r--r-- | libs/gui/CpuConsumer.cpp | 95 | ||||
-rw-r--r-- | libs/gui/GLConsumer.cpp | 6 | ||||
-rw-r--r-- | libs/gui/IConsumerListener.cpp | 20 | ||||
-rw-r--r-- | libs/gui/ISurfaceComposer.cpp | 14 | ||||
-rw-r--r-- | libs/gui/LayerState.cpp | 8 | ||||
-rw-r--r-- | libs/gui/StreamSplitter.cpp | 2 | ||||
-rw-r--r-- | libs/gui/tests/BufferQueue_test.cpp | 2 | ||||
-rw-r--r-- | libs/gui/tests/DisconnectWaiter.h | 2 | ||||
-rw-r--r-- | libs/gui/tests/FrameWaiter.h | 2 | ||||
-rw-r--r-- | libs/gui/tests/IGraphicBufferProducer_test.cpp | 2 | ||||
-rw-r--r-- | libs/gui/tests/StreamSplitter_test.cpp | 2 | ||||
-rw-r--r-- | libs/gui/tests/SurfaceTextureGLThreadToGL.h | 2 | ||||
-rw-r--r-- | libs/ui/GraphicBufferMapper.cpp | 11 |
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)); |