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