blob: c3e10195511f221ad8308bfe181913ec62727981 [file] [log] [blame]
Dan Stoza289ade12014-02-28 11:17:17 -08001/*
2 * Copyright 2014 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
Mark Salyzyn8f515ce2014-06-09 14:32:04 -070017#include <inttypes.h>
18
Dan Stoza3e96f192014-03-03 10:16:19 -080019#define LOG_TAG "BufferQueueConsumer"
20#define ATRACE_TAG ATRACE_TAG_GRAPHICS
21//#define LOG_NDEBUG 0
22
Dan Stoza289ade12014-02-28 11:17:17 -080023#include <gui/BufferItem.h>
24#include <gui/BufferQueueConsumer.h>
25#include <gui/BufferQueueCore.h>
26#include <gui/IConsumerListener.h>
Dan Stozad1c10362014-03-28 15:19:08 -070027#include <gui/IProducerListener.h>
Dan Stoza289ade12014-02-28 11:17:17 -080028
29namespace android {
30
31BufferQueueConsumer::BufferQueueConsumer(const sp<BufferQueueCore>& core) :
32 mCore(core),
33 mSlots(core->mSlots),
34 mConsumerName() {}
35
36BufferQueueConsumer::~BufferQueueConsumer() {}
37
38status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer,
39 nsecs_t expectedPresent) {
40 ATRACE_CALL();
41 Mutex::Autolock lock(mCore->mMutex);
42
43 // Check that the consumer doesn't currently have the maximum number of
44 // buffers acquired. We allow the max buffer count to be exceeded by one
45 // buffer so that the consumer can successfully set up the newly acquired
46 // buffer before releasing the old one.
47 int numAcquiredBuffers = 0;
Dan Stoza3e96f192014-03-03 10:16:19 -080048 for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
Dan Stoza289ade12014-02-28 11:17:17 -080049 if (mSlots[s].mBufferState == BufferSlot::ACQUIRED) {
50 ++numAcquiredBuffers;
51 }
52 }
53 if (numAcquiredBuffers >= mCore->mMaxAcquiredBufferCount + 1) {
54 BQ_LOGE("acquireBuffer: max acquired buffer count reached: %d (max %d)",
55 numAcquiredBuffers, mCore->mMaxAcquiredBufferCount);
56 return INVALID_OPERATION;
57 }
58
59 // Check if the queue is empty.
60 // In asynchronous mode the list is guaranteed to be one buffer deep,
61 // while in synchronous mode we use the oldest buffer.
62 if (mCore->mQueue.empty()) {
63 return NO_BUFFER_AVAILABLE;
64 }
65
66 BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin());
67
68 // If expectedPresent is specified, we may not want to return a buffer yet.
69 // If it's specified and there's more than one buffer queued, we may want
70 // to drop a buffer.
71 if (expectedPresent != 0) {
72 const int MAX_REASONABLE_NSEC = 1000000000ULL; // 1 second
73
74 // The 'expectedPresent' argument indicates when the buffer is expected
75 // to be presented on-screen. If the buffer's desired present time is
76 // earlier (less) than expectedPresent -- meaning it will be displayed
77 // on time or possibly late if we show it as soon as possible -- we
78 // acquire and return it. If we don't want to display it until after the
79 // expectedPresent time, we return PRESENT_LATER without acquiring it.
80 //
81 // To be safe, we don't defer acquisition if expectedPresent is more
82 // than one second in the future beyond the desired present time
83 // (i.e., we'd be holding the buffer for a long time).
84 //
85 // NOTE: Code assumes monotonic time values from the system clock
86 // are positive.
87
88 // Start by checking to see if we can drop frames. We skip this check if
89 // the timestamps are being auto-generated by Surface. If the app isn't
90 // generating timestamps explicitly, it probably doesn't want frames to
91 // be discarded based on them.
92 while (mCore->mQueue.size() > 1 && !mCore->mQueue[0].mIsAutoTimestamp) {
93 // If entry[1] is timely, drop entry[0] (and repeat). We apply an
94 // additional criterion here: we only drop the earlier buffer if our
95 // desiredPresent falls within +/- 1 second of the expected present.
96 // Otherwise, bogus desiredPresent times (e.g., 0 or a small
97 // relative timestamp), which normally mean "ignore the timestamp
98 // and acquire immediately", would cause us to drop frames.
99 //
100 // We may want to add an additional criterion: don't drop the
101 // earlier buffer if entry[1]'s fence hasn't signaled yet.
102 const BufferItem& bufferItem(mCore->mQueue[1]);
103 nsecs_t desiredPresent = bufferItem.mTimestamp;
104 if (desiredPresent < expectedPresent - MAX_REASONABLE_NSEC ||
105 desiredPresent > expectedPresent) {
106 // This buffer is set to display in the near future, or
107 // desiredPresent is garbage. Either way we don't want to drop
108 // the previous buffer just to get this on the screen sooner.
Mark Salyzyn8f515ce2014-06-09 14:32:04 -0700109 BQ_LOGV("acquireBuffer: nodrop desire=%" PRId64 " expect=%"
110 PRId64 " (%" PRId64 ") now=%" PRId64,
111 desiredPresent, expectedPresent,
Dan Stoza289ade12014-02-28 11:17:17 -0800112 desiredPresent - expectedPresent,
113 systemTime(CLOCK_MONOTONIC));
114 break;
115 }
116
Mark Salyzyn8f515ce2014-06-09 14:32:04 -0700117 BQ_LOGV("acquireBuffer: drop desire=%" PRId64 " expect=%" PRId64
118 " size=%zu",
Dan Stoza289ade12014-02-28 11:17:17 -0800119 desiredPresent, expectedPresent, mCore->mQueue.size());
120 if (mCore->stillTracking(front)) {
121 // Front buffer is still in mSlots, so mark the slot as free
122 mSlots[front->mSlot].mBufferState = BufferSlot::FREE;
Dan Stoza0de7ea72015-04-23 13:20:51 -0700123 mCore->mFreeBuffers.push_back(front->mSlot);
Dan Stoza289ade12014-02-28 11:17:17 -0800124 }
125 mCore->mQueue.erase(front);
126 front = mCore->mQueue.begin();
127 }
128
129 // See if the front buffer is due
130 nsecs_t desiredPresent = front->mTimestamp;
131 if (desiredPresent > expectedPresent &&
132 desiredPresent < expectedPresent + MAX_REASONABLE_NSEC) {
Mark Salyzyn8f515ce2014-06-09 14:32:04 -0700133 BQ_LOGV("acquireBuffer: defer desire=%" PRId64 " expect=%" PRId64
134 " (%" PRId64 ") now=%" PRId64,
135 desiredPresent, expectedPresent,
Dan Stoza289ade12014-02-28 11:17:17 -0800136 desiredPresent - expectedPresent,
137 systemTime(CLOCK_MONOTONIC));
138 return PRESENT_LATER;
139 }
140
Mark Salyzyn8f515ce2014-06-09 14:32:04 -0700141 BQ_LOGV("acquireBuffer: accept desire=%" PRId64 " expect=%" PRId64 " "
142 "(%" PRId64 ") now=%" PRId64, desiredPresent, expectedPresent,
Dan Stoza289ade12014-02-28 11:17:17 -0800143 desiredPresent - expectedPresent,
144 systemTime(CLOCK_MONOTONIC));
145 }
146
147 int slot = front->mSlot;
148 *outBuffer = *front;
149 ATRACE_BUFFER_INDEX(slot);
150
Mark Salyzyn8f515ce2014-06-09 14:32:04 -0700151 BQ_LOGV("acquireBuffer: acquiring { slot=%d/%" PRIu64 " buffer=%p }",
Dan Stoza289ade12014-02-28 11:17:17 -0800152 slot, front->mFrameNumber, front->mGraphicBuffer->handle);
153 // If the front buffer is still being tracked, update its slot state
154 if (mCore->stillTracking(front)) {
155 mSlots[slot].mAcquireCalled = true;
156 mSlots[slot].mNeedsCleanupOnRelease = false;
157 mSlots[slot].mBufferState = BufferSlot::ACQUIRED;
158 mSlots[slot].mFence = Fence::NO_FENCE;
159 }
160
161 // If the buffer has previously been acquired by the consumer, set
162 // mGraphicBuffer to NULL to avoid unnecessarily remapping this buffer
163 // on the consumer side
164 if (outBuffer->mAcquireCalled) {
165 outBuffer->mGraphicBuffer = NULL;
166 }
167
168 mCore->mQueue.erase(front);
Dan Stozaae3c3682014-04-18 15:43:35 -0700169
170 // We might have freed a slot while dropping old buffers, or the producer
171 // may be blocked waiting for the number of buffers in the queue to
172 // decrease.
Dan Stoza289ade12014-02-28 11:17:17 -0800173 mCore->mDequeueCondition.broadcast();
174
175 ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size());
176
Dan Stoza0de7ea72015-04-23 13:20:51 -0700177 mCore->validateConsistencyLocked();
178
Dan Stoza289ade12014-02-28 11:17:17 -0800179 return NO_ERROR;
180}
181
Dan Stoza9f3053d2014-03-06 15:14:33 -0800182status_t BufferQueueConsumer::detachBuffer(int slot) {
183 ATRACE_CALL();
184 ATRACE_BUFFER_INDEX(slot);
185 BQ_LOGV("detachBuffer(C): slot %d", slot);
186 Mutex::Autolock lock(mCore->mMutex);
187
188 if (mCore->mIsAbandoned) {
189 BQ_LOGE("detachBuffer(C): BufferQueue has been abandoned");
190 return NO_INIT;
191 }
192
193 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
194 BQ_LOGE("detachBuffer(C): slot index %d out of range [0, %d)",
195 slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
196 return BAD_VALUE;
197 } else if (mSlots[slot].mBufferState != BufferSlot::ACQUIRED) {
198 BQ_LOGE("detachBuffer(C): slot %d is not owned by the consumer "
199 "(state = %d)", slot, mSlots[slot].mBufferState);
200 return BAD_VALUE;
201 }
202
203 mCore->freeBufferLocked(slot);
204 mCore->mDequeueCondition.broadcast();
Dan Stoza0de7ea72015-04-23 13:20:51 -0700205 mCore->validateConsistencyLocked();
Dan Stoza9f3053d2014-03-06 15:14:33 -0800206
207 return NO_ERROR;
208}
209
210status_t BufferQueueConsumer::attachBuffer(int* outSlot,
211 const sp<android::GraphicBuffer>& buffer) {
212 ATRACE_CALL();
213
214 if (outSlot == NULL) {
215 BQ_LOGE("attachBuffer(P): outSlot must not be NULL");
216 return BAD_VALUE;
217 } else if (buffer == NULL) {
218 BQ_LOGE("attachBuffer(P): cannot attach NULL buffer");
219 return BAD_VALUE;
220 }
221
222 Mutex::Autolock lock(mCore->mMutex);
223
Dan Stoza0de7ea72015-04-23 13:20:51 -0700224 // Make sure we don't have too many acquired buffers
Dan Stoza9f3053d2014-03-06 15:14:33 -0800225 int numAcquiredBuffers = 0;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800226 for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
227 if (mSlots[s].mBufferState == BufferSlot::ACQUIRED) {
228 ++numAcquiredBuffers;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800229 }
230 }
231
232 if (numAcquiredBuffers >= mCore->mMaxAcquiredBufferCount + 1) {
233 BQ_LOGE("attachBuffer(P): max acquired buffer count reached: %d "
234 "(max %d)", numAcquiredBuffers,
235 mCore->mMaxAcquiredBufferCount);
236 return INVALID_OPERATION;
237 }
Dan Stoza0de7ea72015-04-23 13:20:51 -0700238
239 // Find a free slot to put the buffer into
240 int found = BufferQueueCore::INVALID_BUFFER_SLOT;
241 if (!mCore->mFreeSlots.empty()) {
242 auto slot = mCore->mFreeSlots.begin();
243 found = *slot;
244 mCore->mFreeSlots.erase(slot);
245 } else if (!mCore->mFreeBuffers.empty()) {
246 found = mCore->mFreeBuffers.front();
247 mCore->mFreeBuffers.remove(found);
248 }
Dan Stoza9f3053d2014-03-06 15:14:33 -0800249 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
250 BQ_LOGE("attachBuffer(P): could not find free buffer slot");
251 return NO_MEMORY;
252 }
253
254 *outSlot = found;
255 ATRACE_BUFFER_INDEX(*outSlot);
256 BQ_LOGV("attachBuffer(C): returning slot %d", *outSlot);
257
258 mSlots[*outSlot].mGraphicBuffer = buffer;
259 mSlots[*outSlot].mBufferState = BufferSlot::ACQUIRED;
260 mSlots[*outSlot].mAttachedByConsumer = true;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800261 mSlots[*outSlot].mNeedsCleanupOnRelease = false;
262 mSlots[*outSlot].mFence = Fence::NO_FENCE;
263 mSlots[*outSlot].mFrameNumber = 0;
264
Dan Stoza99b18b42014-03-28 15:34:33 -0700265 // mAcquireCalled tells BufferQueue that it doesn't need to send a valid
266 // GraphicBuffer pointer on the next acquireBuffer call, which decreases
267 // Binder traffic by not un/flattening the GraphicBuffer. However, it
268 // requires that the consumer maintain a cached copy of the slot <--> buffer
269 // mappings, which is why the consumer doesn't need the valid pointer on
270 // acquire.
271 //
272 // The StreamSplitter is one of the primary users of the attach/detach
273 // logic, and while it is running, all buffers it acquires are immediately
274 // detached, and all buffers it eventually releases are ones that were
275 // attached (as opposed to having been obtained from acquireBuffer), so it
276 // doesn't make sense to maintain the slot/buffer mappings, which would
277 // become invalid for every buffer during detach/attach. By setting this to
278 // false, the valid GraphicBuffer pointer will always be sent with acquire
279 // for attached buffers.
280 mSlots[*outSlot].mAcquireCalled = false;
281
Dan Stoza0de7ea72015-04-23 13:20:51 -0700282 mCore->validateConsistencyLocked();
283
Dan Stoza9f3053d2014-03-06 15:14:33 -0800284 return NO_ERROR;
285}
286
Dan Stoza289ade12014-02-28 11:17:17 -0800287status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber,
288 const sp<Fence>& releaseFence, EGLDisplay eglDisplay,
289 EGLSyncKHR eglFence) {
290 ATRACE_CALL();
291 ATRACE_BUFFER_INDEX(slot);
292
Dan Stoza9f3053d2014-03-06 15:14:33 -0800293 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS ||
294 releaseFence == NULL) {
Dan Stoza52937cd2015-05-01 16:42:55 -0700295 BQ_LOGE("releaseBuffer: slot %d out of range or fence %p NULL", slot,
296 releaseFence.get());
Dan Stoza289ade12014-02-28 11:17:17 -0800297 return BAD_VALUE;
298 }
299
Dan Stozad1c10362014-03-28 15:19:08 -0700300 sp<IProducerListener> listener;
301 { // Autolock scope
302 Mutex::Autolock lock(mCore->mMutex);
Dan Stoza289ade12014-02-28 11:17:17 -0800303
Dan Stozad1c10362014-03-28 15:19:08 -0700304 // If the frame number has changed because the buffer has been reallocated,
305 // we can ignore this releaseBuffer for the old buffer
306 if (frameNumber != mSlots[slot].mFrameNumber) {
307 return STALE_BUFFER_SLOT;
308 }
Dan Stoza289ade12014-02-28 11:17:17 -0800309
Dan Stozad1c10362014-03-28 15:19:08 -0700310 // Make sure this buffer hasn't been queued while acquired by the consumer
311 BufferQueueCore::Fifo::iterator current(mCore->mQueue.begin());
312 while (current != mCore->mQueue.end()) {
313 if (current->mSlot == slot) {
314 BQ_LOGE("releaseBuffer: buffer slot %d pending release is "
315 "currently queued", slot);
316 return BAD_VALUE;
317 }
318 ++current;
319 }
320
321 if (mSlots[slot].mBufferState == BufferSlot::ACQUIRED) {
322 mSlots[slot].mEglDisplay = eglDisplay;
323 mSlots[slot].mEglFence = eglFence;
324 mSlots[slot].mFence = releaseFence;
325 mSlots[slot].mBufferState = BufferSlot::FREE;
Dan Stoza0de7ea72015-04-23 13:20:51 -0700326 mCore->mFreeBuffers.push_back(slot);
Dan Stozad1c10362014-03-28 15:19:08 -0700327 listener = mCore->mConnectedProducerListener;
328 BQ_LOGV("releaseBuffer: releasing slot %d", slot);
329 } else if (mSlots[slot].mNeedsCleanupOnRelease) {
330 BQ_LOGV("releaseBuffer: releasing a stale buffer slot %d "
331 "(state = %d)", slot, mSlots[slot].mBufferState);
332 mSlots[slot].mNeedsCleanupOnRelease = false;
333 return STALE_BUFFER_SLOT;
334 } else {
Dan Stoza52937cd2015-05-01 16:42:55 -0700335 BQ_LOGE("releaseBuffer: attempted to release buffer slot %d "
Dan Stozad1c10362014-03-28 15:19:08 -0700336 "but its state was %d", slot, mSlots[slot].mBufferState);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800337 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800338 }
Dan Stoza289ade12014-02-28 11:17:17 -0800339
Dan Stozad1c10362014-03-28 15:19:08 -0700340 mCore->mDequeueCondition.broadcast();
Dan Stoza0de7ea72015-04-23 13:20:51 -0700341 mCore->validateConsistencyLocked();
Dan Stozad1c10362014-03-28 15:19:08 -0700342 } // Autolock scope
Dan Stoza289ade12014-02-28 11:17:17 -0800343
Dan Stozad1c10362014-03-28 15:19:08 -0700344 // Call back without lock held
345 if (listener != NULL) {
346 listener->onBufferReleased();
347 }
Dan Stoza289ade12014-02-28 11:17:17 -0800348
349 return NO_ERROR;
350}
351
352status_t BufferQueueConsumer::connect(
353 const sp<IConsumerListener>& consumerListener, bool controlledByApp) {
354 ATRACE_CALL();
355
356 if (consumerListener == NULL) {
357 BQ_LOGE("connect(C): consumerListener may not be NULL");
358 return BAD_VALUE;
359 }
360
361 BQ_LOGV("connect(C): controlledByApp=%s",
362 controlledByApp ? "true" : "false");
363
364 Mutex::Autolock lock(mCore->mMutex);
365
366 if (mCore->mIsAbandoned) {
367 BQ_LOGE("connect(C): BufferQueue has been abandoned");
368 return NO_INIT;
369 }
370
371 mCore->mConsumerListener = consumerListener;
372 mCore->mConsumerControlledByApp = controlledByApp;
373
374 return NO_ERROR;
375}
376
377status_t BufferQueueConsumer::disconnect() {
378 ATRACE_CALL();
379
380 BQ_LOGV("disconnect(C)");
381
382 Mutex::Autolock lock(mCore->mMutex);
383
384 if (mCore->mConsumerListener == NULL) {
385 BQ_LOGE("disconnect(C): no consumer is connected");
Dan Stoza9f3053d2014-03-06 15:14:33 -0800386 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800387 }
388
389 mCore->mIsAbandoned = true;
390 mCore->mConsumerListener = NULL;
391 mCore->mQueue.clear();
392 mCore->freeAllBuffersLocked();
393 mCore->mDequeueCondition.broadcast();
394 return NO_ERROR;
395}
396
Dan Stozafebd4f42014-04-09 16:14:51 -0700397status_t BufferQueueConsumer::getReleasedBuffers(uint64_t *outSlotMask) {
Dan Stoza289ade12014-02-28 11:17:17 -0800398 ATRACE_CALL();
399
400 if (outSlotMask == NULL) {
401 BQ_LOGE("getReleasedBuffers: outSlotMask may not be NULL");
402 return BAD_VALUE;
403 }
404
405 Mutex::Autolock lock(mCore->mMutex);
406
407 if (mCore->mIsAbandoned) {
408 BQ_LOGE("getReleasedBuffers: BufferQueue has been abandoned");
409 return NO_INIT;
410 }
411
Dan Stozafebd4f42014-04-09 16:14:51 -0700412 uint64_t mask = 0;
Dan Stoza3e96f192014-03-03 10:16:19 -0800413 for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
Dan Stoza289ade12014-02-28 11:17:17 -0800414 if (!mSlots[s].mAcquireCalled) {
Dan Stozafebd4f42014-04-09 16:14:51 -0700415 mask |= (1ULL << s);
Dan Stoza289ade12014-02-28 11:17:17 -0800416 }
417 }
418
419 // Remove from the mask queued buffers for which acquire has been called,
420 // since the consumer will not receive their buffer addresses and so must
421 // retain their cached information
422 BufferQueueCore::Fifo::iterator current(mCore->mQueue.begin());
423 while (current != mCore->mQueue.end()) {
424 if (current->mAcquireCalled) {
Dan Stozafebd4f42014-04-09 16:14:51 -0700425 mask &= ~(1ULL << current->mSlot);
Dan Stoza289ade12014-02-28 11:17:17 -0800426 }
427 ++current;
428 }
429
Dan Stozafebd4f42014-04-09 16:14:51 -0700430 BQ_LOGV("getReleasedBuffers: returning mask %#" PRIx64, mask);
Dan Stoza289ade12014-02-28 11:17:17 -0800431 *outSlotMask = mask;
432 return NO_ERROR;
433}
434
435status_t BufferQueueConsumer::setDefaultBufferSize(uint32_t width,
436 uint32_t height) {
437 ATRACE_CALL();
438
439 if (width == 0 || height == 0) {
440 BQ_LOGV("setDefaultBufferSize: dimensions cannot be 0 (width=%u "
441 "height=%u)", width, height);
442 return BAD_VALUE;
443 }
444
445 BQ_LOGV("setDefaultBufferSize: width=%u height=%u", width, height);
446
447 Mutex::Autolock lock(mCore->mMutex);
448 mCore->mDefaultWidth = width;
449 mCore->mDefaultHeight = height;
450 return NO_ERROR;
451}
452
453status_t BufferQueueConsumer::setDefaultMaxBufferCount(int bufferCount) {
454 ATRACE_CALL();
455 Mutex::Autolock lock(mCore->mMutex);
456 return mCore->setDefaultMaxBufferCountLocked(bufferCount);
457}
458
459status_t BufferQueueConsumer::disableAsyncBuffer() {
460 ATRACE_CALL();
461
462 Mutex::Autolock lock(mCore->mMutex);
463
464 if (mCore->mConsumerListener != NULL) {
465 BQ_LOGE("disableAsyncBuffer: consumer already connected");
466 return INVALID_OPERATION;
467 }
468
469 BQ_LOGV("disableAsyncBuffer");
470 mCore->mUseAsyncBuffer = false;
471 return NO_ERROR;
472}
473
474status_t BufferQueueConsumer::setMaxAcquiredBufferCount(
475 int maxAcquiredBuffers) {
476 ATRACE_CALL();
477
478 if (maxAcquiredBuffers < 1 ||
479 maxAcquiredBuffers > BufferQueueCore::MAX_MAX_ACQUIRED_BUFFERS) {
480 BQ_LOGE("setMaxAcquiredBufferCount: invalid count %d",
481 maxAcquiredBuffers);
482 return BAD_VALUE;
483 }
484
485 Mutex::Autolock lock(mCore->mMutex);
486
487 if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
488 BQ_LOGE("setMaxAcquiredBufferCount: producer is already connected");
489 return INVALID_OPERATION;
490 }
491
492 BQ_LOGV("setMaxAcquiredBufferCount: %d", maxAcquiredBuffers);
493 mCore->mMaxAcquiredBufferCount = maxAcquiredBuffers;
494 return NO_ERROR;
495}
496
497void BufferQueueConsumer::setConsumerName(const String8& name) {
498 ATRACE_CALL();
499 BQ_LOGV("setConsumerName: '%s'", name.string());
500 Mutex::Autolock lock(mCore->mMutex);
501 mCore->mConsumerName = name;
502 mConsumerName = name;
503}
504
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800505status_t BufferQueueConsumer::setDefaultBufferFormat(PixelFormat defaultFormat) {
Dan Stoza289ade12014-02-28 11:17:17 -0800506 ATRACE_CALL();
507 BQ_LOGV("setDefaultBufferFormat: %u", defaultFormat);
508 Mutex::Autolock lock(mCore->mMutex);
509 mCore->mDefaultBufferFormat = defaultFormat;
510 return NO_ERROR;
511}
512
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800513status_t BufferQueueConsumer::setDefaultBufferDataSpace(
514 android_dataspace defaultDataSpace) {
515 ATRACE_CALL();
516 BQ_LOGV("setDefaultBufferDataSpace: %u", defaultDataSpace);
517 Mutex::Autolock lock(mCore->mMutex);
518 mCore->mDefaultBufferDataSpace = defaultDataSpace;
519 return NO_ERROR;
520}
521
Dan Stoza289ade12014-02-28 11:17:17 -0800522status_t BufferQueueConsumer::setConsumerUsageBits(uint32_t usage) {
523 ATRACE_CALL();
524 BQ_LOGV("setConsumerUsageBits: %#x", usage);
525 Mutex::Autolock lock(mCore->mMutex);
526 mCore->mConsumerUsageBits = usage;
527 return NO_ERROR;
528}
529
530status_t BufferQueueConsumer::setTransformHint(uint32_t hint) {
531 ATRACE_CALL();
532 BQ_LOGV("setTransformHint: %#x", hint);
533 Mutex::Autolock lock(mCore->mMutex);
534 mCore->mTransformHint = hint;
535 return NO_ERROR;
536}
537
Jesse Hall399184a2014-03-03 15:42:54 -0800538sp<NativeHandle> BufferQueueConsumer::getSidebandStream() const {
539 return mCore->mSidebandStream;
540}
541
Dan Stoza289ade12014-02-28 11:17:17 -0800542void BufferQueueConsumer::dump(String8& result, const char* prefix) const {
543 mCore->dump(result, prefix);
544}
545
546} // namespace android