BufferQueue_test.cpp revision 958f501189a29e53767f41bc8172e4af8d1ce2bf
1/* 2 * Copyright (C) 2012 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 "BufferQueue_test" 18//#define LOG_NDEBUG 0 19 20#include <gui/BufferItem.h> 21#include <gui/BufferQueue.h> 22#include <gui/IProducerListener.h> 23 24#include <ui/GraphicBuffer.h> 25 26#include <binder/IPCThreadState.h> 27#include <binder/IServiceManager.h> 28#include <binder/ProcessState.h> 29 30#include <utils/String8.h> 31#include <utils/threads.h> 32 33#include <gtest/gtest.h> 34 35namespace android { 36 37class BufferQueueTest : public ::testing::Test { 38 39public: 40protected: 41 BufferQueueTest() { 42 const ::testing::TestInfo* const testInfo = 43 ::testing::UnitTest::GetInstance()->current_test_info(); 44 ALOGV("Begin test: %s.%s", testInfo->test_case_name(), 45 testInfo->name()); 46 } 47 48 ~BufferQueueTest() { 49 const ::testing::TestInfo* const testInfo = 50 ::testing::UnitTest::GetInstance()->current_test_info(); 51 ALOGV("End test: %s.%s", testInfo->test_case_name(), 52 testInfo->name()); 53 } 54 55 void GetMinUndequeuedBufferCount(int* bufferCount) { 56 ASSERT_TRUE(bufferCount != NULL); 57 ASSERT_EQ(OK, mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, 58 bufferCount)); 59 ASSERT_GE(*bufferCount, 0); 60 } 61 62 void createBufferQueue() { 63 BufferQueue::createBufferQueue(&mProducer, &mConsumer); 64 } 65 66 sp<IGraphicBufferProducer> mProducer; 67 sp<IGraphicBufferConsumer> mConsumer; 68}; 69 70struct DummyConsumer : public BnConsumerListener { 71 virtual void onFrameAvailable(const BufferItem& /* item */) {} 72 virtual void onBuffersReleased() {} 73 virtual void onSidebandStreamChanged() {} 74}; 75 76static const uint32_t TEST_DATA = 0x12345678u; 77 78// XXX: Tests that fork a process to hold the BufferQueue must run before tests 79// that use a local BufferQueue, or else Binder will get unhappy 80TEST_F(BufferQueueTest, BufferQueueInAnotherProcess) { 81 const String16 PRODUCER_NAME = String16("BQTestProducer"); 82 const String16 CONSUMER_NAME = String16("BQTestConsumer"); 83 84 pid_t forkPid = fork(); 85 ASSERT_NE(forkPid, -1); 86 87 if (forkPid == 0) { 88 // Child process 89 sp<IGraphicBufferProducer> producer; 90 sp<IGraphicBufferConsumer> consumer; 91 BufferQueue::createBufferQueue(&producer, &consumer); 92 sp<IServiceManager> serviceManager = defaultServiceManager(); 93 serviceManager->addService(PRODUCER_NAME, IInterface::asBinder(producer)); 94 serviceManager->addService(CONSUMER_NAME, IInterface::asBinder(consumer)); 95 ProcessState::self()->startThreadPool(); 96 IPCThreadState::self()->joinThreadPool(); 97 LOG_ALWAYS_FATAL("Shouldn't be here"); 98 } 99 100 sp<IServiceManager> serviceManager = defaultServiceManager(); 101 sp<IBinder> binderProducer = 102 serviceManager->getService(PRODUCER_NAME); 103 mProducer = interface_cast<IGraphicBufferProducer>(binderProducer); 104 EXPECT_TRUE(mProducer != NULL); 105 sp<IBinder> binderConsumer = 106 serviceManager->getService(CONSUMER_NAME); 107 mConsumer = interface_cast<IGraphicBufferConsumer>(binderConsumer); 108 EXPECT_TRUE(mConsumer != NULL); 109 110 sp<DummyConsumer> dc(new DummyConsumer); 111 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false)); 112 IGraphicBufferProducer::QueueBufferOutput output; 113 ASSERT_EQ(OK, 114 mProducer->connect(NULL, NATIVE_WINDOW_API_CPU, false, &output)); 115 116 int slot; 117 sp<Fence> fence; 118 sp<GraphicBuffer> buffer; 119 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, 120 mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0, 121 GRALLOC_USAGE_SW_WRITE_OFTEN)); 122 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer)); 123 124 uint32_t* dataIn; 125 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN, 126 reinterpret_cast<void**>(&dataIn))); 127 *dataIn = TEST_DATA; 128 ASSERT_EQ(OK, buffer->unlock()); 129 130 IGraphicBufferProducer::QueueBufferInput input(0, false, 131 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1), 132 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE); 133 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output)); 134 135 BufferItem item; 136 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0)); 137 138 uint32_t* dataOut; 139 ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, 140 reinterpret_cast<void**>(&dataOut))); 141 ASSERT_EQ(*dataOut, TEST_DATA); 142 ASSERT_EQ(OK, item.mGraphicBuffer->unlock()); 143} 144 145TEST_F(BufferQueueTest, AcquireBuffer_ExceedsMaxAcquireCount_Fails) { 146 createBufferQueue(); 147 sp<DummyConsumer> dc(new DummyConsumer); 148 mConsumer->consumerConnect(dc, false); 149 IGraphicBufferProducer::QueueBufferOutput qbo; 150 mProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false, 151 &qbo); 152 mProducer->setBufferCount(4); 153 154 int slot; 155 sp<Fence> fence; 156 sp<GraphicBuffer> buf; 157 IGraphicBufferProducer::QueueBufferInput qbi(0, false, 158 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1), 159 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE); 160 BufferItem item; 161 162 for (int i = 0; i < 2; i++) { 163 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, 164 mProducer->dequeueBuffer(&slot, &fence, false, 1, 1, 0, 165 GRALLOC_USAGE_SW_READ_OFTEN)); 166 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf)); 167 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo)); 168 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0)); 169 } 170 171 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, 172 mProducer->dequeueBuffer(&slot, &fence, false, 1, 1, 0, 173 GRALLOC_USAGE_SW_READ_OFTEN)); 174 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf)); 175 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo)); 176 177 // Acquire the third buffer, which should fail. 178 ASSERT_EQ(INVALID_OPERATION, mConsumer->acquireBuffer(&item, 0)); 179} 180 181TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithIllegalValues_ReturnsError) { 182 createBufferQueue(); 183 sp<DummyConsumer> dc(new DummyConsumer); 184 mConsumer->consumerConnect(dc, false); 185 186 int minBufferCount; 187 ASSERT_NO_FATAL_FAILURE(GetMinUndequeuedBufferCount(&minBufferCount)); 188 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount( 189 minBufferCount - 1)); 190 191 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(0)); 192 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(-3)); 193 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount( 194 BufferQueue::MAX_MAX_ACQUIRED_BUFFERS+1)); 195 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(100)); 196} 197 198TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithLegalValues_Succeeds) { 199 createBufferQueue(); 200 sp<DummyConsumer> dc(new DummyConsumer); 201 mConsumer->consumerConnect(dc, false); 202 203 int minBufferCount; 204 ASSERT_NO_FATAL_FAILURE(GetMinUndequeuedBufferCount(&minBufferCount)); 205 206 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1)); 207 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(2)); 208 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(minBufferCount)); 209 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount( 210 BufferQueue::MAX_MAX_ACQUIRED_BUFFERS)); 211} 212 213TEST_F(BufferQueueTest, DetachAndReattachOnProducerSide) { 214 createBufferQueue(); 215 sp<DummyConsumer> dc(new DummyConsumer); 216 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false)); 217 IGraphicBufferProducer::QueueBufferOutput output; 218 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener, 219 NATIVE_WINDOW_API_CPU, false, &output)); 220 221 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(-1)); // Index too low 222 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer( 223 BufferQueueDefs::NUM_BUFFER_SLOTS)); // Index too high 224 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(0)); // Not dequeued 225 226 int slot; 227 sp<Fence> fence; 228 sp<GraphicBuffer> buffer; 229 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, 230 mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0, 231 GRALLOC_USAGE_SW_WRITE_OFTEN)); 232 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(slot)); // Not requested 233 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer)); 234 ASSERT_EQ(OK, mProducer->detachBuffer(slot)); 235 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(slot)); // Not dequeued 236 237 sp<GraphicBuffer> safeToClobberBuffer; 238 // Can no longer request buffer from this slot 239 ASSERT_EQ(BAD_VALUE, mProducer->requestBuffer(slot, &safeToClobberBuffer)); 240 241 uint32_t* dataIn; 242 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN, 243 reinterpret_cast<void**>(&dataIn))); 244 *dataIn = TEST_DATA; 245 ASSERT_EQ(OK, buffer->unlock()); 246 247 int newSlot; 248 ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(NULL, safeToClobberBuffer)); 249 ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(&newSlot, NULL)); 250 251 ASSERT_EQ(OK, mProducer->attachBuffer(&newSlot, buffer)); 252 IGraphicBufferProducer::QueueBufferInput input(0, false, 253 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1), 254 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE); 255 ASSERT_EQ(OK, mProducer->queueBuffer(newSlot, input, &output)); 256 257 BufferItem item; 258 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0))); 259 260 uint32_t* dataOut; 261 ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, 262 reinterpret_cast<void**>(&dataOut))); 263 ASSERT_EQ(*dataOut, TEST_DATA); 264 ASSERT_EQ(OK, item.mGraphicBuffer->unlock()); 265} 266 267TEST_F(BufferQueueTest, DetachAndReattachOnConsumerSide) { 268 createBufferQueue(); 269 sp<DummyConsumer> dc(new DummyConsumer); 270 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false)); 271 IGraphicBufferProducer::QueueBufferOutput output; 272 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener, 273 NATIVE_WINDOW_API_CPU, false, &output)); 274 275 int slot; 276 sp<Fence> fence; 277 sp<GraphicBuffer> buffer; 278 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, 279 mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0, 280 GRALLOC_USAGE_SW_WRITE_OFTEN)); 281 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer)); 282 IGraphicBufferProducer::QueueBufferInput input(0, false, 283 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1), 284 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE); 285 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output)); 286 287 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(-1)); // Index too low 288 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer( 289 BufferQueueDefs::NUM_BUFFER_SLOTS)); // Index too high 290 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(0)); // Not acquired 291 292 BufferItem item; 293 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0))); 294 295 ASSERT_EQ(OK, mConsumer->detachBuffer(item.mBuf)); 296 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(item.mBuf)); // Not acquired 297 298 uint32_t* dataIn; 299 ASSERT_EQ(OK, item.mGraphicBuffer->lock( 300 GraphicBuffer::USAGE_SW_WRITE_OFTEN, 301 reinterpret_cast<void**>(&dataIn))); 302 *dataIn = TEST_DATA; 303 ASSERT_EQ(OK, item.mGraphicBuffer->unlock()); 304 305 int newSlot; 306 sp<GraphicBuffer> safeToClobberBuffer; 307 ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(NULL, safeToClobberBuffer)); 308 ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(&newSlot, NULL)); 309 ASSERT_EQ(OK, mConsumer->attachBuffer(&newSlot, item.mGraphicBuffer)); 310 311 ASSERT_EQ(OK, mConsumer->releaseBuffer(newSlot, 0, EGL_NO_DISPLAY, 312 EGL_NO_SYNC_KHR, Fence::NO_FENCE)); 313 314 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, 315 mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0, 316 GRALLOC_USAGE_SW_WRITE_OFTEN)); 317 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer)); 318 319 uint32_t* dataOut; 320 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, 321 reinterpret_cast<void**>(&dataOut))); 322 ASSERT_EQ(*dataOut, TEST_DATA); 323 ASSERT_EQ(OK, buffer->unlock()); 324} 325 326TEST_F(BufferQueueTest, MoveFromConsumerToProducer) { 327 createBufferQueue(); 328 sp<DummyConsumer> dc(new DummyConsumer); 329 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false)); 330 IGraphicBufferProducer::QueueBufferOutput output; 331 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener, 332 NATIVE_WINDOW_API_CPU, false, &output)); 333 334 int slot; 335 sp<Fence> fence; 336 sp<GraphicBuffer> buffer; 337 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, 338 mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0, 339 GRALLOC_USAGE_SW_WRITE_OFTEN)); 340 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer)); 341 342 uint32_t* dataIn; 343 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN, 344 reinterpret_cast<void**>(&dataIn))); 345 *dataIn = TEST_DATA; 346 ASSERT_EQ(OK, buffer->unlock()); 347 348 IGraphicBufferProducer::QueueBufferInput input(0, false, 349 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1), 350 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE); 351 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output)); 352 353 BufferItem item; 354 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0))); 355 ASSERT_EQ(OK, mConsumer->detachBuffer(item.mBuf)); 356 357 int newSlot; 358 ASSERT_EQ(OK, mProducer->attachBuffer(&newSlot, item.mGraphicBuffer)); 359 ASSERT_EQ(OK, mProducer->queueBuffer(newSlot, input, &output)); 360 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0))); 361 362 uint32_t* dataOut; 363 ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, 364 reinterpret_cast<void**>(&dataOut))); 365 ASSERT_EQ(*dataOut, TEST_DATA); 366 ASSERT_EQ(OK, item.mGraphicBuffer->unlock()); 367} 368 369TEST_F(BufferQueueTest, TestDisallowingAllocation) { 370 createBufferQueue(); 371 sp<DummyConsumer> dc(new DummyConsumer); 372 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true)); 373 IGraphicBufferProducer::QueueBufferOutput output; 374 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener, 375 NATIVE_WINDOW_API_CPU, true, &output)); 376 377 static const uint32_t WIDTH = 320; 378 static const uint32_t HEIGHT = 240; 379 380 ASSERT_EQ(OK, mConsumer->setDefaultBufferSize(WIDTH, HEIGHT)); 381 382 int slot; 383 sp<Fence> fence; 384 sp<GraphicBuffer> buffer; 385 // This should return an error since it would require an allocation 386 ASSERT_EQ(OK, mProducer->allowAllocation(false)); 387 ASSERT_EQ(WOULD_BLOCK, mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 388 0, GRALLOC_USAGE_SW_WRITE_OFTEN)); 389 390 // This should succeed, now that we've lifted the prohibition 391 ASSERT_EQ(OK, mProducer->allowAllocation(true)); 392 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, 393 mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0, 394 GRALLOC_USAGE_SW_WRITE_OFTEN)); 395 396 // Release the previous buffer back to the BufferQueue 397 mProducer->cancelBuffer(slot, fence); 398 399 // This should fail since we're requesting a different size 400 ASSERT_EQ(OK, mProducer->allowAllocation(false)); 401 ASSERT_EQ(WOULD_BLOCK, mProducer->dequeueBuffer(&slot, &fence, false, 402 WIDTH * 2, HEIGHT * 2, 0, GRALLOC_USAGE_SW_WRITE_OFTEN)); 403} 404 405} // namespace android 406