Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 10fcdbed authored by Jim Shargo's avatar Jim Shargo Committed by Android (Google) Code Review
Browse files

Merge changes I374aa204,I0df872b9 into main

* changes:
  libgui: Add unlimited slot support to Surfaces and Consumers
  libgui: Add support for unlimited slot BufferQueues
parents 8703fd84 4f9c275b
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -108,6 +108,15 @@ void BufferQueue::ProxyConsumerListener::onSetFrameRate(float frameRate, int8_t
}
#endif

#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
void BufferQueue::ProxyConsumerListener::onSlotCountChanged(int slotCount) {
    sp<ConsumerListener> listener(mConsumerListener.promote());
    if (listener != nullptr) {
        listener->onSlotCountChanged(slotCount);
    }
}
#endif

void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
        sp<IGraphicBufferConsumer>* outConsumer,
        bool consumerIsSurfaceFlinger) {
+90 −14
Original line number Diff line number Diff line
@@ -341,9 +341,9 @@ status_t BufferQueueConsumer::detachBuffer(int slot) {
            return BAD_VALUE;
        }

        if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
            BQ_LOGE("detachBuffer: slot index %d out of range [0, %d)",
                    slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
        const int totalSlotCount = mCore->getTotalSlotCountLocked();
        if (slot < 0 || slot >= totalSlotCount) {
            BQ_LOGE("detachBuffer: slot index %d out of range [0, %d)", slot, totalSlotCount);
            return BAD_VALUE;
        } else if (!mSlots[slot].mBufferState.isAcquired()) {
            BQ_LOGE("detachBuffer: slot %d is not owned by the consumer "
@@ -483,10 +483,13 @@ status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber,
    ATRACE_CALL();
    ATRACE_BUFFER_INDEX(slot);

    if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS ||
            releaseFence == nullptr) {
        BQ_LOGE("releaseBuffer: slot %d out of range or fence %p NULL", slot,
                releaseFence.get());
    const int totalSlotCount = mCore->getTotalSlotCountLocked();
    if (slot < 0 || slot >= totalSlotCount) {
        BQ_LOGE("releaseBuffer: slot index %d out of range [0, %d)", slot, totalSlotCount);
        return BAD_VALUE;
    }
    if (releaseFence == nullptr) {
        BQ_LOGE("releaseBuffer: slot %d fence %p NULL", slot, releaseFence.get());
        return BAD_VALUE;
    }

@@ -515,6 +518,13 @@ status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber,
    { // Autolock scope
        std::lock_guard<std::mutex> lock(mCore->mMutex);

        const int totalSlotCount = mCore->getTotalSlotCountLocked();
        if (slot < 0 || slot >= totalSlotCount || releaseFence == nullptr) {
            BQ_LOGE("releaseBuffer: slot %d out of range [0, %d) or fence %p NULL", slot,
                    totalSlotCount, releaseFence.get());
            return BAD_VALUE;
        }

        // If the frame number has changed because the buffer has been reallocated,
        // we can ignore this releaseBuffer for the old buffer.
        // Ignore this for the shared buffer where the frame number can easily
@@ -661,6 +671,43 @@ status_t BufferQueueConsumer::getReleasedBuffers(uint64_t *outSlotMask) {
    return NO_ERROR;
}

#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
status_t BufferQueueConsumer::getReleasedBuffersExtended(std::vector<bool>* outSlotMask) {
    ATRACE_CALL();

    if (outSlotMask == nullptr) {
        BQ_LOGE("getReleasedBuffersExtended: outSlotMask may not be NULL");
        return BAD_VALUE;
    }

    std::lock_guard<std::mutex> lock(mCore->mMutex);

    if (mCore->mIsAbandoned) {
        BQ_LOGE("getReleasedBuffersExtended: BufferQueue has been abandoned");
        return NO_INIT;
    }

    const int totalSlotCount = mCore->getTotalSlotCountLocked();
    outSlotMask->resize(totalSlotCount);
    for (int s = 0; s < totalSlotCount; ++s) {
        (*outSlotMask)[s] = !mSlots[s].mAcquireCalled;
    }

    // Remove from the mask queued buffers for which acquire has been called,
    // since the consumer will not receive their buffer addresses and so must
    // retain their cached information
    BufferQueueCore::Fifo::iterator current(mCore->mQueue.begin());
    while (current != mCore->mQueue.end()) {
        if (current->mAcquireCalled) {
            (*outSlotMask)[current->mSlot] = false;
        }
        ++current;
    }

    return NO_ERROR;
}
#endif

status_t BufferQueueConsumer::setDefaultBufferSize(uint32_t width,
        uint32_t height) {
    ATRACE_CALL();
@@ -679,6 +726,28 @@ status_t BufferQueueConsumer::setDefaultBufferSize(uint32_t width,
    return NO_ERROR;
}

#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
status_t BufferQueueConsumer::allowUnlimitedSlots(bool allowUnlimitedSlots) {
    ATRACE_CALL();
    BQ_LOGV("allowUnlimitedSlots: %d", allowUnlimitedSlots);
    std::lock_guard<std::mutex> lock(mCore->mMutex);

    if (mCore->mIsAbandoned) {
        BQ_LOGE("allowUnlimitedSlots: BufferQueue has been abandoned");
        return NO_INIT;
    }

    if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
        BQ_LOGE("allowUnlimitedSlots: BufferQueue already connected");
        return INVALID_OPERATION;
    }

    mCore->mAllowExtendedSlotCount = allowUnlimitedSlots;

    return OK;
}
#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)

status_t BufferQueueConsumer::setMaxBufferCount(int bufferCount) {
    ATRACE_CALL();

@@ -718,16 +787,23 @@ status_t BufferQueueConsumer::setMaxAcquiredBufferCount(
        int maxAcquiredBuffers) {
    ATRACE_FORMAT("%s(%d)", __func__, maxAcquiredBuffers);

    if (maxAcquiredBuffers < 1 ||
            maxAcquiredBuffers > BufferQueueCore::MAX_MAX_ACQUIRED_BUFFERS) {
        BQ_LOGE("setMaxAcquiredBufferCount: invalid count %d",
                maxAcquiredBuffers);
        return BAD_VALUE;
    }

    sp<IConsumerListener> listener;
    { // Autolock scope
        std::unique_lock<std::mutex> lock(mCore->mMutex);

        // We reserve two slots in order to guarantee that the producer and
        // consumer can run asynchronously.
        int maxMaxAcquiredBuffers =
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
                mCore->getTotalSlotCountLocked() - 2;
#else
                BufferQueueCore::MAX_MAX_ACQUIRED_BUFFERS;
#endif
        if (maxAcquiredBuffers < 1 || maxAcquiredBuffers > maxMaxAcquiredBuffers) {
            BQ_LOGE("setMaxAcquiredBufferCount: invalid count %d", maxAcquiredBuffers);
            return BAD_VALUE;
        }

        mCore->waitWhileAllocatingLocked(lock);

        if (mCore->mIsAbandoned) {
+38 −1
Original line number Diff line number Diff line
@@ -38,6 +38,8 @@

#include <system/window.h>

#include <ui/BufferQueueDefs.h>

namespace android {

// Macros for include BufferQueueCore information in log messages
@@ -97,7 +99,11 @@ BufferQueueCore::BufferQueueCore()
        mConnectedProducerListener(),
        mBufferReleasedCbEnabled(false),
        mBufferAttachedCbEnabled(false),
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
        mSlots(BufferQueueDefs::NUM_BUFFER_SLOTS),
#else
        mSlots(),
#endif
        mQueue(),
        mFreeSlots(),
        mFreeBuffers(),
@@ -111,6 +117,9 @@ BufferQueueCore::BufferQueueCore()
        mDefaultWidth(1),
        mDefaultHeight(1),
        mDefaultBufferDataSpace(HAL_DATASPACE_UNKNOWN),
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
        mAllowExtendedSlotCount(false),
#endif
        mMaxBufferCount(BufferQueueDefs::NUM_BUFFER_SLOTS),
        mMaxAcquiredBufferCount(1),
        mMaxDequeuedBufferCount(1),
@@ -221,6 +230,14 @@ void BufferQueueCore::dumpState(const String8& prefix, String8* outResult) const
    }
}

int BufferQueueCore::getTotalSlotCountLocked() const {
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
    return mAllowExtendedSlotCount ? mMaxBufferCount : BufferQueueDefs::NUM_BUFFER_SLOTS;
#else
    return BufferQueueDefs::NUM_BUFFER_SLOTS;
#endif
}

int BufferQueueCore::getMinUndequeuedBufferCountLocked() const {
    // If dequeueBuffer is allowed to error out, we don't have to add an
    // extra buffer.
@@ -253,6 +270,26 @@ int BufferQueueCore::getMaxBufferCountLocked() const {
    return maxBufferCount;
}

#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
status_t BufferQueueCore::extendSlotCountLocked(int size) {
    int previousSize = (int)mSlots.size();
    if (previousSize > size) {
        return BAD_VALUE;
    }
    if (previousSize == size) {
        return NO_ERROR;
    }

    mSlots.resize(size);
    for (int i = previousSize; i < size; i++) {
        mUnusedSlots.push_back(i);
    }

    mMaxBufferCount = size;
    return NO_ERROR;
}
#endif

void BufferQueueCore::clearBufferSlotLocked(int slot) {
    BQ_LOGV("clearBufferSlotLocked: slot %d", slot);

@@ -383,7 +420,7 @@ void BufferQueueCore::notifyBufferReleased() const {
void BufferQueueCore::validateConsistencyLocked() const {
    static const useconds_t PAUSE_TIME = 0;
    int allocatedSlots = 0;
    for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) {
    for (int slot = 0; slot < getTotalSlotCountLocked(); ++slot) {
        bool isInFreeSlots = mFreeSlots.count(slot) != 0;
        bool isInFreeBuffers =
                std::find(mFreeBuffers.cbegin(), mFreeBuffers.cend(), slot) !=
+62 −14
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@
#include <gui/TraceUtils.h>
#include <private/gui/BufferQueueThreadState.h>

#include <utils/Errors.h>
#include <utils/Log.h>
#include <utils/Trace.h>

@@ -108,9 +109,9 @@ status_t BufferQueueProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
        return NO_INIT;
    }

    if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
        BQ_LOGE("requestBuffer: slot index %d out of range [0, %d)",
                slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
    int maxSlot = mCore->getTotalSlotCountLocked();
    if (slot < 0 || slot >= maxSlot) {
        BQ_LOGE("requestBuffer: slot index %d out of range [0, %d)", slot, maxSlot);
        return BAD_VALUE;
    } else if (!mSlots[slot].mBufferState.isDequeued()) {
        BQ_LOGE("requestBuffer: slot %d is not owned by the producer "
@@ -123,6 +124,49 @@ status_t BufferQueueProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
    return NO_ERROR;
}

#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
status_t BufferQueueProducer::extendSlotCount(int size) {
    ATRACE_CALL();

    sp<IConsumerListener> listener;
    {
        std::lock_guard<std::mutex> lock(mCore->mMutex);
        BQ_LOGV("extendSlotCount: size %d", size);

        if (mCore->mIsAbandoned) {
            BQ_LOGE("extendSlotCount: BufferQueue has been abandoned");
            return NO_INIT;
        }

        if (!mCore->mAllowExtendedSlotCount) {
            BQ_LOGE("extendSlotCount: Consumer did not allow unlimited slots");
            return INVALID_OPERATION;
        }

        int maxBeforeExtension = mCore->mMaxBufferCount;

        if (size == maxBeforeExtension) {
            return NO_ERROR;
        }

        if (size < maxBeforeExtension) {
            return BAD_VALUE;
        }

        if (status_t ret = mCore->extendSlotCountLocked(size); ret != OK) {
            return ret;
        }
        listener = mCore->mConsumerListener;
    }

    if (listener) {
        listener->onSlotCountChanged(size);
    }

    return NO_ERROR;
}
#endif

status_t BufferQueueProducer::setMaxDequeuedBufferCount(
        int maxDequeuedBuffers) {
    int maxBufferCount;
@@ -170,9 +214,10 @@ status_t BufferQueueProducer::setMaxDequeuedBufferCount(int maxDequeuedBuffers,
        int bufferCount = mCore->getMinUndequeuedBufferCountLocked();
        bufferCount += maxDequeuedBuffers;

        if (bufferCount > BufferQueueDefs::NUM_BUFFER_SLOTS) {
        if (bufferCount > mCore->getTotalSlotCountLocked()) {
            BQ_LOGE("setMaxDequeuedBufferCount: bufferCount %d too large "
                    "(max %d)", bufferCount, BufferQueueDefs::NUM_BUFFER_SLOTS);
                    "(max %d)",
                    bufferCount, mCore->getTotalSlotCountLocked());
            return BAD_VALUE;
        }

@@ -756,9 +801,9 @@ status_t BufferQueueProducer::detachBuffer(int slot) {
            return BAD_VALUE;
        }

        if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
            BQ_LOGE("detachBuffer: slot index %d out of range [0, %d)",
                    slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
        const int totalSlotCount = mCore->getTotalSlotCountLocked();
        if (slot < 0 || slot >= totalSlotCount) {
            BQ_LOGE("detachBuffer: slot index %d out of range [0, %d)", slot, totalSlotCount);
            return BAD_VALUE;
        } else if (!mSlots[slot].mBufferState.isDequeued()) {
            // TODO(http://b/140581935): This message is BQ_LOGW because it
@@ -993,9 +1038,9 @@ status_t BufferQueueProducer::queueBuffer(int slot,
            return NO_INIT;
        }

        if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
            BQ_LOGE("queueBuffer: slot index %d out of range [0, %d)",
                    slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
        const int totalSlotCount = mCore->getTotalSlotCountLocked();
        if (slot < 0 || slot >= totalSlotCount) {
            BQ_LOGE("queueBuffer: slot index %d out of range [0, %d)", slot, totalSlotCount);
            return BAD_VALUE;
        } else if (!mSlots[slot].mBufferState.isDequeued()) {
            BQ_LOGE("queueBuffer: slot %d is not owned by the producer "
@@ -1239,9 +1284,9 @@ status_t BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
            return BAD_VALUE;
        }

        if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
            BQ_LOGE("cancelBuffer: slot index %d out of range [0, %d)", slot,
                    BufferQueueDefs::NUM_BUFFER_SLOTS);
        const int totalSlotCount = mCore->getTotalSlotCountLocked();
        if (slot < 0 || slot >= totalSlotCount) {
            BQ_LOGE("cancelBuffer: slot index %d out of range [0, %d)", slot, totalSlotCount);
            return BAD_VALUE;
        } else if (!mSlots[slot].mBufferState.isDequeued()) {
            BQ_LOGE("cancelBuffer: slot %d is not owned by the producer "
@@ -1409,6 +1454,9 @@ status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener,
            output->nextFrameNumber = mCore->mFrameCounter + 1;
            output->bufferReplaced = false;
            output->maxBufferCount = mCore->mMaxBufferCount;
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
            output->isSlotExpansionAllowed = mCore->mAllowExtendedSlotCount;
#endif

            if (listener != nullptr) {
                // Set up a death notification so that we can disconnect
+84 −6
Original line number Diff line number Diff line
@@ -37,6 +37,8 @@

#include <private/gui/ComposerService.h>

#include <ui/BufferQueueDefs.h>

#include <log/log.h>
#include <utils/Log.h>
#include <utils/String8.h>
@@ -59,7 +61,11 @@ static int32_t createProcessUniqueId() {
    return android_atomic_inc(&globalCounter);
}

ConsumerBase::ConsumerBase(const sp<IGraphicBufferConsumer>& bufferQueue, bool controlledByApp) :
ConsumerBase::ConsumerBase(const sp<IGraphicBufferConsumer>& bufferQueue, bool controlledByApp)
      :
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
        mSlots(BufferQueueDefs::NUM_BUFFER_SLOTS),
#endif
        mAbandoned(false),
        mConsumer(bufferQueue),
        mPrevFinalReleaseFence(Fence::NO_FENCE) {
@@ -68,7 +74,12 @@ ConsumerBase::ConsumerBase(const sp<IGraphicBufferConsumer>& bufferQueue, bool c

#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
ConsumerBase::ConsumerBase(bool controlledByApp, bool consumerIsSurfaceFlinger)
      : mAbandoned(false), mPrevFinalReleaseFence(Fence::NO_FENCE) {
      :
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
        mSlots(BufferQueueDefs::NUM_BUFFER_SLOTS),
#endif
        mAbandoned(false),
        mPrevFinalReleaseFence(Fence::NO_FENCE) {
    sp<IGraphicBufferProducer> producer;
    BufferQueue::createBufferQueue(&producer, &mConsumer, consumerIsSurfaceFlinger);
    mSurface = sp<Surface>::make(producer, controlledByApp);
@@ -77,7 +88,11 @@ ConsumerBase::ConsumerBase(bool controlledByApp, bool consumerIsSurfaceFlinger)

ConsumerBase::ConsumerBase(const sp<IGraphicBufferProducer>& producer,
                           const sp<IGraphicBufferConsumer>& consumer, bool controlledByApp)
      : mAbandoned(false),
      :
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
        mSlots(BufferQueueDefs::NUM_BUFFER_SLOTS),
#endif
        mAbandoned(false),
        mConsumer(consumer),
        mSurface(sp<Surface>::make(producer, controlledByApp)),
        mPrevFinalReleaseFence(Fence::NO_FENCE) {
@@ -101,9 +116,16 @@ void ConsumerBase::initialize(bool controlledByApp) {
    if (err != NO_ERROR) {
        CB_LOGE("ConsumerBase: error connecting to BufferQueue: %s (%d)",
                strerror(-err), err);
    } else {
        return;
    }

    mConsumer->setConsumerName(mName);
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
    if (err = mConsumer->allowUnlimitedSlots(true); err != NO_ERROR) {
        CB_LOGE("ConsumerBase: error marking as allowed to have unlimited slots: %s (%d)",
                strerror(-err), err);
    }
#endif
}

ConsumerBase::~ConsumerBase() {
@@ -130,7 +152,11 @@ int ConsumerBase::getSlotForBufferLocked(const sp<GraphicBuffer>& buffer) {
    }

    uint64_t id = buffer->getId();
    for (int i = 0; i < BufferQueueDefs::NUM_BUFFER_SLOTS; i++) {
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
    for (int i = 0; i < (int)mSlots.size(); ++i) {
#else
    for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
#endif
        auto& slot = mSlots[i];
        if (slot.mGraphicBuffer && slot.mGraphicBuffer->getId() == id) {
            return i;
@@ -242,6 +268,15 @@ void ConsumerBase::onBuffersReleased() {
        return;
    }

#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
    std::vector<bool> mask;
    mConsumer->getReleasedBuffersExtended(&mask);
    for (size_t i = 0; i < mSlots.size(); i++) {
        if (mask[i]) {
            freeBufferLocked(i);
        }
    }
#else
    uint64_t mask = 0;
    mConsumer->getReleasedBuffers(&mask);
    for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
@@ -249,11 +284,23 @@ void ConsumerBase::onBuffersReleased() {
            freeBufferLocked(i);
        }
    }
#endif
}

void ConsumerBase::onSidebandStreamChanged() {
}

#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
void ConsumerBase::onSlotCountChanged(int slotCount) {
    CB_LOGV("onSlotCountChanged: %d", slotCount);
    Mutex::Autolock lock(mMutex);

    if (slotCount > (int)mSlots.size()) {
        mSlots.resize(slotCount);
    }
}
#endif

void ConsumerBase::abandon() {
    CB_LOGV("abandon");
    Mutex::Autolock lock(mMutex);
@@ -270,7 +317,11 @@ void ConsumerBase::abandonLocked() {
        CB_LOGE("abandonLocked: ConsumerBase is abandoned!");
        return;
    }
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
    for (int i = 0; i < (int)mSlots.size(); ++i) {
#else
    for (int i =0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
#endif
        freeBufferLocked(i);
    }
    // disconnect from the BufferQueue
@@ -387,6 +438,15 @@ status_t ConsumerBase::setMaxBufferCount(int bufferCount) {
        CB_LOGE("setMaxBufferCount: ConsumerBase is abandoned!");
        return NO_INIT;
    }

#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
    if (status_t err = mConsumer->allowUnlimitedSlots(false); err != NO_ERROR) {
        CB_LOGE("ConsumerBase: error marking as not allowed to have unlimited slots: %s (%d)",
                strerror(-err), err);
        return err;
    }
#endif

    return mConsumer->setMaxBufferCount(bufferCount);
}
#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
@@ -448,6 +508,15 @@ status_t ConsumerBase::discardFreeBuffers() {
    if (err != OK) {
        return err;
    }
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
    std::vector<bool> mask;
    mConsumer->getReleasedBuffersExtended(&mask);
    for (int i = 0; i < (int)mSlots.size(); i++) {
        if (mask[i]) {
            freeBufferLocked(i);
        }
    }
#else
    uint64_t mask;
    mConsumer->getReleasedBuffers(&mask);
    for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
@@ -455,6 +524,8 @@ status_t ConsumerBase::discardFreeBuffers() {
            freeBufferLocked(i);
        }
    }
#endif

    return OK;
}

@@ -596,6 +667,9 @@ status_t ConsumerBase::releaseBufferLocked(
    // buffer on the same slot), the buffer producer is definitely no longer
    // tracking it.
    if (!stillTracking(slot, graphicBuffer)) {
        CB_LOGV("releaseBufferLocked: Not tracking, exiting without calling releaseBuffer for "
                "slot=%d/%" PRIu64,
                slot, mSlots[slot].mFrameNumber);
        return OK;
    }

@@ -615,7 +689,11 @@ status_t ConsumerBase::releaseBufferLocked(

bool ConsumerBase::stillTracking(int slot,
        const sp<GraphicBuffer> graphicBuffer) {
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
    if (slot < 0 || slot >= (int)mSlots.size()) {
#else
    if (slot < 0 || slot >= BufferQueue::NUM_BUFFER_SLOTS) {
#endif
        return false;
    }
    return (mSlots[slot].mGraphicBuffer != nullptr &&
Loading