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

Commit f87833e0 authored by John Reck's avatar John Reck Committed by Android (Google) Code Review
Browse files

Merge "BQ: Fix deadlock introduced by onFrameDequeued" into main

parents 25a68e03 624375fd
Loading
Loading
Loading
Loading
+76 −50
Original line number Diff line number Diff line
@@ -418,6 +418,9 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* ou
    EGLSyncKHR eglFence = EGL_NO_SYNC_KHR;
    bool attachedByConsumer = false;

    sp<IConsumerListener> listener;
    bool callOnFrameDequeued = false;
    uint64_t bufferId = 0; // Only used if callOnFrameDequeued == true
    { // Autolock scope
        std::unique_lock<std::mutex> lock(mCore->mMutex);

@@ -561,10 +564,11 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* ou
        }

        if (!(returnFlags & BUFFER_NEEDS_REALLOCATION)) {
            if (mCore->mConsumerListener != nullptr) {
                mCore->mConsumerListener->onFrameDequeued(mSlots[*outSlot].mGraphicBuffer->getId());
            }
            callOnFrameDequeued = true;
            bufferId = mSlots[*outSlot].mGraphicBuffer->getId();
        }

        listener = mCore->mConsumerListener;
    } // Autolock scope

    if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
@@ -581,10 +585,8 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* ou
            if (error == NO_ERROR && !mCore->mIsAbandoned) {
                graphicBuffer->setGenerationNumber(mCore->mGenerationNumber);
                mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
                if (mCore->mConsumerListener != nullptr) {
                    mCore->mConsumerListener->onFrameDequeued(
                            mSlots[*outSlot].mGraphicBuffer->getId());
                }
                callOnFrameDequeued = true;
                bufferId = mSlots[*outSlot].mGraphicBuffer->getId();
            }

            mCore->mIsAllocating = false;
@@ -608,6 +610,10 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* ou
        } // Autolock scope
    }

    if (listener != nullptr && callOnFrameDequeued) {
        listener->onFrameDequeued(bufferId);
    }

    if (attachedByConsumer) {
        returnFlags |= BUFFER_NEEDS_REALLOCATION;
    }
@@ -647,6 +653,8 @@ status_t BufferQueueProducer::detachBuffer(int slot) {
    BQ_LOGV("detachBuffer: slot %d", slot);

    sp<IConsumerListener> listener;
    bool callOnFrameDetached = false;
    uint64_t bufferId = 0; // Only used if callOnFrameDetached is true
    {
        std::lock_guard<std::mutex> lock(mCore->mMutex);

@@ -684,8 +692,9 @@ status_t BufferQueueProducer::detachBuffer(int slot) {

        listener = mCore->mConsumerListener;
        auto gb = mSlots[slot].mGraphicBuffer;
        if (listener != nullptr && gb != nullptr) {
            listener->onFrameDetached(gb->getId());
        if (gb != nullptr) {
            callOnFrameDetached = true;
            bufferId = gb->getId();
        }
        mSlots[slot].mBufferState.detachProducer();
        mCore->mActiveBuffers.erase(slot);
@@ -695,6 +704,10 @@ status_t BufferQueueProducer::detachBuffer(int slot) {
        VALIDATE_CONSISTENCY();
    }

    if (listener != nullptr && callOnFrameDetached) {
        listener->onFrameDetached(bufferId);
    }

    if (listener != nullptr) {
        listener->onBuffersReleased();
    }
@@ -1105,6 +1118,11 @@ status_t BufferQueueProducer::queueBuffer(int slot,
status_t BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
    ATRACE_CALL();
    BQ_LOGV("cancelBuffer: slot %d", slot);

    sp<IConsumerListener> listener;
    bool callOnFrameCancelled = false;
    uint64_t bufferId = 0; // Only used if callOnFrameCancelled == true
    {
        std::lock_guard<std::mutex> lock(mCore->mMutex);

        if (mCore->mIsAbandoned) {
@@ -1123,12 +1141,13 @@ status_t BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
        }

        if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
        BQ_LOGE("cancelBuffer: slot index %d out of range [0, %d)",
                slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
            BQ_LOGE("cancelBuffer: slot index %d out of range [0, %d)", slot,
                    BufferQueueDefs::NUM_BUFFER_SLOTS);
            return BAD_VALUE;
        } else if (!mSlots[slot].mBufferState.isDequeued()) {
            BQ_LOGE("cancelBuffer: slot %d is not owned by the producer "
                "(state = %s)", slot, mSlots[slot].mBufferState.string());
                    "(state = %s)",
                    slot, mSlots[slot].mBufferState.string());
            return BAD_VALUE;
        } else if (fence == nullptr) {
            BQ_LOGE("cancelBuffer: fence is NULL");
@@ -1150,12 +1169,19 @@ status_t BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
        }

        auto gb = mSlots[slot].mGraphicBuffer;
    if (mCore->mConsumerListener != nullptr && gb != nullptr) {
        mCore->mConsumerListener->onFrameCancelled(gb->getId());
        if (gb != nullptr) {
            callOnFrameCancelled = true;
            bufferId = gb->getId();
        }
        mSlots[slot].mFence = fence;
        mCore->mDequeueCondition.notify_all();
        listener = mCore->mConsumerListener;
        VALIDATE_CONSISTENCY();
    }

    if (listener != nullptr && callOnFrameCancelled) {
        listener->onFrameCancelled(bufferId);
    }

    return NO_ERROR;
}