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