[go: nahoru, domu]

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 "BufferQueueConsumer"
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#include <gui/BufferItem.h>
30#include <gui/BufferQueueConsumer.h>
31#include <gui/BufferQueueCore.h>
32#include <gui/IConsumerListener.h>
33#include <gui/IProducerListener.h>
34
35#include <binder/IPCThreadState.h>
36#include <binder/PermissionCache.h>
37#include <private/android_filesystem_config.h>
38
39namespace android {
40
41BufferQueueConsumer::BufferQueueConsumer(const sp<BufferQueueCore>& core) :
42    mCore(core),
43    mSlots(core->mSlots),
44    mConsumerName() {}
45
46BufferQueueConsumer::~BufferQueueConsumer() {}
47
48status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer,
49        nsecs_t expectedPresent, uint64_t maxFrameNumber) {
50    ATRACE_CALL();
51
52    int numDroppedBuffers = 0;
53    sp<IProducerListener> listener;
54    {
55        Mutex::Autolock lock(mCore->mMutex);
56
57        // Check that the consumer doesn't currently have the maximum number of
58        // buffers acquired. We allow the max buffer count to be exceeded by one
59        // buffer so that the consumer can successfully set up the newly acquired
60        // buffer before releasing the old one.
61        int numAcquiredBuffers = 0;
62        for (int s : mCore->mActiveBuffers) {
63            if (mSlots[s].mBufferState.isAcquired()) {
64                ++numAcquiredBuffers;
65            }
66        }
67        if (numAcquiredBuffers >= mCore->mMaxAcquiredBufferCount + 1) {
68            BQ_LOGE("acquireBuffer: max acquired buffer count reached: %d (max %d)",
69                    numAcquiredBuffers, mCore->mMaxAcquiredBufferCount);
70            return INVALID_OPERATION;
71        }
72
73        bool sharedBufferAvailable = mCore->mSharedBufferMode &&
74                mCore->mAutoRefresh && mCore->mSharedBufferSlot !=
75                BufferQueueCore::INVALID_BUFFER_SLOT;
76
77        // In asynchronous mode the list is guaranteed to be one buffer deep,
78        // while in synchronous mode we use the oldest buffer.
79        if (mCore->mQueue.empty() && !sharedBufferAvailable) {
80            return NO_BUFFER_AVAILABLE;
81        }
82
83        BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin());
84
85        // If expectedPresent is specified, we may not want to return a buffer yet.
86        // If it's specified and there's more than one buffer queued, we may want
87        // to drop a buffer.
88        // Skip this if we're in shared buffer mode and the queue is empty,
89        // since in that case we'll just return the shared buffer.
90        if (expectedPresent != 0 && !mCore->mQueue.empty()) {
91            const int MAX_REASONABLE_NSEC = 1000000000ULL; // 1 second
92
93            // The 'expectedPresent' argument indicates when the buffer is expected
94            // to be presented on-screen. If the buffer's desired present time is
95            // earlier (less) than expectedPresent -- meaning it will be displayed
96            // on time or possibly late if we show it as soon as possible -- we
97            // acquire and return it. If we don't want to display it until after the
98            // expectedPresent time, we return PRESENT_LATER without acquiring it.
99            //
100            // To be safe, we don't defer acquisition if expectedPresent is more
101            // than one second in the future beyond the desired present time
102            // (i.e., we'd be holding the buffer for a long time).
103            //
104            // NOTE: Code assumes monotonic time values from the system clock
105            // are positive.
106
107            // Start by checking to see if we can drop frames. We skip this check if
108            // the timestamps are being auto-generated by Surface. If the app isn't
109            // generating timestamps explicitly, it probably doesn't want frames to
110            // be discarded based on them.
111            while (mCore->mQueue.size() > 1 && !mCore->mQueue[0].mIsAutoTimestamp) {
112                const BufferItem& bufferItem(mCore->mQueue[1]);
113
114                // If dropping entry[0] would leave us with a buffer that the
115                // consumer is not yet ready for, don't drop it.
116                if (maxFrameNumber && bufferItem.mFrameNumber > maxFrameNumber) {
117                    break;
118                }
119
120                // If entry[1] is timely, drop entry[0] (and repeat). We apply an
121                // additional criterion here: we only drop the earlier buffer if our
122                // desiredPresent falls within +/- 1 second of the expected present.
123                // Otherwise, bogus desiredPresent times (e.g., 0 or a small
124                // relative timestamp), which normally mean "ignore the timestamp
125                // and acquire immediately", would cause us to drop frames.
126                //
127                // We may want to add an additional criterion: don't drop the
128                // earlier buffer if entry[1]'s fence hasn't signaled yet.
129                nsecs_t desiredPresent = bufferItem.mTimestamp;
130                if (desiredPresent < expectedPresent - MAX_REASONABLE_NSEC ||
131                        desiredPresent > expectedPresent) {
132                    // This buffer is set to display in the near future, or
133                    // desiredPresent is garbage. Either way we don't want to drop
134                    // the previous buffer just to get this on the screen sooner.
135                    BQ_LOGV("acquireBuffer: nodrop desire=%" PRId64 " expect=%"
136                            PRId64 " (%" PRId64 ") now=%" PRId64,
137                            desiredPresent, expectedPresent,
138                            desiredPresent - expectedPresent,
139                            systemTime(CLOCK_MONOTONIC));
140                    break;
141                }
142
143                BQ_LOGV("acquireBuffer: drop desire=%" PRId64 " expect=%" PRId64
144                        " size=%zu",
145                        desiredPresent, expectedPresent, mCore->mQueue.size());
146
147                if (!front->mIsStale) {
148                    // Front buffer is still in mSlots, so mark the slot as free
149                    mSlots[front->mSlot].mBufferState.freeQueued();
150
151                    // After leaving shared buffer mode, the shared buffer will
152                    // still be around. Mark it as no longer shared if this
153                    // operation causes it to be free.
154                    if (!mCore->mSharedBufferMode &&
155                            mSlots[front->mSlot].mBufferState.isFree()) {
156                        mSlots[front->mSlot].mBufferState.mShared = false;
157                    }
158
159                    // Don't put the shared buffer on the free list
160                    if (!mSlots[front->mSlot].mBufferState.isShared()) {
161                        mCore->mActiveBuffers.erase(front->mSlot);
162                        mCore->mFreeBuffers.push_back(front->mSlot);
163                    }
164
165                    listener = mCore->mConnectedProducerListener;
166                    ++numDroppedBuffers;
167                }
168
169                mCore->mQueue.erase(front);
170                front = mCore->mQueue.begin();
171            }
172
173            // See if the front buffer is ready to be acquired
174            nsecs_t desiredPresent = front->mTimestamp;
175            bool bufferIsDue = desiredPresent <= expectedPresent ||
176                    desiredPresent > expectedPresent + MAX_REASONABLE_NSEC;
177            bool consumerIsReady = maxFrameNumber > 0 ?
178                    front->mFrameNumber <= maxFrameNumber : true;
179            if (!bufferIsDue || !consumerIsReady) {
180                BQ_LOGV("acquireBuffer: defer desire=%" PRId64 " expect=%" PRId64
181                        " (%" PRId64 ") now=%" PRId64 " frame=%" PRIu64
182                        " consumer=%" PRIu64,
183                        desiredPresent, expectedPresent,
184                        desiredPresent - expectedPresent,
185                        systemTime(CLOCK_MONOTONIC),
186                        front->mFrameNumber, maxFrameNumber);
187                return PRESENT_LATER;
188            }
189
190            BQ_LOGV("acquireBuffer: accept desire=%" PRId64 " expect=%" PRId64 " "
191                    "(%" PRId64 ") now=%" PRId64, desiredPresent, expectedPresent,
192                    desiredPresent - expectedPresent,
193                    systemTime(CLOCK_MONOTONIC));
194        }
195
196        int slot = BufferQueueCore::INVALID_BUFFER_SLOT;
197
198        if (sharedBufferAvailable && mCore->mQueue.empty()) {
199            // make sure the buffer has finished allocating before acquiring it
200            mCore->waitWhileAllocatingLocked();
201
202            slot = mCore->mSharedBufferSlot;
203
204            // Recreate the BufferItem for the shared buffer from the data that
205            // was cached when it was last queued.
206            outBuffer->mGraphicBuffer = mSlots[slot].mGraphicBuffer;
207            outBuffer->mFence = Fence::NO_FENCE;
208            outBuffer->mCrop = mCore->mSharedBufferCache.crop;
209            outBuffer->mTransform = mCore->mSharedBufferCache.transform &
210                    ~static_cast<uint32_t>(
211                    NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY);
212            outBuffer->mScalingMode = mCore->mSharedBufferCache.scalingMode;
213            outBuffer->mDataSpace = mCore->mSharedBufferCache.dataspace;
214            outBuffer->mFrameNumber = mCore->mFrameCounter;
215            outBuffer->mSlot = slot;
216            outBuffer->mAcquireCalled = mSlots[slot].mAcquireCalled;
217            outBuffer->mTransformToDisplayInverse =
218                    (mCore->mSharedBufferCache.transform &
219                    NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) != 0;
220            outBuffer->mSurfaceDamage = Region::INVALID_REGION;
221            outBuffer->mQueuedBuffer = false;
222            outBuffer->mIsStale = false;
223            outBuffer->mAutoRefresh = mCore->mSharedBufferMode &&
224                    mCore->mAutoRefresh;
225        } else {
226            slot = front->mSlot;
227            *outBuffer = *front;
228        }
229
230        ATRACE_BUFFER_INDEX(slot);
231
232        BQ_LOGV("acquireBuffer: acquiring { slot=%d/%" PRIu64 " buffer=%p }",
233                slot, outBuffer->mFrameNumber, outBuffer->mGraphicBuffer->handle);
234
235        if (!outBuffer->mIsStale) {
236            mSlots[slot].mAcquireCalled = true;
237            // Don't decrease the queue count if the BufferItem wasn't
238            // previously in the queue. This happens in shared buffer mode when
239            // the queue is empty and the BufferItem is created above.
240            if (mCore->mQueue.empty()) {
241                mSlots[slot].mBufferState.acquireNotInQueue();
242            } else {
243                mSlots[slot].mBufferState.acquire();
244            }
245            mSlots[slot].mFence = Fence::NO_FENCE;
246        }
247
248        // If the buffer has previously been acquired by the consumer, set
249        // mGraphicBuffer to NULL to avoid unnecessarily remapping this buffer
250        // on the consumer side
251        if (outBuffer->mAcquireCalled) {
252            outBuffer->mGraphicBuffer = NULL;
253        }
254
255        mCore->mQueue.erase(front);
256
257        // We might have freed a slot while dropping old buffers, or the producer
258        // may be blocked waiting for the number of buffers in the queue to
259        // decrease.
260        mCore->mDequeueCondition.broadcast();
261
262        ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size());
263
264        VALIDATE_CONSISTENCY();
265    }
266
267    if (listener != NULL) {
268        for (int i = 0; i < numDroppedBuffers; ++i) {
269            listener->onBufferReleased();
270        }
271    }
272
273    return NO_ERROR;
274}
275
276status_t BufferQueueConsumer::detachBuffer(int slot) {
277    ATRACE_CALL();
278    ATRACE_BUFFER_INDEX(slot);
279    BQ_LOGV("detachBuffer: slot %d", slot);
280    Mutex::Autolock lock(mCore->mMutex);
281
282    if (mCore->mIsAbandoned) {
283        BQ_LOGE("detachBuffer: BufferQueue has been abandoned");
284        return NO_INIT;
285    }
286
287    if (mCore->mSharedBufferMode || slot == mCore->mSharedBufferSlot) {
288        BQ_LOGE("detachBuffer: detachBuffer not allowed in shared buffer mode");
289        return BAD_VALUE;
290    }
291
292    if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
293        BQ_LOGE("detachBuffer: slot index %d out of range [0, %d)",
294                slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
295        return BAD_VALUE;
296    } else if (!mSlots[slot].mBufferState.isAcquired()) {
297        BQ_LOGE("detachBuffer: slot %d is not owned by the consumer "
298                "(state = %s)", slot, mSlots[slot].mBufferState.string());
299        return BAD_VALUE;
300    }
301
302    mSlots[slot].mBufferState.detachConsumer();
303    mCore->mActiveBuffers.erase(slot);
304    mCore->mFreeSlots.insert(slot);
305    mCore->clearBufferSlotLocked(slot);
306    mCore->mDequeueCondition.broadcast();
307    VALIDATE_CONSISTENCY();
308
309    return NO_ERROR;
310}
311
312status_t BufferQueueConsumer::attachBuffer(int* outSlot,
313        const sp<android::GraphicBuffer>& buffer) {
314    ATRACE_CALL();
315
316    if (outSlot == NULL) {
317        BQ_LOGE("attachBuffer: outSlot must not be NULL");
318        return BAD_VALUE;
319    } else if (buffer == NULL) {
320        BQ_LOGE("attachBuffer: cannot attach NULL buffer");
321        return BAD_VALUE;
322    }
323
324    Mutex::Autolock lock(mCore->mMutex);
325
326    if (mCore->mSharedBufferMode) {
327        BQ_LOGE("attachBuffer: cannot attach a buffer in shared buffer mode");
328        return BAD_VALUE;
329    }
330
331    // Make sure we don't have too many acquired buffers
332    int numAcquiredBuffers = 0;
333    for (int s : mCore->mActiveBuffers) {
334        if (mSlots[s].mBufferState.isAcquired()) {
335            ++numAcquiredBuffers;
336        }
337    }
338
339    if (numAcquiredBuffers >= mCore->mMaxAcquiredBufferCount + 1) {
340        BQ_LOGE("attachBuffer: max acquired buffer count reached: %d "
341                "(max %d)", numAcquiredBuffers,
342                mCore->mMaxAcquiredBufferCount);
343        return INVALID_OPERATION;
344    }
345
346    if (buffer->getGenerationNumber() != mCore->mGenerationNumber) {
347        BQ_LOGE("attachBuffer: generation number mismatch [buffer %u] "
348                "[queue %u]", buffer->getGenerationNumber(),
349                mCore->mGenerationNumber);
350        return BAD_VALUE;
351    }
352
353    // Find a free slot to put the buffer into
354    int found = BufferQueueCore::INVALID_BUFFER_SLOT;
355    if (!mCore->mFreeSlots.empty()) {
356        auto slot = mCore->mFreeSlots.begin();
357        found = *slot;
358        mCore->mFreeSlots.erase(slot);
359    } else if (!mCore->mFreeBuffers.empty()) {
360        found = mCore->mFreeBuffers.front();
361        mCore->mFreeBuffers.remove(found);
362    }
363    if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
364        BQ_LOGE("attachBuffer: could not find free buffer slot");
365        return NO_MEMORY;
366    }
367
368    mCore->mActiveBuffers.insert(found);
369    *outSlot = found;
370    ATRACE_BUFFER_INDEX(*outSlot);
371    BQ_LOGV("attachBuffer: returning slot %d", *outSlot);
372
373    mSlots[*outSlot].mGraphicBuffer = buffer;
374    mSlots[*outSlot].mBufferState.attachConsumer();
375    mSlots[*outSlot].mNeedsReallocation = true;
376    mSlots[*outSlot].mFence = Fence::NO_FENCE;
377    mSlots[*outSlot].mFrameNumber = 0;
378
379    // mAcquireCalled tells BufferQueue that it doesn't need to send a valid
380    // GraphicBuffer pointer on the next acquireBuffer call, which decreases
381    // Binder traffic by not un/flattening the GraphicBuffer. However, it
382    // requires that the consumer maintain a cached copy of the slot <--> buffer
383    // mappings, which is why the consumer doesn't need the valid pointer on
384    // acquire.
385    //
386    // The StreamSplitter is one of the primary users of the attach/detach
387    // logic, and while it is running, all buffers it acquires are immediately
388    // detached, and all buffers it eventually releases are ones that were
389    // attached (as opposed to having been obtained from acquireBuffer), so it
390    // doesn't make sense to maintain the slot/buffer mappings, which would
391    // become invalid for every buffer during detach/attach. By setting this to
392    // false, the valid GraphicBuffer pointer will always be sent with acquire
393    // for attached buffers.
394    mSlots[*outSlot].mAcquireCalled = false;
395
396    VALIDATE_CONSISTENCY();
397
398    return NO_ERROR;
399}
400
401status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber,
402        const sp<Fence>& releaseFence, EGLDisplay eglDisplay,
403        EGLSyncKHR eglFence) {
404    ATRACE_CALL();
405    ATRACE_BUFFER_INDEX(slot);
406
407    if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS ||
408            releaseFence == NULL) {
409        BQ_LOGE("releaseBuffer: slot %d out of range or fence %p NULL", slot,
410                releaseFence.get());
411        return BAD_VALUE;
412    }
413
414    sp<IProducerListener> listener;
415    { // Autolock scope
416        Mutex::Autolock lock(mCore->mMutex);
417
418        // If the frame number has changed because the buffer has been reallocated,
419        // we can ignore this releaseBuffer for the old buffer.
420        // Ignore this for the shared buffer where the frame number can easily
421        // get out of sync due to the buffer being queued and acquired at the
422        // same time.
423        if (frameNumber != mSlots[slot].mFrameNumber &&
424                !mSlots[slot].mBufferState.isShared()) {
425            return STALE_BUFFER_SLOT;
426        }
427
428        if (!mSlots[slot].mBufferState.isAcquired()) {
429            BQ_LOGE("releaseBuffer: attempted to release buffer slot %d "
430                    "but its state was %s", slot,
431                    mSlots[slot].mBufferState.string());
432            return BAD_VALUE;
433        }
434
435        mSlots[slot].mEglDisplay = eglDisplay;
436        mSlots[slot].mEglFence = eglFence;
437        mSlots[slot].mFence = releaseFence;
438        mSlots[slot].mBufferState.release();
439
440        // After leaving shared buffer mode, the shared buffer will
441        // still be around. Mark it as no longer shared if this
442        // operation causes it to be free.
443        if (!mCore->mSharedBufferMode && mSlots[slot].mBufferState.isFree()) {
444            mSlots[slot].mBufferState.mShared = false;
445        }
446        // Don't put the shared buffer on the free list.
447        if (!mSlots[slot].mBufferState.isShared()) {
448            mCore->mActiveBuffers.erase(slot);
449            mCore->mFreeBuffers.push_back(slot);
450        }
451
452        listener = mCore->mConnectedProducerListener;
453        BQ_LOGV("releaseBuffer: releasing slot %d", slot);
454
455        mCore->mDequeueCondition.broadcast();
456        VALIDATE_CONSISTENCY();
457    } // Autolock scope
458
459    // Call back without lock held
460    if (listener != NULL) {
461        listener->onBufferReleased();
462    }
463
464    return NO_ERROR;
465}
466
467status_t BufferQueueConsumer::connect(
468        const sp<IConsumerListener>& consumerListener, bool controlledByApp) {
469    ATRACE_CALL();
470
471    if (consumerListener == NULL) {
472        BQ_LOGE("connect: consumerListener may not be NULL");
473        return BAD_VALUE;
474    }
475
476    BQ_LOGV("connect: controlledByApp=%s",
477            controlledByApp ? "true" : "false");
478
479    Mutex::Autolock lock(mCore->mMutex);
480
481    if (mCore->mIsAbandoned) {
482        BQ_LOGE("connect: BufferQueue has been abandoned");
483        return NO_INIT;
484    }
485
486    mCore->mConsumerListener = consumerListener;
487    mCore->mConsumerControlledByApp = controlledByApp;
488
489    return NO_ERROR;
490}
491
492status_t BufferQueueConsumer::disconnect() {
493    ATRACE_CALL();
494
495    BQ_LOGV("disconnect");
496
497    Mutex::Autolock lock(mCore->mMutex);
498
499    if (mCore->mConsumerListener == NULL) {
500        BQ_LOGE("disconnect: no consumer is connected");
501        return BAD_VALUE;
502    }
503
504    mCore->mIsAbandoned = true;
505    mCore->mConsumerListener = NULL;
506    mCore->mQueue.clear();
507    mCore->freeAllBuffersLocked();
508    mCore->mSharedBufferSlot = BufferQueueCore::INVALID_BUFFER_SLOT;
509    mCore->mDequeueCondition.broadcast();
510    return NO_ERROR;
511}
512
513status_t BufferQueueConsumer::getReleasedBuffers(uint64_t *outSlotMask) {
514    ATRACE_CALL();
515
516    if (outSlotMask == NULL) {
517        BQ_LOGE("getReleasedBuffers: outSlotMask may not be NULL");
518        return BAD_VALUE;
519    }
520
521    Mutex::Autolock lock(mCore->mMutex);
522
523    if (mCore->mIsAbandoned) {
524        BQ_LOGE("getReleasedBuffers: BufferQueue has been abandoned");
525        return NO_INIT;
526    }
527
528    uint64_t mask = 0;
529    for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
530        if (!mSlots[s].mAcquireCalled) {
531            mask |= (1ULL << s);
532        }
533    }
534
535    // Remove from the mask queued buffers for which acquire has been called,
536    // since the consumer will not receive their buffer addresses and so must
537    // retain their cached information
538    BufferQueueCore::Fifo::iterator current(mCore->mQueue.begin());
539    while (current != mCore->mQueue.end()) {
540        if (current->mAcquireCalled) {
541            mask &= ~(1ULL << current->mSlot);
542        }
543        ++current;
544    }
545
546    BQ_LOGV("getReleasedBuffers: returning mask %#" PRIx64, mask);
547    *outSlotMask = mask;
548    return NO_ERROR;
549}
550
551status_t BufferQueueConsumer::setDefaultBufferSize(uint32_t width,
552        uint32_t height) {
553    ATRACE_CALL();
554
555    if (width == 0 || height == 0) {
556        BQ_LOGV("setDefaultBufferSize: dimensions cannot be 0 (width=%u "
557                "height=%u)", width, height);
558        return BAD_VALUE;
559    }
560
561    BQ_LOGV("setDefaultBufferSize: width=%u height=%u", width, height);
562
563    Mutex::Autolock lock(mCore->mMutex);
564    mCore->mDefaultWidth = width;
565    mCore->mDefaultHeight = height;
566    return NO_ERROR;
567}
568
569status_t BufferQueueConsumer::setMaxBufferCount(int bufferCount) {
570    ATRACE_CALL();
571
572    if (bufferCount < 1 || bufferCount > BufferQueueDefs::NUM_BUFFER_SLOTS) {
573        BQ_LOGE("setMaxBufferCount: invalid count %d", bufferCount);
574        return BAD_VALUE;
575    }
576
577    Mutex::Autolock lock(mCore->mMutex);
578
579    if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
580        BQ_LOGE("setMaxBufferCount: producer is already connected");
581        return INVALID_OPERATION;
582    }
583
584    if (bufferCount < mCore->mMaxAcquiredBufferCount) {
585        BQ_LOGE("setMaxBufferCount: invalid buffer count (%d) less than"
586                "mMaxAcquiredBufferCount (%d)", bufferCount,
587                mCore->mMaxAcquiredBufferCount);
588        return BAD_VALUE;
589    }
590
591    int delta = mCore->getMaxBufferCountLocked(mCore->mAsyncMode,
592            mCore->mDequeueBufferCannotBlock, bufferCount) -
593            mCore->getMaxBufferCountLocked();
594    if (!mCore->adjustAvailableSlotsLocked(delta)) {
595        BQ_LOGE("setMaxBufferCount: BufferQueue failed to adjust the number of "
596                "available slots. Delta = %d", delta);
597        return BAD_VALUE;
598    }
599
600    mCore->mMaxBufferCount = bufferCount;
601    return NO_ERROR;
602}
603
604status_t BufferQueueConsumer::setMaxAcquiredBufferCount(
605        int maxAcquiredBuffers) {
606    ATRACE_CALL();
607
608    if (maxAcquiredBuffers < 1 ||
609            maxAcquiredBuffers > BufferQueueCore::MAX_MAX_ACQUIRED_BUFFERS) {
610        BQ_LOGE("setMaxAcquiredBufferCount: invalid count %d",
611                maxAcquiredBuffers);
612        return BAD_VALUE;
613    }
614
615    sp<IConsumerListener> listener;
616    { // Autolock scope
617        Mutex::Autolock lock(mCore->mMutex);
618        mCore->waitWhileAllocatingLocked();
619
620        if (mCore->mIsAbandoned) {
621            BQ_LOGE("setMaxAcquiredBufferCount: consumer is abandoned");
622            return NO_INIT;
623        }
624
625        if (maxAcquiredBuffers == mCore->mMaxAcquiredBufferCount) {
626            return NO_ERROR;
627        }
628
629        // The new maxAcquiredBuffers count should not be violated by the number
630        // of currently acquired buffers
631        int acquiredCount = 0;
632        for (int slot : mCore->mActiveBuffers) {
633            if (mSlots[slot].mBufferState.isAcquired()) {
634                acquiredCount++;
635            }
636        }
637        if (acquiredCount > maxAcquiredBuffers) {
638            BQ_LOGE("setMaxAcquiredBufferCount: the requested maxAcquiredBuffer"
639                    "count (%d) exceeds the current acquired buffer count (%d)",
640                    maxAcquiredBuffers, acquiredCount);
641            return BAD_VALUE;
642        }
643
644        if ((maxAcquiredBuffers + mCore->mMaxDequeuedBufferCount +
645                (mCore->mAsyncMode || mCore->mDequeueBufferCannotBlock ? 1 : 0))
646                > mCore->mMaxBufferCount) {
647            BQ_LOGE("setMaxAcquiredBufferCount: %d acquired buffers would "
648                    "exceed the maxBufferCount (%d) (maxDequeued %d async %d)",
649                    maxAcquiredBuffers, mCore->mMaxBufferCount,
650                    mCore->mMaxDequeuedBufferCount, mCore->mAsyncMode ||
651                    mCore->mDequeueBufferCannotBlock);
652            return BAD_VALUE;
653        }
654
655        int delta = maxAcquiredBuffers - mCore->mMaxAcquiredBufferCount;
656        if (!mCore->adjustAvailableSlotsLocked(delta)) {
657            return BAD_VALUE;
658        }
659
660        BQ_LOGV("setMaxAcquiredBufferCount: %d", maxAcquiredBuffers);
661        mCore->mMaxAcquiredBufferCount = maxAcquiredBuffers;
662        VALIDATE_CONSISTENCY();
663        if (delta < 0) {
664            listener = mCore->mConsumerListener;
665        }
666    }
667    // Call back without lock held
668    if (listener != NULL) {
669        listener->onBuffersReleased();
670    }
671
672    return NO_ERROR;
673}
674
675void BufferQueueConsumer::setConsumerName(const String8& name) {
676    ATRACE_CALL();
677    BQ_LOGV("setConsumerName: '%s'", name.string());
678    Mutex::Autolock lock(mCore->mMutex);
679    mCore->mConsumerName = name;
680    mConsumerName = name;
681}
682
683status_t BufferQueueConsumer::setDefaultBufferFormat(PixelFormat defaultFormat) {
684    ATRACE_CALL();
685    BQ_LOGV("setDefaultBufferFormat: %u", defaultFormat);
686    Mutex::Autolock lock(mCore->mMutex);
687    mCore->mDefaultBufferFormat = defaultFormat;
688    return NO_ERROR;
689}
690
691status_t BufferQueueConsumer::setDefaultBufferDataSpace(
692        android_dataspace defaultDataSpace) {
693    ATRACE_CALL();
694    BQ_LOGV("setDefaultBufferDataSpace: %u", defaultDataSpace);
695    Mutex::Autolock lock(mCore->mMutex);
696    mCore->mDefaultBufferDataSpace = defaultDataSpace;
697    return NO_ERROR;
698}
699
700status_t BufferQueueConsumer::setConsumerUsageBits(uint32_t usage) {
701    ATRACE_CALL();
702    BQ_LOGV("setConsumerUsageBits: %#x", usage);
703    Mutex::Autolock lock(mCore->mMutex);
704    mCore->mConsumerUsageBits = usage;
705    return NO_ERROR;
706}
707
708status_t BufferQueueConsumer::setTransformHint(uint32_t hint) {
709    ATRACE_CALL();
710    BQ_LOGV("setTransformHint: %#x", hint);
711    Mutex::Autolock lock(mCore->mMutex);
712    mCore->mTransformHint = hint;
713    return NO_ERROR;
714}
715
716sp<NativeHandle> BufferQueueConsumer::getSidebandStream() const {
717    return mCore->mSidebandStream;
718}
719
720void BufferQueueConsumer::dump(String8& result, const char* prefix) const {
721    const IPCThreadState* ipc = IPCThreadState::self();
722    const pid_t pid = ipc->getCallingPid();
723    const uid_t uid = ipc->getCallingUid();
724    if ((uid != AID_SHELL)
725            && !PermissionCache::checkPermission(String16(
726            "android.permission.DUMP"), pid, uid)) {
727        result.appendFormat("Permission Denial: can't dump BufferQueueConsumer "
728                "from pid=%d, uid=%d\n", pid, uid);
729        android_errorWriteWithInfoLog(0x534e4554, "27046057", uid, NULL, 0);
730    } else {
731        mCore->dump(result, prefix);
732    }
733}
734
735} // namespace android
736