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

Commit 789a0c82 authored by Pablo Ceballos's avatar Pablo Ceballos
Browse files

Fix Surface slot caching

- Now that it's possible to resize a BufferQueue while buffers are
  dequeued/acquired, it's no longer correct for Surface to clear its
  cache when the BufferQueue is resized since it must keep at least
  the currently dequeued buffers.
- Add an onSlotsFreed callback to IProducerListener so that producers
  that wish to be notified about buffers being freed can do so. Note
  that this isn't currently used in Surface.
- Review and fixup all the places where the producer/consumer
  listeners for freed buffers should be called.

Change-Id: I4ab0c92bc69b75a3c072ddf5d74d78f941dba4c8
parent c5cec281
Loading
Loading
Loading
Loading
+4 −2
Original line number Original line Diff line number Diff line
@@ -32,6 +32,7 @@


#include <list>
#include <list>
#include <set>
#include <set>
#include <vector>


#define BQ_LOGV(x, ...) ALOGV("[%s] " x, mConsumerName.string(), ##__VA_ARGS__)
#define BQ_LOGV(x, ...) ALOGV("[%s] " x, mConsumerName.string(), ##__VA_ARGS__)
#define BQ_LOGD(x, ...) ALOGD("[%s] " x, mConsumerName.string(), ##__VA_ARGS__)
#define BQ_LOGD(x, ...) ALOGD("[%s] " x, mConsumerName.string(), ##__VA_ARGS__)
@@ -120,8 +121,9 @@ private:
    void freeAllBuffersLocked();
    void freeAllBuffersLocked();


    // If delta is positive, makes more slots available. If negative, takes
    // If delta is positive, makes more slots available. If negative, takes
    // away slots. Returns false if the request can't be met.
    // away slots. Returns false if the request can't be met. Any slots that
    bool adjustAvailableSlotsLocked(int delta);
    // were freed will be appended to freedSlots.
    bool adjustAvailableSlotsLocked(int delta, std::vector<int>* freedSlots);


    // waitWhileAllocatingLocked blocks until mIsAllocating is false.
    // waitWhileAllocatingLocked blocks until mIsAllocating is false.
    void waitWhileAllocatingLocked() const;
    void waitWhileAllocatingLocked() const;
+3 −0
Original line number Original line Diff line number Diff line
@@ -41,6 +41,9 @@ public:
    // This is called without any lock held and can be called concurrently by
    // This is called without any lock held and can be called concurrently by
    // multiple threads.
    // multiple threads.
    virtual void onBufferReleased() = 0; // Asynchronous
    virtual void onBufferReleased() = 0; // Asynchronous

    // onSlotFreed is called when the BufferQueue frees a buffer in a slot.
    virtual void onSlotFreed(int /*slot*/) {}; // Asynchronous
};
};


