Merge "Move Vehicle HAL under automotive package"
diff --git a/audio/2.0/IStreamIn.hal b/audio/2.0/IStreamIn.hal
index 9a96f71..e34c95f 100644
--- a/audio/2.0/IStreamIn.hal
+++ b/audio/2.0/IStreamIn.hal
@@ -41,6 +41,26 @@
     setGain(float gain) generates (Result retval);
 
     /*
+     * Commands that can be executed on the driver reader thread.
+     */
+    enum ReadCommand : int32_t {
+        READ,
+        GET_CAPTURE_POSITION
+    };
+
+    /*
+     * Data structure passed to the driver for executing commands
+     * on the driver reader thread.
+     */
+    struct ReadParameters {
+        ReadCommand command;  // discriminator
+        union Params {
+            uint64_t read;    // READ command, amount of bytes to read, >= 0.
+            // No parameters for GET_CAPTURE_POSITION.
+        } params;
+    };
+
+    /*
      * Data structure passed back to the client via status message queue
      * of 'read' operation.
      *
@@ -51,24 +71,36 @@
      */
     struct ReadStatus {
         Result retval;
-        uint64_t read;
+        ReadCommand replyTo;  // discriminator
+        union Reply {
+            uint64_t read;    // READ command, amount of bytes read, >= 0.
+            struct CapturePosition { // same as generated by getCapturePosition.
+                uint64_t frames;
+                uint64_t time;
+            } capturePosition;
+        } reply;
     };
 
     /*
      * Set up required transports for receiving audio buffers from the driver.
      *
-     * The transport consists of two message queues: one is used for passing
-     * audio data from the driver to the client, another is used for reporting
-     * read operation status (amount of bytes actually read or error code),
-     * see ReadStatus structure definition.
+     * The transport consists of three message queues:
+     *  -- command queue is used to instruct the reader thread what operation
+     *     to perform;
+     *  -- data queue is used for passing audio data from the driver
+     *     to the client;
+     *  -- status queue is used for reporting operation status
+     *     (e.g. amount of bytes actually read or error code).
+     * The driver operates on a dedicated thread.
      *
      * @param frameSize the size of a single frame, in bytes.
      * @param framesCount the number of frames in a buffer.
-     * @param threadPriority priority of the thread that performs reads.
+     * @param threadPriority priority of the driver thread.
      * @return retval OK if both message queues were created successfully.
      *                INVALID_STATE if the method was already called.
      *                INVALID_ARGUMENTS if there was a problem setting up
      *                                  the queues.
+     * @return commandMQ a message queue used for passing commands.
      * @return dataMQ a message queue used for passing audio data in the format
      *                specified at the stream opening.
      * @return statusMQ a message queue used for passing status from the driver
@@ -79,7 +111,9 @@
             ThreadPriority threadPriority)
     generates (
             Result retval,
-            fmq_sync<uint8_t> dataMQ, fmq_sync<ReadStatus> statusMQ);
+            fmq_sync<ReadParameters> commandMQ,
+            fmq_sync<uint8_t> dataMQ,
+            fmq_sync<ReadStatus> statusMQ);
 
     /*
      * Return the amount of input frames lost in the audio driver since the last
diff --git a/audio/2.0/IStreamOut.hal b/audio/2.0/IStreamOut.hal
index 336684f..2ec080d 100644
--- a/audio/2.0/IStreamOut.hal
+++ b/audio/2.0/IStreamOut.hal
@@ -44,44 +44,57 @@
     setVolume(float left, float right) generates (Result retval);
 
     /*
+     * Commands that can be executed on the driver writer thread.
+     */
+    enum WriteCommand : int32_t {
+        WRITE,
+        GET_PRESENTATION_POSITION,
+        GET_LATENCY
+    };
+
+    /*
      * Data structure passed back to the client via status message queue
      * of 'write' operation.
      *
-     * Possible values of 'writeRetval' field:
+     * Possible values of 'retval' field:
      *  - OK, write operation was successful;
      *  - INVALID_ARGUMENTS, stream was not configured properly;
-     *  - INVALID_STATE, stream is in a state that doesn't allow writes.
-     *
-     * Possible values of 'presentationPositionRetval' field (must only
-     * be considered if 'writeRetval' field is set to 'OK'):
-     *  - OK, presentation position retrieved successfully;
-     *  - INVALID_ARGUMENTS, indicates that the position can't be retrieved;
-     *  - INVALID_OPERATION, retrieving presentation position isn't supported;
+     *  - INVALID_STATE, stream is in a state that doesn't allow writes;
+     *  - INVALID_OPERATION, retrieving presentation position isn't supported.
      */
     struct WriteStatus {
-        Result writeRetval;
-        uint64_t written;
-        Result presentationPositionRetval;
-        uint64_t frames;    // presentation position
-        TimeSpec timeStamp; // presentation position
+        Result retval;
+        WriteCommand replyTo;  // discriminator
+        union Reply {
+            uint64_t written;  // WRITE command, amount of bytes written, >= 0.
+            struct PresentationPosition {  // same as generated by
+                uint64_t frames;           // getPresentationPosition.
+                TimeSpec timeStamp;
+            } presentationPosition;
+            uint32_t latencyMs; // Same as generated by getLatency.
+        } reply;
     };
 
     /*
      * Set up required transports for passing audio buffers to the driver.
      *
-     * The transport consists of two message queues: one is used for passing
-     * audio data from the client to the driver, another is used for reporting
-     * write operation status (amount of bytes actually written or error code),
-     * and the presentation position immediately after the write, see
-     * WriteStatus structure definition.
+     * The transport consists of three message queues:
+     *  -- command queue is used to instruct the writer thread what operation
+     *     to perform;
+     *  -- data queue is used for passing audio data from the client
+     *     to the driver;
+     *  -- status queue is used for reporting operation status
+     *     (e.g. amount of bytes actually written or error code).
+     * The driver operates on a dedicated thread.
      *
      * @param frameSize the size of a single frame, in bytes.
      * @param framesCount the number of frames in a buffer.
-     * @param threadPriority priority of the thread that performs writes.
+     * @param threadPriority priority of the driver thread.
      * @return retval OK if both message queues were created successfully.
      *                INVALID_STATE if the method was already called.
      *                INVALID_ARGUMENTS if there was a problem setting up
      *                                  the queues.
+     * @return commandMQ a message queue used for passing commands.
      * @return dataMQ a message queue used for passing audio data in the format
      *                specified at the stream opening.
      * @return statusMQ a message queue used for passing status from the driver
@@ -92,7 +105,9 @@
             ThreadPriority threadPriority)
     generates (
             Result retval,
-            fmq_sync<uint8_t> dataMQ, fmq_sync<WriteStatus> statusMQ);
+            fmq_sync<WriteCommand> commandMQ,
+            fmq_sync<uint8_t> dataMQ,
+            fmq_sync<WriteStatus> statusMQ);
 
     /*
      * Return the number of audio frames written by the audio DSP to DAC since
diff --git a/audio/2.0/default/StreamIn.cpp b/audio/2.0/default/StreamIn.cpp
index ad18986..9c49170 100644
--- a/audio/2.0/default/StreamIn.cpp
+++ b/audio/2.0/default/StreamIn.cpp
@@ -16,10 +16,12 @@
 
 #define LOG_TAG "StreamInHAL"
 //#define LOG_NDEBUG 0
+#define ATRACE_TAG ATRACE_TAG_AUDIO
 
 #include <android/log.h>
 #include <hardware/audio.h>
 #include <mediautils/SchedulingPolicyService.h>
+#include <utils/Trace.h>
 
 #include "StreamIn.h"
 
@@ -38,6 +40,7 @@
     // ReadThread's lifespan never exceeds StreamIn's lifespan.
     ReadThread(std::atomic<bool>* stop,
             audio_stream_in_t* stream,
+            StreamIn::CommandMQ* commandMQ,
             StreamIn::DataMQ* dataMQ,
             StreamIn::StatusMQ* statusMQ,
             EventFlag* efGroup,
@@ -45,6 +48,7 @@
             : Thread(false /*canCallJava*/),
               mStop(stop),
               mStream(stream),
