audiohal: Re-implement stream read and write using FMQ

Result: no hwbinder calls due read / write session.

Added IStream.close method for explicitly freeing up of resources
consumed by the stream before automatic server objects reaping
gets to it.

Test: make, perform Loopback RTT, check traces
Bug: 30222631
Change-Id: I678559f6ef30026685df787cd2ba7c2ee449ed27
diff --git a/audio/2.0/default/StreamOut.h b/audio/2.0/default/StreamOut.h
index 9b7f9f8..83f4447 100644
--- a/audio/2.0/default/StreamOut.h
+++ b/audio/2.0/default/StreamOut.h
@@ -17,10 +17,15 @@
 #ifndef ANDROID_HARDWARE_AUDIO_V2_0_STREAMOUT_H
 #define ANDROID_HARDWARE_AUDIO_V2_0_STREAMOUT_H
 
-#include <android/hardware/audio/2.0/IStreamOut.h>
-#include <hidl/Status.h>
+#include <atomic>
+#include <memory>
 
+#include <android/hardware/audio/2.0/IStreamOut.h>
 #include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <fmq/EventFlag.h>
+#include <fmq/MessageQueue.h>
+#include <utils/Thread.h>
 
 #include "Stream.h"
 
@@ -40,6 +45,7 @@
 using ::android::hardware::audio::V2_0::IStreamOutCallback;
 using ::android::hardware::audio::V2_0::ParameterValue;
 using ::android::hardware::audio::V2_0::Result;
+using ::android::hardware::audio::V2_0::ThreadPriority;
 using ::android::hardware::audio::V2_0::TimeSpec;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
@@ -48,6 +54,9 @@
 using ::android::sp;
 
 struct StreamOut : public IStreamOut {
+    typedef MessageQueue<uint8_t, kSynchronizedReadWrite> DataMQ;
+    typedef MessageQueue<WriteStatus, kSynchronizedReadWrite> StatusMQ;
+
     StreamOut(audio_hw_device_t* device, audio_stream_out_t* stream);
 
     // Methods from ::android::hardware::audio::V2_0::IStream follow.
@@ -75,11 +84,14 @@
             const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb)  override;
     Return<Result> setParameters(const hidl_vec<ParameterValue>& parameters)  override;
     Return<void> debugDump(const hidl_handle& fd)  override;
+    Return<Result> close()  override;
 
     // Methods from ::android::hardware::audio::V2_0::IStreamOut follow.
     Return<uint32_t> getLatency()  override;
     Return<Result> setVolume(float left, float right)  override;
-    Return<void> write(const hidl_vec<uint8_t>& data, write_cb _hidl_cb)  override;
+    Return<void> prepareForWriting(
+            uint32_t frameSize, uint32_t framesCount, ThreadPriority threadPriority,
+            prepareForWriting_cb _hidl_cb)  override;
     Return<void> getRenderPosition(getRenderPosition_cb _hidl_cb)  override;
     Return<void> getNextWriteTimestamp(getNextWriteTimestamp_cb _hidl_cb)  override;
     Return<Result> setCallback(const sp<IStreamOutCallback>& callback)  override;
@@ -97,11 +109,17 @@
     Return<void> getMmapPosition(getMmapPosition_cb _hidl_cb) override;
 
   private:
+    bool mIsClosed;
     audio_hw_device_t *mDevice;
     audio_stream_out_t *mStream;
     sp<Stream> mStreamCommon;
     sp<StreamMmap<audio_stream_out_t>> mStreamMmap;
     sp<IStreamOutCallback> mCallback;
+    std::unique_ptr<DataMQ> mDataMQ;
+    std::unique_ptr<StatusMQ> mStatusMQ;
+    EventFlag* mEfGroup;
+    std::atomic<bool> mStopWriteThread;
+    sp<Thread> mWriteThread;
 
     virtual ~StreamOut();