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