+              mCommandMQ(commandMQ),
               mDataMQ(dataMQ),
               mStatusMQ(statusMQ),
               mEfGroup(efGroup),
@@ -58,13 +62,19 @@
   private:
     std::atomic<bool>* mStop;
     audio_stream_in_t* mStream;
+    StreamIn::CommandMQ* mCommandMQ;
     StreamIn::DataMQ* mDataMQ;
     StreamIn::StatusMQ* mStatusMQ;
     EventFlag* mEfGroup;
     ThreadPriority mThreadPriority;
     std::unique_ptr<uint8_t[]> mBuffer;
+    IStreamIn::ReadParameters mParameters;
+    IStreamIn::ReadStatus mStatus;
 
     bool threadLoop() override;
+
+    void doGetCapturePosition();
+    void doRead();
 };
 
 status_t ReadThread::readyToRun() {
@@ -77,6 +87,32 @@
     return OK;
 }
 
+void ReadThread::doRead() {
+    size_t availableToWrite = mDataMQ->availableToWrite();
+    size_t requestedToRead = mParameters.params.read;
+    if (requestedToRead > availableToWrite) {
+        ALOGW("truncating read data from %d to %d due to insufficient data queue space",
+                (int32_t)requestedToRead, (int32_t)availableToWrite);
+        requestedToRead = availableToWrite;
+    }
+    ssize_t readResult = mStream->read(mStream, &mBuffer[0], requestedToRead);
+    mStatus.retval = Result::OK;
+    uint64_t read = 0;
+    if (readResult >= 0) {
+        mStatus.reply.read = readResult;
+        if (!mDataMQ->write(&mBuffer[0], readResult)) {
+            ALOGW("data message queue write failed");
+        }
+    } else {
+        mStatus.retval = Stream::analyzeStatus("read", readResult);
+    }
+}
+
+void ReadThread::doGetCapturePosition() {
+    mStatus.retval = StreamIn::getCapturePositionImpl(
+            mStream, &mStatus.reply.capturePosition.frames, &mStatus.reply.capturePosition.time);
+}
+
 bool ReadThread::threadLoop() {
     // This implementation doesn't return control back to the Thread until it decides to stop,
     // as the Thread uses mutexes, and this can lead to priority inversion.
@@ -87,21 +123,23 @@
         if (!(efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL))) {
             continue;  // Nothing to do.
         }
