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