Home | History | Annotate | Download | only in gui
      1 /*
      2  * Copyright (C) 2010 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 "ConsumerBase"
     20 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
     21 //#define LOG_NDEBUG 0
     22 
     23 #define EGL_EGLEXT_PROTOTYPES
     24 
     25 #include <EGL/egl.h>
     26 #include <EGL/eglext.h>
     27 
     28 #include <hardware/hardware.h>
     29 
     30 #include <cutils/atomic.h>
     31 
     32 #include <gui/BufferItem.h>
     33 #include <gui/ISurfaceComposer.h>
     34 #include <gui/SurfaceComposerClient.h>
     35 #include <gui/ConsumerBase.h>
     36 
     37 #include <private/gui/ComposerService.h>
     38 
     39 #include <utils/Log.h>
     40 #include <utils/String8.h>
     41 #include <utils/Trace.h>
     42 
     43 // Macros for including the ConsumerBase name in log messages
     44 #define CB_LOGV(x, ...) ALOGV("[%s] " x, mName.string(), ##__VA_ARGS__)
     45 //#define CB_LOGD(x, ...) ALOGD("[%s] " x, mName.string(), ##__VA_ARGS__)
     46 //#define CB_LOGI(x, ...) ALOGI("[%s] " x, mName.string(), ##__VA_ARGS__)
     47 //#define CB_LOGW(x, ...) ALOGW("[%s] " x, mName.string(), ##__VA_ARGS__)
     48 #define CB_LOGE(x, ...) ALOGE("[%s] " x, mName.string(), ##__VA_ARGS__)
     49 
     50 namespace android {
     51 
     52 // Get an ID that's unique within this process.
     53 static int32_t createProcessUniqueId() {
     54     static volatile int32_t globalCounter = 0;
     55     return android_atomic_inc(&globalCounter);
     56 }
     57 
     58 ConsumerBase::ConsumerBase(const sp<IGraphicBufferConsumer>& bufferQueue, bool controlledByApp) :
     59         mAbandoned(false),
     60         mConsumer(bufferQueue),
     61         mPrevFinalReleaseFence(Fence::NO_FENCE) {
     62     // Choose a name using the PID and a process-unique ID.
     63     mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
     64 
     65     // Note that we can't create an sp<...>(this) in a ctor that will not keep a
     66     // reference once the ctor ends, as that would cause the refcount of 'this'
     67     // dropping to 0 at the end of the ctor.  Since all we need is a wp<...>
     68     // that's what we create.
     69     wp<ConsumerListener> listener = static_cast<ConsumerListener*>(this);
     70     sp<IConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener);
     71 
     72     status_t err = mConsumer->consumerConnect(proxy, controlledByApp);
     73     if (err != NO_ERROR) {
     74         CB_LOGE("ConsumerBase: error connecting to BufferQueue: %s (%d)",
     75                 strerror(-err), err);
     76     } else {
     77         mConsumer->setConsumerName(mName);
     78     }
     79 }
     80 
     81 ConsumerBase::~ConsumerBase() {
     82     CB_LOGV("~ConsumerBase");
     83     Mutex::Autolock lock(mMutex);
     84 
     85     // Verify that abandon() has been called before we get here.  This should
     86     // be done by ConsumerBase::onLastStrongRef(), but it's possible for a
     87     // derived class to override that method and not call
     88     // ConsumerBase::onLastStrongRef().
     89     LOG_ALWAYS_FATAL_IF(!mAbandoned, "[%s] ~ConsumerBase was called, but the "
     90         "consumer is not abandoned!", mName.string());
     91 }
     92 
     93 void ConsumerBase::onLastStrongRef(const void* id __attribute__((unused))) {
     94     abandon();
     95 }
     96 
     97 void ConsumerBase::freeBufferLocked(int slotIndex) {
     98     CB_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
     99     mSlots[slotIndex].mGraphicBuffer = 0;
    100     mSlots[slotIndex].mFence = Fence::NO_FENCE;
    101     mSlots[slotIndex].mFrameNumber = 0;
    102 }
    103 
    104 void ConsumerBase::onFrameAvailable(const BufferItem& item) {
    105     CB_LOGV("onFrameAvailable");
    106 
    107     sp<FrameAvailableListener> listener;
    108     { // scope for the lock
    109         Mutex::Autolock lock(mFrameAvailableMutex);
    110         listener = mFrameAvailableListener.promote();
    111     }
    112 
    113     if (listener != NULL) {
    114         CB_LOGV("actually calling onFrameAvailable");
    115         listener->onFrameAvailable(item);
    116     }
    117 }
    118 
    119 void ConsumerBase::onFrameReplaced(const BufferItem &item) {
    120     CB_LOGV("onFrameReplaced");
    121 
    122     sp<FrameAvailableListener> listener;
    123     {
    124         Mutex::Autolock lock(mFrameAvailableMutex);
    125         listener = mFrameAvailableListener.promote();
    126     }
    127 
    128     if (listener != NULL) {
    129         CB_LOGV("actually calling onFrameReplaced");
    130         listener->onFrameReplaced(item);
    131     }
    132 }
    133 
    134 void ConsumerBase::onBuffersReleased() {
    135     Mutex::Autolock lock(mMutex);
    136 
    137     CB_LOGV("onBuffersReleased");
    138 
    139     if (mAbandoned) {
    140         // Nothing to do if we're already abandoned.
    141         return;
    142     }
    143 
    144     uint64_t mask = 0;
    145     mConsumer->getReleasedBuffers(&mask);
    146     for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
    147         if (mask & (1ULL << i)) {
    148             freeBufferLocked(i);
    149         }
    150     }
    151 }
    152 
    153 void ConsumerBase::onSidebandStreamChanged() {
    154 }
    155 
    156 void ConsumerBase::abandon() {
    157     CB_LOGV("abandon");
    158     Mutex::Autolock lock(mMutex);
    159 
    160     if (!mAbandoned) {
    161         abandonLocked();
    162         mAbandoned = true;
    163     }
    164 }
    165 
    166 void ConsumerBase::abandonLocked() {
    167     CB_LOGV("abandonLocked");
    168     if (mAbandoned) {
    169         CB_LOGE("abandonLocked: ConsumerBase is abandoned!");
    170         return;
    171     }
    172     for (int i =0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
    173         freeBufferLocked(i);
    174     }
    175     // disconnect from the BufferQueue
    176     mConsumer->consumerDisconnect();
    177     mConsumer.clear();
    178 }
    179 
    180 bool ConsumerBase::isAbandoned() {
    181     Mutex::Autolock _l(mMutex);
    182     return mAbandoned;
    183 }
    184 
    185 void ConsumerBase::setName(const String8& name) {
    186     Mutex::Autolock _l(mMutex);
    187     if (mAbandoned) {
    188         CB_LOGE("setName: ConsumerBase is abandoned!");
    189         return;
    190     }
    191     mName = name;
    192     mConsumer->setConsumerName(name);
    193 }
    194 
    195 void ConsumerBase::setFrameAvailableListener(
    196         const wp<FrameAvailableListener>& listener) {
    197     CB_LOGV("setFrameAvailableListener");
    198     Mutex::Autolock lock(mFrameAvailableMutex);
    199     mFrameAvailableListener = listener;
    200 }
    201 
    202 status_t ConsumerBase::detachBuffer(int slot) {
    203     CB_LOGV("detachBuffer");
    204     Mutex::Autolock lock(mMutex);
    205 
    206     if (mAbandoned) {
    207         CB_LOGE("detachBuffer: ConsumerBase is abandoned!");
    208         return NO_INIT;
    209     }
    210 
    211     status_t result = mConsumer->detachBuffer(slot);
    212     if (result != NO_ERROR) {
    213         CB_LOGE("Failed to detach buffer: %d", result);
    214         return result;
    215     }
    216 
    217     freeBufferLocked(slot);
    218 
    219     return result;
    220 }
    221 
    222 status_t ConsumerBase::setDefaultBufferSize(uint32_t width, uint32_t height) {
    223     Mutex::Autolock _l(mMutex);
    224     if (mAbandoned) {
    225         CB_LOGE("setDefaultBufferSize: ConsumerBase is abandoned!");
    226         return NO_INIT;
    227     }
    228     return mConsumer->setDefaultBufferSize(width, height);
    229 }
    230 
    231 status_t ConsumerBase::setDefaultBufferFormat(PixelFormat defaultFormat) {
    232     Mutex::Autolock _l(mMutex);
    233     if (mAbandoned) {
    234         CB_LOGE("setDefaultBufferFormat: ConsumerBase is abandoned!");
    235         return NO_INIT;
    236     }
    237     return mConsumer->setDefaultBufferFormat(defaultFormat);
    238 }
    239 
    240 status_t ConsumerBase::setDefaultBufferDataSpace(
    241         android_dataspace defaultDataSpace) {
    242     Mutex::Autolock _l(mMutex);
    243     if (mAbandoned) {
    244         CB_LOGE("setDefaultBufferDataSpace: ConsumerBase is abandoned!");
    245         return NO_INIT;
    246     }
    247     return mConsumer->setDefaultBufferDataSpace(defaultDataSpace);
    248 }
    249 
    250 status_t ConsumerBase::setConsumerUsageBits(uint64_t usage) {
    251     Mutex::Autolock lock(mMutex);
    252     if (mAbandoned) {
    253         CB_LOGE("setConsumerUsageBits: ConsumerBase is abandoned!");
    254         return NO_INIT;
    255     }
    256     return mConsumer->setConsumerUsageBits(usage);
    257 }
    258 
    259 status_t ConsumerBase::setTransformHint(uint32_t hint) {
    260     Mutex::Autolock lock(mMutex);
    261     if (mAbandoned) {
    262         CB_LOGE("setTransformHint: ConsumerBase is abandoned!");
    263         return NO_INIT;
    264     }
    265     return mConsumer->setTransformHint(hint);
    266 }
    267 
    268 status_t ConsumerBase::setMaxAcquiredBufferCount(int maxAcquiredBuffers) {
    269     Mutex::Autolock lock(mMutex);
    270     if (mAbandoned) {
    271         CB_LOGE("setMaxAcquiredBufferCount: ConsumerBase is abandoned!");
    272         return NO_INIT;
    273     }
    274     return mConsumer->setMaxAcquiredBufferCount(maxAcquiredBuffers);
    275 }
    276 
    277 sp<NativeHandle> ConsumerBase::getSidebandStream() const {
    278     Mutex::Autolock _l(mMutex);
    279     if (mAbandoned) {
    280         CB_LOGE("getSidebandStream: ConsumerBase is abandoned!");
    281         return nullptr;
    282     }
    283 
    284     sp<NativeHandle> stream;
    285     status_t err = mConsumer->getSidebandStream(&stream);
    286     if (err != NO_ERROR) {
    287         CB_LOGE("failed to get sideband stream: %d", err);
    288         return nullptr;
    289     }
    290 
    291     return stream;
    292 }
    293 
    294 status_t ConsumerBase::getOccupancyHistory(bool forceFlush,
    295         std::vector<OccupancyTracker::Segment>* outHistory) {
    296     Mutex::Autolock _l(mMutex);
    297     if (mAbandoned) {
    298         CB_LOGE("getOccupancyHistory: ConsumerBase is abandoned!");
    299         return NO_INIT;
    300     }
    301     return mConsumer->getOccupancyHistory(forceFlush, outHistory);
    302 }
    303 
    304 status_t ConsumerBase::discardFreeBuffers() {
    305     Mutex::Autolock _l(mMutex);
    306     if (mAbandoned) {
    307         CB_LOGE("discardFreeBuffers: ConsumerBase is abandoned!");
    308         return NO_INIT;
    309     }
    310     status_t err = mConsumer->discardFreeBuffers();
    311     if (err != OK) {
    312         return err;
    313     }
    314     uint64_t mask;
    315     mConsumer->getReleasedBuffers(&mask);
    316     for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
    317         if (mask & (1ULL << i)) {
    318             freeBufferLocked(i);
    319         }
    320     }
    321     return OK;
    322 }
    323 
    324 void ConsumerBase::dumpState(String8& result) const {
    325     dumpState(result, "");
    326 }
    327 
    328 void ConsumerBase::dumpState(String8& result, const char* prefix) const {
    329     Mutex::Autolock _l(mMutex);
    330     dumpLocked(result, prefix);
    331 }
    332 
    333 void ConsumerBase::dumpLocked(String8& result, const char* prefix) const {
    334     result.appendFormat("%smAbandoned=%d\n", prefix, int(mAbandoned));
    335 
    336     if (!mAbandoned) {
    337         String8 consumerState;
    338         mConsumer->dumpState(String8(prefix), &consumerState);
    339         result.append(consumerState);
    340     }
    341 }
    342 
    343 status_t ConsumerBase::acquireBufferLocked(BufferItem *item,
    344         nsecs_t presentWhen, uint64_t maxFrameNumber) {
    345     if (mAbandoned) {
    346         CB_LOGE("acquireBufferLocked: ConsumerBase is abandoned!");
    347         return NO_INIT;
    348     }
    349 
    350     status_t err = mConsumer->acquireBuffer(item, presentWhen, maxFrameNumber);
    351     if (err != NO_ERROR) {
    352         return err;
    353     }
    354 
    355     if (item->mGraphicBuffer != NULL) {
    356         if (mSlots[item->mSlot].mGraphicBuffer != NULL) {
    357             freeBufferLocked(item->mSlot);
    358         }
    359         mSlots[item->mSlot].mGraphicBuffer = item->mGraphicBuffer;
    360     }
    361 
    362     mSlots[item->mSlot].mFrameNumber = item->mFrameNumber;
    363     mSlots[item->mSlot].mFence = item->mFence;
    364 
    365     CB_LOGV("acquireBufferLocked: -> slot=%d/%" PRIu64,
    366             item->mSlot, item->mFrameNumber);
    367 
    368     return OK;
    369 }
    370 
    371 status_t ConsumerBase::addReleaseFence(int slot,
    372         const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence) {
    373     Mutex::Autolock lock(mMutex);
    374     return addReleaseFenceLocked(slot, graphicBuffer, fence);
    375 }
    376 
    377 status_t ConsumerBase::addReleaseFenceLocked(int slot,
    378         const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence) {
    379     CB_LOGV("addReleaseFenceLocked: slot=%d", slot);
    380 
    381     // If consumer no longer tracks this graphicBuffer, we can safely
    382     // drop this fence, as it will never be received by the producer.
    383     if (!stillTracking(slot, graphicBuffer)) {
    384         return OK;
    385     }
    386 
    387     if (!mSlots[slot].mFence.get()) {
    388         mSlots[slot].mFence = fence;
    389         return OK;
    390     }
    391 
    392     // Check status of fences first because merging is expensive.
    393     // Merging an invalid fence with any other fence results in an
    394     // invalid fence.
    395     auto currentStatus = mSlots[slot].mFence->getStatus();
    396     if (currentStatus == Fence::Status::Invalid) {
    397         CB_LOGE("Existing fence has invalid state");
    398         return BAD_VALUE;
    399     }
    400 
    401     auto incomingStatus = fence->getStatus();
    402     if (incomingStatus == Fence::Status::Invalid) {
    403         CB_LOGE("New fence has invalid state");
    404         mSlots[slot].mFence = fence;
    405         return BAD_VALUE;
    406     }
    407 
    408     // If both fences are signaled or both are unsignaled, we need to merge
    409     // them to get an accurate timestamp.
    410     if (currentStatus == incomingStatus) {
    411         char fenceName[32] = {};
    412         snprintf(fenceName, 32, "%.28s:%d", mName.string(), slot);
    413         sp<Fence> mergedFence = Fence::merge(
    414                 fenceName, mSlots[slot].mFence, fence);
    415         if (!mergedFence.get()) {
    416             CB_LOGE("failed to merge release fences");
    417             // synchronization is broken, the best we can do is hope fences
    418             // signal in order so the new fence will act like a union
    419             mSlots[slot].mFence = fence;
    420             return BAD_VALUE;
    421         }
    422         mSlots[slot].mFence = mergedFence;
    423     } else if (incomingStatus == Fence::Status::Unsignaled) {
    424         // If one fence has signaled and the other hasn't, the unsignaled
    425         // fence will approximately correspond with the correct timestamp.
    426         // There's a small race if both fences signal at about the same time
    427         // and their statuses are retrieved with unfortunate timing. However,
    428         // by this point, they will have both signaled and only the timestamp
    429         // will be slightly off; any dependencies after this point will
    430         // already have been met.
    431         mSlots[slot].mFence = fence;
    432     }
    433     // else if (currentStatus == Fence::Status::Unsignaled) is a no-op.
    434 
    435     return OK;
    436 }
    437 
    438 status_t ConsumerBase::releaseBufferLocked(
    439         int slot, const sp<GraphicBuffer> graphicBuffer,
    440         EGLDisplay display, EGLSyncKHR eglFence) {
    441     if (mAbandoned) {
    442         CB_LOGE("releaseBufferLocked: ConsumerBase is abandoned!");
    443         return NO_INIT;
    444     }
    445     // If consumer no longer tracks this graphicBuffer (we received a new
    446     // buffer on the same slot), the buffer producer is definitely no longer
    447     // tracking it.
    448     if (!stillTracking(slot, graphicBuffer)) {
    449         return OK;
    450     }
    451 
    452     CB_LOGV("releaseBufferLocked: slot=%d/%" PRIu64,
    453             slot, mSlots[slot].mFrameNumber);
    454     status_t err = mConsumer->releaseBuffer(slot, mSlots[slot].mFrameNumber,
    455             display, eglFence, mSlots[slot].mFence);
    456     if (err == IGraphicBufferConsumer::STALE_BUFFER_SLOT) {
    457         freeBufferLocked(slot);
    458     }
    459 
    460     mPrevFinalReleaseFence = mSlots[slot].mFence;
    461     mSlots[slot].mFence = Fence::NO_FENCE;
    462 
    463     return err;
    464 }
    465 
    466 bool ConsumerBase::stillTracking(int slot,
    467         const sp<GraphicBuffer> graphicBuffer) {
    468     if (slot < 0 || slot >= BufferQueue::NUM_BUFFER_SLOTS) {
    469         return false;
    470     }
    471     return (mSlots[slot].mGraphicBuffer != NULL &&
    472             mSlots[slot].mGraphicBuffer->handle == graphicBuffer->handle);
    473 }
    474 
    475 } // namespace android
    476