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

Commit 650e25db authored by Jim Shargo's avatar Jim Shargo
Browse files

Surface: return early from dequeueBuffer on failure

In the function

```
Surface::dequeueBuffer(sp<GraphicBuffer>* buffer, sp<Fence>* outFence)
```

we'd always try to map the uninitialized android_native_buffer_t to a
GraphicBuffer.  This would lead to an NPE in the refcounting code
sometimes.

Now, we'll stop short and return early on error.

Bug: 414442592
Flag: EXEMPT small bugfix
Test: new test
Change-Id: I592a94f356d289be0b49696c428b5ba70f9c9803
parent 26597a52
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -753,9 +753,14 @@ status_t Surface::dequeueBuffer(sp<GraphicBuffer>* buffer, sp<Fence>* outFence)
        return BAD_VALUE;
    }

    android_native_buffer_t* anb;
    android_native_buffer_t* anb = nullptr;
    int fd = -1;
    status_t res = dequeueBuffer(&anb, &fd);
    if (res != NO_ERROR) {
        ALOGV("dequeueBuffer() returned %d", res);
        return res;
    }

    *buffer = GraphicBuffer::from(anb);
    *outFence = sp<Fence>::make(fd);
    return res;
+23 −0
Original line number Diff line number Diff line
@@ -61,6 +61,7 @@

#include "Constants.h"
#include "MockConsumer.h"
#include "hardware/gralloc.h"
#include "testserver/TestServerClient.h"

namespace android {
@@ -2424,6 +2425,28 @@ TEST_F(SurfaceTest, QueueAcquireReleaseDequeue_CalledInStack_DoesNotDeadlock) {
    EXPECT_EQ(OK, surface->disconnect(NATIVE_WINDOW_API_CPU));
}

// See: b/414442592
TEST_F(SurfaceTest, DequeueBuffer_WithDeadConsumer_DoesNotCrash) {
    auto [consumer, surface] = BufferItemConsumer::create(GRALLOC_USAGE_SW_READ_OFTEN);

    sp<SurfaceListener> surfaceListener = sp<StubSurfaceListener>::make();
    EXPECT_EQ(OK, surface->connect(NATIVE_WINDOW_API_CPU, surfaceListener, false));

    sp<GraphicBuffer> buffer;
    sp<Fence> fence;
    EXPECT_EQ(OK, surface->dequeueBuffer(&buffer, &fence));
    EXPECT_EQ(OK, surface->queueBuffer(buffer, fence));

    consumer->abandon();

    auto beforeBuffer = buffer;
    auto beforeFence = fence;

    EXPECT_NE(OK, surface->dequeueBuffer(&buffer, &fence));
    EXPECT_EQ(buffer, beforeBuffer);
    EXPECT_EQ(fence, beforeFence);
}

TEST_F(SurfaceTest, ViewSurface_toString) {
    view::Surface surface{};
    EXPECT_EQ("", surface.toString());