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