1 /* 2 * Copyright (C) 2013 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 "Camera3-Stream" 18 #define ATRACE_TAG ATRACE_TAG_CAMERA 19 //#define LOG_NDEBUG 0 20 21 #include <utils/Log.h> 22 #include <utils/Trace.h> 23 #include "device3/Camera3Stream.h" 24 #include "device3/StatusTracker.h" 25 26 #include <cutils/properties.h> 27 28 namespace android { 29 30 namespace camera3 { 31 32 Camera3Stream::~Camera3Stream() { 33 sp<StatusTracker> statusTracker = mStatusTracker.promote(); 34 if (statusTracker != 0 && mStatusId != StatusTracker::NO_STATUS_ID) { 35 statusTracker->removeComponent(mStatusId); 36 } 37 } 38 39 Camera3Stream* Camera3Stream::cast(camera3_stream *stream) { 40 return static_cast<Camera3Stream*>(stream); 41 } 42 43 const Camera3Stream* Camera3Stream::cast(const camera3_stream *stream) { 44 return static_cast<const Camera3Stream*>(stream); 45 } 46 47 Camera3Stream::Camera3Stream(int id, 48 camera3_stream_type type, 49 uint32_t width, uint32_t height, size_t maxSize, int format, 50 android_dataspace dataSpace, camera3_stream_rotation_t rotation, int setId) : 51 camera3_stream(), 52 mId(id), 53 mSetId(setId), 54 mName(String8::format("Camera3Stream[%d]", id)), 55 mMaxSize(maxSize), 56 mState(STATE_CONSTRUCTED), 57 mStatusId(StatusTracker::NO_STATUS_ID), 58 mStreamUnpreparable(true), 59 mOldUsage(0), 60 mOldMaxBuffers(0), 61 mPrepared(false), 62 mPreparedBufferIdx(0), 63 mLastMaxCount(Camera3StreamInterface::ALLOCATE_PIPELINE_MAX), 64 mBufferLimitLatency(kBufferLimitLatencyBinSize) { 65 66 camera3_stream::stream_type = type; 67 camera3_stream::width = width; 68 camera3_stream::height = height; 69 camera3_stream::format = format; 70 camera3_stream::data_space = dataSpace; 71 camera3_stream::rotation = rotation; 72 camera3_stream::usage = 0; 73 camera3_stream::max_buffers = 0; 74 camera3_stream::priv = NULL; 75 76 if ((format == HAL_PIXEL_FORMAT_BLOB || format == HAL_PIXEL_FORMAT_RAW_OPAQUE) && 77 maxSize == 0) { 78 ALOGE("%s: BLOB or RAW_OPAQUE format with size == 0", __FUNCTION__); 79 mState = STATE_ERROR; 80 } 81 } 82 83 int Camera3Stream::getId() const { 84 return mId; 85 } 86 87 int Camera3Stream::getStreamSetId() const { 88 return mSetId; 89 } 90 91 uint32_t Camera3Stream::getWidth() const { 92 return camera3_stream::width; 93 } 94 95 uint32_t Camera3Stream::getHeight() const { 96 return camera3_stream::height; 97 } 98 99 int Camera3Stream::getFormat() const { 100 return camera3_stream::format; 101 } 102 103 android_dataspace Camera3Stream::getDataSpace() const { 104 return camera3_stream::data_space; 105 } 106 107 camera3_stream* Camera3Stream::startConfiguration() { 108 ATRACE_CALL(); 109 Mutex::Autolock l(mLock); 110 status_t res; 111 112 switch (mState) { 113 case STATE_ERROR: 114 ALOGE("%s: In error state", __FUNCTION__); 115 return NULL; 116 case STATE_CONSTRUCTED: 117 // OK 118 break; 119 case STATE_IN_CONFIG: 120 case STATE_IN_RECONFIG: 121 // Can start config again with no trouble; but don't redo 122 // mOldUsage/mOldMaxBuffers 123 return this; 124 case STATE_CONFIGURED: 125 if (hasOutstandingBuffersLocked()) { 126 ALOGE("%s: Cannot configure stream; has outstanding buffers", 127 __FUNCTION__); 128 return NULL; 129 } 130 break; 131 default: 132 ALOGE("%s: Unknown state %d", __FUNCTION__, mState); 133 return NULL; 134 } 135 136 mOldUsage = camera3_stream::usage; 137 mOldMaxBuffers = camera3_stream::max_buffers; 138 139 res = getEndpointUsage(&(camera3_stream::usage)); 140 if (res != OK) { 141 ALOGE("%s: Cannot query consumer endpoint usage!", 142 __FUNCTION__); 143 return NULL; 144 } 145 146 // Stop tracking if currently doing so 147 if (mStatusId != StatusTracker::NO_STATUS_ID) { 148 sp<StatusTracker> statusTracker = mStatusTracker.promote(); 149 if (statusTracker != 0) { 150 statusTracker->removeComponent(mStatusId); 151 } 152 mStatusId = StatusTracker::NO_STATUS_ID; 153 } 154 155 if (mState == STATE_CONSTRUCTED) { 156 mState = STATE_IN_CONFIG; 157 } else { // mState == STATE_CONFIGURED 158 LOG_ALWAYS_FATAL_IF(mState != STATE_CONFIGURED, "Invalid state: 0x%x", mState); 159 mState = STATE_IN_RECONFIG; 160 } 161 162 return this; 163 } 164 165 bool Camera3Stream::isConfiguring() const { 166 Mutex::Autolock l(mLock); 167 return (mState == STATE_IN_CONFIG) || (mState == STATE_IN_RECONFIG); 168 } 169 170 status_t Camera3Stream::finishConfiguration() { 171 ATRACE_CALL(); 172 Mutex::Autolock l(mLock); 173 switch (mState) { 174 case STATE_ERROR: 175 ALOGE("%s: In error state", __FUNCTION__); 176 return INVALID_OPERATION; 177 case STATE_IN_CONFIG: 178 case STATE_IN_RECONFIG: 179 // OK 180 break; 181 case STATE_CONSTRUCTED: 182 case STATE_CONFIGURED: 183 ALOGE("%s: Cannot finish configuration that hasn't been started", 184 __FUNCTION__); 185 return INVALID_OPERATION; 186 default: 187 ALOGE("%s: Unknown state", __FUNCTION__); 188 return INVALID_OPERATION; 189 } 190 191 // Register for idle tracking 192 sp<StatusTracker> statusTracker = mStatusTracker.promote(); 193 if (statusTracker != 0) { 194 mStatusId = statusTracker->addComponent(); 195 } 196 197 // Check if the stream configuration is unchanged, and skip reallocation if 198 // so. As documented in hardware/camera3.h:configure_streams(). 199 if (mState == STATE_IN_RECONFIG && 200 mOldUsage == camera3_stream::usage && 201 mOldMaxBuffers == camera3_stream::max_buffers) { 202 mState = STATE_CONFIGURED; 203 return OK; 204 } 205 206 // Reset prepared state, since buffer config has changed, and existing 207 // allocations are no longer valid 208 mPrepared = false; 209 mStreamUnpreparable = false; 210 211 status_t res; 212 res = configureQueueLocked(); 213 if (res != OK) { 214 ALOGE("%s: Unable to configure stream %d queue: %s (%d)", 215 __FUNCTION__, mId, strerror(-res), res); 216 mState = STATE_ERROR; 217 return res; 218 } 219 220 mState = STATE_CONFIGURED; 221 222 return res; 223 } 224 225 status_t Camera3Stream::cancelConfiguration() { 226 ATRACE_CALL(); 227 Mutex::Autolock l(mLock); 228 switch (mState) { 229 case STATE_ERROR: 230 ALOGE("%s: In error state", __FUNCTION__); 231 return INVALID_OPERATION; 232 case STATE_IN_CONFIG: 233 case STATE_IN_RECONFIG: 234 // OK 235 break; 236 case STATE_CONSTRUCTED: 237 case STATE_CONFIGURED: 238 ALOGE("%s: Cannot cancel configuration that hasn't been started", 239 __FUNCTION__); 240 return INVALID_OPERATION; 241 default: 242 ALOGE("%s: Unknown state", __FUNCTION__); 243 return INVALID_OPERATION; 244 } 245 246 camera3_stream::usage = mOldUsage; 247 camera3_stream::max_buffers = mOldMaxBuffers; 248 249 mState = (mState == STATE_IN_RECONFIG) ? STATE_CONFIGURED : STATE_CONSTRUCTED; 250 return OK; 251 } 252 253 bool Camera3Stream::isUnpreparable() { 254 ATRACE_CALL(); 255 256 Mutex::Autolock l(mLock); 257 return mStreamUnpreparable; 258 } 259 260 status_t Camera3Stream::startPrepare(int maxCount) { 261 ATRACE_CALL(); 262 263 Mutex::Autolock l(mLock); 264 265 if (maxCount < 0) { 266 ALOGE("%s: Stream %d: Can't prepare stream if max buffer count (%d) is < 0", 267 __FUNCTION__, mId, maxCount); 268 return BAD_VALUE; 269 } 270 271 // This function should be only called when the stream is configured already. 272 if (mState != STATE_CONFIGURED) { 273 ALOGE("%s: Stream %d: Can't prepare stream if stream is not in CONFIGURED " 274 "state %d", __FUNCTION__, mId, mState); 275 return INVALID_OPERATION; 276 } 277 278 // This function can't be called if the stream has already received filled 279 // buffers 280 if (mStreamUnpreparable) { 281 ALOGE("%s: Stream %d: Can't prepare stream that's already in use", 282 __FUNCTION__, mId); 283 return INVALID_OPERATION; 284 } 285 286 if (getHandoutOutputBufferCountLocked() > 0) { 287 ALOGE("%s: Stream %d: Can't prepare stream that has outstanding buffers", 288 __FUNCTION__, mId); 289 return INVALID_OPERATION; 290 } 291 292 293 294 size_t pipelineMax = getBufferCountLocked(); 295 size_t clampedCount = (pipelineMax < static_cast<size_t>(maxCount)) ? 296 pipelineMax : static_cast<size_t>(maxCount); 297 size_t bufferCount = (maxCount == Camera3StreamInterface::ALLOCATE_PIPELINE_MAX) ? 298 pipelineMax : clampedCount; 299 300 mPrepared = bufferCount <= mLastMaxCount; 301 302 if (mPrepared) return OK; 303 304 mLastMaxCount = bufferCount; 305 306 mPreparedBuffers.insertAt(camera3_stream_buffer_t(), /*index*/0, bufferCount); 307 mPreparedBufferIdx = 0; 308 309 mState = STATE_PREPARING; 310 311 return NOT_ENOUGH_DATA; 312 } 313 314 bool Camera3Stream::isPreparing() const { 315 Mutex::Autolock l(mLock); 316 return mState == STATE_PREPARING; 317 } 318 319 bool Camera3Stream::isAbandoned() const { 320 Mutex::Autolock l(mLock); 321 return mState == STATE_ABANDONED; 322 } 323 324 status_t Camera3Stream::prepareNextBuffer() { 325 ATRACE_CALL(); 326 327 Mutex::Autolock l(mLock); 328 status_t res = OK; 329 330 // This function should be only called when the stream is preparing 331 if (mState != STATE_PREPARING) { 332 ALOGE("%s: Stream %d: Can't prepare buffer if stream is not in PREPARING " 333 "state %d", __FUNCTION__, mId, mState); 334 return INVALID_OPERATION; 335 } 336 337 // Get next buffer - this may allocate, and take a while for large buffers 338 res = getBufferLocked( &mPreparedBuffers.editItemAt(mPreparedBufferIdx) ); 339 if (res != OK) { 340 ALOGE("%s: Stream %d: Unable to allocate buffer %zu during preparation", 341 __FUNCTION__, mId, mPreparedBufferIdx); 342 return NO_INIT; 343 } 344 345 mPreparedBufferIdx++; 346 347 // Check if we still have buffers left to allocate 348 if (mPreparedBufferIdx < mPreparedBuffers.size()) { 349 return NOT_ENOUGH_DATA; 350 } 351 352 // Done with prepare - mark stream as such, and return all buffers 353 // via cancelPrepare 354 mPrepared = true; 355 356 return cancelPrepareLocked(); 357 } 358 359 status_t Camera3Stream::cancelPrepare() { 360 ATRACE_CALL(); 361 362 Mutex::Autolock l(mLock); 363 364 return cancelPrepareLocked(); 365 } 366 367 status_t Camera3Stream::cancelPrepareLocked() { 368 status_t res = OK; 369 370 // This function should be only called when the stream is mid-preparing. 371 if (mState != STATE_PREPARING) { 372 ALOGE("%s: Stream %d: Can't cancel prepare stream if stream is not in " 373 "PREPARING state %d", __FUNCTION__, mId, mState); 374 return INVALID_OPERATION; 375 } 376 377 // Return all valid buffers to stream, in ERROR state to indicate 378 // they weren't filled. 379 for (size_t i = 0; i < mPreparedBufferIdx; i++) { 380 mPreparedBuffers.editItemAt(i).release_fence = -1; 381 mPreparedBuffers.editItemAt(i).status = CAMERA3_BUFFER_STATUS_ERROR; 382 returnBufferLocked(mPreparedBuffers[i], 0); 383 } 384 mPreparedBuffers.clear(); 385 mPreparedBufferIdx = 0; 386 387 mState = STATE_CONFIGURED; 388 389 return res; 390 } 391 392 status_t Camera3Stream::tearDown() { 393 ATRACE_CALL(); 394 Mutex::Autolock l(mLock); 395 396 status_t res = OK; 397 398 // This function should be only called when the stream is configured. 399 if (mState != STATE_CONFIGURED) { 400 ALOGE("%s: Stream %d: Can't tear down stream if stream is not in " 401 "CONFIGURED state %d", __FUNCTION__, mId, mState); 402 return INVALID_OPERATION; 403 } 404 405 // If any buffers have been handed to the HAL, the stream cannot be torn down. 406 if (getHandoutOutputBufferCountLocked() > 0) { 407 ALOGE("%s: Stream %d: Can't tear down a stream that has outstanding buffers", 408 __FUNCTION__, mId); 409 return INVALID_OPERATION; 410 } 411 412 // Free buffers by disconnecting and then reconnecting to the buffer queue 413 // Only unused buffers will be dropped immediately; buffers that have been filled 414 // and are waiting to be acquired by the consumer and buffers that are currently 415 // acquired will be freed once they are released by the consumer. 416 417 res = disconnectLocked(); 418 if (res != OK) { 419 if (res == -ENOTCONN) { 420 // queue has been disconnected, nothing left to do, so exit with success 421 return OK; 422 } 423 ALOGE("%s: Stream %d: Unable to disconnect to tear down buffers: %s (%d)", 424 __FUNCTION__, mId, strerror(-res), res); 425 return res; 426 } 427 428 mState = STATE_IN_CONFIG; 429 430 res = configureQueueLocked(); 431 if (res != OK) { 432 ALOGE("%s: Unable to configure stream %d queue: %s (%d)", 433 __FUNCTION__, mId, strerror(-res), res); 434 mState = STATE_ERROR; 435 return res; 436 } 437 438 // Reset prepared state, since we've reconnected to the queue and can prepare again. 439 mPrepared = false; 440 mStreamUnpreparable = false; 441 442 mState = STATE_CONFIGURED; 443 444 return OK; 445 } 446 447 status_t Camera3Stream::getBuffer(camera3_stream_buffer *buffer, 448 const std::vector<size_t>& surface_ids) { 449 ATRACE_CALL(); 450 Mutex::Autolock l(mLock); 451 status_t res = OK; 452 453 // This function should be only called when the stream is configured already. 454 if (mState != STATE_CONFIGURED) { 455 ALOGE("%s: Stream %d: Can't get buffers if stream is not in CONFIGURED state %d", 456 __FUNCTION__, mId, mState); 457 return INVALID_OPERATION; 458 } 459 460 // Wait for new buffer returned back if we are running into the limit. 461 if (getHandoutOutputBufferCountLocked() == camera3_stream::max_buffers) { 462 ALOGV("%s: Already dequeued max output buffers (%d), wait for next returned one.", 463 __FUNCTION__, camera3_stream::max_buffers); 464 nsecs_t waitStart = systemTime(SYSTEM_TIME_MONOTONIC); 465 res = mOutputBufferReturnedSignal.waitRelative(mLock, kWaitForBufferDuration); 466 nsecs_t waitEnd = systemTime(SYSTEM_TIME_MONOTONIC); 467 mBufferLimitLatency.add(waitStart, waitEnd); 468 if (res != OK) { 469 if (res == TIMED_OUT) { 470 ALOGE("%s: wait for output buffer return timed out after %lldms (max_buffers %d)", 471 __FUNCTION__, kWaitForBufferDuration / 1000000LL, 472 camera3_stream::max_buffers); 473 } 474 return res; 475 } 476 } 477 478 res = getBufferLocked(buffer, surface_ids); 479 if (res == OK) { 480 fireBufferListenersLocked(*buffer, /*acquired*/true, /*output*/true); 481 if (buffer->buffer) { 482 mOutstandingBuffers.push_back(*buffer->buffer); 483 } 484 } 485 486 return res; 487 } 488 489 bool Camera3Stream::isOutstandingBuffer(const camera3_stream_buffer &buffer) { 490 if (buffer.buffer == nullptr) { 491 return false; 492 } 493 494 for (auto b : mOutstandingBuffers) { 495 if (b == *buffer.buffer) { 496 return true; 497 } 498 } 499 return false; 500 } 501 502 void Camera3Stream::removeOutstandingBuffer(const camera3_stream_buffer &buffer) { 503 if (buffer.buffer == nullptr) { 504 return; 505 } 506 507 for (auto b = mOutstandingBuffers.begin(); b != mOutstandingBuffers.end(); b++) { 508 if (*b == *buffer.buffer) { 509 mOutstandingBuffers.erase(b); 510 return; 511 } 512 } 513 } 514 515 status_t Camera3Stream::returnBuffer(const camera3_stream_buffer &buffer, 516 nsecs_t timestamp) { 517 ATRACE_CALL(); 518 Mutex::Autolock l(mLock); 519 520 // Check if this buffer is outstanding. 521 if (!isOutstandingBuffer(buffer)) { 522 ALOGE("%s: Stream %d: Returning an unknown buffer.", __FUNCTION__, mId); 523 return BAD_VALUE; 524 } 525 526 /** 527 * TODO: Check that the state is valid first. 528 * 529 * <HAL3.2 IN_CONFIG and IN_RECONFIG in addition to CONFIGURED. 530 * >= HAL3.2 CONFIGURED only 531 * 532 * Do this for getBuffer as well. 533 */ 534 status_t res = returnBufferLocked(buffer, timestamp); 535 if (res == OK) { 536 fireBufferListenersLocked(buffer, /*acquired*/false, /*output*/true); 537 } 538 539 // Even if returning the buffer failed, we still want to signal whoever is waiting for the 540 // buffer to be returned. 541 mOutputBufferReturnedSignal.signal(); 542 543 removeOutstandingBuffer(buffer); 544 return res; 545 } 546 547 status_t Camera3Stream::getInputBuffer(camera3_stream_buffer *buffer) { 548 ATRACE_CALL(); 549 Mutex::Autolock l(mLock); 550 status_t res = OK; 551 552 // This function should be only called when the stream is configured already. 553 if (mState != STATE_CONFIGURED) { 554 ALOGE("%s: Stream %d: Can't get input buffers if stream is not in CONFIGURED state %d", 555 __FUNCTION__, mId, mState); 556 return INVALID_OPERATION; 557 } 558 559 // Wait for new buffer returned back if we are running into the limit. 560 if (getHandoutInputBufferCountLocked() == camera3_stream::max_buffers) { 561 ALOGV("%s: Already dequeued max input buffers (%d), wait for next returned one.", 562 __FUNCTION__, camera3_stream::max_buffers); 563 res = mInputBufferReturnedSignal.waitRelative(mLock, kWaitForBufferDuration); 564 if (res != OK) { 565 if (res == TIMED_OUT) { 566 ALOGE("%s: wait for input buffer return timed out after %lldms", __FUNCTION__, 567 kWaitForBufferDuration / 1000000LL); 568 } 569 return res; 570 } 571 } 572 573 res = getInputBufferLocked(buffer); 574 if (res == OK) { 575 fireBufferListenersLocked(*buffer, /*acquired*/true, /*output*/false); 576 if (buffer->buffer) { 577 mOutstandingBuffers.push_back(*buffer->buffer); 578 } 579 } 580 581 return res; 582 } 583 584 status_t Camera3Stream::returnInputBuffer(const camera3_stream_buffer &buffer) { 585 ATRACE_CALL(); 586 Mutex::Autolock l(mLock); 587 588 // Check if this buffer is outstanding. 589 if (!isOutstandingBuffer(buffer)) { 590 ALOGE("%s: Stream %d: Returning an unknown buffer.", __FUNCTION__, mId); 591 return BAD_VALUE; 592 } 593 594 status_t res = returnInputBufferLocked(buffer); 595 if (res == OK) { 596 fireBufferListenersLocked(buffer, /*acquired*/false, /*output*/false); 597 mInputBufferReturnedSignal.signal(); 598 } 599 600 removeOutstandingBuffer(buffer); 601 return res; 602 } 603 604 status_t Camera3Stream::getInputBufferProducer(sp<IGraphicBufferProducer> *producer) { 605 ATRACE_CALL(); 606 Mutex::Autolock l(mLock); 607 608 return getInputBufferProducerLocked(producer); 609 } 610 611 void Camera3Stream::fireBufferListenersLocked( 612 const camera3_stream_buffer& buffer, bool acquired, bool output) { 613 List<wp<Camera3StreamBufferListener> >::iterator it, end; 614 615 // TODO: finish implementing 616 617 Camera3StreamBufferListener::BufferInfo info = 618 Camera3StreamBufferListener::BufferInfo(); 619 info.mOutput = output; 620 info.mError = (buffer.status == CAMERA3_BUFFER_STATUS_ERROR); 621 // TODO: rest of fields 622 623 for (it = mBufferListenerList.begin(), end = mBufferListenerList.end(); 624 it != end; 625 ++it) { 626 627 sp<Camera3StreamBufferListener> listener = it->promote(); 628 if (listener != 0) { 629 if (acquired) { 630 listener->onBufferAcquired(info); 631 } else { 632 listener->onBufferReleased(info); 633 } 634 } 635 } 636 } 637 638 bool Camera3Stream::hasOutstandingBuffers() const { 639 ATRACE_CALL(); 640 Mutex::Autolock l(mLock); 641 return hasOutstandingBuffersLocked(); 642 } 643 644 status_t Camera3Stream::setStatusTracker(sp<StatusTracker> statusTracker) { 645 Mutex::Autolock l(mLock); 646 sp<StatusTracker> oldTracker = mStatusTracker.promote(); 647 if (oldTracker != 0 && mStatusId != StatusTracker::NO_STATUS_ID) { 648 oldTracker->removeComponent(mStatusId); 649 } 650 mStatusId = StatusTracker::NO_STATUS_ID; 651 mStatusTracker = statusTracker; 652 653 return OK; 654 } 655 656 status_t Camera3Stream::disconnect() { 657 ATRACE_CALL(); 658 Mutex::Autolock l(mLock); 659 ALOGV("%s: Stream %d: Disconnecting...", __FUNCTION__, mId); 660 status_t res = disconnectLocked(); 661 662 mBufferLimitLatency.log("Stream %d latency histogram for wait on max_buffers", mId); 663 mBufferLimitLatency.reset(); 664 665 if (res == -ENOTCONN) { 666 // "Already disconnected" -- not an error 667 return OK; 668 } else { 669 return res; 670 } 671 } 672 673 void Camera3Stream::dump(int fd, const Vector<String16> &args) const 674 { 675 (void)args; 676 mBufferLimitLatency.dump(fd, 677 " Latency histogram for wait on max_buffers"); 678 } 679 680 status_t Camera3Stream::getBufferLocked(camera3_stream_buffer *, 681 const std::vector<size_t>&) { 682 ALOGE("%s: This type of stream does not support output", __FUNCTION__); 683 return INVALID_OPERATION; 684 } 685 status_t Camera3Stream::returnBufferLocked(const camera3_stream_buffer &, 686 nsecs_t) { 687 ALOGE("%s: This type of stream does not support output", __FUNCTION__); 688 return INVALID_OPERATION; 689 } 690 status_t Camera3Stream::getInputBufferLocked(camera3_stream_buffer *) { 691 ALOGE("%s: This type of stream does not support input", __FUNCTION__); 692 return INVALID_OPERATION; 693 } 694 status_t Camera3Stream::returnInputBufferLocked( 695 const camera3_stream_buffer &) { 696 ALOGE("%s: This type of stream does not support input", __FUNCTION__); 697 return INVALID_OPERATION; 698 } 699 status_t Camera3Stream::getInputBufferProducerLocked(sp<IGraphicBufferProducer>*) { 700 ALOGE("%s: This type of stream does not support input", __FUNCTION__); 701 return INVALID_OPERATION; 702 } 703 704 void Camera3Stream::addBufferListener( 705 wp<Camera3StreamBufferListener> listener) { 706 Mutex::Autolock l(mLock); 707 708 List<wp<Camera3StreamBufferListener> >::iterator it, end; 709 for (it = mBufferListenerList.begin(), end = mBufferListenerList.end(); 710 it != end; 711 ) { 712 if (*it == listener) { 713 ALOGE("%s: Try to add the same listener twice, ignoring...", __FUNCTION__); 714 return; 715 } 716 it++; 717 } 718 719 mBufferListenerList.push_back(listener); 720 } 721 722 void Camera3Stream::removeBufferListener( 723 const sp<Camera3StreamBufferListener>& listener) { 724 Mutex::Autolock l(mLock); 725 726 bool erased = true; 727 List<wp<Camera3StreamBufferListener> >::iterator it, end; 728 for (it = mBufferListenerList.begin(), end = mBufferListenerList.end(); 729 it != end; 730 ) { 731 732 if (*it == listener) { 733 it = mBufferListenerList.erase(it); 734 erased = true; 735 } else { 736 ++it; 737 } 738 } 739 740 if (!erased) { 741 ALOGW("%s: Could not find listener to remove, already removed", 742 __FUNCTION__); 743 } 744 } 745 746 void Camera3Stream::setBufferFreedListener( 747 Camera3StreamBufferFreedListener* listener) { 748 Mutex::Autolock l(mLock); 749 // Only allow set listener during stream configuration because stream is guaranteed to be IDLE 750 // at this state, so setBufferFreedListener won't collide with onBufferFreed callbacks 751 if (mState != STATE_IN_CONFIG && mState != STATE_IN_RECONFIG) { 752 ALOGE("%s: listener must be set during stream configuration!",__FUNCTION__); 753 return; 754 } 755 mBufferFreedListener = listener; 756 } 757 758 }; // namespace camera3 759 760 }; // namespace android 761