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