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