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