-
-        const size_t availToWrite = mDataMQ->availableToWrite();
-        ssize_t readResult = mStream->read(mStream, &mBuffer[0], availToWrite);
-        Result retval = Result::OK;
-        uint64_t read = 0;
-        if (readResult >= 0) {
-            read = readResult;
-            if (!mDataMQ->write(&mBuffer[0], readResult)) {
-                ALOGW("data message queue write failed");
-            }
-        } else {
-            retval = Stream::analyzeStatus("read", readResult);
+        if (!mCommandMQ->read(&mParameters)) {
+            continue;  // Nothing to do.
         }
-        IStreamIn::ReadStatus status = { retval, read };
-        if (!mStatusMQ->write(&status)) {
+        mStatus.replyTo = mParameters.command;
+        switch (mParameters.command) {
+            case IStreamIn::ReadCommand::READ:
+                doRead();
+                break;
+            case IStreamIn::ReadCommand::GET_CAPTURE_POSITION:
+                doGetCapturePosition();
+                break;
+            default:
+                ALOGE("Unknown read thread command code %d", mParameters.command);
+                mStatus.retval = Result::NOT_SUPPORTED;
+                break;
+        }
+        if (!mStatusMQ->write(&mStatus)) {
             ALOGW("status message queue write failed");
         }
         mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY));
@@ -120,7 +158,18 @@
 }
 
 StreamIn::~StreamIn() {
+    ATRACE_CALL();
     close();
+    if (mReadThread.get()) {
+        ATRACE_NAME("mReadThread->join");
+        status_t status = mReadThread->join();
+        ALOGE_IF(status, "read thread exit error: %s", strerror(-status));
+    }
+    if (mEfGroup) {
+        status_t status = EventFlag::deleteEventFlag(&mEfGroup);
+        ALOGE_IF(status, "read MQ event flag deletion error: %s", strerror(-status));
+    }
+    mDevice->close_input_stream(mDevice, mStream);
     mStream = nullptr;
     mDevice = nullptr;
 }
@@ -240,14 +289,10 @@
     mIsClosed = true;
     if (mReadThread.get()) {
         mStopReadThread.store(true, std::memory_order_release);
-        status_t status = mReadThread->requestExitAndWait();
-        ALOGE_IF(status, "read thread exit error: %s", strerror(-status));
     }
     if (mEfGroup) {
-        status_t status = EventFlag::deleteEventFlag(&mEfGroup);
-        ALOGE_IF(status, "read MQ event flag deletion error: %s", strerror(-status));
+        mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL));
     }
-    mDevice->close_input_stream(mDevice, mStream);
     return Result::OK;
 }
 
@@ -275,17 +320,19 @@
     if (mDataMQ) {
         ALOGE("the client attempts to call prepareForReading twice");
         _hidl_cb(Result::INVALID_STATE,
-                DataMQ::Descriptor(), StatusMQ::Descriptor());
+                CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor());
         return Void();
     }
+    std::unique_ptr<CommandMQ> tempCommandMQ(new CommandMQ(1));
     std::unique_ptr<DataMQ> tempDataMQ(
             new DataMQ(frameSize * framesCount, true /* EventFlag */));
     std::unique_ptr<StatusMQ> tempStatusMQ(new StatusMQ(1));
-    if (!tempDataMQ->isValid() || !tempStatusMQ->isValid()) {
+    if (!tempCommandMQ->isValid() || !tempDataMQ->isValid() || !tempStatusMQ->isValid()) {
+        ALOGE_IF(!tempCommandMQ->isValid(), "command MQ is invalid");
         ALOGE_IF(!tempDataMQ->isValid(), "data MQ is invalid");
         ALOGE_IF(!tempStatusMQ->isValid(), "status MQ is invalid");
         _hidl_cb(Result::INVALID_ARGUMENTS,
-                DataMQ::Descriptor(), StatusMQ::Descriptor());
+                CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor());
         return Void();
     }
     // TODO: Remove event flag management once blocking MQ is implemented. b/33815422
@@ -293,7 +340,7 @@
     if (status != OK || !mEfGroup) {
         ALOGE("failed creating event flag for data MQ: %s", strerror(-status));
         _hidl_cb(Result::INVALID_ARGUMENTS,
-                DataMQ::Descriptor(), StatusMQ::Descriptor());
+                CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor());
         return Void();
     }
 
@@ -301,6 +348,7 @@
     mReadThread = new ReadThread(
             &mStopReadThread,
             mStream,
+            tempCommandMQ.get(),
             tempDataMQ.get(),
             tempStatusMQ.get(),
             mEfGroup,
@@ -309,13 +357,14 @@
     if (status != OK) {
         ALOGW("failed to start reader thread: %s", strerror(-status));
         _hidl_cb(Result::INVALID_ARGUMENTS,
-                DataMQ::Descriptor(), StatusMQ::Descriptor());
+                CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor());
         return Void();
     }
 
+    mCommandMQ = std::move(tempCommandMQ);
     mDataMQ = std::move(tempDataMQ);
     mStatusMQ = std::move(tempStatusMQ);
-    _hidl_cb(Result::OK, *mDataMQ->getDesc(), *mStatusMQ->getDesc());
+    _hidl_cb(Result::OK, *mCommandMQ->getDesc(), *mDataMQ->getDesc(), *mStatusMQ->getDesc());
     return Void();
 }
 
@@ -323,22 +372,28 @@
     return mStream->get_input_frames_lost(mStream);
 }
 
