audio: Improve logging in remote submix module

Implement IModule::dump to display the current state in
the audioflinger dump.

Throttle repetitive logging when there is nothing to read.

Remove stale comment for already fixed b/307586684.

Bug: 307586684
Test: adb shell dumpsys media.audio_flinger
Change-Id: I1f1f6e1658d035d46af3a933a825b20a78c7f297
diff --git a/audio/aidl/default/r_submix/SubmixRoute.cpp b/audio/aidl/default/r_submix/SubmixRoute.cpp
index 7d706c2..325a012 100644
--- a/audio/aidl/default/r_submix/SubmixRoute.cpp
+++ b/audio/aidl/default/r_submix/SubmixRoute.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include <mutex>
+
 #define LOG_TAG "AHAL_SubmixRoute"
 #include <android-base/logging.h>
 #include <media/AidlConversionCppNdk.h>
@@ -28,10 +30,11 @@
 namespace aidl::android::hardware::audio::core::r_submix {
 
 // static
-SubmixRoute::RoutesMonitor SubmixRoute::getRoutes() {
+SubmixRoute::RoutesMonitor SubmixRoute::getRoutes(bool tryLock) {
     static std::mutex submixRoutesLock;
     static RoutesMap submixRoutes;
-    return RoutesMonitor(submixRoutesLock, submixRoutes);
+    return !tryLock ? RoutesMonitor(submixRoutesLock, submixRoutes)
+                    : RoutesMonitor(submixRoutesLock, submixRoutes, tryLock);
 }
 
 // static
@@ -66,6 +69,21 @@
     getRoutes()->erase(deviceAddress);
 }
 
+// static
+std::string SubmixRoute::dumpRoutes() {
+    auto routes = getRoutes(true /*tryLock*/);
+    std::string result;
+    if (routes->empty()) result.append(" <Empty>");
+    for (const auto& r : *(routes.operator->())) {
+        result.append(" - ")
+                .append(r.first.toString())
+                .append(": ")
+                .append(r.second->dump())
+                .append("\n");
+    }
+    return result;
+}
+
 // Verify a submix input or output stream can be opened.
 bool SubmixRoute::isStreamConfigValid(bool isInput, const AudioConfig& streamConfig) {
     // If the stream is already open, don't open it again.
@@ -258,4 +276,23 @@
     }
 }
 
+std::string SubmixRoute::dump() NO_THREAD_SAFETY_ANALYSIS {
+    const bool isLocked = mLock.try_lock();
+    std::string result = std::string(isLocked ? "" : "! ")
+                                 .append("Input ")
+                                 .append(mStreamInOpen ? "open" : "closed")
+                                 .append(mStreamInStandby ? ", standby" : ", active")
+                                 .append(", refcount: ")
+                                 .append(std::to_string(mInputRefCount))
+                                 .append(", framesRead: ")
+                                 .append(mSource ? std::to_string(mSource->framesRead()) : "<null>")
+                                 .append("; Output ")
+                                 .append(mStreamOutOpen ? "open" : "closed")
+                                 .append(mStreamOutStandby ? ", standby" : ", active")
+                                 .append(", framesWritten: ")
+                                 .append(mSink ? std::to_string(mSink->framesWritten()) : "<null>");
+    if (isLocked) mLock.unlock();
+    return result;
+}
+
 }  // namespace aidl::android::hardware::audio::core::r_submix