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

Commit 4cbf3c53 authored by Dan Stoza's avatar Dan Stoza Committed by Android (Google) Code Review
Browse files

Merge "BufferQueue: Guard against unbounded queue growth"

parents 1034cfc7 ae3c3682
Loading
Loading
Loading
Loading
+4 −2
Original line number Original line Diff line number Diff line
@@ -160,8 +160,10 @@ status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer,
    }
    }


    mCore->mQueue.erase(front);
    mCore->mQueue.erase(front);
    // TODO: Should this call be after we free a slot while dropping buffers?

    // Simply acquiring the next buffer doesn't enable a producer to dequeue.
    // We might have freed a slot while dropping old buffers, or the producer
    // may be blocked waiting for the number of buffers in the queue to
    // decrease.
    mCore->mDequeueCondition.broadcast();
    mCore->mDequeueCondition.broadcast();


    ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size());
    ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size());
+31 −35
Original line number Original line Diff line number Diff line
@@ -205,9 +205,21 @@ status_t BufferQueueProducer::waitForFreeSlotThenRelock(const char* caller,
            }
            }
        }
        }


        // If no buffer is found, wait for a buffer to be released or for
        // If we disconnect and reconnect quickly, we can be in a state where
        // the max buffer count to change
        // our slots are empty but we have many buffers in the queue. This can
        tryAgain = (*found == BufferQueueCore::INVALID_BUFFER_SLOT);
        // cause us to run out of memory if we outrun the consumer. Wait here if
        // it looks like we have too many buffers queued up.
        bool tooManyBuffers = mCore->mQueue.size() > maxBufferCount;
        if (tooManyBuffers) {
            BQ_LOGV("%s: queue size is %d, waiting", caller,
                    mCore->mQueue.size());
        }

        // If no buffer is found, or if the queue has too many buffers
        // outstanding, wait for a buffer to be acquired or released, or for the
        // max buffer count to change.
        tryAgain = (*found == BufferQueueCore::INVALID_BUFFER_SLOT) ||
                   tooManyBuffers;
        if (tryAgain) {
        if (tryAgain) {
            // Return an error if we're in non-blocking mode (producer and
            // Return an error if we're in non-blocking mode (producer and
            // consumer are controlled by the application).
            // consumer are controlled by the application).
@@ -707,11 +719,6 @@ status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener,
    BQ_LOGV("connect(P): api=%d producerControlledByApp=%s", api,
    BQ_LOGV("connect(P): api=%d producerControlledByApp=%s", api,
            producerControlledByApp ? "true" : "false");
            producerControlledByApp ? "true" : "false");


    // If we disconnect and reconnect quickly, we can be in a state where our
    // slots are empty but we have many buffers in the queue. This can cause us
    // to run out of memory if we outrun the consumer. Wait here if it looks
    // like we have too many buffers queued up.
    while (true) {
    if (mCore->mIsAbandoned) {
    if (mCore->mIsAbandoned) {
        BQ_LOGE("connect(P): BufferQueue has been abandoned");
        BQ_LOGE("connect(P): BufferQueue has been abandoned");
        return NO_INIT;
        return NO_INIT;
@@ -733,17 +740,6 @@ status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener,
        return BAD_VALUE;
        return BAD_VALUE;
    }
    }


        size_t maxBufferCount = mCore->getMaxBufferCountLocked(false);
        if (mCore->mQueue.size() <= maxBufferCount) {
            // The queue size seems small enough to proceed
            // TODO: Make this bound tighter?
            break;
        }

        BQ_LOGV("connect(P): queue size is %d, waiting", mCore->mQueue.size());
        mCore->mDequeueCondition.wait(mCore->mMutex);
    }

    int status = NO_ERROR;
    int status = NO_ERROR;
    switch (api) {
    switch (api) {
        case NATIVE_WINDOW_API_EGL:
        case NATIVE_WINDOW_API_EGL: