blob: 0ff7b80bc7c0cf3c98289159cbb2684b7986cb89 [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
Dan Stoza3e96f192014-03-03 10:16:19 -080017#define LOG_TAG "BufferQueueProducer"
18#define ATRACE_TAG ATRACE_TAG_GRAPHICS
19//#define LOG_NDEBUG 0
20
Dan Stoza289ade12014-02-28 11:17:17 -080021#define EGL_EGLEXT_PROTOTYPES
22
23#include <gui/BufferItem.h>
24#include <gui/BufferQueueCore.h>
25#include <gui/BufferQueueProducer.h>
26#include <gui/IConsumerListener.h>
27#include <gui/IGraphicBufferAlloc.h>
28
29#include <utils/Log.h>
30#include <utils/Trace.h>
31
32namespace android {
33
34BufferQueueProducer::BufferQueueProducer(const sp<BufferQueueCore>& core) :
35 mCore(core),
36 mSlots(core->mSlots),
37 mConsumerName() {}
38
39BufferQueueProducer::~BufferQueueProducer() {}
40
41status_t BufferQueueProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
42 ATRACE_CALL();
43 BQ_LOGV("requestBuffer: slot %d", slot);
44 Mutex::Autolock lock(mCore->mMutex);
45
46 if (mCore->mIsAbandoned) {
47 BQ_LOGE("requestBuffer: BufferQueue has been abandoned");
48 return NO_INIT;
49 }
50
Dan Stoza3e96f192014-03-03 10:16:19 -080051 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
Dan Stoza289ade12014-02-28 11:17:17 -080052 BQ_LOGE("requestBuffer: slot index %d out of range [0, %d)",
Dan Stoza3e96f192014-03-03 10:16:19 -080053 slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
Dan Stoza289ade12014-02-28 11:17:17 -080054 return BAD_VALUE;
55 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
56 BQ_LOGE("requestBuffer: slot %d is not owned by the producer "
57 "(state = %d)", slot, mSlots[slot].mBufferState);
58 return BAD_VALUE;
59 }
60
61 mSlots[slot].mRequestBufferCalled = true;
62 *buf = mSlots[slot].mGraphicBuffer;
63 return NO_ERROR;
64}
65
66status_t BufferQueueProducer::setBufferCount(int bufferCount) {
67 ATRACE_CALL();
68 BQ_LOGV("setBufferCount: count = %d", bufferCount);
69
70 sp<IConsumerListener> listener;
71 { // Autolock scope
72 Mutex::Autolock lock(mCore->mMutex);
73
74 if (mCore->mIsAbandoned) {
75 BQ_LOGE("setBufferCount: BufferQueue has been abandoned");
76 return NO_INIT;
77 }
78
Dan Stoza3e96f192014-03-03 10:16:19 -080079 if (bufferCount > BufferQueueDefs::NUM_BUFFER_SLOTS) {
Dan Stoza289ade12014-02-28 11:17:17 -080080 BQ_LOGE("setBufferCount: bufferCount %d too large (max %d)",
Dan Stoza3e96f192014-03-03 10:16:19 -080081 bufferCount, BufferQueueDefs::NUM_BUFFER_SLOTS);
Dan Stoza289ade12014-02-28 11:17:17 -080082 return BAD_VALUE;
83 }
84
85 // There must be no dequeued buffers when changing the buffer count.
Dan Stoza3e96f192014-03-03 10:16:19 -080086 for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
Dan Stoza289ade12014-02-28 11:17:17 -080087 if (mSlots[s].mBufferState == BufferSlot::DEQUEUED) {
88 BQ_LOGE("setBufferCount: buffer owned by producer");
89 return -EINVAL;
90 }
91 }
92
93 if (bufferCount == 0) {
94 mCore->mOverrideMaxBufferCount = 0;
95 mCore->mDequeueCondition.broadcast();
96 return NO_ERROR;
97 }
98
99 const int minBufferSlots = mCore->getMinMaxBufferCountLocked(false);
100 if (bufferCount < minBufferSlots) {
101 BQ_LOGE("setBufferCount: requested buffer count %d is less than "
102 "minimum %d", bufferCount, minBufferSlots);
103 return BAD_VALUE;
104 }
105
106 // Here we are guaranteed that the producer doesn't have any dequeued
107 // buffers and will release all of its buffer references. We don't
108 // clear the queue, however, so that currently queued buffers still
109 // get displayed.
110 mCore->freeAllBuffersLocked();
111 mCore->mOverrideMaxBufferCount = bufferCount;
112 mCore->mDequeueCondition.broadcast();
113 listener = mCore->mConsumerListener;
114 } // Autolock scope
115
116 // Call back without lock held
117 if (listener != NULL) {
118 listener->onBuffersReleased();
119 }
120
121 return NO_ERROR;
122}
123
124status_t BufferQueueProducer::dequeueBuffer(int *outSlot,
125 sp<android::Fence> *outFence, bool async,
126 uint32_t width, uint32_t height, uint32_t format, uint32_t usage) {
127 ATRACE_CALL();
128 { // Autolock scope
129 Mutex::Autolock lock(mCore->mMutex);
130 mConsumerName = mCore->mConsumerName;
131 } // Autolock scope
132
133 BQ_LOGV("dequeueBuffer: async=%s w=%u h=%u format=%#x, usage=%#x",
134 async ? "true" : "false", width, height, format, usage);
135
136 if ((width && !height) || (!width && height)) {
137 BQ_LOGE("dequeueBuffer: invalid size: w=%u h=%u", width, height);
138 return BAD_VALUE;
139 }
140
141 status_t returnFlags = NO_ERROR;
142 EGLDisplay eglDisplay = EGL_NO_DISPLAY;
143 EGLSyncKHR eglFence = EGL_NO_SYNC_KHR;
144
145 { // Autolock scope
146 Mutex::Autolock lock(mCore->mMutex);
147
148 if (format == 0) {
149 format = mCore->mDefaultBufferFormat;
150 }
151
152 // Enable the usage bits the consumer requested
153 usage |= mCore->mConsumerUsageBits;
154
155 int found = -1;
156 bool tryAgain = true;
157 while (tryAgain) {
158 if (mCore->mIsAbandoned) {
159 BQ_LOGE("dequeueBuffer: BufferQueue has been abandoned");
160 return NO_INIT;
161 }
162
163 const int maxBufferCount = mCore->getMaxBufferCountLocked(async);
164 if (async && mCore->mOverrideMaxBufferCount) {
165 // FIXME: Some drivers are manually setting the buffer count
166 // (which they shouldn't), so we do this extra test here to
167 // handle that case. This is TEMPORARY until we get this fixed.
168 if (mCore->mOverrideMaxBufferCount < maxBufferCount) {
169 BQ_LOGE("dequeueBuffer: async mode is invalid with "
170 "buffer count override");
171 return BAD_VALUE;
172 }
173 }
174
175 // Free up any buffers that are in slots beyond the max buffer count
Dan Stoza3e96f192014-03-03 10:16:19 -0800176 for (int s = maxBufferCount; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
Dan Stoza289ade12014-02-28 11:17:17 -0800177 assert(mSlots[s].mBufferState == BufferSlot::FREE);
178 if (mSlots[s].mGraphicBuffer != NULL) {
179 mCore->freeBufferLocked(s);
180 returnFlags |= RELEASE_ALL_BUFFERS;
181 }
182 }
183
184 // Look for a free buffer to give to the client
185 found = BufferQueueCore::INVALID_BUFFER_SLOT;
186 int dequeuedCount = 0;
187 int acquiredCount = 0;
188 for (int s = 0; s < maxBufferCount; ++s) {
189 switch (mSlots[s].mBufferState) {
190 case BufferSlot::DEQUEUED:
191 ++dequeuedCount;
192 break;
193 case BufferSlot::ACQUIRED:
194 ++acquiredCount;
195 break;
196 case BufferSlot::FREE:
197 // We return the oldest of the free buffers to avoid
198 // stalling the producer if possible, since the consumer
199 // may still have pending reads of in-flight buffers
200 if (found == BufferQueueCore::INVALID_BUFFER_SLOT ||
201 mSlots[s].mFrameNumber < mSlots[found].mFrameNumber) {
202 found = s;
203 }
204 break;
205 default:
206 break;
207 }
208 }
209
210 // Producers are not allowed to dequeue more than one buffer if they
211 // did not set a buffer count
212 if (!mCore->mOverrideMaxBufferCount && dequeuedCount) {
213 BQ_LOGE("dequeueBuffer: can't dequeue multiple buffers "
214 "without setting the buffer count");
215 return -EINVAL;
216 }
217
218 // See whether a buffer has been queued since the last
219 // setBufferCount so we know whether to perform the min undequeued
220 // buffers check below
221 if (mCore->mBufferHasBeenQueued) {
222 // Make sure the producer is not trying to dequeue more buffers
223 // than allowed
224 const int newUndequeuedCount =
225 maxBufferCount - (dequeuedCount + 1);
226 const int minUndequeuedCount =
227 mCore->getMinUndequeuedBufferCountLocked(async);
228 if (newUndequeuedCount < minUndequeuedCount) {
229 BQ_LOGE("dequeueBuffer: min undequeued buffer count (%d) "
230 "exceeded (dequeued=%d undequeued=%d)",
231 minUndequeuedCount, dequeuedCount,
232 newUndequeuedCount);
233 return -EBUSY;
234 }
235 }
236
237 // If no buffer is found, wait for a buffer to be released or for
238 // the max buffer count to change
239 tryAgain = (found == BufferQueueCore::INVALID_BUFFER_SLOT);
240 if (tryAgain) {
241 // Return an error if we're in non-blocking mode (producer and
242 // consumer are controlled by the application).
243 // However, the consumer is allowed to briefly acquire an extra
244 // buffer (which could cause us to have to wait here), which is
245 // okay, since it is only used to implement an atomic acquire +
246 // release (e.g., in GLConsumer::updateTexImage())
247 if (mCore->mDequeueBufferCannotBlock &&
248 (acquiredCount <= mCore->mMaxAcquiredBufferCount)) {
249 return WOULD_BLOCK;
250 }
251 mCore->mDequeueCondition.wait(mCore->mMutex);
252 }
253 } // while (tryAgain)
254
255 // This should not happen
256 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
257 BQ_LOGE("dequeueBuffer: no available buffer slots");
258 return -EBUSY;
259 }
260
261 *outSlot = found;
262 ATRACE_BUFFER_INDEX(found);
263
264 const bool useDefaultSize = !width && !height;
265 if (useDefaultSize) {
266 width = mCore->mDefaultWidth;
267 height = mCore->mDefaultHeight;
268 }
269
270 mSlots[found].mBufferState = BufferSlot::DEQUEUED;
271
272 const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
273 if ((buffer == NULL) ||
274 (static_cast<uint32_t>(buffer->width) != width) ||
275 (static_cast<uint32_t>(buffer->height) != height) ||
276 (static_cast<uint32_t>(buffer->format) != format) ||
277 ((static_cast<uint32_t>(buffer->usage) & usage) != usage))
278 {
279 mSlots[found].mAcquireCalled = false;
280 mSlots[found].mGraphicBuffer = NULL;
281 mSlots[found].mRequestBufferCalled = false;
282 mSlots[found].mEglDisplay = EGL_NO_DISPLAY;
283 mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
284 mSlots[found].mFence = Fence::NO_FENCE;
285
286 returnFlags |= BUFFER_NEEDS_REALLOCATION;
287 }
288
289 if (CC_UNLIKELY(mSlots[found].mFence == NULL)) {
290 BQ_LOGE("dequeueBuffer: about to return a NULL fence - "
291 "slot=%d w=%d h=%d format=%u",
292 found, buffer->width, buffer->height, buffer->format);
293 }
294
295 eglDisplay = mSlots[found].mEglDisplay;
296 eglFence = mSlots[found].mEglFence;
297 *outFence = mSlots[found].mFence;
298 mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
299 mSlots[found].mFence = Fence::NO_FENCE;
300 } // Autolock scope
301
302 if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
303 status_t error;
304 sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
305 width, height, format, usage, &error));
306 if (graphicBuffer == NULL) {
307 BQ_LOGE("dequeueBuffer: createGraphicBuffer failed");
308 return error;
309 }
310
311 { // Autolock scope
312 Mutex::Autolock lock(mCore->mMutex);
313
314 if (mCore->mIsAbandoned) {
315 BQ_LOGE("dequeueBuffer: BufferQueue has been abandoned");
316 return NO_INIT;
317 }
318
319 mSlots[*outSlot].mFrameNumber = ~0;
320 mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
321 } // Autolock scope
322 }
323
324 if (eglFence != EGL_NO_SYNC_KHR) {
325 EGLint result = eglClientWaitSyncKHR(eglDisplay, eglFence, 0,
326 1000000000);
327 // If something goes wrong, log the error, but return the buffer without
328 // synchronizing access to it. It's too late at this point to abort the
329 // dequeue operation.
330 if (result == EGL_FALSE) {
331 BQ_LOGE("dequeueBuffer: error %#x waiting for fence",
332 eglGetError());
333 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
334 BQ_LOGE("dequeueBuffer: timeout waiting for fence");
335 }
336 eglDestroySyncKHR(eglDisplay, eglFence);
337 }
338
339 BQ_LOGV("dequeueBuffer: returning slot=%d/%llu buf=%p flags=%#x", *outSlot,
340 mSlots[*outSlot].mFrameNumber,
341 mSlots[*outSlot].mGraphicBuffer->handle, returnFlags);
342
343 return returnFlags;
344}
345
346status_t BufferQueueProducer::queueBuffer(int slot,
347 const QueueBufferInput &input, QueueBufferOutput *output) {
348 ATRACE_CALL();
349 ATRACE_BUFFER_INDEX(slot);
350
351 int64_t timestamp;
352 bool isAutoTimestamp;
353 Rect crop;
354 int scalingMode;
355 uint32_t transform;
356 bool async;
357 sp<Fence> fence;
358 input.deflate(&timestamp, &isAutoTimestamp, &crop, &scalingMode, &transform,
359 &async, &fence);
360
361 if (fence == NULL) {
362 BQ_LOGE("queueBuffer: fence is NULL");
363 return BAD_VALUE;
364 }
365
366 switch (scalingMode) {
367 case NATIVE_WINDOW_SCALING_MODE_FREEZE:
368 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
369 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
370 case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP:
371 break;
372 default:
373 BQ_LOGE("queueBuffer: unknown scaling mode %d", scalingMode);
374 return -EINVAL;
375 }
376
377 sp<IConsumerListener> listener;
378 { // Autolock scope
379 Mutex::Autolock lock(mCore->mMutex);
380
381 if (mCore->mIsAbandoned) {
382 BQ_LOGE("queueBuffer: BufferQueue has been abandoned");
383 return NO_INIT;
384 }
385
386 const int maxBufferCount = mCore->getMaxBufferCountLocked(async);
387 if (async && mCore->mOverrideMaxBufferCount) {
388 // FIXME: Some drivers are manually setting the buffer count
389 // (which they shouldn't), so we do this extra test here to
390 // handle that case. This is TEMPORARY until we get this fixed.
391 if (mCore->mOverrideMaxBufferCount < maxBufferCount) {
392 BQ_LOGE("queueBuffer: async mode is invalid with "
393 "buffer count override");
394 return BAD_VALUE;
395 }
396 }
397
398 if (slot < 0 || slot >= maxBufferCount) {
399 BQ_LOGE("queueBuffer: slot index %d out of range [0, %d)",
400 slot, maxBufferCount);
401 return -EINVAL;
402 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
403 BQ_LOGE("queueBuffer: slot %d is not owned by the producer "
404 "(state = %d)", slot, mSlots[slot].mBufferState);
405 return -EINVAL;
406 } else if (!mSlots[slot].mRequestBufferCalled) {
407 BQ_LOGE("queueBuffer: slot %d was queued without requesting "
408 "a buffer", slot);
409 return -EINVAL;
410 }
411
412 BQ_LOGV("queueBuffer: slot=%d/%llu time=%llu crop=[%d,%d,%d,%d] "
413 "transform=%#x scale=%s",
414 slot, mCore->mFrameCounter + 1, timestamp,
415 crop.left, crop.top, crop.right, crop.bottom,
416 transform, BufferItem::scalingModeName(scalingMode));
417
418 const sp<GraphicBuffer>& graphicBuffer(mSlots[slot].mGraphicBuffer);
419 Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight());
420 Rect croppedRect;
421 crop.intersect(bufferRect, &croppedRect);
422 if (croppedRect != crop) {
423 BQ_LOGE("queueBuffer: crop rect is not contained within the "
424 "buffer in slot %d", slot);
425 return -EINVAL;
426 }
427
428 mSlots[slot].mFence = fence;
429 mSlots[slot].mBufferState = BufferSlot::QUEUED;
430 ++mCore->mFrameCounter;
431 mSlots[slot].mFrameNumber = mCore->mFrameCounter;
432
433 BufferItem item;
434 item.mAcquireCalled = mSlots[slot].mAcquireCalled;
435 item.mGraphicBuffer = mSlots[slot].mGraphicBuffer;
436 item.mCrop = crop;
437 item.mTransform = transform & ~NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
438 item.mTransformToDisplayInverse =
439 bool(transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY);
440 item.mScalingMode = scalingMode;
441 item.mTimestamp = timestamp;
442 item.mIsAutoTimestamp = isAutoTimestamp;
443 item.mFrameNumber = mCore->mFrameCounter;
444 item.mSlot = slot;
445 item.mFence = fence;
446 item.mIsDroppable = mCore->mDequeueBufferCannotBlock || async;
447
448 if (mCore->mQueue.empty()) {
449 // When the queue is empty, we can ignore mDequeueBufferCannotBlock
450 // and simply queue this buffer
451 mCore->mQueue.push_back(item);
452 listener = mCore->mConsumerListener;
453 } else {
454 // When the queue is not empty, we need to look at the front buffer
455 // state to see if we need to replace it
456 BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin());
457 if (front->mIsDroppable) {
458 // If the front queued buffer is still being tracked, we first
459 // mark it as freed
460 if (mCore->stillTracking(front)) {
461 mSlots[front->mSlot].mBufferState = BufferSlot::FREE;
462 // Reset the frame number of the freed buffer so that it is
463 // the first in line to be dequeued again
464 mSlots[front->mSlot].mFrameNumber = 0;
465 }
466 // Overwrite the droppable buffer with the incoming one
467 *front = item;
468 } else {
469 mCore->mQueue.push_back(item);
470 listener = mCore->mConsumerListener;
471 }
472 }
473
474 mCore->mBufferHasBeenQueued = true;
475 mCore->mDequeueCondition.broadcast();
476
477 output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
478 mCore->mTransformHint, mCore->mQueue.size());
479
480 ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size());
481 } // Autolock scope
482
483 // Call back without lock held
484 if (listener != NULL) {
485 listener->onFrameAvailable();
486 }
487
488 return NO_ERROR;
489}
490
491void BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
492 ATRACE_CALL();
493 BQ_LOGV("cancelBuffer: slot %d", slot);
494 Mutex::Autolock lock(mCore->mMutex);
495
496 if (mCore->mIsAbandoned) {
497 BQ_LOGE("cancelBuffer: BufferQueue has been abandoned");
498 return;
499 }
500
Dan Stoza3e96f192014-03-03 10:16:19 -0800501 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
Dan Stoza289ade12014-02-28 11:17:17 -0800502 BQ_LOGE("cancelBuffer: slot index %d out of range [0, %d)",
Dan Stoza3e96f192014-03-03 10:16:19 -0800503 slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
Dan Stoza289ade12014-02-28 11:17:17 -0800504 return;
505 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
506 BQ_LOGE("cancelBuffer: slot %d is not owned by the producer "
507 "(state = %d)", slot, mSlots[slot].mBufferState);
508 return;
509 } else if (fence == NULL) {
510 BQ_LOGE("cancelBuffer: fence is NULL");
511 return;
512 }
513
514 mSlots[slot].mBufferState = BufferSlot::FREE;
515 mSlots[slot].mFrameNumber = 0;
516 mSlots[slot].mFence = fence;
517 mCore->mDequeueCondition.broadcast();
518}
519
520int BufferQueueProducer::query(int what, int *outValue) {
521 ATRACE_CALL();
522 Mutex::Autolock lock(mCore->mMutex);
523
524 if (outValue == NULL) {
525 BQ_LOGE("query: outValue was NULL");
526 return BAD_VALUE;
527 }
528
529 if (mCore->mIsAbandoned) {
530 BQ_LOGE("query: BufferQueue has been abandoned");
531 return NO_INIT;
532 }
533
534 int value;
535 switch (what) {
536 case NATIVE_WINDOW_WIDTH:
537 value = mCore->mDefaultWidth;
538 break;
539 case NATIVE_WINDOW_HEIGHT:
540 value = mCore->mDefaultHeight;
541 break;
542 case NATIVE_WINDOW_FORMAT:
543 value = mCore->mDefaultBufferFormat;
544 break;
545 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
546 value = mCore->getMinUndequeuedBufferCountLocked(false);
547 break;
548 case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
549 value = (mCore->mQueue.size() > 1);
550 break;
551 case NATIVE_WINDOW_CONSUMER_USAGE_BITS:
552 value = mCore->mConsumerUsageBits;
553 break;
554 default:
555 return BAD_VALUE;
556 }
557
558 BQ_LOGV("query: %d? %d", what, value);
559 *outValue = value;
560 return NO_ERROR;
561}
562
563status_t BufferQueueProducer::connect(const sp<android::IBinder> &token,
564 int api, bool producerControlledByApp, QueueBufferOutput *output) {
565 ATRACE_CALL();
566 Mutex::Autolock lock(mCore->mMutex);
567 mConsumerName = mCore->mConsumerName;
568 BQ_LOGV("connect(P): api=%d producerControlledByApp=%s", api,
569 producerControlledByApp ? "true" : "false");
570
571 // If we disconnect and reconnect quickly, we can be in a state where our
572 // slots are empty but we have many buffers in the queue. This can cause us
573 // to run out of memory if we outrun the consumer. Wait here if it looks
574 // like we have too many buffers queued up.
575 while (true) {
576 if (mCore->mIsAbandoned) {
577 BQ_LOGE("connect(P): BufferQueue has been abandoned");
578 return NO_INIT;
579 }
580
581 if (mCore->mConsumerListener == NULL) {
582 BQ_LOGE("connect(P): BufferQueue has no consumer");
583 return NO_INIT;
584 }
585
586 if (output == NULL) {
587 BQ_LOGE("connect(P): output was NULL");
588 return BAD_VALUE;
589 }
590
591 if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
592 BQ_LOGE("connect(P): already connected (cur=%d req=%d)",
593 mCore->mConnectedApi, api);
594 return BAD_VALUE;
595 }
596
597 size_t maxBufferCount = mCore->getMaxBufferCountLocked(false);
598 if (mCore->mQueue.size() <= maxBufferCount) {
599 // The queue size seems small enough to proceed
600 // TODO: Make this bound tighter?
601 break;
602 }
603
604 BQ_LOGV("connect(P): queue size is %d, waiting", mCore->mQueue.size());
605 mCore->mDequeueCondition.wait(mCore->mMutex);
606 }
607
608 int status = NO_ERROR;
609 switch (api) {
610 case NATIVE_WINDOW_API_EGL:
611 case NATIVE_WINDOW_API_CPU:
612 case NATIVE_WINDOW_API_MEDIA:
613 case NATIVE_WINDOW_API_CAMERA:
614 mCore->mConnectedApi = api;
615 output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
616 mCore->mTransformHint, mCore->mQueue.size());
617
618 // Set up a death notification so that we can disconnect
619 // automatically if the remote producer dies
620 if (token != NULL && token->remoteBinder() != NULL) {
621 status = token->linkToDeath(
622 static_cast<IBinder::DeathRecipient*>(this));
623 if (status == NO_ERROR) {
624 mCore->mConnectedProducerToken = token;
625 } else {
626 BQ_LOGE("connect(P): linkToDeath failed: %s (%d)",
627 strerror(-status), status);
628 }
629 }
630 break;
631 default:
632 BQ_LOGE("connect(P): unknown API %d", api);
633 status = BAD_VALUE;
634 break;
635 }
636
637 mCore->mBufferHasBeenQueued = false;
638 mCore->mDequeueBufferCannotBlock =
639 mCore->mConsumerControlledByApp && producerControlledByApp;
640
641 return status;
642}
643
644status_t BufferQueueProducer::disconnect(int api) {
645 ATRACE_CALL();
646 BQ_LOGV("disconnect(P): api %d", api);
647
648 int status = NO_ERROR;
649 sp<IConsumerListener> listener;
650 { // Autolock scope
651 Mutex::Autolock lock(mCore->mMutex);
652
653 if (mCore->mIsAbandoned) {
654 // It's not really an error to disconnect after the surface has
655 // been abandoned; it should just be a no-op.
656 return NO_ERROR;
657 }
658
659 switch (api) {
660 case NATIVE_WINDOW_API_EGL:
661 case NATIVE_WINDOW_API_CPU:
662 case NATIVE_WINDOW_API_MEDIA:
663 case NATIVE_WINDOW_API_CAMERA:
664 if (mCore->mConnectedApi == api) {
665 mCore->freeAllBuffersLocked();
666
667 // Remove our death notification callback if we have one
668 sp<IBinder> token = mCore->mConnectedProducerToken;
669 if (token != NULL) {
670 // This can fail if we're here because of the death
671 // notification, but we just ignore it
672 token->unlinkToDeath(
673 static_cast<IBinder::DeathRecipient*>(this));
674 }
675 mCore->mConnectedProducerToken = NULL;
676 mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API;
Jesse Hall399184a2014-03-03 15:42:54 -0800677 mCore->mSidebandStream.clear();
Dan Stoza289ade12014-02-28 11:17:17 -0800678 mCore->mDequeueCondition.broadcast();
679 listener = mCore->mConsumerListener;
680 } else {
681 BQ_LOGE("disconnect(P): connected to another API "
682 "(cur=%d req=%d)", mCore->mConnectedApi, api);
683 status = -EINVAL;
684 }
685 break;
686 default:
687 BQ_LOGE("disconnect(P): unknown API %d", api);
688 status = -EINVAL;
689 break;
690 }
691 } // Autolock scope
692
693 // Call back without lock held
694 if (listener != NULL) {
695 listener->onBuffersReleased();
696 }
697
698 return status;
699}
700
Jesse Hall399184a2014-03-03 15:42:54 -0800701status_t BufferQueueProducer::setSidebandStream(const sp<NativeHandle>& stream) {
702 Mutex::Autolock _l(mCore->mMutex);
703 mCore->mSidebandStream = stream;
704 return NO_ERROR;
705}
706
Dan Stoza289ade12014-02-28 11:17:17 -0800707void BufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) {
708 // If we're here, it means that a producer we were connected to died.
709 // We're guaranteed that we are still connected to it because we remove
710 // this callback upon disconnect. It's therefore safe to read mConnectedApi
711 // without synchronization here.
712 int api = mCore->mConnectedApi;
713 disconnect(api);
714}
715
716} // namespace android