Add handling of "hard" I/O errors to AudioFlinger

"Hard" errors are unrecoverable errors reported by the HAL. In
AIDL HAL, "hard" errors are indicated by switching the stream
into the `ERROR` state, which only allows closing it.

The asynchronous error callback in the AIDL stream interface is
also used to indicate that an unrecoverable error has occured
(for example, it can be a DSP firmware crash). In this case the
I/O stream must be re-opened. So far, audioflinger did not have
support for this scenario. What was happening before is that the
offload track was invalidated, causing the output thread to be
closed. Then track recreation by the client caused the thread to
be created again. However, this sequence is a race between the
audioserver and the app, and thus it is possible that the track
gets recreated on still the same thread, which is unusable
because the HAL stream is in the `ERROR` state.

Bug: 339400414
Test: repro steps in the bug
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:bf203ce4210f480a6ddf158c6fb0b49b4f80f345)
Merged-In: I100d235506f5e3fdfb781a043bbf64746e918d84
Change-Id: I100d235506f5e3fdfb781a043bbf64746e918d84
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index ddf0669..98e3298 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -946,7 +946,7 @@
     // StreamOutHalInterfaceCallback implementation
     virtual     void        onWriteReady();
     virtual     void        onDrainReady();
-    virtual     void        onError();
+    virtual     void        onError(bool /*isHardError*/);
 
 public: // AsyncCallbackThread
                 void        resetWriteBlocked(uint32_t sequence);
@@ -958,7 +958,7 @@
     virtual bool shouldStandby_l() REQUIRES(mutex(), ThreadBase_ThreadLoop);
     virtual void onAddNewTrack_l() REQUIRES(mutex());
 public:  // AsyncCallbackThread
-                void        onAsyncError(); // error reported by AsyncCallbackThread
+                void        onAsyncError(bool isHardError); // error reported by AsyncCallbackThread
 protected:
     // StreamHalInterfaceCodecFormatCallback implementation
                 void        onCodecFormatChanged(
@@ -1371,6 +1371,8 @@
     bool destroyTrack_l(const sp<IAfTrack>& track) final REQUIRES(mutex());
 
     void removeTrack_l(const sp<IAfTrack>& track) REQUIRES(mutex());
+    std::set<audio_port_handle_t> getTrackPortIds_l() REQUIRES(mutex());
+    std::set<audio_port_handle_t> getTrackPortIds();
 
     void readOutputParameters_l() REQUIRES(mutex());
     MetadataUpdate updateMetadata_l() final REQUIRES(mutex());
@@ -1834,7 +1836,7 @@
             void        resetWriteBlocked();
             void        setDraining(uint32_t sequence);
             void        resetDraining();
-            void        setAsyncError();
+            void        setAsyncError(bool isHardError);
 
 private:
     const wp<PlaybackThread>   mPlaybackThread;
@@ -1848,7 +1850,8 @@
     uint32_t                   mDrainSequence;
     audio_utils::condition_variable mWaitWorkCV;
     mutable audio_utils::mutex mMutex{audio_utils::MutexOrder::kAsyncCallbackThread_Mutex};
-    bool                       mAsyncError;
+    enum AsyncError { ASYNC_ERROR_NONE, ASYNC_ERROR_SOFT, ASYNC_ERROR_HARD };
+    AsyncError                 mAsyncError;
 
     audio_utils::mutex& mutex() const RETURN_CAPABILITY(audio_utils::AsyncCallbackThread_Mutex) {
         return mMutex;