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