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