Home | History | Annotate | Download | only in gui
      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 #include <gui/BufferItem.h>
     24 #include <gui/BufferQueueConsumer.h>
     25 #include <gui/BufferQueueCore.h>
     26 #include <gui/IConsumerListener.h>
     27 #include <gui/IProducerListener.h>
     28 
     29 namespace android {
     30 
     31 BufferQueueConsumer::BufferQueueConsumer(const sp<BufferQueueCore>& core) :
     32     mCore(core),
     33     mSlots(core->mSlots),
     34     mConsumerName() {}
     35 
     36 BufferQueueConsumer::~BufferQueueConsumer() {}
     37 
     38 status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer,
     39         nsecs_t expectedPresent) {
     40     ATRACE_CALL();
     41     Mutex::Autolock lock(mCore->mMutex);
     42 
     43     // Check that the consumer doesn't currently have the maximum number of
     44     // buffers acquired. We allow the max buffer count to be exceeded by one
     45     // buffer so that the consumer can successfully set up the newly acquired
     46     // buffer before releasing the old one.
     47     int numAcquiredBuffers = 0;
     48     for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
     49         if (mSlots[s].mBufferState == BufferSlot::ACQUIRED) {
     50             ++numAcquiredBuffers;
     51         }
     52     }
     53     if (numAcquiredBuffers >= mCore->mMaxAcquiredBufferCount + 1) {
     54         BQ_LOGE("acquireBuffer: max acquired buffer count reached: %d (max %d)",
     55                 numAcquiredBuffers, mCore->mMaxAcquiredBufferCount);
     56         return INVALID_OPERATION;
     57     }
     58 
     59     // Check if the queue is empty.
     60     // In asynchronous mode the list is guaranteed to be one buffer deep,
     61     // while in synchronous mode we use the oldest buffer.
     62     if (mCore->mQueue.empty()) {
     63         return NO_BUFFER_AVAILABLE;
     64     }
     65 
     66     BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin());
     67 
     68     // If expectedPresent is specified, we may not want to return a buffer yet.
     69     // If it's specified and there's more than one buffer queued, we may want
     70     // to drop a buffer.
     71     if (expectedPresent != 0) {
     72         const int MAX_REASONABLE_NSEC = 1000000000ULL; // 1 second
     73 
     74         // The 'expectedPresent' argument indicates when the buffer is expected
     75         // to be presented on-screen. If the buffer's desired present time is
     76         // earlier (less) than expectedPresent -- meaning it will be displayed
     77         // on time or possibly late if we show it as soon as possible -- we
     78         // acquire and return it. If we don't want to display it until after the
     79         // expectedPresent time, we return PRESENT_LATER without acquiring it.
     80         //
     81         // To be safe, we don't defer acquisition if expectedPresent is more
     82         // than one second in the future beyond the desired present time
     83         // (i.e., we'd be holding the buffer for a long time).
     84         //
     85         // NOTE: Code assumes monotonic time values from the system clock
     86         // are positive.
     87 
     88         // Start by checking to see if we can drop frames. We skip this check if
     89         // the timestamps are being auto-generated by Surface. If the app isn't
     90         // generating timestamps explicitly, it probably doesn't want frames to
     91         // be discarded based on them.
     92         while (mCore->mQueue.size() > 1 && !mCore->mQueue[0].mIsAutoTimestamp) {
     93             // If entry[1] is timely, drop entry[0] (and repeat). We apply an
     94             // additional criterion here: we only drop the earlier buffer if our
     95             // desiredPresent falls within +/- 1 second of the expected present.
     96             // Otherwise, bogus desiredPresent times (e.g., 0 or a small
     97             // relative timestamp), which normally mean "ignore the timestamp
     98             // and acquire immediately", would cause us to drop frames.
     99             //
    100             // We may want to add an additional criterion: don't drop the
    101             // earlier buffer if entry[1]'s fence hasn't signaled yet.
    102             const BufferItem& bufferItem(mCore->mQueue[1]);
    103             nsecs_t desiredPresent = bufferItem.mTimestamp;
    104             if (desiredPresent < expectedPresent - MAX_REASONABLE_NSEC ||
    105                     desiredPresent > expectedPresent) {
    106                 // This buffer is set to display in the near future, or
    107                 // desiredPresent is garbage. Either way we don't want to drop
    108                 // the previous buffer just to get this on the screen sooner.
    109                 BQ_LOGV("acquireBuffer: nodrop desire=%" PRId64 " expect=%"
    110                         PRId64 " (%" PRId64 ") now=%" PRId64,
    111                         desiredPresent, expectedPresent,
    112                         desiredPresent - expectedPresent,
    113                         systemTime(CLOCK_MONOTONIC));
    114                 break;
    115             }
    116 
    117             BQ_LOGV("acquireBuffer: drop desire=%" PRId64 " expect=%" PRId64
    118                     " size=%zu",
    119                     desiredPresent, expectedPresent, mCore->mQueue.size());
    120             if (mCore->stillTracking(front)) {
    121                 // Front buffer is still in mSlots, so mark the slot as free
    122                 mSlots[front->mSlot].mBufferState = BufferSlot::FREE;
    123             }
    124             mCore->mQueue.erase(front);
    125             front = mCore->mQueue.begin();
    126         }
    127 
    128         // See if the front buffer is due
    129         nsecs_t desiredPresent = front->mTimestamp;
    130         if (desiredPresent > expectedPresent &&
    131                 desiredPresent < expectedPresent + MAX_REASONABLE_NSEC) {
    132             BQ_LOGV("acquireBuffer: defer desire=%" PRId64 " expect=%" PRId64
    133                     " (%" PRId64 ") now=%" PRId64,
    134                     desiredPresent, expectedPresent,
    135                     desiredPresent - expectedPresent,
    136                     systemTime(CLOCK_MONOTONIC));
    137             return PRESENT_LATER;
    138         }
    139 
    140         BQ_LOGV("acquireBuffer: accept desire=%" PRId64 " expect=%" PRId64 " "
    141                 "(%" PRId64 ") now=%" PRId64, desiredPresent, expectedPresent,
    142                 desiredPresent - expectedPresent,
    143                 systemTime(CLOCK_MONOTONIC));
    144     }
    145 
    146     int slot = front->mSlot;
    147     *outBuffer = *front;
    148     ATRACE_BUFFER_INDEX(slot);
    149 
    150     BQ_LOGV("acquireBuffer: acquiring { slot=%d/%" PRIu64 " buffer=%p }",
    151             slot, front->mFrameNumber, front->mGraphicBuffer->handle);
    152     // If the front buffer is still being tracked, update its slot state
    153     if (mCore->stillTracking(front)) {
    154         mSlots[slot].mAcquireCalled = true;
    155         mSlots[slot].mNeedsCleanupOnRelease = false;
    156         mSlots[slot].mBufferState = BufferSlot::ACQUIRED;
    157         mSlots[slot].mFence = Fence::NO_FENCE;
    158     }
    159 
    160     // If the buffer has previously been acquired by the consumer, set
    161     // mGraphicBuffer to NULL to avoid unnecessarily remapping this buffer
    162     // on the consumer side
    163     if (outBuffer->mAcquireCalled) {
    164         outBuffer->mGraphicBuffer = NULL;
    165     }
    166 
    167     mCore->mQueue.erase(front);
    168 
    169     // We might have freed a slot while dropping old buffers, or the producer
    170     // may be blocked waiting for the number of buffers in the queue to
    171     // decrease.
    172     mCore->mDequeueCondition.broadcast();
    173 
    174     ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size());
    175 
    176     return NO_ERROR;
    177 }
    178 
    179 status_t BufferQueueConsumer::detachBuffer(int slot) {
    180     ATRACE_CALL();
    181     ATRACE_BUFFER_INDEX(slot);
    182     BQ_LOGV("detachBuffer(C): slot %d", slot);
    183     Mutex::Autolock lock(mCore->mMutex);
    184 
    185     if (mCore->mIsAbandoned) {
    186         BQ_LOGE("detachBuffer(C): BufferQueue has been abandoned");
    187         return NO_INIT;
    188     }
    189 
    190     if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
    191         BQ_LOGE("detachBuffer(C): slot index %d out of range [0, %d)",
    192                 slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
    193         return BAD_VALUE;
    194     } else if (mSlots[slot].mBufferState != BufferSlot::ACQUIRED) {
    195         BQ_LOGE("detachBuffer(C): slot %d is not owned by the consumer "
    196                 "(state = %d)", slot, mSlots[slot].mBufferState);
    197         return BAD_VALUE;
    198     }
    199 
    200     mCore->freeBufferLocked(slot);
    201     mCore->mDequeueCondition.broadcast();
    202 
    203     return NO_ERROR;
    204 }
    205 
    206 status_t BufferQueueConsumer::attachBuffer(int* outSlot,
    207         const sp<android::GraphicBuffer>& buffer) {
    208     ATRACE_CALL();
    209 
    210     if (outSlot == NULL) {
    211         BQ_LOGE("attachBuffer(P): outSlot must not be NULL");
    212         return BAD_VALUE;
    213     } else if (buffer == NULL) {
    214         BQ_LOGE("attachBuffer(P): cannot attach NULL buffer");
    215         return BAD_VALUE;
    216     }
    217 
    218     Mutex::Autolock lock(mCore->mMutex);
    219 
    220     // Make sure we don't have too many acquired buffers and find a free slot
    221     // to put the buffer into (the oldest if there are multiple).
    222     int numAcquiredBuffers = 0;
    223     int found = BufferQueueCore::INVALID_BUFFER_SLOT;
    224     for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
    225         if (mSlots[s].mBufferState == BufferSlot::ACQUIRED) {
    226             ++numAcquiredBuffers;
    227         } else if (mSlots[s].mBufferState == BufferSlot::FREE) {
    228             if (found == BufferQueueCore::INVALID_BUFFER_SLOT ||
    229                     mSlots[s].mFrameNumber < mSlots[found].mFrameNumber) {
    230                 found = s;
    231             }
    232         }
    233     }
    234 
    235     if (numAcquiredBuffers >= mCore->mMaxAcquiredBufferCount + 1) {
    236         BQ_LOGE("attachBuffer(P): max acquired buffer count reached: %d "
    237                 "(max %d)", numAcquiredBuffers,
    238                 mCore->mMaxAcquiredBufferCount);
    239         return INVALID_OPERATION;
    240     }
    241     if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
    242         BQ_LOGE("attachBuffer(P): could not find free buffer slot");
    243         return NO_MEMORY;
    244     }
    245 
    246     *outSlot = found;
    247     ATRACE_BUFFER_INDEX(*outSlot);
    248     BQ_LOGV("attachBuffer(C): returning slot %d", *outSlot);
    249 
    250     mSlots[*outSlot].mGraphicBuffer = buffer;
    251     mSlots[*outSlot].mBufferState = BufferSlot::ACQUIRED;
    252     mSlots[*outSlot].mAttachedByConsumer = true;
    253     mSlots[*outSlot].mNeedsCleanupOnRelease = false;
    254     mSlots[*outSlot].mFence = Fence::NO_FENCE;
    255     mSlots[*outSlot].mFrameNumber = 0;
    256 
    257     // mAcquireCalled tells BufferQueue that it doesn't need to send a valid
    258     // GraphicBuffer pointer on the next acquireBuffer call, which decreases
    259     // Binder traffic by not un/flattening the GraphicBuffer. However, it
    260     // requires that the consumer maintain a cached copy of the slot <--> buffer
    261     // mappings, which is why the consumer doesn't need the valid pointer on
    262     // acquire.
    263     //
    264     // The StreamSplitter is one of the primary users of the attach/detach
    265     // logic, and while it is running, all buffers it acquires are immediately
    266     // detached, and all buffers it eventually releases are ones that were
    267     // attached (as opposed to having been obtained from acquireBuffer), so it
    268     // doesn't make sense to maintain the slot/buffer mappings, which would
    269     // become invalid for every buffer during detach/attach. By setting this to
    270     // false, the valid GraphicBuffer pointer will always be sent with acquire
    271     // for attached buffers.
    272     mSlots[*outSlot].mAcquireCalled = false;
    273 
    274     return NO_ERROR;
    275 }
    276 
    277 status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber,
    278         const sp<Fence>& releaseFence, EGLDisplay eglDisplay,
    279         EGLSyncKHR eglFence) {
    280     ATRACE_CALL();
    281     ATRACE_BUFFER_INDEX(slot);
    282 
    283     if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS ||
    284             releaseFence == NULL) {
    285         return BAD_VALUE;
    286     }
    287 
    288     sp<IProducerListener> listener;
    289     { // Autolock scope
    290         Mutex::Autolock lock(mCore->mMutex);
    291 
    292         // If the frame number has changed because the buffer has been reallocated,
    293         // we can ignore this releaseBuffer for the old buffer
    294         if (frameNumber != mSlots[slot].mFrameNumber) {
    295             return STALE_BUFFER_SLOT;
    296         }
    297 
    298         // Make sure this buffer hasn't been queued while acquired by the consumer
    299         BufferQueueCore::Fifo::iterator current(mCore->mQueue.begin());
    300         while (current != mCore->mQueue.end()) {
    301             if (current->mSlot == slot) {
    302                 BQ_LOGE("releaseBuffer: buffer slot %d pending release is "
    303                         "currently queued", slot);
    304                 return BAD_VALUE;
    305             }
    306             ++current;
    307         }
    308 
    309         if (mSlots[slot].mBufferState == BufferSlot::ACQUIRED) {
    310             mSlots[slot].mEglDisplay = eglDisplay;
    311             mSlots[slot].mEglFence = eglFence;
    312             mSlots[slot].mFence = releaseFence;
    313             mSlots[slot].mBufferState = BufferSlot::FREE;
    314             listener = mCore->mConnectedProducerListener;
    315             BQ_LOGV("releaseBuffer: releasing slot %d", slot);
    316         } else if (mSlots[slot].mNeedsCleanupOnRelease) {
    317             BQ_LOGV("releaseBuffer: releasing a stale buffer slot %d "
    318                     "(state = %d)", slot, mSlots[slot].mBufferState);
    319             mSlots[slot].mNeedsCleanupOnRelease = false;
    320             return STALE_BUFFER_SLOT;
    321         } else {
    322             BQ_LOGV("releaseBuffer: attempted to release buffer slot %d "
    323                     "but its state was %d", slot, mSlots[slot].mBufferState);
    324             return BAD_VALUE;
    325         }
    326 
    327         mCore->mDequeueCondition.broadcast();
    328     } // Autolock scope
    329 
    330     // Call back without lock held
    331     if (listener != NULL) {
    332         listener->onBufferReleased();
    333     }
    334 
    335     return NO_ERROR;
    336 }
    337 
    338 status_t BufferQueueConsumer::connect(
    339         const sp<IConsumerListener>& consumerListener, bool controlledByApp) {
    340     ATRACE_CALL();
    341 
    342     if (consumerListener == NULL) {
    343         BQ_LOGE("connect(C): consumerListener may not be NULL");
    344         return BAD_VALUE;
    345     }
    346 
    347     BQ_LOGV("connect(C): controlledByApp=%s",
    348             controlledByApp ? "true" : "false");
    349 
    350     Mutex::Autolock lock(mCore->mMutex);
    351 
    352     if (mCore->mIsAbandoned) {
    353         BQ_LOGE("connect(C): BufferQueue has been abandoned");
    354         return NO_INIT;
    355     }
    356 
    357     mCore->mConsumerListener = consumerListener;
    358     mCore->mConsumerControlledByApp = controlledByApp;
    359 
    360     return NO_ERROR;
    361 }
    362 
    363 status_t BufferQueueConsumer::disconnect() {
    364     ATRACE_CALL();
    365 
    366     BQ_LOGV("disconnect(C)");
    367 
    368     Mutex::Autolock lock(mCore->mMutex);
    369 
    370     if (mCore->mConsumerListener == NULL) {
    371         BQ_LOGE("disconnect(C): no consumer is connected");
    372         return BAD_VALUE;
    373     }
    374 
    375     mCore->mIsAbandoned = true;
    376     mCore->mConsumerListener = NULL;
    377     mCore->mQueue.clear();
    378     mCore->freeAllBuffersLocked();
    379     mCore->mDequeueCondition.broadcast();
    380     return NO_ERROR;
    381 }
    382 
    383 status_t BufferQueueConsumer::getReleasedBuffers(uint64_t *outSlotMask) {
    384     ATRACE_CALL();
    385 
    386     if (outSlotMask == NULL) {
    387         BQ_LOGE("getReleasedBuffers: outSlotMask may not be NULL");
    388         return BAD_VALUE;
    389     }
    390 
    391     Mutex::Autolock lock(mCore->mMutex);
    392 
    393     if (mCore->mIsAbandoned) {
    394         BQ_LOGE("getReleasedBuffers: BufferQueue has been abandoned");
    395         return NO_INIT;
    396     }
    397 
    398     uint64_t mask = 0;
    399     for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
    400         if (!mSlots[s].mAcquireCalled) {
    401             mask |= (1ULL << s);
    402         }
    403     }
    404 
    405     // Remove from the mask queued buffers for which acquire has been called,
    406     // since the consumer will not receive their buffer addresses and so must
    407     // retain their cached information
    408     BufferQueueCore::Fifo::iterator current(mCore->mQueue.begin());
    409     while (current != mCore->mQueue.end()) {
    410         if (current->mAcquireCalled) {
    411             mask &= ~(1ULL << current->mSlot);
    412         }
    413         ++current;
    414     }
    415 
    416     BQ_LOGV("getReleasedBuffers: returning mask %#" PRIx64, mask);
    417     *outSlotMask = mask;
    418     return NO_ERROR;
    419 }
    420 
    421 status_t BufferQueueConsumer::setDefaultBufferSize(uint32_t width,
    422         uint32_t height) {
    423     ATRACE_CALL();
    424 
    425     if (width == 0 || height == 0) {
    426         BQ_LOGV("setDefaultBufferSize: dimensions cannot be 0 (width=%u "
    427                 "height=%u)", width, height);
    428         return BAD_VALUE;
    429     }
    430 
    431     BQ_LOGV("setDefaultBufferSize: width=%u height=%u", width, height);
    432 
    433     Mutex::Autolock lock(mCore->mMutex);
    434     mCore->mDefaultWidth = width;
    435     mCore->mDefaultHeight = height;
    436     return NO_ERROR;
    437 }
    438 
    439 status_t BufferQueueConsumer::setDefaultMaxBufferCount(int bufferCount) {
    440     ATRACE_CALL();
    441     Mutex::Autolock lock(mCore->mMutex);
    442     return mCore->setDefaultMaxBufferCountLocked(bufferCount);
    443 }
    444 
    445 status_t BufferQueueConsumer::disableAsyncBuffer() {
    446     ATRACE_CALL();
    447 
    448     Mutex::Autolock lock(mCore->mMutex);
    449 
    450     if (mCore->mConsumerListener != NULL) {
    451         BQ_LOGE("disableAsyncBuffer: consumer already connected");
    452         return INVALID_OPERATION;
    453     }
    454 
    455     BQ_LOGV("disableAsyncBuffer");
    456     mCore->mUseAsyncBuffer = false;
    457     return NO_ERROR;
    458 }
    459 
    460 status_t BufferQueueConsumer::setMaxAcquiredBufferCount(
    461         int maxAcquiredBuffers) {
    462     ATRACE_CALL();
    463 
    464     if (maxAcquiredBuffers < 1 ||
    465             maxAcquiredBuffers > BufferQueueCore::MAX_MAX_ACQUIRED_BUFFERS) {
    466         BQ_LOGE("setMaxAcquiredBufferCount: invalid count %d",
    467                 maxAcquiredBuffers);
    468         return BAD_VALUE;
    469     }
    470 
    471     Mutex::Autolock lock(mCore->mMutex);
    472 
    473     if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
    474         BQ_LOGE("setMaxAcquiredBufferCount: producer is already connected");
    475         return INVALID_OPERATION;
    476     }
    477 
    478     BQ_LOGV("setMaxAcquiredBufferCount: %d", maxAcquiredBuffers);
    479     mCore->mMaxAcquiredBufferCount = maxAcquiredBuffers;
    480     return NO_ERROR;
    481 }
    482 
    483 void BufferQueueConsumer::setConsumerName(const String8& name) {
    484     ATRACE_CALL();
    485     BQ_LOGV("setConsumerName: '%s'", name.string());
    486     Mutex::Autolock lock(mCore->mMutex);
    487     mCore->mConsumerName = name;
    488     mConsumerName = name;
    489 }
    490 
    491 status_t BufferQueueConsumer::setDefaultBufferFormat(uint32_t defaultFormat) {
    492     ATRACE_CALL();
    493     BQ_LOGV("setDefaultBufferFormat: %u", defaultFormat);
    494     Mutex::Autolock lock(mCore->mMutex);
    495     mCore->mDefaultBufferFormat = defaultFormat;
    496     return NO_ERROR;
    497 }
    498 
    499 status_t BufferQueueConsumer::setConsumerUsageBits(uint32_t usage) {
    500     ATRACE_CALL();
    501     BQ_LOGV("setConsumerUsageBits: %#x", usage);
    502     Mutex::Autolock lock(mCore->mMutex);
    503     mCore->mConsumerUsageBits = usage;
    504     return NO_ERROR;
    505 }
    506 
    507 status_t BufferQueueConsumer::setTransformHint(uint32_t hint) {
    508     ATRACE_CALL();
    509     BQ_LOGV("setTransformHint: %#x", hint);
    510     Mutex::Autolock lock(mCore->mMutex);
    511     mCore->mTransformHint = hint;
    512     return NO_ERROR;
    513 }
    514 
    515 sp<NativeHandle> BufferQueueConsumer::getSidebandStream() const {
    516     return mCore->mSidebandStream;
    517 }
    518 
    519 void BufferQueueConsumer::dump(String8& result, const char* prefix) const {
    520     mCore->dump(result, prefix);
    521 }
    522 
    523 } // namespace android
    524