SurfaceFlinger: Report stuck fences to client

It's ocassionally observed in traces that the GPU is hung
resulting in fences failing to fire. This normally propagates
back up as an ANR in dequeueBuffers or onFrameAvailable. The ANR
might then pass from the app team, to the HWUI team, to the WM
team, and then if we are lucky enough to get a trace, to the
GPU team. In this CL we allow the client process to monitor
this situation itself, and proactively trigger an ANR with
a more useful and informative message than "stuck in
dequeueBuffers"

Bug: 216160569
Test: Existing tests pass
Change-Id: I3ff93bf57d24268ac57734dfed2df185985ffe1f
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 7a63af0..4ce5e4f 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -447,6 +447,27 @@
     }
 }
 
+void TransactionCompletedListener::onTransactionQueueStalled() {
+      std::unordered_map<void*, std::function<void()>> callbackCopy;
+      {
+          std::scoped_lock<std::mutex> lock(mMutex);
+          callbackCopy = mQueueStallListeners;
+      }
+      for (auto const& it : callbackCopy) {
+          it.second();
+      }
+}
+
+void TransactionCompletedListener::addQueueStallListener(std::function<void()> stallListener,
+                                                         void* id) {
+    std::scoped_lock<std::mutex> lock(mMutex);
+    mQueueStallListeners[id] = stallListener;
+}
+void TransactionCompletedListener::removeQueueStallListener(void *id) {
+    std::scoped_lock<std::mutex> lock(mMutex);
+    mQueueStallListeners.erase(id);
+}
+
 void TransactionCompletedListener::onReleaseBuffer(ReleaseCallbackId callbackId,
                                                    sp<Fence> releaseFence,
                                                    uint32_t currentMaxAcquiredBufferCount) {