BufferQueueProducer.cpp revision ae3c3682333f25e860fe54e2bae3599bb466cdb6
1/*
2 * Copyright 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "BufferQueueProducer"
18#define ATRACE_TAG ATRACE_TAG_GRAPHICS
19//#define LOG_NDEBUG 0
20
21#define EGL_EGLEXT_PROTOTYPES
22
23#include <gui/BufferItem.h>
24#include <gui/BufferQueueCore.h>
25#include <gui/BufferQueueProducer.h>
26#include <gui/IConsumerListener.h>
27#include <gui/IGraphicBufferAlloc.h>
28#include <gui/IProducerListener.h>
29
30#include <utils/Log.h>
31#include <utils/Trace.h>
32
33namespace android {
34
35BufferQueueProducer::BufferQueueProducer(const sp<BufferQueueCore>& core) :
36    mCore(core),
37    mSlots(core->mSlots),
38    mConsumerName() {}
39
40BufferQueueProducer::~BufferQueueProducer() {}
41
42status_t BufferQueueProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
43    ATRACE_CALL();
44    BQ_LOGV("requestBuffer: slot %d", slot);
45    Mutex::Autolock lock(mCore->mMutex);
46
47    if (mCore->mIsAbandoned) {
48        BQ_LOGE("requestBuffer: BufferQueue has been abandoned");
49        return NO_INIT;
50    }
51
52    if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
53        BQ_LOGE("requestBuffer: slot index %d out of range [0, %d)",
54                slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
55        return BAD_VALUE;
56    } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
57        BQ_LOGE("requestBuffer: slot %d is not owned by the producer "
58                "(state = %d)", slot, mSlots[slot].mBufferState);
59        return BAD_VALUE;
60    }
61
62    mSlots[slot].mRequestBufferCalled = true;
63    *buf = mSlots[slot].mGraphicBuffer;
64    return NO_ERROR;
65}
66
67status_t BufferQueueProducer::setBufferCount(int bufferCount) {
68    ATRACE_CALL();
69    BQ_LOGV("setBufferCount: count = %d", bufferCount);
70
71    sp<IConsumerListener> listener;
72    { // Autolock scope
73        Mutex::Autolock lock(mCore->mMutex);
74
75        if (mCore->mIsAbandoned) {
76            BQ_LOGE("setBufferCount: BufferQueue has been abandoned");
77            return NO_INIT;
78        }
79
80        if (bufferCount > BufferQueueDefs::NUM_BUFFER_SLOTS) {
81            BQ_LOGE("setBufferCount: bufferCount %d too large (max %d)",
82                    bufferCount, BufferQueueDefs::NUM_BUFFER_SLOTS);
83            return BAD_VALUE;
84        }
85
86        // There must be no dequeued buffers when changing the buffer count.
87        for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
88            if (mSlots[s].mBufferState == BufferSlot::DEQUEUED) {
89                BQ_LOGE("setBufferCount: buffer owned by producer");
90                return BAD_VALUE;
91            }
92        }
93
94        if (bufferCount == 0) {
95            mCore->mOverrideMaxBufferCount = 0;
96            mCore->mDequeueCondition.broadcast();
97            return NO_ERROR;
98        }
99
100        const int minBufferSlots = mCore->getMinMaxBufferCountLocked(false);
101        if (bufferCount < minBufferSlots) {
102            BQ_LOGE("setBufferCount: requested buffer count %d is less than "
103                    "minimum %d", bufferCount, minBufferSlots);
104            return BAD_VALUE;
105        }
106
107        // Here we are guaranteed that the producer doesn't have any dequeued
108        // buffers and will release all of its buffer references. We don't
109        // clear the queue, however, so that currently queued buffers still
110        // get displayed.
111        mCore->freeAllBuffersLocked();
112        mCore->mOverrideMaxBufferCount = bufferCount;
113        mCore->mDequeueCondition.broadcast();
114        listener = mCore->mConsumerListener;
115    } // Autolock scope
116
117    // Call back without lock held
118    if (listener != NULL) {
119        listener->onBuffersReleased();
120    }
121
122    return NO_ERROR;
123}
124
125status_t BufferQueueProducer::waitForFreeSlotThenRelock(const char* caller,
126        bool async, int* found, status_t* returnFlags) const {
127    bool tryAgain = true;
128    while (tryAgain) {
129        if (mCore->mIsAbandoned) {
130            BQ_LOGE("%s: BufferQueue has been abandoned", caller);
131            return NO_INIT;
132        }
133
134        const int maxBufferCount = mCore->getMaxBufferCountLocked(async);
135        if (async && mCore->mOverrideMaxBufferCount) {
136            // FIXME: Some drivers are manually setting the buffer count
137            // (which they shouldn't), so we do this extra test here to
138            // handle that case. This is TEMPORARY until we get this fixed.
139            if (mCore->mOverrideMaxBufferCount < maxBufferCount) {
140                BQ_LOGE("%s: async mode is invalid with buffer count override",
141                        caller);
142                return BAD_VALUE;
143            }
144        }
145
146        // Free up any buffers that are in slots beyond the max buffer count
147        for (int s = maxBufferCount; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
148            assert(mSlots[s].mBufferState == BufferSlot::FREE);
149            if (mSlots[s].mGraphicBuffer != NULL) {
150                mCore->freeBufferLocked(s);
151                *returnFlags |= RELEASE_ALL_BUFFERS;
152            }
153        }
154
155        // Look for a free buffer to give to the client
156        *found = BufferQueueCore::INVALID_BUFFER_SLOT;
157        int dequeuedCount = 0;
158        int acquiredCount = 0;
159        for (int s = 0; s < maxBufferCount; ++s) {
160            switch (mSlots[s].mBufferState) {
161                case BufferSlot::DEQUEUED:
162                    ++dequeuedCount;
163                    break;
164                case BufferSlot::ACQUIRED:
165                    ++acquiredCount;
166                    break;
167                case BufferSlot::FREE:
168                    // We return the oldest of the free buffers to avoid
169                    // stalling the producer if possible, since the consumer
170                    // may still have pending reads of in-flight buffers
171                    if (*found == BufferQueueCore::INVALID_BUFFER_SLOT ||
172                            mSlots[s].mFrameNumber < mSlots[*found].mFrameNumber) {
173                        *found = s;
174                    }
175                    break;
176                default:
177                    break;
178            }
179        }
180
181        // Producers are not allowed to dequeue more than one buffer if they
182        // did not set a buffer count
183        if (!mCore->mOverrideMaxBufferCount && dequeuedCount) {
184            BQ_LOGE("%s: can't dequeue multiple buffers without setting the "
185                    "buffer count", caller);
186            return INVALID_OPERATION;
187        }
188
189        // See whether a buffer has been queued since the last
190        // setBufferCount so we know whether to perform the min undequeued
191        // buffers check below
192        if (mCore->mBufferHasBeenQueued) {
193            // Make sure the producer is not trying to dequeue more buffers
194            // than allowed
195            const int newUndequeuedCount =
196                maxBufferCount - (dequeuedCount + 1);
197            const int minUndequeuedCount =
198                mCore->getMinUndequeuedBufferCountLocked(async);
199            if (newUndequeuedCount < minUndequeuedCount) {
200                BQ_LOGE("%s: min undequeued buffer count (%d) exceeded "
201                        "(dequeued=%d undequeued=%d)",
202                        caller, minUndequeuedCount,
203                        dequeuedCount, newUndequeuedCount);
204                return INVALID_OPERATION;
205            }
206        }
207
208        // If we disconnect and reconnect quickly, we can be in a state where
209        // our slots are empty but we have many buffers in the queue. This can
210        // cause us to run out of memory if we outrun the consumer. Wait here if
211        // it looks like we have too many buffers queued up.
212        bool tooManyBuffers = mCore->mQueue.size() > maxBufferCount;
213        if (tooManyBuffers) {
214            BQ_LOGV("%s: queue size is %d, waiting", caller,
215                    mCore->mQueue.size());
216        }
217
218        // If no buffer is found, or if the queue has too many buffers
219        // outstanding, wait for a buffer to be acquired or released, or for the
220        // max buffer count to change.
221        tryAgain = (*found == BufferQueueCore::INVALID_BUFFER_SLOT) ||
222                   tooManyBuffers;
223        if (tryAgain) {
224            // Return an error if we're in non-blocking mode (producer and
225            // consumer are controlled by the application).
226            // However, the consumer is allowed to briefly acquire an extra
227            // buffer (which could cause us to have to wait here), which is
228            // okay, since it is only used to implement an atomic acquire +
229            // release (e.g., in GLConsumer::updateTexImage())
230            if (mCore->mDequeueBufferCannotBlock &&
231                    (acquiredCount <= mCore->mMaxAcquiredBufferCount)) {
232                return WOULD_BLOCK;
233            }
234            mCore->mDequeueCondition.wait(mCore->mMutex);
235        }
236    } // while (tryAgain)
237
238    return NO_ERROR;
239}
240
241status_t BufferQueueProducer::dequeueBuffer(int *outSlot,
242        sp<android::Fence> *outFence, bool async,
243        uint32_t width, uint32_t height, uint32_t format, uint32_t usage) {
244    ATRACE_CALL();
245    { // Autolock scope
246        Mutex::Autolock lock(mCore->mMutex);
247        mConsumerName = mCore->mConsumerName;
248    } // Autolock scope
249
250    BQ_LOGV("dequeueBuffer: async=%s w=%u h=%u format=%#x, usage=%#x",
251            async ? "true" : "false", width, height, format, usage);
252
253    if ((width && !height) || (!width && height)) {
254        BQ_LOGE("dequeueBuffer: invalid size: w=%u h=%u", width, height);
255        return BAD_VALUE;
256    }
257
258    status_t returnFlags = NO_ERROR;
259    EGLDisplay eglDisplay = EGL_NO_DISPLAY;
260    EGLSyncKHR eglFence = EGL_NO_SYNC_KHR;
261    bool attachedByConsumer = false;
262
263    { // Autolock scope
264        Mutex::Autolock lock(mCore->mMutex);
265
266        if (format == 0) {
267            format = mCore->mDefaultBufferFormat;
268        }
269
270        // Enable the usage bits the consumer requested
271        usage |= mCore->mConsumerUsageBits;
272
273        int found;
274        status_t status = waitForFreeSlotThenRelock("dequeueBuffer", async,
275                &found, &returnFlags);
276        if (status != NO_ERROR) {
277            return status;
278        }
279
280        // This should not happen
281        if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
282            BQ_LOGE("dequeueBuffer: no available buffer slots");
283            return -EBUSY;
284        }
285
286        *outSlot = found;
287        ATRACE_BUFFER_INDEX(found);
288
289        attachedByConsumer = mSlots[found].mAttachedByConsumer;
290
291        const bool useDefaultSize = !width && !height;
292        if (useDefaultSize) {
293            width = mCore->mDefaultWidth;
294            height = mCore->mDefaultHeight;
295        }
296
297        mSlots[found].mBufferState = BufferSlot::DEQUEUED;
298
299        const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
300        if ((buffer == NULL) ||
301                (static_cast<uint32_t>(buffer->width) != width) ||
302                (static_cast<uint32_t>(buffer->height) != height) ||
303                (static_cast<uint32_t>(buffer->format) != format) ||
304                ((static_cast<uint32_t>(buffer->usage) & usage) != usage))
305        {
306            mSlots[found].mAcquireCalled = false;
307            mSlots[found].mGraphicBuffer = NULL;
308            mSlots[found].mRequestBufferCalled = false;
309            mSlots[found].mEglDisplay = EGL_NO_DISPLAY;
310            mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
311            mSlots[found].mFence = Fence::NO_FENCE;
312
313            returnFlags |= BUFFER_NEEDS_REALLOCATION;
314        }
315
316        if (CC_UNLIKELY(mSlots[found].mFence == NULL)) {
317            BQ_LOGE("dequeueBuffer: about to return a NULL fence - "
318                    "slot=%d w=%d h=%d format=%u",
319                    found, buffer->width, buffer->height, buffer->format);
320        }
321
322        eglDisplay = mSlots[found].mEglDisplay;
323        eglFence = mSlots[found].mEglFence;
324        *outFence = mSlots[found].mFence;
325        mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
326        mSlots[found].mFence = Fence::NO_FENCE;
327    } // Autolock scope
328
329    if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
330        status_t error;
331        sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
332                    width, height, format, usage, &error));
333        if (graphicBuffer == NULL) {
334            BQ_LOGE("dequeueBuffer: createGraphicBuffer failed");
335            return error;
336        }
337
338        { // Autolock scope
339            Mutex::Autolock lock(mCore->mMutex);
340
341            if (mCore->mIsAbandoned) {
342                BQ_LOGE("dequeueBuffer: BufferQueue has been abandoned");
343                return NO_INIT;
344            }
345
346            mSlots[*outSlot].mFrameNumber = UINT32_MAX;
347            mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
348        } // Autolock scope
349    }
350
351    if (attachedByConsumer) {
352        returnFlags |= BUFFER_NEEDS_REALLOCATION;
353    }
354
355    if (eglFence != EGL_NO_SYNC_KHR) {
356        EGLint result = eglClientWaitSyncKHR(eglDisplay, eglFence, 0,
357                1000000000);
358        // If something goes wrong, log the error, but return the buffer without
359        // synchronizing access to it. It's too late at this point to abort the
360        // dequeue operation.
361        if (result == EGL_FALSE) {
362            BQ_LOGE("dequeueBuffer: error %#x waiting for fence",
363                    eglGetError());
364        } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
365            BQ_LOGE("dequeueBuffer: timeout waiting for fence");
366        }
367        eglDestroySyncKHR(eglDisplay, eglFence);
368    }
369
370    BQ_LOGV("dequeueBuffer: returning slot=%d/%llu buf=%p flags=%#x", *outSlot,
371            mSlots[*outSlot].mFrameNumber,
372            mSlots[*outSlot].mGraphicBuffer->handle, returnFlags);
373
374    return returnFlags;
375}
376
377status_t BufferQueueProducer::detachBuffer(int slot) {
378    ATRACE_CALL();
379    ATRACE_BUFFER_INDEX(slot);
380    BQ_LOGV("detachBuffer(P): slot %d", slot);
381    Mutex::Autolock lock(mCore->mMutex);
382
383    if (mCore->mIsAbandoned) {
384        BQ_LOGE("detachBuffer(P): BufferQueue has been abandoned");
385        return NO_INIT;
386    }
387
388    if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
389        BQ_LOGE("detachBuffer(P): slot index %d out of range [0, %d)",
390                slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
391        return BAD_VALUE;
392    } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
393        BQ_LOGE("detachBuffer(P): slot %d is not owned by the producer "
394                "(state = %d)", slot, mSlots[slot].mBufferState);
395        return BAD_VALUE;
396    } else if (!mSlots[slot].mRequestBufferCalled) {
397        BQ_LOGE("detachBuffer(P): buffer in slot %d has not been requested",
398                slot);
399        return BAD_VALUE;
400    }
401
402    mCore->freeBufferLocked(slot);
403    mCore->mDequeueCondition.broadcast();
404
405    return NO_ERROR;
406}
407
408status_t BufferQueueProducer::attachBuffer(int* outSlot,
409        const sp<android::GraphicBuffer>& buffer) {
410    ATRACE_CALL();
411
412    if (outSlot == NULL) {
413        BQ_LOGE("attachBuffer(P): outSlot must not be NULL");
414        return BAD_VALUE;
415    } else if (buffer == NULL) {
416        BQ_LOGE("attachBuffer(P): cannot attach NULL buffer");
417        return BAD_VALUE;
418    }
419
420    Mutex::Autolock lock(mCore->mMutex);
421
422    status_t returnFlags = NO_ERROR;
423    int found;
424    // TODO: Should we provide an async flag to attachBuffer? It seems
425    // unlikely that buffers which we are attaching to a BufferQueue will
426    // be asynchronous (droppable), but it may not be impossible.
427    status_t status = waitForFreeSlotThenRelock("attachBuffer(P)", false,
428            &found, &returnFlags);
429    if (status != NO_ERROR) {
430        return status;
431    }
432
433    // This should not happen
434    if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
435        BQ_LOGE("attachBuffer(P): no available buffer slots");
436        return -EBUSY;
437    }
438
439    *outSlot = found;
440    ATRACE_BUFFER_INDEX(*outSlot);
441    BQ_LOGV("attachBuffer(P): returning slot %d flags=%#x",
442            *outSlot, returnFlags);
443
444    mSlots[*outSlot].mGraphicBuffer = buffer;
445    mSlots[*outSlot].mBufferState = BufferSlot::DEQUEUED;
446    mSlots[*outSlot].mEglFence = EGL_NO_SYNC_KHR;
447    mSlots[*outSlot].mFence = Fence::NO_FENCE;
448    mSlots[*outSlot].mRequestBufferCalled = true;
449
450    return returnFlags;
451}
452
453status_t BufferQueueProducer::queueBuffer(int slot,
454        const QueueBufferInput &input, QueueBufferOutput *output) {
455    ATRACE_CALL();
456    ATRACE_BUFFER_INDEX(slot);
457
458    int64_t timestamp;
459    bool isAutoTimestamp;
460    Rect crop;
461    int scalingMode;
462    uint32_t transform;
463    bool async;
464    sp<Fence> fence;
465    input.deflate(&timestamp, &isAutoTimestamp, &crop, &scalingMode, &transform,
466            &async, &fence);
467
468    if (fence == NULL) {
469        BQ_LOGE("queueBuffer: fence is NULL");
470        return BAD_VALUE;
471    }
472
473    switch (scalingMode) {
474        case NATIVE_WINDOW_SCALING_MODE_FREEZE:
475        case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
476        case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
477        case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP:
478            break;
479        default:
480            BQ_LOGE("queueBuffer: unknown scaling mode %d", scalingMode);
481            return BAD_VALUE;
482    }
483
484    sp<IConsumerListener> listener;
485    { // Autolock scope
486        Mutex::Autolock lock(mCore->mMutex);
487
488        if (mCore->mIsAbandoned) {
489            BQ_LOGE("queueBuffer: BufferQueue has been abandoned");
490            return NO_INIT;
491        }
492
493        const int maxBufferCount = mCore->getMaxBufferCountLocked(async);
494        if (async && mCore->mOverrideMaxBufferCount) {
495            // FIXME: Some drivers are manually setting the buffer count
496            // (which they shouldn't), so we do this extra test here to
497            // handle that case. This is TEMPORARY until we get this fixed.
498            if (mCore->mOverrideMaxBufferCount < maxBufferCount) {
499                BQ_LOGE("queueBuffer: async mode is invalid with "
500                        "buffer count override");
501                return BAD_VALUE;
502            }
503        }
504
505        if (slot < 0 || slot >= maxBufferCount) {
506            BQ_LOGE("queueBuffer: slot index %d out of range [0, %d)",
507                    slot, maxBufferCount);
508            return BAD_VALUE;
509        } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
510            BQ_LOGE("queueBuffer: slot %d is not owned by the producer "
511                    "(state = %d)", slot, mSlots[slot].mBufferState);
512            return BAD_VALUE;
513        } else if (!mSlots[slot].mRequestBufferCalled) {
514            BQ_LOGE("queueBuffer: slot %d was queued without requesting "
515                    "a buffer", slot);
516            return BAD_VALUE;
517        }
518
519        BQ_LOGV("queueBuffer: slot=%d/%llu time=%llu crop=[%d,%d,%d,%d] "
520                "transform=%#x scale=%s",
521                slot, mCore->mFrameCounter + 1, timestamp,
522                crop.left, crop.top, crop.right, crop.bottom,
523                transform, BufferItem::scalingModeName(scalingMode));
524
525        const sp<GraphicBuffer>& graphicBuffer(mSlots[slot].mGraphicBuffer);
526        Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight());
527        Rect croppedRect;
528        crop.intersect(bufferRect, &croppedRect);
529        if (croppedRect != crop) {
530            BQ_LOGE("queueBuffer: crop rect is not contained within the "
531                    "buffer in slot %d", slot);
532            return BAD_VALUE;
533        }
534
535        mSlots[slot].mFence = fence;
536        mSlots[slot].mBufferState = BufferSlot::QUEUED;
537        ++mCore->mFrameCounter;
538        mSlots[slot].mFrameNumber = mCore->mFrameCounter;
539
540        BufferItem item;
541        item.mAcquireCalled = mSlots[slot].mAcquireCalled;
542        item.mGraphicBuffer = mSlots[slot].mGraphicBuffer;
543        item.mCrop = crop;
544        item.mTransform = transform & ~NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
545        item.mTransformToDisplayInverse =
546                bool(transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY);
547        item.mScalingMode = scalingMode;
548        item.mTimestamp = timestamp;
549        item.mIsAutoTimestamp = isAutoTimestamp;
550        item.mFrameNumber = mCore->mFrameCounter;
551        item.mSlot = slot;
552        item.mFence = fence;
553        item.mIsDroppable = mCore->mDequeueBufferCannotBlock || async;
554
555        if (mCore->mQueue.empty()) {
556            // When the queue is empty, we can ignore mDequeueBufferCannotBlock
557            // and simply queue this buffer
558            mCore->mQueue.push_back(item);
559            listener = mCore->mConsumerListener;
560        } else {
561            // When the queue is not empty, we need to look at the front buffer
562            // state to see if we need to replace it
563            BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin());
564            if (front->mIsDroppable) {
565                // If the front queued buffer is still being tracked, we first
566                // mark it as freed
567                if (mCore->stillTracking(front)) {
568                    mSlots[front->mSlot].mBufferState = BufferSlot::FREE;
569                    // Reset the frame number of the freed buffer so that it is
570                    // the first in line to be dequeued again
571                    mSlots[front->mSlot].mFrameNumber = 0;
572                }
573                // Overwrite the droppable buffer with the incoming one
574                *front = item;
575            } else {
576                mCore->mQueue.push_back(item);
577                listener = mCore->mConsumerListener;
578            }
579        }
580
581        mCore->mBufferHasBeenQueued = true;
582        mCore->mDequeueCondition.broadcast();
583
584        output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
585                mCore->mTransformHint, mCore->mQueue.size());
586
587        ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size());
588    } // Autolock scope
589
590    // Call back without lock held
591    if (listener != NULL) {
592        listener->onFrameAvailable();
593    }
594
595    return NO_ERROR;
596}
597
598void BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
599    ATRACE_CALL();
600    BQ_LOGV("cancelBuffer: slot %d", slot);
601    Mutex::Autolock lock(mCore->mMutex);
602
603    if (mCore->mIsAbandoned) {
604        BQ_LOGE("cancelBuffer: BufferQueue has been abandoned");
605        return;
606    }
607
608    if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
609        BQ_LOGE("cancelBuffer: slot index %d out of range [0, %d)",
610                slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
611        return;
612    } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
613        BQ_LOGE("cancelBuffer: slot %d is not owned by the producer "
614                "(state = %d)", slot, mSlots[slot].mBufferState);
615        return;
616    } else if (fence == NULL) {
617        BQ_LOGE("cancelBuffer: fence is NULL");
618        return;
619    }
620
621    mSlots[slot].mBufferState = BufferSlot::FREE;
622    mSlots[slot].mFrameNumber = 0;
623    mSlots[slot].mFence = fence;
624    mCore->mDequeueCondition.broadcast();
625}
626
627int BufferQueueProducer::query(int what, int *outValue) {
628    ATRACE_CALL();
629    Mutex::Autolock lock(mCore->mMutex);
630
631    if (outValue == NULL) {
632        BQ_LOGE("query: outValue was NULL");
633        return BAD_VALUE;
634    }
635
636    if (mCore->mIsAbandoned) {
637        BQ_LOGE("query: BufferQueue has been abandoned");
638        return NO_INIT;
639    }
640
641    int value;
642    switch (what) {
643        case NATIVE_WINDOW_WIDTH:
644            value = mCore->mDefaultWidth;
645            break;
646        case NATIVE_WINDOW_HEIGHT:
647            value = mCore->mDefaultHeight;
648            break;
649        case NATIVE_WINDOW_FORMAT:
650            value = mCore->mDefaultBufferFormat;
651            break;
652        case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
653            value = mCore->getMinUndequeuedBufferCountLocked(false);
654            break;
655        case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
656            value = (mCore->mQueue.size() > 1);
657            break;
658        case NATIVE_WINDOW_CONSUMER_USAGE_BITS:
659            value = mCore->mConsumerUsageBits;
660            break;
661        default:
662            return BAD_VALUE;
663    }
664
665    BQ_LOGV("query: %d? %d", what, value);
666    *outValue = value;
667    return NO_ERROR;
668}
669
670status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener,
671        int api, bool producerControlledByApp, QueueBufferOutput *output) {
672    ATRACE_CALL();
673    Mutex::Autolock lock(mCore->mMutex);
674    mConsumerName = mCore->mConsumerName;
675    BQ_LOGV("connect(P): api=%d producerControlledByApp=%s", api,
676            producerControlledByApp ? "true" : "false");
677
678    if (mCore->mIsAbandoned) {
679        BQ_LOGE("connect(P): BufferQueue has been abandoned");
680        return NO_INIT;
681    }
682
683    if (mCore->mConsumerListener == NULL) {
684        BQ_LOGE("connect(P): BufferQueue has no consumer");
685        return NO_INIT;
686    }
687
688    if (output == NULL) {
689        BQ_LOGE("connect(P): output was NULL");
690        return BAD_VALUE;
691    }
692
693    if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
694        BQ_LOGE("connect(P): already connected (cur=%d req=%d)",
695                mCore->mConnectedApi, api);
696        return BAD_VALUE;
697    }
698
699    int status = NO_ERROR;
700    switch (api) {
701        case NATIVE_WINDOW_API_EGL:
702        case NATIVE_WINDOW_API_CPU:
703        case NATIVE_WINDOW_API_MEDIA:
704        case NATIVE_WINDOW_API_CAMERA:
705            mCore->mConnectedApi = api;
706            output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
707                    mCore->mTransformHint, mCore->mQueue.size());
708
709            // Set up a death notification so that we can disconnect
710            // automatically if the remote producer dies
711            if (listener != NULL &&
712                    listener->asBinder()->remoteBinder() != NULL) {
713                status = listener->asBinder()->linkToDeath(
714                        static_cast<IBinder::DeathRecipient*>(this));
715                if (status != NO_ERROR) {
716                    BQ_LOGE("connect(P): linkToDeath failed: %s (%d)",
717                            strerror(-status), status);
718                }
719            }
720            mCore->mConnectedProducerListener = listener;
721            break;
722        default:
723            BQ_LOGE("connect(P): unknown API %d", api);
724            status = BAD_VALUE;
725            break;
726    }
727
728    mCore->mBufferHasBeenQueued = false;
729    mCore->mDequeueBufferCannotBlock =
730            mCore->mConsumerControlledByApp && producerControlledByApp;
731
732    return status;
733}
734
735status_t BufferQueueProducer::disconnect(int api) {
736    ATRACE_CALL();
737    BQ_LOGV("disconnect(P): api %d", api);
738
739    int status = NO_ERROR;
740    sp<IConsumerListener> listener;
741    { // Autolock scope
742        Mutex::Autolock lock(mCore->mMutex);
743
744        if (mCore->mIsAbandoned) {
745            // It's not really an error to disconnect after the surface has
746            // been abandoned; it should just be a no-op.
747            return NO_ERROR;
748        }
749
750        switch (api) {
751            case NATIVE_WINDOW_API_EGL:
752            case NATIVE_WINDOW_API_CPU:
753            case NATIVE_WINDOW_API_MEDIA:
754            case NATIVE_WINDOW_API_CAMERA:
755                if (mCore->mConnectedApi == api) {
756                    mCore->freeAllBuffersLocked();
757
758                    // Remove our death notification callback if we have one
759                    if (mCore->mConnectedProducerListener != NULL) {
760                        sp<IBinder> token =
761                                mCore->mConnectedProducerListener->asBinder();
762                        // This can fail if we're here because of the death
763                        // notification, but we just ignore it
764                        token->unlinkToDeath(
765                                static_cast<IBinder::DeathRecipient*>(this));
766                    }
767                    mCore->mConnectedProducerListener = NULL;
768                    mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API;
769                    mCore->mSidebandStream.clear();
770                    mCore->mDequeueCondition.broadcast();
771                    listener = mCore->mConsumerListener;
772                } else {
773                    BQ_LOGE("disconnect(P): connected to another API "
774                            "(cur=%d req=%d)", mCore->mConnectedApi, api);
775                    status = BAD_VALUE;
776                }
777                break;
778            default:
779                BQ_LOGE("disconnect(P): unknown API %d", api);
780                status = BAD_VALUE;
781                break;
782        }
783    } // Autolock scope
784
785    // Call back without lock held
786    if (listener != NULL) {
787        listener->onBuffersReleased();
788    }
789
790    return status;
791}
792
793status_t BufferQueueProducer::setSidebandStream(const sp<NativeHandle>& stream) {
794    sp<IConsumerListener> listener;
795    { // Autolock scope
796        Mutex::Autolock _l(mCore->mMutex);
797        mCore->mSidebandStream = stream;
798        listener = mCore->mConsumerListener;
799    } // Autolock scope
800
801    if (listener != NULL) {
802        listener->onSidebandStreamChanged();
803    }
804    return NO_ERROR;
805}
806
807void BufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) {
808    // If we're here, it means that a producer we were connected to died.
809    // We're guaranteed that we are still connected to it because we remove
810    // this callback upon disconnect. It's therefore safe to read mConnectedApi
811    // without synchronization here.
812    int api = mCore->mConnectedApi;
813    disconnect(api);
814}
815
816} // namespace android
817