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

Commit c652d17c authored by Pablo Ceballos's avatar Pablo Ceballos Committed by Android (Google) Code Review
Browse files

Merge "BQ: Prevent operations on disconnected BQs"

parents b11bd816 583b1b32
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -117,7 +117,7 @@ public:
    //
    // The buffer will not be overwritten until the fence signals.  The fence
    // will usually be the one obtained from dequeueBuffer.
    virtual void cancelBuffer(int slot, const sp<Fence>& fence);
    virtual status_t cancelBuffer(int slot, const sp<Fence>& fence);

    // Query native window attributes.  The "what" values are enumerated in
    // window.h (e.g. NATIVE_WINDOW_FORMAT).
+23 −7
Original line number Diff line number Diff line
@@ -74,7 +74,8 @@ public:
    // The slot must be in the range of [0, NUM_BUFFER_SLOTS).
    //
    // Return of a value other than NO_ERROR means an error has occurred:
    // * NO_INIT - the buffer queue has been abandoned.
    // * NO_INIT - the buffer queue has been abandoned or the producer is not
    //             connected.
    // * BAD_VALUE - one of the two conditions occurred:
    //              * slot was out of range (see above)
    //              * buffer specified by the slot is not dequeued
@@ -170,7 +171,8 @@ public:
    // success.
    //
    // Return of a negative means an error has occurred:
    // * NO_INIT - the buffer queue has been abandoned.
    // * NO_INIT - the buffer queue has been abandoned or the producer is not
    //             connected.
    // * BAD_VALUE - both in async mode and buffer count was less than the
    //               max numbers of buffers that can be allocated at once.
    // * INVALID_OPERATION - cannot attach the buffer because it would cause
@@ -198,7 +200,8 @@ public:
    // requestBuffer).
    //
    // Return of a value other than NO_ERROR means an error has occurred:
    // * NO_INIT - the buffer queue has been abandoned.
    // * NO_INIT - the buffer queue has been abandoned or the producer is not
    //             connected.
    // * BAD_VALUE - the given slot number is invalid, either because it is
    //               out of the range [0, NUM_BUFFER_SLOTS), or because the slot
    //               it refers to is not currently dequeued and requested.
@@ -218,7 +221,8 @@ public:
    // equivalent to fence from the dequeueBuffer call.
    //
    // Return of a value other than NO_ERROR means an error has occurred:
    // * NO_INIT - the buffer queue has been abandoned.
    // * NO_INIT - the buffer queue has been abandoned or the producer is not
    //             connected.
    // * BAD_VALUE - either outBuffer or outFence were NULL.
    // * NO_MEMORY - no slots were found that were both free and contained a
    //               GraphicBuffer.
@@ -237,7 +241,8 @@ public:
    // success.
    //
    // Return of a negative value means an error has occurred:
    // * NO_INIT - the buffer queue has been abandoned.
    // * NO_INIT - the buffer queue has been abandoned or the producer is not
    //             connected.
    // * BAD_VALUE - outSlot or buffer were NULL, invalid combination of
    //               async mode and buffer count override, or the generation
    //               number of the buffer did not match the buffer queue.
@@ -271,7 +276,8 @@ public:
    // (refer to the documentation below).
    //
    // Return of a value other than NO_ERROR means an error has occurred:
    // * NO_INIT - the buffer queue has been abandoned.
    // * NO_INIT - the buffer queue has been abandoned or the producer is not
    //             connected.
    // * BAD_VALUE - one of the below conditions occurred:
    //              * fence was NULL
    //              * scaling mode was unknown
@@ -384,9 +390,19 @@ public:
    //
    // The buffer is not queued for use by the consumer.
    //
    // The slot must be in the range of [0, NUM_BUFFER_SLOTS).
    //
    // The buffer will not be overwritten until the fence signals.  The fence
    // will usually be the one obtained from dequeueBuffer.
    virtual void cancelBuffer(int slot, const sp<Fence>& fence) = 0;
    //
    // Return of a value other than NO_ERROR means an error has occurred:
    // * NO_INIT - the buffer queue has been abandoned or the producer is not
    //             connected.
    // * BAD_VALUE - one of the below conditions occurred:
    //              * fence was NULL
    //              * slot index was out of range (see above).
    //              * the slot was not in the dequeued state
    virtual status_t cancelBuffer(int slot, const sp<Fence>& fence) = 0;

    // query retrieves some information for this surface
    // 'what' tokens allowed are that of NATIVE_WINDOW_* in <window.h>
+56 −7
Original line number Diff line number Diff line
@@ -57,6 +57,11 @@ status_t BufferQueueProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
        return NO_INIT;
    }

    if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
        BQ_LOGE("requestBuffer: BufferQueue has no connected producer");
        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);
