BufferQueueProducer.cpp revision ccdfd60d79a8b7f1ed6401d0f2e8e29166a10584
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#include <inttypes.h>
18
19#define LOG_TAG "BufferQueueProducer"
20#define ATRACE_TAG ATRACE_TAG_GRAPHICS
21//#define LOG_NDEBUG 0
22
23#define EGL_EGLEXT_PROTOTYPES
24
25#include <gui/BufferItem.h>
26#include <gui/BufferQueueCore.h>
27#include <gui/BufferQueueProducer.h>
28#include <gui/IConsumerListener.h>
29#include <gui/IGraphicBufferAlloc.h>
30#include <gui/IProducerListener.h>
31
32#include <utils/Log.h>
33#include <utils/Trace.h>
34
35namespace android {
36
37BufferQueueProducer::BufferQueueProducer(const sp<BufferQueueCore>& core) :
38    mCore(core),
39    mSlots(core->mSlots),
40    mConsumerName(),
41    mStickyTransform(0),
42    mLastQueueBufferFence(Fence::NO_FENCE),
43    mCallbackMutex(),
44    mNextCallbackTicket(0),
45    mCurrentCallbackTicket(0),
46    mCallbackCondition() {}
47
48BufferQueueProducer::~BufferQueueProducer() {}
49
50status_t BufferQueueProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
51    ATRACE_CALL();
52    BQ_LOGV("requestBuffer: slot %d", slot);
53    Mutex::Autolock lock(mCore->mMutex);
54
55    if (mCore->mIsAbandoned) {
56        BQ_LOGE("requestBuffer: BufferQueue has been abandoned");
57        return NO_INIT;
58    }
59
60    if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
61        BQ_LOGE("requestBuffer: BufferQueue has no connected producer");
62        return NO_INIT;
63    }
64
65    if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
66        BQ_LOGE("requestBuffer: slot index %d out of range [0, %d)",
67                slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
68        return BAD_VALUE;
69    } else if (!mSlots[slot].mBufferState.isDequeued()) {
70        BQ_LOGE("requestBuffer: slot %d is not owned by the producer "
71                "(state = %s)", slot, mSlots[slot].mBufferState.string());
72        return BAD_VALUE;
73    }
74
75    mSlots[slot].mRequestBufferCalled = true;
76    *buf = mSlots[slot].mGraphicBuffer;
77    return NO_ERROR;
78}
79
80status_t BufferQueueProducer::setMaxDequeuedBufferCount(
81        int maxDequeuedBuffers) {
82    ATRACE_CALL();
83    BQ_LOGV("setMaxDequeuedBufferCount: maxDequeuedBuffers = %d",
84            maxDequeuedBuffers);
85
86    sp<IConsumerListener> listener;
87    { // Autolock scope
88        Mutex::Autolock lock(mCore->mMutex);
89        mCore->waitWhileAllocatingLocked();
90
91        if (mCore->mIsAbandoned) {
92            BQ_LOGE("setMaxDequeuedBufferCount: BufferQueue has been "
93                    "abandoned");
94            return NO_INIT;
95        }
96
97        // There must be no dequeued buffers when changing the buffer count.
98        for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
99            if (mSlots[s].mBufferState.isDequeued()) {
100                BQ_LOGE("setMaxDequeuedBufferCount: buffer owned by producer");
101                return BAD_VALUE;
102            }
103        }
104
105        int bufferCount = mCore->getMinUndequeuedBufferCountLocked();
106        bufferCount += maxDequeuedBuffers;
107
108        if (bufferCount > BufferQueueDefs::NUM_BUFFER_SLOTS) {
109            BQ_LOGE("setMaxDequeuedBufferCount: bufferCount %d too large "
110                    "(max %d)", bufferCount, BufferQueueDefs::NUM_BUFFER_SLOTS);
111            return BAD_VALUE;
112        }
113
114        const int minBufferSlots = mCore->getMinMaxBufferCountLocked();
115        if (bufferCount < minBufferSlots) {
116            BQ_LOGE("setMaxDequeuedBufferCount: requested buffer count %d is "
117                    "less than minimum %d", bufferCount, minBufferSlots);
118            return BAD_VALUE;
119        }
120
121        if (bufferCount > mCore->mMaxBufferCount) {
122            BQ_LOGE("setMaxDequeuedBufferCount: %d dequeued buffers would "
123                    "exceed the maxBufferCount (%d) (maxAcquired %d async %d "
124                    "mDequeuedBufferCannotBlock %d)", maxDequeuedBuffers,
125                    mCore->mMaxBufferCount, mCore->mMaxAcquiredBufferCount,
126                    mCore->mAsyncMode, mCore->mDequeueBufferCannotBlock);
127            return BAD_VALUE;
128        }
129
130        // Here we are guaranteed that the producer doesn't have any dequeued
131        // buffers and will release all of its buffer references. We don't
132        // clear the queue, however, so that currently queued buffers still
133        // get displayed.
134        mCore->freeAllBuffersLocked();
135        mCore->mMaxDequeuedBufferCount = maxDequeuedBuffers;
136        mCore->mDequeueCondition.broadcast();
137        listener = mCore->mConsumerListener;
138    } // Autolock scope
139
140    // Call back without lock held
141    if (listener != NULL) {
142        listener->onBuffersReleased();
143    }
144
145    return NO_ERROR;
146}
147
148status_t BufferQueueProducer::setAsyncMode(bool async) {
149    ATRACE_CALL();
150    BQ_LOGV("setAsyncMode: async = %d", async);
151
152    sp<IConsumerListener> listener;
153    { // Autolock scope
154        Mutex::Autolock lock(mCore->mMutex);
155        mCore->waitWhileAllocatingLocked();
156
157        if (mCore->mIsAbandoned) {
158            BQ_LOGE("setAsyncMode: BufferQueue has been abandoned");
159            return NO_INIT;
160        }
161
162        if ((mCore->mMaxAcquiredBufferCount + mCore->mMaxDequeuedBufferCount +
163                (async || mCore->mDequeueBufferCannotBlock ? 1 : 0)) >
164                mCore->mMaxBufferCount) {
165            BQ_LOGE("setAsyncMode(%d): this call would cause the "
166                    "maxBufferCount (%d) to be exceeded (maxAcquired %d "
167                    "maxDequeued %d mDequeueBufferCannotBlock %d)", async,
168                    mCore->mMaxBufferCount, mCore->mMaxAcquiredBufferCount,
169                    mCore->mMaxDequeuedBufferCount,
170                    mCore->mDequeueBufferCannotBlock);
171            return BAD_VALUE;
172        }
173
174        mCore->mAsyncMode = async;
175        mCore->mDequeueCondition.broadcast();
176        listener = mCore->mConsumerListener;
177    } // Autolock scope
178
179    // Call back without lock held
180    if (listener != NULL) {
181        listener->onBuffersReleased();
182    }
183    return NO_ERROR;
184}
185
186status_t BufferQueueProducer::waitForFreeSlotThenRelock(const char* caller,
187        int* found, status_t* returnFlags) const {
188    bool tryAgain = true;
189    while (tryAgain) {
190        if (mCore->mIsAbandoned) {
191            BQ_LOGE("%s: BufferQueue has been abandoned", caller);
192            return NO_INIT;
193        }
194
195        const int maxBufferCount = mCore->getMaxBufferCountLocked();
196
197        // Free up any buffers that are in slots beyond the max buffer count
198        for (int s = maxBufferCount; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
199            assert(mSlots[s].mBufferState.isFree());
200            if (mSlots[s].mGraphicBuffer != NULL) {
201                mCore->freeBufferLocked(s);
202                *returnFlags |= RELEASE_ALL_BUFFERS;
203            }
204        }
205
206        int dequeuedCount = 0;
207        int acquiredCount = 0;
208        for (int s = 0; s < maxBufferCount; ++s) {
209            if (mSlots[s].mBufferState.isDequeued()) {
210                ++dequeuedCount;
211            }
212            if (mSlots[s].mBufferState.isAcquired()) {
213                ++acquiredCount;
214            }
215        }
216
217        // Producers are not allowed to dequeue more than
218        // mMaxDequeuedBufferCount buffers.
219        // This check is only done if a buffer has already been queued
220        if (mCore->mBufferHasBeenQueued &&
221                dequeuedCount >= mCore->mMaxDequeuedBufferCount) {
222            BQ_LOGE("%s: attempting to exceed the max dequeued buffer count "
223                    "(%d)", caller, mCore->mMaxDequeuedBufferCount);
224            return INVALID_OPERATION;
225        }
226
227        *found = BufferQueueCore::INVALID_BUFFER_SLOT;
228
229        // If we disconnect and reconnect quickly, we can be in a state where
230        // our slots are empty but we have many buffers in the queue. This can
231        // cause us to run out of memory if we outrun the consumer. Wait here if
232        // it looks like we have too many buffers queued up.
233        bool tooManyBuffers = mCore->mQueue.size()
234                            > static_cast<size_t>(maxBufferCount);
235        if (tooManyBuffers) {
236            BQ_LOGV("%s: queue size is %zu, waiting", caller,
237                    mCore->mQueue.size());
238        } else {
239            // If in single buffer mode and a shared buffer exists, always
240            // return it.
241            if (mCore->mSingleBufferMode && mCore->mSingleBufferSlot !=
242                    BufferQueueCore::INVALID_BUFFER_SLOT) {
243                *found = mCore->mSingleBufferSlot;
244            } else if (!mCore->mFreeBuffers.empty()) {
245                auto slot = mCore->mFreeBuffers.begin();
246                *found = *slot;
247                mCore->mFreeBuffers.erase(slot);
248            } else if (mCore->mAllowAllocation && !mCore->mFreeSlots.empty()) {
249                auto slot = mCore->mFreeSlots.begin();
250                // Only return free slots up to the max buffer count
251                if (*slot < maxBufferCount) {
252                    *found = *slot;
253                    mCore->mFreeSlots.erase(slot);
254                }
255            }
256        }
257
258        // If no buffer is found, or if the queue has too many buffers
259        // outstanding, wait for a buffer to be acquired or released, or for the
260        // max buffer count to change.
261        tryAgain = (*found == BufferQueueCore::INVALID_BUFFER_SLOT) ||
262                   tooManyBuffers;
263        if (tryAgain) {
264            // Return an error if we're in non-blocking mode (producer and
265            // consumer are controlled by the application).
266            // However, the consumer is allowed to briefly acquire an extra
267            // buffer (which could cause us to have to wait here), which is
268            // okay, since it is only used to implement an atomic acquire +
269            // release (e.g., in GLConsumer::updateTexImage())
270            if ((mCore->mDequeueBufferCannotBlock || mCore->mAsyncMode) &&
271                    (acquiredCount <= mCore->mMaxAcquiredBufferCount)) {
272                return WOULD_BLOCK;
273            }
274            mCore->mDequeueCondition.wait(mCore->mMutex);
275        }
276    } // while (tryAgain)
277
278    return NO_ERROR;
279}
280
281status_t BufferQueueProducer::dequeueBuffer(int *outSlot,
282        sp<android::Fence> *outFence, uint32_t width, uint32_t height,
283        PixelFormat format, uint32_t usage) {
284    ATRACE_CALL();
285    { // Autolock scope
286        Mutex::Autolock lock(mCore->mMutex);
287        mConsumerName = mCore->mConsumerName;
288
289        if (mCore->mIsAbandoned) {
290            BQ_LOGE("dequeueBuffer: BufferQueue has been abandoned");
291            return NO_INIT;
292        }
293
294        if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
295            BQ_LOGE("dequeueBuffer: BufferQueue has no connected producer");
296            return NO_INIT;
297        }
298    } // Autolock scope
299
300    BQ_LOGV("dequeueBuffer: w=%u h=%u format=%#x, usage=%#x", width, height,
301            format, usage);
302
303    if ((width && !height) || (!width && height)) {
304        BQ_LOGE("dequeueBuffer: invalid size: w=%u h=%u", width, height);
305        return BAD_VALUE;
306    }
307
308    status_t returnFlags = NO_ERROR;
309    EGLDisplay eglDisplay = EGL_NO_DISPLAY;
310    EGLSyncKHR eglFence = EGL_NO_SYNC_KHR;
311    bool attachedByConsumer = false;
312
313    { // Autolock scope
314        Mutex::Autolock lock(mCore->mMutex);
315        mCore->waitWhileAllocatingLocked();
316
317        if (format == 0) {
318            format = mCore->mDefaultBufferFormat;
319        }
320
321        // Enable the usage bits the consumer requested
322        usage |= mCore->mConsumerUsageBits;
323
324        const bool useDefaultSize = !width && !height;
325        if (useDefaultSize) {
326            width = mCore->mDefaultWidth;
327            height = mCore->mDefaultHeight;
328        }
329
330        int found = BufferItem::INVALID_BUFFER_SLOT;
331        while (found == BufferItem::INVALID_BUFFER_SLOT) {
332            status_t status = waitForFreeSlotThenRelock("dequeueBuffer", &found,
333                    &returnFlags);
334            if (status != NO_ERROR) {
335                return status;
336            }
337
338            // This should not happen
339            if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
340                BQ_LOGE("dequeueBuffer: no available buffer slots");
341                return -EBUSY;
342            }
343
344            const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
345
346            // If we are not allowed to allocate new buffers,
347            // waitForFreeSlotThenRelock must have returned a slot containing a
348            // buffer. If this buffer would require reallocation to meet the
349            // requested attributes, we free it and attempt to get another one.
350            if (!mCore->mAllowAllocation) {
351                if (buffer->needsReallocation(width, height, format, usage)) {
352                    if (mCore->mSingleBufferMode &&
353                            mCore->mSingleBufferSlot == found) {
354                        BQ_LOGE("dequeueBuffer: cannot re-allocate a shared"
355                                "buffer");
356                        return BAD_VALUE;
357                    }
358
359                    mCore->freeBufferLocked(found);
360                    found = BufferItem::INVALID_BUFFER_SLOT;
361                    continue;
362                }
363            }
364        }
365
366        *outSlot = found;
367        ATRACE_BUFFER_INDEX(found);
368
369        attachedByConsumer = mSlots[found].mAttachedByConsumer;
370
371        mSlots[found].mBufferState.dequeue();
372
373        // If single buffer mode has just been enabled, cache the slot of the
374        // first buffer that is dequeued and mark it as the shared buffer.
375        if (mCore->mSingleBufferMode && mCore->mSingleBufferSlot ==
376                BufferQueueCore::INVALID_BUFFER_SLOT) {
377            mCore->mSingleBufferSlot = found;
378            mSlots[found].mBufferState.mShared = true;
379        }
380
381        const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
382        if ((buffer == NULL) ||
383                buffer->needsReallocation(width, height, format, usage))
384        {
385            mSlots[found].mAcquireCalled = false;
386            mSlots[found].mGraphicBuffer = NULL;
387            mSlots[found].mRequestBufferCalled = false;
388            mSlots[found].mEglDisplay = EGL_NO_DISPLAY;
389            mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
390            mSlots[found].mFence = Fence::NO_FENCE;
391            mCore->mBufferAge = 0;
392            mCore->mIsAllocating = true;
393
394            returnFlags |= BUFFER_NEEDS_REALLOCATION;
395        } else {
396            // We add 1 because that will be the frame number when this buffer
397            // is queued
398            mCore->mBufferAge =
399                    mCore->mFrameCounter + 1 - mSlots[found].mFrameNumber;
400        }
401
402        BQ_LOGV("dequeueBuffer: setting buffer age to %" PRIu64,
403                mCore->mBufferAge);
404
405        if (CC_UNLIKELY(mSlots[found].mFence == NULL)) {
406            BQ_LOGE("dequeueBuffer: about to return a NULL fence - "
407                    "slot=%d w=%d h=%d format=%u",
408                    found, buffer->width, buffer->height, buffer->format);
409        }
410
411        eglDisplay = mSlots[found].mEglDisplay;
412        eglFence = mSlots[found].mEglFence;
413        *outFence = mSlots[found].mFence;
414        mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
415        mSlots[found].mFence = Fence::NO_FENCE;
416
417        mCore->validateConsistencyLocked();
418    } // Autolock scope
419
420    if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
421        status_t error;
422        BQ_LOGV("dequeueBuffer: allocating a new buffer for slot %d", *outSlot);
423        sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
424                width, height, format, usage, &error));
425        { // Autolock scope
426            Mutex::Autolock lock(mCore->mMutex);
427
428            if (graphicBuffer != NULL && !mCore->mIsAbandoned) {
429                graphicBuffer->setGenerationNumber(mCore->mGenerationNumber);
430                mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
431            }
432
433            mCore->mIsAllocating = false;
434            mCore->mIsAllocatingCondition.broadcast();
435
436            if (graphicBuffer == NULL) {
437                BQ_LOGE("dequeueBuffer: createGraphicBuffer failed");
438                return error;
439            }
440
441            if (mCore->mIsAbandoned) {
442                BQ_LOGE("dequeueBuffer: BufferQueue has been abandoned");
443                return NO_INIT;
444            }
445        } // Autolock scope
446    }
447
448    if (attachedByConsumer) {
449        returnFlags |= BUFFER_NEEDS_REALLOCATION;
450    }
451
452    if (eglFence != EGL_NO_SYNC_KHR) {
453        EGLint result = eglClientWaitSyncKHR(eglDisplay, eglFence, 0,
454                1000000000);
455        // If something goes wrong, log the error, but return the buffer without
456        // synchronizing access to it. It's too late at this point to abort the
457        // dequeue operation.
458        if (result == EGL_FALSE) {
459            BQ_LOGE("dequeueBuffer: error %#x waiting for fence",
460                    eglGetError());
461        } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
462            BQ_LOGE("dequeueBuffer: timeout waiting for fence");
463        }
464        eglDestroySyncKHR(eglDisplay, eglFence);
465    }
466
467    BQ_LOGV("dequeueBuffer: returning slot=%d/%" PRIu64 " buf=%p flags=%#x",
468            *outSlot,
469            mSlots[*outSlot].mFrameNumber,
470            mSlots[*outSlot].mGraphicBuffer->handle, returnFlags);
471
472    return returnFlags;
473}
474
475status_t BufferQueueProducer::detachBuffer(int slot) {
476    ATRACE_CALL();
477    ATRACE_BUFFER_INDEX(slot);
478    BQ_LOGV("detachBuffer: slot %d", slot);
479    Mutex::Autolock lock(mCore->mMutex);
480
481    if (mCore->mIsAbandoned) {
482        BQ_LOGE("detachBuffer: BufferQueue has been abandoned");
483        return NO_INIT;
484    }
485
486    if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
487        BQ_LOGE("detachBuffer: BufferQueue has no connected producer");
488        return NO_INIT;
489    }
490
491    if (mCore->mSingleBufferMode) {
492        BQ_LOGE("detachBuffer: cannot detach a buffer in single buffer"
493                "mode");
494        return BAD_VALUE;
495    }
496
497    if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
498        BQ_LOGE("detachBuffer: slot index %d out of range [0, %d)",
499                slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
500        return BAD_VALUE;
501    } else if (!mSlots[slot].mBufferState.isDequeued()) {
502        BQ_LOGE("detachBuffer: slot %d is not owned by the producer "
503                "(state = %s)", slot, mSlots[slot].mBufferState.string());
504        return BAD_VALUE;
505    } else if (!mSlots[slot].mRequestBufferCalled) {
506        BQ_LOGE("detachBuffer: buffer in slot %d has not been requested",
507                slot);
508        return BAD_VALUE;
509    }
510
511    mSlots[slot].mBufferState.detachProducer();
512    mCore->freeBufferLocked(slot);
513    mCore->mDequeueCondition.broadcast();
514    mCore->validateConsistencyLocked();
515
516    return NO_ERROR;
517}
518
519status_t BufferQueueProducer::detachNextBuffer(sp<GraphicBuffer>* outBuffer,
520        sp<Fence>* outFence) {
521    ATRACE_CALL();
522
523    if (outBuffer == NULL) {
524        BQ_LOGE("detachNextBuffer: outBuffer must not be NULL");
525        return BAD_VALUE;
526    } else if (outFence == NULL) {
527        BQ_LOGE("detachNextBuffer: outFence must not be NULL");
528        return BAD_VALUE;
529    }
530
531    Mutex::Autolock lock(mCore->mMutex);
532
533    if (mCore->mIsAbandoned) {
534        BQ_LOGE("detachNextBuffer: BufferQueue has been abandoned");
535        return NO_INIT;
536    }
537
538    if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
539        BQ_LOGE("detachNextBuffer: BufferQueue has no connected producer");
540        return NO_INIT;
541    }
542
543    if (mCore->mSingleBufferMode) {
544        BQ_LOGE("detachNextBuffer: cannot detach a buffer in single buffer"
545                "mode");
546        return BAD_VALUE;
547    }
548
549    mCore->waitWhileAllocatingLocked();
550
551    if (mCore->mFreeBuffers.empty()) {
552        return NO_MEMORY;
553    }
554
555    int found = mCore->mFreeBuffers.front();
556    mCore->mFreeBuffers.remove(found);
557
558    BQ_LOGV("detachNextBuffer detached slot %d", found);
559
560    *outBuffer = mSlots[found].mGraphicBuffer;
561    *outFence = mSlots[found].mFence;
562    mCore->freeBufferLocked(found);
563    mCore->validateConsistencyLocked();
564
565    return NO_ERROR;
566}
567
568status_t BufferQueueProducer::attachBuffer(int* outSlot,
569        const sp<android::GraphicBuffer>& buffer) {
570    ATRACE_CALL();
571
572    if (outSlot == NULL) {
573        BQ_LOGE("attachBuffer: outSlot must not be NULL");
574        return BAD_VALUE;
575    } else if (buffer == NULL) {
576        BQ_LOGE("attachBuffer: cannot attach NULL buffer");
577        return BAD_VALUE;
578    }
579
580    Mutex::Autolock lock(mCore->mMutex);
581
582    if (mCore->mIsAbandoned) {
583        BQ_LOGE("attachBuffer: BufferQueue has been abandoned");
584        return NO_INIT;
585    }
586
587    if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
588        BQ_LOGE("attachBuffer: BufferQueue has no connected producer");
589        return NO_INIT;
590    }
591
592    if (mCore->mSingleBufferMode) {
593        BQ_LOGE("attachBuffer: cannot atach a buffer in single buffer mode");
594        return BAD_VALUE;
595    }
596
597    if (buffer->getGenerationNumber() != mCore->mGenerationNumber) {
598        BQ_LOGE("attachBuffer: generation number mismatch [buffer %u] "
599                "[queue %u]", buffer->getGenerationNumber(),
600                mCore->mGenerationNumber);
601        return BAD_VALUE;
602    }
603
604    mCore->waitWhileAllocatingLocked();
605
606    status_t returnFlags = NO_ERROR;
607    int found;
608    status_t status = waitForFreeSlotThenRelock("attachBuffer", &found,
609            &returnFlags);
610    if (status != NO_ERROR) {
611        return status;
612    }
613
614    // This should not happen
615    if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
616        BQ_LOGE("attachBuffer: no available buffer slots");
617        return -EBUSY;
618    }
619
620    *outSlot = found;
621    ATRACE_BUFFER_INDEX(*outSlot);
622    BQ_LOGV("attachBuffer: returning slot %d flags=%#x",
623            *outSlot, returnFlags);
624
625    mSlots[*outSlot].mGraphicBuffer = buffer;
626    mSlots[*outSlot].mBufferState.attachProducer();
627    mSlots[*outSlot].mEglFence = EGL_NO_SYNC_KHR;
628    mSlots[*outSlot].mFence = Fence::NO_FENCE;
629    mSlots[*outSlot].mRequestBufferCalled = true;
630
631    mCore->validateConsistencyLocked();
632
633    return returnFlags;
634}
635
636status_t BufferQueueProducer::queueBuffer(int slot,
637        const QueueBufferInput &input, QueueBufferOutput *output) {
638    ATRACE_CALL();
639    ATRACE_BUFFER_INDEX(slot);
640
641    int64_t timestamp;
642    bool isAutoTimestamp;
643    android_dataspace dataSpace;
644    Rect crop(Rect::EMPTY_RECT);
645    int scalingMode;
646    uint32_t transform;
647    uint32_t stickyTransform;
648    sp<Fence> fence;
649    input.deflate(&timestamp, &isAutoTimestamp, &dataSpace, &crop, &scalingMode,
650            &transform, &fence, &stickyTransform);
651    Region surfaceDamage = input.getSurfaceDamage();
652
653    if (fence == NULL) {
654        BQ_LOGE("queueBuffer: fence is NULL");
655        return BAD_VALUE;
656    }
657
658    switch (scalingMode) {
659        case NATIVE_WINDOW_SCALING_MODE_FREEZE:
660        case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
661        case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
662        case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP:
663            break;
664        default:
665            BQ_LOGE("queueBuffer: unknown scaling mode %d", scalingMode);
666            return BAD_VALUE;
667    }
668
669    sp<IConsumerListener> frameAvailableListener;
670    sp<IConsumerListener> frameReplacedListener;
671    int callbackTicket = 0;
672    BufferItem item;
673    { // Autolock scope
674        Mutex::Autolock lock(mCore->mMutex);
675
676        if (mCore->mIsAbandoned) {
677            BQ_LOGE("queueBuffer: BufferQueue has been abandoned");
678            return NO_INIT;
679        }
680
681        if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
682            BQ_LOGE("queueBuffer: BufferQueue has no connected producer");
683            return NO_INIT;
684        }
685
686        const int maxBufferCount = mCore->getMaxBufferCountLocked();
687
688        if (slot < 0 || slot >= maxBufferCount) {
689            BQ_LOGE("queueBuffer: slot index %d out of range [0, %d)",
690                    slot, maxBufferCount);
691            return BAD_VALUE;
692        } else if (!mSlots[slot].mBufferState.isDequeued()) {
693            BQ_LOGE("queueBuffer: slot %d is not owned by the producer "
694                    "(state = %s)", slot, mSlots[slot].mBufferState.string());
695            return BAD_VALUE;
696        } else if (!mSlots[slot].mRequestBufferCalled) {
697            BQ_LOGE("queueBuffer: slot %d was queued without requesting "
698                    "a buffer", slot);
699            return BAD_VALUE;
700        }
701
702        BQ_LOGV("queueBuffer: slot=%d/%" PRIu64 " time=%" PRIu64 " dataSpace=%d"
703                " crop=[%d,%d,%d,%d] transform=%#x scale=%s",
704                slot, mCore->mFrameCounter + 1, timestamp, dataSpace,
705                crop.left, crop.top, crop.right, crop.bottom, transform,
706                BufferItem::scalingModeName(static_cast<uint32_t>(scalingMode)));
707
708        const sp<GraphicBuffer>& graphicBuffer(mSlots[slot].mGraphicBuffer);
709        Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight());
710        Rect croppedRect(Rect::EMPTY_RECT);
711        crop.intersect(bufferRect, &croppedRect);
712        if (croppedRect != crop) {
713            BQ_LOGE("queueBuffer: crop rect is not contained within the "
714                    "buffer in slot %d", slot);
715            return BAD_VALUE;
716        }
717
718        // Override UNKNOWN dataspace with consumer default
719        if (dataSpace == HAL_DATASPACE_UNKNOWN) {
720            dataSpace = mCore->mDefaultBufferDataSpace;
721        }
722
723        mSlots[slot].mFence = fence;
724        mSlots[slot].mBufferState.queue();
725
726        ++mCore->mFrameCounter;
727        mSlots[slot].mFrameNumber = mCore->mFrameCounter;
728
729        item.mAcquireCalled = mSlots[slot].mAcquireCalled;
730        item.mGraphicBuffer = mSlots[slot].mGraphicBuffer;
731        item.mCrop = crop;
732        item.mTransform = transform &
733                ~static_cast<uint32_t>(NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY);
734        item.mTransformToDisplayInverse =
735                (transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) != 0;
736        item.mScalingMode = static_cast<uint32_t>(scalingMode);
737        item.mTimestamp = timestamp;
738        item.mIsAutoTimestamp = isAutoTimestamp;
739        item.mDataSpace = dataSpace;
740        item.mFrameNumber = mCore->mFrameCounter;
741        item.mSlot = slot;
742        item.mFence = fence;
743        item.mIsDroppable = mCore->mAsyncMode ||
744                mCore->mDequeueBufferCannotBlock ||
745                (mCore->mSingleBufferMode && mCore->mSingleBufferSlot == slot);
746        item.mSurfaceDamage = surfaceDamage;
747
748        mStickyTransform = stickyTransform;
749
750        // Cache the shared buffer data so that the BufferItem can be recreated.
751        if (mCore->mSingleBufferMode) {
752            mCore->mSingleBufferCache.crop = crop;
753            mCore->mSingleBufferCache.transform = transform;
754            mCore->mSingleBufferCache.scalingMode = static_cast<uint32_t>(
755                    scalingMode);
756            mCore->mSingleBufferCache.dataspace = dataSpace;
757        }
758
759        if (mCore->mQueue.empty()) {
760            // When the queue is empty, we can ignore mDequeueBufferCannotBlock
761            // and simply queue this buffer
762            mCore->mQueue.push_back(item);
763            frameAvailableListener = mCore->mConsumerListener;
764        } else {
765            // When the queue is not empty, we need to look at the front buffer
766            // state to see if we need to replace it
767            BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin());
768            if (front->mIsDroppable) {
769                // If the front queued buffer is still being tracked, we first
770                // mark it as freed
771                if (mCore->stillTracking(front)) {
772                    mSlots[front->mSlot].mBufferState.freeQueued();
773
774                    // After leaving single buffer mode, the shared buffer will
775                    // still be around. Mark it as no longer shared if this
776                    // operation causes it to be free.
777                    if (!mCore->mSingleBufferMode &&
778                            mSlots[front->mSlot].mBufferState.isFree()) {
779                        mSlots[front->mSlot].mBufferState.mShared = false;
780                    }
781                    // Don't put the shared buffer on the free list.
782                    if (!mSlots[front->mSlot].mBufferState.isShared()) {
783                        mCore->mFreeBuffers.push_front(front->mSlot);
784                    }
785                }
786                // Overwrite the droppable buffer with the incoming one
787                *front = item;
788                frameReplacedListener = mCore->mConsumerListener;
789            } else {
790                mCore->mQueue.push_back(item);
791                frameAvailableListener = mCore->mConsumerListener;
792            }
793        }
794
795        mCore->mBufferHasBeenQueued = true;
796        mCore->mDequeueCondition.broadcast();
797
798        output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
799                mCore->mTransformHint,
800                static_cast<uint32_t>(mCore->mQueue.size()));
801
802        ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size());
803
804        // Take a ticket for the callback functions
805        callbackTicket = mNextCallbackTicket++;
806
807        mCore->validateConsistencyLocked();
808    } // Autolock scope
809
810    // Wait without lock held
811    if (mCore->mConnectedApi == NATIVE_WINDOW_API_EGL) {
812        // Waiting here allows for two full buffers to be queued but not a
813        // third. In the event that frames take varying time, this makes a
814        // small trade-off in favor of latency rather than throughput.
815        mLastQueueBufferFence->waitForever("Throttling EGL Production");
816        mLastQueueBufferFence = fence;
817    }
818
819    // Don't send the GraphicBuffer through the callback, and don't send
820    // the slot number, since the consumer shouldn't need it
821    item.mGraphicBuffer.clear();
822    item.mSlot = BufferItem::INVALID_BUFFER_SLOT;
823
824    // Call back without the main BufferQueue lock held, but with the callback
825    // lock held so we can ensure that callbacks occur in order
826    {
827        Mutex::Autolock lock(mCallbackMutex);
828        while (callbackTicket != mCurrentCallbackTicket) {
829            mCallbackCondition.wait(mCallbackMutex);
830        }
831
832        if (frameAvailableListener != NULL) {
833            frameAvailableListener->onFrameAvailable(item);
834        } else if (frameReplacedListener != NULL) {
835            frameReplacedListener->onFrameReplaced(item);
836        }
837
838        ++mCurrentCallbackTicket;
839        mCallbackCondition.broadcast();
840    }
841
842    return NO_ERROR;
843}
844
845status_t BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
846    ATRACE_CALL();
847    BQ_LOGV("cancelBuffer: slot %d", slot);
848    Mutex::Autolock lock(mCore->mMutex);
849
850    if (mCore->mIsAbandoned) {
851        BQ_LOGE("cancelBuffer: BufferQueue has been abandoned");
852        return NO_INIT;
853    }
854
855    if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
856        BQ_LOGE("cancelBuffer: BufferQueue has no connected producer");
857        return NO_INIT;
858    }
859
860    if (mCore->mSingleBufferMode) {
861        BQ_LOGE("cancelBuffer: cannot cancel a buffer in single buffer mode");
862        return BAD_VALUE;
863    }
864
865    if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
866        BQ_LOGE("cancelBuffer: slot index %d out of range [0, %d)",
867                slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
868        return BAD_VALUE;
869    } else if (!mSlots[slot].mBufferState.isDequeued()) {
870        BQ_LOGE("cancelBuffer: slot %d is not owned by the producer "
871                "(state = %s)", slot, mSlots[slot].mBufferState.string());
872        return BAD_VALUE;
873    } else if (fence == NULL) {
874        BQ_LOGE("cancelBuffer: fence is NULL");
875        return BAD_VALUE;
876    }
877
878    mSlots[slot].mBufferState.cancel();
879
880    // After leaving single buffer mode, the shared buffer will still be around.
881    // Mark it as no longer shared if this operation causes it to be free.
882    if (!mCore->mSingleBufferMode && mSlots[slot].mBufferState.isFree()) {
883        mSlots[slot].mBufferState.mShared = false;
884    }
885
886    // Don't put the shared buffer on the free list.
887    if (!mSlots[slot].mBufferState.isShared()) {
888        mCore->mFreeBuffers.push_front(slot);
889    }
890    mSlots[slot].mFence = fence;
891    mCore->mDequeueCondition.broadcast();
892    mCore->validateConsistencyLocked();
893
894    return NO_ERROR;
895}
896
897int BufferQueueProducer::query(int what, int *outValue) {
898    ATRACE_CALL();
899    Mutex::Autolock lock(mCore->mMutex);
900
901    if (outValue == NULL) {
902        BQ_LOGE("query: outValue was NULL");
903        return BAD_VALUE;
904    }
905
906    if (mCore->mIsAbandoned) {
907        BQ_LOGE("query: BufferQueue has been abandoned");
908        return NO_INIT;
909    }
910
911    int value;
912    switch (what) {
913        case NATIVE_WINDOW_WIDTH:
914            value = static_cast<int32_t>(mCore->mDefaultWidth);
915            break;
916        case NATIVE_WINDOW_HEIGHT:
917            value = static_cast<int32_t>(mCore->mDefaultHeight);
918            break;
919        case NATIVE_WINDOW_FORMAT:
920            value = static_cast<int32_t>(mCore->mDefaultBufferFormat);
921            break;
922        case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
923            value = mCore->getMinUndequeuedBufferCountLocked();
924            break;
925        case NATIVE_WINDOW_STICKY_TRANSFORM:
926            value = static_cast<int32_t>(mStickyTransform);
927            break;
928        case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
929            value = (mCore->mQueue.size() > 1);
930            break;
931        case NATIVE_WINDOW_CONSUMER_USAGE_BITS:
932            value = static_cast<int32_t>(mCore->mConsumerUsageBits);
933            break;
934        case NATIVE_WINDOW_DEFAULT_DATASPACE:
935            value = static_cast<int32_t>(mCore->mDefaultBufferDataSpace);
936            break;
937        case NATIVE_WINDOW_BUFFER_AGE:
938            if (mCore->mBufferAge > INT32_MAX) {
939                value = 0;
940            } else {
941                value = static_cast<int32_t>(mCore->mBufferAge);
942            }
943            break;
944        default:
945            return BAD_VALUE;
946    }
947
948    BQ_LOGV("query: %d? %d", what, value);
949    *outValue = value;
950    return NO_ERROR;
951}
952
953status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener,
954        int api, bool producerControlledByApp, QueueBufferOutput *output) {
955    ATRACE_CALL();
956    Mutex::Autolock lock(mCore->mMutex);
957    mConsumerName = mCore->mConsumerName;
958    BQ_LOGV("connect: api=%d producerControlledByApp=%s", api,
959            producerControlledByApp ? "true" : "false");
960
961    if (mCore->mIsAbandoned) {
962        BQ_LOGE("connect: BufferQueue has been abandoned");
963        return NO_INIT;
964    }
965
966    if (mCore->mConsumerListener == NULL) {
967        BQ_LOGE("connect: BufferQueue has no consumer");
968        return NO_INIT;
969    }
970
971    if (output == NULL) {
972        BQ_LOGE("connect: output was NULL");
973        return BAD_VALUE;
974    }
975
976    if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
977        BQ_LOGE("connect: already connected (cur=%d req=%d)",
978                mCore->mConnectedApi, api);
979        return BAD_VALUE;
980    }
981
982    int status = NO_ERROR;
983    switch (api) {
984        case NATIVE_WINDOW_API_EGL:
985        case NATIVE_WINDOW_API_CPU:
986        case NATIVE_WINDOW_API_MEDIA:
987        case NATIVE_WINDOW_API_CAMERA:
988            mCore->mConnectedApi = api;
989            output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
990                    mCore->mTransformHint,
991                    static_cast<uint32_t>(mCore->mQueue.size()));
992
993            // Set up a death notification so that we can disconnect
994            // automatically if the remote producer dies
995            if (listener != NULL &&
996                    IInterface::asBinder(listener)->remoteBinder() != NULL) {
997                status = IInterface::asBinder(listener)->linkToDeath(
998                        static_cast<IBinder::DeathRecipient*>(this));
999                if (status != NO_ERROR) {
1000                    BQ_LOGE("connect: linkToDeath failed: %s (%d)",
1001                            strerror(-status), status);
1002                }
1003            }
1004            mCore->mConnectedProducerListener = listener;
1005            break;
1006        default:
1007            BQ_LOGE("connect: unknown API %d", api);
1008            status = BAD_VALUE;
1009            break;
1010    }
1011
1012    mCore->mBufferHasBeenQueued = false;
1013    mCore->mDequeueBufferCannotBlock =  mCore->mConsumerControlledByApp &&
1014            producerControlledByApp;
1015    mCore->mAllowAllocation = true;
1016
1017    return status;
1018}
1019
1020status_t BufferQueueProducer::disconnect(int api) {
1021    ATRACE_CALL();
1022    BQ_LOGV("disconnect: api %d", api);
1023
1024    int status = NO_ERROR;
1025    sp<IConsumerListener> listener;
1026    { // Autolock scope
1027        Mutex::Autolock lock(mCore->mMutex);
1028        mCore->waitWhileAllocatingLocked();
1029
1030        if (mCore->mIsAbandoned) {
1031            // It's not really an error to disconnect after the surface has
1032            // been abandoned; it should just be a no-op.
1033            return NO_ERROR;
1034        }
1035
1036        switch (api) {
1037            case NATIVE_WINDOW_API_EGL:
1038            case NATIVE_WINDOW_API_CPU:
1039            case NATIVE_WINDOW_API_MEDIA:
1040            case NATIVE_WINDOW_API_CAMERA:
1041                if (mCore->mConnectedApi == api) {
1042                    mCore->freeAllBuffersLocked();
1043
1044                    // Remove our death notification callback if we have one
1045                    if (mCore->mConnectedProducerListener != NULL) {
1046                        sp<IBinder> token =
1047                                IInterface::asBinder(mCore->mConnectedProducerListener);
1048                        // This can fail if we're here because of the death
1049                        // notification, but we just ignore it
1050                        token->unlinkToDeath(
1051                                static_cast<IBinder::DeathRecipient*>(this));
1052                    }
1053                    mCore->mConnectedProducerListener = NULL;
1054                    mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API;
1055                    mCore->mSidebandStream.clear();
1056                    mCore->mDequeueCondition.broadcast();
1057                    listener = mCore->mConsumerListener;
1058                } else if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
1059                    BQ_LOGE("disconnect: still connected to another API "
1060                            "(cur=%d req=%d)", mCore->mConnectedApi, api);
1061                    status = BAD_VALUE;
1062                }
1063                break;
1064            default:
1065                BQ_LOGE("disconnect: unknown API %d", api);
1066                status = BAD_VALUE;
1067                break;
1068        }
1069    } // Autolock scope
1070
1071    // Call back without lock held
1072    if (listener != NULL) {
1073        listener->onBuffersReleased();
1074    }
1075
1076    return status;
1077}
1078
1079status_t BufferQueueProducer::setSidebandStream(const sp<NativeHandle>& stream) {
1080    sp<IConsumerListener> listener;
1081    { // Autolock scope
1082        Mutex::Autolock _l(mCore->mMutex);
1083        mCore->mSidebandStream = stream;
1084        listener = mCore->mConsumerListener;
1085    } // Autolock scope
1086
1087    if (listener != NULL) {
1088        listener->onSidebandStreamChanged();
1089    }
1090    return NO_ERROR;
1091}
1092
1093void BufferQueueProducer::allocateBuffers(uint32_t width, uint32_t height,
1094        PixelFormat format, uint32_t usage) {
1095    ATRACE_CALL();
1096    while (true) {
1097        Vector<int> freeSlots;
1098        size_t newBufferCount = 0;
1099        uint32_t allocWidth = 0;
1100        uint32_t allocHeight = 0;
1101        PixelFormat allocFormat = PIXEL_FORMAT_UNKNOWN;
1102        uint32_t allocUsage = 0;
1103        { // Autolock scope
1104            Mutex::Autolock lock(mCore->mMutex);
1105            mCore->waitWhileAllocatingLocked();
1106
1107            if (!mCore->mAllowAllocation) {
1108                BQ_LOGE("allocateBuffers: allocation is not allowed for this "
1109                        "BufferQueue");
1110                return;
1111            }
1112
1113            int currentBufferCount = 0;
1114            for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) {
1115                if (mSlots[slot].mGraphicBuffer != NULL) {
1116                    ++currentBufferCount;
1117                } else {
1118                    if (!mSlots[slot].mBufferState.isFree()) {
1119                        BQ_LOGE("allocateBuffers: slot %d without buffer is not FREE",
1120                                slot);
1121                        continue;
1122                    }
1123
1124                    freeSlots.push_back(slot);
1125                }
1126            }
1127
1128            int maxBufferCount = mCore->getMaxBufferCountLocked();
1129            BQ_LOGV("allocateBuffers: allocating from %d buffers up to %d buffers",
1130                    currentBufferCount, maxBufferCount);
1131            if (maxBufferCount <= currentBufferCount)
1132                return;
1133            newBufferCount =
1134                    static_cast<size_t>(maxBufferCount - currentBufferCount);
1135            if (freeSlots.size() < newBufferCount) {
1136                BQ_LOGE("allocateBuffers: ran out of free slots");
1137                return;
1138            }
1139            allocWidth = width > 0 ? width : mCore->mDefaultWidth;
1140            allocHeight = height > 0 ? height : mCore->mDefaultHeight;
1141            allocFormat = format != 0 ? format : mCore->mDefaultBufferFormat;
1142            allocUsage = usage | mCore->mConsumerUsageBits;
1143
1144            mCore->mIsAllocating = true;
1145        } // Autolock scope
1146
1147        Vector<sp<GraphicBuffer>> buffers;
1148        for (size_t i = 0; i <  newBufferCount; ++i) {
1149            status_t result = NO_ERROR;
1150            sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
1151                    allocWidth, allocHeight, allocFormat, allocUsage, &result));
1152            if (result != NO_ERROR) {
1153                BQ_LOGE("allocateBuffers: failed to allocate buffer (%u x %u, format"
1154                        " %u, usage %u)", width, height, format, usage);
1155                Mutex::Autolock lock(mCore->mMutex);
1156                mCore->mIsAllocating = false;
1157                mCore->mIsAllocatingCondition.broadcast();
1158                return;
1159            }
1160            buffers.push_back(graphicBuffer);
1161        }
1162
1163        { // Autolock scope
1164            Mutex::Autolock lock(mCore->mMutex);
1165            uint32_t checkWidth = width > 0 ? width : mCore->mDefaultWidth;
1166            uint32_t checkHeight = height > 0 ? height : mCore->mDefaultHeight;
1167            PixelFormat checkFormat = format != 0 ?
1168                    format : mCore->mDefaultBufferFormat;
1169            uint32_t checkUsage = usage | mCore->mConsumerUsageBits;
1170            if (checkWidth != allocWidth || checkHeight != allocHeight ||
1171                checkFormat != allocFormat || checkUsage != allocUsage) {
1172                // Something changed while we released the lock. Retry.
1173                BQ_LOGV("allocateBuffers: size/format/usage changed while allocating. Retrying.");
1174                mCore->mIsAllocating = false;
1175                mCore->mIsAllocatingCondition.broadcast();
1176                continue;
1177            }
1178
1179            for (size_t i = 0; i < newBufferCount; ++i) {
1180                int slot = freeSlots[i];
1181                if (!mSlots[slot].mBufferState.isFree()) {
1182                    // A consumer allocated the FREE slot with attachBuffer. Discard the buffer we
1183                    // allocated.
1184                    BQ_LOGV("allocateBuffers: slot %d was acquired while allocating. "
1185                            "Dropping allocated buffer.", slot);
1186                    continue;
1187                }
1188                mCore->freeBufferLocked(slot); // Clean up the slot first
1189                mSlots[slot].mGraphicBuffer = buffers[i];
1190                mSlots[slot].mFence = Fence::NO_FENCE;
1191
1192                // freeBufferLocked puts this slot on the free slots list. Since
1193                // we then attached a buffer, move the slot to free buffer list.
1194                mCore->mFreeSlots.erase(slot);
1195                mCore->mFreeBuffers.push_front(slot);
1196
1197                BQ_LOGV("allocateBuffers: allocated a new buffer in slot %d", slot);
1198            }
1199
1200            mCore->mIsAllocating = false;
1201            mCore->mIsAllocatingCondition.broadcast();
1202            mCore->validateConsistencyLocked();
1203        } // Autolock scope
1204    }
1205}
1206
1207status_t BufferQueueProducer::allowAllocation(bool allow) {
1208    ATRACE_CALL();
1209    BQ_LOGV("allowAllocation: %s", allow ? "true" : "false");
1210
1211    Mutex::Autolock lock(mCore->mMutex);
1212    mCore->mAllowAllocation = allow;
1213    return NO_ERROR;
1214}
1215
1216status_t BufferQueueProducer::setGenerationNumber(uint32_t generationNumber) {
1217    ATRACE_CALL();
1218    BQ_LOGV("setGenerationNumber: %u", generationNumber);
1219
1220    Mutex::Autolock lock(mCore->mMutex);
1221    mCore->mGenerationNumber = generationNumber;
1222    return NO_ERROR;
1223}
1224
1225String8 BufferQueueProducer::getConsumerName() const {
1226    ATRACE_CALL();
1227    BQ_LOGV("getConsumerName: %s", mConsumerName.string());
1228    return mConsumerName;
1229}
1230
1231uint64_t BufferQueueProducer::getNextFrameNumber() const {
1232    ATRACE_CALL();
1233
1234    Mutex::Autolock lock(mCore->mMutex);
1235    uint64_t nextFrameNumber = mCore->mFrameCounter + 1;
1236    return nextFrameNumber;
1237}
1238
1239status_t BufferQueueProducer::setSingleBufferMode(bool singleBufferMode) {
1240    ATRACE_CALL();
1241    BQ_LOGV("setSingleBufferMode: %d", singleBufferMode);
1242
1243    Mutex::Autolock lock(mCore->mMutex);
1244    if (!singleBufferMode) {
1245        mCore->mSingleBufferSlot = BufferQueueCore::INVALID_BUFFER_SLOT;
1246    }
1247    mCore->mSingleBufferMode = singleBufferMode;
1248
1249    return NO_ERROR;
1250}
1251
1252void BufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) {
1253    // If we're here, it means that a producer we were connected to died.
1254    // We're guaranteed that we are still connected to it because we remove
1255    // this callback upon disconnect. It's therefore safe to read mConnectedApi
1256    // without synchronization here.
1257    int api = mCore->mConnectedApi;
1258    disconnect(api);
1259}
1260
1261} // namespace android
1262