-Return<void> StreamIn::getCapturePosition(getCapturePosition_cb _hidl_cb)  {
+// static
+Result StreamIn::getCapturePositionImpl(
+        audio_stream_in_t *stream, uint64_t *frames, uint64_t *time) {
     Result retval(Result::NOT_SUPPORTED);
-    uint64_t frames = 0, time = 0;
-    if (mStream->get_capture_position != NULL) {
-        int64_t halFrames, halTime;
-        retval = Stream::analyzeStatus(
-                "get_capture_position",
-                mStream->get_capture_position(mStream, &halFrames, &halTime),
-                // HAL may have a stub function, always returning ENOSYS, don't
-                // spam the log in this case.
-                ENOSYS);
-        if (retval == Result::OK) {
-            frames = halFrames;
-            time = halTime;
-        }
+    if (stream->get_capture_position != NULL) return retval;
+    int64_t halFrames, halTime;
+    retval = Stream::analyzeStatus(
+            "get_capture_position",
+            stream->get_capture_position(stream, &halFrames, &halTime),
+            // HAL may have a stub function, always returning ENOSYS, don't
+            // spam the log in this case.
+            ENOSYS);
+    if (retval == Result::OK) {
+        *frames = halFrames;
+        *time = halTime;
     }
+    return retval;
+};
+
+Return<void> StreamIn::getCapturePosition(getCapturePosition_cb _hidl_cb)  {
+    uint64_t frames = 0, time = 0;
+    Result retval = getCapturePositionImpl(mStream, &frames, &time);
     _hidl_cb(retval, frames, time);
     return Void();
 }
diff --git a/audio/2.0/default/StreamIn.h b/audio/2.0/default/StreamIn.h
index fc813d9..3566430 100644
--- a/audio/2.0/default/StreamIn.h
+++ b/audio/2.0/default/StreamIn.h
@@ -52,6 +52,7 @@
 using ::android::sp;
 
 struct StreamIn : public IStreamIn {
+    typedef MessageQueue<ReadParameters, kSynchronizedReadWrite> CommandMQ;
     typedef MessageQueue<uint8_t, kSynchronizedReadWrite> DataMQ;
     typedef MessageQueue<ReadStatus, kSynchronizedReadWrite> StatusMQ;
 
@@ -97,12 +98,16 @@
     Return<void> createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) override;
     Return<void> getMmapPosition(getMmapPosition_cb _hidl_cb) override;
 
+    static Result getCapturePositionImpl(
+            audio_stream_in_t *stream, uint64_t *frames, uint64_t *time);
+
   private:
     bool mIsClosed;
     audio_hw_device_t *mDevice;
     audio_stream_in_t *mStream;
     sp<Stream> mStreamCommon;
     sp<StreamMmap<audio_stream_in_t>> mStreamMmap;
+    std::unique_ptr<CommandMQ> mCommandMQ;
     std::unique_ptr<DataMQ> mDataMQ;
     std::unique_ptr<StatusMQ> mStatusMQ;
     EventFlag* mEfGroup;
diff --git a/audio/2.0/default/StreamOut.cpp b/audio/2.0/default/StreamOut.cpp
index 2d764b7..6e46db2 100644
--- a/audio/2.0/default/StreamOut.cpp
+++ b/audio/2.0/default/StreamOut.cpp
@@ -16,10 +16,12 @@
 
 #define LOG_TAG "StreamOutHAL"
 //#define LOG_NDEBUG 0
+#define ATRACE_TAG ATRACE_TAG_AUDIO
 
 #include <android/log.h>
 #include <hardware/audio.h>
 #include <mediautils/SchedulingPolicyService.h>
+#include <utils/Trace.h>
 
 #include "StreamOut.h"
 
@@ -36,6 +38,7 @@
     // WriteThread's lifespan never exceeds StreamOut's lifespan.
     WriteThread(std::atomic<bool>* stop,
             audio_stream_out_t* stream,
+            StreamOut::CommandMQ* commandMQ,
             StreamOut::DataMQ* dataMQ,
             StreamOut::StatusMQ* statusMQ,
             EventFlag* efGroup,
@@ -43,6 +46,7 @@
             : Thread(false /*canCallJava*/),
               mStop(stop),
               mStream(stream),
+              mCommandMQ(commandMQ),
               mDataMQ(dataMQ),
               mStatusMQ(statusMQ),
               mEfGroup(efGroup),
@@ -56,13 +60,19 @@
   private:
     std::atomic<bool>* mStop;
     audio_stream_out_t* mStream;
+    StreamOut::CommandMQ* mCommandMQ;
     StreamOut::DataMQ* mDataMQ;
     StreamOut::StatusMQ* mStatusMQ;
     EventFlag* mEfGroup;
     ThreadPriority mThreadPriority;
     std::unique_ptr<uint8_t[]> mBuffer;
+    IStreamOut::WriteStatus mStatus;
 
     bool threadLoop() override;
+
+    void doGetLatency();
+    void doGetPresentationPosition();
+    void doWrite();
 };
 
 status_t WriteThread::readyToRun() {
@@ -75,6 +85,32 @@
     return OK;
 }
 
+void WriteThread::doWrite() {
+    const size_t availToRead = mDataMQ->availableToRead();
+    mStatus.retval = Result::OK;
+    mStatus.reply.written = 0;
+    if (mDataMQ->read(&mBuffer[0], availToRead)) {
+        ssize_t writeResult = mStream->write(mStream, &mBuffer[0], availToRead);
+        if (writeResult >= 0) {
+            mStatus.reply.written = writeResult;
+        } else {
+            mStatus.retval = Stream::analyzeStatus("write", writeResult);
+        }
+    }
+}
+
+void WriteThread::doGetPresentationPosition() {
+    mStatus.retval = StreamOut::getPresentationPositionImpl(
+            mStream,
+            &mStatus.reply.presentationPosition.frames,
+            &mStatus.reply.presentationPosition.timeStamp);
+}
+
+void WriteThread::doGetLatency() {
+    mStatus.retval = Result::OK;
+    mStatus.reply.latencyMs = mStream->get_latency(mStream);
+}
+
 bool WriteThread::threadLoop() {
     // This implementation doesn't return control back to the Thread until it decides to stop,
     // as the Thread uses mutexes, and this can lead to priority inversion.
@@ -86,24 +122,26 @@
         if (!(efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY))) {
             continue;  // Nothing to do.
         }
-
-        const size_t availToRead = mDataMQ->availableToRead();
-        IStreamOut::WriteStatus status;
-        status.writeRetval = Result::OK;
-        status.written = 0;
-        if (mDataMQ->read(&mBuffer[0], availToRead)) {
-            ssize_t writeResult = mStream->write(mStream, &mBuffer[0], availToRead);
-            if (writeResult >= 0) {
-                status.written = writeResult;
-            } else {
-                status.writeRetval = Stream::analyzeStatus("write", writeResult);
-            }
+        if (!mCommandMQ->read(&mStatus.replyTo)) {
+            continue;  // Nothing to do.
         }
-        status.presentationPositionRetval = status.writeRetval == Result::OK ?
-                StreamOut::getPresentationPositionImpl(mStream, &status.frames, &status.timeStamp) :
-                Result::OK;
-        if (!mStatusMQ->write(&status)) {
-            ALOGW("status message queue write failed");
+        switch (mStatus.replyTo) {
+            case IStreamOut::WriteCommand::WRITE:
+                doWrite();
+                break;
+            case IStreamOut::WriteCommand::GET_PRESENTATION_POSITION:
+                doGetPresentationPosition();
+                break;
+            case IStreamOut::WriteCommand::GET_LATENCY:
+                doGetLatency();
+                break;
+            default:
+                ALOGE("Unknown write thread command code %d", mStatus.replyTo);
+                mStatus.retval = Result::NOT_SUPPORTED;
+                break;
+        }
+        if (!mStatusMQ->write(&mStatus)) {
+            ALOGE("status message queue write failed");
         }
         mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL));
     }
@@ -121,7 +159,19 @@
 }
 
 StreamOut::~StreamOut() {
+    ATRACE_CALL();
     close();
+    if (mWriteThread.get()) {
+        ATRACE_NAME("mWriteThread->join");
+        status_t status = mWriteThread->join();
+        ALOGE_IF(status, "write thread exit error: %s", strerror(-status));
+    }
+    if (mEfGroup) {
+        status_t status = EventFlag::deleteEventFlag(&mEfGroup);
+        ALOGE_IF(status, "write MQ event flag deletion error: %s", strerror(-status));
+    }
+    mCallback.clear();
+    mDevice->close_output_stream(mDevice, mStream);
     mStream = nullptr;
     mDevice = nullptr;
 }
