Merge "SurfaceFlinger: Emit TransactionCompleted callbacks directly." into sc-dev
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 825626a..8d1258a 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -173,7 +173,7 @@
         "SurfaceFlingerDefaultFactory.cpp",
         "SurfaceInterceptor.cpp",
         "SurfaceTracing.cpp",
-        "TransactionCompletedThread.cpp",
+        "TransactionCallbackInvoker.cpp",
     ],
 }
 
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index e470eb9..cf87f62 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -190,7 +190,7 @@
                 JankData(surfaceFrame->getToken(), surfaceFrame->getJankType().value()));
     }
 
-    mFlinger->getTransactionCompletedThread().finalizePendingCallbackHandles(
+    mFlinger->getTransactionCallbackInvoker().finalizePendingCallbackHandles(
             mDrawingState.callbackHandles, jankData);
 
     mDrawingState.callbackHandles = {};
@@ -455,14 +455,14 @@
 
             // Notify the transaction completed thread that there is a pending latched callback
             // handle
-            mFlinger->getTransactionCompletedThread().registerPendingCallbackHandle(handle);
+            mFlinger->getTransactionCallbackInvoker().registerPendingCallbackHandle(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().registerUnpresentedCallbackHandle(handle);
+            mFlinger->getTransactionCallbackInvoker().registerUnpresentedCallbackHandle(handle);
         }
     }
 
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 9cd15e8..36ae19c 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -54,7 +54,7 @@
 #include "Scheduler/Seamlessness.h"
 #include "SurfaceFlinger.h"
 #include "SurfaceTracing.h"
-#include "TransactionCompletedThread.h"
+#include "TransactionCallbackInvoker.h"
 
 using namespace android::surfaceflinger;
 
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 689a302..77f4009 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2195,8 +2195,8 @@
         }
     });
 
-    mTransactionCompletedThread.addPresentFence(mPreviousPresentFences[0]);
-    mTransactionCompletedThread.sendCallbacks();
+    mTransactionCallbackInvoker.addPresentFence(mPreviousPresentFences[0]);
+    mTransactionCallbackInvoker.sendCallbacks();
 
     if (display && display->isPrimary() && display->getPowerMode() == hal::PowerMode::ON &&
         presentFenceTime->isValid()) {
@@ -3555,8 +3555,8 @@
     // that listeners with SurfaceControls will start registration during setClientStateLocked
     // below.
     for (const auto& listener : listenerCallbacks) {
-        mTransactionCompletedThread.startRegistration(listener);
-        mTransactionCompletedThread.endRegistration(listener);
+        mTransactionCallbackInvoker.startRegistration(listener);
+        mTransactionCallbackInvoker.endRegistration(listener);
     }
 
     std::unordered_set<ListenerCallbacks, ListenerCallbacksHash> listenerCallbacksWithSurfaces;
@@ -3575,12 +3575,12 @@
     }
 
     for (const auto& listenerCallback : listenerCallbacksWithSurfaces) {
-        mTransactionCompletedThread.endRegistration(listenerCallback);
+        mTransactionCallbackInvoker.endRegistration(listenerCallback);
     }
 
     // If the state doesn't require a traversal and there are callbacks, send them now
     if (!(clientStateFlags & eTraversalNeeded) && hasListenerCallbacks) {
-        mTransactionCompletedThread.sendCallbacks();
+        mTransactionCallbackInvoker.sendCallbacks();
     }
     transactionFlags |= clientStateFlags;
 
@@ -3695,7 +3695,7 @@
     for (auto& listener : s.listeners) {
         // note that startRegistration will not re-register if the listener has
         // already be registered for a prior surface control
-        mTransactionCompletedThread.startRegistration(listener);
+        mTransactionCallbackInvoker.startRegistration(listener);
         listenerCallbacks.insert(listener);
     }
 
