• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #define LOG_TAG "ConsumerBase"
18 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
19 //#define LOG_NDEBUG 0
20 
21 #define EGL_EGLEXT_PROTOTYPES
22 
23 #include <EGL/egl.h>
24 #include <EGL/eglext.h>
25 
26 #include <hardware/hardware.h>
27 
28 #include <cutils/atomic.h>
29 
30 #include <com_android_graphics_libgui_flags.h>
31 #include <gui/BufferItem.h>
32 #include <gui/BufferQueue.h>
33 #include <gui/ConsumerBase.h>
34 #include <gui/ISurfaceComposer.h>
35 #include <gui/Surface.h>
36 #include <gui/SurfaceComposerClient.h>
37 
38 #include <private/gui/ComposerService.h>
39 
40 #include <ui/BufferQueueDefs.h>
41 
42 #include <log/log.h>
43 #include <utils/Log.h>
44 #include <utils/String8.h>
45 #include <utils/Trace.h>
46 
47 #include <inttypes.h>
48 
49 // Macros for including the ConsumerBase name in log messages
50 #define CB_LOGV(x, ...) ALOGV("[%s] " x, mName.c_str(), ##__VA_ARGS__)
51 // #define CB_LOGD(x, ...) ALOGD("[%s] " x, mName.c_str(), ##__VA_ARGS__)
52 // #define CB_LOGI(x, ...) ALOGI("[%s] " x, mName.c_str(), ##__VA_ARGS__)
53 // #define CB_LOGW(x, ...) ALOGW("[%s] " x, mName.c_str(), ##__VA_ARGS__)
54 #define CB_LOGE(x, ...) ALOGE("[%s] " x, mName.c_str(), ##__VA_ARGS__)
55 
56 namespace android {
57 
58 // Get an ID that's unique within this process.
createProcessUniqueId()59 static int32_t createProcessUniqueId() {
60     static volatile int32_t globalCounter = 0;
61     return android_atomic_inc(&globalCounter);
62 }
63 
ConsumerBase(const sp<IGraphicBufferConsumer> & bufferQueue,bool controlledByApp)64 ConsumerBase::ConsumerBase(const sp<IGraphicBufferConsumer>& bufferQueue, bool controlledByApp)
65       :
66 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
67         mSlots(BufferQueueDefs::NUM_BUFFER_SLOTS),
68 #endif
69         mAbandoned(false),
70         mConsumer(bufferQueue),
71         mPrevFinalReleaseFence(Fence::NO_FENCE) {
72     initialize(controlledByApp);
73 }
74 
75 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
ConsumerBase(bool controlledByApp,bool consumerIsSurfaceFlinger)76 ConsumerBase::ConsumerBase(bool controlledByApp, bool consumerIsSurfaceFlinger)
77       :
78 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
79         mSlots(BufferQueueDefs::NUM_BUFFER_SLOTS),
80 #endif
81         mAbandoned(false),
82         mPrevFinalReleaseFence(Fence::NO_FENCE) {
83     sp<IGraphicBufferProducer> producer;
84     BufferQueue::createBufferQueue(&producer, &mConsumer, consumerIsSurfaceFlinger);
85     mSurface = sp<Surface>::make(producer, controlledByApp);
86     initialize(controlledByApp);
87 }
88 
ConsumerBase(const sp<IGraphicBufferProducer> & producer,const sp<IGraphicBufferConsumer> & consumer,bool controlledByApp)89 ConsumerBase::ConsumerBase(const sp<IGraphicBufferProducer>& producer,
90                            const sp<IGraphicBufferConsumer>& consumer, bool controlledByApp)
91       :
92 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
93         mSlots(BufferQueueDefs::NUM_BUFFER_SLOTS),
94 #endif
95         mAbandoned(false),
96         mConsumer(consumer),
97         mSurface(sp<Surface>::make(producer, controlledByApp)),
98         mPrevFinalReleaseFence(Fence::NO_FENCE) {
99     initialize(controlledByApp);
100 }
101 
102 #endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
103 
initialize(bool controlledByApp)104 void ConsumerBase::initialize(bool controlledByApp) {
105     // Choose a name using the PID and a process-unique ID.
106     mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
107 
108     // Note that we can't create an sp<...>(this) in a ctor that will not keep a
109     // reference once the ctor ends, as that would cause the refcount of 'this'
110     // dropping to 0 at the end of the ctor.  Since all we need is a wp<...>
111     // that's what we create.
112     wp<ConsumerListener> listener = static_cast<ConsumerListener*>(this);
113     sp<IConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener);
114 
115     status_t err = mConsumer->consumerConnect(proxy, controlledByApp);
116     if (err != NO_ERROR) {
117         CB_LOGE("ConsumerBase: error connecting to BufferQueue: %s (%d)",
118                 strerror(-err), err);
119         return;
120     }
121 
122     mConsumer->setConsumerName(mName);
123 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
124     if (err = mConsumer->allowUnlimitedSlots(true); err != NO_ERROR) {
125         CB_LOGE("ConsumerBase: error marking as allowed to have unlimited slots: %s (%d)",
126                 strerror(-err), err);
127     }
128 #endif
129 }
130 
~ConsumerBase()131 ConsumerBase::~ConsumerBase() {
132     CB_LOGV("~ConsumerBase");
133     Mutex::Autolock lock(mMutex);
134 
135     // Verify that abandon() has been called before we get here.  This should
136     // be done by ConsumerBase::onLastStrongRef(), but it's possible for a
137     // derived class to override that method and not call
138     // ConsumerBase::onLastStrongRef().
139     LOG_ALWAYS_FATAL_IF(!mAbandoned,
140                         "[%s] ~ConsumerBase was called, but the "
141                         "consumer is not abandoned!",
142                         mName.c_str());
143 }
144 
onLastStrongRef(const void * id)145 void ConsumerBase::onLastStrongRef(const void* id __attribute__((unused))) {
146     abandon();
147 }
148 
getSlotForBufferLocked(const sp<GraphicBuffer> & buffer)149 int ConsumerBase::getSlotForBufferLocked(const sp<GraphicBuffer>& buffer) {
150     if (!buffer) {
151         return BufferQueue::INVALID_BUFFER_SLOT;
152     }
153 
154     uint64_t id = buffer->getId();
155 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
156     for (int i = 0; i < (int)mSlots.size(); ++i) {
157 #else
158     for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
159 #endif
160         auto& slot = mSlots[i];
161         if (slot.mGraphicBuffer && slot.mGraphicBuffer->getId() == id) {
162             return i;
163         }
164     }
165 
166     return BufferQueue::INVALID_BUFFER_SLOT;
167 }
168 
169 status_t ConsumerBase::detachBufferLocked(int slotIndex) {
170     status_t result = mConsumer->detachBuffer(slotIndex);
171 
172     if (result != NO_ERROR) {
173         CB_LOGE("Failed to detach buffer: %d", result);
174         return result;
175     }
176 
177     freeBufferLocked(slotIndex);
178 
179     return result;
180 }
181 
182 void ConsumerBase::freeBufferLocked(int slotIndex) {
183     CB_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
184     mSlots[slotIndex].mGraphicBuffer = nullptr;
185     mSlots[slotIndex].mFence = Fence::NO_FENCE;
186     mSlots[slotIndex].mFrameNumber = 0;
187 }
188 
189 void ConsumerBase::onFrameDequeued(const uint64_t bufferId) {
190     CB_LOGV("onFrameDequeued");
191 
192     sp<FrameAvailableListener> listener;
193     {
194         Mutex::Autolock lock(mFrameAvailableMutex);
195         listener = mFrameAvailableListener.promote();
196     }
197 
198     if (listener != nullptr) {
199         listener->onFrameDequeued(bufferId);
200     }
201 }
202 
203 void ConsumerBase::onFrameCancelled(const uint64_t bufferId) {
204     CB_LOGV("onFrameCancelled");
205 
206     sp<FrameAvailableListener> listener;
207     {
208         Mutex::Autolock lock(mFrameAvailableMutex);
209         listener = mFrameAvailableListener.promote();
210     }
211 
212     if (listener != nullptr) {
213         listener->onFrameCancelled(bufferId);
214     }
215 }
216 
217 void ConsumerBase::onFrameDetached(const uint64_t bufferId) {
218     CB_LOGV("onFrameDetached");
219 
220     sp<FrameAvailableListener> listener;
221     {
222         Mutex::Autolock lock(mFrameAvailableMutex);
223         listener = mFrameAvailableListener.promote();
224     }
225 
226     if (listener != nullptr) {
227         listener->onFrameDetached(bufferId);
228     }
229 }
230 
231 void ConsumerBase::onFrameAvailable(const BufferItem& item) {
232     CB_LOGV("onFrameAvailable");
233 
234     sp<FrameAvailableListener> listener;
235     { // scope for the lock
236         Mutex::Autolock lock(mFrameAvailableMutex);
237         listener = mFrameAvailableListener.promote();
238     }
239 
240     if (listener != nullptr) {
241         CB_LOGV("actually calling onFrameAvailable");
242         listener->onFrameAvailable(item);
243     }
244 }
245 
246 void ConsumerBase::onFrameReplaced(const BufferItem &item) {
247     CB_LOGV("onFrameReplaced");
248 
249     sp<FrameAvailableListener> listener;
250     {
251         Mutex::Autolock lock(mFrameAvailableMutex);
252         listener = mFrameAvailableListener.promote();
253     }
254 
255     if (listener != nullptr) {
256         CB_LOGV("actually calling onFrameReplaced");
257         listener->onFrameReplaced(item);
258     }
259 }
260 
261 void ConsumerBase::onBuffersReleased() {
262     Mutex::Autolock lock(mMutex);
263     onBuffersReleasedLocked();
264 }
265 
266 void ConsumerBase::onBuffersReleasedLocked() {
267     CB_LOGV("onBuffersReleased");
268 
269     if (mAbandoned) {
270         // Nothing to do if we're already abandoned.
271         return;
272     }
273 
274 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
275     std::vector<bool> mask;
276     mConsumer->getReleasedBuffersExtended(&mask);
277     for (size_t i = 0; i < mSlots.size(); i++) {
278         if (mask[i]) {
279             freeBufferLocked(i);
280         }
281     }
282 #else
283     uint64_t mask = 0;
284     mConsumer->getReleasedBuffers(&mask);
285     for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
286         if (mask & (1ULL << i)) {
287             freeBufferLocked(i);
288         }
289     }
290 #endif
291 }
292 
293 void ConsumerBase::onSidebandStreamChanged() {
294 }
295 
296 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
297 void ConsumerBase::onSlotCountChanged(int slotCount) {
298     CB_LOGV("onSlotCountChanged: %d", slotCount);
299     Mutex::Autolock lock(mMutex);
300 
301     if (slotCount > (int)mSlots.size()) {
302         mSlots.resize(slotCount);
303     }
304 }
305 #endif
306 
307 void ConsumerBase::abandon() {
308     CB_LOGV("abandon");
309     Mutex::Autolock lock(mMutex);
310 
311     if (!mAbandoned) {
312         abandonLocked();
313         mAbandoned = true;
314     }
315 }
316 
317 void ConsumerBase::abandonLocked() {
318     CB_LOGV("abandonLocked");
319     if (mAbandoned) {
320         CB_LOGE("abandonLocked: ConsumerBase is abandoned!");
321         return;
322     }
323 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
324     for (int i = 0; i < (int)mSlots.size(); ++i) {
325 #else
326     for (int i =0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
327 #endif
328         freeBufferLocked(i);
329     }
330     // disconnect from the BufferQueue
331     mConsumer->consumerDisconnect();
332     mConsumer.clear();
333 }
334 
335 bool ConsumerBase::isAbandoned() {
336     Mutex::Autolock _l(mMutex);
337     return mAbandoned;
338 }
339 
340 void ConsumerBase::setName(const String8& name) {
341     Mutex::Autolock _l(mMutex);
342     if (mAbandoned) {
343         CB_LOGE("setName: ConsumerBase is abandoned!");
344         return;
345     }
346     mName = name;
347     mConsumer->setConsumerName(name);
348 }
349 
350 void ConsumerBase::setFrameAvailableListener(
351         const wp<FrameAvailableListener>& listener) {
352     CB_LOGV("setFrameAvailableListener");
353     Mutex::Autolock lock(mFrameAvailableMutex);
354     mFrameAvailableListener = listener;
355 }
356 
357 status_t ConsumerBase::detachBuffer(int slot) {
358     CB_LOGV("detachBuffer");
359     Mutex::Autolock lock(mMutex);
360 
361     if (mAbandoned) {
362         CB_LOGE("detachBuffer: ConsumerBase is abandoned!");
363         return NO_INIT;
364     }
365 
366     return detachBufferLocked(slot);
367 }
368 
369 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
370 status_t ConsumerBase::detachBuffer(const sp<GraphicBuffer>& buffer) {
371     CB_LOGV("detachBuffer");
372     Mutex::Autolock lock(mMutex);
373 
374     if (mAbandoned) {
375         CB_LOGE("detachBuffer: ConsumerBase is abandoned!");
376         return NO_INIT;
377     }
378     if (buffer == nullptr) {
379         return BAD_VALUE;
380     }
381 
382     int slotIndex = getSlotForBufferLocked(buffer);
383     if (slotIndex == BufferQueue::INVALID_BUFFER_SLOT) {
384         return BAD_VALUE;
385     }
386 
387     return detachBufferLocked(slotIndex);
388 }
389 #endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
390 
391 status_t ConsumerBase::addReleaseFence(const sp<GraphicBuffer> buffer, const sp<Fence>& fence) {
392     CB_LOGV("addReleaseFence");
393     Mutex::Autolock lock(mMutex);
394 
395     if (mAbandoned) {
396         CB_LOGE("addReleaseFence: ConsumerBase is abandoned!");
397         return NO_INIT;
398     }
399     if (buffer == nullptr) {
400         return BAD_VALUE;
401     }
402 
403     int slotIndex = getSlotForBufferLocked(buffer);
404     if (slotIndex == BufferQueue::INVALID_BUFFER_SLOT) {
405         return BAD_VALUE;
406     }
407 
408     return addReleaseFenceLocked(slotIndex, buffer, fence);
409 }
410 
411 status_t ConsumerBase::setDefaultBufferSize(uint32_t width, uint32_t height) {
412     Mutex::Autolock _l(mMutex);
413     if (mAbandoned) {
414         CB_LOGE("setDefaultBufferSize: ConsumerBase is abandoned!");
415         return NO_INIT;
416     }
417     return mConsumer->setDefaultBufferSize(width, height);
418 }
419 
420 status_t ConsumerBase::setDefaultBufferFormat(PixelFormat defaultFormat) {
421     Mutex::Autolock _l(mMutex);
422     if (mAbandoned) {
423         CB_LOGE("setDefaultBufferFormat: ConsumerBase is abandoned!");
424         return NO_INIT;
425     }
426     return mConsumer->setDefaultBufferFormat(defaultFormat);
427 }
428 
429 status_t ConsumerBase::setDefaultBufferDataSpace(
430         android_dataspace defaultDataSpace) {
431     Mutex::Autolock _l(mMutex);
432     if (mAbandoned) {
433         CB_LOGE("setDefaultBufferDataSpace: ConsumerBase is abandoned!");
434         return NO_INIT;
435     }
436     return mConsumer->setDefaultBufferDataSpace(defaultDataSpace);
437 }
438 
439 status_t ConsumerBase::setConsumerUsageBits(uint64_t usage) {
440     Mutex::Autolock lock(mMutex);
441     if (mAbandoned) {
442         CB_LOGE("setConsumerUsageBits: ConsumerBase is abandoned!");
443         return NO_INIT;
444     }
445     return mConsumer->setConsumerUsageBits(usage);
446 }
447 
448 status_t ConsumerBase::setTransformHint(uint32_t hint) {
449     Mutex::Autolock lock(mMutex);
450     if (mAbandoned) {
451         CB_LOGE("setTransformHint: ConsumerBase is abandoned!");
452         return NO_INIT;
453     }
454     return mConsumer->setTransformHint(hint);
455 }
456 
457 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
458 status_t ConsumerBase::setMaxBufferCount(int bufferCount) {
459     Mutex::Autolock lock(mMutex);
460     if (mAbandoned) {
461         CB_LOGE("setMaxBufferCount: ConsumerBase is abandoned!");
462         return NO_INIT;
463     }
464 
465 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
466     if (status_t err = mConsumer->allowUnlimitedSlots(false); err != NO_ERROR) {
467         CB_LOGE("ConsumerBase: error marking as not allowed to have unlimited slots: %s (%d)",
468                 strerror(-err), err);
469         return err;
470     }
471 #endif
472 
473     return mConsumer->setMaxBufferCount(bufferCount);
474 }
475 #endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
476 
477 status_t ConsumerBase::setMaxAcquiredBufferCount(int maxAcquiredBuffers) {
478     Mutex::Autolock lock(mMutex);
479     if (mAbandoned) {
480         CB_LOGE("setMaxAcquiredBufferCount: ConsumerBase is abandoned!");
481         return NO_INIT;
482     }
483     return mConsumer->setMaxAcquiredBufferCount(maxAcquiredBuffers,
484                                                 {[this]() { onBuffersReleasedLocked(); }});
485 }
486 
487 status_t ConsumerBase::setConsumerIsProtected(bool isProtected) {
488     Mutex::Autolock lock(mMutex);
489     if (mAbandoned) {
490         CB_LOGE("setConsumerIsProtected: ConsumerBase is abandoned!");
491         return NO_INIT;
492     }
493     return mConsumer->setConsumerIsProtected(isProtected);
494 }
495 
496 sp<NativeHandle> ConsumerBase::getSidebandStream() const {
497     Mutex::Autolock _l(mMutex);
498     if (mAbandoned) {
499         CB_LOGE("getSidebandStream: ConsumerBase is abandoned!");
500         return nullptr;
501     }
502 
503     sp<NativeHandle> stream;
504     status_t err = mConsumer->getSidebandStream(&stream);
505     if (err != NO_ERROR) {
506         CB_LOGE("failed to get sideband stream: %d", err);
507         return nullptr;
508     }
509 
510     return stream;
511 }
512 
513 status_t ConsumerBase::getOccupancyHistory(bool forceFlush,
514         std::vector<OccupancyTracker::Segment>* outHistory) {
515     Mutex::Autolock _l(mMutex);
516     if (mAbandoned) {
517         CB_LOGE("getOccupancyHistory: ConsumerBase is abandoned!");
518         return NO_INIT;
519     }
520     return mConsumer->getOccupancyHistory(forceFlush, outHistory);
521 }
522 
523 status_t ConsumerBase::discardFreeBuffers() {
524     Mutex::Autolock _l(mMutex);
525     if (mAbandoned) {
526         CB_LOGE("discardFreeBuffers: ConsumerBase is abandoned!");
527         return NO_INIT;
528     }
529     status_t err = mConsumer->discardFreeBuffers();
530     if (err != OK) {
531         return err;
532     }
533 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
534     std::vector<bool> mask;
535     mConsumer->getReleasedBuffersExtended(&mask);
536     for (int i = 0; i < (int)mSlots.size(); i++) {
537         if (mask[i]) {
538             freeBufferLocked(i);
539         }
540     }
541 #else
542     uint64_t mask;
543     mConsumer->getReleasedBuffers(&mask);
544     for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
545         if (mask & (1ULL << i)) {
546             freeBufferLocked(i);
547         }
548     }
549 #endif
550 
551     return OK;
552 }
553 
554 void ConsumerBase::dumpState(String8& result) const {
555     dumpState(result, "");
556 }
557 
558 void ConsumerBase::dumpState(String8& result, const char* prefix) const {
559     Mutex::Autolock _l(mMutex);
560     dumpLocked(result, prefix);
561 }
562 
563 void ConsumerBase::dumpLocked(String8& result, const char* prefix) const {
564     result.appendFormat("%smAbandoned=%d\n", prefix, int(mAbandoned));
565 
566     if (!mAbandoned) {
567         String8 consumerState;
568         mConsumer->dumpState(String8(prefix), &consumerState);
569         result.append(consumerState);
570     }
571 }
572 
573 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
574 sp<Surface> ConsumerBase::getSurface() const {
575     LOG_ALWAYS_FATAL_IF(mSurface == nullptr,
576                         "It's illegal to get the surface of a Consumer that does not own it. This "
577                         "should be impossible once the old CTOR is removed.");
578     return mSurface;
579 }
580 
581 sp<IGraphicBufferConsumer> ConsumerBase::getIGraphicBufferConsumer() const {
582     return mConsumer;
583 }
584 #endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
585 
586 status_t ConsumerBase::acquireBufferLocked(BufferItem *item,
587         nsecs_t presentWhen, uint64_t maxFrameNumber) {
588     if (mAbandoned) {
589         CB_LOGE("acquireBufferLocked: ConsumerBase is abandoned!");
590         return NO_INIT;
591     }
592 
593     status_t err = mConsumer->acquireBuffer(item, presentWhen, maxFrameNumber);
594     if (err != NO_ERROR) {
595         return err;
596     }
597 
598     if (item->mGraphicBuffer != nullptr) {
599         if (mSlots[item->mSlot].mGraphicBuffer != nullptr) {
600             freeBufferLocked(item->mSlot);
601         }
602         mSlots[item->mSlot].mGraphicBuffer = item->mGraphicBuffer;
603     }
604 
605     mSlots[item->mSlot].mFrameNumber = item->mFrameNumber;
606     mSlots[item->mSlot].mFence = item->mFence;
607 
608     CB_LOGV("acquireBufferLocked: -> slot=%d/%" PRIu64,
609             item->mSlot, item->mFrameNumber);
610 
611     return OK;
612 }
613 
614 status_t ConsumerBase::addReleaseFence(int slot,
615         const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence) {
616     Mutex::Autolock lock(mMutex);
617     return addReleaseFenceLocked(slot, graphicBuffer, fence);
618 }
619 
620 status_t ConsumerBase::addReleaseFenceLocked(int slot,
621         const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence) {
622     CB_LOGV("addReleaseFenceLocked: slot=%d", slot);
623 
624     // If consumer no longer tracks this graphicBuffer, we can safely
625     // drop this fence, as it will never be received by the producer.
626     if (!stillTracking(slot, graphicBuffer)) {
627         return OK;
628     }
629 
630     if (!mSlots[slot].mFence.get()) {
631         mSlots[slot].mFence = fence;
632         return OK;
633     }
634 
635     // Check status of fences first because merging is expensive.
636     // Merging an invalid fence with any other fence results in an
637     // invalid fence.
638     auto currentStatus = mSlots[slot].mFence->getStatus();
639     if (currentStatus == Fence::Status::Invalid) {
640         CB_LOGE("Existing fence has invalid state");
641         return BAD_VALUE;
642     }
643 
644     auto incomingStatus = fence->getStatus();
645     if (incomingStatus == Fence::Status::Invalid) {
646         CB_LOGE("New fence has invalid state");
647         mSlots[slot].mFence = fence;
648         return BAD_VALUE;
649     }
650 
651     // If both fences are signaled or both are unsignaled, we need to merge
652     // them to get an accurate timestamp.
653     if (currentStatus == incomingStatus) {
654         char fenceName[32] = {};
655         snprintf(fenceName, 32, "%.28s:%d", mName.c_str(), slot);
656         sp<Fence> mergedFence = Fence::merge(
657                 fenceName, mSlots[slot].mFence, fence);
658         if (!mergedFence.get()) {
659             CB_LOGE("failed to merge release fences");
660             // synchronization is broken, the best we can do is hope fences
661             // signal in order so the new fence will act like a union
662             mSlots[slot].mFence = fence;
663             return BAD_VALUE;
664         }
665         mSlots[slot].mFence = mergedFence;
666     } else if (incomingStatus == Fence::Status::Unsignaled) {
667         // If one fence has signaled and the other hasn't, the unsignaled
668         // fence will approximately correspond with the correct timestamp.
669         // There's a small race if both fences signal at about the same time
670         // and their statuses are retrieved with unfortunate timing. However,
671         // by this point, they will have both signaled and only the timestamp
672         // will be slightly off; any dependencies after this point will
673         // already have been met.
674         mSlots[slot].mFence = fence;
675     }
676     // else if (currentStatus == Fence::Status::Unsignaled) is a no-op.
677 
678     return OK;
679 }
680 
681 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
682 status_t ConsumerBase::releaseBufferLocked(int slot, const sp<GraphicBuffer> graphicBuffer) {
683 #else
684 status_t ConsumerBase::releaseBufferLocked(
685         int slot, const sp<GraphicBuffer> graphicBuffer,
686         EGLDisplay display, EGLSyncKHR eglFence) {
687 #endif
688     if (mAbandoned) {
689         CB_LOGE("releaseBufferLocked: ConsumerBase is abandoned!");
690         return NO_INIT;
691     }
692     // If consumer no longer tracks this graphicBuffer (we received a new
693     // buffer on the same slot), the buffer producer is definitely no longer
694     // tracking it.
695     if (!stillTracking(slot, graphicBuffer)) {
696         CB_LOGV("releaseBufferLocked: Not tracking, exiting without calling releaseBuffer for "
697                 "slot=%d/%" PRIu64,
698                 slot, mSlots[slot].mFrameNumber);
699         return OK;
700     }
701 
702     CB_LOGV("releaseBufferLocked: slot=%d/%" PRIu64,
703             slot, mSlots[slot].mFrameNumber);
704 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
705     status_t err = mConsumer->releaseBuffer(slot, mSlots[slot].mFrameNumber, mSlots[slot].mFence);
706 #else
707     status_t err = mConsumer->releaseBuffer(slot, mSlots[slot].mFrameNumber,
708             display, eglFence, mSlots[slot].mFence);
709 #endif
710     if (err == IGraphicBufferConsumer::STALE_BUFFER_SLOT) {
711         freeBufferLocked(slot);
712     }
713 
714     mPrevFinalReleaseFence = mSlots[slot].mFence;
715     mSlots[slot].mFence = Fence::NO_FENCE;
716 
717     return err;
718 }
719 
720 bool ConsumerBase::stillTracking(int slot,
721         const sp<GraphicBuffer> graphicBuffer) {
722 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
723     if (slot < 0 || slot >= (int)mSlots.size()) {
724 #else
725     if (slot < 0 || slot >= BufferQueue::NUM_BUFFER_SLOTS) {
726 #endif
727         return false;
728     }
729     return (mSlots[slot].mGraphicBuffer != nullptr &&
730             mSlots[slot].mGraphicBuffer->handle == graphicBuffer->handle);
731 }
732 
733 } // namespace android
734