@@ -225,15 +275,10 @@
     mIsClosed = true;
     if (mWriteThread.get()) {
         mStopWriteThread.store(true, std::memory_order_release);
-        status_t status = mWriteThread->requestExitAndWait();
-        ALOGE_IF(status, "write thread exit error: %s", strerror(-status));
     }
     if (mEfGroup) {
-        status_t status = EventFlag::deleteEventFlag(&mEfGroup);
-        ALOGE_IF(status, "write MQ event flag deletion error: %s", strerror(-status));
+        mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY));
     }
-    mCallback.clear();
-    mDevice->close_output_stream(mDevice, mStream);
     return Result::OK;
 }
 
@@ -259,17 +304,19 @@
     if (mDataMQ) {
         ALOGE("the client attempts to call prepareForWriting twice");
         _hidl_cb(Result::INVALID_STATE,
-                DataMQ::Descriptor(), StatusMQ::Descriptor());
+                CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor());
         return Void();
     }
+    std::unique_ptr<CommandMQ> tempCommandMQ(new CommandMQ(1));
     std::unique_ptr<DataMQ> tempDataMQ(
             new DataMQ(frameSize * framesCount, true /* EventFlag */));
     std::unique_ptr<StatusMQ> tempStatusMQ(new StatusMQ(1));
-    if (!tempDataMQ->isValid() || !tempStatusMQ->isValid()) {
+    if (!tempCommandMQ->isValid() || !tempDataMQ->isValid() || !tempStatusMQ->isValid()) {
+        ALOGE_IF(!tempCommandMQ->isValid(), "command MQ is invalid");
         ALOGE_IF(!tempDataMQ->isValid(), "data MQ is invalid");
         ALOGE_IF(!tempStatusMQ->isValid(), "status MQ is invalid");
         _hidl_cb(Result::INVALID_ARGUMENTS,
-                DataMQ::Descriptor(), StatusMQ::Descriptor());
+                CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor());
         return Void();
     }
     // TODO: Remove event flag management once blocking MQ is implemented. b/33815422
@@ -277,7 +324,7 @@
     if (status != OK || !mEfGroup) {
         ALOGE("failed creating event flag for data MQ: %s", strerror(-status));
         _hidl_cb(Result::INVALID_ARGUMENTS,
-                DataMQ::Descriptor(), StatusMQ::Descriptor());
+                CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor());
         return Void();
     }
 