@@ -3708,7 +3708,7 @@
     }
     if (layer == nullptr) {
         for (auto& [listener, callbackIds] : s.listeners) {
-            mTransactionCompletedThread.registerUnpresentedCallbackHandle(
+            mTransactionCallbackInvoker.registerUnpresentedCallbackHandle(
                     new CallbackHandle(listener, callbackIds, s.surface));
         }
         return 0;
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 400345f..f924f45 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -64,7 +64,7 @@
 #include "SurfaceFlingerFactory.h"
 #include "SurfaceTracing.h"
 #include "TracedOrdinal.h"
-#include "TransactionCompletedThread.h"
+#include "TransactionCallbackInvoker.h"
 
 #include <atomic>
 #include <cstdint>
@@ -319,8 +319,8 @@
 
     void removeFromOffscreenLayers(Layer* layer);
 
-    TransactionCompletedThread& getTransactionCompletedThread() {
-        return mTransactionCompletedThread;
+    TransactionCallbackInvoker& getTransactionCallbackInvoker() {
+        return mTransactionCallbackInvoker;
     }
 
     // Converts from a binder handle to a Layer
@@ -1161,7 +1161,7 @@
     std::atomic<uint32_t> mHwcFrameMissedCount = 0;
     std::atomic<uint32_t> mGpuFrameMissedCount = 0;
 
-    TransactionCompletedThread mTransactionCompletedThread;
+    TransactionCallbackInvoker mTransactionCallbackInvoker;
 
     // Restrict layers to use two buffers in their bufferqueues.
     bool mLayerTripleBufferingDisabled = false;
diff --git a/services/surfaceflinger/TransactionCallbackInvoker.cpp b/services/surfaceflinger/TransactionCallbackInvoker.cpp
new file mode 100644
index 0000000..a78510e
--- /dev/null
+++ b/services/surfaceflinger/TransactionCallbackInvoker.cpp
@@ -0,0 +1,298 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// TODO(b/129481165): remove the #pragma below and fix conversion issues
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wconversion"
+
+//#define LOG_NDEBUG 0
+#undef LOG_TAG
+#define LOG_TAG "TransactionCallbackInvoker"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include "TransactionCallbackInvoker.h"
+
+#include <cinttypes>
+
+#include <binder/IInterface.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+// Returns 0 if they are equal
+//         <0 if the first id that doesn't match is lower in c2 or all ids match but c2 is shorter
+//         >0 if the first id that doesn't match is greater in c2 or all ids match but c2 is longer
+//
+// See CallbackIdsHash for a explaniation of why this works
+static int compareCallbackIds(const std::vector<CallbackId>& c1,
+                              const std::vector<CallbackId>& c2) {
+    if (c1.empty()) {
+        return !c2.empty();
+    }
+    return c1.front() - c2.front();
+}
+
+TransactionCallbackInvoker::~TransactionCallbackInvoker() {
+    {
+        std::lock_guard lock(mMutex);
+        for (const auto& [listener, transactionStats] : mCompletedTransactions) {
+            listener->unlinkToDeath(mDeathRecipient);
+        }
+    }
+}
+
+status_t TransactionCallbackInvoker::startRegistration(const ListenerCallbacks& listenerCallbacks) {
+    std::lock_guard lock(mMutex);
+
+    auto [itr, inserted] = mRegisteringTransactions.insert(listenerCallbacks);
+    auto& [listener, callbackIds] = listenerCallbacks;
+
+    if (inserted) {
+        if (mCompletedTransactions.count(listener) == 0) {
+            status_t err = listener->linkToDeath(mDeathRecipient);
+            if (err != NO_ERROR) {
+                ALOGE("cannot add callback because linkToDeath failed, err: %d", err);
+                return err;
+            }
+        }
+        auto& transactionStatsDeque = mCompletedTransactions[listener];
+        transactionStatsDeque.emplace_back(callbackIds);
+    }
+
+    return NO_ERROR;
+}
+
+status_t TransactionCallbackInvoker::endRegistration(const ListenerCallbacks& listenerCallbacks) {
+    std::lock_guard lock(mMutex);
+
+    auto itr = mRegisteringTransactions.find(listenerCallbacks);
+    if (itr == mRegisteringTransactions.end()) {
+        ALOGE("cannot end a registration that does not exist");
+        return BAD_VALUE;
+    }
+
+    mRegisteringTransactions.erase(itr);
+
+    return NO_ERROR;
+}
+
+bool TransactionCallbackInvoker::isRegisteringTransaction(
+        const sp<IBinder>& transactionListener, const std::vector<CallbackId>& callbackIds) {
+    ListenerCallbacks listenerCallbacks(transactionListener, callbackIds);
+
+    auto itr = mRegisteringTransactions.find(listenerCallbacks);
+    return itr != mRegisteringTransactions.end();
+}
+
+status_t TransactionCallbackInvoker::registerPendingCallbackHandle(
+        const sp<CallbackHandle>& handle) {
+    std::lock_guard lock(mMutex);
+
+    // If we can't find the transaction stats something has gone wrong. The client should call
+    // startRegistration before trying to register a pending callback handle.
+    TransactionStats* transactionStats;
+    status_t err = findTransactionStats(handle->listener, handle->callbackIds, &transactionStats);
+    if (err != NO_ERROR) {
+        ALOGE("cannot find transaction stats");
+        return err;
+    }
+
+    mPendingTransactions[handle->listener][handle->callbackIds]++;
+    return NO_ERROR;
+}
+
+status_t TransactionCallbackInvoker::finalizePendingCallbackHandles(
+        const std::deque<sp<CallbackHandle>>& handles, const std::vector<JankData>& jankData) {
+    if (handles.empty()) {
+        return NO_ERROR;
+    }
+    std::lock_guard lock(mMutex);
+
+    for (const auto& handle : handles) {
+        auto listener = mPendingTransactions.find(handle->listener);
+        if (listener != mPendingTransactions.end()) {
+            auto& pendingCallbacks = listener->second;
+            auto pendingCallback = pendingCallbacks.find(handle->callbackIds);
+
+            if (pendingCallback != pendingCallbacks.end()) {
+                auto& pendingCount = pendingCallback->second;
+
+                // Decrease the pending count for this listener
+                if (--pendingCount == 0) {
+                    pendingCallbacks.erase(pendingCallback);
+                }
+            } else {
+                ALOGW("there are more latched callbacks than there were registered callbacks");
+            }
+            if (listener->second.size() == 0) {
+                mPendingTransactions.erase(listener);
+            }
+        } else {
+            ALOGW("cannot find listener in mPendingTransactions");
+        }
+
+        status_t err = addCallbackHandle(handle, jankData);
+        if (err != NO_ERROR) {
+            ALOGE("could not add callback handle");
+            return err;
+        }
+    }
+
+    return NO_ERROR;
+}
+
+status_t TransactionCallbackInvoker::registerUnpresentedCallbackHandle(
+        const sp<CallbackHandle>& handle) {
+    std::lock_guard lock(mMutex);
+
+    return addCallbackHandle(handle, std::vector<JankData>());
+}
+
+status_t TransactionCallbackInvoker::findTransactionStats(
+        const sp<IBinder>& listener, const std::vector<CallbackId>& callbackIds,
+        TransactionStats** outTransactionStats) {
+    auto& transactionStatsDeque = mCompletedTransactions[listener];
+
+    // Search back to front because the most recent transactions are at the back of the deque
+    auto itr = transactionStatsDeque.rbegin();
+    for (; itr != transactionStatsDeque.rend(); itr++) {
+        if (compareCallbackIds(itr->callbackIds, callbackIds) == 0) {
+            *outTransactionStats = &(*itr);
+            return NO_ERROR;
+        }
+    }
+
+    ALOGE("could not find transaction stats");
+    return BAD_VALUE;
+}
+
+status_t TransactionCallbackInvoker::addCallbackHandle(const sp<CallbackHandle>& handle,
+        const std::vector<JankData>& jankData) {
+    // If we can't find the transaction stats something has gone wrong. The client should call
+    // startRegistration before trying to add a callback handle.
+    TransactionStats* transactionStats;
+    status_t err = findTransactionStats(handle->listener, handle->callbackIds, &transactionStats);
+    if (err != NO_ERROR) {
+        return err;
+    }
+
+    transactionStats->latchTime = handle->latchTime;
+    // If the layer has already been destroyed, don't add the SurfaceControl to the callback.
+    // The client side keeps a sp<> to the SurfaceControl so if the SurfaceControl has been
+    // destroyed the client side is dead and there won't be anyone to send the callback to.
+    sp<IBinder> surfaceControl = handle->surfaceControl.promote();
+    if (surfaceControl) {
+        FrameEventHistoryStats eventStats(handle->frameNumber,
+                                          handle->gpuCompositionDoneFence->getSnapshot().fence,
+                                          handle->compositorTiming, handle->refreshStartTime,
+                                          handle->dequeueReadyTime);
+        transactionStats->surfaceStats.emplace_back(surfaceControl, handle->acquireTime,
+                                                    handle->previousReleaseFence,
+                                                    handle->transformHint, eventStats, jankData);
+    }
+    return NO_ERROR;
+}
+
+void TransactionCallbackInvoker::addPresentFence(const sp<Fence>& presentFence) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    mPresentFence = presentFence;
+}
+
+void TransactionCallbackInvoker::sendCallbacks() {
+    std::lock_guard lock(mMutex);
+
+    // For each listener
+    auto completedTransactionsItr = mCompletedTransactions.begin();
+    while (completedTransactionsItr != mCompletedTransactions.end()) {
+        auto& [listener, transactionStatsDeque] = *completedTransactionsItr;
+        ListenerStats listenerStats;
+        listenerStats.listener = listener;
+
+        // For each transaction
+        auto transactionStatsItr = transactionStatsDeque.begin();
+        while (transactionStatsItr != transactionStatsDeque.end()) {
+            auto& transactionStats = *transactionStatsItr;
+
+            // If this transaction is still registering, it is not safe to send a callback
+            // because there could be surface controls that haven't been added to
+            // transaction stats or mPendingTransactions.
+            if (isRegisteringTransaction(listener, transactionStats.callbackIds)) {
+                break;
+            }
+
+            // If we are still waiting on the callback handles for this transaction, stop
+            // here because all transaction callbacks for the same listener must come in order
+            auto pendingTransactions = mPendingTransactions.find(listener);
+            if (pendingTransactions != mPendingTransactions.end() &&
+                pendingTransactions->second.count(transactionStats.callbackIds) != 0) {
+                break;
+            }
+
+            // If the transaction has been latched
+            if (transactionStats.latchTime >= 0) {
+                if (!mPresentFence) {
+                    break;
+                }
+                transactionStats.presentFence = mPresentFence;
+            }
+
+            // Remove the transaction from completed to the callback
+            listenerStats.transactionStats.push_back(std::move(transactionStats));
+            transactionStatsItr = transactionStatsDeque.erase(transactionStatsItr);
+        }
+        // If the listener has completed transactions
+        if (!listenerStats.transactionStats.empty()) {
+            // If the listener is still alive
+            if (listener->isBinderAlive()) {
+                // Send callback.  The listener stored in listenerStats
+                // comes from the cross-process setTransactionState call to
+                // SF.  This MUST be an ITransactionCompletedListener.  We
+                // keep it as an IBinder due to consistency reasons: if we
+                // interface_cast at the IPC boundary when reading a Parcel,
+                // we get pointers that compare unequal in the SF process.
+                interface_cast<ITransactionCompletedListener>(listenerStats.listener)
+                        ->onTransactionCompleted(listenerStats);
+                if (transactionStatsDeque.empty()) {
+                    listener->unlinkToDeath(mDeathRecipient);
+                    completedTransactionsItr =
+                            mCompletedTransactions.erase(completedTransactionsItr);
+                } else {
+                    completedTransactionsItr++;
+                }
+            } else {
+                completedTransactionsItr =
+                        mCompletedTransactions.erase(completedTransactionsItr);
+            }
+        } else {
+            completedTransactionsItr++;
+        }
+    }
+
+    if (mPresentFence) {
+        mPresentFence.clear();
+    }
+}
+
+// -----------------------------------------------------------------------
+
+CallbackHandle::CallbackHandle(const sp<IBinder>& transactionListener,
+                               const std::vector<CallbackId>& ids, const sp<IBinder>& sc)
+      : listener(transactionListener), callbackIds(ids), surfaceControl(sc) {}
+
+} // namespace android
+
+// TODO(b/129481165): remove the #pragma below and fix conversion issues
+#pragma clang diagnostic pop // ignored "-Wconversion"
diff --git a/services/surfaceflinger/TransactionCompletedThread.h b/services/surfaceflinger/TransactionCallbackInvoker.h
similarity index 88%
rename from services/surfaceflinger/TransactionCompletedThread.h
rename to services/surfaceflinger/TransactionCallbackInvoker.h
index c4ba7e4..a240c82 100644
--- a/services/surfaceflinger/TransactionCompletedThread.h
+++ b/services/surfaceflinger/TransactionCallbackInvoker.h
@@ -52,11 +52,9 @@
     uint64_t frameNumber = 0;
 };
 
