OSDN Git Service

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