1 /*
2  * Copyright 2014 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 "BufferQueueCore"
18 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
19 //#define LOG_NDEBUG 0
20 
21 #define EGL_EGLEXT_PROTOTYPES
22 
23 #if DEBUG_ONLY_CODE
24 #define VALIDATE_CONSISTENCY() do { validateConsistencyLocked(); } while (0)
25 #else
26 #define VALIDATE_CONSISTENCY()
27 #endif
28 
29 #include <inttypes.h>
30 
31 #include <cutils/atomic.h>
32 
33 #include <gui/BufferItem.h>
34 #include <gui/BufferQueueCore.h>
35 #include <gui/IConsumerListener.h>
36 #include <gui/IProducerListener.h>
37 #include <gui/ISurfaceComposer.h>
38 #include <private/gui/ComposerService.h>
39 
40 #include <system/window.h>
41 
42 namespace android {
43 
44 // Macros for include BufferQueueCore information in log messages
45 #define BQ_LOGV(x, ...)                                                                           \
46     ALOGV("[%s](id:%" PRIx64 ",api:%d,p:%d,c:%" PRIu64 ") " x, mConsumerName.string(), mUniqueId, \
47           mConnectedApi, mConnectedPid, mUniqueId >> 32, ##__VA_ARGS__)
48 #define BQ_LOGD(x, ...)                                                                           \
49     ALOGD("[%s](id:%" PRIx64 ",api:%d,p:%d,c:%" PRIu64 ") " x, mConsumerName.string(), mUniqueId, \
50           mConnectedApi, mConnectedPid, mUniqueId >> 32, ##__VA_ARGS__)
51 #define BQ_LOGI(x, ...)                                                                           \
52     ALOGI("[%s](id:%" PRIx64 ",api:%d,p:%d,c:%" PRIu64 ") " x, mConsumerName.string(), mUniqueId, \
53           mConnectedApi, mConnectedPid, mUniqueId >> 32, ##__VA_ARGS__)
54 #define BQ_LOGW(x, ...)                                                                           \
55     ALOGW("[%s](id:%" PRIx64 ",api:%d,p:%d,c:%" PRIu64 ") " x, mConsumerName.string(), mUniqueId, \
56           mConnectedApi, mConnectedPid, mUniqueId >> 32, ##__VA_ARGS__)
57 #define BQ_LOGE(x, ...)                                                                           \
58     ALOGE("[%s](id:%" PRIx64 ",api:%d,p:%d,c:%" PRIu64 ") " x, mConsumerName.string(), mUniqueId, \
59           mConnectedApi, mConnectedPid, mUniqueId >> 32, ##__VA_ARGS__)
60 
getUniqueName()61 static String8 getUniqueName() {
62     static volatile int32_t counter = 0;
63     return String8::format("unnamed-%d-%d", getpid(),
64             android_atomic_inc(&counter));
65 }
66 
getUniqueId()67 static uint64_t getUniqueId() {
68     static std::atomic<uint32_t> counter{0};
69     static uint64_t id = static_cast<uint64_t>(getpid()) << 32;
70     return id | counter++;
71 }
72 
getProcessName(int pid,String8 & name)73 static status_t getProcessName(int pid, String8& name) {
74     FILE* fp = fopen(String8::format("/proc/%d/cmdline", pid), "r");
75     if (NULL != fp) {
76         const size_t size = 64;
77         char proc_name[size];
78         char* result = fgets(proc_name, size, fp);
79         fclose(fp);
80         if (result != nullptr) {
81             name = proc_name;
82             return NO_ERROR;
83         }
84     }
85     return INVALID_OPERATION;
86 }
87 
BufferQueueCore()88 BufferQueueCore::BufferQueueCore()
89       : mMutex(),
90         mIsAbandoned(false),
91         mConsumerControlledByApp(false),
92         mConsumerName(getUniqueName()),
93         mConsumerListener(),
94         mConsumerUsageBits(0),
95         mConsumerIsProtected(false),
96         mConnectedApi(NO_CONNECTED_API),
97         mLinkedToDeath(),
98         mConnectedProducerListener(),
99         mBufferReleasedCbEnabled(false),
100         mSlots(),
101         mQueue(),
102         mFreeSlots(),
103         mFreeBuffers(),
104         mUnusedSlots(),
105         mActiveBuffers(),
106         mDequeueCondition(),
107         mDequeueBufferCannotBlock(false),
108         mQueueBufferCanDrop(false),
109         mLegacyBufferDrop(true),
110         mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888),
111         mDefaultWidth(1),
112         mDefaultHeight(1),
113         mDefaultBufferDataSpace(HAL_DATASPACE_UNKNOWN),
114         mMaxBufferCount(BufferQueueDefs::NUM_BUFFER_SLOTS),
115         mMaxAcquiredBufferCount(1),
116         mMaxDequeuedBufferCount(1),
117         mBufferHasBeenQueued(false),
118         mFrameCounter(0),
119         mTransformHint(0),
120         mIsAllocating(false),
121         mIsAllocatingCondition(),
122         mAllowAllocation(true),
123         mBufferAge(0),
124         mGenerationNumber(0),
125         mAsyncMode(false),
126         mSharedBufferMode(false),
127         mAutoRefresh(false),
128         mSharedBufferSlot(INVALID_BUFFER_SLOT),
129         mSharedBufferCache(Rect::INVALID_RECT, 0, NATIVE_WINDOW_SCALING_MODE_FREEZE,
130                            HAL_DATASPACE_UNKNOWN),
131         mLastQueuedSlot(INVALID_BUFFER_SLOT),
132         mUniqueId(getUniqueId()),
133         mAutoPrerotation(false),
134         mTransformHintInUse(0) {
135     int numStartingBuffers = getMaxBufferCountLocked();
136     for (int s = 0; s < numStartingBuffers; s++) {
137         mFreeSlots.insert(s);
138     }
139     for (int s = numStartingBuffers; s < BufferQueueDefs::NUM_BUFFER_SLOTS;
140             s++) {
141         mUnusedSlots.push_front(s);
142     }
143 }
144 
~BufferQueueCore()145 BufferQueueCore::~BufferQueueCore() {}
146 
dumpState(const String8 & prefix,String8 * outResult) const147 void BufferQueueCore::dumpState(const String8& prefix, String8* outResult) const {
148     std::lock_guard<std::mutex> lock(mMutex);
149 
150     outResult->appendFormat("%s- BufferQueue ", prefix.string());
151     outResult->appendFormat("mMaxAcquiredBufferCount=%d mMaxDequeuedBufferCount=%d\n",
152                             mMaxAcquiredBufferCount, mMaxDequeuedBufferCount);
153     outResult->appendFormat("%s  mDequeueBufferCannotBlock=%d mAsyncMode=%d\n", prefix.string(),
154                             mDequeueBufferCannotBlock, mAsyncMode);
155     outResult->appendFormat("%s  mQueueBufferCanDrop=%d mLegacyBufferDrop=%d\n", prefix.string(),
156                             mQueueBufferCanDrop, mLegacyBufferDrop);
157     outResult->appendFormat("%s  default-size=[%dx%d] default-format=%d ", prefix.string(),
158                             mDefaultWidth, mDefaultHeight, mDefaultBufferFormat);
159     outResult->appendFormat("%s  transform-hint=%02x frame-counter=%" PRIu64 "\n", prefix.string(),
160                             mTransformHint, mFrameCounter);
161     outResult->appendFormat("%s  mTransformHintInUse=%02x mAutoPrerotation=%d\n", prefix.string(),
162                             mTransformHintInUse, mAutoPrerotation);
163 
164     outResult->appendFormat("%sFIFO(%zu):\n", prefix.string(), mQueue.size());
165 
166     outResult->appendFormat("%s(mConsumerName=%s, ", prefix.string(), mConsumerName.string());
167 
168     outResult->appendFormat("mConnectedApi=%d, mConsumerUsageBits=%" PRIu64 ", ", mConnectedApi,
169                             mConsumerUsageBits);
170 
171     String8 producerProcName = String8("\?\?\?");
172     String8 consumerProcName = String8("\?\?\?");
173     int32_t pid = getpid();
174     getProcessName(mConnectedPid, producerProcName);
175     getProcessName(pid, consumerProcName);
176     outResult->appendFormat("mId=%" PRIx64 ", producer=[%d:%s], consumer=[%d:%s])\n", mUniqueId,
177                             mConnectedPid, producerProcName.string(), pid,
178                             consumerProcName.string());
179     Fifo::const_iterator current(mQueue.begin());
180     while (current != mQueue.end()) {
181         double timestamp = current->mTimestamp / 1e9;
182         outResult->appendFormat("%s  %02d:%p ", prefix.string(), current->mSlot,
183                                 current->mGraphicBuffer.get());
184         outResult->appendFormat("crop=[%d,%d,%d,%d] ", current->mCrop.left, current->mCrop.top,
185                                 current->mCrop.right, current->mCrop.bottom);
186         outResult->appendFormat("xform=0x%02x time=%.4f scale=%s\n", current->mTransform, timestamp,
187                                 BufferItem::scalingModeName(current->mScalingMode));
188         ++current;
189     }
190 
191     outResult->appendFormat("%sSlots:\n", prefix.string());
192     for (int s : mActiveBuffers) {
193         const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer);
194         // A dequeued buffer might be null if it's still being allocated
195         if (buffer.get()) {
196             outResult->appendFormat("%s %s[%02d:%p] ", prefix.string(),
197                                     (mSlots[s].mBufferState.isAcquired()) ? ">" : " ", s,
198                                     buffer.get());
199             outResult->appendFormat("state=%-8s %p frame=%" PRIu64, mSlots[s].mBufferState.string(),
200                                     buffer->handle, mSlots[s].mFrameNumber);
201             outResult->appendFormat(" [%4ux%4u:%4u,%3X]\n", buffer->width, buffer->height,
202                                     buffer->stride, buffer->format);
203         } else {
204             outResult->appendFormat("%s  [%02d:%p] ", prefix.string(), s, buffer.get());
205             outResult->appendFormat("state=%-8s frame=%" PRIu64 "\n",
206                                     mSlots[s].mBufferState.string(), mSlots[s].mFrameNumber);
207         }
208     }
209     for (int s : mFreeBuffers) {
210         const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer);
211         outResult->appendFormat("%s  [%02d:%p] ", prefix.string(), s, buffer.get());
212         outResult->appendFormat("state=%-8s %p frame=%" PRIu64, mSlots[s].mBufferState.string(),
213                                 buffer->handle, mSlots[s].mFrameNumber);
214         outResult->appendFormat(" [%4ux%4u:%4u,%3X]\n", buffer->width, buffer->height,
215                                 buffer->stride, buffer->format);
216     }
217 
218     for (int s : mFreeSlots) {
219         const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer);
220         outResult->appendFormat("%s  [%02d:%p] state=%-8s\n", prefix.string(), s, buffer.get(),
221                                 mSlots[s].mBufferState.string());
222     }
223 }
224 
getMinUndequeuedBufferCountLocked() const225 int BufferQueueCore::getMinUndequeuedBufferCountLocked() const {
226     // If dequeueBuffer is allowed to error out, we don't have to add an
227     // extra buffer.
228     if (mAsyncMode || mDequeueBufferCannotBlock) {
229         return mMaxAcquiredBufferCount + 1;
230     }
231 
232     return mMaxAcquiredBufferCount;
233 }
234 
getMinMaxBufferCountLocked() const235 int BufferQueueCore::getMinMaxBufferCountLocked() const {
236     return getMinUndequeuedBufferCountLocked() + 1;
237 }
238 
getMaxBufferCountLocked(bool asyncMode,bool dequeueBufferCannotBlock,int maxBufferCount) const239 int BufferQueueCore::getMaxBufferCountLocked(bool asyncMode,
240         bool dequeueBufferCannotBlock, int maxBufferCount) const {
241     int maxCount = mMaxAcquiredBufferCount + mMaxDequeuedBufferCount +
242             ((asyncMode || dequeueBufferCannotBlock) ? 1 : 0);
243     maxCount = std::min(maxBufferCount, maxCount);
244     return maxCount;
245 }
246 
getMaxBufferCountLocked() const247 int BufferQueueCore::getMaxBufferCountLocked() const {
248     int maxBufferCount = mMaxAcquiredBufferCount + mMaxDequeuedBufferCount +
249             ((mAsyncMode || mDequeueBufferCannotBlock) ? 1 : 0);
250 
251     // limit maxBufferCount by mMaxBufferCount always
252     maxBufferCount = std::min(mMaxBufferCount, maxBufferCount);
253 
254     return maxBufferCount;
255 }
256 
clearBufferSlotLocked(int slot)257 void BufferQueueCore::clearBufferSlotLocked(int slot) {
258     BQ_LOGV("clearBufferSlotLocked: slot %d", slot);
259 
260     mSlots[slot].mGraphicBuffer.clear();
261     mSlots[slot].mBufferState.reset();
262     mSlots[slot].mRequestBufferCalled = false;
263     mSlots[slot].mFrameNumber = 0;
264     mSlots[slot].mAcquireCalled = false;
265     mSlots[slot].mNeedsReallocation = true;
266 
267     // Destroy fence as BufferQueue now takes ownership
268     if (mSlots[slot].mEglFence != EGL_NO_SYNC_KHR) {
269         eglDestroySyncKHR(mSlots[slot].mEglDisplay, mSlots[slot].mEglFence);
270         mSlots[slot].mEglFence = EGL_NO_SYNC_KHR;
271     }
272     mSlots[slot].mFence = Fence::NO_FENCE;
273     mSlots[slot].mEglDisplay = EGL_NO_DISPLAY;
274 
275     if (mLastQueuedSlot == slot) {
276         mLastQueuedSlot = INVALID_BUFFER_SLOT;
277     }
278 }
279 
freeAllBuffersLocked()280 void BufferQueueCore::freeAllBuffersLocked() {
281     for (int s : mFreeSlots) {
282         clearBufferSlotLocked(s);
283     }
284 
285     for (int s : mFreeBuffers) {
286         mFreeSlots.insert(s);
287         clearBufferSlotLocked(s);
288     }
289     mFreeBuffers.clear();
290 
291     for (int s : mActiveBuffers) {
292         mFreeSlots.insert(s);
293         clearBufferSlotLocked(s);
294     }
295     mActiveBuffers.clear();
296 
297     for (auto& b : mQueue) {
298         b.mIsStale = true;
299 
300         // We set this to false to force the BufferQueue to resend the buffer
301         // handle upon acquire, since if we're here due to a producer
302         // disconnect, the consumer will have been told to purge its cache of
303         // slot-to-buffer-handle mappings and will not be able to otherwise
304         // obtain a valid buffer handle.
305         b.mAcquireCalled = false;
306     }
307 
308     VALIDATE_CONSISTENCY();
309 }
310 
discardFreeBuffersLocked()311 void BufferQueueCore::discardFreeBuffersLocked() {
312     // Notify producer about the discarded buffers.
313     if (mConnectedProducerListener != nullptr && mFreeBuffers.size() > 0) {
314         std::vector<int32_t> freeBuffers(mFreeBuffers.begin(), mFreeBuffers.end());
315         mConnectedProducerListener->onBuffersDiscarded(freeBuffers);
316     }
317 
318     for (int s : mFreeBuffers) {
319         mFreeSlots.insert(s);
320         clearBufferSlotLocked(s);
321     }
322     mFreeBuffers.clear();
323 
324     VALIDATE_CONSISTENCY();
325 }
326 
adjustAvailableSlotsLocked(int delta)327 bool BufferQueueCore::adjustAvailableSlotsLocked(int delta) {
328     if (delta >= 0) {
329         // If we're going to fail, do so before modifying anything
330         if (delta > static_cast<int>(mUnusedSlots.size())) {
331             return false;
332         }
333         while (delta > 0) {
334             if (mUnusedSlots.empty()) {
335                 return false;
336             }
337             int slot = mUnusedSlots.back();
338             mUnusedSlots.pop_back();
339             mFreeSlots.insert(slot);
340             delta--;
341         }
342     } else {
343         // If we're going to fail, do so before modifying anything
344         if (-delta > static_cast<int>(mFreeSlots.size() +
345                 mFreeBuffers.size())) {
346             return false;
347         }
348         while (delta < 0) {
349             if (!mFreeSlots.empty()) {
350                 auto slot = mFreeSlots.begin();
351                 clearBufferSlotLocked(*slot);
352                 mUnusedSlots.push_back(*slot);
353                 mFreeSlots.erase(slot);
354             } else if (!mFreeBuffers.empty()) {
355                 int slot = mFreeBuffers.back();
356                 clearBufferSlotLocked(slot);
357                 mUnusedSlots.push_back(slot);
358                 mFreeBuffers.pop_back();
359             } else {
360                 return false;
361             }
362             delta++;
363         }
364     }
365     return true;
366 }
367 
waitWhileAllocatingLocked(std::unique_lock<std::mutex> & lock) const368 void BufferQueueCore::waitWhileAllocatingLocked(std::unique_lock<std::mutex>& lock) const {
369     ATRACE_CALL();
370     while (mIsAllocating) {
371         mIsAllocatingCondition.wait(lock);
372     }
373 }
374 
375 #if DEBUG_ONLY_CODE
validateConsistencyLocked() const376 void BufferQueueCore::validateConsistencyLocked() const {
377     static const useconds_t PAUSE_TIME = 0;
378     int allocatedSlots = 0;
379     for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) {
380         bool isInFreeSlots = mFreeSlots.count(slot) != 0;
381         bool isInFreeBuffers =
382                 std::find(mFreeBuffers.cbegin(), mFreeBuffers.cend(), slot) !=
383                 mFreeBuffers.cend();
384         bool isInActiveBuffers = mActiveBuffers.count(slot) != 0;
385         bool isInUnusedSlots =
386                 std::find(mUnusedSlots.cbegin(), mUnusedSlots.cend(), slot) !=
387                 mUnusedSlots.cend();
388 
389         if (isInFreeSlots || isInFreeBuffers || isInActiveBuffers) {
390             allocatedSlots++;
391         }
392 
393         if (isInUnusedSlots) {
394             if (isInFreeSlots) {
395                 BQ_LOGE("Slot %d is in mUnusedSlots and in mFreeSlots", slot);
396                 usleep(PAUSE_TIME);
397             }
398             if (isInFreeBuffers) {
399                 BQ_LOGE("Slot %d is in mUnusedSlots and in mFreeBuffers", slot);
400                 usleep(PAUSE_TIME);
401             }
402             if (isInActiveBuffers) {
403                 BQ_LOGE("Slot %d is in mUnusedSlots and in mActiveBuffers",
404                         slot);
405                 usleep(PAUSE_TIME);
406             }
407             if (!mSlots[slot].mBufferState.isFree()) {
408                 BQ_LOGE("Slot %d is in mUnusedSlots but is not FREE", slot);
409                 usleep(PAUSE_TIME);
410             }
411             if (mSlots[slot].mGraphicBuffer != nullptr) {
412                 BQ_LOGE("Slot %d is in mUnusedSluts but has an active buffer",
413                         slot);
414                 usleep(PAUSE_TIME);
415             }
416         } else if (isInFreeSlots) {
417             if (isInUnusedSlots) {
418                 BQ_LOGE("Slot %d is in mFreeSlots and in mUnusedSlots", slot);
419                 usleep(PAUSE_TIME);
420             }
421             if (isInFreeBuffers) {
422                 BQ_LOGE("Slot %d is in mFreeSlots and in mFreeBuffers", slot);
423                 usleep(PAUSE_TIME);
424             }
425             if (isInActiveBuffers) {
426                 BQ_LOGE("Slot %d is in mFreeSlots and in mActiveBuffers", slot);
427                 usleep(PAUSE_TIME);
428             }
429             if (!mSlots[slot].mBufferState.isFree()) {
430                 BQ_LOGE("Slot %d is in mFreeSlots but is not FREE", slot);
431                 usleep(PAUSE_TIME);
432             }
433             if (mSlots[slot].mGraphicBuffer != nullptr) {
434                 BQ_LOGE("Slot %d is in mFreeSlots but has a buffer",
435                         slot);
436                 usleep(PAUSE_TIME);
437             }
438         } else if (isInFreeBuffers) {
439             if (isInUnusedSlots) {
440                 BQ_LOGE("Slot %d is in mFreeBuffers and in mUnusedSlots", slot);
441                 usleep(PAUSE_TIME);
442             }
443             if (isInFreeSlots) {
444                 BQ_LOGE("Slot %d is in mFreeBuffers and in mFreeSlots", slot);
445                 usleep(PAUSE_TIME);
446             }
447             if (isInActiveBuffers) {
448                 BQ_LOGE("Slot %d is in mFreeBuffers and in mActiveBuffers",
449                         slot);
450                 usleep(PAUSE_TIME);
451             }
452             if (!mSlots[slot].mBufferState.isFree()) {
453                 BQ_LOGE("Slot %d is in mFreeBuffers but is not FREE", slot);
454                 usleep(PAUSE_TIME);
455             }
456             if (mSlots[slot].mGraphicBuffer == nullptr) {
457                 BQ_LOGE("Slot %d is in mFreeBuffers but has no buffer", slot);
458                 usleep(PAUSE_TIME);
459             }
460         } else if (isInActiveBuffers) {
461             if (isInUnusedSlots) {
462                 BQ_LOGE("Slot %d is in mActiveBuffers and in mUnusedSlots",
463                         slot);
464                 usleep(PAUSE_TIME);
465             }
466             if (isInFreeSlots) {
467                 BQ_LOGE("Slot %d is in mActiveBuffers and in mFreeSlots", slot);
468                 usleep(PAUSE_TIME);
469             }
470             if (isInFreeBuffers) {
471                 BQ_LOGE("Slot %d is in mActiveBuffers and in mFreeBuffers",
472                         slot);
473                 usleep(PAUSE_TIME);
474             }
475             if (mSlots[slot].mBufferState.isFree() &&
476                     !mSlots[slot].mBufferState.isShared()) {
477                 BQ_LOGE("Slot %d is in mActiveBuffers but is FREE", slot);
478                 usleep(PAUSE_TIME);
479             }
480             if (mSlots[slot].mGraphicBuffer == nullptr && !mIsAllocating) {
481                 BQ_LOGE("Slot %d is in mActiveBuffers but has no buffer", slot);
482                 usleep(PAUSE_TIME);
483             }
484         } else {
485             BQ_LOGE("Slot %d isn't in any of mUnusedSlots, mFreeSlots, "
486                     "mFreeBuffers, or mActiveBuffers", slot);
487             usleep(PAUSE_TIME);
488         }
489     }
490 
491     if (allocatedSlots != getMaxBufferCountLocked()) {
492         BQ_LOGE("Number of allocated slots is incorrect. Allocated = %d, "
493                 "Should be %d (%zu free slots, %zu free buffers, "
494                 "%zu activeBuffers, %zu unusedSlots)", allocatedSlots,
495                 getMaxBufferCountLocked(), mFreeSlots.size(),
496                 mFreeBuffers.size(), mActiveBuffers.size(),
497                 mUnusedSlots.size());
498     }
499 }
500 #endif
501 
502 } // namespace android
503