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