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::setFrameAvailableListener(
    186         const wp<FrameAvailableListener>& listener) {
    187     CB_LOGV("setFrameAvailableListener");
    188     Mutex::Autolock lock(mFrameAvailableMutex);
    189     mFrameAvailableListener = listener;
    190 }
    191 
    192 status_t ConsumerBase::detachBuffer(int slot) {
    193     CB_LOGV("detachBuffer");
    194     Mutex::Autolock lock(mMutex);
    195 
    196     if (mAbandoned) {
    197         CB_LOGE("detachBuffer: ConsumerBase is abandoned!");
    198         return NO_INIT;
    199     }
    200 
    201     status_t result = mConsumer->detachBuffer(slot);
    202     if (result != NO_ERROR) {
    203         CB_LOGE("Failed to detach buffer: %d", result);
    204         return result;
    205     }
    206 
    207     freeBufferLocked(slot);
    208 
    209     return result;
    210 }
    211 
    212 status_t ConsumerBase::setDefaultBufferSize(uint32_t width, uint32_t height) {
    213     Mutex::Autolock _l(mMutex);
    214     if (mAbandoned) {
    215         CB_LOGE("setDefaultBufferSize: ConsumerBase is abandoned!");
    216         return NO_INIT;
    217     }
    218     return mConsumer->setDefaultBufferSize(width, height);
    219 }
    220 
    221 status_t ConsumerBase::setDefaultBufferFormat(PixelFormat defaultFormat) {
    222     Mutex::Autolock _l(mMutex);
    223     if (mAbandoned) {
    224         CB_LOGE("setDefaultBufferFormat: ConsumerBase is abandoned!");
    225         return NO_INIT;
    226     }
    227     return mConsumer->setDefaultBufferFormat(defaultFormat);
    228 }
    229 
    230 status_t ConsumerBase::setDefaultBufferDataSpace(
    231         android_dataspace defaultDataSpace) {
    232     Mutex::Autolock _l(mMutex);
    233     if (mAbandoned) {
    234         CB_LOGE("setDefaultBufferDataSpace: ConsumerBase is abandoned!");
    235         return NO_INIT;
    236     }
    237     return mConsumer->setDefaultBufferDataSpace(defaultDataSpace);
    238 }
    239 
    240 status_t ConsumerBase::getOccupancyHistory(bool forceFlush,
    241         std::vector<OccupancyTracker::Segment>* outHistory) {
    242     Mutex::Autolock _l(mMutex);
    243     if (mAbandoned) {
    244         CB_LOGE("getOccupancyHistory: ConsumerBase is abandoned!");
    245         return NO_INIT;
    246     }
    247     return mConsumer->getOccupancyHistory(forceFlush, outHistory);
    248 }
    249 
    250 status_t ConsumerBase::discardFreeBuffers() {
    251     Mutex::Autolock _l(mMutex);
    252     if (mAbandoned) {
    253         CB_LOGE("discardFreeBuffers: ConsumerBase is abandoned!");
    254         return NO_INIT;
    255     }
    256     status_t err = mConsumer->discardFreeBuffers();
    257     if (err != OK) {
    258         return err;
    259     }
    260     uint64_t mask;
    261     mConsumer->getReleasedBuffers(&mask);
    262     for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
    263         if (mask & (1ULL << i)) {
    264             freeBufferLocked(i);
    265         }
    266     }
    267     return OK;
    268 }
    269 
    270 void ConsumerBase::dumpState(String8& result) const {
    271     dumpState(result, "");
    272 }
    273 
    274 void ConsumerBase::dumpState(String8& result, const char* prefix) const {
    275     Mutex::Autolock _l(mMutex);
    276     dumpLocked(result, prefix);
    277 }
    278 
    279 void ConsumerBase::dumpLocked(String8& result, const char* prefix) const {
    280     result.appendFormat("%smAbandoned=%d\n", prefix, int(mAbandoned));
    281 
    282     if (!mAbandoned) {
    283         String8 consumerState;
    284         mConsumer->dumpState(String8(prefix), &consumerState);
    285         result.append(consumerState);
    286     }
    287 }
    288 
    289 status_t ConsumerBase::acquireBufferLocked(BufferItem *item,
    290         nsecs_t presentWhen, uint64_t maxFrameNumber) {
    291     if (mAbandoned) {
    292         CB_LOGE("acquireBufferLocked: ConsumerBase is abandoned!");
    293         return NO_INIT;
    294     }
    295 
    296     status_t err = mConsumer->acquireBuffer(item, presentWhen, maxFrameNumber);
    297     if (err != NO_ERROR) {
    298         return err;
    299     }
    300 
    301     if (item->mGraphicBuffer != NULL) {
    302         if (mSlots[item->mSlot].mGraphicBuffer != NULL) {
    303             freeBufferLocked(item->mSlot);
    304         }
    305         mSlots[item->mSlot].mGraphicBuffer = item->mGraphicBuffer;
    306     }
    307 
    308     mSlots[item->mSlot].mFrameNumber = item->mFrameNumber;
    309     mSlots[item->mSlot].mFence = item->mFence;
    310 
    311     CB_LOGV("acquireBufferLocked: -> slot=%d/%" PRIu64,
    312             item->mSlot, item->mFrameNumber);
    313 
    314     return OK;
    315 }
    316 
    317 status_t ConsumerBase::addReleaseFence(int slot,
    318         const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence) {
    319     Mutex::Autolock lock(mMutex);
    320     return addReleaseFenceLocked(slot, graphicBuffer, fence);
    321 }
    322 
    323 status_t ConsumerBase::addReleaseFenceLocked(int slot,
    324         const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence) {
    325     CB_LOGV("addReleaseFenceLocked: slot=%d", slot);
    326 
    327     // If consumer no longer tracks this graphicBuffer, we can safely
    328     // drop this fence, as it will never be received by the producer.
    329     if (!stillTracking(slot, graphicBuffer)) {
    330         return OK;
    331     }
    332 
    333     if (!mSlots[slot].mFence.get()) {
    334         mSlots[slot].mFence = fence;
    335         return OK;
    336     }
    337 
    338     // Check status of fences first because merging is expensive.
    339     // Merging an invalid fence with any other fence results in an
    340     // invalid fence.
    341     auto currentStatus = mSlots[slot].mFence->getStatus();
    342     if (currentStatus == Fence::Status::Invalid) {
    343         CB_LOGE("Existing fence has invalid state");
    344         return BAD_VALUE;
    345     }
    346 
    347     auto incomingStatus = fence->getStatus();
    348     if (incomingStatus == Fence::Status::Invalid) {
    349         CB_LOGE("New fence has invalid state");
    350         mSlots[slot].mFence = fence;
    351         return BAD_VALUE;
    352     }
    353 
    354     // If both fences are signaled or both are unsignaled, we need to merge
    355     // them to get an accurate timestamp.
    356     if (currentStatus == incomingStatus) {
    357         char fenceName[32] = {};
    358         snprintf(fenceName, 32, "%.28s:%d", mName.string(), slot);
    359         sp<Fence> mergedFence = Fence::merge(
    360                 fenceName, mSlots[slot].mFence, fence);
    361         if (!mergedFence.get()) {
    362             CB_LOGE("failed to merge release fences");
    363             // synchronization is broken, the best we can do is hope fences
    364             // signal in order so the new fence will act like a union
    365             mSlots[slot].mFence = fence;
    366             return BAD_VALUE;
    367         }
    368         mSlots[slot].mFence = mergedFence;
    369     } else if (incomingStatus == Fence::Status::Unsignaled) {
    370         // If one fence has signaled and the other hasn't, the unsignaled
    371         // fence will approximately correspond with the correct timestamp.
    372         // There's a small race if both fences signal at about the same time
    373         // and their statuses are retrieved with unfortunate timing. However,
    374         // by this point, they will have both signaled and only the timestamp
    375         // will be slightly off; any dependencies after this point will
    376         // already have been met.
    377         mSlots[slot].mFence = fence;
    378     }
    379     // else if (currentStatus == Fence::Status::Unsignaled) is a no-op.
    380 
    381     return OK;
    382 }
    383 
    384 status_t ConsumerBase::releaseBufferLocked(
    385         int slot, const sp<GraphicBuffer> graphicBuffer,
    386         EGLDisplay display, EGLSyncKHR eglFence) {
    387     if (mAbandoned) {
    388         CB_LOGE("releaseBufferLocked: ConsumerBase is abandoned!");
    389         return NO_INIT;
    390     }
    391     // If consumer no longer tracks this graphicBuffer (we received a new
    392     // buffer on the same slot), the buffer producer is definitely no longer
    393     // tracking it.
    394     if (!stillTracking(slot, graphicBuffer)) {
    395         return OK;
    396     }
    397 
    398     CB_LOGV("releaseBufferLocked: slot=%d/%" PRIu64,
    399             slot, mSlots[slot].mFrameNumber);
    400     status_t err = mConsumer->releaseBuffer(slot, mSlots[slot].mFrameNumber,
    401             display, eglFence, mSlots[slot].mFence);
    402     if (err == IGraphicBufferConsumer::STALE_BUFFER_SLOT) {
    403         freeBufferLocked(slot);
    404     }
    405 
    406     mPrevFinalReleaseFence = mSlots[slot].mFence;
    407     mSlots[slot].mFence = Fence::NO_FENCE;
    408 
    409     return err;
    410 }
    411 
    412 bool ConsumerBase::stillTracking(int slot,
    413         const sp<GraphicBuffer> graphicBuffer) {
    414     if (slot < 0 || slot >= BufferQueue::NUM_BUFFER_SLOTS) {
    415         return false;
    416     }
    417     return (mSlots[slot].mGraphicBuffer != NULL &&
    418             mSlots[slot].mGraphicBuffer->handle == graphicBuffer->handle);
    419 }
    420 
    421 } // namespace android
    422