• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <inttypes.h>
18 
19 #define LOG_TAG "BufferQueueProducer"
20 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
21 //#define LOG_NDEBUG 0
22 
23 #define EGL_EGLEXT_PROTOTYPES
24 
25 #include <gui/BufferItem.h>
26 #include <gui/BufferQueueCore.h>
27 #include <gui/BufferQueueProducer.h>
28 #include <gui/IConsumerListener.h>
29 #include <gui/IGraphicBufferAlloc.h>
30 #include <gui/IProducerListener.h>
31 
32 #include <utils/Log.h>
33 #include <utils/Trace.h>
34 
35 namespace android {
36 
BufferQueueProducer(const sp<BufferQueueCore> & core)37 BufferQueueProducer::BufferQueueProducer(const sp<BufferQueueCore>& core) :
38     mCore(core),
39     mSlots(core->mSlots),
40     mConsumerName(),
41     mStickyTransform(0) {}
42 
~BufferQueueProducer()43 BufferQueueProducer::~BufferQueueProducer() {}
44 
requestBuffer(int slot,sp<GraphicBuffer> * buf)45 status_t BufferQueueProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
46     ATRACE_CALL();
47     BQ_LOGV("requestBuffer: slot %d", slot);
48     Mutex::Autolock lock(mCore->mMutex);
49 
50     if (mCore->mIsAbandoned) {
51         BQ_LOGE("requestBuffer: BufferQueue has been abandoned");
52         return NO_INIT;
53     }
54 
55     if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
56         BQ_LOGE("requestBuffer: slot index %d out of range [0, %d)",
57                 slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
58         return BAD_VALUE;
59     } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
60         BQ_LOGE("requestBuffer: slot %d is not owned by the producer "
61                 "(state = %d)", slot, mSlots[slot].mBufferState);
62         return BAD_VALUE;
63     }
64 
65     mSlots[slot].mRequestBufferCalled = true;
66     *buf = mSlots[slot].mGraphicBuffer;
67     return NO_ERROR;
68 }
69 
setBufferCount(int bufferCount)70 status_t BufferQueueProducer::setBufferCount(int bufferCount) {
71     ATRACE_CALL();
72     BQ_LOGV("setBufferCount: count = %d", bufferCount);
73 
74     sp<IConsumerListener> listener;
75     { // Autolock scope
76         Mutex::Autolock lock(mCore->mMutex);
77         mCore->waitWhileAllocatingLocked();
78 
79         if (mCore->mIsAbandoned) {
80             BQ_LOGE("setBufferCount: BufferQueue has been abandoned");
81             return NO_INIT;
82         }
83 
84         if (bufferCount > BufferQueueDefs::NUM_BUFFER_SLOTS) {
85             BQ_LOGE("setBufferCount: bufferCount %d too large (max %d)",
86                     bufferCount, BufferQueueDefs::NUM_BUFFER_SLOTS);
87             return BAD_VALUE;
88         }
89 
90         // There must be no dequeued buffers when changing the buffer count.
91         for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
92             if (mSlots[s].mBufferState == BufferSlot::DEQUEUED) {
93                 BQ_LOGE("setBufferCount: buffer owned by producer");
94                 return BAD_VALUE;
95             }
96         }
97 
98         if (bufferCount == 0) {
99             mCore->mOverrideMaxBufferCount = 0;
100             mCore->mDequeueCondition.broadcast();
101             return NO_ERROR;
102         }
103 
104         const int minBufferSlots = mCore->getMinMaxBufferCountLocked(false);
105         if (bufferCount < minBufferSlots) {
106             BQ_LOGE("setBufferCount: requested buffer count %d is less than "
107                     "minimum %d", bufferCount, minBufferSlots);
108             return BAD_VALUE;
109         }
110 
111         // Here we are guaranteed that the producer doesn't have any dequeued
112         // buffers and will release all of its buffer references. We don't
113         // clear the queue, however, so that currently queued buffers still
114         // get displayed.
115         mCore->freeAllBuffersLocked();
116         mCore->mOverrideMaxBufferCount = bufferCount;
117         mCore->mDequeueCondition.broadcast();
118         listener = mCore->mConsumerListener;
119     } // Autolock scope
120 
121     // Call back without lock held
122     if (listener != NULL) {
123         listener->onBuffersReleased();
124     }
125 
126     return NO_ERROR;
127 }
128 
waitForFreeSlotThenRelock(const char * caller,bool async,int * found,status_t * returnFlags) const129 status_t BufferQueueProducer::waitForFreeSlotThenRelock(const char* caller,
130         bool async, int* found, status_t* returnFlags) const {
131     bool tryAgain = true;
132     while (tryAgain) {
133         if (mCore->mIsAbandoned) {
134             BQ_LOGE("%s: BufferQueue has been abandoned", caller);
135             return NO_INIT;
136         }
137 
138         const int maxBufferCount = mCore->getMaxBufferCountLocked(async);
139         if (async && mCore->mOverrideMaxBufferCount) {
140             // FIXME: Some drivers are manually setting the buffer count
141             // (which they shouldn't), so we do this extra test here to
142             // handle that case. This is TEMPORARY until we get this fixed.
143             if (mCore->mOverrideMaxBufferCount < maxBufferCount) {
144                 BQ_LOGE("%s: async mode is invalid with buffer count override",
145                         caller);
146                 return BAD_VALUE;
147             }
148         }
149 
150         // Free up any buffers that are in slots beyond the max buffer count
151         for (int s = maxBufferCount; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
152             assert(mSlots[s].mBufferState == BufferSlot::FREE);
153             if (mSlots[s].mGraphicBuffer != NULL) {
154                 mCore->freeBufferLocked(s);
155                 *returnFlags |= RELEASE_ALL_BUFFERS;
156             }
157         }
158 
159         // Look for a free buffer to give to the client
160         *found = BufferQueueCore::INVALID_BUFFER_SLOT;
161         int dequeuedCount = 0;
162         int acquiredCount = 0;
163         for (int s = 0; s < maxBufferCount; ++s) {
164             switch (mSlots[s].mBufferState) {
165                 case BufferSlot::DEQUEUED:
166                     ++dequeuedCount;
167                     break;
168                 case BufferSlot::ACQUIRED:
169                     ++acquiredCount;
170                     break;
171                 case BufferSlot::FREE:
172                     // We return the oldest of the free buffers to avoid
173                     // stalling the producer if possible, since the consumer
174                     // may still have pending reads of in-flight buffers
175                     if (*found == BufferQueueCore::INVALID_BUFFER_SLOT ||
176                             mSlots[s].mFrameNumber < mSlots[*found].mFrameNumber) {
177                         *found = s;
178                     }
179                     break;
180                 default:
181                     break;
182             }
183         }
184 
185         // Producers are not allowed to dequeue more than one buffer if they
186         // did not set a buffer count
187         if (!mCore->mOverrideMaxBufferCount && dequeuedCount) {
188             BQ_LOGE("%s: can't dequeue multiple buffers without setting the "
189                     "buffer count", caller);
190             return INVALID_OPERATION;
191         }
192 
193         // See whether a buffer has been queued since the last
194         // setBufferCount so we know whether to perform the min undequeued
195         // buffers check below
196         if (mCore->mBufferHasBeenQueued) {
197             // Make sure the producer is not trying to dequeue more buffers
198             // than allowed
199             const int newUndequeuedCount =
200                 maxBufferCount - (dequeuedCount + 1);
201             const int minUndequeuedCount =
202                 mCore->getMinUndequeuedBufferCountLocked(async);
203             if (newUndequeuedCount < minUndequeuedCount) {
204                 BQ_LOGE("%s: min undequeued buffer count (%d) exceeded "
205                         "(dequeued=%d undequeued=%d)",
206                         caller, minUndequeuedCount,
207                         dequeuedCount, newUndequeuedCount);
208                 return INVALID_OPERATION;
209             }
210         }
211 
212         // If we disconnect and reconnect quickly, we can be in a state where
213         // our slots are empty but we have many buffers in the queue. This can
214         // cause us to run out of memory if we outrun the consumer. Wait here if
215         // it looks like we have too many buffers queued up.
216         bool tooManyBuffers = mCore->mQueue.size()
217                             > static_cast<size_t>(maxBufferCount);
218         if (tooManyBuffers) {
219             BQ_LOGV("%s: queue size is %zu, waiting", caller,
220                     mCore->mQueue.size());
221         }
222 
223         // If no buffer is found, or if the queue has too many buffers
224         // outstanding, wait for a buffer to be acquired or released, or for the
225         // max buffer count to change.
226         tryAgain = (*found == BufferQueueCore::INVALID_BUFFER_SLOT) ||
227                    tooManyBuffers;
228         if (tryAgain) {
229             // Return an error if we're in non-blocking mode (producer and
230             // consumer are controlled by the application).
231             // However, the consumer is allowed to briefly acquire an extra
232             // buffer (which could cause us to have to wait here), which is
233             // okay, since it is only used to implement an atomic acquire +
234             // release (e.g., in GLConsumer::updateTexImage())
235             if (mCore->mDequeueBufferCannotBlock &&
236                     (acquiredCount <= mCore->mMaxAcquiredBufferCount)) {
237                 return WOULD_BLOCK;
238             }
239             mCore->mDequeueCondition.wait(mCore->mMutex);
240         }
241     } // while (tryAgain)
242 
243     return NO_ERROR;
244 }
245 
dequeueBuffer(int * outSlot,sp<android::Fence> * outFence,bool async,uint32_t width,uint32_t height,uint32_t format,uint32_t usage)246 status_t BufferQueueProducer::dequeueBuffer(int *outSlot,
247         sp<android::Fence> *outFence, bool async,
248         uint32_t width, uint32_t height, uint32_t format, uint32_t usage) {
249     ATRACE_CALL();
250     { // Autolock scope
251         Mutex::Autolock lock(mCore->mMutex);
252         mConsumerName = mCore->mConsumerName;
253     } // Autolock scope
254 
255     BQ_LOGV("dequeueBuffer: async=%s w=%u h=%u format=%#x, usage=%#x",
256             async ? "true" : "false", width, height, format, usage);
257 
258     if ((width && !height) || (!width && height)) {
259         BQ_LOGE("dequeueBuffer: invalid size: w=%u h=%u", width, height);
260         return BAD_VALUE;
261     }
262 
263     status_t returnFlags = NO_ERROR;
264     EGLDisplay eglDisplay = EGL_NO_DISPLAY;
265     EGLSyncKHR eglFence = EGL_NO_SYNC_KHR;
266     bool attachedByConsumer = false;
267 
268     { // Autolock scope
269         Mutex::Autolock lock(mCore->mMutex);
270         mCore->waitWhileAllocatingLocked();
271 
272         if (format == 0) {
273             format = mCore->mDefaultBufferFormat;
274         }
275 
276         // Enable the usage bits the consumer requested
277         usage |= mCore->mConsumerUsageBits;
278 
279         int found;
280         status_t status = waitForFreeSlotThenRelock("dequeueBuffer", async,
281                 &found, &returnFlags);
282         if (status != NO_ERROR) {
283             return status;
284         }
285 
286         // This should not happen
287         if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
288             BQ_LOGE("dequeueBuffer: no available buffer slots");
289             return -EBUSY;
290         }
291 
292         *outSlot = found;
293         ATRACE_BUFFER_INDEX(found);
294 
295         attachedByConsumer = mSlots[found].mAttachedByConsumer;
296 
297         const bool useDefaultSize = !width && !height;
298         if (useDefaultSize) {
299             width = mCore->mDefaultWidth;
300             height = mCore->mDefaultHeight;
301         }
302 
303         mSlots[found].mBufferState = BufferSlot::DEQUEUED;
304 
305         const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
306         if ((buffer == NULL) ||
307                 (static_cast<uint32_t>(buffer->width) != width) ||
308                 (static_cast<uint32_t>(buffer->height) != height) ||
309                 (static_cast<uint32_t>(buffer->format) != format) ||
310                 ((static_cast<uint32_t>(buffer->usage) & usage) != usage))
311         {
312             mSlots[found].mAcquireCalled = false;
313             mSlots[found].mGraphicBuffer = NULL;
314             mSlots[found].mRequestBufferCalled = false;
315             mSlots[found].mEglDisplay = EGL_NO_DISPLAY;
316             mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
317             mSlots[found].mFence = Fence::NO_FENCE;
318 
319             returnFlags |= BUFFER_NEEDS_REALLOCATION;
320         }
321 
322         if (CC_UNLIKELY(mSlots[found].mFence == NULL)) {
323             BQ_LOGE("dequeueBuffer: about to return a NULL fence - "
324                     "slot=%d w=%d h=%d format=%u",
325                     found, buffer->width, buffer->height, buffer->format);
326         }
327 
328         eglDisplay = mSlots[found].mEglDisplay;
329         eglFence = mSlots[found].mEglFence;
330         *outFence = mSlots[found].mFence;
331         mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
332         mSlots[found].mFence = Fence::NO_FENCE;
333     } // Autolock scope
334 
335     if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
336         status_t error;
337         BQ_LOGV("dequeueBuffer: allocating a new buffer for slot %d", *outSlot);
338         sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
339                     width, height, format, usage, &error));
340         if (graphicBuffer == NULL) {
341             BQ_LOGE("dequeueBuffer: createGraphicBuffer failed");
342             return error;
343         }
344 
345         { // Autolock scope
346             Mutex::Autolock lock(mCore->mMutex);
347 
348             if (mCore->mIsAbandoned) {
349                 BQ_LOGE("dequeueBuffer: BufferQueue has been abandoned");
350                 return NO_INIT;
351             }
352 
353             mSlots[*outSlot].mFrameNumber = UINT32_MAX;
354             mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
355         } // Autolock scope
356     }
357 
358     if (attachedByConsumer) {
359         returnFlags |= BUFFER_NEEDS_REALLOCATION;
360     }
361 
362     if (eglFence != EGL_NO_SYNC_KHR) {
363         EGLint result = eglClientWaitSyncKHR(eglDisplay, eglFence, 0,
364                 1000000000);
365         // If something goes wrong, log the error, but return the buffer without
366         // synchronizing access to it. It's too late at this point to abort the
367         // dequeue operation.
368         if (result == EGL_FALSE) {
369             BQ_LOGE("dequeueBuffer: error %#x waiting for fence",
370                     eglGetError());
371         } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
372             BQ_LOGE("dequeueBuffer: timeout waiting for fence");
373         }
374         eglDestroySyncKHR(eglDisplay, eglFence);
375     }
376 
377     BQ_LOGV("dequeueBuffer: returning slot=%d/%" PRIu64 " buf=%p flags=%#x",
378             *outSlot,
379             mSlots[*outSlot].mFrameNumber,
380             mSlots[*outSlot].mGraphicBuffer->handle, returnFlags);
381 
382     return returnFlags;
383 }
384 
detachBuffer(int slot)385 status_t BufferQueueProducer::detachBuffer(int slot) {
386     ATRACE_CALL();
387     ATRACE_BUFFER_INDEX(slot);
388     BQ_LOGV("detachBuffer(P): slot %d", slot);
389     Mutex::Autolock lock(mCore->mMutex);
390 
391     if (mCore->mIsAbandoned) {
392         BQ_LOGE("detachBuffer(P): BufferQueue has been abandoned");
393         return NO_INIT;
394     }
395 
396     if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
397         BQ_LOGE("detachBuffer(P): slot index %d out of range [0, %d)",
398                 slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
399         return BAD_VALUE;
400     } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
401         BQ_LOGE("detachBuffer(P): slot %d is not owned by the producer "
402                 "(state = %d)", slot, mSlots[slot].mBufferState);
403         return BAD_VALUE;
404     } else if (!mSlots[slot].mRequestBufferCalled) {
405         BQ_LOGE("detachBuffer(P): buffer in slot %d has not been requested",
406                 slot);
407         return BAD_VALUE;
408     }
409 
410     mCore->freeBufferLocked(slot);
411     mCore->mDequeueCondition.broadcast();
412 
413     return NO_ERROR;
414 }
415 
detachNextBuffer(sp<GraphicBuffer> * outBuffer,sp<Fence> * outFence)416 status_t BufferQueueProducer::detachNextBuffer(sp<GraphicBuffer>* outBuffer,
417         sp<Fence>* outFence) {
418     ATRACE_CALL();
419 
420     if (outBuffer == NULL) {
421         BQ_LOGE("detachNextBuffer: outBuffer must not be NULL");
422         return BAD_VALUE;
423     } else if (outFence == NULL) {
424         BQ_LOGE("detachNextBuffer: outFence must not be NULL");
425         return BAD_VALUE;
426     }
427 
428     Mutex::Autolock lock(mCore->mMutex);
429     mCore->waitWhileAllocatingLocked();
430 
431     if (mCore->mIsAbandoned) {
432         BQ_LOGE("detachNextBuffer: BufferQueue has been abandoned");
433         return NO_INIT;
434     }
435 
436     // Find the oldest valid slot
437     int found = BufferQueueCore::INVALID_BUFFER_SLOT;
438     for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
439         if (mSlots[s].mBufferState == BufferSlot::FREE &&
440                 mSlots[s].mGraphicBuffer != NULL) {
441             if (found == BufferQueueCore::INVALID_BUFFER_SLOT ||
442                     mSlots[s].mFrameNumber < mSlots[found].mFrameNumber) {
443                 found = s;
444             }
445         }
446     }
447 
448     if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
449         return NO_MEMORY;
450     }
451 
452     BQ_LOGV("detachNextBuffer detached slot %d", found);
453 
454     *outBuffer = mSlots[found].mGraphicBuffer;
455     *outFence = mSlots[found].mFence;
456     mCore->freeBufferLocked(found);
457 
458     return NO_ERROR;
459 }
460 
attachBuffer(int * outSlot,const sp<android::GraphicBuffer> & buffer)461 status_t BufferQueueProducer::attachBuffer(int* outSlot,
462         const sp<android::GraphicBuffer>& buffer) {
463     ATRACE_CALL();
464 
465     if (outSlot == NULL) {
466         BQ_LOGE("attachBuffer(P): outSlot must not be NULL");
467         return BAD_VALUE;
468     } else if (buffer == NULL) {
469         BQ_LOGE("attachBuffer(P): cannot attach NULL buffer");
470         return BAD_VALUE;
471     }
472 
473     Mutex::Autolock lock(mCore->mMutex);
474     mCore->waitWhileAllocatingLocked();
475 
476     status_t returnFlags = NO_ERROR;
477     int found;
478     // TODO: Should we provide an async flag to attachBuffer? It seems
479     // unlikely that buffers which we are attaching to a BufferQueue will
480     // be asynchronous (droppable), but it may not be impossible.
481     status_t status = waitForFreeSlotThenRelock("attachBuffer(P)", false,
482             &found, &returnFlags);
483     if (status != NO_ERROR) {
484         return status;
485     }
486 
487     // This should not happen
488     if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
489         BQ_LOGE("attachBuffer(P): no available buffer slots");
490         return -EBUSY;
491     }
492 
493     *outSlot = found;
494     ATRACE_BUFFER_INDEX(*outSlot);
495     BQ_LOGV("attachBuffer(P): returning slot %d flags=%#x",
496             *outSlot, returnFlags);
497 
498     mSlots[*outSlot].mGraphicBuffer = buffer;
499     mSlots[*outSlot].mBufferState = BufferSlot::DEQUEUED;
500     mSlots[*outSlot].mEglFence = EGL_NO_SYNC_KHR;
501     mSlots[*outSlot].mFence = Fence::NO_FENCE;
502     mSlots[*outSlot].mRequestBufferCalled = true;
503 
504     return returnFlags;
505 }
506 
queueBuffer(int slot,const QueueBufferInput & input,QueueBufferOutput * output)507 status_t BufferQueueProducer::queueBuffer(int slot,
508         const QueueBufferInput &input, QueueBufferOutput *output) {
509     ATRACE_CALL();
510     ATRACE_BUFFER_INDEX(slot);
511 
512     int64_t timestamp;
513     bool isAutoTimestamp;
514     Rect crop;
515     int scalingMode;
516     uint32_t transform;
517     uint32_t stickyTransform;
518     bool async;
519     sp<Fence> fence;
520     input.deflate(&timestamp, &isAutoTimestamp, &crop, &scalingMode, &transform,
521             &async, &fence, &stickyTransform);
522 
523     if (fence == NULL) {
524         BQ_LOGE("queueBuffer: fence is NULL");
525         // Temporary workaround for b/17946343: soldier-on instead of returning an error. This
526         // prevents the client from dying, at the risk of visible corruption due to hwcomposer
527         // reading the buffer before the producer is done rendering it. Unless the buffer is the
528         // last frame of an animation, the corruption will be transient.
529         fence = Fence::NO_FENCE;
530         // return BAD_VALUE;
531     }
532 
533     switch (scalingMode) {
534         case NATIVE_WINDOW_SCALING_MODE_FREEZE:
535         case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
536         case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
537         case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP:
538             break;
539         default:
540             BQ_LOGE("queueBuffer: unknown scaling mode %d", scalingMode);
541             return BAD_VALUE;
542     }
543 
544     sp<IConsumerListener> listener;
545     { // Autolock scope
546         Mutex::Autolock lock(mCore->mMutex);
547 
548         if (mCore->mIsAbandoned) {
549             BQ_LOGE("queueBuffer: BufferQueue has been abandoned");
550             return NO_INIT;
551         }
552 
553         const int maxBufferCount = mCore->getMaxBufferCountLocked(async);
554         if (async && mCore->mOverrideMaxBufferCount) {
555             // FIXME: Some drivers are manually setting the buffer count
556             // (which they shouldn't), so we do this extra test here to
557             // handle that case. This is TEMPORARY until we get this fixed.
558             if (mCore->mOverrideMaxBufferCount < maxBufferCount) {
559                 BQ_LOGE("queueBuffer: async mode is invalid with "
560                         "buffer count override");
561                 return BAD_VALUE;
562             }
563         }
564 
565         if (slot < 0 || slot >= maxBufferCount) {
566             BQ_LOGE("queueBuffer: slot index %d out of range [0, %d)",
567                     slot, maxBufferCount);
568             return BAD_VALUE;
569         } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
570             BQ_LOGE("queueBuffer: slot %d is not owned by the producer "
571                     "(state = %d)", slot, mSlots[slot].mBufferState);
572             return BAD_VALUE;
573         } else if (!mSlots[slot].mRequestBufferCalled) {
574             BQ_LOGE("queueBuffer: slot %d was queued without requesting "
575                     "a buffer", slot);
576             return BAD_VALUE;
577         }
578 
579         BQ_LOGV("queueBuffer: slot=%d/%" PRIu64 " time=%" PRIu64
580                 " crop=[%d,%d,%d,%d] transform=%#x scale=%s",
581                 slot, mCore->mFrameCounter + 1, timestamp,
582                 crop.left, crop.top, crop.right, crop.bottom,
583                 transform, BufferItem::scalingModeName(scalingMode));
584 
585         const sp<GraphicBuffer>& graphicBuffer(mSlots[slot].mGraphicBuffer);
586         Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight());
587         Rect croppedRect;
588         crop.intersect(bufferRect, &croppedRect);
589         if (croppedRect != crop) {
590             BQ_LOGE("queueBuffer: crop rect is not contained within the "
591                     "buffer in slot %d", slot);
592             return BAD_VALUE;
593         }
594 
595         mSlots[slot].mFence = fence;
596         mSlots[slot].mBufferState = BufferSlot::QUEUED;
597         ++mCore->mFrameCounter;
598         mSlots[slot].mFrameNumber = mCore->mFrameCounter;
599 
600         BufferItem item;
601         item.mAcquireCalled = mSlots[slot].mAcquireCalled;
602         item.mGraphicBuffer = mSlots[slot].mGraphicBuffer;
603         item.mCrop = crop;
604         item.mTransform = transform & ~NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
605         item.mTransformToDisplayInverse =
606                 bool(transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY);
607         item.mScalingMode = scalingMode;
608         item.mTimestamp = timestamp;
609         item.mIsAutoTimestamp = isAutoTimestamp;
610         item.mFrameNumber = mCore->mFrameCounter;
611         item.mSlot = slot;
612         item.mFence = fence;
613         item.mIsDroppable = mCore->mDequeueBufferCannotBlock || async;
614 
615         mStickyTransform = stickyTransform;
616 
617         if (mCore->mQueue.empty()) {
618             // When the queue is empty, we can ignore mDequeueBufferCannotBlock
619             // and simply queue this buffer
620             mCore->mQueue.push_back(item);
621             listener = mCore->mConsumerListener;
622         } else {
623             // When the queue is not empty, we need to look at the front buffer
624             // state to see if we need to replace it
625             BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin());
626             if (front->mIsDroppable) {
627                 // If the front queued buffer is still being tracked, we first
628                 // mark it as freed
629                 if (mCore->stillTracking(front)) {
630                     mSlots[front->mSlot].mBufferState = BufferSlot::FREE;
631                     // Reset the frame number of the freed buffer so that it is
632                     // the first in line to be dequeued again
633                     mSlots[front->mSlot].mFrameNumber = 0;
634                 }
635                 // Overwrite the droppable buffer with the incoming one
636                 *front = item;
637             } else {
638                 mCore->mQueue.push_back(item);
639                 listener = mCore->mConsumerListener;
640             }
641         }
642 
643         mCore->mBufferHasBeenQueued = true;
644         mCore->mDequeueCondition.broadcast();
645 
646         output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
647                 mCore->mTransformHint, mCore->mQueue.size());
648 
649         ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size());
650     } // Autolock scope
651 
652     // Call back without lock held
653     if (listener != NULL) {
654         listener->onFrameAvailable();
655     }
656 
657     return NO_ERROR;
658 }
659 
cancelBuffer(int slot,const sp<Fence> & fence)660 void BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
661     ATRACE_CALL();
662     BQ_LOGV("cancelBuffer: slot %d", slot);
663     Mutex::Autolock lock(mCore->mMutex);
664 
665     if (mCore->mIsAbandoned) {
666         BQ_LOGE("cancelBuffer: BufferQueue has been abandoned");
667         return;
668     }
669 
670     if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
671         BQ_LOGE("cancelBuffer: slot index %d out of range [0, %d)",
672                 slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
673         return;
674     } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
675         BQ_LOGE("cancelBuffer: slot %d is not owned by the producer "
676                 "(state = %d)", slot, mSlots[slot].mBufferState);
677         return;
678     } else if (fence == NULL) {
679         BQ_LOGE("cancelBuffer: fence is NULL");
680         return;
681     }
682 
683     mSlots[slot].mBufferState = BufferSlot::FREE;
684     mSlots[slot].mFrameNumber = 0;
685     mSlots[slot].mFence = fence;
686     mCore->mDequeueCondition.broadcast();
687 }
688 
query(int what,int * outValue)689 int BufferQueueProducer::query(int what, int *outValue) {
690     ATRACE_CALL();
691     Mutex::Autolock lock(mCore->mMutex);
692 
693     if (outValue == NULL) {
694         BQ_LOGE("query: outValue was NULL");
695         return BAD_VALUE;
696     }
697 
698     if (mCore->mIsAbandoned) {
699         BQ_LOGE("query: BufferQueue has been abandoned");
700         return NO_INIT;
701     }
702 
703     int value;
704     switch (what) {
705         case NATIVE_WINDOW_WIDTH:
706             value = mCore->mDefaultWidth;
707             break;
708         case NATIVE_WINDOW_HEIGHT:
709             value = mCore->mDefaultHeight;
710             break;
711         case NATIVE_WINDOW_FORMAT:
712             value = mCore->mDefaultBufferFormat;
713             break;
714         case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
715             value = mCore->getMinUndequeuedBufferCountLocked(false);
716             break;
717         case NATIVE_WINDOW_STICKY_TRANSFORM:
718             value = static_cast<int>(mStickyTransform);
719             break;
720         case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
721             value = (mCore->mQueue.size() > 1);
722             break;
723         case NATIVE_WINDOW_CONSUMER_USAGE_BITS:
724             value = mCore->mConsumerUsageBits;
725             break;
726         default:
727             return BAD_VALUE;
728     }
729 
730     BQ_LOGV("query: %d? %d", what, value);
731     *outValue = value;
732     return NO_ERROR;
733 }
734 
connect(const sp<IProducerListener> & listener,int api,bool producerControlledByApp,QueueBufferOutput * output)735 status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener,
736         int api, bool producerControlledByApp, QueueBufferOutput *output) {
737     ATRACE_CALL();
738     Mutex::Autolock lock(mCore->mMutex);
739     mConsumerName = mCore->mConsumerName;
740     BQ_LOGV("connect(P): api=%d producerControlledByApp=%s", api,
741             producerControlledByApp ? "true" : "false");
742 
743     if (mCore->mIsAbandoned) {
744         BQ_LOGE("connect(P): BufferQueue has been abandoned");
745         return NO_INIT;
746     }
747 
748     if (mCore->mConsumerListener == NULL) {
749         BQ_LOGE("connect(P): BufferQueue has no consumer");
750         return NO_INIT;
751     }
752 
753     if (output == NULL) {
754         BQ_LOGE("connect(P): output was NULL");
755         return BAD_VALUE;
756     }
757 
758     if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
759         BQ_LOGE("connect(P): already connected (cur=%d req=%d)",
760                 mCore->mConnectedApi, api);
761         return BAD_VALUE;
762     }
763 
764     int status = NO_ERROR;
765     switch (api) {
766         case NATIVE_WINDOW_API_EGL:
767         case NATIVE_WINDOW_API_CPU:
768         case NATIVE_WINDOW_API_MEDIA:
769         case NATIVE_WINDOW_API_CAMERA:
770             mCore->mConnectedApi = api;
771             output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
772                     mCore->mTransformHint, mCore->mQueue.size());
773 
774             // Set up a death notification so that we can disconnect
775             // automatically if the remote producer dies
776             if (listener != NULL &&
777                     listener->asBinder()->remoteBinder() != NULL) {
778                 status = listener->asBinder()->linkToDeath(
779                         static_cast<IBinder::DeathRecipient*>(this));
780                 if (status != NO_ERROR) {
781                     BQ_LOGE("connect(P): linkToDeath failed: %s (%d)",
782                             strerror(-status), status);
783                 }
784             }
785             mCore->mConnectedProducerListener = listener;
786             break;
787         default:
788             BQ_LOGE("connect(P): unknown API %d", api);
789             status = BAD_VALUE;
790             break;
791     }
792 
793     mCore->mBufferHasBeenQueued = false;
794     mCore->mDequeueBufferCannotBlock =
795             mCore->mConsumerControlledByApp && producerControlledByApp;
796 
797     return status;
798 }
799 
disconnect(int api)800 status_t BufferQueueProducer::disconnect(int api) {
801     ATRACE_CALL();
802     BQ_LOGV("disconnect(P): api %d", api);
803 
804     int status = NO_ERROR;
805     sp<IConsumerListener> listener;
806     { // Autolock scope
807         Mutex::Autolock lock(mCore->mMutex);
808         mCore->waitWhileAllocatingLocked();
809 
810         if (mCore->mIsAbandoned) {
811             // It's not really an error to disconnect after the surface has
812             // been abandoned; it should just be a no-op.
813             return NO_ERROR;
814         }
815 
816         switch (api) {
817             case NATIVE_WINDOW_API_EGL:
818             case NATIVE_WINDOW_API_CPU:
819             case NATIVE_WINDOW_API_MEDIA:
820             case NATIVE_WINDOW_API_CAMERA:
821                 if (mCore->mConnectedApi == api) {
822                     mCore->freeAllBuffersLocked();
823 
824                     // Remove our death notification callback if we have one
825                     if (mCore->mConnectedProducerListener != NULL) {
826                         sp<IBinder> token =
827                                 mCore->mConnectedProducerListener->asBinder();
828                         // This can fail if we're here because of the death
829                         // notification, but we just ignore it
830                         token->unlinkToDeath(
831                                 static_cast<IBinder::DeathRecipient*>(this));
832                     }
833                     mCore->mConnectedProducerListener = NULL;
834                     mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API;
835                     mCore->mSidebandStream.clear();
836                     mCore->mDequeueCondition.broadcast();
837                     listener = mCore->mConsumerListener;
838                 } else {
839                     BQ_LOGE("disconnect(P): connected to another API "
840                             "(cur=%d req=%d)", mCore->mConnectedApi, api);
841                     status = BAD_VALUE;
842                 }
843                 break;
844             default:
845                 BQ_LOGE("disconnect(P): unknown API %d", api);
846                 status = BAD_VALUE;
847                 break;
848         }
849     } // Autolock scope
850 
851     // Call back without lock held
852     if (listener != NULL) {
853         listener->onBuffersReleased();
854     }
855 
856     return status;
857 }
858 
setSidebandStream(const sp<NativeHandle> & stream)859 status_t BufferQueueProducer::setSidebandStream(const sp<NativeHandle>& stream) {
860     sp<IConsumerListener> listener;
861     { // Autolock scope
862         Mutex::Autolock _l(mCore->mMutex);
863         mCore->mSidebandStream = stream;
864         listener = mCore->mConsumerListener;
865     } // Autolock scope
866 
867     if (listener != NULL) {
868         listener->onSidebandStreamChanged();
869     }
870     return NO_ERROR;
871 }
872 
allocateBuffers(bool async,uint32_t width,uint32_t height,uint32_t format,uint32_t usage)873 void BufferQueueProducer::allocateBuffers(bool async, uint32_t width,
874         uint32_t height, uint32_t format, uint32_t usage) {
875     ATRACE_CALL();
876     while (true) {
877         Vector<int> freeSlots;
878         size_t newBufferCount = 0;
879         uint32_t allocWidth = 0;
880         uint32_t allocHeight = 0;
881         uint32_t allocFormat = 0;
882         uint32_t allocUsage = 0;
883         { // Autolock scope
884             Mutex::Autolock lock(mCore->mMutex);
885             mCore->waitWhileAllocatingLocked();
886 
887             int currentBufferCount = 0;
888             for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) {
889                 if (mSlots[slot].mGraphicBuffer != NULL) {
890                     ++currentBufferCount;
891                 } else {
892                     if (mSlots[slot].mBufferState != BufferSlot::FREE) {
893                         BQ_LOGE("allocateBuffers: slot %d without buffer is not FREE",
894                                 slot);
895                         continue;
896                     }
897 
898                     freeSlots.push_back(slot);
899                 }
900             }
901 
902             int maxBufferCount = mCore->getMaxBufferCountLocked(async);
903             BQ_LOGV("allocateBuffers: allocating from %d buffers up to %d buffers",
904                     currentBufferCount, maxBufferCount);
905             if (maxBufferCount <= currentBufferCount)
906                 return;
907             newBufferCount = maxBufferCount - currentBufferCount;
908             if (freeSlots.size() < newBufferCount) {
909                 BQ_LOGE("allocateBuffers: ran out of free slots");
910                 return;
911             }
912             allocWidth = width > 0 ? width : mCore->mDefaultWidth;
913             allocHeight = height > 0 ? height : mCore->mDefaultHeight;
914             allocFormat = format != 0 ? format : mCore->mDefaultBufferFormat;
915             allocUsage = usage | mCore->mConsumerUsageBits;
916 
917             mCore->mIsAllocating = true;
918         } // Autolock scope
919 
920         Vector<sp<GraphicBuffer> > buffers;
921         for (size_t i = 0; i <  newBufferCount; ++i) {
922             status_t result = NO_ERROR;
923             sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
924                     allocWidth, allocHeight, allocFormat, allocUsage, &result));
925             if (result != NO_ERROR) {
926                 BQ_LOGE("allocateBuffers: failed to allocate buffer (%u x %u, format"
927                         " %u, usage %u)", width, height, format, usage);
928                 Mutex::Autolock lock(mCore->mMutex);
929                 mCore->mIsAllocating = false;
930                 mCore->mIsAllocatingCondition.broadcast();
931                 return;
932             }
933             buffers.push_back(graphicBuffer);
934         }
935 
936         { // Autolock scope
937             Mutex::Autolock lock(mCore->mMutex);
938             uint32_t checkWidth = width > 0 ? width : mCore->mDefaultWidth;
939             uint32_t checkHeight = height > 0 ? height : mCore->mDefaultHeight;
940             uint32_t checkFormat = format != 0 ? format : mCore->mDefaultBufferFormat;
941             uint32_t checkUsage = usage | mCore->mConsumerUsageBits;
942             if (checkWidth != allocWidth || checkHeight != allocHeight ||
943                 checkFormat != allocFormat || checkUsage != allocUsage) {
944                 // Something changed while we released the lock. Retry.
945                 BQ_LOGV("allocateBuffers: size/format/usage changed while allocating. Retrying.");
946                 mCore->mIsAllocating = false;
947                 mCore->mIsAllocatingCondition.broadcast();
948                 continue;
949             }
950 
951             for (size_t i = 0; i < newBufferCount; ++i) {
952                 int slot = freeSlots[i];
953                 if (mSlots[slot].mBufferState != BufferSlot::FREE) {
954                     // A consumer allocated the FREE slot with attachBuffer. Discard the buffer we
955                     // allocated.
956                     BQ_LOGV("allocateBuffers: slot %d was acquired while allocating. "
957                             "Dropping allocated buffer.", slot);
958                     continue;
959                 }
960                 mCore->freeBufferLocked(slot); // Clean up the slot first
961                 mSlots[slot].mGraphicBuffer = buffers[i];
962                 mSlots[slot].mFrameNumber = 0;
963                 mSlots[slot].mFence = Fence::NO_FENCE;
964                 BQ_LOGV("allocateBuffers: allocated a new buffer in slot %d", slot);
965             }
966 
967             mCore->mIsAllocating = false;
968             mCore->mIsAllocatingCondition.broadcast();
969         } // Autolock scope
970     }
971 }
972 
binderDied(const wp<android::IBinder> &)973 void BufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) {
974     // If we're here, it means that a producer we were connected to died.
975     // We're guaranteed that we are still connected to it because we remove
976     // this callback upon disconnect. It's therefore safe to read mConnectedApi
977     // without synchronization here.
978     int api = mCore->mConnectedApi;
979     disconnect(api);
980 }
981 
982 } // namespace android
983