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