@@ -286,6 +291,16 @@ status_t BufferQueueProducer::dequeueBuffer(int *outSlot,
    { // Autolock scope
        Mutex::Autolock lock(mCore->mMutex);
        mConsumerName = mCore->mConsumerName;

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

        if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
            BQ_LOGE("dequeueBuffer: BufferQueue has no connected producer");
            return NO_INIT;
        }
    } // Autolock scope

    BQ_LOGV("dequeueBuffer: async=%s w=%u h=%u format=%#x, usage=%#x",
@@ -453,6 +468,11 @@ status_t BufferQueueProducer::detachBuffer(int slot) {
        return NO_INIT;
    }

    if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
        BQ_LOGE("detachBuffer(P): BufferQueue has no connected producer");
        return NO_INIT;
    }

    if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
        BQ_LOGE("detachBuffer(P): slot index %d out of range [0, %d)",
                slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
@@ -487,13 +507,19 @@ status_t BufferQueueProducer::detachNextBuffer(sp<GraphicBuffer>* outBuffer,
    }

    Mutex::Autolock lock(mCore->mMutex);
    mCore->waitWhileAllocatingLocked();

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

    if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
        BQ_LOGE("detachNextBuffer: BufferQueue has no connected producer");
        return NO_INIT;
    }

    mCore->waitWhileAllocatingLocked();

    if (mCore->mFreeBuffers.empty()) {
        return NO_MEMORY;
    }
@@ -524,7 +550,16 @@ status_t BufferQueueProducer::attachBuffer(int* outSlot,
    }

    Mutex::Autolock lock(mCore->mMutex);
    mCore->waitWhileAllocatingLocked();

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

    if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
        BQ_LOGE("attachBuffer(P): BufferQueue has no connected producer");
        return NO_INIT;
    }

    if (buffer->getGenerationNumber() != mCore->mGenerationNumber) {
        BQ_LOGE("attachBuffer: generation number mismatch [buffer %u] "
@@ -533,6 +568,8 @@ status_t BufferQueueProducer::attachBuffer(int* outSlot,
        return BAD_VALUE;
    }

    mCore->waitWhileAllocatingLocked();

    status_t returnFlags = NO_ERROR;
    int found;
    // TODO: Should we provide an async flag to attachBuffer? It seems
@@ -612,6 +649,11 @@ status_t BufferQueueProducer::queueBuffer(int slot,
            return NO_INIT;
        }

        if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
            BQ_LOGE("queueBuffer: BufferQueue has no connected producer");
            return NO_INIT;
        }

        const int maxBufferCount = mCore->getMaxBufferCountLocked(async);

        if (slot < 0 || slot >= maxBufferCount) {
@@ -748,27 +790,32 @@ status_t BufferQueueProducer::queueBuffer(int slot,
    return NO_ERROR;
}

void BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
status_t BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
    ATRACE_CALL();
    BQ_LOGV("cancelBuffer: slot %d", slot);
    Mutex::Autolock lock(mCore->mMutex);

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

    if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
        BQ_LOGE("cancelBuffer: BufferQueue has no connected producer");
        return NO_INIT;
    }

    if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
        BQ_LOGE("cancelBuffer: slot index %d out of range [0, %d)",
                slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
        return;
        return BAD_VALUE;
    } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
        BQ_LOGE("cancelBuffer: slot %d is not owned by the producer "
                "(state = %d)", slot, mSlots[slot].mBufferState);
        return;
        return BAD_VALUE;
    } else if (fence == NULL) {
        BQ_LOGE("cancelBuffer: fence is NULL");
        return;
        return BAD_VALUE;
    }

    mCore->mFreeBuffers.push_front(slot);
@@ -776,6 +823,8 @@ void BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
    mSlots[slot].mFence = fence;
    mCore->mDequeueCondition.broadcast();
    mCore->validateConsistencyLocked();

    return NO_ERROR;
}

int BufferQueueProducer::query(int what, int *outValue) {
+9 −3
Original line number Diff line number Diff line
@@ -206,12 +206,17 @@ public:
        return result;
    }

    virtual void cancelBuffer(int buf, const sp<Fence>& fence) {
    virtual status_t cancelBuffer(int buf, const sp<Fence>& fence) {
        Parcel data, reply;
        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
        data.writeInt32(buf);
        data.write(*fence.get());
        remote()->transact(CANCEL_BUFFER, data, &reply);
        status_t result = remote()->transact(CANCEL_BUFFER, data, &reply);
        if (result != NO_ERROR) {
            return result;
        }
        result = reply.readInt32();
        return result;
    }

    virtual int query(int what, int* value) {
@@ -434,7 +439,8 @@ status_t BnGraphicBufferProducer::onTransact(
            int buf = data.readInt32();
            sp<Fence> fence = new Fence();
            data.read(*fence.get());
            cancelBuffer(buf, fence);
            status_t result = cancelBuffer(buf, fence);
            reply->writeInt32(result);
            return NO_ERROR;
        }
        case QUERY: {
+3 −0
Original line number Diff line number Diff line
@@ -449,6 +449,9 @@ void configureANW(const sp<ANativeWindow>& anw,
        const CpuConsumerTestParams& params,
        int maxBufferSlack) {
    status_t err;
    err = native_window_api_connect(anw.get(), NATIVE_WINDOW_API_CPU);
    ASSERT_NO_ERROR(err, "connect error: ");

    err = native_window_set_buffers_dimensions(anw.get(),
            params.width, params.height);
    ASSERT_NO_ERROR(err, "set_buffers_dimensions error: ");
Loading