Support BufferHub-backed IGBP in libgui_test
Use gtest's TestWithParam tests to support testing both BufferQueue
backend and BufferHub backend. Testing against BufferHub backend is
gated by USE_BUFFER_HUB_AS_BUFFER_QUEUE build time flag, so that build
targets don't support BufferHub won't be impacted by this test.
Known issues:
b/36724099: Add support for BufferHubProducer::setAsyncMode(true)
b/38137191: Implement BufferHubProducer::detachBuffer
b/69981968: Implement BufferHubProducer::attachBuffer
b/70041889: BufferHubProducer need to support metadata: numPendingBuffers
b/70041952: BufferHubProducer need to support metadata: nextFrameNumber
b/73267953: Make BufferHub hornor producer and consumer connection
Bug: 68733388
Bug: 70046255
Bug: 73160000
Test: libgui_test
Change-Id: I35631762781a622cabb0fba7302d18fb983dde40
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index 4151212..1988690 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -18,6 +18,8 @@
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
//#define LOG_NDEBUG 0
+#include <gui/BufferHubConsumer.h>
+#include <gui/BufferHubProducer.h>
#include <gui/BufferQueue.h>
#include <gui/BufferQueueConsumer.h>
#include <gui/BufferQueueCore.h>
@@ -101,4 +103,31 @@
*outConsumer = consumer;
}
+void BufferQueue::createBufferHubQueue(sp<IGraphicBufferProducer>* outProducer,
+ sp<IGraphicBufferConsumer>* outConsumer) {
+ LOG_ALWAYS_FATAL_IF(outProducer == NULL, "BufferQueue: outProducer must not be NULL");
+ LOG_ALWAYS_FATAL_IF(outConsumer == NULL, "BufferQueue: outConsumer must not be NULL");
+
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+
+ dvr::ProducerQueueConfigBuilder configBuilder;
+ std::shared_ptr<dvr::ProducerQueue> producerQueue =
+ dvr::ProducerQueue::Create(configBuilder.SetMetadata<DvrNativeBufferMetadata>().Build(),
+ dvr::UsagePolicy{});
+ LOG_ALWAYS_FATAL_IF(producerQueue == NULL, "BufferQueue: failed to create ProducerQueue.");
+
+ std::shared_ptr<dvr::ConsumerQueue> consumerQueue = producerQueue->CreateConsumerQueue();
+ LOG_ALWAYS_FATAL_IF(consumerQueue == NULL, "BufferQueue: failed to create ConsumerQueue.");
+
+ producer = BufferHubProducer::Create(producerQueue);
+ consumer = BufferHubConsumer::Create(consumerQueue);
+
+ LOG_ALWAYS_FATAL_IF(producer == NULL, "BufferQueue: failed to create BufferQueueProducer");
+ LOG_ALWAYS_FATAL_IF(consumer == NULL, "BufferQueue: failed to create BufferQueueConsumer");
+
+ *outProducer = producer;
+ *outConsumer = consumer;
+}
+
}; // namespace android
diff --git a/libs/gui/include/gui/BufferQueue.h b/libs/gui/include/gui/BufferQueue.h
index ba5cbf7..f175573 100644
--- a/libs/gui/include/gui/BufferQueue.h
+++ b/libs/gui/include/gui/BufferQueue.h
@@ -79,6 +79,10 @@
sp<IGraphicBufferConsumer>* outConsumer,
bool consumerIsSurfaceFlinger = false);
+ // Creates an IGraphicBufferProducer and IGraphicBufferConsumer pair backed by BufferHub.
+ static void createBufferHubQueue(sp<IGraphicBufferProducer>* outProducer,
+ sp<IGraphicBufferConsumer>* outConsumer);
+
BufferQueue() = delete; // Create through createBufferQueue
};
diff --git a/libs/gui/tests/IGraphicBufferProducer_test.cpp b/libs/gui/tests/IGraphicBufferProducer_test.cpp
index dd23bd4..a35cf11 100644
--- a/libs/gui/tests/IGraphicBufferProducer_test.cpp
+++ b/libs/gui/tests/IGraphicBufferProducer_test.cpp
@@ -42,6 +42,10 @@
#define TEST_CONTROLLED_BY_APP false
#define TEST_PRODUCER_USAGE_BITS (0)
+#ifndef USE_BUFFER_HUB_AS_BUFFER_QUEUE
+#define USE_BUFFER_HUB_AS_BUFFER_QUEUE 0
+#endif
+
namespace android {
namespace {
@@ -66,9 +70,15 @@
const int QUEUE_BUFFER_INPUT_SCALING_MODE = 0;
const int QUEUE_BUFFER_INPUT_TRANSFORM = 0;
const sp<Fence> QUEUE_BUFFER_INPUT_FENCE = Fence::NO_FENCE;
+
+ // Enums to control which IGraphicBufferProducer backend to test.
+ enum IGraphicBufferProducerTestCode {
+ USE_BUFFER_QUEUE_PRODUCER = 0,
+ USE_BUFFER_HUB_PRODUCER,
+ };
}; // namespace anonymous
-class IGraphicBufferProducerTest : public ::testing::Test {
+class IGraphicBufferProducerTest : public ::testing::TestWithParam<uint32_t> {
protected:
IGraphicBufferProducerTest() {}
@@ -81,10 +91,27 @@
mDC = new DummyConsumer;
- BufferQueue::createBufferQueue(&mProducer, &mConsumer);
+ switch (GetParam()) {
+ case USE_BUFFER_QUEUE_PRODUCER: {
+ BufferQueue::createBufferQueue(&mProducer, &mConsumer);
+ break;
+ }
+ case USE_BUFFER_HUB_PRODUCER: {
+ BufferQueue::createBufferHubQueue(&mProducer, &mConsumer);
+ break;
+ }
+ default: {
+ // Should never reach here.
+ LOG_ALWAYS_FATAL("Invalid test params: %u", GetParam());
+ break;
+ }
+ }
// Test check: Can't connect producer if no consumer yet
- ASSERT_EQ(NO_INIT, TryConnectProducer());
+ if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
+ // TODO(b/73267953): Make BufferHub honor producer and consumer connection.
+ ASSERT_EQ(NO_INIT, TryConnectProducer());
+ }
// Must connect consumer before producer connects will succeed.
ASSERT_OK(mConsumer->consumerConnect(mDC, /*controlledByApp*/false));
@@ -229,7 +256,7 @@
sp<IGraphicBufferConsumer> mConsumer;
};
-TEST_F(IGraphicBufferProducerTest, ConnectFirst_ReturnsError) {
+TEST_P(IGraphicBufferProducerTest, ConnectFirst_ReturnsError) {
IGraphicBufferProducer::QueueBufferOutput output;
// NULL output returns BAD_VALUE
@@ -247,7 +274,7 @@
// TODO: get a token from a dead process somehow
}
-TEST_F(IGraphicBufferProducerTest, ConnectAgain_ReturnsError) {
+TEST_P(IGraphicBufferProducerTest, ConnectAgain_ReturnsError) {
ASSERT_NO_FATAL_FAILURE(ConnectProducer());
// Can't connect when there is already a producer connected
@@ -259,20 +286,23 @@
ASSERT_OK(mConsumer->consumerDisconnect());
// Can't connect when IGBP is abandoned
- EXPECT_EQ(NO_INIT, mProducer->connect(TEST_TOKEN,
- TEST_API,
- TEST_CONTROLLED_BY_APP,
- &output));
+ if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
+ // TODO(b/73267953): Make BufferHub honor producer and consumer connection.
+ EXPECT_EQ(NO_INIT, mProducer->connect(TEST_TOKEN,
+ TEST_API,
+ TEST_CONTROLLED_BY_APP,
+ &output));
+ }
}
-TEST_F(IGraphicBufferProducerTest, Disconnect_Succeeds) {
+TEST_P(IGraphicBufferProducerTest, Disconnect_Succeeds) {
ASSERT_NO_FATAL_FAILURE(ConnectProducer());
ASSERT_OK(mProducer->disconnect(TEST_API));
}
-TEST_F(IGraphicBufferProducerTest, Disconnect_ReturnsError) {
+TEST_P(IGraphicBufferProducerTest, Disconnect_ReturnsError) {
ASSERT_NO_FATAL_FAILURE(ConnectProducer());
// Must disconnect with same API number
@@ -283,7 +313,7 @@
// TODO: somehow kill mProducer so that this returns DEAD_OBJECT
}
-TEST_F(IGraphicBufferProducerTest, Query_Succeeds) {
+TEST_P(IGraphicBufferProducerTest, Query_Succeeds) {
ASSERT_NO_FATAL_FAILURE(ConnectProducer());
int32_t value = -1;
@@ -308,7 +338,7 @@
}
-TEST_F(IGraphicBufferProducerTest, Query_ReturnsError) {
+TEST_P(IGraphicBufferProducerTest, Query_ReturnsError) {
ASSERT_NO_FATAL_FAILURE(ConnectProducer());
// One past the end of the last 'query' enum value. Update this if we add more enums.
@@ -334,14 +364,17 @@
ASSERT_OK(mConsumer->consumerDisconnect());
// BQ was abandoned
- EXPECT_EQ(NO_INIT, mProducer->query(NATIVE_WINDOW_FORMAT, &value));
+ if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
+ // TODO(b/73267953): Make BufferHub honor producer and consumer connection.
+ EXPECT_EQ(NO_INIT, mProducer->query(NATIVE_WINDOW_FORMAT, &value));
+ }
// TODO: other things in window.h that are supported by Surface::query
// but not by BufferQueue::query
}
// TODO: queue under more complicated situations not involving just a single buffer
-TEST_F(IGraphicBufferProducerTest, Queue_Succeeds) {
+TEST_P(IGraphicBufferProducerTest, Queue_Succeeds) {
ASSERT_NO_FATAL_FAILURE(ConnectProducer());
int dequeuedSlot = -1;
@@ -371,16 +404,21 @@
EXPECT_EQ(DEFAULT_WIDTH, output.width);
EXPECT_EQ(DEFAULT_HEIGHT, output.height);
EXPECT_EQ(DEFAULT_TRANSFORM_HINT, output.transformHint);
+
// Since queueBuffer was called exactly once
- EXPECT_EQ(1u, output.numPendingBuffers);
- EXPECT_EQ(2u, output.nextFrameNumber);
+ if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
+ // TODO(b/70041889): BufferHubProducer need to support metadata: numPendingBuffers
+ EXPECT_EQ(1u, output.numPendingBuffers);
+ // TODO(b/70041952): BufferHubProducer need to support metadata: nextFrameNumber
+ EXPECT_EQ(2u, output.nextFrameNumber);
+ }
}
// Buffer was not in the dequeued state
EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output));
}
-TEST_F(IGraphicBufferProducerTest, Queue_ReturnsError) {
+TEST_P(IGraphicBufferProducerTest, Queue_ReturnsError) {
ASSERT_NO_FATAL_FAILURE(ConnectProducer());
// Invalid slot number
@@ -463,15 +501,16 @@
ASSERT_OK(mConsumer->consumerDisconnect());
// The buffer queue has been abandoned.
- {
+ if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
IGraphicBufferProducer::QueueBufferOutput output;
+ // TODO(b/73267953): Make BufferHub honor producer and consumer connection.
EXPECT_EQ(NO_INIT, mProducer->queueBuffer(dequeuedSlot, input, &output));
}
}
-TEST_F(IGraphicBufferProducerTest, CancelBuffer_DoesntCrash) {
+TEST_P(IGraphicBufferProducerTest, CancelBuffer_DoesntCrash) {
ASSERT_NO_FATAL_FAILURE(ConnectProducer());
int dequeuedSlot = -1;
@@ -488,7 +527,7 @@
mProducer->cancelBuffer(dequeuedSlot, dequeuedFence);
}
-TEST_F(IGraphicBufferProducerTest, SetMaxDequeuedBufferCount_Succeeds) {
+TEST_P(IGraphicBufferProducerTest, SetMaxDequeuedBufferCount_Succeeds) {
ASSERT_NO_FATAL_FAILURE(ConnectProducer());
int minUndequeuedBuffers;
ASSERT_OK(mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
@@ -540,7 +579,7 @@
ASSERT_OK(mProducer->setMaxDequeuedBufferCount(maxBuffers-1));
}
-TEST_F(IGraphicBufferProducerTest, SetMaxDequeuedBufferCount_Fails) {
+TEST_P(IGraphicBufferProducerTest, SetMaxDequeuedBufferCount_Fails) {
ASSERT_NO_FATAL_FAILURE(ConnectProducer());
int minUndequeuedBuffers;
ASSERT_OK(mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
@@ -578,12 +617,19 @@
ASSERT_OK(mConsumer->consumerDisconnect());
// Fail because the buffer queue was abandoned
- EXPECT_EQ(NO_INIT, mProducer->setMaxDequeuedBufferCount(minBuffers))
- << "bufferCount: " << minBuffers;
-
+ if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
+ // TODO(b/73267953): Make BufferHub honor producer and consumer connection.
+ EXPECT_EQ(NO_INIT, mProducer->setMaxDequeuedBufferCount(minBuffers))
+ << "bufferCount: " << minBuffers;
+ }
}
-TEST_F(IGraphicBufferProducerTest, SetAsyncMode_Succeeds) {
+TEST_P(IGraphicBufferProducerTest, SetAsyncMode_Succeeds) {
+ if (GetParam() == USE_BUFFER_HUB_PRODUCER) {
+ // TODO(b/36724099): Add support for BufferHubProducer::setAsyncMode(true)
+ return;
+ }
+
ASSERT_OK(mConsumer->setMaxAcquiredBufferCount(1)) << "maxAcquire: " << 1;
ASSERT_NO_FATAL_FAILURE(ConnectProducer());
ASSERT_OK(mProducer->setAsyncMode(true)) << "async mode: " << true;
@@ -609,7 +655,7 @@
}
}
-TEST_F(IGraphicBufferProducerTest, SetAsyncMode_Fails) {
+TEST_P(IGraphicBufferProducerTest, SetAsyncMode_Fails) {
ASSERT_NO_FATAL_FAILURE(ConnectProducer());
// Prerequisite to fail out a valid setBufferCount call
{
@@ -628,11 +674,13 @@
ASSERT_OK(mConsumer->consumerDisconnect());
// Fail because the buffer queue was abandoned
- EXPECT_EQ(NO_INIT, mProducer->setAsyncMode(false)) << "asyncMode: "
- << false;
+ if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
+ // TODO(b/36724099): Make BufferHub honor producer and consumer connection.
+ EXPECT_EQ(NO_INIT, mProducer->setAsyncMode(false)) << "asyncMode: " << false;
+ }
}
-TEST_F(IGraphicBufferProducerTest,
+TEST_P(IGraphicBufferProducerTest,
DisconnectedProducerReturnsError_dequeueBuffer) {
int slot = -1;
sp<Fence> fence;
@@ -642,15 +690,18 @@
TEST_PRODUCER_USAGE_BITS, nullptr, nullptr));
}
-TEST_F(IGraphicBufferProducerTest,
+TEST_P(IGraphicBufferProducerTest,
DisconnectedProducerReturnsError_detachNextBuffer) {
sp<Fence> fence;
sp<GraphicBuffer> buffer;
- ASSERT_EQ(NO_INIT, mProducer->detachNextBuffer(&buffer, &fence));
+ if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
+ // TODO(b/38137191): Implement BufferHubProducer::detachBuffer
+ ASSERT_EQ(NO_INIT, mProducer->detachNextBuffer(&buffer, &fence));
+ }
}
-TEST_F(IGraphicBufferProducerTest,
+TEST_P(IGraphicBufferProducerTest,
DisconnectedProducerReturnsError_requestBuffer) {
ASSERT_NO_FATAL_FAILURE(ConnectProducer());
@@ -674,7 +725,7 @@
}
-TEST_F(IGraphicBufferProducerTest,
+TEST_P(IGraphicBufferProducerTest,
DisconnectedProducerReturnsError_detachBuffer) {
int slot = -1;
sp<Fence> fence;
@@ -684,10 +735,13 @@
ASSERT_OK(mProducer->disconnect(TEST_API));
- ASSERT_EQ(NO_INIT, mProducer->detachBuffer(slot));
+ if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
+ // TODO(b/38137191): Implement BufferHubProducer::detachBuffer
+ ASSERT_EQ(NO_INIT, mProducer->detachBuffer(slot));
+ }
}
-TEST_F(IGraphicBufferProducerTest,
+TEST_P(IGraphicBufferProducerTest,
DisconnectedProducerReturnsError_queueBuffer) {
int slot = -1;
sp<Fence> fence;
@@ -704,7 +758,7 @@
ASSERT_EQ(NO_INIT, mProducer->queueBuffer(slot, input, &output));
}
-TEST_F(IGraphicBufferProducerTest,
+TEST_P(IGraphicBufferProducerTest,
DisconnectedProducerReturnsError_cancelBuffer) {
int slot = -1;
sp<Fence> fence;
@@ -717,7 +771,7 @@
ASSERT_EQ(NO_INIT, mProducer->cancelBuffer(slot, fence));
}
-TEST_F(IGraphicBufferProducerTest,
+TEST_P(IGraphicBufferProducerTest,
DisconnectedProducerReturnsError_attachBuffer) {
int slot = -1;
sp<Fence> fence;
@@ -725,11 +779,27 @@
setupDequeueRequestBuffer(&slot, &fence, &buffer);
- ASSERT_OK(mProducer->detachBuffer(slot));
+ if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
+ // TODO(b/38137191): Implement BufferHubProducer::detachBuffer
+ ASSERT_OK(mProducer->detachBuffer(slot));
+ }
ASSERT_OK(mProducer->disconnect(TEST_API));
- ASSERT_EQ(NO_INIT, mProducer->attachBuffer(&slot, buffer));
+ if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
+ // TODO(b/69981968): Implement BufferHubProducer::attachBuffer
+ ASSERT_EQ(NO_INIT, mProducer->attachBuffer(&slot, buffer));
+ }
}
+#if USE_BUFFER_HUB_AS_BUFFER_QUEUE
+INSTANTIATE_TEST_CASE_P(IGraphicBufferProducerBackends, IGraphicBufferProducerTest,
+ ::testing::Values(USE_BUFFER_QUEUE_PRODUCER, USE_BUFFER_HUB_PRODUCER));
+#else
+// TODO(b/70046255): Remove the #ifdef here and always tests both backends once BufferHubQueue can
+// pass all existing libgui tests.
+INSTANTIATE_TEST_CASE_P(IGraphicBufferProducerBackends, IGraphicBufferProducerTest,
+ ::testing::Values(USE_BUFFER_QUEUE_PRODUCER));
+#endif
+
} // namespace android