@@ -285,6 +332,7 @@
     mWriteThread = new WriteThread(
             &mStopWriteThread,
             mStream,
+            tempCommandMQ.get(),
             tempDataMQ.get(),
             tempStatusMQ.get(),
             mEfGroup,
@@ -293,13 +341,14 @@
     if (status != OK) {
         ALOGW("failed to start writer thread: %s", strerror(-status));
         _hidl_cb(Result::INVALID_ARGUMENTS,
-                DataMQ::Descriptor(), StatusMQ::Descriptor());
+                CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor());
         return Void();
     }
 
+    mCommandMQ = std::move(tempCommandMQ);
     mDataMQ = std::move(tempDataMQ);
     mStatusMQ = std::move(tempStatusMQ);
-    _hidl_cb(Result::OK, *mDataMQ->getDesc(), *mStatusMQ->getDesc());
+    _hidl_cb(Result::OK, *mCommandMQ->getDesc(), *mDataMQ->getDesc(), *mStatusMQ->getDesc());
     return Void();
 }
 
diff --git a/audio/2.0/default/StreamOut.h b/audio/2.0/default/StreamOut.h
index 754a0c0..6616557 100644
--- a/audio/2.0/default/StreamOut.h
+++ b/audio/2.0/default/StreamOut.h
@@ -54,6 +54,7 @@
 using ::android::sp;
 
 struct StreamOut : public IStreamOut {
+    typedef MessageQueue<WriteCommand, kSynchronizedReadWrite> CommandMQ;
     typedef MessageQueue<uint8_t, kSynchronizedReadWrite> DataMQ;
     typedef MessageQueue<WriteStatus, kSynchronizedReadWrite> StatusMQ;
 
@@ -118,6 +119,7 @@
     sp<Stream> mStreamCommon;
     sp<StreamMmap<audio_stream_out_t>> mStreamMmap;
     sp<IStreamOutCallback> mCallback;
+    std::unique_ptr<CommandMQ> mCommandMQ;
     std::unique_ptr<DataMQ> mDataMQ;
     std::unique_ptr<StatusMQ> mStatusMQ;
     EventFlag* mEfGroup;
diff --git a/audio/effect/2.0/default/Effect.cpp b/audio/effect/2.0/default/Effect.cpp
index 3c97fc4..0a4aeb7 100644
--- a/audio/effect/2.0/default/Effect.cpp
+++ b/audio/effect/2.0/default/Effect.cpp
@@ -17,8 +17,11 @@
 #include <memory.h>
 
 #define LOG_TAG "EffectHAL"
+#define ATRACE_TAG ATRACE_TAG_AUDIO
+
 #include <android/log.h>
 #include <media/EffectsFactoryApi.h>
+#include <utils/Trace.h>
 
 #include "Conversions.h"
 #include "Effect.h"
@@ -78,8 +81,9 @@
                 static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS_ALL),
                 &efState,
                 NS_PER_SEC);
-        if (!(efState & static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS_ALL))) {
-            continue;  // Nothing to do.
+        if (!(efState & static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS_ALL))
+                || (efState & static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_QUIT))) {
+            continue;  // Nothing to do or time to quit.
         }
         Result retval = Result::OK;
         if (efState & static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS_REVERSE)
@@ -134,7 +138,23 @@
 }
 
 Effect::~Effect() {
+    ATRACE_CALL();
     close();
+    if (mProcessThread.get()) {
+        ATRACE_NAME("mProcessThread->join");
+        status_t status = mProcessThread->join();
+        ALOGE_IF(status, "processing thread exit error: %s", strerror(-status));
+    }
+    if (mEfGroup) {
+        status_t status = EventFlag::deleteEventFlag(&mEfGroup);
+        ALOGE_IF(status, "processing MQ event flag deletion error: %s", strerror(-status));
+    }
+    mInBuffer.clear();
+    mOutBuffer.clear();
+    int status = EffectRelease(mHandle);
+    ALOGW_IF(status, "Error releasing effect %p: %s", mHandle, strerror(-status));
+    EffectMap::getInstance().remove(mHandle);
+    mHandle = 0;
 }
 
 // static
@@ -731,19 +751,10 @@
     mIsClosed = true;
     if (mProcessThread.get()) {
         mStopProcessThread.store(true, std::memory_order_release);
-        status_t status = mProcessThread->requestExitAndWait();
-        ALOGE_IF(status, "processing thread exit error: %s", strerror(-status));
     }
     if (mEfGroup) {
-        status_t status = EventFlag::deleteEventFlag(&mEfGroup);
-        ALOGE_IF(status, "processing MQ event flag deletion error: %s", strerror(-status));
+        mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_QUIT));
     }
-    mInBuffer.clear();
-    mOutBuffer.clear();
-    int status = EffectRelease(mHandle);
-    ALOGW_IF(status, "Error releasing effect %p: %s", mHandle, strerror(-status));
-    EffectMap::getInstance().remove(mHandle);
-    mHandle = 0;
     return Result::OK;
 }
 
diff --git a/audio/effect/2.0/types.hal b/audio/effect/2.0/types.hal
index 0cac59a..0626ec5 100644
--- a/audio/effect/2.0/types.hal
+++ b/audio/effect/2.0/types.hal
@@ -293,5 +293,7 @@
     DONE_PROCESSING = 1 << 0,
     REQUEST_PROCESS = 1 << 1,
     REQUEST_PROCESS_REVERSE = 1 << 2,
