StreamHalHidl: Use atomic_wp and make pointers const

Avoid concurrency issues with modification of wp.

Test: basic audio
Bug: 177278988
Change-Id: I5b968a1dad24e1d6c18260884d35c3170661da01
diff --git a/media/libaudiohal/impl/StreamHalHidl.h b/media/libaudiohal/impl/StreamHalHidl.h
index 88f8587..8b1c3d3 100644
--- a/media/libaudiohal/impl/StreamHalHidl.h
+++ b/media/libaudiohal/impl/StreamHalHidl.h
@@ -25,6 +25,7 @@
 #include <fmq/EventFlag.h>
 #include <fmq/MessageQueue.h>
 #include <media/audiohal/StreamHalInterface.h>
+#include <mediautils/Synchronization.h>
 
 #include "ConversionHelperHidl.h"
 #include "StreamPowerLog.h"
@@ -100,9 +101,6 @@
     // Subclasses can not be constructed directly by clients.
     explicit StreamHalHidl(IStream *stream);
 
-    // The destructor automatically closes the stream.
-    virtual ~StreamHalHidl();
-
     status_t getCachedBufferSize(size_t *size);
 
     bool requestHalThreadPriority(pid_t threadPid, pid_t threadId);
@@ -112,7 +110,7 @@
 
   private:
     const int HAL_THREAD_PRIORITY_DEFAULT = -1;
-    IStream *mStream;
+    IStream * const mStream;
     int mHalThreadPriority;
     size_t mCachedBufferSize;
 };
@@ -184,9 +182,16 @@
     typedef MessageQueue<uint8_t, hardware::kSynchronizedReadWrite> DataMQ;
     typedef MessageQueue<WriteStatus, hardware::kSynchronizedReadWrite> StatusMQ;
 
-    wp<StreamOutHalInterfaceCallback> mCallback;
-    wp<StreamOutHalInterfaceEventCallback> mEventCallback;
-    sp<IStreamOut> mStream;
+    // Do not move the Defer.  This should be the first member variable in the class;
+    // thus the last member destructor called upon instance destruction.
+    //
+    // The last step is to flush all binder commands so that the AudioFlinger
+    // may recognize the deletion of IStreamOut (mStream) with less delay. See b/35394629.
+    mediautils::Defer mLast{[]() { hardware::IPCThreadState::self()->flushCommands(); }};
+
+    mediautils::atomic_wp<StreamOutHalInterfaceCallback> mCallback;
+    mediautils::atomic_wp<StreamOutHalInterfaceEventCallback> mEventCallback;
+    const sp<IStreamOut> mStream;
     std::unique_ptr<CommandMQ> mCommandMQ;
     std::unique_ptr<DataMQ> mDataMQ;
     std::unique_ptr<StatusMQ> mStatusMQ;
@@ -242,7 +247,14 @@
     typedef MessageQueue<uint8_t, hardware::kSynchronizedReadWrite> DataMQ;
     typedef MessageQueue<ReadStatus, hardware::kSynchronizedReadWrite> StatusMQ;
 
-    sp<IStreamIn> mStream;
+    // Do not move the Defer.  This should be the first member variable in the class;
+    // thus the last member destructor called upon instance destruction.
+    //
+    // The last step is to flush all binder commands so that the AudioFlinger
+    // may recognize the deletion of IStreamIn (mStream) with less delay. See b/35394629.
+    mediautils::Defer mLast{[]() { hardware::IPCThreadState::self()->flushCommands(); }};
+
+    const sp<IStreamIn> mStream;
     std::unique_ptr<CommandMQ> mCommandMQ;
     std::unique_ptr<DataMQ> mDataMQ;
     std::unique_ptr<StatusMQ> mStatusMQ;