blob: 2af2fe1f91696a79f16ec97549d45759e7957ba7 [file] [log] [blame]
Igor Murashkin7ea777f2013-11-18 16:58:36 -08001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "IGraphicBufferProducer_test"
18//#define LOG_NDEBUG 0
19
Peiyong Lind8460c82020-07-28 16:04:22 -070020#include "MockConsumer.h"
Brian Anderson5ea5e592016-12-01 16:54:33 -080021
Igor Murashkin7ea777f2013-11-18 16:58:36 -080022#include <gtest/gtest.h>
23
24#include <utils/String8.h>
25#include <utils/threads.h>
26
27#include <ui/GraphicBuffer.h>
Igor Murashkin7ea777f2013-11-18 16:58:36 -080028
29#include <gui/BufferQueue.h>
Dan Stozaf0eaf252014-03-21 13:05:51 -070030#include <gui/IProducerListener.h>
Igor Murashkin7ea777f2013-11-18 16:58:36 -080031
Mathias Agopian6a3c05b2017-04-27 20:06:55 -070032#include <system/window.h>
33
Igor Murashkin7ea777f2013-11-18 16:58:36 -080034#include <vector>
35
36#define ASSERT_OK(x) ASSERT_EQ(OK, (x))
37#define EXPECT_OK(x) EXPECT_EQ(OK, (x))
38
Dan Stozaf0eaf252014-03-21 13:05:51 -070039#define TEST_TOKEN ((IProducerListener*)(NULL))
Igor Murashkin7ea777f2013-11-18 16:58:36 -080040#define TEST_API NATIVE_WINDOW_API_CPU
41#define TEST_API_OTHER NATIVE_WINDOW_API_EGL // valid API that's not TEST_API
42#define TEST_CONTROLLED_BY_APP false
43#define TEST_PRODUCER_USAGE_BITS (0)
44
Jiwen 'Steve' Cai22029502018-02-12 22:26:05 -080045#ifndef USE_BUFFER_HUB_AS_BUFFER_QUEUE
46#define USE_BUFFER_HUB_AS_BUFFER_QUEUE 0
47#endif
48
Igor Murashkin7ea777f2013-11-18 16:58:36 -080049namespace android {
50
51namespace {
Dan Stozaf8cebe52015-04-20 12:09:38 -070052 // Default dimensions before setDefaultBufferSize is called
53 const uint32_t DEFAULT_WIDTH = 1;
54 const uint32_t DEFAULT_HEIGHT = 1;
55
56 // Default format before setDefaultBufferFormat is called
57 const PixelFormat DEFAULT_FORMAT = HAL_PIXEL_FORMAT_RGBA_8888;
58
59 // Default transform hint before setTransformHint is called
60 const uint32_t DEFAULT_TRANSFORM_HINT = 0;
61
62 // TODO: Make these constants in header
63 const int DEFAULT_CONSUMER_USAGE_BITS = 0;
64
65 // Parameters for a generic "valid" input for queueBuffer.
66 const int64_t QUEUE_BUFFER_INPUT_TIMESTAMP = 1384888611;
67 const bool QUEUE_BUFFER_INPUT_IS_AUTO_TIMESTAMP = false;
68 const android_dataspace QUEUE_BUFFER_INPUT_DATASPACE = HAL_DATASPACE_UNKNOWN;
69 const Rect QUEUE_BUFFER_INPUT_RECT = Rect(DEFAULT_WIDTH, DEFAULT_HEIGHT);
70 const int QUEUE_BUFFER_INPUT_SCALING_MODE = 0;
71 const int QUEUE_BUFFER_INPUT_TRANSFORM = 0;
Dan Stozaf8cebe52015-04-20 12:09:38 -070072 const sp<Fence> QUEUE_BUFFER_INPUT_FENCE = Fence::NO_FENCE;
Yin-Chia Yeh64ee5f52020-01-02 17:53:18 +070073 const uint32_t QUEUE_BUFFER_INPUT_STICKY_TRANSFORM = 0;
74 const bool QUEUE_BUFFER_INPUT_GET_TIMESTAMPS = 0;
75 const int QUEUE_BUFFER_INPUT_SLOT = -1;
Jiwen 'Steve' Cai22029502018-02-12 22:26:05 -080076
77 // Enums to control which IGraphicBufferProducer backend to test.
78 enum IGraphicBufferProducerTestCode {
79 USE_BUFFER_QUEUE_PRODUCER = 0,
80 USE_BUFFER_HUB_PRODUCER,
81 };
Igor Murashkin7ea777f2013-11-18 16:58:36 -080082}; // namespace anonymous
83
Jiwen 'Steve' Cai22029502018-02-12 22:26:05 -080084class IGraphicBufferProducerTest : public ::testing::TestWithParam<uint32_t> {
Igor Murashkin7ea777f2013-11-18 16:58:36 -080085protected:
86
87 IGraphicBufferProducerTest() {}
88
89 virtual void SetUp() {
90 const ::testing::TestInfo* const testInfo =
91 ::testing::UnitTest::GetInstance()->current_test_info();
92 ALOGV("Begin test: %s.%s", testInfo->test_case_name(),
93 testInfo->name());
94
Peiyong Lind8460c82020-07-28 16:04:22 -070095 mMC = new MockConsumer;
Igor Murashkin7ea777f2013-11-18 16:58:36 -080096
Jiwen 'Steve' Cai22029502018-02-12 22:26:05 -080097 switch (GetParam()) {
98 case USE_BUFFER_QUEUE_PRODUCER: {
99 BufferQueue::createBufferQueue(&mProducer, &mConsumer);
100 break;
101 }
102 case USE_BUFFER_HUB_PRODUCER: {
103 BufferQueue::createBufferHubQueue(&mProducer, &mConsumer);
104 break;
105 }
106 default: {
107 // Should never reach here.
108 LOG_ALWAYS_FATAL("Invalid test params: %u", GetParam());
109 break;
110 }
111 }
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800112
113 // Test check: Can't connect producer if no consumer yet
Jiwen 'Steve' Cai22029502018-02-12 22:26:05 -0800114 if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
115 // TODO(b/73267953): Make BufferHub honor producer and consumer connection.
116 ASSERT_EQ(NO_INIT, TryConnectProducer());
117 }
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800118
119 // Must connect consumer before producer connects will succeed.
Peiyong Lind8460c82020-07-28 16:04:22 -0700120 ASSERT_OK(mConsumer->consumerConnect(mMC, /*controlledByApp*/ false));
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800121 }
122
123 virtual void TearDown() {
124 const ::testing::TestInfo* const testInfo =
125 ::testing::UnitTest::GetInstance()->current_test_info();
126 ALOGV("End test: %s.%s", testInfo->test_case_name(),
127 testInfo->name());
128 }
129
130 status_t TryConnectProducer() {
131 IGraphicBufferProducer::QueueBufferOutput output;
132 return mProducer->connect(TEST_TOKEN,
133 TEST_API,
134 TEST_CONTROLLED_BY_APP,
135 &output);
136 // TODO: use params to vary token, api, producercontrolledbyapp, etc
137 }
138
139 // Connect to a producer in a 'correct' fashion.
140 // Precondition: Consumer is connected.
141 void ConnectProducer() {
142 ASSERT_OK(TryConnectProducer());
143 }
144
145 // Create a generic "valid" input for queueBuffer
146 // -- uses the default buffer format, width, etc.
147 static IGraphicBufferProducer::QueueBufferInput CreateBufferInput() {
148 return QueueBufferInputBuilder().build();
149 }
150
151 // Builder pattern to slightly vary *almost* correct input
152 // -- avoids copying and pasting
153 struct QueueBufferInputBuilder {
154 QueueBufferInputBuilder() {
155 timestamp = QUEUE_BUFFER_INPUT_TIMESTAMP;
156 isAutoTimestamp = QUEUE_BUFFER_INPUT_IS_AUTO_TIMESTAMP;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800157 dataSpace = QUEUE_BUFFER_INPUT_DATASPACE;
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800158 crop = QUEUE_BUFFER_INPUT_RECT;
159 scalingMode = QUEUE_BUFFER_INPUT_SCALING_MODE;
160 transform = QUEUE_BUFFER_INPUT_TRANSFORM;
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800161 fence = QUEUE_BUFFER_INPUT_FENCE;
Yin-Chia Yeh64ee5f52020-01-02 17:53:18 +0700162 stickyTransform = QUEUE_BUFFER_INPUT_STICKY_TRANSFORM;
163 getTimestamps = QUEUE_BUFFER_INPUT_GET_TIMESTAMPS;
164 slot = QUEUE_BUFFER_INPUT_SLOT;
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800165 }
166
167 IGraphicBufferProducer::QueueBufferInput build() {
168 return IGraphicBufferProducer::QueueBufferInput(
169 timestamp,
170 isAutoTimestamp,
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800171 dataSpace,
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800172 crop,
173 scalingMode,
174 transform,
Yin-Chia Yeh64ee5f52020-01-02 17:53:18 +0700175 fence,
176 stickyTransform,
177 getTimestamps,
178 slot);
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800179 }
180
181 QueueBufferInputBuilder& setTimestamp(int64_t timestamp) {
182 this->timestamp = timestamp;
183 return *this;
184 }
185
186 QueueBufferInputBuilder& setIsAutoTimestamp(bool isAutoTimestamp) {
187 this->isAutoTimestamp = isAutoTimestamp;
188 return *this;
189 }
190
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800191 QueueBufferInputBuilder& setDataSpace(android_dataspace dataSpace) {
192 this->dataSpace = dataSpace;
193 return *this;
194 }
195
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800196 QueueBufferInputBuilder& setCrop(Rect crop) {
197 this->crop = crop;
198 return *this;
199 }
200
201 QueueBufferInputBuilder& setScalingMode(int scalingMode) {
202 this->scalingMode = scalingMode;
203 return *this;
204 }
205
206 QueueBufferInputBuilder& setTransform(uint32_t transform) {
207 this->transform = transform;
208 return *this;
209 }
210
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800211 QueueBufferInputBuilder& setFence(sp<Fence> fence) {
212 this->fence = fence;
213 return *this;
214 }
215
Yin-Chia Yeh64ee5f52020-01-02 17:53:18 +0700216 QueueBufferInputBuilder& setStickyTransform(uint32_t stickyTransform) {
217 this->stickyTransform = stickyTransform;
218 return *this;
219 }
220
221 QueueBufferInputBuilder& setGetTimestamps(bool getTimestamps) {
222 this->getTimestamps = getTimestamps;
223 return *this;
224 }
225
226 QueueBufferInputBuilder& setSlot(int slot) {
227 this->slot = slot;
228 return *this;
229 }
230
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800231 private:
232 int64_t timestamp;
233 bool isAutoTimestamp;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800234 android_dataspace dataSpace;
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800235 Rect crop;
236 int scalingMode;
237 uint32_t transform;
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800238 sp<Fence> fence;
Yin-Chia Yeh64ee5f52020-01-02 17:53:18 +0700239 uint32_t stickyTransform;
240 bool getTimestamps;
241 int slot;
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800242 }; // struct QueueBufferInputBuilder
243
Yin-Chia Yeh64ee5f52020-01-02 17:53:18 +0700244 status_t dequeueBuffer(uint32_t w, uint32_t h, uint32_t format, uint32_t usage,
245 IGraphicBufferProducer::DequeueBufferOutput* result) {
246 result->result =
247 mProducer->dequeueBuffer(&result->slot, &result->fence, w, h, format, usage,
248 &result->bufferAge, nullptr);
249 return result->result;
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800250 }
251
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700252 void setupDequeueRequestBuffer(int *slot, sp<Fence> *fence,
253 sp<GraphicBuffer> *buffer)
254 {
Yi Konga03e0442018-07-17 11:16:57 -0700255 ASSERT_TRUE(slot != nullptr);
256 ASSERT_TRUE(fence != nullptr);
257 ASSERT_TRUE(buffer != nullptr);
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700258
259 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
260
Ian Elliottd11b0442017-07-18 11:05:49 -0600261
262 ASSERT_EQ(OK,
263 ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
264 (mProducer->dequeueBuffer(slot, fence, DEFAULT_WIDTH, DEFAULT_HEIGHT,
265 DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS,
266 nullptr, nullptr)));
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700267
268 EXPECT_LE(0, *slot);
269 EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, *slot);
270
271 // Request the buffer (pre-requisite for queueing)
272 ASSERT_OK(mProducer->requestBuffer(*slot, buffer));
273 }
274
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800275private: // hide from test body
Peiyong Lind8460c82020-07-28 16:04:22 -0700276 sp<MockConsumer> mMC;
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800277
278protected: // accessible from test body
279 sp<IGraphicBufferProducer> mProducer;
280 sp<IGraphicBufferConsumer> mConsumer;
281};
282
Jiwen 'Steve' Cai22029502018-02-12 22:26:05 -0800283TEST_P(IGraphicBufferProducerTest, ConnectFirst_ReturnsError) {
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800284 IGraphicBufferProducer::QueueBufferOutput output;
285
286 // NULL output returns BAD_VALUE
287 EXPECT_EQ(BAD_VALUE, mProducer->connect(TEST_TOKEN,
288 TEST_API,
289 TEST_CONTROLLED_BY_APP,
Yi Konga03e0442018-07-17 11:16:57 -0700290 /*output*/nullptr));
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800291
292 // Invalid API returns bad value
293 EXPECT_EQ(BAD_VALUE, mProducer->connect(TEST_TOKEN,
294 /*api*/0xDEADBEEF,
295 TEST_CONTROLLED_BY_APP,
296 &output));
297
298 // TODO: get a token from a dead process somehow
299}
300
Jiwen 'Steve' Cai22029502018-02-12 22:26:05 -0800301TEST_P(IGraphicBufferProducerTest, ConnectAgain_ReturnsError) {
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800302 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
303
304 // Can't connect when there is already a producer connected
305 IGraphicBufferProducer::QueueBufferOutput output;
306 EXPECT_EQ(BAD_VALUE, mProducer->connect(TEST_TOKEN,
307 TEST_API,
308 TEST_CONTROLLED_BY_APP,
309 &output));
310
311 ASSERT_OK(mConsumer->consumerDisconnect());
312 // Can't connect when IGBP is abandoned
Jiwen 'Steve' Cai22029502018-02-12 22:26:05 -0800313 if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
314 // TODO(b/73267953): Make BufferHub honor producer and consumer connection.
315 EXPECT_EQ(NO_INIT, mProducer->connect(TEST_TOKEN,
316 TEST_API,
317 TEST_CONTROLLED_BY_APP,
318 &output));
319 }
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800320}
321
Jiwen 'Steve' Cai22029502018-02-12 22:26:05 -0800322TEST_P(IGraphicBufferProducerTest, Disconnect_Succeeds) {
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800323 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
324
325 ASSERT_OK(mProducer->disconnect(TEST_API));
326}
327
328
Jiwen 'Steve' Cai22029502018-02-12 22:26:05 -0800329TEST_P(IGraphicBufferProducerTest, Disconnect_ReturnsError) {
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800330 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
331
332 // Must disconnect with same API number
333 ASSERT_EQ(BAD_VALUE, mProducer->disconnect(TEST_API_OTHER));
334 // API must not be out of range
335 ASSERT_EQ(BAD_VALUE, mProducer->disconnect(/*api*/0xDEADBEEF));
336
337 // TODO: somehow kill mProducer so that this returns DEAD_OBJECT
338}
339
Jiwen 'Steve' Cai22029502018-02-12 22:26:05 -0800340TEST_P(IGraphicBufferProducerTest, Query_Succeeds) {
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800341 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
342
Dan Stozaf8cebe52015-04-20 12:09:38 -0700343 int32_t value = -1;
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800344 EXPECT_OK(mProducer->query(NATIVE_WINDOW_WIDTH, &value));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700345 EXPECT_EQ(DEFAULT_WIDTH, static_cast<uint32_t>(value));
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800346
347 EXPECT_OK(mProducer->query(NATIVE_WINDOW_HEIGHT, &value));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700348 EXPECT_EQ(DEFAULT_HEIGHT, static_cast<uint32_t>(value));
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800349
350 EXPECT_OK(mProducer->query(NATIVE_WINDOW_FORMAT, &value));
351 EXPECT_EQ(DEFAULT_FORMAT, value);
352
353 EXPECT_OK(mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &value));
354 EXPECT_LE(0, value);
355 EXPECT_GE(BufferQueue::NUM_BUFFER_SLOTS, value);
356
357 EXPECT_OK(mProducer->query(NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &value));
358 EXPECT_FALSE(value); // Can't run behind when we haven't touched the queue
359
360 EXPECT_OK(mProducer->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &value));
361 EXPECT_EQ(DEFAULT_CONSUMER_USAGE_BITS, value);
362
Yin-Chia Yeh64ee5f52020-01-02 17:53:18 +0700363 { // Test the batched version
364 std::vector<int32_t> inputs = {
365 NATIVE_WINDOW_WIDTH,
366 NATIVE_WINDOW_HEIGHT,
367 NATIVE_WINDOW_FORMAT,
368 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
369 NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND,
370 NATIVE_WINDOW_CONSUMER_USAGE_BITS };
371 using QueryOutput = IGraphicBufferProducer::QueryOutput;
372 std::vector<QueryOutput> outputs;
373 EXPECT_OK(mProducer->query(inputs, &outputs));
374 EXPECT_EQ(DEFAULT_WIDTH, static_cast<uint32_t>(outputs[0].value));
375 EXPECT_EQ(DEFAULT_HEIGHT, static_cast<uint32_t>(outputs[1].value));
376 EXPECT_EQ(DEFAULT_FORMAT, outputs[2].value);
377 EXPECT_LE(0, outputs[3].value);
378 EXPECT_FALSE(outputs[4].value);
379 EXPECT_EQ(DEFAULT_CONSUMER_USAGE_BITS, outputs[5].value);
380 for (const QueryOutput& output : outputs) {
381 EXPECT_OK(output.result);
382 }
383 }
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800384}
385
Jiwen 'Steve' Cai22029502018-02-12 22:26:05 -0800386TEST_P(IGraphicBufferProducerTest, Query_ReturnsError) {
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800387 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
388
389 // One past the end of the last 'query' enum value. Update this if we add more enums.
Michael Lentined8ead0c2015-05-19 15:23:43 -0700390 const int NATIVE_WINDOW_QUERY_LAST_OFF_BY_ONE = NATIVE_WINDOW_BUFFER_AGE + 1;
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800391
392 int value;
393 // What was out of range
394 EXPECT_EQ(BAD_VALUE, mProducer->query(/*what*/-1, &value));
395 EXPECT_EQ(BAD_VALUE, mProducer->query(/*what*/0xDEADBEEF, &value));
396 EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_QUERY_LAST_OFF_BY_ONE, &value));
397
398 // Some enums from window.h are 'invalid'
399 EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER, &value));
400 EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_CONCRETE_TYPE, &value));
401 EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_DEFAULT_WIDTH, &value));
402 EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_DEFAULT_HEIGHT, &value));
403 EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_TRANSFORM_HINT, &value));
404 // TODO: Consider documented the above enums as unsupported or make a new enum for IGBP
405
Yin-Chia Yeh64ee5f52020-01-02 17:53:18 +0700406 { // Test the batched version
407 std::vector<int32_t> inputs = {
408 -1,
409 static_cast<int32_t>(0xDEADBEEF),
410 NATIVE_WINDOW_QUERY_LAST_OFF_BY_ONE,
411 NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER,
412 NATIVE_WINDOW_CONCRETE_TYPE,
413 NATIVE_WINDOW_DEFAULT_WIDTH,
414 NATIVE_WINDOW_DEFAULT_HEIGHT,
415 NATIVE_WINDOW_TRANSFORM_HINT};
416 using QueryOutput = IGraphicBufferProducer::QueryOutput;
417 std::vector<QueryOutput> outputs;
418 EXPECT_OK(mProducer->query(inputs, &outputs));
419 for (const QueryOutput& output : outputs) {
420 EXPECT_EQ(BAD_VALUE, output.result);
421 }
422 }
423
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800424 // Value was NULL
Yi Konga03e0442018-07-17 11:16:57 -0700425 EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_FORMAT, /*value*/nullptr));
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800426
427 ASSERT_OK(mConsumer->consumerDisconnect());
428
429 // BQ was abandoned
Jiwen 'Steve' Cai22029502018-02-12 22:26:05 -0800430 if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
431 // TODO(b/73267953): Make BufferHub honor producer and consumer connection.
432 EXPECT_EQ(NO_INIT, mProducer->query(NATIVE_WINDOW_FORMAT, &value));
433 }
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800434
435 // TODO: other things in window.h that are supported by Surface::query
436 // but not by BufferQueue::query
437}
438
439// TODO: queue under more complicated situations not involving just a single buffer
Jiwen 'Steve' Cai22029502018-02-12 22:26:05 -0800440TEST_P(IGraphicBufferProducerTest, Queue_Succeeds) {
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800441 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
442
443 int dequeuedSlot = -1;
444 sp<Fence> dequeuedFence;
445
Ian Elliottd11b0442017-07-18 11:05:49 -0600446 ASSERT_EQ(OK,
447 ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
448 (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence, DEFAULT_WIDTH,
449 DEFAULT_HEIGHT, DEFAULT_FORMAT,
450 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr)));
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800451
452 EXPECT_LE(0, dequeuedSlot);
453 EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, dequeuedSlot);
454
455 // Request the buffer (pre-requisite for queueing)
456 sp<GraphicBuffer> dequeuedBuffer;
457 ASSERT_OK(mProducer->requestBuffer(dequeuedSlot, &dequeuedBuffer));
458
459 // A generic "valid" input
460 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
461 IGraphicBufferProducer::QueueBufferOutput output;
462
463 // Queue the buffer back into the BQ
464 ASSERT_OK(mProducer->queueBuffer(dequeuedSlot, input, &output));
465
466 {
Brian Anderson7c3ba8a2016-07-25 12:48:08 -0700467 EXPECT_EQ(DEFAULT_WIDTH, output.width);
468 EXPECT_EQ(DEFAULT_HEIGHT, output.height);
469 EXPECT_EQ(DEFAULT_TRANSFORM_HINT, output.transformHint);
Jiwen 'Steve' Cai22029502018-02-12 22:26:05 -0800470
Brian Anderson7c3ba8a2016-07-25 12:48:08 -0700471 // Since queueBuffer was called exactly once
Jiwen 'Steve' Cai22029502018-02-12 22:26:05 -0800472 if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
473 // TODO(b/70041889): BufferHubProducer need to support metadata: numPendingBuffers
474 EXPECT_EQ(1u, output.numPendingBuffers);
475 // TODO(b/70041952): BufferHubProducer need to support metadata: nextFrameNumber
476 EXPECT_EQ(2u, output.nextFrameNumber);
477 }
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800478 }
479
480 // Buffer was not in the dequeued state
481 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output));
Yin-Chia Yeh64ee5f52020-01-02 17:53:18 +0700482
483 { // Test batched methods
484 constexpr size_t BATCH_SIZE = 4;
485
486 ASSERT_OK(mProducer->setMaxDequeuedBufferCount(BATCH_SIZE));
487 // Dequeue
488 using DequeueBufferInput = IGraphicBufferProducer::DequeueBufferInput;
489 using DequeueBufferOutput = IGraphicBufferProducer::DequeueBufferOutput;
490 DequeueBufferInput dequeueInput;
491 dequeueInput.width = DEFAULT_WIDTH;
492 dequeueInput.height = DEFAULT_HEIGHT;
493 dequeueInput.format = DEFAULT_FORMAT;
494 dequeueInput.usage = TEST_PRODUCER_USAGE_BITS;
495 dequeueInput.getTimestamps = false;
496 std::vector<DequeueBufferInput> dequeueInputs(BATCH_SIZE, dequeueInput);
497 std::vector<DequeueBufferOutput> dequeueOutputs;
498 EXPECT_OK(mProducer->dequeueBuffers(dequeueInputs, &dequeueOutputs));
499 ASSERT_EQ(dequeueInputs.size(), dequeueOutputs.size());
500
501 // Request
502 std::vector<int32_t> requestInputs;
503 requestInputs.reserve(BATCH_SIZE);
504 for (const DequeueBufferOutput& dequeueOutput : dequeueOutputs) {
505 ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
506 dequeueOutput.result);
507 requestInputs.emplace_back(dequeueOutput.slot);
508 }
509 using RequestBufferOutput = IGraphicBufferProducer::RequestBufferOutput;
510 std::vector<RequestBufferOutput> requestOutputs;
511 EXPECT_OK(mProducer->requestBuffers(requestInputs, &requestOutputs));
512 ASSERT_EQ(requestInputs.size(), requestOutputs.size());
513 for (const RequestBufferOutput& requestOutput : requestOutputs) {
514 EXPECT_OK(requestOutput.result);
515 }
516
517 // Queue
518 using QueueBufferInput = IGraphicBufferProducer::QueueBufferInput;
519 using QueueBufferOutput = IGraphicBufferProducer::QueueBufferOutput;
520 std::vector<QueueBufferInput> queueInputs;
521 queueInputs.reserve(BATCH_SIZE);
522 for (const DequeueBufferOutput& dequeueOutput : dequeueOutputs) {
523 queueInputs.emplace_back(CreateBufferInput()).slot =
524 dequeueOutput.slot;
525 }
526 std::vector<QueueBufferOutput> queueOutputs;
527 EXPECT_OK(mProducer->queueBuffers(queueInputs, &queueOutputs));
528 ASSERT_EQ(queueInputs.size(), queueOutputs.size());
529 for (const QueueBufferOutput& queueOutput : queueOutputs) {
530 EXPECT_OK(queueOutput.result);
531 }
532
533 // Re-queue
534 EXPECT_OK(mProducer->queueBuffers(queueInputs, &queueOutputs));
535 ASSERT_EQ(queueInputs.size(), queueOutputs.size());
536 for (const QueueBufferOutput& queueOutput : queueOutputs) {
537 EXPECT_EQ(BAD_VALUE, queueOutput.result);
538 }
539 }
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800540}
541
Jiwen 'Steve' Cai22029502018-02-12 22:26:05 -0800542TEST_P(IGraphicBufferProducerTest, Queue_ReturnsError) {
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800543 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
544
Yin-Chia Yeh64ee5f52020-01-02 17:53:18 +0700545 using QueueBufferInput = IGraphicBufferProducer::QueueBufferInput;
546 using QueueBufferOutput = IGraphicBufferProducer::QueueBufferOutput;
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800547 // Invalid slot number
548 {
549 // A generic "valid" input
Yin-Chia Yeh64ee5f52020-01-02 17:53:18 +0700550 QueueBufferInput input = CreateBufferInput();
551 QueueBufferOutput output;
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800552
553 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(/*slot*/-1, input, &output));
554 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(/*slot*/0xDEADBEEF, input, &output));
555 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(BufferQueue::NUM_BUFFER_SLOTS,
556 input, &output));
Yin-Chia Yeh64ee5f52020-01-02 17:53:18 +0700557
558 { // Test with the batched version
559 constexpr size_t BATCH_SIZE = 16;
560 input.slot = -1;
561 std::vector<QueueBufferInput> inputs(BATCH_SIZE, input);
562 std::vector<QueueBufferOutput> outputs;
563 EXPECT_OK(mProducer->queueBuffers(inputs, &outputs));
564 ASSERT_EQ(inputs.size(), outputs.size());
565 for (const QueueBufferOutput& output : outputs) {
566 EXPECT_EQ(BAD_VALUE, output.result);
567 }
568 }
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800569 }
570
571 // Slot was not in the dequeued state (all slots start out in Free state)
572 {
Yin-Chia Yeh64ee5f52020-01-02 17:53:18 +0700573 QueueBufferInput input = CreateBufferInput();
574 QueueBufferOutput output;
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800575
576 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(/*slot*/0, input, &output));
Yin-Chia Yeh64ee5f52020-01-02 17:53:18 +0700577
578 { // Test with the batched version
579 constexpr size_t BATCH_SIZE = 16;
580 input.slot = 0;
581 std::vector<QueueBufferInput> inputs(BATCH_SIZE, input);
582 std::vector<QueueBufferOutput> outputs;
583 EXPECT_OK(mProducer->queueBuffers(inputs, &outputs));
584 ASSERT_EQ(inputs.size(), outputs.size());
585 for (const QueueBufferOutput& output : outputs) {
586 EXPECT_EQ(BAD_VALUE, output.result);
587 }
588 }
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800589 }
590
591 // Put the slot into the "dequeued" state for the rest of the test
592 int dequeuedSlot = -1;
593 sp<Fence> dequeuedFence;
594
Ian Elliottd11b0442017-07-18 11:05:49 -0600595 ASSERT_EQ(OK,
596 ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
597 (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence, DEFAULT_WIDTH,
598 DEFAULT_HEIGHT, DEFAULT_FORMAT,
599 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr)));
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800600
601 // Slot was enqueued without requesting a buffer
602 {
Yin-Chia Yeh64ee5f52020-01-02 17:53:18 +0700603 QueueBufferInput input = CreateBufferInput();
604 QueueBufferOutput output;
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800605
606 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output));
Yin-Chia Yeh64ee5f52020-01-02 17:53:18 +0700607
608 { // Test with the batched version
609 constexpr size_t BATCH_SIZE = 16;
610 input.slot = dequeuedSlot;
611 std::vector<QueueBufferInput> inputs(BATCH_SIZE, input);
612 std::vector<QueueBufferOutput> outputs;
613 EXPECT_OK(mProducer->queueBuffers(inputs, &outputs));
614 ASSERT_EQ(inputs.size(), outputs.size());
615 for (const QueueBufferOutput& output : outputs) {
616 EXPECT_EQ(BAD_VALUE, output.result);
617 }
618 }
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800619 }
620
621 // Request the buffer so that the rest of the tests don't fail on earlier checks.
622 sp<GraphicBuffer> dequeuedBuffer;
623 ASSERT_OK(mProducer->requestBuffer(dequeuedSlot, &dequeuedBuffer));
624
625 // Fence was NULL
626 {
Yi Konga03e0442018-07-17 11:16:57 -0700627 sp<Fence> nullFence = nullptr;
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800628
Yin-Chia Yeh64ee5f52020-01-02 17:53:18 +0700629 QueueBufferInput input =
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800630 QueueBufferInputBuilder().setFence(nullFence).build();
Yin-Chia Yeh64ee5f52020-01-02 17:53:18 +0700631 QueueBufferOutput output;
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800632
633 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output));
Yin-Chia Yeh64ee5f52020-01-02 17:53:18 +0700634
635 { // Test with the batched version
636 constexpr size_t BATCH_SIZE = 16;
637 input.slot = dequeuedSlot;
638 std::vector<QueueBufferInput> inputs(BATCH_SIZE, input);
639 std::vector<QueueBufferOutput> outputs;
640 EXPECT_OK(mProducer->queueBuffers(inputs, &outputs));
641 ASSERT_EQ(inputs.size(), outputs.size());
642 for (const QueueBufferOutput& output : outputs) {
643 EXPECT_EQ(BAD_VALUE, output.result);
644 }
645 }
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800646 }
647
648 // Scaling mode was unknown
649 {
650 IGraphicBufferProducer::QueueBufferInput input =
651 QueueBufferInputBuilder().setScalingMode(-1).build();
652 IGraphicBufferProducer::QueueBufferOutput output;
653
654 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output));
655
Yin-Chia Yeh64ee5f52020-01-02 17:53:18 +0700656 { // Test with the batched version
657 constexpr size_t BATCH_SIZE = 16;
658 input.slot = dequeuedSlot;
659 std::vector<QueueBufferInput> inputs(BATCH_SIZE, input);
660 std::vector<QueueBufferOutput> outputs;
661 EXPECT_OK(mProducer->queueBuffers(inputs, &outputs));
662 ASSERT_EQ(inputs.size(), outputs.size());
663 for (const QueueBufferOutput& output : outputs) {
664 EXPECT_EQ(BAD_VALUE, output.result);
665 }
666 }
667
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800668 input = QueueBufferInputBuilder().setScalingMode(0xDEADBEEF).build();
669
670 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output));
Yin-Chia Yeh64ee5f52020-01-02 17:53:18 +0700671
672 { // Test with the batched version
673 constexpr size_t BATCH_SIZE = 16;
674 input.slot = dequeuedSlot;
675 std::vector<QueueBufferInput> inputs(BATCH_SIZE, input);
676 std::vector<QueueBufferOutput> outputs;
677 EXPECT_OK(mProducer->queueBuffers(inputs, &outputs));
678 ASSERT_EQ(inputs.size(), outputs.size());
679 for (const QueueBufferOutput& output : outputs) {
680 EXPECT_EQ(BAD_VALUE, output.result);
681 }
682 }
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800683 }
684
685 // Crop rect is out of bounds of the buffer dimensions
686 {
687 IGraphicBufferProducer::QueueBufferInput input =
688 QueueBufferInputBuilder().setCrop(Rect(DEFAULT_WIDTH + 1, DEFAULT_HEIGHT + 1))
689 .build();
690 IGraphicBufferProducer::QueueBufferOutput output;
691
692 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output));
Yin-Chia Yeh64ee5f52020-01-02 17:53:18 +0700693
694 { // Test with the batched version
695 constexpr size_t BATCH_SIZE = 16;
696 input.slot = dequeuedSlot;
697 std::vector<QueueBufferInput> inputs(BATCH_SIZE, input);
698 std::vector<QueueBufferOutput> outputs;
699 EXPECT_OK(mProducer->queueBuffers(inputs, &outputs));
700 ASSERT_EQ(inputs.size(), outputs.size());
701 for (const QueueBufferOutput& output : outputs) {
702 EXPECT_EQ(BAD_VALUE, output.result);
703 }
704 }
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800705 }
706
707 // Abandon the buffer queue so that the last test fails
708 ASSERT_OK(mConsumer->consumerDisconnect());
709
710 // The buffer queue has been abandoned.
Jiwen 'Steve' Cai22029502018-02-12 22:26:05 -0800711 if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800712 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
713 IGraphicBufferProducer::QueueBufferOutput output;
714
Jiwen 'Steve' Cai22029502018-02-12 22:26:05 -0800715 // TODO(b/73267953): Make BufferHub honor producer and consumer connection.
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800716 EXPECT_EQ(NO_INIT, mProducer->queueBuffer(dequeuedSlot, input, &output));
Yin-Chia Yeh64ee5f52020-01-02 17:53:18 +0700717
718 { // Test with the batched version
719 constexpr size_t BATCH_SIZE = 16;
720 input.slot = dequeuedSlot;
721 std::vector<QueueBufferInput> inputs(BATCH_SIZE, input);
722 std::vector<QueueBufferOutput> outputs;
723 EXPECT_OK(mProducer->queueBuffers(inputs, &outputs));
724 ASSERT_EQ(inputs.size(), outputs.size());
725 for (const QueueBufferOutput& output : outputs) {
726 EXPECT_EQ(NO_INIT, output.result);
727 }
728 }
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800729 }
730}
731
Jiwen 'Steve' Cai22029502018-02-12 22:26:05 -0800732TEST_P(IGraphicBufferProducerTest, CancelBuffer_DoesntCrash) {
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800733 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
734
735 int dequeuedSlot = -1;
736 sp<Fence> dequeuedFence;
737
Ian Elliottd11b0442017-07-18 11:05:49 -0600738 ASSERT_EQ(OK,
739 ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
740 (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence, DEFAULT_WIDTH,
741 DEFAULT_HEIGHT, DEFAULT_FORMAT,
742 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr)));
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800743
744 // No return code, but at least test that it doesn't blow up...
745 // TODO: add a return code
746 mProducer->cancelBuffer(dequeuedSlot, dequeuedFence);
Yin-Chia Yeh64ee5f52020-01-02 17:53:18 +0700747
748 { // Test batched methods
749 constexpr size_t BATCH_SIZE = 4;
750 ASSERT_OK(mProducer->setMaxDequeuedBufferCount(BATCH_SIZE));
751
752 // Dequeue
753 using DequeueBufferInput = IGraphicBufferProducer::DequeueBufferInput;
754 using DequeueBufferOutput = IGraphicBufferProducer::DequeueBufferOutput;
755 DequeueBufferInput dequeueInput;
756 dequeueInput.width = DEFAULT_WIDTH;
757 dequeueInput.height = DEFAULT_HEIGHT;
758 dequeueInput.format = DEFAULT_FORMAT;
759 dequeueInput.usage = TEST_PRODUCER_USAGE_BITS;
760 dequeueInput.getTimestamps = false;
761 std::vector<DequeueBufferInput> dequeueInputs(BATCH_SIZE, dequeueInput);
762 std::vector<DequeueBufferOutput> dequeueOutputs;
763 EXPECT_OK(mProducer->dequeueBuffers(dequeueInputs, &dequeueOutputs));
764 ASSERT_EQ(dequeueInputs.size(), dequeueOutputs.size());
765
766 // Cancel
767 using CancelBufferInput = IGraphicBufferProducer::CancelBufferInput;
768 std::vector<CancelBufferInput> cancelInputs;
769 cancelInputs.reserve(BATCH_SIZE);
770 for (const DequeueBufferOutput& dequeueOutput : dequeueOutputs) {
771 ASSERT_EQ(OK,
772 ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
773 dequeueOutput.result);
774 CancelBufferInput& cancelInput = cancelInputs.emplace_back();
775 cancelInput.slot = dequeueOutput.slot;
776 cancelInput.fence = dequeueOutput.fence;
777 }
778 std::vector<status_t> cancelOutputs;
779 EXPECT_OK(mProducer->cancelBuffers(cancelInputs, &cancelOutputs));
780 ASSERT_EQ(cancelInputs.size(), cancelOutputs.size());
781 for (status_t result : cancelOutputs) {
782 EXPECT_OK(result);
783 }
784 }
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800785}
786
Jiwen 'Steve' Cai22029502018-02-12 22:26:05 -0800787TEST_P(IGraphicBufferProducerTest, SetMaxDequeuedBufferCount_Succeeds) {
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700788 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
Pablo Ceballosfa455352015-08-12 17:47:47 -0700789 int minUndequeuedBuffers;
790 ASSERT_OK(mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
791 &minUndequeuedBuffers));
792
793 const int minBuffers = 1;
794 const int maxBuffers = BufferQueue::NUM_BUFFER_SLOTS - minUndequeuedBuffers;
795
796 ASSERT_OK(mProducer->setAsyncMode(false)) << "async mode: " << false;
797 ASSERT_OK(mProducer->setMaxDequeuedBufferCount(minBuffers))
798 << "bufferCount: " << minBuffers;
799
Pablo Ceballosfa455352015-08-12 17:47:47 -0700800 // Should now be able to dequeue up to minBuffers times
Yin-Chia Yeh64ee5f52020-01-02 17:53:18 +0700801 IGraphicBufferProducer::DequeueBufferOutput result;
Pablo Ceballosfa455352015-08-12 17:47:47 -0700802 for (int i = 0; i < minBuffers; ++i) {
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700803 EXPECT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700804 (dequeueBuffer(DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
Yin-Chia Yeh64ee5f52020-01-02 17:53:18 +0700805 TEST_PRODUCER_USAGE_BITS, &result)))
Pablo Ceballosfa455352015-08-12 17:47:47 -0700806 << "iteration: " << i << ", slot: " << result.slot;
Pablo Ceballosfa455352015-08-12 17:47:47 -0700807 }
808
809 ASSERT_OK(mProducer->setMaxDequeuedBufferCount(maxBuffers));
810
Pablo Ceballos72daab62015-12-07 16:38:43 -0800811 // queue the first buffer to enable max dequeued buffer count checking
812 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
813 IGraphicBufferProducer::QueueBufferOutput output;
814 sp<GraphicBuffer> buffer;
815 ASSERT_OK(mProducer->requestBuffer(result.slot, &buffer));
816 ASSERT_OK(mProducer->queueBuffer(result.slot, input, &output));
817
Pablo Ceballosfa455352015-08-12 17:47:47 -0700818 // Should now be able to dequeue up to maxBuffers times
Pablo Ceballos72daab62015-12-07 16:38:43 -0800819 int dequeuedSlot = -1;
820 sp<Fence> dequeuedFence;
Pablo Ceballosfa455352015-08-12 17:47:47 -0700821 for (int i = 0; i < maxBuffers; ++i) {
Ian Elliottd11b0442017-07-18 11:05:49 -0600822 EXPECT_EQ(OK,
823 ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
824 (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence, DEFAULT_WIDTH,
825 DEFAULT_HEIGHT, DEFAULT_FORMAT,
826 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr)))
Pablo Ceballosfa455352015-08-12 17:47:47 -0700827 << "iteration: " << i << ", slot: " << dequeuedSlot;
828 }
Pablo Ceballos72daab62015-12-07 16:38:43 -0800829
830 // Cancel a buffer, so we can decrease the buffer count
831 ASSERT_OK(mProducer->cancelBuffer(dequeuedSlot, dequeuedFence));
832
833 // Should now be able to decrease the max dequeued count by 1
834 ASSERT_OK(mProducer->setMaxDequeuedBufferCount(maxBuffers-1));
Pablo Ceballosfa455352015-08-12 17:47:47 -0700835}
836
Jiwen 'Steve' Cai22029502018-02-12 22:26:05 -0800837TEST_P(IGraphicBufferProducerTest, SetMaxDequeuedBufferCount_Fails) {
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700838 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
Pablo Ceballosfa455352015-08-12 17:47:47 -0700839 int minUndequeuedBuffers;
840 ASSERT_OK(mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
841 &minUndequeuedBuffers));
842
843 const int minBuffers = 1;
844 const int maxBuffers = BufferQueue::NUM_BUFFER_SLOTS - minUndequeuedBuffers;
845
846 ASSERT_OK(mProducer->setAsyncMode(false)) << "async mode: " << false;
847 // Buffer count was out of range
848 EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(0))
849 << "bufferCount: " << 0;
850 EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(maxBuffers + 1))
851 << "bufferCount: " << maxBuffers + 1;
852
Pablo Ceballos72daab62015-12-07 16:38:43 -0800853 // Set max dequeue count to 2
854 ASSERT_OK(mProducer->setMaxDequeuedBufferCount(2));
855 // Dequeue 2 buffers
856 int dequeuedSlot = -1;
857 sp<Fence> dequeuedFence;
858 for (int i = 0; i < 2; i++) {
Ian Elliottd11b0442017-07-18 11:05:49 -0600859 ASSERT_EQ(OK,
860 ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
861 (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence, DEFAULT_WIDTH,
862 DEFAULT_HEIGHT, DEFAULT_FORMAT,
863 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr)))
Pablo Ceballosfa455352015-08-12 17:47:47 -0700864 << "slot: " << dequeuedSlot;
865 }
866
Pablo Ceballos72daab62015-12-07 16:38:43 -0800867 // Client has too many buffers dequeued
868 EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(1))
Pablo Ceballosfa455352015-08-12 17:47:47 -0700869 << "bufferCount: " << minBuffers;
870
871 // Abandon buffer queue
872 ASSERT_OK(mConsumer->consumerDisconnect());
873
874 // Fail because the buffer queue was abandoned
Jiwen 'Steve' Cai22029502018-02-12 22:26:05 -0800875 if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
876 // TODO(b/73267953): Make BufferHub honor producer and consumer connection.
877 EXPECT_EQ(NO_INIT, mProducer->setMaxDequeuedBufferCount(minBuffers))
878 << "bufferCount: " << minBuffers;
879 }
Pablo Ceballosfa455352015-08-12 17:47:47 -0700880}
881
Jiwen 'Steve' Cai22029502018-02-12 22:26:05 -0800882TEST_P(IGraphicBufferProducerTest, SetAsyncMode_Succeeds) {
883 if (GetParam() == USE_BUFFER_HUB_PRODUCER) {
884 // TODO(b/36724099): Add support for BufferHubProducer::setAsyncMode(true)
885 return;
886 }
887
Pablo Ceballosfa455352015-08-12 17:47:47 -0700888 ASSERT_OK(mConsumer->setMaxAcquiredBufferCount(1)) << "maxAcquire: " << 1;
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700889 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
Pablo Ceballosfa455352015-08-12 17:47:47 -0700890 ASSERT_OK(mProducer->setAsyncMode(true)) << "async mode: " << true;
891 ASSERT_OK(mProducer->setMaxDequeuedBufferCount(1)) << "maxDequeue: " << 1;
892
893 int dequeuedSlot = -1;
894 sp<Fence> dequeuedFence;
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700895 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
Pablo Ceballosfa455352015-08-12 17:47:47 -0700896 IGraphicBufferProducer::QueueBufferOutput output;
897 sp<GraphicBuffer> dequeuedBuffer;
898
899 // Should now be able to queue/dequeue as many buffers as we want without
900 // blocking
901 for (int i = 0; i < 5; ++i) {
Ian Elliottd11b0442017-07-18 11:05:49 -0600902 ASSERT_EQ(OK,
903 ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
904 (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence, DEFAULT_WIDTH,
905 DEFAULT_HEIGHT, DEFAULT_FORMAT,
906 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr)))
Brian Anderson7c3ba8a2016-07-25 12:48:08 -0700907 << "slot : " << dequeuedSlot;
Pablo Ceballosfa455352015-08-12 17:47:47 -0700908 ASSERT_OK(mProducer->requestBuffer(dequeuedSlot, &dequeuedBuffer));
909 ASSERT_OK(mProducer->queueBuffer(dequeuedSlot, input, &output));
910 }
911}
912
Jiwen 'Steve' Cai22029502018-02-12 22:26:05 -0800913TEST_P(IGraphicBufferProducerTest, SetAsyncMode_Fails) {
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700914 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
Pablo Ceballosfa455352015-08-12 17:47:47 -0700915 // Prerequisite to fail out a valid setBufferCount call
916 {
917 int dequeuedSlot = -1;
918 sp<Fence> dequeuedFence;
919
Ian Elliottd11b0442017-07-18 11:05:49 -0600920 ASSERT_EQ(OK,
921 ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
922 (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence, DEFAULT_WIDTH,
923 DEFAULT_HEIGHT, DEFAULT_FORMAT,
924 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr)))
Brian Anderson7c3ba8a2016-07-25 12:48:08 -0700925 << "slot: " << dequeuedSlot;
Pablo Ceballosfa455352015-08-12 17:47:47 -0700926 }
927
Pablo Ceballosfa455352015-08-12 17:47:47 -0700928 // Abandon buffer queue
929 ASSERT_OK(mConsumer->consumerDisconnect());
930
931 // Fail because the buffer queue was abandoned
Jiwen 'Steve' Cai22029502018-02-12 22:26:05 -0800932 if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
933 // TODO(b/36724099): Make BufferHub honor producer and consumer connection.
934 EXPECT_EQ(NO_INIT, mProducer->setAsyncMode(false)) << "asyncMode: " << false;
935 }
Pablo Ceballosfa455352015-08-12 17:47:47 -0700936}
937
Jiwen 'Steve' Cai22029502018-02-12 22:26:05 -0800938TEST_P(IGraphicBufferProducerTest,
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700939 DisconnectedProducerReturnsError_dequeueBuffer) {
940 int slot = -1;
941 sp<Fence> fence;
942
Ian Elliottd11b0442017-07-18 11:05:49 -0600943 ASSERT_EQ(NO_INIT,
944 mProducer->dequeueBuffer(&slot, &fence, DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
945 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr));
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700946}
947
Jiwen 'Steve' Cai22029502018-02-12 22:26:05 -0800948TEST_P(IGraphicBufferProducerTest,
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700949 DisconnectedProducerReturnsError_detachNextBuffer) {
950 sp<Fence> fence;
951 sp<GraphicBuffer> buffer;
952
Jiwen 'Steve' Cai42875352018-04-30 17:55:11 -0700953 ASSERT_EQ(NO_INIT, mProducer->detachNextBuffer(&buffer, &fence));
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700954}
955
Jiwen 'Steve' Cai22029502018-02-12 22:26:05 -0800956TEST_P(IGraphicBufferProducerTest,
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700957 DisconnectedProducerReturnsError_requestBuffer) {
958 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
959
960 int slot = -1;
961 sp<Fence> fence;
962
Ian Elliottd11b0442017-07-18 11:05:49 -0600963 ASSERT_EQ(OK,
964 ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
965 (mProducer->dequeueBuffer(&slot, &fence, DEFAULT_WIDTH, DEFAULT_HEIGHT,
966 DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS,
967 nullptr, nullptr)));
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700968
969 EXPECT_LE(0, slot);
970 EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, slot);
971
972 ASSERT_OK(mProducer->disconnect(TEST_API));
973
974 sp<GraphicBuffer> buffer;
975
976 ASSERT_EQ(NO_INIT, mProducer->requestBuffer(slot, &buffer));
977}
978
979
Jiwen 'Steve' Cai22029502018-02-12 22:26:05 -0800980TEST_P(IGraphicBufferProducerTest,
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700981 DisconnectedProducerReturnsError_detachBuffer) {
982 int slot = -1;
983 sp<Fence> fence;
984 sp<GraphicBuffer> buffer;
985
986 setupDequeueRequestBuffer(&slot, &fence, &buffer);
987
988 ASSERT_OK(mProducer->disconnect(TEST_API));
989
Jiwen 'Steve' Cai42875352018-04-30 17:55:11 -0700990 ASSERT_EQ(NO_INIT, mProducer->detachBuffer(slot));
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700991}
992
Jiwen 'Steve' Cai22029502018-02-12 22:26:05 -0800993TEST_P(IGraphicBufferProducerTest,
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700994 DisconnectedProducerReturnsError_queueBuffer) {
995 int slot = -1;
996 sp<Fence> fence;
997 sp<GraphicBuffer> buffer;
998
999 setupDequeueRequestBuffer(&slot, &fence, &buffer);
1000
1001 ASSERT_OK(mProducer->disconnect(TEST_API));
1002
1003 // A generic "valid" input
1004 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
1005 IGraphicBufferProducer::QueueBufferOutput output;
1006
1007 ASSERT_EQ(NO_INIT, mProducer->queueBuffer(slot, input, &output));
1008}
1009
Jiwen 'Steve' Cai22029502018-02-12 22:26:05 -08001010TEST_P(IGraphicBufferProducerTest,
Pablo Ceballos583b1b32015-09-03 18:23:52 -07001011 DisconnectedProducerReturnsError_cancelBuffer) {
1012 int slot = -1;
1013 sp<Fence> fence;
1014 sp<GraphicBuffer> buffer;
1015
1016 setupDequeueRequestBuffer(&slot, &fence, &buffer);
1017
1018 ASSERT_OK(mProducer->disconnect(TEST_API));
1019
1020 ASSERT_EQ(NO_INIT, mProducer->cancelBuffer(slot, fence));
1021}
1022
Jiwen 'Steve' Cai22029502018-02-12 22:26:05 -08001023TEST_P(IGraphicBufferProducerTest,
Pablo Ceballos583b1b32015-09-03 18:23:52 -07001024 DisconnectedProducerReturnsError_attachBuffer) {
1025 int slot = -1;
1026 sp<Fence> fence;
1027 sp<GraphicBuffer> buffer;
1028
1029 setupDequeueRequestBuffer(&slot, &fence, &buffer);
Jiwen 'Steve' Cai42875352018-04-30 17:55:11 -07001030 ASSERT_TRUE(buffer != nullptr);
Pablo Ceballos583b1b32015-09-03 18:23:52 -07001031
Jiwen 'Steve' Cai42875352018-04-30 17:55:11 -07001032 ASSERT_OK(mProducer->detachBuffer(slot));
1033 EXPECT_OK(buffer->initCheck());
1034
Pablo Ceballos583b1b32015-09-03 18:23:52 -07001035 ASSERT_OK(mProducer->disconnect(TEST_API));
1036
Jiwen 'Steve' Cai57ae3ee2018-05-03 17:51:52 -07001037 ASSERT_EQ(NO_INIT, mProducer->attachBuffer(&slot, buffer));
1038}
1039
1040TEST_P(IGraphicBufferProducerTest, DetachThenAttach_Succeeds) {
1041 int slot = -1;
1042 sp<Fence> fence;
1043 sp<GraphicBuffer> buffer;
1044
1045 setupDequeueRequestBuffer(&slot, &fence, &buffer);
1046 ASSERT_TRUE(buffer != nullptr);
1047
1048 ASSERT_OK(mProducer->detachBuffer(slot));
1049 EXPECT_OK(buffer->initCheck());
1050
Jiwen 'Steve' Cai57ae3ee2018-05-03 17:51:52 -07001051 EXPECT_OK(mProducer->attachBuffer(&slot, buffer));
Jiwen 'Steve' Cai57ae3ee2018-05-03 17:51:52 -07001052 EXPECT_OK(buffer->initCheck());
Yin-Chia Yeh64ee5f52020-01-02 17:53:18 +07001053
1054 ASSERT_OK(mProducer->detachBuffer(slot));
1055
1056 { // Test batched methods
1057 constexpr size_t BATCH_SIZE = 4;
1058 ASSERT_OK(mProducer->setMaxDequeuedBufferCount(BATCH_SIZE));
1059
1060 // Dequeue
1061 using DequeueBufferInput = IGraphicBufferProducer::DequeueBufferInput;
1062 using DequeueBufferOutput = IGraphicBufferProducer::DequeueBufferOutput;
1063 DequeueBufferInput dequeueInput;
1064 dequeueInput.width = DEFAULT_WIDTH;
1065 dequeueInput.height = DEFAULT_HEIGHT;
1066 dequeueInput.format = DEFAULT_FORMAT;
1067 dequeueInput.usage = TEST_PRODUCER_USAGE_BITS;
1068 dequeueInput.getTimestamps = false;
1069 std::vector<DequeueBufferInput> dequeueInputs(BATCH_SIZE, dequeueInput);
1070 std::vector<DequeueBufferOutput> dequeueOutputs;
1071 EXPECT_OK(mProducer->dequeueBuffers(dequeueInputs, &dequeueOutputs));
1072 ASSERT_EQ(dequeueInputs.size(), dequeueOutputs.size());
1073
1074 // Request
1075 std::vector<int32_t> requestInputs;
1076 requestInputs.reserve(BATCH_SIZE);
1077 for (const DequeueBufferOutput& dequeueOutput : dequeueOutputs) {
1078 ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
1079 dequeueOutput.result);
1080 requestInputs.emplace_back(dequeueOutput.slot);
1081 }
1082 using RequestBufferOutput = IGraphicBufferProducer::RequestBufferOutput;
1083 std::vector<RequestBufferOutput> requestOutputs;
1084 EXPECT_OK(mProducer->requestBuffers(requestInputs, &requestOutputs));
1085 ASSERT_EQ(requestInputs.size(), requestOutputs.size());
1086 for (const RequestBufferOutput& requestOutput : requestOutputs) {
1087 EXPECT_OK(requestOutput.result);
1088 }
1089
1090 // Detach
1091 std::vector<int32_t> detachInputs;
1092 detachInputs.reserve(BATCH_SIZE);
1093 for (const DequeueBufferOutput& dequeueOutput : dequeueOutputs) {
1094 detachInputs.emplace_back(dequeueOutput.slot);
1095 }
1096 std::vector<status_t> detachOutputs;
1097 EXPECT_OK(mProducer->detachBuffers(detachInputs, &detachOutputs));
1098 ASSERT_EQ(detachInputs.size(), detachOutputs.size());
1099 for (status_t result : detachOutputs) {
1100 EXPECT_OK(result);
1101 }
1102
1103 // Attach
1104 using AttachBufferOutput = IGraphicBufferProducer::AttachBufferOutput;
1105 std::vector<sp<GraphicBuffer>> attachInputs;
1106 attachInputs.reserve(BATCH_SIZE);
1107 for (const RequestBufferOutput& requestOutput : requestOutputs) {
1108 attachInputs.emplace_back(requestOutput.buffer);
1109 }
1110 std::vector<AttachBufferOutput> attachOutputs;
1111 EXPECT_OK(mProducer->attachBuffers(attachInputs, &attachOutputs));
1112 ASSERT_EQ(attachInputs.size(), attachOutputs.size());
1113 for (const AttachBufferOutput& attachOutput : attachOutputs) {
1114 EXPECT_OK(attachOutput.result);
1115 EXPECT_NE(-1, attachOutput.slot);
1116 }
1117 }
Pablo Ceballos583b1b32015-09-03 18:23:52 -07001118}
1119
Jiwen 'Steve' Cai22029502018-02-12 22:26:05 -08001120#if USE_BUFFER_HUB_AS_BUFFER_QUEUE
1121INSTANTIATE_TEST_CASE_P(IGraphicBufferProducerBackends, IGraphicBufferProducerTest,
1122 ::testing::Values(USE_BUFFER_QUEUE_PRODUCER, USE_BUFFER_HUB_PRODUCER));
1123#else
1124// TODO(b/70046255): Remove the #ifdef here and always tests both backends once BufferHubQueue can
1125// pass all existing libgui tests.
1126INSTANTIATE_TEST_CASE_P(IGraphicBufferProducerBackends, IGraphicBufferProducerTest,
1127 ::testing::Values(USE_BUFFER_QUEUE_PRODUCER));
1128#endif
1129
Igor Murashkin7ea777f2013-11-18 16:58:36 -08001130} // namespace android