blast: Send transaction callback

Send transaction callback to client via the
TransactionCompletedListener.

Test: Transaction_test
Bug: 80477568

Change-Id: Iac98780b1357b9cc54b93cc3c848013b28fab441
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 0e14d8c..adc91a7 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -64,6 +64,12 @@
     return hasFrameUpdate();
 }
 
+bool BufferStateLayer::willPresentCurrentTransaction() const {
+    // Returns true if the most recent Transaction applied to CurrentState will be presented.
+    return getSidebandStreamChanged() || getAutoRefresh() ||
+            (mCurrentState.modified && mCurrentState.buffer != nullptr);
+}
+
 bool BufferStateLayer::getTransformToDisplayInverse() const {
     return mCurrentState.transformToDisplayInverse;
 }
@@ -183,6 +189,34 @@
     return true;
 }
 
+bool BufferStateLayer::setTransactionCompletedListeners(
+        const std::vector<sp<CallbackHandle>>& handles) {
+    // If there is no handle, we will not send a callback
+    if (handles.empty()) {
+        return false;
+    }
+
+    const bool willPresent = willPresentCurrentTransaction();
+
+    for (const auto& handle : handles) {
+        // If this layer will be presented in this frame
+        if (willPresent) {
+            // Notify the transaction completed thread that there is a pending latched callback
+            // handle
+            mFlinger->getTransactionCompletedThread().registerPendingLatchedCallbackHandle(handle);
+
+            // Store so latched time and release fence can be set
+            mCurrentState.callbackHandles.push_back(handle);
+
+        } else { // If this layer will NOT need to be relatched and presented this frame
+            // Notify the transaction completed thread this handle is done
+            mFlinger->getTransactionCompletedThread().addUnlatchedCallbackHandle(handle);
+        }
+    }
+
+    return willPresent;
+}
+
 bool BufferStateLayer::setSize(uint32_t w, uint32_t h) {
     if (mCurrentState.active.w == w && mCurrentState.active.h == h) return false;
     mCurrentState.active.w = w;
@@ -404,6 +438,9 @@
         return BAD_VALUE;
     }
 
+    mFlinger->getTransactionCompletedThread().addLatchedCallbackHandles(
+            getDrawingState().callbackHandles);
+
     // Handle sync fences
     if (SyncFeatures::getInstance().useNativeFenceSync() && releaseFence != Fence::NO_FENCE) {
         // TODO(alecmouri): Fail somewhere upstream if the fence is invalid.