BufferQueueProducer.cpp revision 289ade165e60b5f71734d30e535f16eb1f4313ad
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 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(×tamp, &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 706