Optimize BLAST buffer releases via Unix sockets

Bug: 294133380
Flag: com.android.graphics.libgui.flags.buffer_release_channel
Test: BLASTBufferQueueTest
Change-Id: Ia183452198dadc7f8e540f7219bd44d8b5823458
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index a6d2b15..082d8aa 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -2783,11 +2783,14 @@
         return;
     }
     SFTRACE_FORMAT_INSTANT("callReleaseBufferCallback %s - %" PRIu64, getDebugName(), framenumber);
+    ReleaseCallbackId callbackId{buffer->getId(), framenumber};
+    const sp<Fence>& fence = releaseFence ? releaseFence : Fence::NO_FENCE;
     uint32_t currentMaxAcquiredBufferCount =
             mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate(mOwnerUid);
-    listener->onReleaseBuffer({buffer->getId(), framenumber},
-                              releaseFence ? releaseFence : Fence::NO_FENCE,
-                              currentMaxAcquiredBufferCount);
+    listener->onReleaseBuffer(callbackId, fence, currentMaxAcquiredBufferCount);
+    if (mBufferReleaseChannel) {
+        mBufferReleaseChannel->writeReleaseFence(callbackId, fence);
+    }
 }
 
 sp<CallbackHandle> Layer::findCallbackHandle() {
@@ -2905,6 +2908,7 @@
 
 void Layer::releasePendingBuffer(nsecs_t dequeueReadyTime) {
     for (const auto& handle : mDrawingState.callbackHandles) {
+        handle->bufferReleaseChannel = mBufferReleaseChannel;
         handle->transformHint = mTransformHint;
         handle->dequeueReadyTime = dequeueReadyTime;
         handle->currentMaxAcquiredBufferCount =
@@ -4376,6 +4380,11 @@
     return haveTrustedPresentationListener;
 }
 
+void Layer::setBufferReleaseChannel(
+        const std::shared_ptr<gui::BufferReleaseChannel::ProducerEndpoint>& channel) {
+    mBufferReleaseChannel = channel;
+}
+
 void Layer::updateLastLatchTime(nsecs_t latchTime) {
     mLastLatchTime = latchTime;
 }
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 52f169e..d470738 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -550,6 +550,7 @@
     };
 
     BufferInfo mBufferInfo;
+    std::shared_ptr<gui::BufferReleaseChannel::ProducerEndpoint> mBufferReleaseChannel;
 
     // implements compositionengine::LayerFE
     const compositionengine::LayerFECompositionState* getCompositionState() const;
@@ -813,6 +814,8 @@
 
     bool setTrustedPresentationInfo(TrustedPresentationThresholds const& thresholds,
                                     TrustedPresentationListener const& listener);
+    void setBufferReleaseChannel(
+            const std::shared_ptr<gui::BufferReleaseChannel::ProducerEndpoint>& channel);
 
     // Creates a new handle each time, so we only expect
     // this to be called once.
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 1d35730..beb05b9 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -5951,6 +5951,10 @@
         }
     }
 
+    if (what & layer_state_t::eBufferReleaseChannelChanged) {
+        layer->setBufferReleaseChannel(s.bufferReleaseChannel);
+    }
+
     const auto& requestedLayerState = mLayerLifecycleManager.getLayerFromId(layer->getSequence());
     bool willPresentCurrentTransaction = requestedLayerState &&
             (requestedLayerState->hasReadyFrame() ||
diff --git a/services/surfaceflinger/TransactionCallbackInvoker.cpp b/services/surfaceflinger/TransactionCallbackInvoker.cpp
index 881bf35..9ea0f5f 100644
--- a/services/surfaceflinger/TransactionCallbackInvoker.cpp
+++ b/services/surfaceflinger/TransactionCallbackInvoker.cpp
@@ -149,6 +149,12 @@
                                                     handle->transformHint,
                                                     handle->currentMaxAcquiredBufferCount,
                                                     eventStats, handle->previousReleaseCallbackId);
+        if (handle->bufferReleaseChannel &&
+            handle->previousReleaseCallbackId != ReleaseCallbackId::INVALID_ID) {
+            mBufferReleases.emplace_back(handle->bufferReleaseChannel,
+                                         handle->previousReleaseCallbackId,
+                                         handle->previousReleaseFence);
+        }
     }
     return NO_ERROR;
 }
@@ -158,6 +164,11 @@
 }
 
 void TransactionCallbackInvoker::sendCallbacks(bool onCommitOnly) {
+    for (const auto& bufferRelease : mBufferReleases) {
+        bufferRelease.channel->writeReleaseFence(bufferRelease.callbackId, bufferRelease.fence);
+    }
+    mBufferReleases.clear();
+
     // For each listener
     auto completedTransactionsItr = mCompletedTransactions.begin();
     ftl::SmallVector<ListenerStats, 10> listenerStatsToSend;
diff --git a/services/surfaceflinger/TransactionCallbackInvoker.h b/services/surfaceflinger/TransactionCallbackInvoker.h
index 7853a9f..f74f964 100644
--- a/services/surfaceflinger/TransactionCallbackInvoker.h
+++ b/services/surfaceflinger/TransactionCallbackInvoker.h
@@ -28,6 +28,7 @@
 #include <android-base/thread_annotations.h>
 #include <binder/IBinder.h>
 #include <ftl/future.h>
+#include <gui/BufferReleaseChannel.h>
 #include <gui/ITransactionCompletedListener.h>
 #include <ui/Fence.h>
 #include <ui/FenceResult.h>
@@ -59,6 +60,7 @@
     uint64_t frameNumber = 0;
     uint64_t previousFrameNumber = 0;
     ReleaseCallbackId previousReleaseCallbackId = ReleaseCallbackId::INVALID_ID;
+    std::shared_ptr<gui::BufferReleaseChannel::ProducerEndpoint> bufferReleaseChannel;
 };
 
 class TransactionCallbackInvoker {
@@ -86,6 +88,13 @@
     std::unordered_map<sp<IBinder>, std::deque<TransactionStats>, IListenerHash>
         mCompletedTransactions;
 
+    struct BufferRelease {
+        std::shared_ptr<gui::BufferReleaseChannel::ProducerEndpoint> channel;
+        ReleaseCallbackId callbackId;
+        sp<Fence> fence;
+    };
+    std::vector<BufferRelease> mBufferReleases;
+
     sp<Fence> mPresentFence;
 };