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