Add some tracing for release fences

* Fix FenceMonitor to cleanly teardown
* App-side tracing for BBQ release callbacks
* Trace future compleition in TxnCallbackInvoker

Bug: 360932099
Bug: 357762453
Flag: EXEMPT debugging
Test: builds
Test: perfetto
Change-Id: I188c04da1e249b672b428837c328568d9e7a1e66
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index 3c1971f..94998e5 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -31,6 +31,7 @@
 #include <sys/epoll.h>
 #include <sys/eventfd.h>
 
+#include <gui/FenceMonitor.h>
 #include <gui/FrameRateUtils.h>
 #include <gui/GLConsumer.h>
 #include <gui/IProducerListener.h>
@@ -475,6 +476,16 @@
     ATRACE_CALL();
     BQA_LOGV("releaseBufferCallback %s", id.to_string().c_str());
 
+    if (CC_UNLIKELY(atrace_is_tag_enabled(ATRACE_TAG_GRAPHICS))) {
+        if (!mFenceMonitor) {
+            std::string monitorName = "release :";
+            monitorName.append(mName.c_str());
+            mFenceMonitor.emplace(monitorName.c_str());
+        }
+
+        mFenceMonitor->queueFence(releaseFence);
+    }
+
     // Calculate how many buffers we need to hold before we release them back
     // to the buffer queue. This will prevent higher latency when we are running
     // on a lower refresh rate than the max supported. We only do that for EGL
diff --git a/libs/gui/FenceMonitor.cpp b/libs/gui/FenceMonitor.cpp
index 230c81a..e38f1a8 100644
--- a/libs/gui/FenceMonitor.cpp
+++ b/libs/gui/FenceMonitor.cpp
@@ -25,9 +25,18 @@
 namespace android::gui {
 
 FenceMonitor::FenceMonitor(const char* name) : mName(name), mFencesQueued(0), mFencesSignaled(0) {
-    std::thread thread(&FenceMonitor::loop, this);
-    pthread_setname_np(thread.native_handle(), mName);
-    thread.detach();
+    mThread = std::thread(&FenceMonitor::loop, this);
+}
+
+FenceMonitor::~FenceMonitor() {
+    {
+        std::lock_guard<std::mutex> lock(mMutex);
+        mStopped = true;
+        mCondition.notify_one();
+    }
+    if (mThread.joinable()) {
+        mThread.join();
+    }
 }
 
 void FenceMonitor::queueFence(const sp<Fence>& fence) {
@@ -35,24 +44,26 @@
 
     std::lock_guard<std::mutex> lock(mMutex);
     if (fence->getSignalTime() != Fence::SIGNAL_TIME_PENDING) {
-        snprintf(message, sizeof(message), "%s fence %u has signaled", mName, mFencesQueued);
+        snprintf(message, sizeof(message), "%s fence %u has signaled", mName.c_str(),
+                 mFencesQueued);
         ATRACE_NAME(message);
         // Need an increment on both to make the trace number correct.
         mFencesQueued++;
         mFencesSignaled++;
         return;
     }
-    snprintf(message, sizeof(message), "Trace %s fence %u", mName, mFencesQueued);
+    snprintf(message, sizeof(message), "Trace %s fence %u", mName.c_str(), mFencesQueued);
     ATRACE_NAME(message);
 
     mQueue.push_back(fence);
     mCondition.notify_one();
     mFencesQueued++;
-    ATRACE_INT(mName, int32_t(mQueue.size()));
+    ATRACE_INT(mName.c_str(), int32_t(mQueue.size()));
 }
 
 void FenceMonitor::loop() {
-    while (true) {
+    pthread_setname_np(pthread_self(), mName.c_str());
+    while (!mStopped) {
         threadLoop();
     }
 }
@@ -62,15 +73,18 @@
     uint32_t fenceNum;
     {
         std::unique_lock<std::mutex> lock(mMutex);
-        while (mQueue.empty()) {
+        while (mQueue.empty() && !mStopped) {
             mCondition.wait(lock);
         }
+        if (mStopped) {
+            return;
+        }
         fence = mQueue[0];
         fenceNum = mFencesSignaled;
     }
     {
         char message[64];
-        snprintf(message, sizeof(message), "waiting for %s %u", mName, fenceNum);
+        snprintf(message, sizeof(message), "waiting for %s %u", mName.c_str(), fenceNum);
         ATRACE_NAME(message);
 
         status_t result = fence->waitForever(message);
@@ -82,8 +96,8 @@
         std::lock_guard<std::mutex> lock(mMutex);
         mQueue.pop_front();
         mFencesSignaled++;
-        ATRACE_INT(mName, int32_t(mQueue.size()));
+        ATRACE_INT(mName.c_str(), int32_t(mQueue.size()));
     }
 }
 
-} // namespace android::gui
\ No newline at end of file
+} // namespace android::gui
diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h
index d787d6c..868dbd0 100644
--- a/libs/gui/include/gui/BLASTBufferQueue.h
+++ b/libs/gui/include/gui/BLASTBufferQueue.h
@@ -20,6 +20,7 @@
 #include <com_android_graphics_libgui_flags.h>
 #include <gui/BufferItem.h>
 #include <gui/BufferItemConsumer.h>
+#include <gui/FenceMonitor.h>
 #include <gui/IGraphicBufferConsumer.h>
 #include <gui/IGraphicBufferProducer.h>
 #include <gui/SurfaceComposerClient.h>
@@ -316,6 +317,8 @@
 
     std::unordered_set<uint64_t> mSyncedFrameNumbers GUARDED_BY(mMutex);
 
+    std::optional<gui::FenceMonitor> mFenceMonitor GUARDED_BY(mMutex);
+
 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
     class BufferReleaseReader {
     public:
diff --git a/libs/gui/include/gui/FenceMonitor.h b/libs/gui/include/gui/FenceMonitor.h
index 62cedde..ac5cc0a 100644
--- a/libs/gui/include/gui/FenceMonitor.h
+++ b/libs/gui/include/gui/FenceMonitor.h
@@ -19,6 +19,7 @@
 #include <cstdint>
 #include <deque>
 #include <mutex>
+#include <thread>
 
 #include <ui/Fence.h>
 
@@ -28,17 +29,20 @@
 public:
     explicit FenceMonitor(const char* name);
     void queueFence(const sp<Fence>& fence);
+    ~FenceMonitor();
 
 private:
     void loop();
     void threadLoop();
 
-    const char* mName;
+    std::string mName;
     uint32_t mFencesQueued;
     uint32_t mFencesSignaled;
     std::deque<sp<Fence>> mQueue;
     std::condition_variable mCondition;
     std::mutex mMutex;
+    std::thread mThread;
+    std::atomic_bool mStopped = false;
 };
 
-} // namespace android::gui
\ No newline at end of file
+} // namespace android::gui