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