Loading libs/gui/BufferQueueConsumer.cpp +7 −3 Original line number Original line Diff line number Diff line Loading @@ -166,7 +166,9 @@ status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer, mCore->mFreeBuffers.push_back(front->mSlot); mCore->mFreeBuffers.push_back(front->mSlot); } } if (mCore->mBufferReleasedCbEnabled) { listener = mCore->mConnectedProducerListener; listener = mCore->mConnectedProducerListener; } ++numDroppedBuffers; ++numDroppedBuffers; } } Loading Loading @@ -457,7 +459,9 @@ status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber, mCore->mFreeBuffers.push_back(slot); mCore->mFreeBuffers.push_back(slot); } } if (mCore->mBufferReleasedCbEnabled) { listener = mCore->mConnectedProducerListener; listener = mCore->mConnectedProducerListener; } BQ_LOGV("releaseBuffer: releasing slot %d", slot); BQ_LOGV("releaseBuffer: releasing slot %d", slot); mCore->mDequeueCondition.notify_all(); mCore->mDequeueCondition.notify_all(); Loading Loading @@ -668,7 +672,7 @@ status_t BufferQueueConsumer::setMaxAcquiredBufferCount( BQ_LOGV("setMaxAcquiredBufferCount: %d", maxAcquiredBuffers); BQ_LOGV("setMaxAcquiredBufferCount: %d", maxAcquiredBuffers); mCore->mMaxAcquiredBufferCount = maxAcquiredBuffers; mCore->mMaxAcquiredBufferCount = maxAcquiredBuffers; VALIDATE_CONSISTENCY(); VALIDATE_CONSISTENCY(); if (delta < 0) { if (delta < 0 && mCore->mBufferReleasedCbEnabled) { listener = mCore->mConsumerListener; listener = mCore->mConsumerListener; } } } } Loading libs/gui/BufferQueueCore.cpp +7 −0 Original line number Original line Diff line number Diff line Loading @@ -65,6 +65,7 @@ BufferQueueCore::BufferQueueCore() : mConnectedApi(NO_CONNECTED_API), mConnectedApi(NO_CONNECTED_API), mLinkedToDeath(), mLinkedToDeath(), mConnectedProducerListener(), mConnectedProducerListener(), mBufferReleasedCbEnabled(false), mSlots(), mSlots(), mQueue(), mQueue(), mFreeSlots(), mFreeSlots(), Loading Loading @@ -260,6 +261,12 @@ void BufferQueueCore::freeAllBuffersLocked() { } } void BufferQueueCore::discardFreeBuffersLocked() { void BufferQueueCore::discardFreeBuffersLocked() { // Notify producer about the discarded buffers. if (mConnectedProducerListener != nullptr && mFreeBuffers.size() > 0) { std::vector<int32_t> freeBuffers(mFreeBuffers.begin(), mFreeBuffers.end()); mConnectedProducerListener->onBuffersDiscarded(freeBuffers); } for (int s : mFreeBuffers) { for (int s : mFreeBuffers) { mFreeSlots.insert(s); mFreeSlots.insert(s); clearBufferSlotLocked(s); clearBufferSlotLocked(s); Loading libs/gui/BufferQueueProducer.cpp +2 −3 Original line number Original line Diff line number Diff line Loading @@ -1221,9 +1221,8 @@ status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener, } } mCore->mLinkedToDeath = listener; mCore->mLinkedToDeath = listener; } } if (listener->needsReleaseNotify()) { mCore->mConnectedProducerListener = listener; mCore->mConnectedProducerListener = listener; } mCore->mBufferReleasedCbEnabled = listener->needsReleaseNotify(); } } break; break; default: default: Loading libs/gui/IProducerListener.cpp +26 −0 Original line number Original line Diff line number Diff line Loading @@ -24,6 +24,7 @@ namespace android { enum { enum { ON_BUFFER_RELEASED = IBinder::FIRST_CALL_TRANSACTION, ON_BUFFER_RELEASED = IBinder::FIRST_CALL_TRANSACTION, NEEDS_RELEASE_NOTIFY, NEEDS_RELEASE_NOTIFY, ON_BUFFERS_DISCARDED, }; }; class BpProducerListener : public BpInterface<IProducerListener> class BpProducerListener : public BpInterface<IProducerListener> Loading Loading @@ -56,6 +57,13 @@ public: } } return result; return result; } } virtual void onBuffersDiscarded(const std::vector<int>& discardedSlots) { Parcel data, reply; data.writeInterfaceToken(IProducerListener::getInterfaceDescriptor()); data.writeInt32Vector(discardedSlots); remote()->transact(ON_BUFFERS_DISCARDED, data, &reply, IBinder::FLAG_ONEWAY); } }; }; // Out-of-line virtual method definition to trigger vtable emission in this // Out-of-line virtual method definition to trigger vtable emission in this Loading @@ -76,6 +84,10 @@ public: virtual bool needsReleaseNotify() override { virtual bool needsReleaseNotify() override { return mBase->needsReleaseNotify(); return mBase->needsReleaseNotify(); } } virtual void onBuffersDiscarded(const std::vector<int32_t>& discardedSlots) override { return mBase->onBuffersDiscarded(discardedSlots); } }; }; IMPLEMENT_HYBRID_META_INTERFACE(ProducerListener, IMPLEMENT_HYBRID_META_INTERFACE(ProducerListener, Loading @@ -92,6 +104,17 @@ status_t BnProducerListener::onTransact(uint32_t code, const Parcel& data, CHECK_INTERFACE(IProducerListener, data, reply); CHECK_INTERFACE(IProducerListener, data, reply); reply->writeBool(needsReleaseNotify()); reply->writeBool(needsReleaseNotify()); return NO_ERROR; return NO_ERROR; case ON_BUFFERS_DISCARDED: { CHECK_INTERFACE(IProducerListener, data, reply); std::vector<int32_t> discardedSlots; status_t result = data.readInt32Vector(&discardedSlots); if (result != NO_ERROR) { ALOGE("ON_BUFFERS_DISCARDED failed to read discardedSlots: %d", result); return result; } onBuffersDiscarded(discardedSlots); return NO_ERROR; } } } return BBinder::onTransact(code, data, reply, flags); return BBinder::onTransact(code, data, reply, flags); } } Loading @@ -104,4 +127,7 @@ bool BnProducerListener::needsReleaseNotify() { return true; return true; } } void BnProducerListener::onBuffersDiscarded(const std::vector<int32_t>& /*discardedSlots*/) { } } // namespace android } // namespace android libs/gui/Surface.cpp +49 −0 Original line number Original line Diff line number Diff line Loading @@ -35,6 +35,7 @@ #include <ui/DisplayStatInfo.h> #include <ui/DisplayStatInfo.h> #include <ui/Fence.h> #include <ui/Fence.h> #include <ui/GraphicBuffer.h> #include <ui/HdrCapabilities.h> #include <ui/HdrCapabilities.h> #include <ui/Region.h> #include <ui/Region.h> Loading Loading @@ -1286,6 +1287,14 @@ int Surface::connect(int api, const sp<IProducerListener>& listener) { return connect(api, listener, false); return connect(api, listener, false); } } int Surface::connect( int api, bool reportBufferRemoval, const sp<SurfaceListener>& sListener) { if (sListener != nullptr) { mListenerProxy = new ProducerListenerProxy(this, sListener); } return connect(api, mListenerProxy, reportBufferRemoval); } int Surface::connect( int Surface::connect( int api, const sp<IProducerListener>& listener, bool reportBufferRemoval) { int api, const sp<IProducerListener>& listener, bool reportBufferRemoval) { ATRACE_CALL(); ATRACE_CALL(); Loading Loading @@ -1684,6 +1693,28 @@ void Surface::freeAllBuffers() { } } } } status_t Surface::getAndFlushBuffersFromSlots(const std::vector<int32_t>& slots, std::vector<sp<GraphicBuffer>>* outBuffers) { ALOGV("Surface::getAndFlushBuffersFromSlots"); for (int32_t i : slots) { if (i < 0 || i >= NUM_BUFFER_SLOTS) { ALOGE("%s: Invalid slotIndex: %d", __FUNCTION__, i); return BAD_VALUE; } } Mutex::Autolock lock(mMutex); for (int32_t i : slots) { if (mSlots[i].buffer == nullptr) { ALOGW("%s: Discarded slot %d doesn't contain buffer!", __FUNCTION__, i); continue; } outBuffers->push_back(mSlots[i].buffer); mSlots[i].buffer = nullptr; } return OK; } void Surface::setSurfaceDamage(android_native_rect_t* rects, size_t numRects) { void Surface::setSurfaceDamage(android_native_rect_t* rects, size_t numRects) { ATRACE_CALL(); ATRACE_CALL(); ALOGV("Surface::setSurfaceDamage"); ALOGV("Surface::setSurfaceDamage"); Loading Loading @@ -1951,4 +1982,22 @@ status_t Surface::attachAndQueueBufferWithDataspace(Surface* surface, sp<Graphic return err; return err; } } void Surface::ProducerListenerProxy::onBuffersDiscarded(const std::vector<int32_t>& slots) { ATRACE_CALL(); sp<Surface> parent = mParent.promote(); if (parent == nullptr) { return; } std::vector<sp<GraphicBuffer>> discardedBufs; status_t res = parent->getAndFlushBuffersFromSlots(slots, &discardedBufs); if (res != OK) { ALOGE("%s: Failed to get buffers from slots: %s(%d)", __FUNCTION__, strerror(-res), res); return; } mSurfaceListener->onBuffersDiscarded(discardedBufs); } }; // namespace android }; // namespace android Loading
libs/gui/BufferQueueConsumer.cpp +7 −3 Original line number Original line Diff line number Diff line Loading @@ -166,7 +166,9 @@ status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer, mCore->mFreeBuffers.push_back(front->mSlot); mCore->mFreeBuffers.push_back(front->mSlot); } } if (mCore->mBufferReleasedCbEnabled) { listener = mCore->mConnectedProducerListener; listener = mCore->mConnectedProducerListener; } ++numDroppedBuffers; ++numDroppedBuffers; } } Loading Loading @@ -457,7 +459,9 @@ status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber, mCore->mFreeBuffers.push_back(slot); mCore->mFreeBuffers.push_back(slot); } } if (mCore->mBufferReleasedCbEnabled) { listener = mCore->mConnectedProducerListener; listener = mCore->mConnectedProducerListener; } BQ_LOGV("releaseBuffer: releasing slot %d", slot); BQ_LOGV("releaseBuffer: releasing slot %d", slot); mCore->mDequeueCondition.notify_all(); mCore->mDequeueCondition.notify_all(); Loading Loading @@ -668,7 +672,7 @@ status_t BufferQueueConsumer::setMaxAcquiredBufferCount( BQ_LOGV("setMaxAcquiredBufferCount: %d", maxAcquiredBuffers); BQ_LOGV("setMaxAcquiredBufferCount: %d", maxAcquiredBuffers); mCore->mMaxAcquiredBufferCount = maxAcquiredBuffers; mCore->mMaxAcquiredBufferCount = maxAcquiredBuffers; VALIDATE_CONSISTENCY(); VALIDATE_CONSISTENCY(); if (delta < 0) { if (delta < 0 && mCore->mBufferReleasedCbEnabled) { listener = mCore->mConsumerListener; listener = mCore->mConsumerListener; } } } } Loading
libs/gui/BufferQueueCore.cpp +7 −0 Original line number Original line Diff line number Diff line Loading @@ -65,6 +65,7 @@ BufferQueueCore::BufferQueueCore() : mConnectedApi(NO_CONNECTED_API), mConnectedApi(NO_CONNECTED_API), mLinkedToDeath(), mLinkedToDeath(), mConnectedProducerListener(), mConnectedProducerListener(), mBufferReleasedCbEnabled(false), mSlots(), mSlots(), mQueue(), mQueue(), mFreeSlots(), mFreeSlots(), Loading Loading @@ -260,6 +261,12 @@ void BufferQueueCore::freeAllBuffersLocked() { } } void BufferQueueCore::discardFreeBuffersLocked() { void BufferQueueCore::discardFreeBuffersLocked() { // Notify producer about the discarded buffers. if (mConnectedProducerListener != nullptr && mFreeBuffers.size() > 0) { std::vector<int32_t> freeBuffers(mFreeBuffers.begin(), mFreeBuffers.end()); mConnectedProducerListener->onBuffersDiscarded(freeBuffers); } for (int s : mFreeBuffers) { for (int s : mFreeBuffers) { mFreeSlots.insert(s); mFreeSlots.insert(s); clearBufferSlotLocked(s); clearBufferSlotLocked(s); Loading
libs/gui/BufferQueueProducer.cpp +2 −3 Original line number Original line Diff line number Diff line Loading @@ -1221,9 +1221,8 @@ status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener, } } mCore->mLinkedToDeath = listener; mCore->mLinkedToDeath = listener; } } if (listener->needsReleaseNotify()) { mCore->mConnectedProducerListener = listener; mCore->mConnectedProducerListener = listener; } mCore->mBufferReleasedCbEnabled = listener->needsReleaseNotify(); } } break; break; default: default: Loading
libs/gui/IProducerListener.cpp +26 −0 Original line number Original line Diff line number Diff line Loading @@ -24,6 +24,7 @@ namespace android { enum { enum { ON_BUFFER_RELEASED = IBinder::FIRST_CALL_TRANSACTION, ON_BUFFER_RELEASED = IBinder::FIRST_CALL_TRANSACTION, NEEDS_RELEASE_NOTIFY, NEEDS_RELEASE_NOTIFY, ON_BUFFERS_DISCARDED, }; }; class BpProducerListener : public BpInterface<IProducerListener> class BpProducerListener : public BpInterface<IProducerListener> Loading Loading @@ -56,6 +57,13 @@ public: } } return result; return result; } } virtual void onBuffersDiscarded(const std::vector<int>& discardedSlots) { Parcel data, reply; data.writeInterfaceToken(IProducerListener::getInterfaceDescriptor()); data.writeInt32Vector(discardedSlots); remote()->transact(ON_BUFFERS_DISCARDED, data, &reply, IBinder::FLAG_ONEWAY); } }; }; // Out-of-line virtual method definition to trigger vtable emission in this // Out-of-line virtual method definition to trigger vtable emission in this Loading @@ -76,6 +84,10 @@ public: virtual bool needsReleaseNotify() override { virtual bool needsReleaseNotify() override { return mBase->needsReleaseNotify(); return mBase->needsReleaseNotify(); } } virtual void onBuffersDiscarded(const std::vector<int32_t>& discardedSlots) override { return mBase->onBuffersDiscarded(discardedSlots); } }; }; IMPLEMENT_HYBRID_META_INTERFACE(ProducerListener, IMPLEMENT_HYBRID_META_INTERFACE(ProducerListener, Loading @@ -92,6 +104,17 @@ status_t BnProducerListener::onTransact(uint32_t code, const Parcel& data, CHECK_INTERFACE(IProducerListener, data, reply); CHECK_INTERFACE(IProducerListener, data, reply); reply->writeBool(needsReleaseNotify()); reply->writeBool(needsReleaseNotify()); return NO_ERROR; return NO_ERROR; case ON_BUFFERS_DISCARDED: { CHECK_INTERFACE(IProducerListener, data, reply); std::vector<int32_t> discardedSlots; status_t result = data.readInt32Vector(&discardedSlots); if (result != NO_ERROR) { ALOGE("ON_BUFFERS_DISCARDED failed to read discardedSlots: %d", result); return result; } onBuffersDiscarded(discardedSlots); return NO_ERROR; } } } return BBinder::onTransact(code, data, reply, flags); return BBinder::onTransact(code, data, reply, flags); } } Loading @@ -104,4 +127,7 @@ bool BnProducerListener::needsReleaseNotify() { return true; return true; } } void BnProducerListener::onBuffersDiscarded(const std::vector<int32_t>& /*discardedSlots*/) { } } // namespace android } // namespace android
libs/gui/Surface.cpp +49 −0 Original line number Original line Diff line number Diff line Loading @@ -35,6 +35,7 @@ #include <ui/DisplayStatInfo.h> #include <ui/DisplayStatInfo.h> #include <ui/Fence.h> #include <ui/Fence.h> #include <ui/GraphicBuffer.h> #include <ui/HdrCapabilities.h> #include <ui/HdrCapabilities.h> #include <ui/Region.h> #include <ui/Region.h> Loading Loading @@ -1286,6 +1287,14 @@ int Surface::connect(int api, const sp<IProducerListener>& listener) { return connect(api, listener, false); return connect(api, listener, false); } } int Surface::connect( int api, bool reportBufferRemoval, const sp<SurfaceListener>& sListener) { if (sListener != nullptr) { mListenerProxy = new ProducerListenerProxy(this, sListener); } return connect(api, mListenerProxy, reportBufferRemoval); } int Surface::connect( int Surface::connect( int api, const sp<IProducerListener>& listener, bool reportBufferRemoval) { int api, const sp<IProducerListener>& listener, bool reportBufferRemoval) { ATRACE_CALL(); ATRACE_CALL(); Loading Loading @@ -1684,6 +1693,28 @@ void Surface::freeAllBuffers() { } } } } status_t Surface::getAndFlushBuffersFromSlots(const std::vector<int32_t>& slots, std::vector<sp<GraphicBuffer>>* outBuffers) { ALOGV("Surface::getAndFlushBuffersFromSlots"); for (int32_t i : slots) { if (i < 0 || i >= NUM_BUFFER_SLOTS) { ALOGE("%s: Invalid slotIndex: %d", __FUNCTION__, i); return BAD_VALUE; } } Mutex::Autolock lock(mMutex); for (int32_t i : slots) { if (mSlots[i].buffer == nullptr) { ALOGW("%s: Discarded slot %d doesn't contain buffer!", __FUNCTION__, i); continue; } outBuffers->push_back(mSlots[i].buffer); mSlots[i].buffer = nullptr; } return OK; } void Surface::setSurfaceDamage(android_native_rect_t* rects, size_t numRects) { void Surface::setSurfaceDamage(android_native_rect_t* rects, size_t numRects) { ATRACE_CALL(); ATRACE_CALL(); ALOGV("Surface::setSurfaceDamage"); ALOGV("Surface::setSurfaceDamage"); Loading Loading @@ -1951,4 +1982,22 @@ status_t Surface::attachAndQueueBufferWithDataspace(Surface* surface, sp<Graphic return err; return err; } } void Surface::ProducerListenerProxy::onBuffersDiscarded(const std::vector<int32_t>& slots) { ATRACE_CALL(); sp<Surface> parent = mParent.promote(); if (parent == nullptr) { return; } std::vector<sp<GraphicBuffer>> discardedBufs; status_t res = parent->getAndFlushBuffersFromSlots(slots, &discardedBufs); if (res != OK) { ALOGE("%s: Failed to get buffers from slots: %s(%d)", __FUNCTION__, strerror(-res), res); return; } mSurfaceListener->onBuffersDiscarded(discardedBufs); } }; // namespace android }; // namespace android