1 /*
2  * Copyright (C) 2019 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 #undef LOG_TAG
18 #define LOG_TAG "BLASTBufferQueue"
19 
20 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
21 //#define LOG_NDEBUG 0
22 
23 #include <cutils/atomic.h>
24 #include <gui/BLASTBufferQueue.h>
25 #include <gui/BufferItemConsumer.h>
26 #include <gui/BufferQueueConsumer.h>
27 #include <gui/BufferQueueCore.h>
28 #include <gui/BufferQueueProducer.h>
29 
30 #include <gui/FrameRateUtils.h>
31 #include <gui/GLConsumer.h>
32 #include <gui/IProducerListener.h>
33 #include <gui/Surface.h>
34 #include <gui/TraceUtils.h>
35 #include <utils/Singleton.h>
36 #include <utils/Trace.h>
37 
38 #include <private/gui/ComposerService.h>
39 #include <private/gui/ComposerServiceAIDL.h>
40 
41 #include <android-base/thread_annotations.h>
42 #include <chrono>
43 
44 #include <com_android_graphics_libgui_flags.h>
45 
46 using namespace com::android::graphics::libgui;
47 using namespace std::chrono_literals;
48 
49 namespace {
boolToString(bool b)50 inline const char* boolToString(bool b) {
51     return b ? "true" : "false";
52 }
53 } // namespace
54 
55 namespace android {
56 
57 // Macros to include adapter info in log messages
58 #define BQA_LOGD(x, ...) \
59     ALOGD("[%s](f:%u,a:%u) " x, mName.c_str(), mNumFrameAvailable, mNumAcquired, ##__VA_ARGS__)
60 #define BQA_LOGV(x, ...) \
61     ALOGV("[%s](f:%u,a:%u) " x, mName.c_str(), mNumFrameAvailable, mNumAcquired, ##__VA_ARGS__)
62 // enable logs for a single layer
63 //#define BQA_LOGV(x, ...) \
64 //    ALOGV_IF((strstr(mName.c_str(), "SurfaceView") != nullptr), "[%s](f:%u,a:%u) " x, \
65 //              mName.c_str(), mNumFrameAvailable, mNumAcquired, ##__VA_ARGS__)
66 #define BQA_LOGE(x, ...) \
67     ALOGE("[%s](f:%u,a:%u) " x, mName.c_str(), mNumFrameAvailable, mNumAcquired, ##__VA_ARGS__)
68 
69 #define BBQ_TRACE(x, ...)                                                                  \
70     ATRACE_FORMAT("%s - %s(f:%u,a:%u)" x, __FUNCTION__, mName.c_str(), mNumFrameAvailable, \
71                   mNumAcquired, ##__VA_ARGS__)
72 
73 #define UNIQUE_LOCK_WITH_ASSERTION(mutex) \
74     std::unique_lock _lock{mutex};        \
75     base::ScopedLockAssertion assumeLocked(mutex);
76 
onDisconnect()77 void BLASTBufferItemConsumer::onDisconnect() {
78     Mutex::Autolock lock(mMutex);
79     mPreviouslyConnected = mCurrentlyConnected;
80     mCurrentlyConnected = false;
81     if (mPreviouslyConnected) {
82         mDisconnectEvents.push(mCurrentFrameNumber);
83     }
84     mFrameEventHistory.onDisconnect();
85 }
86 
addAndGetFrameTimestamps(const NewFrameEventsEntry * newTimestamps,FrameEventHistoryDelta * outDelta)87 void BLASTBufferItemConsumer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps,
88                                                        FrameEventHistoryDelta* outDelta) {
89     Mutex::Autolock lock(mMutex);
90     if (newTimestamps) {
91         // BufferQueueProducer only adds a new timestamp on
92         // queueBuffer
93         mCurrentFrameNumber = newTimestamps->frameNumber;
94         mFrameEventHistory.addQueue(*newTimestamps);
95     }
96     if (outDelta) {
97         // frame event histories will be processed
98         // only after the producer connects and requests
99         // deltas for the first time.  Forward this intent
100         // to SF-side to turn event processing back on
101         mPreviouslyConnected = mCurrentlyConnected;
102         mCurrentlyConnected = true;
103         mFrameEventHistory.getAndResetDelta(outDelta);
104     }
105 }
106 
updateFrameTimestamps(uint64_t frameNumber,uint64_t previousFrameNumber,nsecs_t refreshStartTime,const sp<Fence> & glDoneFence,const sp<Fence> & presentFence,const sp<Fence> & prevReleaseFence,CompositorTiming compositorTiming,nsecs_t latchTime,nsecs_t dequeueReadyTime)107 void BLASTBufferItemConsumer::updateFrameTimestamps(
108         uint64_t frameNumber, uint64_t previousFrameNumber, nsecs_t refreshStartTime,
109         const sp<Fence>& glDoneFence, const sp<Fence>& presentFence,
110         const sp<Fence>& prevReleaseFence, CompositorTiming compositorTiming, nsecs_t latchTime,
111         nsecs_t dequeueReadyTime) {
112     Mutex::Autolock lock(mMutex);
113 
114     // if the producer is not connected, don't bother updating,
115     // the next producer that connects won't access this frame event
116     if (!mCurrentlyConnected) return;
117     std::shared_ptr<FenceTime> glDoneFenceTime = std::make_shared<FenceTime>(glDoneFence);
118     std::shared_ptr<FenceTime> presentFenceTime = std::make_shared<FenceTime>(presentFence);
119     std::shared_ptr<FenceTime> releaseFenceTime = std::make_shared<FenceTime>(prevReleaseFence);
120 
121     mFrameEventHistory.addLatch(frameNumber, latchTime);
122     if (flags::frametimestamps_previousrelease()) {
123         if (previousFrameNumber > 0) {
124             mFrameEventHistory.addRelease(previousFrameNumber, dequeueReadyTime,
125                                           std::move(releaseFenceTime));
126         }
127     } else {
128         mFrameEventHistory.addRelease(frameNumber, dequeueReadyTime, std::move(releaseFenceTime));
129     }
130 
131     mFrameEventHistory.addPreComposition(frameNumber, refreshStartTime);
132     mFrameEventHistory.addPostComposition(frameNumber, glDoneFenceTime, presentFenceTime,
133                                           compositorTiming);
134 }
135 
getConnectionEvents(uint64_t frameNumber,bool * needsDisconnect)136 void BLASTBufferItemConsumer::getConnectionEvents(uint64_t frameNumber, bool* needsDisconnect) {
137     bool disconnect = false;
138     Mutex::Autolock lock(mMutex);
139     while (!mDisconnectEvents.empty() && mDisconnectEvents.front() <= frameNumber) {
140         disconnect = true;
141         mDisconnectEvents.pop();
142     }
143     if (needsDisconnect != nullptr) *needsDisconnect = disconnect;
144 }
145 
onSidebandStreamChanged()146 void BLASTBufferItemConsumer::onSidebandStreamChanged() {
147     sp<BLASTBufferQueue> bbq = mBLASTBufferQueue.promote();
148     if (bbq != nullptr) {
149         sp<NativeHandle> stream = getSidebandStream();
150         bbq->setSidebandStream(stream);
151     }
152 }
153 
154 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_SETFRAMERATE)
onSetFrameRate(float frameRate,int8_t compatibility,int8_t changeFrameRateStrategy)155 void BLASTBufferItemConsumer::onSetFrameRate(float frameRate, int8_t compatibility,
156                                              int8_t changeFrameRateStrategy) {
157     sp<BLASTBufferQueue> bbq = mBLASTBufferQueue.promote();
158     if (bbq != nullptr) {
159         bbq->setFrameRate(frameRate, compatibility, changeFrameRateStrategy);
160     }
161 }
162 #endif
163 
resizeFrameEventHistory(size_t newSize)164 void BLASTBufferItemConsumer::resizeFrameEventHistory(size_t newSize) {
165     Mutex::Autolock lock(mMutex);
166     mFrameEventHistory.resize(newSize);
167 }
168 
BLASTBufferQueue(const std::string & name,bool updateDestinationFrame)169 BLASTBufferQueue::BLASTBufferQueue(const std::string& name, bool updateDestinationFrame)
170       : mSurfaceControl(nullptr),
171         mSize(1, 1),
172         mRequestedSize(mSize),
173         mFormat(PIXEL_FORMAT_RGBA_8888),
174         mTransactionReadyCallback(nullptr),
175         mSyncTransaction(nullptr),
176         mUpdateDestinationFrame(updateDestinationFrame) {
177     createBufferQueue(&mProducer, &mConsumer);
178     // since the adapter is in the client process, set dequeue timeout
179     // explicitly so that dequeueBuffer will block
180     mProducer->setDequeueTimeout(std::numeric_limits<int64_t>::max());
181 
182     // safe default, most producers are expected to override this
183     mProducer->setMaxDequeuedBufferCount(2);
184     mBufferItemConsumer = new BLASTBufferItemConsumer(mConsumer,
185                                                       GraphicBuffer::USAGE_HW_COMPOSER |
186                                                               GraphicBuffer::USAGE_HW_TEXTURE,
187                                                       1, false, this);
188     static std::atomic<uint32_t> nextId = 0;
189     mProducerId = nextId++;
190     mName = name + "#" + std::to_string(mProducerId);
191     auto consumerName = mName + "(BLAST Consumer)" + std::to_string(mProducerId);
192     mQueuedBufferTrace = "QueuedBuffer - " + mName + "BLAST#" + std::to_string(mProducerId);
193     mBufferItemConsumer->setName(String8(consumerName.c_str()));
194     mBufferItemConsumer->setFrameAvailableListener(this);
195 
196     ComposerServiceAIDL::getComposerService()->getMaxAcquiredBufferCount(&mMaxAcquiredBuffers);
197     mBufferItemConsumer->setMaxAcquiredBufferCount(mMaxAcquiredBuffers);
198     mCurrentMaxAcquiredBufferCount = mMaxAcquiredBuffers;
199     mNumAcquired = 0;
200     mNumFrameAvailable = 0;
201 
202     TransactionCompletedListener::getInstance()->addQueueStallListener(
203             [&](const std::string& reason) {
204                 std::function<void(const std::string&)> callbackCopy;
205                 {
206                     std::unique_lock _lock{mMutex};
207                     callbackCopy = mTransactionHangCallback;
208                 }
209                 if (callbackCopy) callbackCopy(reason);
210             },
211             this);
212 
213     BQA_LOGV("BLASTBufferQueue created");
214 }
215 
BLASTBufferQueue(const std::string & name,const sp<SurfaceControl> & surface,int width,int height,int32_t format)216 BLASTBufferQueue::BLASTBufferQueue(const std::string& name, const sp<SurfaceControl>& surface,
217                                    int width, int height, int32_t format)
218       : BLASTBufferQueue(name) {
219     update(surface, width, height, format);
220 }
221 
~BLASTBufferQueue()222 BLASTBufferQueue::~BLASTBufferQueue() {
223     TransactionCompletedListener::getInstance()->removeQueueStallListener(this);
224     if (mPendingTransactions.empty()) {
225         return;
226     }
227     BQA_LOGE("Applying pending transactions on dtor %d",
228              static_cast<uint32_t>(mPendingTransactions.size()));
229     SurfaceComposerClient::Transaction t;
230     mergePendingTransactions(&t, std::numeric_limits<uint64_t>::max() /* frameNumber */);
231     // All transactions on our apply token are one-way. See comment on mAppliedLastTransaction
232     t.setApplyToken(mApplyToken).apply(false, true);
233 
234     if (mTransactionReadyCallback) {
235         mTransactionReadyCallback(mSyncTransaction);
236     }
237 }
238 
update(const sp<SurfaceControl> & surface,uint32_t width,uint32_t height,int32_t format)239 void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width, uint32_t height,
240                               int32_t format) {
241     LOG_ALWAYS_FATAL_IF(surface == nullptr, "BLASTBufferQueue: mSurfaceControl must not be NULL");
242 
243     std::lock_guard _lock{mMutex};
244     if (mFormat != format) {
245         mFormat = format;
246         mBufferItemConsumer->setDefaultBufferFormat(convertBufferFormat(format));
247     }
248 
249     const bool surfaceControlChanged = !SurfaceControl::isSameSurface(mSurfaceControl, surface);
250     if (surfaceControlChanged && mSurfaceControl != nullptr) {
251         BQA_LOGD("Updating SurfaceControl without recreating BBQ");
252     }
253     bool applyTransaction = false;
254 
255     // Always update the native object even though they might have the same layer handle, so we can
256     // get the updated transform hint from WM.
257     mSurfaceControl = surface;
258     SurfaceComposerClient::Transaction t;
259     if (surfaceControlChanged) {
260         t.setFlags(mSurfaceControl, layer_state_t::eEnableBackpressure,
261                    layer_state_t::eEnableBackpressure);
262         applyTransaction = true;
263     }
264     mTransformHint = mSurfaceControl->getTransformHint();
265     mBufferItemConsumer->setTransformHint(mTransformHint);
266     BQA_LOGV("update width=%d height=%d format=%d mTransformHint=%d", width, height, format,
267              mTransformHint);
268 
269     ui::Size newSize(width, height);
270     if (mRequestedSize != newSize) {
271         mRequestedSize.set(newSize);
272         mBufferItemConsumer->setDefaultBufferSize(mRequestedSize.width, mRequestedSize.height);
273         if (mLastBufferInfo.scalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE) {
274             // If the buffer supports scaling, update the frame immediately since the client may
275             // want to scale the existing buffer to the new size.
276             mSize = mRequestedSize;
277             if (mUpdateDestinationFrame) {
278                 t.setDestinationFrame(mSurfaceControl, Rect(newSize));
279                 applyTransaction = true;
280             }
281         }
282     }
283     if (applyTransaction) {
284         // All transactions on our apply token are one-way. See comment on mAppliedLastTransaction
285         t.setApplyToken(mApplyToken).apply(false, true);
286     }
287 }
288 
findMatchingStat(const std::vector<SurfaceControlStats> & stats,const sp<SurfaceControl> & sc)289 static std::optional<SurfaceControlStats> findMatchingStat(
290         const std::vector<SurfaceControlStats>& stats, const sp<SurfaceControl>& sc) {
291     for (auto stat : stats) {
292         if (SurfaceControl::isSameSurface(sc, stat.surfaceControl)) {
293             return stat;
294         }
295     }
296     return std::nullopt;
297 }
298 
transactionCommittedCallbackThunk(void * context,nsecs_t latchTime,const sp<Fence> & presentFence,const std::vector<SurfaceControlStats> & stats)299 static void transactionCommittedCallbackThunk(void* context, nsecs_t latchTime,
300                                               const sp<Fence>& presentFence,
301                                               const std::vector<SurfaceControlStats>& stats) {
302     if (context == nullptr) {
303         return;
304     }
305     sp<BLASTBufferQueue> bq = static_cast<BLASTBufferQueue*>(context);
306     bq->transactionCommittedCallback(latchTime, presentFence, stats);
307 }
308 
transactionCommittedCallback(nsecs_t,const sp<Fence> &,const std::vector<SurfaceControlStats> & stats)309 void BLASTBufferQueue::transactionCommittedCallback(nsecs_t /*latchTime*/,
310                                                     const sp<Fence>& /*presentFence*/,
311                                                     const std::vector<SurfaceControlStats>& stats) {
312     {
313         std::lock_guard _lock{mMutex};
314         BBQ_TRACE();
315         BQA_LOGV("transactionCommittedCallback");
316         if (!mSurfaceControlsWithPendingCallback.empty()) {
317             sp<SurfaceControl> pendingSC = mSurfaceControlsWithPendingCallback.front();
318             std::optional<SurfaceControlStats> stat = findMatchingStat(stats, pendingSC);
319             if (stat) {
320                 uint64_t currFrameNumber = stat->frameEventStats.frameNumber;
321 
322                 // We need to check if we were waiting for a transaction callback in order to
323                 // process any pending buffers and unblock. It's possible to get transaction
324                 // callbacks for previous requests so we need to ensure that there are no pending
325                 // frame numbers that were in a sync. We remove the frame from mSyncedFrameNumbers
326                 // set and then check if it's empty. If there are no more pending syncs, we can
327                 // proceed with flushing the shadow queue.
328                 mSyncedFrameNumbers.erase(currFrameNumber);
329                 if (mSyncedFrameNumbers.empty()) {
330                     flushShadowQueue();
331                 }
332             } else {
333                 BQA_LOGE("Failed to find matching SurfaceControl in transactionCommittedCallback");
334             }
335         } else {
336             BQA_LOGE("No matching SurfaceControls found: mSurfaceControlsWithPendingCallback was "
337                      "empty.");
338         }
339         decStrong((void*)transactionCommittedCallbackThunk);
340     }
341 }
342 
transactionCallbackThunk(void * context,nsecs_t latchTime,const sp<Fence> & presentFence,const std::vector<SurfaceControlStats> & stats)343 static void transactionCallbackThunk(void* context, nsecs_t latchTime,
344                                      const sp<Fence>& presentFence,
345                                      const std::vector<SurfaceControlStats>& stats) {
346     if (context == nullptr) {
347         return;
348     }
349     sp<BLASTBufferQueue> bq = static_cast<BLASTBufferQueue*>(context);
350     bq->transactionCallback(latchTime, presentFence, stats);
351 }
352 
transactionCallback(nsecs_t,const sp<Fence> &,const std::vector<SurfaceControlStats> & stats)353 void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence>& /*presentFence*/,
354                                            const std::vector<SurfaceControlStats>& stats) {
355     {
356         std::lock_guard _lock{mMutex};
357         BBQ_TRACE();
358         BQA_LOGV("transactionCallback");
359 
360         if (!mSurfaceControlsWithPendingCallback.empty()) {
361             sp<SurfaceControl> pendingSC = mSurfaceControlsWithPendingCallback.front();
362             mSurfaceControlsWithPendingCallback.pop();
363             std::optional<SurfaceControlStats> statsOptional = findMatchingStat(stats, pendingSC);
364             if (statsOptional) {
365                 SurfaceControlStats stat = *statsOptional;
366                 if (stat.transformHint) {
367                     mTransformHint = *stat.transformHint;
368                     mBufferItemConsumer->setTransformHint(mTransformHint);
369                     BQA_LOGV("updated mTransformHint=%d", mTransformHint);
370                 }
371                 // Update frametime stamps if the frame was latched and presented, indicated by a
372                 // valid latch time.
373                 if (stat.latchTime > 0) {
374                     mBufferItemConsumer
375                             ->updateFrameTimestamps(stat.frameEventStats.frameNumber,
376                                                     stat.frameEventStats.previousFrameNumber,
377                                                     stat.frameEventStats.refreshStartTime,
378                                                     stat.frameEventStats.gpuCompositionDoneFence,
379                                                     stat.presentFence, stat.previousReleaseFence,
380                                                     stat.frameEventStats.compositorTiming,
381                                                     stat.latchTime,
382                                                     stat.frameEventStats.dequeueReadyTime);
383                 }
384                 auto currFrameNumber = stat.frameEventStats.frameNumber;
385                 std::vector<ReleaseCallbackId> staleReleases;
386                 for (const auto& [key, value]: mSubmitted) {
387                     if (currFrameNumber > key.framenumber) {
388                         staleReleases.push_back(key);
389                     }
390                 }
391                 for (const auto& staleRelease : staleReleases) {
392                     releaseBufferCallbackLocked(staleRelease,
393                                                 stat.previousReleaseFence
394                                                         ? stat.previousReleaseFence
395                                                         : Fence::NO_FENCE,
396                                                 stat.currentMaxAcquiredBufferCount,
397                                                 true /* fakeRelease */);
398                 }
399             } else {
400                 BQA_LOGE("Failed to find matching SurfaceControl in transactionCallback");
401             }
402         } else {
403             BQA_LOGE("No matching SurfaceControls found: mSurfaceControlsWithPendingCallback was "
404                      "empty.");
405         }
406 
407         decStrong((void*)transactionCallbackThunk);
408     }
409 }
410 
411 // Unlike transactionCallbackThunk the release buffer callback does not extend the life of the
412 // BBQ. This is because if the BBQ is destroyed, then the buffers will be released by the client.
413 // So we pass in a weak pointer to the BBQ and if it still alive, then we release the buffer.
414 // Otherwise, this is a no-op.
releaseBufferCallbackThunk(wp<BLASTBufferQueue> context,const ReleaseCallbackId & id,const sp<Fence> & releaseFence,std::optional<uint32_t> currentMaxAcquiredBufferCount)415 static void releaseBufferCallbackThunk(wp<BLASTBufferQueue> context, const ReleaseCallbackId& id,
416                                        const sp<Fence>& releaseFence,
417                                        std::optional<uint32_t> currentMaxAcquiredBufferCount) {
418     sp<BLASTBufferQueue> blastBufferQueue = context.promote();
419     if (blastBufferQueue) {
420         blastBufferQueue->releaseBufferCallback(id, releaseFence, currentMaxAcquiredBufferCount);
421     } else {
422         ALOGV("releaseBufferCallbackThunk %s blastBufferQueue is dead", id.to_string().c_str());
423     }
424 }
425 
flushShadowQueue()426 void BLASTBufferQueue::flushShadowQueue() {
427     BQA_LOGV("flushShadowQueue");
428     int numFramesToFlush = mNumFrameAvailable;
429     while (numFramesToFlush > 0) {
430         acquireNextBufferLocked(std::nullopt);
431         numFramesToFlush--;
432     }
433 }
434 
releaseBufferCallback(const ReleaseCallbackId & id,const sp<Fence> & releaseFence,std::optional<uint32_t> currentMaxAcquiredBufferCount)435 void BLASTBufferQueue::releaseBufferCallback(
436         const ReleaseCallbackId& id, const sp<Fence>& releaseFence,
437         std::optional<uint32_t> currentMaxAcquiredBufferCount) {
438     std::lock_guard _lock{mMutex};
439     BBQ_TRACE();
440     releaseBufferCallbackLocked(id, releaseFence, currentMaxAcquiredBufferCount,
441                                 false /* fakeRelease */);
442 }
443 
releaseBufferCallbackLocked(const ReleaseCallbackId & id,const sp<Fence> & releaseFence,std::optional<uint32_t> currentMaxAcquiredBufferCount,bool fakeRelease)444 void BLASTBufferQueue::releaseBufferCallbackLocked(
445         const ReleaseCallbackId& id, const sp<Fence>& releaseFence,
446         std::optional<uint32_t> currentMaxAcquiredBufferCount, bool fakeRelease) {
447     ATRACE_CALL();
448     BQA_LOGV("releaseBufferCallback %s", id.to_string().c_str());
449 
450     // Calculate how many buffers we need to hold before we release them back
451     // to the buffer queue. This will prevent higher latency when we are running
452     // on a lower refresh rate than the max supported. We only do that for EGL
453     // clients as others don't care about latency
454     const auto it = mSubmitted.find(id);
455     const bool isEGL = it != mSubmitted.end() && it->second.mApi == NATIVE_WINDOW_API_EGL;
456 
457     if (currentMaxAcquiredBufferCount) {
458         mCurrentMaxAcquiredBufferCount = *currentMaxAcquiredBufferCount;
459     }
460 
461     const uint32_t numPendingBuffersToHold =
462             isEGL ? std::max(0, mMaxAcquiredBuffers - (int32_t)mCurrentMaxAcquiredBufferCount) : 0;
463 
464     auto rb = ReleasedBuffer{id, releaseFence};
465     if (std::find(mPendingRelease.begin(), mPendingRelease.end(), rb) == mPendingRelease.end()) {
466         mPendingRelease.emplace_back(rb);
467         if (fakeRelease) {
468             BQA_LOGE("Faking releaseBufferCallback from transactionCompleteCallback %" PRIu64,
469                      id.framenumber);
470             BBQ_TRACE("FakeReleaseCallback");
471         }
472     }
473 
474     // Release all buffers that are beyond the ones that we need to hold
475     while (mPendingRelease.size() > numPendingBuffersToHold) {
476         const auto releasedBuffer = mPendingRelease.front();
477         mPendingRelease.pop_front();
478         releaseBuffer(releasedBuffer.callbackId, releasedBuffer.releaseFence);
479         // Don't process the transactions here if mSyncedFrameNumbers is not empty. That means
480         // are still transactions that have sync buffers in them that have not been applied or
481         // dropped. Instead, let onFrameAvailable handle processing them since it will merge with
482         // the syncTransaction.
483         if (mSyncedFrameNumbers.empty()) {
484             acquireNextBufferLocked(std::nullopt);
485         }
486     }
487 
488     ATRACE_INT("PendingRelease", mPendingRelease.size());
489     ATRACE_INT(mQueuedBufferTrace.c_str(),
490                mNumFrameAvailable + mNumAcquired - mPendingRelease.size());
491     mCallbackCV.notify_all();
492 }
493 
releaseBuffer(const ReleaseCallbackId & callbackId,const sp<Fence> & releaseFence)494 void BLASTBufferQueue::releaseBuffer(const ReleaseCallbackId& callbackId,
495                                      const sp<Fence>& releaseFence) {
496     auto it = mSubmitted.find(callbackId);
497     if (it == mSubmitted.end()) {
498         BQA_LOGE("ERROR: releaseBufferCallback without corresponding submitted buffer %s",
499                  callbackId.to_string().c_str());
500         return;
501     }
502     mNumAcquired--;
503     BBQ_TRACE("frame=%" PRIu64, callbackId.framenumber);
504     BQA_LOGV("released %s", callbackId.to_string().c_str());
505     mBufferItemConsumer->releaseBuffer(it->second, releaseFence);
506     mSubmitted.erase(it);
507     // Remove the frame number from mSyncedFrameNumbers since we can get a release callback
508     // without getting a transaction committed if the buffer was dropped.
509     mSyncedFrameNumbers.erase(callbackId.framenumber);
510 }
511 
getBufferSize(const BufferItem & item)512 static ui::Size getBufferSize(const BufferItem& item) {
513     uint32_t bufWidth = item.mGraphicBuffer->getWidth();
514     uint32_t bufHeight = item.mGraphicBuffer->getHeight();
515 
516     // Take the buffer's orientation into account
517     if (item.mTransform & ui::Transform::ROT_90) {
518         std::swap(bufWidth, bufHeight);
519     }
520     return ui::Size(bufWidth, bufHeight);
521 }
522 
acquireNextBufferLocked(const std::optional<SurfaceComposerClient::Transaction * > transaction)523 status_t BLASTBufferQueue::acquireNextBufferLocked(
524         const std::optional<SurfaceComposerClient::Transaction*> transaction) {
525     // Check if we have frames available and we have not acquired the maximum number of buffers.
526     // Even with this check, the consumer can fail to acquire an additional buffer if the consumer
527     // has already acquired (mMaxAcquiredBuffers + 1) and the new buffer is not droppable. In this
528     // case mBufferItemConsumer->acquireBuffer will return with NO_BUFFER_AVAILABLE.
529     if (mNumFrameAvailable == 0) {
530         BQA_LOGV("Can't acquire next buffer. No available frames");
531         return BufferQueue::NO_BUFFER_AVAILABLE;
532     }
533 
534     if (mNumAcquired >= (mMaxAcquiredBuffers + 2)) {
535         BQA_LOGV("Can't acquire next buffer. Already acquired max frames %d max:%d + 2",
536                  mNumAcquired, mMaxAcquiredBuffers);
537         return BufferQueue::NO_BUFFER_AVAILABLE;
538     }
539 
540     if (mSurfaceControl == nullptr) {
541         BQA_LOGE("ERROR : surface control is null");
542         return NAME_NOT_FOUND;
543     }
544 
545     SurfaceComposerClient::Transaction localTransaction;
546     bool applyTransaction = true;
547     SurfaceComposerClient::Transaction* t = &localTransaction;
548     if (transaction) {
549         t = *transaction;
550         applyTransaction = false;
551     }
552 
553     BufferItem bufferItem;
554 
555     status_t status =
556             mBufferItemConsumer->acquireBuffer(&bufferItem, 0 /* expectedPresent */, false);
557     if (status == BufferQueue::NO_BUFFER_AVAILABLE) {
558         BQA_LOGV("Failed to acquire a buffer, err=NO_BUFFER_AVAILABLE");
559         return status;
560     } else if (status != OK) {
561         BQA_LOGE("Failed to acquire a buffer, err=%s", statusToString(status).c_str());
562         return status;
563     }
564 
565     auto buffer = bufferItem.mGraphicBuffer;
566     mNumFrameAvailable--;
567     BBQ_TRACE("frame=%" PRIu64, bufferItem.mFrameNumber);
568 
569     if (buffer == nullptr) {
570         mBufferItemConsumer->releaseBuffer(bufferItem, Fence::NO_FENCE);
571         BQA_LOGE("Buffer was empty");
572         return BAD_VALUE;
573     }
574 
575     if (rejectBuffer(bufferItem)) {
576         BQA_LOGE("rejecting buffer:active_size=%dx%d, requested_size=%dx%d "
577                  "buffer{size=%dx%d transform=%d}",
578                  mSize.width, mSize.height, mRequestedSize.width, mRequestedSize.height,
579                  buffer->getWidth(), buffer->getHeight(), bufferItem.mTransform);
580         mBufferItemConsumer->releaseBuffer(bufferItem, Fence::NO_FENCE);
581         return acquireNextBufferLocked(transaction);
582     }
583 
584     mNumAcquired++;
585     mLastAcquiredFrameNumber = bufferItem.mFrameNumber;
586     ReleaseCallbackId releaseCallbackId(buffer->getId(), mLastAcquiredFrameNumber);
587     mSubmitted[releaseCallbackId] = bufferItem;
588 
589     bool needsDisconnect = false;
590     mBufferItemConsumer->getConnectionEvents(bufferItem.mFrameNumber, &needsDisconnect);
591 
592     // if producer disconnected before, notify SurfaceFlinger
593     if (needsDisconnect) {
594         t->notifyProducerDisconnect(mSurfaceControl);
595     }
596 
597     // Ensure BLASTBufferQueue stays alive until we receive the transaction complete callback.
598     incStrong((void*)transactionCallbackThunk);
599 
600     // Only update mSize for destination bounds if the incoming buffer matches the requested size.
601     // Otherwise, it could cause stretching since the destination bounds will update before the
602     // buffer with the new size is acquired.
603     if (mRequestedSize == getBufferSize(bufferItem) ||
604         bufferItem.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE) {
605         mSize = mRequestedSize;
606     }
607     Rect crop = computeCrop(bufferItem);
608     mLastBufferInfo.update(true /* hasBuffer */, bufferItem.mGraphicBuffer->getWidth(),
609                            bufferItem.mGraphicBuffer->getHeight(), bufferItem.mTransform,
610                            bufferItem.mScalingMode, crop);
611 
612     auto releaseBufferCallback =
613             std::bind(releaseBufferCallbackThunk, wp<BLASTBufferQueue>(this) /* callbackContext */,
614                       std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
615     sp<Fence> fence = bufferItem.mFence ? new Fence(bufferItem.mFence->dup()) : Fence::NO_FENCE;
616 
617     nsecs_t dequeueTime = -1;
618     {
619         std::lock_guard _lock{mTimestampMutex};
620         auto dequeueTimeIt = mDequeueTimestamps.find(buffer->getId());
621         if (dequeueTimeIt != mDequeueTimestamps.end()) {
622             dequeueTime = dequeueTimeIt->second;
623             mDequeueTimestamps.erase(dequeueTimeIt);
624         }
625     }
626 
627     t->setBuffer(mSurfaceControl, buffer, fence, bufferItem.mFrameNumber, mProducerId,
628                  releaseBufferCallback, dequeueTime);
629     t->setDataspace(mSurfaceControl, static_cast<ui::Dataspace>(bufferItem.mDataSpace));
630     t->setHdrMetadata(mSurfaceControl, bufferItem.mHdrMetadata);
631     t->setSurfaceDamageRegion(mSurfaceControl, bufferItem.mSurfaceDamage);
632     t->addTransactionCompletedCallback(transactionCallbackThunk, static_cast<void*>(this));
633 
634     mSurfaceControlsWithPendingCallback.push(mSurfaceControl);
635 
636     if (mUpdateDestinationFrame) {
637         t->setDestinationFrame(mSurfaceControl, Rect(mSize));
638     } else {
639         const bool ignoreDestinationFrame =
640                 bufferItem.mScalingMode == NATIVE_WINDOW_SCALING_MODE_FREEZE;
641         t->setFlags(mSurfaceControl,
642                     ignoreDestinationFrame ? layer_state_t::eIgnoreDestinationFrame : 0,
643                     layer_state_t::eIgnoreDestinationFrame);
644     }
645     t->setBufferCrop(mSurfaceControl, crop);
646     t->setTransform(mSurfaceControl, bufferItem.mTransform);
647     t->setTransformToDisplayInverse(mSurfaceControl, bufferItem.mTransformToDisplayInverse);
648     t->setAutoRefresh(mSurfaceControl, bufferItem.mAutoRefresh);
649     if (!bufferItem.mIsAutoTimestamp) {
650         t->setDesiredPresentTime(bufferItem.mTimestamp);
651     }
652 
653     // Drop stale frame timeline infos
654     while (!mPendingFrameTimelines.empty() &&
655            mPendingFrameTimelines.front().first < bufferItem.mFrameNumber) {
656         ATRACE_FORMAT_INSTANT("dropping stale frameNumber: %" PRIu64 " vsyncId: %" PRId64,
657                               mPendingFrameTimelines.front().first,
658                               mPendingFrameTimelines.front().second.vsyncId);
659         mPendingFrameTimelines.pop();
660     }
661 
662     if (!mPendingFrameTimelines.empty() &&
663         mPendingFrameTimelines.front().first == bufferItem.mFrameNumber) {
664         ATRACE_FORMAT_INSTANT("Transaction::setFrameTimelineInfo frameNumber: %" PRIu64
665                               " vsyncId: %" PRId64,
666                               bufferItem.mFrameNumber,
667                               mPendingFrameTimelines.front().second.vsyncId);
668         t->setFrameTimelineInfo(mPendingFrameTimelines.front().second);
669         mPendingFrameTimelines.pop();
670     }
671 
672     mergePendingTransactions(t, bufferItem.mFrameNumber);
673     if (applyTransaction) {
674         // All transactions on our apply token are one-way. See comment on mAppliedLastTransaction
675         t->setApplyToken(mApplyToken).apply(false, true);
676         mAppliedLastTransaction = true;
677         mLastAppliedFrameNumber = bufferItem.mFrameNumber;
678     } else {
679         t->setBufferHasBarrier(mSurfaceControl, mLastAppliedFrameNumber);
680         mAppliedLastTransaction = false;
681     }
682 
683     BQA_LOGV("acquireNextBufferLocked size=%dx%d mFrameNumber=%" PRIu64
684              " applyTransaction=%s mTimestamp=%" PRId64 "%s mPendingTransactions.size=%d"
685              " graphicBufferId=%" PRIu64 "%s transform=%d",
686              mSize.width, mSize.height, bufferItem.mFrameNumber, boolToString(applyTransaction),
687              bufferItem.mTimestamp, bufferItem.mIsAutoTimestamp ? "(auto)" : "",
688              static_cast<uint32_t>(mPendingTransactions.size()), bufferItem.mGraphicBuffer->getId(),
689              bufferItem.mAutoRefresh ? " mAutoRefresh" : "", bufferItem.mTransform);
690     return OK;
691 }
692 
computeCrop(const BufferItem & item)693 Rect BLASTBufferQueue::computeCrop(const BufferItem& item) {
694     if (item.mScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) {
695         return GLConsumer::scaleDownCrop(item.mCrop, mSize.width, mSize.height);
696     }
697     return item.mCrop;
698 }
699 
acquireAndReleaseBuffer()700 void BLASTBufferQueue::acquireAndReleaseBuffer() {
701     BBQ_TRACE();
702     BufferItem bufferItem;
703     status_t status =
704             mBufferItemConsumer->acquireBuffer(&bufferItem, 0 /* expectedPresent */, false);
705     if (status != OK) {
706         BQA_LOGE("Failed to acquire a buffer in acquireAndReleaseBuffer, err=%s",
707                  statusToString(status).c_str());
708         return;
709     }
710     mNumFrameAvailable--;
711     mBufferItemConsumer->releaseBuffer(bufferItem, bufferItem.mFence);
712 }
713 
onFrameAvailable(const BufferItem & item)714 void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) {
715     std::function<void(SurfaceComposerClient::Transaction*)> prevCallback = nullptr;
716     SurfaceComposerClient::Transaction* prevTransaction = nullptr;
717 
718     {
719         UNIQUE_LOCK_WITH_ASSERTION(mMutex);
720         BBQ_TRACE();
721         bool waitForTransactionCallback = !mSyncedFrameNumbers.empty();
722 
723         const bool syncTransactionSet = mTransactionReadyCallback != nullptr;
724         BQA_LOGV("onFrameAvailable-start syncTransactionSet=%s", boolToString(syncTransactionSet));
725 
726         if (syncTransactionSet) {
727             // If we are going to re-use the same mSyncTransaction, release the buffer that may
728             // already be set in the Transaction. This is to allow us a free slot early to continue
729             // processing a new buffer.
730             if (!mAcquireSingleBuffer) {
731                 auto bufferData = mSyncTransaction->getAndClearBuffer(mSurfaceControl);
732                 if (bufferData) {
733                     BQA_LOGD("Releasing previous buffer when syncing: framenumber=%" PRIu64,
734                              bufferData->frameNumber);
735                     releaseBuffer(bufferData->generateReleaseCallbackId(),
736                                   bufferData->acquireFence);
737                 }
738             }
739 
740             if (waitForTransactionCallback) {
741                 // We are waiting on a previous sync's transaction callback so allow another sync
742                 // transaction to proceed.
743                 //
744                 // We need to first flush out the transactions that were in between the two syncs.
745                 // We do this by merging them into mSyncTransaction so any buffer merging will get
746                 // a release callback invoked.
747                 while (mNumFrameAvailable > 0) {
748                     // flush out the shadow queue
749                     acquireAndReleaseBuffer();
750                 }
751             } else {
752                 // Make sure the frame available count is 0 before proceeding with a sync to ensure
753                 // the correct frame is used for the sync. The only way mNumFrameAvailable would be
754                 // greater than 0 is if we already ran out of buffers previously. This means we
755                 // need to flush the buffers before proceeding with the sync.
756                 while (mNumFrameAvailable > 0) {
757                     BQA_LOGD("waiting until no queued buffers");
758                     mCallbackCV.wait(_lock);
759                 }
760             }
761         }
762 
763         // add to shadow queue
764         mNumFrameAvailable++;
765         if (waitForTransactionCallback && mNumFrameAvailable >= 2) {
766             acquireAndReleaseBuffer();
767         }
768         ATRACE_INT(mQueuedBufferTrace.c_str(),
769                    mNumFrameAvailable + mNumAcquired - mPendingRelease.size());
770 
771         BQA_LOGV("onFrameAvailable framenumber=%" PRIu64 " syncTransactionSet=%s",
772                  item.mFrameNumber, boolToString(syncTransactionSet));
773 
774         if (syncTransactionSet) {
775             // Add to mSyncedFrameNumbers before waiting in case any buffers are released
776             // while waiting for a free buffer. The release and commit callback will try to
777             // acquire buffers if there are any available, but we don't want it to acquire
778             // in the case where a sync transaction wants the buffer.
779             mSyncedFrameNumbers.emplace(item.mFrameNumber);
780             // If there's no available buffer and we're in a sync transaction, we need to wait
781             // instead of returning since we guarantee a buffer will be acquired for the sync.
782             while (acquireNextBufferLocked(mSyncTransaction) == BufferQueue::NO_BUFFER_AVAILABLE) {
783                 BQA_LOGD("waiting for available buffer");
784                 mCallbackCV.wait(_lock);
785             }
786 
787             // Only need a commit callback when syncing to ensure the buffer that's synced has been
788             // sent to SF
789             incStrong((void*)transactionCommittedCallbackThunk);
790             mSyncTransaction->addTransactionCommittedCallback(transactionCommittedCallbackThunk,
791                                                               static_cast<void*>(this));
792             if (mAcquireSingleBuffer) {
793                 prevCallback = mTransactionReadyCallback;
794                 prevTransaction = mSyncTransaction;
795                 mTransactionReadyCallback = nullptr;
796                 mSyncTransaction = nullptr;
797             }
798         } else if (!waitForTransactionCallback) {
799             acquireNextBufferLocked(std::nullopt);
800         }
801     }
802     if (prevCallback) {
803         prevCallback(prevTransaction);
804     }
805 }
806 
onFrameReplaced(const BufferItem & item)807 void BLASTBufferQueue::onFrameReplaced(const BufferItem& item) {
808     BQA_LOGV("onFrameReplaced framenumber=%" PRIu64, item.mFrameNumber);
809     // Do nothing since we are not storing unacquired buffer items locally.
810 }
811 
onFrameDequeued(const uint64_t bufferId)812 void BLASTBufferQueue::onFrameDequeued(const uint64_t bufferId) {
813     std::lock_guard _lock{mTimestampMutex};
814     mDequeueTimestamps[bufferId] = systemTime();
815 };
816 
onFrameCancelled(const uint64_t bufferId)817 void BLASTBufferQueue::onFrameCancelled(const uint64_t bufferId) {
818     std::lock_guard _lock{mTimestampMutex};
819     mDequeueTimestamps.erase(bufferId);
820 };
821 
syncNextTransaction(std::function<void (SurfaceComposerClient::Transaction *)> callback,bool acquireSingleBuffer)822 bool BLASTBufferQueue::syncNextTransaction(
823         std::function<void(SurfaceComposerClient::Transaction*)> callback,
824         bool acquireSingleBuffer) {
825     LOG_ALWAYS_FATAL_IF(!callback,
826                         "BLASTBufferQueue: callback passed in to syncNextTransaction must not be "
827                         "NULL");
828 
829     std::lock_guard _lock{mMutex};
830     BBQ_TRACE();
831     if (mTransactionReadyCallback) {
832         ALOGW("Attempting to overwrite transaction callback in syncNextTransaction");
833         return false;
834     }
835 
836     mTransactionReadyCallback = callback;
837     mSyncTransaction = new SurfaceComposerClient::Transaction();
838     mAcquireSingleBuffer = acquireSingleBuffer;
839     return true;
840 }
841 
stopContinuousSyncTransaction()842 void BLASTBufferQueue::stopContinuousSyncTransaction() {
843     std::function<void(SurfaceComposerClient::Transaction*)> prevCallback = nullptr;
844     SurfaceComposerClient::Transaction* prevTransaction = nullptr;
845     {
846         std::lock_guard _lock{mMutex};
847         if (mAcquireSingleBuffer || !mTransactionReadyCallback) {
848             ALOGW("Attempting to stop continuous sync when none are active");
849             return;
850         }
851 
852         prevCallback = mTransactionReadyCallback;
853         prevTransaction = mSyncTransaction;
854 
855         mTransactionReadyCallback = nullptr;
856         mSyncTransaction = nullptr;
857         mAcquireSingleBuffer = true;
858     }
859 
860     if (prevCallback) {
861         prevCallback(prevTransaction);
862     }
863 }
864 
clearSyncTransaction()865 void BLASTBufferQueue::clearSyncTransaction() {
866     std::lock_guard _lock{mMutex};
867     if (!mAcquireSingleBuffer) {
868         ALOGW("Attempting to clear sync transaction when none are active");
869         return;
870     }
871 
872     mTransactionReadyCallback = nullptr;
873     mSyncTransaction = nullptr;
874 }
875 
rejectBuffer(const BufferItem & item)876 bool BLASTBufferQueue::rejectBuffer(const BufferItem& item) {
877     if (item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE) {
878         // Only reject buffers if scaling mode is freeze.
879         return false;
880     }
881 
882     ui::Size bufferSize = getBufferSize(item);
883     if (mRequestedSize != mSize && mRequestedSize == bufferSize) {
884         return false;
885     }
886 
887     // reject buffers if the buffer size doesn't match.
888     return mSize != bufferSize;
889 }
890 
891 class BBQSurface : public Surface {
892 private:
893     std::mutex mMutex;
894     sp<BLASTBufferQueue> mBbq GUARDED_BY(mMutex);
895     bool mDestroyed GUARDED_BY(mMutex) = false;
896 
897 public:
BBQSurface(const sp<IGraphicBufferProducer> & igbp,bool controlledByApp,const sp<IBinder> & scHandle,const sp<BLASTBufferQueue> & bbq)898     BBQSurface(const sp<IGraphicBufferProducer>& igbp, bool controlledByApp,
899                const sp<IBinder>& scHandle, const sp<BLASTBufferQueue>& bbq)
900           : Surface(igbp, controlledByApp, scHandle), mBbq(bbq) {}
901 
allocateBuffers()902     void allocateBuffers() override {
903         uint32_t reqWidth = mReqWidth ? mReqWidth : mUserWidth;
904         uint32_t reqHeight = mReqHeight ? mReqHeight : mUserHeight;
905         auto gbp = getIGraphicBufferProducer();
906         std::thread ([reqWidth, reqHeight, gbp=getIGraphicBufferProducer(),
907                       reqFormat=mReqFormat, reqUsage=mReqUsage] () {
908             gbp->allocateBuffers(reqWidth, reqHeight,
909                                  reqFormat, reqUsage);
910 
911         }).detach();
912     }
913 
setFrameRate(float frameRate,int8_t compatibility,int8_t changeFrameRateStrategy)914     status_t setFrameRate(float frameRate, int8_t compatibility,
915                           int8_t changeFrameRateStrategy) override {
916         if (flags::bq_setframerate()) {
917             return Surface::setFrameRate(frameRate, compatibility, changeFrameRateStrategy);
918         }
919 
920         std::lock_guard _lock{mMutex};
921         if (mDestroyed) {
922             return DEAD_OBJECT;
923         }
924         if (!ValidateFrameRate(frameRate, compatibility, changeFrameRateStrategy,
925                                "BBQSurface::setFrameRate")) {
926             return BAD_VALUE;
927         }
928         return mBbq->setFrameRate(frameRate, compatibility, changeFrameRateStrategy);
929     }
930 
setFrameTimelineInfo(uint64_t frameNumber,const FrameTimelineInfo & frameTimelineInfo)931     status_t setFrameTimelineInfo(uint64_t frameNumber,
932                                   const FrameTimelineInfo& frameTimelineInfo) override {
933         std::lock_guard _lock{mMutex};
934         if (mDestroyed) {
935             return DEAD_OBJECT;
936         }
937         return mBbq->setFrameTimelineInfo(frameNumber, frameTimelineInfo);
938     }
939 
destroy()940     void destroy() override {
941         Surface::destroy();
942 
943         std::lock_guard _lock{mMutex};
944         mDestroyed = true;
945         mBbq = nullptr;
946     }
947 };
948 
949 // TODO: Can we coalesce this with frame updates? Need to confirm
950 // no timing issues.
setFrameRate(float frameRate,int8_t compatibility,bool shouldBeSeamless)951 status_t BLASTBufferQueue::setFrameRate(float frameRate, int8_t compatibility,
952                                         bool shouldBeSeamless) {
953     std::lock_guard _lock{mMutex};
954     SurfaceComposerClient::Transaction t;
955 
956     return t.setFrameRate(mSurfaceControl, frameRate, compatibility, shouldBeSeamless).apply();
957 }
958 
setFrameTimelineInfo(uint64_t frameNumber,const FrameTimelineInfo & frameTimelineInfo)959 status_t BLASTBufferQueue::setFrameTimelineInfo(uint64_t frameNumber,
960                                                 const FrameTimelineInfo& frameTimelineInfo) {
961     ATRACE_FORMAT("%s(%s) frameNumber: %" PRIu64 " vsyncId: %" PRId64, __func__, mName.c_str(),
962                   frameNumber, frameTimelineInfo.vsyncId);
963     std::lock_guard _lock{mMutex};
964     mPendingFrameTimelines.push({frameNumber, frameTimelineInfo});
965     return OK;
966 }
967 
setSidebandStream(const sp<NativeHandle> & stream)968 void BLASTBufferQueue::setSidebandStream(const sp<NativeHandle>& stream) {
969     std::lock_guard _lock{mMutex};
970     SurfaceComposerClient::Transaction t;
971 
972     t.setSidebandStream(mSurfaceControl, stream).apply();
973 }
974 
getSurface(bool includeSurfaceControlHandle)975 sp<Surface> BLASTBufferQueue::getSurface(bool includeSurfaceControlHandle) {
976     std::lock_guard _lock{mMutex};
977     sp<IBinder> scHandle = nullptr;
978     if (includeSurfaceControlHandle && mSurfaceControl) {
979         scHandle = mSurfaceControl->getHandle();
980     }
981     return new BBQSurface(mProducer, true, scHandle, this);
982 }
983 
mergeWithNextTransaction(SurfaceComposerClient::Transaction * t,uint64_t frameNumber)984 void BLASTBufferQueue::mergeWithNextTransaction(SurfaceComposerClient::Transaction* t,
985                                                 uint64_t frameNumber) {
986     std::lock_guard _lock{mMutex};
987     if (mLastAcquiredFrameNumber >= frameNumber) {
988         // Apply the transaction since we have already acquired the desired frame.
989         t->apply();
990     } else {
991         mPendingTransactions.emplace_back(frameNumber, *t);
992         // Clear the transaction so it can't be applied elsewhere.
993         t->clear();
994     }
995 }
996 
applyPendingTransactions(uint64_t frameNumber)997 void BLASTBufferQueue::applyPendingTransactions(uint64_t frameNumber) {
998     std::lock_guard _lock{mMutex};
999 
1000     SurfaceComposerClient::Transaction t;
1001     mergePendingTransactions(&t, frameNumber);
1002     // All transactions on our apply token are one-way. See comment on mAppliedLastTransaction
1003     t.setApplyToken(mApplyToken).apply(false, true);
1004 }
1005 
mergePendingTransactions(SurfaceComposerClient::Transaction * t,uint64_t frameNumber)1006 void BLASTBufferQueue::mergePendingTransactions(SurfaceComposerClient::Transaction* t,
1007                                                 uint64_t frameNumber) {
1008     auto mergeTransaction =
1009             [&t, currentFrameNumber = frameNumber](
1010                     std::tuple<uint64_t, SurfaceComposerClient::Transaction> pendingTransaction) {
1011                 auto& [targetFrameNumber, transaction] = pendingTransaction;
1012                 if (currentFrameNumber < targetFrameNumber) {
1013                     return false;
1014                 }
1015                 t->merge(std::move(transaction));
1016                 return true;
1017             };
1018 
1019     mPendingTransactions.erase(std::remove_if(mPendingTransactions.begin(),
1020                                               mPendingTransactions.end(), mergeTransaction),
1021                                mPendingTransactions.end());
1022 }
1023 
gatherPendingTransactions(uint64_t frameNumber)1024 SurfaceComposerClient::Transaction* BLASTBufferQueue::gatherPendingTransactions(
1025         uint64_t frameNumber) {
1026     std::lock_guard _lock{mMutex};
1027     SurfaceComposerClient::Transaction* t = new SurfaceComposerClient::Transaction();
1028     mergePendingTransactions(t, frameNumber);
1029     return t;
1030 }
1031 
1032 // Maintains a single worker thread per process that services a list of runnables.
1033 class AsyncWorker : public Singleton<AsyncWorker> {
1034 private:
1035     std::thread mThread;
1036     bool mDone = false;
1037     std::deque<std::function<void()>> mRunnables;
1038     std::mutex mMutex;
1039     std::condition_variable mCv;
run()1040     void run() {
1041         std::unique_lock<std::mutex> lock(mMutex);
1042         while (!mDone) {
1043             while (!mRunnables.empty()) {
1044                 std::deque<std::function<void()>> runnables = std::move(mRunnables);
1045                 mRunnables.clear();
1046                 lock.unlock();
1047                 // Run outside the lock since the runnable might trigger another
1048                 // post to the async worker.
1049                 execute(runnables);
1050                 lock.lock();
1051             }
1052             mCv.wait(lock);
1053         }
1054     }
1055 
execute(std::deque<std::function<void ()>> & runnables)1056     void execute(std::deque<std::function<void()>>& runnables) {
1057         while (!runnables.empty()) {
1058             std::function<void()> runnable = runnables.front();
1059             runnables.pop_front();
1060             runnable();
1061         }
1062     }
1063 
1064 public:
AsyncWorker()1065     AsyncWorker() : Singleton<AsyncWorker>() { mThread = std::thread(&AsyncWorker::run, this); }
1066 
~AsyncWorker()1067     ~AsyncWorker() {
1068         mDone = true;
1069         mCv.notify_all();
1070         if (mThread.joinable()) {
1071             mThread.join();
1072         }
1073     }
1074 
post(std::function<void ()> runnable)1075     void post(std::function<void()> runnable) {
1076         std::unique_lock<std::mutex> lock(mMutex);
1077         mRunnables.emplace_back(std::move(runnable));
1078         mCv.notify_one();
1079     }
1080 };
1081 ANDROID_SINGLETON_STATIC_INSTANCE(AsyncWorker);
1082 
1083 // Asynchronously calls ProducerListener functions so we can emulate one way binder calls.
1084 class AsyncProducerListener : public BnProducerListener {
1085 private:
1086     const sp<IProducerListener> mListener;
1087 
1088 public:
AsyncProducerListener(const sp<IProducerListener> & listener)1089     AsyncProducerListener(const sp<IProducerListener>& listener) : mListener(listener) {}
1090 
onBufferReleased()1091     void onBufferReleased() override {
1092         AsyncWorker::getInstance().post([listener = mListener]() { listener->onBufferReleased(); });
1093     }
1094 
onBuffersDiscarded(const std::vector<int32_t> & slots)1095     void onBuffersDiscarded(const std::vector<int32_t>& slots) override {
1096         AsyncWorker::getInstance().post(
1097                 [listener = mListener, slots = slots]() { listener->onBuffersDiscarded(slots); });
1098     }
1099 };
1100 
1101 // Extends the BufferQueueProducer to create a wrapper around the listener so the listener calls
1102 // can be non-blocking when the producer is in the client process.
1103 class BBQBufferQueueProducer : public BufferQueueProducer {
1104 public:
BBQBufferQueueProducer(const sp<BufferQueueCore> & core,wp<BLASTBufferQueue> bbq)1105     BBQBufferQueueProducer(const sp<BufferQueueCore>& core, wp<BLASTBufferQueue> bbq)
1106           : BufferQueueProducer(core, false /* consumerIsSurfaceFlinger*/),
1107             mBLASTBufferQueue(std::move(bbq)) {}
1108 
connect(const sp<IProducerListener> & listener,int api,bool producerControlledByApp,QueueBufferOutput * output)1109     status_t connect(const sp<IProducerListener>& listener, int api, bool producerControlledByApp,
1110                      QueueBufferOutput* output) override {
1111         if (!listener) {
1112             return BufferQueueProducer::connect(listener, api, producerControlledByApp, output);
1113         }
1114 
1115         return BufferQueueProducer::connect(new AsyncProducerListener(listener), api,
1116                                             producerControlledByApp, output);
1117     }
1118 
1119     // We want to resize the frame history when changing the size of the buffer queue
setMaxDequeuedBufferCount(int maxDequeuedBufferCount)1120     status_t setMaxDequeuedBufferCount(int maxDequeuedBufferCount) override {
1121         int maxBufferCount;
1122         status_t status = BufferQueueProducer::setMaxDequeuedBufferCount(maxDequeuedBufferCount,
1123                                                                          &maxBufferCount);
1124         // if we can't determine the max buffer count, then just skip growing the history size
1125         if (status == OK) {
1126             size_t newFrameHistorySize = maxBufferCount + 2; // +2 because triple buffer rendering
1127             // optimize away resizing the frame history unless it will grow
1128             if (newFrameHistorySize > FrameEventHistory::INITIAL_MAX_FRAME_HISTORY) {
1129                 sp<BLASTBufferQueue> bbq = mBLASTBufferQueue.promote();
1130                 if (bbq != nullptr) {
1131                     ALOGV("increasing frame history size to %zu", newFrameHistorySize);
1132                     bbq->resizeFrameEventHistory(newFrameHistorySize);
1133                 }
1134             }
1135         }
1136         return status;
1137     }
1138 
query(int what,int * value)1139     int query(int what, int* value) override {
1140         if (what == NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER) {
1141             *value = 1;
1142             return NO_ERROR;
1143         }
1144         return BufferQueueProducer::query(what, value);
1145     }
1146 
1147 private:
1148     const wp<BLASTBufferQueue> mBLASTBufferQueue;
1149 };
1150 
1151 // Similar to BufferQueue::createBufferQueue but creates an adapter specific bufferqueue producer.
1152 // This BQP allows invoking client specified ProducerListeners and invoke them asynchronously,
1153 // emulating one way binder call behavior. Without this, if the listener calls back into the queue,
1154 // we can deadlock.
createBufferQueue(sp<IGraphicBufferProducer> * outProducer,sp<IGraphicBufferConsumer> * outConsumer)1155 void BLASTBufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
1156                                          sp<IGraphicBufferConsumer>* outConsumer) {
1157     LOG_ALWAYS_FATAL_IF(outProducer == nullptr, "BLASTBufferQueue: outProducer must not be NULL");
1158     LOG_ALWAYS_FATAL_IF(outConsumer == nullptr, "BLASTBufferQueue: outConsumer must not be NULL");
1159 
1160     sp<BufferQueueCore> core(new BufferQueueCore());
1161     LOG_ALWAYS_FATAL_IF(core == nullptr, "BLASTBufferQueue: failed to create BufferQueueCore");
1162 
1163     sp<IGraphicBufferProducer> producer(new BBQBufferQueueProducer(core, this));
1164     LOG_ALWAYS_FATAL_IF(producer == nullptr,
1165                         "BLASTBufferQueue: failed to create BBQBufferQueueProducer");
1166 
1167     sp<BufferQueueConsumer> consumer(new BufferQueueConsumer(core));
1168     consumer->setAllowExtraAcquire(true);
1169     LOG_ALWAYS_FATAL_IF(consumer == nullptr,
1170                         "BLASTBufferQueue: failed to create BufferQueueConsumer");
1171 
1172     *outProducer = producer;
1173     *outConsumer = consumer;
1174 }
1175 
resizeFrameEventHistory(size_t newSize)1176 void BLASTBufferQueue::resizeFrameEventHistory(size_t newSize) {
1177     // This can be null during creation of the buffer queue, but resizing won't do anything at that
1178     // point in time, so just ignore. This can go away once the class relationships and lifetimes of
1179     // objects are cleaned up with a major refactor of BufferQueue as a whole.
1180     if (mBufferItemConsumer != nullptr) {
1181         std::unique_lock _lock{mMutex};
1182         mBufferItemConsumer->resizeFrameEventHistory(newSize);
1183     }
1184 }
1185 
convertBufferFormat(PixelFormat & format)1186 PixelFormat BLASTBufferQueue::convertBufferFormat(PixelFormat& format) {
1187     PixelFormat convertedFormat = format;
1188     switch (format) {
1189         case PIXEL_FORMAT_TRANSPARENT:
1190         case PIXEL_FORMAT_TRANSLUCENT:
1191             convertedFormat = PIXEL_FORMAT_RGBA_8888;
1192             break;
1193         case PIXEL_FORMAT_OPAQUE:
1194             convertedFormat = PIXEL_FORMAT_RGBX_8888;
1195             break;
1196     }
1197     return convertedFormat;
1198 }
1199 
getLastTransformHint() const1200 uint32_t BLASTBufferQueue::getLastTransformHint() const {
1201     std::lock_guard _lock{mMutex};
1202     if (mSurfaceControl != nullptr) {
1203         return mSurfaceControl->getTransformHint();
1204     } else {
1205         return 0;
1206     }
1207 }
1208 
getLastAcquiredFrameNum()1209 uint64_t BLASTBufferQueue::getLastAcquiredFrameNum() {
1210     std::lock_guard _lock{mMutex};
1211     return mLastAcquiredFrameNumber;
1212 }
1213 
isSameSurfaceControl(const sp<SurfaceControl> & surfaceControl) const1214 bool BLASTBufferQueue::isSameSurfaceControl(const sp<SurfaceControl>& surfaceControl) const {
1215     std::lock_guard _lock{mMutex};
1216     return SurfaceControl::isSameSurface(mSurfaceControl, surfaceControl);
1217 }
1218 
setTransactionHangCallback(std::function<void (const std::string &)> callback)1219 void BLASTBufferQueue::setTransactionHangCallback(
1220         std::function<void(const std::string&)> callback) {
1221     std::lock_guard _lock{mMutex};
1222     mTransactionHangCallback = callback;
1223 }
1224 
1225 } // namespace android
1226