BufferQueueProducer.cpp revision 3e96f1982fda358424b0b75f394cbf7c1794a072
1/* 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 LOG_TAG "BufferQueueProducer" 18#define ATRACE_TAG ATRACE_TAG_GRAPHICS 19//#define LOG_NDEBUG 0 20 21#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 51 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) { 52 BQ_LOGE("requestBuffer: slot index %d out of range [0, %d)", 53 slot, BufferQueueDefs::NUM_BUFFER_SLOTS); 54 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 79 if (bufferCount > BufferQueueDefs::NUM_BUFFER_SLOTS) { 80 BQ_LOGE("setBufferCount: bufferCount %d too large (max %d)", 81 bufferCount, BufferQueueDefs::NUM_BUFFER_SLOTS); 82 return BAD_VALUE; 83 } 84 85 // There must be no dequeued buffers when changing the buffer count. 86 for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { 87 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 176 for (int s = maxBufferCount; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { 177 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(×tamp, &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 501 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) { 502 BQ_LOGE("cancelBuffer: slot index %d out of range [0, %d)", 503 slot, BufferQueueDefs::NUM_BUFFER_SLOTS); 504 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; 677 mCore->mDequeueCondition.broadcast(); 678 listener = mCore->mConsumerListener; 679 } else { 680 BQ_LOGE("disconnect(P): connected to another API " 681 "(cur=%d req=%d)", mCore->mConnectedApi, api); 682 status = -EINVAL; 683 } 684 break; 685 default: 686 BQ_LOGE("disconnect(P): unknown API %d", api); 687 status = -EINVAL; 688 break; 689 } 690 } // Autolock scope 691 692 // Call back without lock held 693 if (listener != NULL) { 694 listener->onBuffersReleased(); 695 } 696 697 return status; 698} 699 700void BufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) { 701 // If we're here, it means that a producer we were connected to died. 702 // We're guaranteed that we are still connected to it because we remove 703 // this callback upon disconnect. It's therefore safe to read mConnectedApi 704 // without synchronization here. 705 int api = mCore->mConnectedApi; 706 disconnect(api); 707} 708 709} // namespace android 710