class IProducerListener : public ProducerListener, public IInterface
class IProducerListener : public ProducerListener, public IInterface
+82 −47
Original line number Original line Diff line number Diff line
@@ -274,6 +274,10 @@ status_t BufferQueueConsumer::detachBuffer(int slot) {
    ATRACE_CALL();
    ATRACE_CALL();
    ATRACE_BUFFER_INDEX(slot);
    ATRACE_BUFFER_INDEX(slot);
    BQ_LOGV("detachBuffer: slot %d", slot);
    BQ_LOGV("detachBuffer: slot %d", slot);

    sp<IConsumerListener> consumerListener;
    sp<IProducerListener> producerListener;
    {
        Mutex::Autolock lock(mCore->mMutex);
        Mutex::Autolock lock(mCore->mMutex);


        if (mCore->mIsAbandoned) {
        if (mCore->mIsAbandoned) {
@@ -303,6 +307,18 @@ status_t BufferQueueConsumer::detachBuffer(int slot) {
        mCore->clearBufferSlotLocked(slot);
        mCore->clearBufferSlotLocked(slot);
        mCore->mDequeueCondition.broadcast();
        mCore->mDequeueCondition.broadcast();
        VALIDATE_CONSISTENCY();
        VALIDATE_CONSISTENCY();
        producerListener = mCore->mConnectedProducerListener;
        consumerListener = mCore->mConsumerListener;
    }

    // Call back without lock held
    if (producerListener != NULL) {
        producerListener->onSlotFreed(slot);
    }
    if (consumerListener != NULL) {
        consumerListener->onBuffersReleased();
    }



    return NO_ERROR;
    return NO_ERROR;
}
}
@@ -573,8 +589,9 @@ status_t BufferQueueConsumer::setMaxBufferCount(int bufferCount) {
        return BAD_VALUE;
        return BAD_VALUE;
    }
    }


    sp<IConsumerListener> listener;
    {
        Mutex::Autolock lock(mCore->mMutex);
        Mutex::Autolock lock(mCore->mMutex);

        if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
        if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
            BQ_LOGE("setMaxBufferCount: producer is already connected");
            BQ_LOGE("setMaxBufferCount: producer is already connected");
            return INVALID_OPERATION;
            return INVALID_OPERATION;
@@ -590,13 +607,22 @@ status_t BufferQueueConsumer::setMaxBufferCount(int bufferCount) {
        int delta = mCore->getMaxBufferCountLocked(mCore->mAsyncMode,
        int delta = mCore->getMaxBufferCountLocked(mCore->mAsyncMode,
                mCore->mDequeueBufferCannotBlock, bufferCount) -
                mCore->mDequeueBufferCannotBlock, bufferCount) -
                mCore->getMaxBufferCountLocked();
                mCore->getMaxBufferCountLocked();
    if (!mCore->adjustAvailableSlotsLocked(delta)) {
        if (!mCore->adjustAvailableSlotsLocked(delta, nullptr)) {
        BQ_LOGE("setMaxBufferCount: BufferQueue failed to adjust the number of "
            BQ_LOGE("setMaxBufferCount: BufferQueue failed to adjust the number"
                "available slots. Delta = %d", delta);
                    " of available slots. Delta = %d", delta);
            return BAD_VALUE;
            return BAD_VALUE;
        }
        }


        mCore->mMaxBufferCount = bufferCount;
        mCore->mMaxBufferCount = bufferCount;
        if (delta < 0) {
            listener = mCore->mConsumerListener;
        }
    }

    // Call back without lock held
    if (listener != NULL) {
        listener->onBuffersReleased();
    }
    return NO_ERROR;
    return NO_ERROR;
}
}


@@ -611,7 +637,9 @@ status_t BufferQueueConsumer::setMaxAcquiredBufferCount(
        return BAD_VALUE;
        return BAD_VALUE;
    }
    }


    sp<IConsumerListener> listener;
    sp<IConsumerListener> consumerListener;
    sp<IProducerListener> producerListener;
    std::vector<int> freedSlots;
    { // Autolock scope
    { // Autolock scope
        Mutex::Autolock lock(mCore->mMutex);
        Mutex::Autolock lock(mCore->mMutex);
        mCore->waitWhileAllocatingLocked();
        mCore->waitWhileAllocatingLocked();
@@ -648,7 +676,7 @@ status_t BufferQueueConsumer::setMaxAcquiredBufferCount(
        }
        }


        int delta = maxAcquiredBuffers - mCore->mMaxAcquiredBufferCount;
        int delta = maxAcquiredBuffers - mCore->mMaxAcquiredBufferCount;
        if (!mCore->adjustAvailableSlotsLocked(delta)) {
        if (!mCore->adjustAvailableSlotsLocked(delta, &freedSlots)) {
            return BAD_VALUE;
            return BAD_VALUE;
        }
        }


@@ -656,12 +684,19 @@ status_t BufferQueueConsumer::setMaxAcquiredBufferCount(
        mCore->mMaxAcquiredBufferCount = maxAcquiredBuffers;
        mCore->mMaxAcquiredBufferCount = maxAcquiredBuffers;
        VALIDATE_CONSISTENCY();
        VALIDATE_CONSISTENCY();
        if (delta < 0) {
        if (delta < 0) {
            listener = mCore->mConsumerListener;
            consumerListener = mCore->mConsumerListener;
            producerListener = mCore->mConnectedProducerListener;
        }
        }
    }
    }

    // Call back without lock held
    // Call back without lock held
    if (listener != NULL) {
    if (consumerListener != NULL) {
        listener->onBuffersReleased();
        consumerListener->onBuffersReleased();
    }
    if (producerListener != NULL) {
        for (int i : freedSlots) {
            producerListener->onSlotFreed(i);
        }
    }
    }


    return NO_ERROR;
    return NO_ERROR;
