Enable write side of MonoPipe to be shutdown

Bug: 7253033
Change-Id: Iea8390763b59ffa7a8e2a6b77dd04ea23442698f
diff --git a/include/media/nbaio/MonoPipe.h b/include/media/nbaio/MonoPipe.h
index c47bf6c..5fcfe9e 100644
--- a/include/media/nbaio/MonoPipe.h
+++ b/include/media/nbaio/MonoPipe.h
@@ -77,6 +77,17 @@
             void    setAvgFrames(size_t setpoint);
             size_t  maxFrames() const { return mMaxFrames; }
 
+            // Set the shutdown state for the write side of a pipe.
+            // This may be called by an unrelated thread.  When shutdown state is 'true',
+            // a write that would otherwise block instead returns a short transfer count.
+            // There is no guarantee how long it will take for the shutdown to be recognized,
+            // but it will not be an unbounded amount of time.
+            // The state can be restored to normal by calling shutdown(false).
+            void    shutdown(bool newState = true);
+
+            // Return true if the write side of a pipe is currently shutdown.
+            bool    isShutdown();
+
 private:
     // A pair of methods and a helper variable which allows the reader and the
     // writer to update and observe the values of mFront and mNextRdPTS in an
@@ -114,6 +125,8 @@
 
     int64_t offsetTimestampByAudioFrames(int64_t ts, size_t audFrames);
     LinearTransform mSamplesToLocalTime;
+
+    bool            mIsShutdown;    // whether shutdown(true) was called, no barriers are needed
 };
 
 }   // namespace android
diff --git a/media/libnbaio/MonoPipe.cpp b/media/libnbaio/MonoPipe.cpp
index bbdc8c1..e8d3d9b 100644
--- a/media/libnbaio/MonoPipe.cpp
+++ b/media/libnbaio/MonoPipe.cpp
@@ -41,7 +41,8 @@
         mWriteTsValid(false),
         // mWriteTs
         mSetpoint((reqFrames * 11) / 16),
-        mWriteCanBlock(writeCanBlock)
+        mWriteCanBlock(writeCanBlock),
+        mIsShutdown(false)
 {
     CCHelper tmpHelper;
     status_t res;
@@ -121,7 +122,7 @@
             android_atomic_release_store(written + mRear, &mRear);
             totalFramesWritten += written;
         }
-        if (!mWriteCanBlock) {
+        if (!mWriteCanBlock || mIsShutdown) {
             break;
         }
         count -= written;
@@ -299,4 +300,14 @@
     return ts + frame_lt_duration;
 }
 
+void MonoPipe::shutdown(bool newState)
+{
+    mIsShutdown = newState;
+}
+
+bool MonoPipe::isShutdown()
+{
+    return mIsShutdown;
+}
+
 }   // namespace android