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

Commit 889234d4 authored by Emilian Peev's avatar Emilian Peev
Browse files

Camera: Avoid freeing outstanding input buffers

The producer end can disconnect at any time which
will trigger the freeing of the input buffer. If
any input buffers are outstanding and being processed
by the camera device freeing them can cause stability
issues.

Bug: 63682712
Test: Manual using application.
Change-Id: I25da97786d75e82b1b13dce34953de597bea9b2e
parent 679b6f6e
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -293,6 +293,15 @@ status_t Camera3InputStream::getEndpointUsage(uint32_t *usage) const {
void Camera3InputStream::onBufferFreed(const wp<GraphicBuffer>& gb) {
    const sp<GraphicBuffer> buffer = gb.promote();
    if (buffer != nullptr) {
        camera3_stream_buffer streamBuffer =
                {nullptr, &buffer->handle, 0, -1, -1};
        // Check if this buffer is outstanding.
        if (isOutstandingBuffer(streamBuffer)) {
            ALOGV("%s: Stream %d: Trying to free a buffer that is still being "
                    "processed.", __FUNCTION__, mId);
            return;
        }

        sp<Camera3StreamBufferFreedListener> callback = mBufferFreedListener.promote();
        if (callback != nullptr) {
            callback->onBufferFreed(mId, buffer->handle);
+7 −1
Original line number Diff line number Diff line
@@ -479,6 +479,7 @@ status_t Camera3Stream::getBuffer(camera3_stream_buffer *buffer,
    if (res == OK) {
        fireBufferListenersLocked(*buffer, /*acquired*/true, /*output*/true);
        if (buffer->buffer) {
            Mutex::Autolock l(mOutstandingBuffersLock);
            mOutstandingBuffers.push_back(*buffer->buffer);
        }
    }
@@ -486,11 +487,13 @@ status_t Camera3Stream::getBuffer(camera3_stream_buffer *buffer,
    return res;
}

bool Camera3Stream::isOutstandingBuffer(const camera3_stream_buffer &buffer) {
bool Camera3Stream::isOutstandingBuffer(const camera3_stream_buffer &buffer) const{
    if (buffer.buffer == nullptr) {
        return false;
    }

    Mutex::Autolock l(mOutstandingBuffersLock);

    for (auto b : mOutstandingBuffers) {
        if (b == *buffer.buffer) {
            return true;
@@ -504,6 +507,8 @@ void Camera3Stream::removeOutstandingBuffer(const camera3_stream_buffer &buffer)
        return;
    }

    Mutex::Autolock l(mOutstandingBuffersLock);

    for (auto b = mOutstandingBuffers.begin(); b != mOutstandingBuffers.end(); b++) {
        if (*b == *buffer.buffer) {
            mOutstandingBuffers.erase(b);
@@ -575,6 +580,7 @@ status_t Camera3Stream::getInputBuffer(camera3_stream_buffer *buffer, bool respe
    if (res == OK) {
        fireBufferListenersLocked(*buffer, /*acquired*/true, /*output*/false);
        if (buffer->buffer) {
            Mutex::Autolock l(mOutstandingBuffersLock);
            mOutstandingBuffers.push_back(*buffer->buffer);
        }
    }
+4 −3
Original line number Diff line number Diff line
@@ -461,6 +461,9 @@ class Camera3Stream :
    // INVALID_OPERATION if they cannot be obtained.
    virtual status_t getEndpointUsage(uint32_t *usage) const = 0;

    // Return whether the buffer is in the list of outstanding buffers.
    bool isOutstandingBuffer(const camera3_stream_buffer& buffer) const;

    // Tracking for idle state
    wp<StatusTracker> mStatusTracker;
    // Status tracker component ID
@@ -483,9 +486,6 @@ class Camera3Stream :

    status_t        cancelPrepareLocked();

    // Return whether the buffer is in the list of outstanding buffers.
    bool isOutstandingBuffer(const camera3_stream_buffer& buffer);

    // Remove the buffer from the list of outstanding buffers.
    void removeOutstandingBuffer(const camera3_stream_buffer& buffer);

@@ -502,6 +502,7 @@ class Camera3Stream :
    // Number of buffers allocated on last prepare call.
    size_t mLastMaxCount;

    mutable Mutex mOutstandingBuffersLock;
    // Outstanding buffers dequeued from the stream's buffer queue.
    List<buffer_handle_t> mOutstandingBuffers;