+8 −1
Original line number Original line Diff line number Diff line
@@ -225,7 +225,8 @@ void BufferQueueCore::freeAllBuffersLocked() {
    VALIDATE_CONSISTENCY();
    VALIDATE_CONSISTENCY();
}
}


bool BufferQueueCore::adjustAvailableSlotsLocked(int delta) {
bool BufferQueueCore::adjustAvailableSlotsLocked(int delta,
        std::vector<int>* freedSlots) {
    if (delta >= 0) {
    if (delta >= 0) {
        // If we're going to fail, do so before modifying anything
        // If we're going to fail, do so before modifying anything
        if (delta > static_cast<int>(mUnusedSlots.size())) {
        if (delta > static_cast<int>(mUnusedSlots.size())) {
@@ -252,11 +253,17 @@ bool BufferQueueCore::adjustAvailableSlotsLocked(int delta) {
                clearBufferSlotLocked(*slot);
                clearBufferSlotLocked(*slot);
                mUnusedSlots.push_back(*slot);
                mUnusedSlots.push_back(*slot);
                mFreeSlots.erase(slot);
                mFreeSlots.erase(slot);
                if (freedSlots) {
                    freedSlots->push_back(*slot);
                }
            } else if (!mFreeBuffers.empty()) {
            } else if (!mFreeBuffers.empty()) {
                int slot = mFreeBuffers.back();
                int slot = mFreeBuffers.back();
                clearBufferSlotLocked(slot);
                clearBufferSlotLocked(slot);
                mUnusedSlots.push_back(slot);
                mUnusedSlots.push_back(slot);
                mFreeBuffers.pop_back();
                mFreeBuffers.pop_back();
                if (freedSlots) {
                    freedSlots->push_back(slot);
                }
            } else {
            } else {
                return false;
                return false;
            }
            }
+248 −143
Original line number Original line Diff line number Diff line
@@ -90,7 +90,9 @@ status_t BufferQueueProducer::setMaxDequeuedBufferCount(
    BQ_LOGV("setMaxDequeuedBufferCount: maxDequeuedBuffers = %d",
    BQ_LOGV("setMaxDequeuedBufferCount: maxDequeuedBuffers = %d",
            maxDequeuedBuffers);
            maxDequeuedBuffers);


    sp<IConsumerListener> listener;
    sp<IConsumerListener> consumerListener;
    sp<IProducerListener> producerListener;
    std::vector<int> freedSlots;
    { // Autolock scope
    { // Autolock scope
        Mutex::Autolock lock(mCore->mMutex);
        Mutex::Autolock lock(mCore->mMutex);
        mCore->waitWhileAllocatingLocked();
        mCore->waitWhileAllocatingLocked();
@@ -142,20 +144,26 @@ status_t BufferQueueProducer::setMaxDequeuedBufferCount(
        }
        }


        int delta = maxDequeuedBuffers - mCore->mMaxDequeuedBufferCount;
        int delta = maxDequeuedBuffers - mCore->mMaxDequeuedBufferCount;
        if (!mCore->adjustAvailableSlotsLocked(delta)) {
        if (!mCore->adjustAvailableSlotsLocked(delta, &freedSlots)) {
            return BAD_VALUE;
            return BAD_VALUE;
        }
        }
        mCore->mMaxDequeuedBufferCount = maxDequeuedBuffers;
        mCore->mMaxDequeuedBufferCount = maxDequeuedBuffers;
        VALIDATE_CONSISTENCY();
        VALIDATE_CONSISTENCY();
        if (delta < 0) {
        if (delta < 0) {
            listener = mCore->mConsumerListener;
            consumerListener = mCore->mConsumerListener;
            producerListener = mCore->mConnectedProducerListener;
        }
        }
        mCore->mDequeueCondition.broadcast();
        mCore->mDequeueCondition.broadcast();
    } // Autolock scope
    } // Autolock scope


    // Call back without lock held
    // Call back without lock held
    if (listener != NULL) {
    if (consumerListener != NULL) {
        listener->onBuffersReleased();
        consumerListener->onBuffersReleased();
    }
    if (producerListener != NULL) {
        for (int i : freedSlots) {
            producerListener->onSlotFreed(i);
        }
    }
    }


    return NO_ERROR;
    return NO_ERROR;
@@ -165,7 +173,9 @@ status_t BufferQueueProducer::setAsyncMode(bool async) {
    ATRACE_CALL();
    ATRACE_CALL();
    BQ_LOGV("setAsyncMode: async = %d", async);
    BQ_LOGV("setAsyncMode: async = %d", async);


    sp<IConsumerListener> listener;
    sp<IConsumerListener> consumerListener;
    sp<IProducerListener> producerListener;
    std::vector<int> freedSlots;
    { // Autolock scope
    { // Autolock scope
        Mutex::Autolock lock(mCore->mMutex);
        Mutex::Autolock lock(mCore->mMutex);
        mCore->waitWhileAllocatingLocked();
        mCore->waitWhileAllocatingLocked();
@@ -191,7 +201,7 @@ status_t BufferQueueProducer::setAsyncMode(bool async) {
                mCore->mDequeueBufferCannotBlock, mCore->mMaxBufferCount)
                mCore->mDequeueBufferCannotBlock, mCore->mMaxBufferCount)
                - mCore->getMaxBufferCountLocked();
                - mCore->getMaxBufferCountLocked();


        if (!mCore->adjustAvailableSlotsLocked(delta)) {
        if (!mCore->adjustAvailableSlotsLocked(delta, &freedSlots)) {
            BQ_LOGE("setAsyncMode: BufferQueue failed to adjust the number of "
            BQ_LOGE("setAsyncMode: BufferQueue failed to adjust the number of "
                    "available slots. Delta = %d", delta);
                    "available slots. Delta = %d", delta);
            return BAD_VALUE;
            return BAD_VALUE;
@@ -199,12 +209,20 @@ status_t BufferQueueProducer::setAsyncMode(bool async) {
        mCore->mAsyncMode = async;
        mCore->mAsyncMode = async;
        VALIDATE_CONSISTENCY();
        VALIDATE_CONSISTENCY();
        mCore->mDequeueCondition.broadcast();
        mCore->mDequeueCondition.broadcast();
        listener = mCore->mConsumerListener;
        if (delta < 0) {
            consumerListener = mCore->mConsumerListener;
            producerListener = mCore->mConnectedProducerListener;
        }
    } // Autolock scope
    } // Autolock scope


    // Call back without lock held
    // Call back without lock held
    if (listener != NULL) {
    if (consumerListener != NULL) {
        listener->onBuffersReleased();
        consumerListener->onBuffersReleased();
    }
    if (producerListener != NULL) {
        for (int i : freedSlots) {
            producerListener->onSlotFreed(i);
        }
    }
    }
    return NO_ERROR;
    return NO_ERROR;
}
}
@@ -361,6 +379,9 @@ status_t BufferQueueProducer::dequeueBuffer(int *outSlot,
    EGLSyncKHR eglFence = EGL_NO_SYNC_KHR;
    EGLSyncKHR eglFence = EGL_NO_SYNC_KHR;
    bool attachedByConsumer = false;
    bool attachedByConsumer = false;


    sp<IConsumerListener> consumerListener;
    sp<IProducerListener> producerListener;
    int found = BufferItem::INVALID_BUFFER_SLOT;
    { // Autolock scope
    { // Autolock scope
        Mutex::Autolock lock(mCore->mMutex);
        Mutex::Autolock lock(mCore->mMutex);
        mCore->waitWhileAllocatingLocked();
        mCore->waitWhileAllocatingLocked();
@@ -378,7 +399,6 @@ status_t BufferQueueProducer::dequeueBuffer(int *outSlot,
            height = mCore->mDefaultHeight;
            height = mCore->mDefaultHeight;
        }
        }


        int found = BufferItem::INVALID_BUFFER_SLOT;
        while (found == BufferItem::INVALID_BUFFER_SLOT) {
        while (found == BufferItem::INVALID_BUFFER_SLOT) {
            status_t status = waitForFreeSlotThenRelock(FreeSlotCaller::Dequeue,
            status_t status = waitForFreeSlotThenRelock(FreeSlotCaller::Dequeue,
                    &found);
                    &found);
@@ -408,6 +428,8 @@ status_t BufferQueueProducer::dequeueBuffer(int *outSlot,
                    mCore->mFreeSlots.insert(found);
                    mCore->mFreeSlots.insert(found);
                    mCore->clearBufferSlotLocked(found);
                    mCore->clearBufferSlotLocked(found);
                    found = BufferItem::INVALID_BUFFER_SLOT;
                    found = BufferItem::INVALID_BUFFER_SLOT;
                    consumerListener = mCore->mConsumerListener;
                    producerListener = mCore->mConnectedProducerListener;
                    continue;
                    continue;
                }
                }
            }
            }
@@ -444,6 +466,10 @@ status_t BufferQueueProducer::dequeueBuffer(int *outSlot,
        if ((buffer == NULL) ||
        if ((buffer == NULL) ||
                buffer->needsReallocation(width, height, format, usage))
                buffer->needsReallocation(width, height, format, usage))
        {
        {
            if (buffer != NULL) {
                consumerListener = mCore->mConsumerListener;
                producerListener = mCore->mConnectedProducerListener;
            }
            mSlots[found].mAcquireCalled = false;
            mSlots[found].mAcquireCalled = false;
            mSlots[found].mGraphicBuffer = NULL;
            mSlots[found].mGraphicBuffer = NULL;
            mSlots[found].mRequestBufferCalled = false;
            mSlots[found].mRequestBufferCalled = false;
@@ -531,6 +557,14 @@ status_t BufferQueueProducer::dequeueBuffer(int *outSlot,
            mSlots[*outSlot].mFrameNumber,
            mSlots[*outSlot].mFrameNumber,
            mSlots[*outSlot].mGraphicBuffer->handle, returnFlags);
            mSlots[*outSlot].mGraphicBuffer->handle, returnFlags);


    // Call back without lock held
    if (consumerListener != NULL) {
        consumerListener->onBuffersReleased();
    }
    if (producerListener != NULL) {
        producerListener->onSlotFreed(found);
    }

    return returnFlags;
    return returnFlags;
}
}


@@ -538,6 +572,10 @@ status_t BufferQueueProducer::detachBuffer(int slot) {
    ATRACE_CALL();
    ATRACE_CALL();
    ATRACE_BUFFER_INDEX(slot);
    ATRACE_BUFFER_INDEX(slot);
    BQ_LOGV("detachBuffer: slot %d", slot);
    BQ_LOGV("detachBuffer: slot %d", slot);

    sp<IConsumerListener> consumerListener;
    sp<IProducerListener> producerListener;
    {
        Mutex::Autolock lock(mCore->mMutex);
        Mutex::Autolock lock(mCore->mMutex);


        if (mCore->mIsAbandoned) {
        if (mCore->mIsAbandoned) {
@@ -551,7 +589,8 @@ status_t BufferQueueProducer::detachBuffer(int slot) {
        }
        }


        if (mCore->mSingleBufferMode || mCore->mSingleBufferSlot == slot) {
        if (mCore->mSingleBufferMode || mCore->mSingleBufferSlot == slot) {
        BQ_LOGE("detachBuffer: cannot detach a buffer in single buffer mode");
            BQ_LOGE("detachBuffer: cannot detach a buffer in single buffer "
                    "mode");
            return BAD_VALUE;
            return BAD_VALUE;
        }
        }


@@ -575,6 +614,17 @@ status_t BufferQueueProducer::detachBuffer(int slot) {
        mCore->clearBufferSlotLocked(slot);
        mCore->clearBufferSlotLocked(slot);
        mCore->mDequeueCondition.broadcast();
        mCore->mDequeueCondition.broadcast();
        VALIDATE_CONSISTENCY();
        VALIDATE_CONSISTENCY();
        producerListener = mCore->mConnectedProducerListener;
        consumerListener = mCore->mConsumerListener;
    }

    // Call back without lock held
    if (consumerListener != NULL) {
        consumerListener->onBuffersReleased();
    }
    if (producerListener != NULL) {
        producerListener->onSlotFreed(slot);
    }


    return NO_ERROR;
    return NO_ERROR;
}
}
@@ -591,8 +641,11 @@ status_t BufferQueueProducer::detachNextBuffer(sp<GraphicBuffer>* outBuffer,
        return BAD_VALUE;
        return BAD_VALUE;
    }
    }


    sp<IConsumerListener> consumerListener;
    sp<IProducerListener> producerListener;
    int found = BufferQueueCore::INVALID_BUFFER_SLOT;
    {
        Mutex::Autolock lock(mCore->mMutex);
        Mutex::Autolock lock(mCore->mMutex);

        if (mCore->mIsAbandoned) {
        if (mCore->mIsAbandoned) {
            BQ_LOGE("detachNextBuffer: BufferQueue has been abandoned");
            BQ_LOGE("detachNextBuffer: BufferQueue has been abandoned");
            return NO_INIT;
            return NO_INIT;
@@ -615,7 +668,7 @@ status_t BufferQueueProducer::detachNextBuffer(sp<GraphicBuffer>* outBuffer,
            return NO_MEMORY;
            return NO_MEMORY;
        }
        }


    int found = mCore->mFreeBuffers.front();
        found = mCore->mFreeBuffers.front();
        mCore->mFreeBuffers.remove(found);
        mCore->mFreeBuffers.remove(found);
        mCore->mFreeSlots.insert(found);
        mCore->mFreeSlots.insert(found);


@@ -625,6 +678,17 @@ status_t BufferQueueProducer::detachNextBuffer(sp<GraphicBuffer>* outBuffer,
        *outFence = mSlots[found].mFence;
        *outFence = mSlots[found].mFence;
        mCore->clearBufferSlotLocked(found);
        mCore->clearBufferSlotLocked(found);
        VALIDATE_CONSISTENCY();
        VALIDATE_CONSISTENCY();
        consumerListener = mCore->mConsumerListener;
        producerListener = mCore->mConnectedProducerListener;
    }

    // Call back without lock held
    if (consumerListener != NULL) {
        consumerListener->onBuffersReleased();
    }
    if (producerListener != NULL) {
        producerListener->onSlotFreed(found);
    }


    return NO_ERROR;
    return NO_ERROR;
}
}
@@ -1020,6 +1084,11 @@ int BufferQueueProducer::query(int what, int *outValue) {
status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener,
status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener,
        int api, bool producerControlledByApp, QueueBufferOutput *output) {
        int api, bool producerControlledByApp, QueueBufferOutput *output) {
    ATRACE_CALL();
    ATRACE_CALL();
    int status = NO_ERROR;
    sp<IConsumerListener> consumerListener;
    sp<IProducerListener> producerListener;
    std::vector<int> freedSlots;
    {
        Mutex::Autolock lock(mCore->mMutex);
        Mutex::Autolock lock(mCore->mMutex);
        mConsumerName = mCore->mConsumerName;
        mConsumerName = mCore->mConsumerName;
        BQ_LOGV("connect: api=%d producerControlledByApp=%s", api,
        BQ_LOGV("connect: api=%d producerControlledByApp=%s", api,
@@ -1046,18 +1115,19 @@ status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener,
            return BAD_VALUE;
            return BAD_VALUE;
        }
        }


        bool dequeueBufferCannotBlock = mDequeueTimeout < 0 ?
                mCore->mConsumerControlledByApp && producerControlledByApp :
                false;
        int delta = mCore->getMaxBufferCountLocked(mCore->mAsyncMode,
        int delta = mCore->getMaxBufferCountLocked(mCore->mAsyncMode,
            mDequeueTimeout < 0 ?
                dequeueBufferCannotBlock, mCore->mMaxBufferCount) -
            mCore->mConsumerControlledByApp && producerControlledByApp : false,
            mCore->mMaxBufferCount) -
                mCore->getMaxBufferCountLocked();
                mCore->getMaxBufferCountLocked();
    if (!mCore->adjustAvailableSlotsLocked(delta)) {

        BQ_LOGE("connect: BufferQueue failed to adjust the number of available "
        if (!mCore->adjustAvailableSlotsLocked(delta, &freedSlots)) {
                "slots. Delta = %d", delta);
            BQ_LOGE("connect: BufferQueue failed to adjust the number of "
                    "available slots. Delta = %d", delta);
            return BAD_VALUE;
            return BAD_VALUE;
        }
        }


    int status = NO_ERROR;
        switch (api) {
        switch (api) {
            case NATIVE_WINDOW_API_EGL:
            case NATIVE_WINDOW_API_EGL:
            case NATIVE_WINDOW_API_CPU:
            case NATIVE_WINDOW_API_CPU:
@@ -1071,7 +1141,8 @@ status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener,
                // Set up a death notification so that we can disconnect
                // Set up a death notification so that we can disconnect
                // automatically if the remote producer dies
                // automatically if the remote producer dies
                if (listener != NULL &&
                if (listener != NULL &&
                    IInterface::asBinder(listener)->remoteBinder() != NULL) {
                        IInterface::asBinder(listener)->remoteBinder() !=
                        NULL) {
                    status = IInterface::asBinder(listener)->linkToDeath(
                    status = IInterface::asBinder(listener)->linkToDeath(
                            static_cast<IBinder::DeathRecipient*>(this));
                            static_cast<IBinder::DeathRecipient*>(this));
                    if (status != NO_ERROR) {
                    if (status != NO_ERROR) {
@@ -1088,14 +1159,27 @@ status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener,
        }
        }


        mCore->mBufferHasBeenQueued = false;
        mCore->mBufferHasBeenQueued = false;
    mCore->mDequeueBufferCannotBlock = false;
        mCore->mDequeueBufferCannotBlock = dequeueBufferCannotBlock;
    if (mDequeueTimeout < 0) {
        mCore->mDequeueBufferCannotBlock =
                mCore->mConsumerControlledByApp && producerControlledByApp;
    }


        mCore->mAllowAllocation = true;
        mCore->mAllowAllocation = true;
        VALIDATE_CONSISTENCY();
        VALIDATE_CONSISTENCY();

        if (delta < 0) {
            consumerListener = mCore->mConsumerListener;
            producerListener = listener;
        }
    }

    // Call back without lock held
    if (consumerListener != NULL) {
        consumerListener->onBuffersReleased();
    }
    if (producerListener != NULL) {
        for (int i : freedSlots) {
            producerListener->onSlotFreed(i);
        }
    }

    return status;
    return status;
}
}


@@ -1313,12 +1397,16 @@ status_t BufferQueueProducer::setDequeueTimeout(nsecs_t timeout) {
    ATRACE_CALL();
    ATRACE_CALL();
    BQ_LOGV("setDequeueTimeout: %" PRId64, timeout);
    BQ_LOGV("setDequeueTimeout: %" PRId64, timeout);


    sp<IConsumerListener> consumerListener;
    sp<IProducerListener> producerListener;
    std::vector<int> freedSlots;
    {
        Mutex::Autolock lock(mCore->mMutex);
        Mutex::Autolock lock(mCore->mMutex);
        int delta = mCore->getMaxBufferCountLocked(mCore->mAsyncMode, false,
        int delta = mCore->getMaxBufferCountLocked(mCore->mAsyncMode, false,
                mCore->mMaxBufferCount) - mCore->getMaxBufferCountLocked();
                mCore->mMaxBufferCount) - mCore->getMaxBufferCountLocked();
    if (!mCore->adjustAvailableSlotsLocked(delta)) {
        if (!mCore->adjustAvailableSlotsLocked(delta, &freedSlots)) {
        BQ_LOGE("setDequeueTimeout: BufferQueue failed to adjust the number of "
            BQ_LOGE("setDequeueTimeout: BufferQueue failed to adjust the number"
                "available slots. Delta = %d", delta);
                    " of available slots. Delta = %d", delta);
            return BAD_VALUE;
            return BAD_VALUE;
        }
        }


@@ -1326,6 +1414,23 @@ status_t BufferQueueProducer::setDequeueTimeout(nsecs_t timeout) {
        mCore->mDequeueBufferCannotBlock = false;
        mCore->mDequeueBufferCannotBlock = false;


        VALIDATE_CONSISTENCY();
        VALIDATE_CONSISTENCY();

        if (delta < 0) {
            consumerListener = mCore->mConsumerListener;
            producerListener = mCore->mConnectedProducerListener;
        }
    }

    // Call back without lock held
    if (consumerListener != NULL) {
        consumerListener->onBuffersReleased();
    }
    if (producerListener != NULL) {
        for (int i : freedSlots) {
            producerListener->onSlotFreed(i);
        }
    }

    return NO_ERROR;
    return NO_ERROR;
}
}


Loading