TimeCheck: Dump TimerThread tasks on timeout

On timeout, shows pending and retired tasks.
Fix race condition on TimerThread construction.
Split mutexes for better concurrency.
Track tasks that don't have timeout.
Enable dumping of pending requests.
Enable dumping of recent retired requests.
Format time in HH:MM:SS.MSc system_clock easier debugging.
Add default TimeCheck constructor that does nothing.

Test: atest libmediautils_test
Test: atest methodstatistics_tests
Test: atest timecheck_tests
Test: adb shell dumpsys media.audio_flinger
Test: adb shell dumpsys media.audio_policy
Test: adb shell dumpsys media.metrics
Bug: 219958414
Change-Id: I25742006578448813e557cdd20e304b9be286964
diff --git a/media/utils/include/mediautils/TimeCheck.h b/media/utils/include/mediautils/TimeCheck.h
index 991a921..d5130b0 100644
--- a/media/utils/include/mediautils/TimeCheck.h
+++ b/media/utils/include/mediautils/TimeCheck.h
@@ -50,27 +50,31 @@
      *                                    destroyed or leaves scope before the timer expires.)
      *                      float elapsedMs (the elapsed time to this event).
      *                  The callback when timeout is true will be called on a different thread.
-     *                  Currently this is guaranteed to block the destructor
-     *                  (potential lock inversion warning here) nevertheless
-     *                  it would be safer not to depend on stack contents.
+     *                  This will cancel the callback on the destructor but is not guaranteed
+     *                  to block for callback completion if it is already in progress
+     *                  (for maximum concurrency and reduced deadlock potential), so use proper
+     *                  lifetime analysis (e.g. shared or weak pointers).
      * \param timeoutMs timeout in milliseconds.
+     *                  A zero timeout means no timeout is set -
+     *                  the callback is called only when
+     *                  the TimeCheck object is destroyed or leaves scope.
      * \param crashOnTimeout true if the object issues an abort on timeout.
      */
     explicit TimeCheck(std::string tag, OnTimerFunc&& onTimer = {},
             uint32_t timeoutMs = kDefaultTimeOutMs, bool crashOnTimeout = true);
+
+    TimeCheck() = default;
     // Remove copy constructors as there should only be one call to the destructor.
     // Move is kept implicitly disabled, but would be logically consistent if enabled.
     TimeCheck(const TimeCheck& other) = delete;
     TimeCheck& operator=(const TimeCheck&) = delete;
 
     ~TimeCheck();
+    static std::string toString();
     static void setAudioHalPids(const std::vector<pid_t>& pids);
     static std::vector<pid_t> getAudioHalPids();
 
   private:
-    static TimerThread& getTimeCheckThread();
-    static void accessAudioHalPids(std::vector<pid_t>* pids, bool update);
-
     // Helper class for handling events.
     // The usage here is const safe.
     class TimeCheckHandler {
@@ -85,11 +89,14 @@
         void onTimeout() const;
     };
 
+    static TimerThread& getTimeCheckThread();
+    static void accessAudioHalPids(std::vector<pid_t>* pids, bool update);
+
     // mTimeCheckHandler is immutable, prefer to be first initialized, last destroyed.
     // Technically speaking, we do not need a shared_ptr here because TimerThread::cancelTask()
     // is mutually exclusive of the callback, but the price paid for lifetime safety is minimal.
     const std::shared_ptr<const TimeCheckHandler> mTimeCheckHandler;
-    const TimerThread::Handle mTimerHandle;
+    const TimerThread::Handle mTimerHandle = TimerThread::INVALID_HANDLE;
 };
 
 }  // namespace android::mediautils