-    REQUEST_PROCESS_ALL = REQUEST_PROCESS | REQUEST_PROCESS_REVERSE
+    REQUEST_QUIT = 1 << 3,
+    REQUEST_PROCESS_ALL =
+        REQUEST_PROCESS | REQUEST_PROCESS_REVERSE | REQUEST_QUIT
 };
diff --git a/bluetooth/1.0/default/bluetooth_address.cc b/bluetooth/1.0/default/bluetooth_address.cc
index b917de9..656d78d 100644
--- a/bluetooth/1.0/default/bluetooth_address.cc
+++ b/bluetooth/1.0/default/bluetooth_address.cc
@@ -83,6 +83,34 @@
     valid_bda = true;
   }
 
+  /* Generate new BDA if necessary */
+  if (!valid_bda) {
+    char bdstr[kStringLength + 1];
+
+    /* No autogen BDA. Generate one now. */
+    local_addr[0] = 0x22;
+    local_addr[1] = 0x22;
+    local_addr[2] = (uint8_t)rand();
+    local_addr[3] = (uint8_t)rand();
+    local_addr[4] = (uint8_t)rand();
+    local_addr[5] = (uint8_t)rand();
+
+    /* Convert to ascii, and store as a persistent property */
+    bytes_to_string(local_addr, bdstr);
+
+    ALOGE("%s: No preset BDA! Generating BDA: %s for prop %s", __func__,
+          (char*)bdstr, PERSIST_BDADDR_PROPERTY);
+    ALOGE("%s: This is a bug in the platform!  Please fix!", __func__);
+
+    if (property_set(PERSIST_BDADDR_PROPERTY, (char*)bdstr) < 0) {
+      ALOGE("%s: Failed to set random BDA in prop %s", __func__,
+            PERSIST_BDADDR_PROPERTY);
+      valid_bda = false;
+    } else {
+      valid_bda = true;
+    }
+  }
+
   return valid_bda;
 }
 
diff --git a/bluetooth/1.0/default/test/bluetooth_address_test.cc b/bluetooth/1.0/default/test/bluetooth_address_test.cc
index 9f80ec2..adcd9c1 100644
--- a/bluetooth/1.0/default/test/bluetooth_address_test.cc
+++ b/bluetooth/1.0/default/test/bluetooth_address_test.cc
@@ -219,10 +219,18 @@
   EXPECT_TRUE(BluetoothAddress::get_local_address(address));
   EXPECT_TRUE(memcmp(address, kTestAddr1_bytes, BluetoothAddress::kBytes) == 0);
 
-  // File contains a zero address.
+  // File contains a zero address.  A random address will be generated.
   FileWriteString(kAddrPath, kZeros);
   EXPECT_TRUE(property_set(PROPERTY_BT_BDADDR_PATH, kAddrPath) == 0);
-  EXPECT_FALSE(BluetoothAddress::get_local_address(address));
+  EXPECT_TRUE(property_set(PERSIST_BDADDR_PROPERTY, kTestAddrBad1) == 0);
+  EXPECT_TRUE(BluetoothAddress::get_local_address(address));
+  EXPECT_TRUE(memcmp(address, kZeros_bytes, BluetoothAddress::kBytes) != 0);
+  char prop[PROP_VALUE_MAX] = "Before reading";
+  EXPECT_TRUE(property_get(PERSIST_BDADDR_PROPERTY, prop, NULL) ==
+              BluetoothAddress::kStringLength);
+  char address_str[BluetoothAddress::kStringLength + 1];
+  BluetoothAddress::bytes_to_string(address, address_str);
+  EXPECT_TRUE(memcmp(address_str, prop, BluetoothAddress::kStringLength) == 0);
 
   // Factory property contains an address.
   EXPECT_TRUE(property_set(PERSIST_BDADDR_PROPERTY, kTestAddrBad1) == 0);
diff --git a/camera/device/3.2/default/Android.bp b/camera/device/3.2/default/Android.bp
index 40d4253..62e3c3e 100644
--- a/camera/device/3.2/default/Android.bp
+++ b/camera/device/3.2/default/Android.bp
@@ -1,5 +1,5 @@
 cc_library_shared {
-    name: "android.hardware.camera.device@3.2-impl",
+    name: "camera.device@3.2-impl",
     srcs: ["CameraDevice.cpp",
            "CameraDeviceSession.cpp",
            "convert.cpp"],
@@ -20,27 +20,3 @@
     ],
     export_include_dirs: ["."]
 }
-
-cc_library_shared {
-    name: "android.hardware.camera.device@3.2-impl-binderized",
-    srcs: ["CameraDevice.cpp",
-           "CameraDeviceSession.cpp",
-           "convert.cpp"],
-    cppflags: ["-DBINDERIZED"],
-    shared_libs: [
-        "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
-        "libutils",
-        "libcutils",
-        "android.hardware.camera.device@3.2",
-        "android.hardware.camera.provider@2.4",
-        "liblog",
-        "libhardware",
-        "libcamera_metadata"
-    ],
-    static_libs: [
-        "android.hardware.camera.common@1.0-helper"
-    ],
-    export_include_dirs: ["."]
-}
diff --git a/camera/device/3.2/default/CameraDeviceSession.cpp b/camera/device/3.2/default/CameraDeviceSession.cpp
index 26b7b73..b47a220 100644
--- a/camera/device/3.2/default/CameraDeviceSession.cpp
+++ b/camera/device/3.2/default/CameraDeviceSession.cpp
@@ -118,9 +118,6 @@
 private:
     bool mInitialized;
 