-class TransactionCompletedThread {
+class TransactionCallbackInvoker {
 public:
-    ~TransactionCompletedThread();
-
-    void run();
+    ~TransactionCallbackInvoker();
 
     // Adds listener and callbackIds in case there are no SurfaceControls that are supposed
     // to be included in the callback. This functions should be call before attempting to register
@@ -66,13 +64,13 @@
     // It is safe to send a callback if the Transaction doesn't have any Pending callback handles.
     status_t endRegistration(const ListenerCallbacks& listenerCallbacks);
 
-    // Informs the TransactionCompletedThread that there is a Transaction with a CallbackHandle
+    // Informs the TransactionCallbackInvoker that there is a Transaction with a CallbackHandle
     // that needs to be latched and presented this frame. This function should be called once the
-    // layer has received the CallbackHandle so the TransactionCompletedThread knows not to send
+    // layer has received the CallbackHandle so the TransactionCallbackInvoker knows not to send
     // a callback for that Listener/Transaction pair until that CallbackHandle has been latched and
     // presented.
     status_t registerPendingCallbackHandle(const sp<CallbackHandle>& handle);
-    // Notifies the TransactionCompletedThread that a pending CallbackHandle has been presented.
+    // Notifies the TransactionCallbackInvoker that a pending CallbackHandle has been presented.
     status_t finalizePendingCallbackHandles(const std::deque<sp<CallbackHandle>>& handles,
                                             const std::vector<JankData>& jankData);
 
@@ -85,7 +83,6 @@
     void sendCallbacks();
 
 private:
-    void threadMain();
 
     bool isRegisteringTransaction(const sp<IBinder>& transactionListener,
                                   const std::vector<CallbackId>& callbackIds) REQUIRES(mMutex);
@@ -97,7 +94,7 @@
     status_t addCallbackHandle(const sp<CallbackHandle>& handle,
                                const std::vector<JankData>& jankData) REQUIRES(mMutex);
 
-    class ThreadDeathRecipient : public IBinder::DeathRecipient {
+    class CallbackDeathRecipient : public IBinder::DeathRecipient {
     public:
         // This function is a no-op. isBinderAlive needs a linked DeathRecipient to work.
         // Death recipients needs a binderDied function.
@@ -106,12 +103,8 @@
         // sendObituary is only called if linkToDeath was called with a DeathRecipient.)
         void binderDied(const wp<IBinder>& /*who*/) override {}
     };
-    sp<ThreadDeathRecipient> mDeathRecipient;
-
-    // Protects the creation and destruction of mThread
-    std::mutex mThreadMutex;
-
-    std::thread mThread GUARDED_BY(mThreadMutex);
+    sp<CallbackDeathRecipient> mDeathRecipient =
+        new CallbackDeathRecipient();
 
     std::mutex mMutex;
     std::condition_variable_any mConditionVariable;
@@ -128,9 +121,6 @@
     std::unordered_map<sp<IBinder>, std::deque<TransactionStats>, IListenerHash>
             mCompletedTransactions GUARDED_BY(mMutex);
 
-    bool mRunning GUARDED_BY(mMutex) = false;
-    bool mKeepRunning GUARDED_BY(mMutex) = true;
-
     sp<Fence> mPresentFence GUARDED_BY(mMutex);
 };
 
diff --git a/services/surfaceflinger/TransactionCompletedThread.cpp b/services/surfaceflinger/TransactionCompletedThread.cpp
deleted file mode 100644
index 1797af4..0000000
--- a/services/surfaceflinger/TransactionCompletedThread.cpp
+++ /dev/null
@@ -1,372 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-
-//#define LOG_NDEBUG 0
-#undef LOG_TAG
-#define LOG_TAG "TransactionCompletedThread"
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-
-#include "TransactionCompletedThread.h"
-
-#include <cinttypes>
-
-#include <binder/IInterface.h>
-#include <utils/RefBase.h>
-
-namespace android {
-
-// Returns 0 if they are equal
-//         <0 if the first id that doesn't match is lower in c2 or all ids match but c2 is shorter
-//         >0 if the first id that doesn't match is greater in c2 or all ids match but c2 is longer
-//
-// See CallbackIdsHash for a explaniation of why this works
-static int compareCallbackIds(const std::vector<CallbackId>& c1,
-                              const std::vector<CallbackId>& c2) {
-    if (c1.empty()) {
-        return !c2.empty();
-    }
-    return c1.front() - c2.front();
-}
-
-TransactionCompletedThread::~TransactionCompletedThread() {
-    std::lock_guard lockThread(mThreadMutex);
-
-    {
-        std::lock_guard lock(mMutex);
-        mKeepRunning = false;
-        mConditionVariable.notify_all();
-    }
-
-    if (mThread.joinable()) {
-        mThread.join();
-    }
-
-    {
-        std::lock_guard lock(mMutex);
-        for (const auto& [listener, transactionStats] : mCompletedTransactions) {
-            listener->unlinkToDeath(mDeathRecipient);
-        }
-    }
-}
-
-void TransactionCompletedThread::run() {
-    std::lock_guard lock(mMutex);
-    if (mRunning || !mKeepRunning) {
-        return;
-    }
-    mDeathRecipient = new ThreadDeathRecipient();
-    mRunning = true;
-
-    std::lock_guard lockThread(mThreadMutex);
-    mThread = std::thread(&TransactionCompletedThread::threadMain, this);
-}
-
-status_t TransactionCompletedThread::startRegistration(const ListenerCallbacks& listenerCallbacks) {
-    // begin running if not already running
-    run();
-    std::lock_guard lock(mMutex);
-    if (!mRunning) {
-        ALOGE("cannot add callback because the callback thread isn't running");
-        return BAD_VALUE;
-    }
-
-    auto [itr, inserted] = mRegisteringTransactions.insert(listenerCallbacks);
-    auto& [listener, callbackIds] = listenerCallbacks;
-
-    if (inserted) {
-        if (mCompletedTransactions.count(listener) == 0) {
-            status_t err = listener->linkToDeath(mDeathRecipient);
-            if (err != NO_ERROR) {
-                ALOGE("cannot add callback because linkToDeath failed, err: %d", err);
-                return err;
-            }
-        }
-        auto& transactionStatsDeque = mCompletedTransactions[listener];
-        transactionStatsDeque.emplace_back(callbackIds);
-    }
-
-    return NO_ERROR;
-}
-
-status_t TransactionCompletedThread::endRegistration(const ListenerCallbacks& listenerCallbacks) {
-    std::lock_guard lock(mMutex);
-    if (!mRunning) {
-        ALOGE("cannot add callback because the callback thread isn't running");
-        return BAD_VALUE;
-    }
-
-    auto itr = mRegisteringTransactions.find(listenerCallbacks);
-    if (itr == mRegisteringTransactions.end()) {
-        ALOGE("cannot end a registration that does not exist");
-        return BAD_VALUE;
-    }
-
-    mRegisteringTransactions.erase(itr);
-
-    return NO_ERROR;
-}
-
-bool TransactionCompletedThread::isRegisteringTransaction(
-        const sp<IBinder>& transactionListener, const std::vector<CallbackId>& callbackIds) {
-    ListenerCallbacks listenerCallbacks(transactionListener, callbackIds);
-
-    auto itr = mRegisteringTransactions.find(listenerCallbacks);
-    return itr != mRegisteringTransactions.end();
-}
-
-status_t TransactionCompletedThread::registerPendingCallbackHandle(
-        const sp<CallbackHandle>& handle) {
-    std::lock_guard lock(mMutex);
-    if (!mRunning) {
-        ALOGE("cannot register callback handle because the callback thread isn't running");
-        return BAD_VALUE;
-    }
-
-    // If we can't find the transaction stats something has gone wrong. The client should call
-    // startRegistration before trying to register a pending callback handle.
-    TransactionStats* transactionStats;
-    status_t err = findTransactionStats(handle->listener, handle->callbackIds, &transactionStats);
-    if (err != NO_ERROR) {
-        ALOGE("cannot find transaction stats");
-        return err;
-    }
-
-    mPendingTransactions[handle->listener][handle->callbackIds]++;
-    return NO_ERROR;
-}
-
-status_t TransactionCompletedThread::finalizePendingCallbackHandles(
-        const std::deque<sp<CallbackHandle>>& handles, const std::vector<JankData>& jankData) {
-    if (handles.empty()) {
-        return NO_ERROR;
-    }
-    std::lock_guard lock(mMutex);
-    if (!mRunning) {
-        ALOGE("cannot add presented callback handle because the callback thread isn't running");
-        return BAD_VALUE;
-    }
-
-    for (const auto& handle : handles) {
-        auto listener = mPendingTransactions.find(handle->listener);
-        if (listener != mPendingTransactions.end()) {
-            auto& pendingCallbacks = listener->second;
-            auto pendingCallback = pendingCallbacks.find(handle->callbackIds);
-
-            if (pendingCallback != pendingCallbacks.end()) {
-                auto& pendingCount = pendingCallback->second;
-
-                // Decrease the pending count for this listener
-                if (--pendingCount == 0) {
-                    pendingCallbacks.erase(pendingCallback);
-                }
-            } else {
-                ALOGW("there are more latched callbacks than there were registered callbacks");
-            }
-            if (listener->second.size() == 0) {
-                mPendingTransactions.erase(listener);
-            }
-        } else {
-            ALOGW("cannot find listener in mPendingTransactions");
-        }
-
-        status_t err = addCallbackHandle(handle, jankData);
-        if (err != NO_ERROR) {
-            ALOGE("could not add callback handle");
-            return err;
-        }
-    }
-
-    return NO_ERROR;
-}
-
-status_t TransactionCompletedThread::registerUnpresentedCallbackHandle(
-        const sp<CallbackHandle>& handle) {
-    std::lock_guard lock(mMutex);
-    if (!mRunning) {
-        ALOGE("cannot add unpresented callback handle because the callback thread isn't running");
-        return BAD_VALUE;
-    }
-
-    return addCallbackHandle(handle, std::vector<JankData>());
-}
-
-status_t TransactionCompletedThread::findTransactionStats(
-        const sp<IBinder>& listener, const std::vector<CallbackId>& callbackIds,
-        TransactionStats** outTransactionStats) {
-    auto& transactionStatsDeque = mCompletedTransactions[listener];
-
-    // Search back to front because the most recent transactions are at the back of the deque
-    auto itr = transactionStatsDeque.rbegin();
-    for (; itr != transactionStatsDeque.rend(); itr++) {
-        if (compareCallbackIds(itr->callbackIds, callbackIds) == 0) {
-            *outTransactionStats = &(*itr);
-            return NO_ERROR;
-        }
-    }
-
-    ALOGE("could not find transaction stats");
-    return BAD_VALUE;
-}
-
-status_t TransactionCompletedThread::addCallbackHandle(const sp<CallbackHandle>& handle,
-        const std::vector<JankData>& jankData) {
-    // If we can't find the transaction stats something has gone wrong. The client should call
-    // startRegistration before trying to add a callback handle.
-    TransactionStats* transactionStats;
-    status_t err = findTransactionStats(handle->listener, handle->callbackIds, &transactionStats);
-    if (err != NO_ERROR) {
-        return err;
-    }
-
-    transactionStats->latchTime = handle->latchTime;
-    // If the layer has already been destroyed, don't add the SurfaceControl to the callback.
-    // The client side keeps a sp<> to the SurfaceControl so if the SurfaceControl has been
-    // destroyed the client side is dead and there won't be anyone to send the callback to.
-    sp<IBinder> surfaceControl = handle->surfaceControl.promote();
-    if (surfaceControl) {
-        FrameEventHistoryStats eventStats(handle->frameNumber,
-                                          handle->gpuCompositionDoneFence->getSnapshot().fence,
-                                          handle->compositorTiming, handle->refreshStartTime,
-                                          handle->dequeueReadyTime);
-        transactionStats->surfaceStats.emplace_back(surfaceControl, handle->acquireTime,
-                                                    handle->previousReleaseFence,
-                                                    handle->transformHint, eventStats, jankData);
-    }
-    return NO_ERROR;
-}
-
-void TransactionCompletedThread::addPresentFence(const sp<Fence>& presentFence) {
-    std::lock_guard<std::mutex> lock(mMutex);
-    mPresentFence = presentFence;
-}
-
-void TransactionCompletedThread::sendCallbacks() {
-    std::lock_guard lock(mMutex);
-    if (mRunning) {
-        mConditionVariable.notify_all();
-    }
-}
-
-void TransactionCompletedThread::threadMain() {
-    std::lock_guard lock(mMutex);
-
-    while (mKeepRunning) {
-        mConditionVariable.wait(mMutex);
-        std::vector<ListenerStats> completedListenerStats;
-
-        // For each listener
-        auto completedTransactionsItr = mCompletedTransactions.begin();
-        while (completedTransactionsItr != mCompletedTransactions.end()) {
-            auto& [listener, transactionStatsDeque] = *completedTransactionsItr;
-            ListenerStats listenerStats;
-            listenerStats.listener = listener;
-
-            // For each transaction
-            auto transactionStatsItr = transactionStatsDeque.begin();
-            while (transactionStatsItr != transactionStatsDeque.end()) {
-                auto& transactionStats = *transactionStatsItr;
-
-                // If this transaction is still registering, it is not safe to send a callback
-                // because there could be surface controls that haven't been added to
-                // transaction stats or mPendingTransactions.
-                if (isRegisteringTransaction(listener, transactionStats.callbackIds)) {
-                    break;
-                }
-
-                // If we are still waiting on the callback handles for this transaction, stop
-                // here because all transaction callbacks for the same listener must come in order
-                auto pendingTransactions = mPendingTransactions.find(listener);
-                if (pendingTransactions != mPendingTransactions.end() &&
-                    pendingTransactions->second.count(transactionStats.callbackIds) != 0) {
-                    break;
-                }
-
-                // If the transaction has been latched
-                if (transactionStats.latchTime >= 0) {
-                    if (!mPresentFence) {
-                        break;
-                    }
-                    transactionStats.presentFence = mPresentFence;
-                }
-
-                // Remove the transaction from completed to the callback
-                listenerStats.transactionStats.push_back(std::move(transactionStats));
-                transactionStatsItr = transactionStatsDeque.erase(transactionStatsItr);
-            }
-            // If the listener has completed transactions
-            if (!listenerStats.transactionStats.empty()) {
-                // If the listener is still alive
-                if (listener->isBinderAlive()) {
-                    // Send callback.  The listener stored in listenerStats
-                    // comes from the cross-process setTransactionState call to
-                    // SF.  This MUST be an ITransactionCompletedListener.  We
-                    // keep it as an IBinder due to consistency reasons: if we
-                    // interface_cast at the IPC boundary when reading a Parcel,
-                    // we get pointers that compare unequal in the SF process.
-                    interface_cast<ITransactionCompletedListener>(listenerStats.listener)
-                            ->onTransactionCompleted(listenerStats);
-                    if (transactionStatsDeque.empty()) {
-                        listener->unlinkToDeath(mDeathRecipient);
-                        completedTransactionsItr =
-                                mCompletedTransactions.erase(completedTransactionsItr);
-                    } else {
-                        completedTransactionsItr++;
-                    }
-                } else {
-                    completedTransactionsItr =
-                            mCompletedTransactions.erase(completedTransactionsItr);
-                }
-            } else {
-                completedTransactionsItr++;
-            }
-
-            completedListenerStats.push_back(std::move(listenerStats));
-        }
-
-        if (mPresentFence) {
-            mPresentFence.clear();
-        }
-
-        // If everyone else has dropped their reference to a layer and its listener is dead,
-        // we are about to cause the layer to be deleted. If this happens at the wrong time and
-        // we are holding mMutex, we will cause a deadlock.
-        //
-        // The deadlock happens because this thread is holding on to mMutex and when we delete
-        // the layer, it grabs SF's mStateLock. A different SF binder thread grabs mStateLock,
-        // then call's TransactionCompletedThread::run() which tries to grab mMutex.
-        //
-        // To avoid this deadlock, we need to unlock mMutex when dropping our last reference to
-        // to the layer.
-        mMutex.unlock();
-        completedListenerStats.clear();
-        mMutex.lock();
-    }
-}
-
-// -----------------------------------------------------------------------
-
-CallbackHandle::CallbackHandle(const sp<IBinder>& transactionListener,
-                               const std::vector<CallbackId>& ids, const sp<IBinder>& sc)
-      : listener(transactionListener), callbackIds(ids), surfaceControl(sc) {}
-
-} // namespace android
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wconversion"