libgui: Add generation numbers to BufferQueue
This change allows producers to set a generation number on a
BufferQueue. This number will be embedded in any new GraphicBuffers
created in that BufferQueue, and attempts to attach buffers which have
a different generation number will fail.
It also plumbs the setGenerationNumber method through Surface, with the
additional effect that any buffers attached to the Surface after
setting a new generation number will automatically be updated with the
new number (as opposed to failing, as would happen on through IGBP).
Bug: 20923096
Change-Id: I32bf726b035f99c3e5834beaf76afb9f01adcbc2
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index 1584fef..3d1139d 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -402,4 +402,46 @@
WIDTH * 2, HEIGHT * 2, 0, GRALLOC_USAGE_SW_WRITE_OFTEN));
}
+TEST_F(BufferQueueTest, TestGenerationNumbers) {
+ createBufferQueue();
+ sp<DummyConsumer> dc(new DummyConsumer);
+ ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
+ IGraphicBufferProducer::QueueBufferOutput output;
+ ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
+ NATIVE_WINDOW_API_CPU, true, &output));
+
+ ASSERT_EQ(OK, mProducer->setGenerationNumber(1));
+
+ // Get one buffer to play with
+ int slot;
+ sp<Fence> fence;
+ ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
+ mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0, 0));
+
+ sp<GraphicBuffer> buffer;
+ ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
+
+ // Ensure that the generation number we set propagates to allocated buffers
+ ASSERT_EQ(1U, buffer->getGenerationNumber());
+
+ ASSERT_EQ(OK, mProducer->detachBuffer(slot));
+
+ ASSERT_EQ(OK, mProducer->setGenerationNumber(2));
+
+ // These should fail, since we've changed the generation number on the queue
+ int outSlot;
+ ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(&outSlot, buffer));
+ ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(&outSlot, buffer));
+
+ buffer->setGenerationNumber(2);
+
+ // This should succeed now that we've changed the buffer's generation number
+ ASSERT_EQ(OK, mProducer->attachBuffer(&outSlot, buffer));
+
+ ASSERT_EQ(OK, mProducer->detachBuffer(outSlot));
+
+ // This should also succeed with the new generation number
+ ASSERT_EQ(OK, mConsumer->attachBuffer(&outSlot, buffer));
+}
+
} // namespace android
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 4f87824..cf0043d 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -177,4 +177,37 @@
ASSERT_EQ(TEST_DATASPACE, dataSpace);
}
+TEST_F(SurfaceTest, SettingGenerationNumber) {
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+ sp<CpuConsumer> cpuConsumer = new CpuConsumer(consumer, 1);
+ sp<Surface> surface = new Surface(producer);
+ sp<ANativeWindow> window(surface);
+
+ // Allocate a buffer with a generation number of 0
+ ANativeWindowBuffer* buffer;
+ int fenceFd;
+ ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffer, &fenceFd));
+ ASSERT_EQ(NO_ERROR, window->cancelBuffer(window.get(), buffer, fenceFd));
+
+ // Detach the buffer and check its generation number
+ sp<GraphicBuffer> graphicBuffer;
+ sp<Fence> fence;
+ ASSERT_EQ(NO_ERROR, surface->detachNextBuffer(&graphicBuffer, &fence));
+ ASSERT_EQ(0U, graphicBuffer->getGenerationNumber());
+
+ ASSERT_EQ(NO_ERROR, surface->setGenerationNumber(1));
+ buffer = static_cast<ANativeWindowBuffer*>(graphicBuffer.get());
+
+ // This should change the generation number of the GraphicBuffer
+ ASSERT_EQ(NO_ERROR, surface->attachBuffer(buffer));
+
+ // Check that the new generation number sticks with the buffer
+ ASSERT_EQ(NO_ERROR, window->cancelBuffer(window.get(), buffer, -1));
+ ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffer, &fenceFd));
+ graphicBuffer = static_cast<GraphicBuffer*>(buffer);
+ ASSERT_EQ(1U, graphicBuffer->getGenerationNumber());
+}
+
}