audio: Add missing throttling and error handling to 'out_' thread

A follow-up to aosp/3467287, adding missing CPU throttling
and error handling from the MonoPipe.

Bug: 364960013
Bug: 394103912
Test: atest CtsMediaAudioTestCases
Test: atest VtsHalAudioCoreTargetTest
Change-Id: I14ac36edb2c9307b4a4e252b2ee866b6a845decd
diff --git a/audio/aidl/default/alsa/StreamAlsa.cpp b/audio/aidl/default/alsa/StreamAlsa.cpp
index 114c4c0..210c26b 100644
--- a/audio/aidl/default/alsa/StreamAlsa.cpp
+++ b/audio/aidl/default/alsa/StreamAlsa.cpp
@@ -280,13 +280,22 @@
     const size_t bufferSize = mBufferSizeFrames * mFrameSizeBytes;
     std::vector<char> buffer(bufferSize);
     while (mIoThreadIsRunning) {
-        ssize_t framesRead = mSources[idx]->read(&buffer[0], mBufferSizeFrames);
-        if (framesRead > 0) {
+        ssize_t framesReadOrError = mSources[idx]->read(&buffer[0], mBufferSizeFrames);
+        if (framesReadOrError > 0) {
             int ret = proxy_write_with_retries(mAlsaDeviceProxies[idx].get(), &buffer[0],
-                                               framesRead * mFrameSizeBytes, mReadWriteRetries);
+                                               framesReadOrError * mFrameSizeBytes,
+                                               mReadWriteRetries);
             // Errors when the stream is being stopped are expected.
             LOG_IF(WARNING, ret != 0 && mIoThreadIsRunning)
                     << __func__ << "[" << idx << "]: Error writing into ALSA: " << ret;
+        } else if (framesReadOrError == 0) {
+            // MonoPipeReader does not have a blocking read, while use of std::condition_variable
+            // requires use of a mutex. For now, just do a 1ms sleep. Consider using a different
+            // pipe / ring buffer mechanism.
+            if (mIoThreadIsRunning) usleep(1000);
+        } else {
+            LOG(WARNING) << __func__ << "[" << idx
+                         << "]: Error while reading from the pipe: " << framesReadOrError;
         }
     }
 }