@@ -52,19 +52,18 @@ using namespace std::chrono_literals;
5252namespace {
5353
5454#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
55- // RAII wrapper to defer arbitrary work until the Deferred instance is deleted.
56- template <class F >
57- class Deferred {
55+ template <class Mutex >
56+ class UnlockGuard {
5857public:
59- explicit Deferred (F f ) : mF{ std::move (f) } {}
58+ explicit UnlockGuard (Mutex& lock ) : mLock{lock } { mLock . unlock (); }
6059
61- ~Deferred () { mF (); }
60+ ~UnlockGuard () { mLock . lock (); }
6261
63- Deferred (const Deferred &) = delete ;
64- Deferred & operator =(const Deferred &) = delete ;
62+ UnlockGuard (const UnlockGuard &) = delete ;
63+ UnlockGuard & operator =(const UnlockGuard &) = delete ;
6564
6665private:
67- F mF ;
66+ Mutex& mLock ;
6867};
6968#endif
7069
@@ -271,9 +270,6 @@ BLASTBufferQueue::~BLASTBufferQueue() {
271270void BLASTBufferQueue::onFirstRef () {
272271 // safe default, most producers are expected to override this
273272 mProducer ->setMaxDequeuedBufferCount (2 );
274- #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
275- mBufferReleaseThread .emplace (sp<BLASTBufferQueue>::fromExisting (this ));
276- #endif
277273}
278274
279275void BLASTBufferQueue::update (const sp<SurfaceControl>& surface, uint32_t width, uint32_t height,
@@ -297,11 +293,16 @@ void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width,
297293 mSurfaceControl = surface;
298294 SurfaceComposerClient::Transaction t;
299295 if (surfaceControlChanged) {
300- t.setFlags (mSurfaceControl , layer_state_t ::eEnableBackpressure,
301- layer_state_t ::eEnableBackpressure);
302296#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
303- t.setBufferReleaseChannel (mSurfaceControl , mBufferReleaseProducer );
297+ // SELinux policy may prevent this process from sending the BufferReleaseChannel's file
298+ // descriptor to SurfaceFlinger, causing the entire transaction to be dropped. This
299+ // transaction is applied separately to ensure we don't lose the other updates.
300+ t.setApplyToken (mApplyToken )
301+ .setBufferReleaseChannel (mSurfaceControl , mBufferReleaseProducer )
302+ .apply (false /* synchronous */ , true /* oneWay */ );
304303#endif
304+ t.setFlags (mSurfaceControl , layer_state_t ::eEnableBackpressure,
305+ layer_state_t ::eEnableBackpressure);
305306 applyTransaction = true ;
306307 }
307308 mTransformHint = mSurfaceControl ->getTransformHint ();
@@ -325,7 +326,7 @@ void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width,
325326 }
326327 if (applyTransaction) {
327328 // All transactions on our apply token are one-way. See comment on mAppliedLastTransaction
328- t.setApplyToken (mApplyToken ).apply (false , true );
329+ t.setApplyToken (mApplyToken ).apply (false /* synchronous */ , true /* oneWay */ );
329330 }
330331}
331332
@@ -419,7 +420,6 @@ void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence
419420 stat.latchTime ,
420421 stat.frameEventStats .dequeueReadyTime );
421422 }
422- #if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
423423 auto currFrameNumber = stat.frameEventStats .frameNumber ;
424424 std::vector<ReleaseCallbackId> staleReleases;
425425 for (const auto & [key, value]: mSubmitted ) {
@@ -435,7 +435,6 @@ void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence
435435 stat.currentMaxAcquiredBufferCount ,
436436 true /* fakeRelease */ );
437437 }
438- #endif
439438 } else {
440439 BQA_LOGE (" Failed to find matching SurfaceControl in transactionCallback" );
441440 }
@@ -469,6 +468,9 @@ ReleaseBufferCallback BLASTBufferQueue::makeReleaseBufferCallbackThunk() {
469468 return ;
470469 }
471470 bbq->releaseBufferCallback (id, releaseFence, currentMaxAcquiredBufferCount);
471+ #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
472+ bbq->drainBufferReleaseConsumer ();
473+ #endif
472474 };
473475}
474476
@@ -535,8 +537,6 @@ void BLASTBufferQueue::releaseBuffer(const ReleaseCallbackId& callbackId,
535537 const sp<Fence>& releaseFence) {
536538 auto it = mSubmitted .find (callbackId);
537539 if (it == mSubmitted .end ()) {
538- BQA_LOGE (" ERROR: releaseBufferCallback without corresponding submitted buffer %s" ,
539- callbackId.to_string ().c_str ());
540540 return ;
541541 }
542542 mNumAcquired --;
@@ -646,12 +646,7 @@ status_t BLASTBufferQueue::acquireNextBufferLocked(
646646 bufferItem.mGraphicBuffer ->getHeight (), bufferItem.mTransform ,
647647 bufferItem.mScalingMode , crop);
648648
649- #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
650- ReleaseBufferCallback releaseBufferCallback =
651- applyTransaction ? nullptr : makeReleaseBufferCallbackThunk ();
652- #else
653649 auto releaseBufferCallback = makeReleaseBufferCallbackThunk ();
654- #endif
655650 sp<Fence> fence = bufferItem.mFence ? new Fence (bufferItem.mFence ->dup ()) : Fence::NO_FENCE;
656651
657652 nsecs_t dequeueTime = -1 ;
@@ -1230,12 +1225,7 @@ class BBQBufferQueueProducer : public BufferQueueProducer {
12301225 // we want to ignore it. This must be done before unlocking the BufferQueue lock to ensure
12311226 // we don't miss an interrupt.
12321227 bbq->mBufferReleaseReader ->clearInterrupts ();
1233- bbq->mThreadsBlockingOnDequeue ++;
1234- bufferQueueLock.unlock ();
1235- Deferred cleanup{[&]() {
1236- bufferQueueLock.lock ();
1237- bbq->mThreadsBlockingOnDequeue --;
1238- }};
1228+ UnlockGuard unlockGuard{bufferQueueLock};
12391229
12401230 ATRACE_FORMAT (" waiting for free buffer" );
12411231 ReleaseCallbackId id;
@@ -1345,6 +1335,21 @@ void BLASTBufferQueue::setApplyToken(sp<IBinder> applyToken) {
13451335
13461336#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
13471337
1338+ void BLASTBufferQueue::drainBufferReleaseConsumer () {
1339+ ATRACE_CALL ();
1340+ while (true ) {
1341+ ReleaseCallbackId id;
1342+ sp<Fence> fence;
1343+ uint32_t maxAcquiredBufferCount;
1344+ status_t status =
1345+ mBufferReleaseConsumer ->readReleaseFence (id, fence, maxAcquiredBufferCount);
1346+ if (status != OK) {
1347+ return ;
1348+ }
1349+ releaseBufferCallback (id, fence, maxAcquiredBufferCount);
1350+ }
1351+ }
1352+
13481353BLASTBufferQueue::BufferReleaseReader::BufferReleaseReader (BLASTBufferQueue& bbq) : mBbq{bbq} {
13491354 mEpollFd = android::base::unique_fd{epoll_create1 (EPOLL_CLOEXEC)};
13501355 LOG_ALWAYS_FATAL_IF (!mEpollFd .ok (),
@@ -1438,95 +1443,6 @@ void BLASTBufferQueue::BufferReleaseReader::clearInterrupts() {
14381443 }
14391444}
14401445
1441- BLASTBufferQueue::BufferReleaseThread::BufferReleaseThread (const sp<BLASTBufferQueue>& bbq) {
1442- android::base::unique_fd epollFd{epoll_create1 (EPOLL_CLOEXEC)};
1443- LOG_ALWAYS_FATAL_IF (!epollFd.ok (),
1444- " Failed to create buffer release background thread epoll file descriptor. "
1445- " errno=%d message='%s'" ,
1446- errno, strerror (errno));
1447-
1448- epoll_event registerEndpointFd{};
1449- registerEndpointFd.events = EPOLLIN;
1450- registerEndpointFd.data .fd = bbq->mBufferReleaseConsumer ->getFd ();
1451- status_t status = epoll_ctl (epollFd.get (), EPOLL_CTL_ADD, bbq->mBufferReleaseConsumer ->getFd (),
1452- ®isterEndpointFd);
1453- LOG_ALWAYS_FATAL_IF (status == -1 ,
1454- " Failed to register background thread buffer release consumer file "
1455- " descriptor with epoll. errno=%d message='%s'" ,
1456- errno, strerror (errno));
1457-
1458- // EventFd is used to break the background thread's loop.
1459- android::base::unique_fd eventFd{eventfd (0 , EFD_CLOEXEC | EFD_NONBLOCK)};
1460- LOG_ALWAYS_FATAL_IF (!eventFd.ok (),
1461- " Failed to create background thread buffer release event file descriptor. "
1462- " errno=%d message='%s'" ,
1463- errno, strerror (errno));
1464-
1465- epoll_event registerEventFd{};
1466- registerEventFd.events = EPOLLIN;
1467- registerEventFd.data .fd = eventFd.get ();
1468- status = epoll_ctl (epollFd.get (), EPOLL_CTL_ADD, eventFd.get (), ®isterEventFd);
1469- LOG_ALWAYS_FATAL_IF (status == -1 ,
1470- " Failed to register background thread event file descriptor with epoll. "
1471- " errno=%d message='%s'" ,
1472- errno, strerror (errno));
1473-
1474- mEventFd = eventFd.get ();
1475-
1476- std::thread ([epollFd = std::move (epollFd), eventFd = std::move (eventFd),
1477- weakBbq = wp<BLASTBufferQueue>(bbq)]() {
1478- pthread_setname_np (pthread_self (), " BufferReleaseThread" );
1479- while (true ) {
1480- epoll_event event{};
1481- int eventCount;
1482- do {
1483- eventCount = epoll_wait (epollFd.get (), &event, 1 /* maxevents*/ , -1 /* timeout*/ );
1484- } while (eventCount == -1 && errno != EINTR);
1485-
1486- if (eventCount == -1 ) {
1487- ALOGE (" epoll_wait error while waiting for buffer release in background thread. "
1488- " errno=%d message='%s'" ,
1489- errno, strerror (errno));
1490- continue ;
1491- }
1492-
1493- // EventFd is used to join this thread.
1494- if (event.data .fd == eventFd.get ()) {
1495- return ;
1496- }
1497-
1498- sp<BLASTBufferQueue> bbq = weakBbq.promote ();
1499- if (!bbq) {
1500- return ;
1501- }
1502-
1503- // If there are threads blocking on dequeue, give those threads priority for handling
1504- // the release.
1505- if (bbq->mThreadsBlockingOnDequeue > 0 ) {
1506- std::this_thread::sleep_for (0ms);
1507- continue ;
1508- }
1509-
1510- ReleaseCallbackId id;
1511- sp<Fence> fence;
1512- uint32_t maxAcquiredBufferCount;
1513- status_t status = bbq->mBufferReleaseConsumer ->readReleaseFence (id, fence,
1514- maxAcquiredBufferCount);
1515- if (status != OK) {
1516- ALOGE (" failed to read from buffer release consumer in background thread. errno=%d "
1517- " message='%s'" ,
1518- errno, strerror (errno));
1519- continue ;
1520- }
1521- bbq->releaseBufferCallback (id, fence, maxAcquiredBufferCount);
1522- }
1523- }).detach ();
1524- }
1525-
1526- BLASTBufferQueue::BufferReleaseThread::~BufferReleaseThread () {
1527- eventfd_write (mEventFd , 1 );
1528- }
1529-
15301446#endif
15311447
15321448} // namespace android
0 commit comments