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