-    // Some existing gralloc drivers do not support retaining more than once,
-    // when we are in passthrough mode.
-#ifdef BINDERIZED
     bool openGralloc()
     {
         const hw_module_t* module;
@@ -209,12 +206,6 @@
 
     // gralloc0
     const gralloc_module_t* mModule;
-#else
-    bool openGralloc() { return true; }
-    void closeGralloc() {}
-    buffer_handle_t cloneBuffer(buffer_handle_t handle) { return handle; }
-    void releaseBuffer(buffer_handle_t) {}
-#endif
 };
 
 HandleImporter sHandleImporter;
diff --git a/camera/provider/2.4/default/Android.bp b/camera/provider/2.4/default/Android.bp
index ee40ce5..e29f62c 100644
--- a/camera/provider/2.4/default/Android.bp
+++ b/camera/provider/2.4/default/Android.bp
@@ -10,7 +10,7 @@
         "libcutils",
         "android.hardware.camera.device@1.0",
         "android.hardware.camera.device@3.2",
-        "android.hardware.camera.device@3.2-impl",
+        "camera.device@3.2-impl",
         "android.hardware.camera.provider@2.4",
         "android.hardware.camera.common@1.0",
         "liblog",
@@ -25,7 +25,7 @@
 cc_binary {
     name: "android.hardware.camera.provider@2.4-service",
     relative_install_path: "hw",
-    srcs: ["service.cpp", "CameraProvider.cpp"],
+    srcs: ["service.cpp"],
     compile_multilib: "32",
     init_rc: ["android.hardware.camera.provider@2.4-service.rc"],
     shared_libs: [
@@ -40,7 +40,6 @@
         "android.hardware.camera.provider@2.4",
         "android.hardware.camera.common@1.0",
         "libcutils",
-        "android.hardware.camera.device@3.2-impl-binderized",
         "libcamera_metadata"
     ],
     static_libs: [
diff --git a/camera/provider/2.4/default/service.cpp b/camera/provider/2.4/default/service.cpp
index 9600559..cf66e04 100644
--- a/camera/provider/2.4/default/service.cpp
+++ b/camera/provider/2.4/default/service.cpp
@@ -17,41 +17,13 @@
 #define LOG_TAG "android.hardware.camera.provider@2.4-service"
 
 #include <android/hardware/camera/provider/2.4/ICameraProvider.h>
-#include <CameraProvider.h>
-
-#include <hidl/HidlTransportSupport.h>
 #include <hidl/LegacySupport.h>
-#include <utils/StrongPointer.h>
 
-using android::hardware::configureRpcThreadpool;
-using android::hardware::joinRpcThreadpool;
-using android::sp;
 using android::hardware::camera::provider::V2_4::ICameraProvider;
-using android::hardware::camera::provider::V2_4::implementation::HIDL_FETCH_ICameraProvider;
+using android::hardware::defaultPassthroughServiceImplementation;
 
 int main()
 {
-    const char instance[] = "legacy/0";
-
-    // TODO(b/34817742): use defaultServicePassthroughImplementation
-    // so that the toggle is implemented correctly
-    using ::android::hardware::details::blockIfBinderizationDisabled;
-    blockIfBinderizationDisabled(ICameraProvider::descriptor, instance);
-
     ALOGI("Camera provider Service is starting.");
-
-    configureRpcThreadpool(1, true /* callerWillJoin */);
-    // TODO (b/34510650): check the passthrough/binderized dev key
-    sp<ICameraProvider> service = HIDL_FETCH_ICameraProvider(instance);
-    if (service == nullptr) {
-        ALOGI("Camera provider getService returned NULL");
-        return -1;
-    }
-
-    LOG_FATAL_IF(service->isRemote(), "Camera provider service is REMOTE!");
-
-    service->registerAsService(instance);
-    joinRpcThreadpool();
-
-    return 0;
+    return defaultPassthroughServiceImplementation<ICameraProvider>("legacy/0");
 }
\ No newline at end of file
diff --git a/thermal/1.0/default/service.cpp b/thermal/1.0/default/service.cpp
index ea86de4..b83cbf8 100644
--- a/thermal/1.0/default/service.cpp
+++ b/thermal/1.0/default/service.cpp
@@ -23,5 +23,5 @@
 using android::hardware::defaultPassthroughServiceImplementation;
 
 int main() {
-    return defaultPassthroughServiceImplementation<IThermal>("thermal");
+    return defaultPassthroughServiceImplementation<IThermal>();
 }
diff --git a/thermal/1.0/vts/functional/thermal_hidl_hal_test.cpp b/thermal/1.0/vts/functional/thermal_hidl_hal_test.cpp
index 3c887c8..5bdd2c2 100644
--- a/thermal/1.0/vts/functional/thermal_hidl_hal_test.cpp
+++ b/thermal/1.0/vts/functional/thermal_hidl_hal_test.cpp
@@ -40,7 +40,6 @@
 using ::android::hardware::Void;
 using ::android::sp;
 
-#define THERMAL_SERVICE_NAME "thermal"
 #define MONITORING_OPERATION_NUMBER 10
 
 #define MAX_DEVICE_TEMPERATURE 200
@@ -50,7 +49,7 @@
 class ThermalHidlTest : public ::testing::Test {
  public:
   virtual void SetUp() override {
-    thermal_ = IThermal::getService(THERMAL_SERVICE_NAME);
+    thermal_ = IThermal::getService();
     ASSERT_NE(thermal_, nullptr);
     baseSize_ = 0;
     names_.clear();