Add standby mode for aaudio service stream.

When the stream is stopped, everything will remain open but just stop
writing data. But this will keep the DSP running and using power
until the stream is closed.
To resolve this issue, the solution is to put the stream into standby
mode so that the HAL can release the corresponding resource.
When the HAL releases the resource, the shared file descriptor will also
be released. In that case, when the stream is restarted, AAudioService
needs to recreate shared buffer and the client needs to replace the new
shared buffer.

Test: atest AAudioTests
Test: test_steal_exclusive
Bug: 201000721
Bug: 196394385
Bug: 167345722
Bug: 208619472
Change-Id: Ib4f98e7aee72c2e56acd7f2f0ac378a94ec26241
diff --git a/media/libaaudio/src/binding/AAudioBinderAdapter.cpp b/media/libaaudio/src/binding/AAudioBinderAdapter.cpp
index 6e3a1c8..42d81ca 100644
--- a/media/libaaudio/src/binding/AAudioBinderAdapter.cpp
+++ b/media/libaaudio/src/binding/AAudioBinderAdapter.cpp
@@ -124,4 +124,16 @@
     return result;
 }
 
+aaudio_result_t AAudioBinderAdapter::exitStandby(aaudio_handle_t streamHandle,
+                                                 AudioEndpointParcelable &endpointOut) {
+    aaudio_result_t result;
+    Endpoint endpoint;
+    Status status = mDelegate->exitStandby(streamHandle, &endpoint, &result);
+    if (!status.isOk()) {
+        result = AAudioConvert_androidToAAudioResult(statusTFromBinderStatus(status));
+    }
+    endpointOut = std::move(endpoint);
+    return result;
+}
+
 }  // namespace aaudio
diff --git a/media/libaaudio/src/binding/AAudioBinderAdapter.h b/media/libaaudio/src/binding/AAudioBinderAdapter.h
index 5e9ab57..d170783 100644
--- a/media/libaaudio/src/binding/AAudioBinderAdapter.h
+++ b/media/libaaudio/src/binding/AAudioBinderAdapter.h
@@ -57,6 +57,9 @@
     aaudio_result_t unregisterAudioThread(aaudio_handle_t streamHandle,
                                           pid_t clientThreadId) override;
 
+    aaudio_result_t exitStandby(aaudio_handle_t streamHandle,
+                                AudioEndpointParcelable &parcelable) override;
+
 private:
     IAAudioService* const mDelegate;
 };
diff --git a/media/libaaudio/src/binding/AAudioBinderClient.cpp b/media/libaaudio/src/binding/AAudioBinderClient.cpp
index 135bac3..8e5facc 100644
--- a/media/libaaudio/src/binding/AAudioBinderClient.cpp
+++ b/media/libaaudio/src/binding/AAudioBinderClient.cpp
@@ -201,3 +201,11 @@
 
     return service->unregisterAudioThread(streamHandle, clientThreadId);
 }
+
+aaudio_result_t AAudioBinderClient::exitStandby(aaudio_handle_t streamHandle,
+                                                AudioEndpointParcelable &endpointOut) {
+    std::shared_ptr<AAudioServiceInterface> service = getAAudioService();
+    if (service.get() == nullptr) return AAUDIO_ERROR_NO_SERVICE;
+
+    return service->exitStandby(streamHandle, endpointOut);
+}
diff --git a/media/libaaudio/src/binding/AAudioBinderClient.h b/media/libaaudio/src/binding/AAudioBinderClient.h
index 557ced5..0968f4c 100644
--- a/media/libaaudio/src/binding/AAudioBinderClient.h
+++ b/media/libaaudio/src/binding/AAudioBinderClient.h
@@ -108,6 +108,9 @@
         return AAUDIO_ERROR_UNAVAILABLE;
     }
 
+    aaudio_result_t exitStandby(aaudio_handle_t streamHandle,
+                                AudioEndpointParcelable &endpointOut) override;
+
     void onStreamChange(aaudio_handle_t /*handle*/, int32_t /*opcode*/, int32_t /*value*/) {
         // TODO This is just a stub so we can have a client Binder to pass to the service.
         // TODO Implemented in a later CL.
diff --git a/media/libaaudio/src/binding/AAudioServiceInterface.h b/media/libaaudio/src/binding/AAudioServiceInterface.h
index bf94774..e901767 100644
--- a/media/libaaudio/src/binding/AAudioServiceInterface.h
+++ b/media/libaaudio/src/binding/AAudioServiceInterface.h
@@ -95,6 +95,16 @@
 
     virtual aaudio_result_t stopClient(aaudio_handle_t streamHandle,
                                        audio_port_handle_t clientHandle) = 0;
+
+    /**
+     * Exit the standby mode.
+     *
+     * @param streamHandle the stream handle
+     * @param parcelable contains new data queue information
+     * @return the result of the execution
+     */
+    virtual aaudio_result_t exitStandby(aaudio_handle_t streamHandle,
+                                        AudioEndpointParcelable &parcelable) = 0;
 };
 
 } /* namespace aaudio */
diff --git a/media/libaaudio/src/binding/AudioEndpointParcelable.cpp b/media/libaaudio/src/binding/AudioEndpointParcelable.cpp
index dea3e4a..b1262df 100644
--- a/media/libaaudio/src/binding/AudioEndpointParcelable.cpp
+++ b/media/libaaudio/src/binding/AudioEndpointParcelable.cpp
@@ -79,6 +79,22 @@
     return index;
 }
 
+void AudioEndpointParcelable::closeDataFileDescriptor() {
+    const int32_t curDataMemoryIndex = mDownDataQueueParcelable.getSharedMemoryIndex();
+    mSharedMemories[curDataMemoryIndex].closeAndReleaseFd();
+}
+
+void AudioEndpointParcelable::updateDataFileDescriptor(
+        AudioEndpointParcelable* endpointParcelable) {
+    const int32_t curDataMemoryIndex = mDownDataQueueParcelable.getSharedMemoryIndex();
+    const int32_t newDataMemoryIndex =
+            endpointParcelable->mDownDataQueueParcelable.getSharedMemoryIndex();
+    mSharedMemories[curDataMemoryIndex].close();
+    mSharedMemories[curDataMemoryIndex].setup(
+            endpointParcelable->mSharedMemories[newDataMemoryIndex]);
+    mDownDataQueueParcelable.updateMemory(endpointParcelable->mDownDataQueueParcelable);
+}
+
 aaudio_result_t AudioEndpointParcelable::resolve(EndpointDescriptor *descriptor) {
     aaudio_result_t result = mUpMessageQueueParcelable.resolve(mSharedMemories,
                                                            &descriptor->upMessageQueueDescriptor);
@@ -92,6 +108,10 @@
     return result;
 }
 
+aaudio_result_t AudioEndpointParcelable::resolveDataQueue(RingBufferDescriptor *descriptor) {
+    return mDownDataQueueParcelable.resolve(mSharedMemories, descriptor);
+}
+
 aaudio_result_t AudioEndpointParcelable::close() {
     int err = 0;
     for (int i = 0; i < mNumSharedMemories; i++) {
diff --git a/media/libaaudio/src/binding/AudioEndpointParcelable.h b/media/libaaudio/src/binding/AudioEndpointParcelable.h
index 544aa92..5d2c38f 100644
--- a/media/libaaudio/src/binding/AudioEndpointParcelable.h
+++ b/media/libaaudio/src/binding/AudioEndpointParcelable.h
@@ -52,7 +52,20 @@
      */
     int32_t addFileDescriptor(const android::base::unique_fd& fd, int32_t sizeInBytes);
 
+    /**
+     * Close current data file descriptor. The duplicated file descriptor will be close.
+     */
+    void closeDataFileDescriptor();
+
+    /**
+     * Update current data file descriptor with given endpoint parcelable.
+     * @param endpointParcelable an endpoint parcelable that contains new data file
+     *                           descriptor information
+     */
+    void updateDataFileDescriptor(AudioEndpointParcelable* endpointParcelable);
+
     aaudio_result_t resolve(EndpointDescriptor *descriptor);
+    aaudio_result_t resolveDataQueue(RingBufferDescriptor *descriptor);
 
     aaudio_result_t close();
 
diff --git a/media/libaaudio/src/binding/RingBufferParcelable.cpp b/media/libaaudio/src/binding/RingBufferParcelable.cpp
index fa7ca72..3bc51d0 100644
--- a/media/libaaudio/src/binding/RingBufferParcelable.cpp
+++ b/media/libaaudio/src/binding/RingBufferParcelable.cpp
@@ -33,6 +33,7 @@
         : mReadCounterParcelable(parcelable.readCounterParcelable),
           mWriteCounterParcelable(parcelable.writeCounterParcelable),
           mDataParcelable(parcelable.dataParcelable),
+          mSharedMemoryIndex(parcelable.sharedMemoryIndex),
           mBytesPerFrame(parcelable.bytesPerFrame),
           mFramesPerBurst(parcelable.framesPerBurst),
           mCapacityInFrames(parcelable.capacityInFrames),
@@ -45,6 +46,7 @@
     result.readCounterParcelable = mReadCounterParcelable.parcelable();
     result.writeCounterParcelable = mWriteCounterParcelable.parcelable();
     result.dataParcelable = mDataParcelable.parcelable();
+    result.sharedMemoryIndex = mSharedMemoryIndex;
     result.bytesPerFrame = mBytesPerFrame;
     result.framesPerBurst = mFramesPerBurst;
     result.capacityInFrames = mCapacityInFrames;
@@ -60,6 +62,7 @@
                  int32_t readCounterOffset,
                  int32_t writeCounterOffset,
                  int32_t counterSizeBytes) {
+    mSharedMemoryIndex = sharedMemoryIndex;
     mReadCounterParcelable.setup(sharedMemoryIndex, readCounterOffset, counterSizeBytes);
     mWriteCounterParcelable.setup(sharedMemoryIndex, writeCounterOffset, counterSizeBytes);
     mDataParcelable.setup(sharedMemoryIndex, dataMemoryOffset, dataSizeInBytes);
@@ -68,12 +71,13 @@
 void RingBufferParcelable::setupMemory(int32_t sharedMemoryIndex,
                  int32_t dataMemoryOffset,
                  int32_t dataSizeInBytes) {
+    mSharedMemoryIndex = sharedMemoryIndex;
     mReadCounterParcelable.setup(sharedMemoryIndex, 0, 0);
     mWriteCounterParcelable.setup(sharedMemoryIndex, 0, 0);
     mDataParcelable.setup(sharedMemoryIndex, dataMemoryOffset, dataSizeInBytes);
 }
 
-int32_t RingBufferParcelable::getBytesPerFrame() {
+int32_t RingBufferParcelable::getBytesPerFrame() const {
     return mBytesPerFrame;
 }
 
@@ -81,7 +85,7 @@
     mBytesPerFrame = bytesPerFrame;
 }
 
-int32_t RingBufferParcelable::getFramesPerBurst() {
+int32_t RingBufferParcelable::getFramesPerBurst() const {
     return mFramesPerBurst;
 }
 
@@ -89,7 +93,7 @@
     mFramesPerBurst = framesPerBurst;
 }
 
-int32_t RingBufferParcelable::getCapacityInFrames() {
+int32_t RingBufferParcelable::getCapacityInFrames() const {
     return mCapacityInFrames;
 }
 
@@ -124,6 +128,14 @@
     return AAUDIO_OK;
 }
 
+void RingBufferParcelable::updateMemory(const RingBufferParcelable& parcelable) {
+    setupMemory(mSharedMemoryIndex, 0,
+                parcelable.getCapacityInFrames() * parcelable.getBytesPerFrame());
+    setBytesPerFrame(parcelable.getBytesPerFrame());
+    setFramesPerBurst(parcelable.getFramesPerBurst());
+    setCapacityInFrames(parcelable.getCapacityInFrames());
+}
+
 aaudio_result_t RingBufferParcelable::validate() const {
     if (mCapacityInFrames < 0 || mCapacityInFrames >= 32 * 1024) {
         ALOGE("invalid mCapacityInFrames = %d", mCapacityInFrames);
diff --git a/media/libaaudio/src/binding/RingBufferParcelable.h b/media/libaaudio/src/binding/RingBufferParcelable.h
index 2508cea..29d0d86 100644
--- a/media/libaaudio/src/binding/RingBufferParcelable.h
+++ b/media/libaaudio/src/binding/RingBufferParcelable.h
@@ -46,15 +46,15 @@
                      int32_t dataMemoryOffset,
                      int32_t dataSizeInBytes);
 
-    int32_t getBytesPerFrame();
+    int32_t getBytesPerFrame() const;
 
     void setBytesPerFrame(int32_t bytesPerFrame);
 
-    int32_t getFramesPerBurst();
+    int32_t getFramesPerBurst() const;
 
     void setFramesPerBurst(int32_t framesPerBurst);
 
-    int32_t getCapacityInFrames();
+    int32_t getCapacityInFrames() const;
 
     void setCapacityInFrames(int32_t capacityInFrames);
 
@@ -62,6 +62,12 @@
 
     aaudio_result_t resolve(SharedMemoryParcelable *memoryParcels, RingBufferDescriptor *descriptor);
 
+    void updateMemory(const RingBufferParcelable& parcelable);
+
+    int32_t getSharedMemoryIndex() const {
+        return mSharedMemoryIndex;
+    }
+
     void dump();
 
     // Extract a parcelable representation of this object.
@@ -71,6 +77,7 @@
     SharedRegionParcelable  mReadCounterParcelable;
     SharedRegionParcelable  mWriteCounterParcelable;
     SharedRegionParcelable  mDataParcelable;
+    int32_t                 mSharedMemoryIndex = -1;
     int32_t                 mBytesPerFrame = 0;     // index is in frames
     int32_t                 mFramesPerBurst = 0;    // for ISOCHRONOUS queues
     int32_t                 mCapacityInFrames = 0;  // zero if unused
diff --git a/media/libaaudio/src/binding/SharedMemoryParcelable.cpp b/media/libaaudio/src/binding/SharedMemoryParcelable.cpp
index 3a49655..741aefc 100644
--- a/media/libaaudio/src/binding/SharedMemoryParcelable.cpp
+++ b/media/libaaudio/src/binding/SharedMemoryParcelable.cpp
@@ -64,6 +64,10 @@
     mSizeInBytes = sizeInBytes;
 }
 
+void SharedMemoryParcelable::setup(const SharedMemoryParcelable &sharedMemoryParcelable) {
+    setup(sharedMemoryParcelable.mFd, sharedMemoryParcelable.mSizeInBytes);
+}
+
 aaudio_result_t SharedMemoryParcelable::close() {
     if (mResolvedAddress != MMAP_UNRESOLVED_ADDRESS) {
         int err = munmap(mResolvedAddress, mSizeInBytes);
@@ -76,6 +80,14 @@
     return AAUDIO_OK;
 }
 
+aaudio_result_t SharedMemoryParcelable::closeAndReleaseFd() {
+    aaudio_result_t result = close();
+    if (result == AAUDIO_OK) {
+        mFd.reset();
+    }
+    return result;
+}
+
 aaudio_result_t SharedMemoryParcelable::resolveSharedMemory(const unique_fd& fd) {
     mResolvedAddress = (uint8_t *) mmap(nullptr, mSizeInBytes, PROT_READ | PROT_WRITE,
                                         MAP_SHARED, fd.get(), 0);
diff --git a/media/libaaudio/src/binding/SharedMemoryParcelable.h b/media/libaaudio/src/binding/SharedMemoryParcelable.h
index 1f2c335..7762fef 100644
--- a/media/libaaudio/src/binding/SharedMemoryParcelable.h
+++ b/media/libaaudio/src/binding/SharedMemoryParcelable.h
@@ -52,12 +52,16 @@
      */
     void setup(const android::base::unique_fd& fd, int32_t sizeInBytes);
 
+    void setup(const SharedMemoryParcelable& sharedMemoryParcelable);
+
     // mmap() shared memory
     aaudio_result_t resolve(int32_t offsetInBytes, int32_t sizeInBytes, void **regionAddressPtr);
 
     // munmap() any mapped memory
     aaudio_result_t close();
 
+    aaudio_result_t closeAndReleaseFd();
+
     int32_t getSizeInBytes();
 
     void dump();
diff --git a/media/libaaudio/src/binding/aidl/aaudio/IAAudioService.aidl b/media/libaaudio/src/binding/aidl/aaudio/IAAudioService.aidl
index 44d2211..485c2e2 100644
--- a/media/libaaudio/src/binding/aidl/aaudio/IAAudioService.aidl
+++ b/media/libaaudio/src/binding/aidl/aaudio/IAAudioService.aidl
@@ -78,4 +78,6 @@
 
     int unregisterAudioThread(int streamHandle,
                               int clientThreadId);
+
+    int exitStandby(int streamHandle, out Endpoint endpoint);
 }
diff --git a/media/libaaudio/src/binding/aidl/aaudio/RingBuffer.aidl b/media/libaaudio/src/binding/aidl/aaudio/RingBuffer.aidl
index a58b33a..dd64493 100644
--- a/media/libaaudio/src/binding/aidl/aaudio/RingBuffer.aidl
+++ b/media/libaaudio/src/binding/aidl/aaudio/RingBuffer.aidl
@@ -26,4 +26,5 @@
     int                 framesPerBurst;    // for ISOCHRONOUS queues
     int                 capacityInFrames;  // zero if unused
     int /* RingbufferFlags */ flags;  // = RingbufferFlags::NONE;
+    int                 sharedMemoryIndex;
 }
\ No newline at end of file
diff --git a/media/libaaudio/src/client/AudioEndpoint.cpp b/media/libaaudio/src/client/AudioEndpoint.cpp
index 24888de..e780f4f 100644
--- a/media/libaaudio/src/client/AudioEndpoint.cpp
+++ b/media/libaaudio/src/client/AudioEndpoint.cpp
@@ -139,38 +139,49 @@
     );
 
     // ============================ data queue =============================
-    descriptor = &pEndpointDescriptor->dataQueueDescriptor;
-    ALOGV("configure() data framesPerBurst = %d", descriptor->framesPerBurst);
+    result = configureDataQueue(pEndpointDescriptor->dataQueueDescriptor, direction);
+
+    return result;
+}
+
+aaudio_result_t AudioEndpoint::configureDataQueue(const RingBufferDescriptor& descriptor,
+                                                  aaudio_direction_t direction) {
+    aaudio_result_t result = AudioEndpoint_validateQueueDescriptor("data", &descriptor);
+    if (result != AAUDIO_OK) {
+        return result;
+    }
+
+    ALOGV("configure() data framesPerBurst = %d", descriptor.framesPerBurst);
     ALOGV("configure() data readCounterAddress = %p",
-          descriptor->readCounterAddress);
+          descriptor.readCounterAddress);
 
     // An example of free running is when the other side is read or written by hardware DMA
     // or a DSP. It does not update its counter so we have to update it.
     int64_t *remoteCounter = (direction == AAUDIO_DIRECTION_OUTPUT)
-                             ? descriptor->readCounterAddress // read by other side
-                             : descriptor->writeCounterAddress; // written by other side
+                             ? descriptor.readCounterAddress // read by other side
+                             : descriptor.writeCounterAddress; // written by other side
     mFreeRunning = (remoteCounter == nullptr);
     ALOGV("configure() mFreeRunning = %d", mFreeRunning ? 1 : 0);
 
-    int64_t *readCounterAddress = (descriptor->readCounterAddress == nullptr)
+    int64_t *readCounterAddress = (descriptor.readCounterAddress == nullptr)
                                   ? &mDataReadCounter
-                                  : descriptor->readCounterAddress;
-    int64_t *writeCounterAddress = (descriptor->writeCounterAddress == nullptr)
+                                  : descriptor.readCounterAddress;
+    int64_t *writeCounterAddress = (descriptor.writeCounterAddress == nullptr)
                                   ? &mDataWriteCounter
-                                  : descriptor->writeCounterAddress;
+                                  : descriptor.writeCounterAddress;
 
     // Clear buffer to avoid an initial glitch on some devices.
-    size_t bufferSizeBytes = descriptor->capacityInFrames * descriptor->bytesPerFrame;
-    memset(descriptor->dataAddress, 0, bufferSizeBytes);
+    size_t bufferSizeBytes = descriptor.capacityInFrames * descriptor.bytesPerFrame;
+    memset(descriptor.dataAddress, 0, bufferSizeBytes);
 
     mDataQueue = std::make_unique<FifoBufferIndirect>(
-            descriptor->bytesPerFrame,
-            descriptor->capacityInFrames,
+            descriptor.bytesPerFrame,
+            descriptor.capacityInFrames,
             readCounterAddress,
             writeCounterAddress,
-            descriptor->dataAddress
+            descriptor.dataAddress
     );
-    uint32_t threshold = descriptor->capacityInFrames / 2;
+    uint32_t threshold = descriptor.capacityInFrames / 2;
     mDataQueue->setThreshold(threshold);
     return result;
 }
@@ -181,47 +192,66 @@
 }
 
 int32_t AudioEndpoint::getEmptyFramesAvailable(WrappingBuffer *wrappingBuffer) {
-    return mDataQueue->getEmptyRoomAvailable(wrappingBuffer);
+    return mDataQueue == nullptr ? 0 : mDataQueue->getEmptyRoomAvailable(wrappingBuffer);
 }
 
 int32_t AudioEndpoint::getEmptyFramesAvailable() {
-    return mDataQueue->getEmptyFramesAvailable();
+    return mDataQueue == nullptr ? 0 : mDataQueue->getEmptyFramesAvailable();
 }
 
 int32_t AudioEndpoint::getFullFramesAvailable(WrappingBuffer *wrappingBuffer) {
-    return mDataQueue->getFullDataAvailable(wrappingBuffer);
+    return mDataQueue == nullptr ? 0 : mDataQueue->getFullDataAvailable(wrappingBuffer);
 }
 
 int32_t AudioEndpoint::getFullFramesAvailable() {
-    return mDataQueue->getFullFramesAvailable();
+    return mDataQueue == nullptr ? 0 : mDataQueue->getFullFramesAvailable();
+}
+
+android::fifo_frames_t AudioEndpoint::read(void *buffer, android::fifo_frames_t numFrames) {
+    return mDataQueue == nullptr ? 0 : mDataQueue->read(buffer, numFrames);
+}
+
+android::fifo_frames_t AudioEndpoint::write(void *buffer, android::fifo_frames_t numFrames) {
+    return mDataQueue == nullptr ? 0 : mDataQueue->write(buffer, numFrames);
 }
 
 void AudioEndpoint::advanceWriteIndex(int32_t deltaFrames) {
-    mDataQueue->advanceWriteIndex(deltaFrames);
+    if (mDataQueue != nullptr) {
+        mDataQueue->advanceWriteIndex(deltaFrames);
+    }
 }
 
 void AudioEndpoint::advanceReadIndex(int32_t deltaFrames) {
-    mDataQueue->advanceReadIndex(deltaFrames);
+    if (mDataQueue != nullptr) {
+        mDataQueue->advanceReadIndex(deltaFrames);
+    }
 }
 
 void AudioEndpoint::setDataReadCounter(fifo_counter_t framesRead) {
-    mDataQueue->setReadCounter(framesRead);
+    if (mDataQueue != nullptr) {
+        mDataQueue->setReadCounter(framesRead);
+    }
 }
 
 fifo_counter_t AudioEndpoint::getDataReadCounter() const {
-    return mDataQueue->getReadCounter();
+    return mDataQueue == nullptr ? 0 : mDataQueue->getReadCounter();
 }
 
 void AudioEndpoint::setDataWriteCounter(fifo_counter_t framesRead) {
-    mDataQueue->setWriteCounter(framesRead);
+    if (mDataQueue != nullptr) {
+        mDataQueue->setWriteCounter(framesRead);
+    }
 }
 
 fifo_counter_t AudioEndpoint::getDataWriteCounter() const {
-    return mDataQueue->getWriteCounter();
+    return mDataQueue == nullptr ? 0 : mDataQueue->getWriteCounter();
 }
 
 int32_t AudioEndpoint::setBufferSizeInFrames(int32_t requestedFrames,
                                             int32_t *actualFrames) {
+    if (mDataQueue == nullptr) {
+        return AAUDIO_ERROR_INVALID_STATE;
+    }
     if (requestedFrames < ENDPOINT_DATA_QUEUE_SIZE_MIN) {
         requestedFrames = ENDPOINT_DATA_QUEUE_SIZE_MIN;
     }
@@ -231,11 +261,11 @@
 }
 
 int32_t AudioEndpoint::getBufferSizeInFrames() const {
-    return mDataQueue->getThreshold();
+    return mDataQueue == nullptr ? 0 : mDataQueue->getThreshold();
 }
 
 int32_t AudioEndpoint::getBufferCapacityInFrames() const {
-    return (int32_t)mDataQueue->getBufferCapacityInFrames();
+    return mDataQueue == nullptr ? 0 : (int32_t)mDataQueue->getBufferCapacityInFrames();
 }
 
 void AudioEndpoint::dump() const {
@@ -244,5 +274,7 @@
 }
 
 void AudioEndpoint::eraseDataMemory() {
-    mDataQueue->eraseMemory();
+    if (mDataQueue != nullptr) {
+        mDataQueue->eraseMemory();
+    }
 }
diff --git a/media/libaaudio/src/client/AudioEndpoint.h b/media/libaaudio/src/client/AudioEndpoint.h
index b3dbc20..01dd05a 100644
--- a/media/libaaudio/src/client/AudioEndpoint.h
+++ b/media/libaaudio/src/client/AudioEndpoint.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_AAUDIO_AUDIO_ENDPOINT_H
 #define ANDROID_AAUDIO_AUDIO_ENDPOINT_H
 
+#include <mutex>
+
 #include <aaudio/AAudio.h>
 
 #include "binding/AAudioServiceMessage.h"
@@ -42,6 +44,9 @@
     aaudio_result_t configure(const EndpointDescriptor *pEndpointDescriptor,
                               aaudio_direction_t direction);
 
+    aaudio_result_t configureDataQueue(const RingBufferDescriptor &descriptor,
+                            aaudio_direction_t direction);
+
     /**
      * Read from a command passed up from the Server.
      * @return 1 if command received, 0 for no command, or negative error.
@@ -56,6 +61,10 @@
 
     int32_t getFullFramesAvailable();
 
+    android::fifo_frames_t read(void* buffer, android::fifo_frames_t numFrames);
+
+    android::fifo_frames_t write(void* buffer, android::fifo_frames_t numFrames);
+
     void advanceReadIndex(int32_t deltaFrames);
 
     void advanceWriteIndex(int32_t deltaFrames);
@@ -85,11 +94,21 @@
 
     int32_t getBufferCapacityInFrames() const;
 
+    void setThreshold(int32_t frames) {
+        mDataQueue->setThreshold(frames);
+    }
+
+    int32_t getThreshold() {
+        return mDataQueue->getThreshold();
+    }
+
     /**
      * Write zeros to the data queue memory.
      */
     void eraseDataMemory();
 
+    void freeDataQueue();
+
     void dump() const;
 
 private:
@@ -98,6 +117,8 @@
     bool                    mFreeRunning{false};
     android::fifo_counter_t mDataReadCounter{0}; // only used if free-running
     android::fifo_counter_t mDataWriteCounter{0}; // only used if free-running
+
+    std::mutex mDataQueueLock;
 };
 
 } // namespace aaudio
diff --git a/media/libaaudio/src/client/AudioStreamInternal.cpp b/media/libaaudio/src/client/AudioStreamInternal.cpp
index afdc2ac..9f0564f 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternal.cpp
@@ -81,8 +81,6 @@
 aaudio_result_t AudioStreamInternal::open(const AudioStreamBuilder &builder) {
 
     aaudio_result_t result = AAUDIO_OK;
-    int32_t framesPerBurst;
-    int32_t framesPerHardwareBurst;
     AAudioStreamRequest request;
     AAudioStreamConfiguration configurationOutput;
 
@@ -97,9 +95,6 @@
         return result;
     }
 
-    const int32_t burstMinMicros = android::AudioSystem::getAAudioHardwareBurstMinUsec();
-    int32_t burstMicros = 0;
-
     const audio_format_t requestedFormat = getFormat();
     // We have to do volume scaling. So we prefer FLOAT format.
     if (requestedFormat == AUDIO_FORMAT_DEFAULT) {
@@ -215,12 +210,28 @@
         goto error;
     }
 
-    framesPerHardwareBurst = mEndpointDescriptor.dataQueueDescriptor.framesPerBurst;
+    if ((result = configureDataInformation(builder.getFramesPerDataCallback())) != AAUDIO_OK) {
+        goto error;
+    }
+
+    setState(AAUDIO_STREAM_STATE_OPEN);
+
+    return result;
+
+error:
+    safeReleaseClose();
+    return result;
+}
+
+aaudio_result_t AudioStreamInternal::configureDataInformation(int32_t callbackFrames) {
+    int32_t framesPerHardwareBurst = mEndpointDescriptor.dataQueueDescriptor.framesPerBurst;
 
     // Scale up the burst size to meet the minimum equivalent in microseconds.
     // This is to avoid waking the CPU too often when the HW burst is very small
     // or at high sample rates.
-    framesPerBurst = framesPerHardwareBurst;
+    int32_t framesPerBurst = framesPerHardwareBurst;
+    int32_t burstMicros = 0;
+    const int32_t burstMinMicros = android::AudioSystem::getAAudioHardwareBurstMinUsec();
     do {
         if (burstMicros > 0) {  // skip first loop
             framesPerBurst *= 2;
@@ -233,8 +244,7 @@
     // Validate final burst size.
     if (framesPerBurst < MIN_FRAMES_PER_BURST || framesPerBurst > MAX_FRAMES_PER_BURST) {
         ALOGE("%s - framesPerBurst out of range = %d", __func__, framesPerBurst);
-        result = AAUDIO_ERROR_OUT_OF_RANGE;
-        goto error;
+        return AAUDIO_ERROR_OUT_OF_RANGE;
     }
     setFramesPerBurst(framesPerBurst); // only save good value
 
@@ -242,26 +252,21 @@
     if (mBufferCapacityInFrames < getFramesPerBurst()
             || mBufferCapacityInFrames > MAX_BUFFER_CAPACITY_IN_FRAMES) {
         ALOGE("%s - bufferCapacity out of range = %d", __func__, mBufferCapacityInFrames);
-        result = AAUDIO_ERROR_OUT_OF_RANGE;
-        goto error;
+        return AAUDIO_ERROR_OUT_OF_RANGE;
     }
 
     mClockModel.setSampleRate(getSampleRate());
     mClockModel.setFramesPerBurst(framesPerHardwareBurst);
 
     if (isDataCallbackSet()) {
-        mCallbackFrames = builder.getFramesPerDataCallback();
+        mCallbackFrames = callbackFrames;
         if (mCallbackFrames > getBufferCapacity() / 2) {
             ALOGW("%s - framesPerCallback too big = %d, capacity = %d",
                   __func__, mCallbackFrames, getBufferCapacity());
-            result = AAUDIO_ERROR_OUT_OF_RANGE;
-            goto error;
-
+            return AAUDIO_ERROR_OUT_OF_RANGE;
         } else if (mCallbackFrames < 0) {
             ALOGW("%s - framesPerCallback negative", __func__);
-            result = AAUDIO_ERROR_OUT_OF_RANGE;
-            goto error;
-
+            return AAUDIO_ERROR_OUT_OF_RANGE;
         }
         if (mCallbackFrames == AAUDIO_UNSPECIFIED) {
             mCallbackFrames = getFramesPerBurst();
@@ -302,14 +307,7 @@
     }
 
     setBufferSize(mBufferCapacityInFrames / 2); // Default buffer size to match Q
-
-    setState(AAUDIO_STREAM_STATE_OPEN);
-
-    return result;
-
-error:
-    safeReleaseClose();
-    return result;
+    return AAUDIO_OK;
 }
 
 // This must be called under mStreamLock.
@@ -357,6 +355,60 @@
     }
 }
 
+aaudio_result_t AudioStreamInternal::exitStandby_l() {
+    AudioEndpointParcelable endpointParcelable;
+    // The stream is in standby mode, copy all available data and then close the duplicated
+    // shared file descriptor so that it won't cause issue when the HAL try to reallocate new
+    // shared file descriptor when exiting from standby.
+    // Cache current read counter, which will be reset to new read and write counter
+    // when the new data queue and endpoint are reconfigured.
+    const android::fifo_counter_t readCounter = mAudioEndpoint->getDataReadCounter();
+    // Cache the buffer size which may be from client.
+    const int32_t previousBufferSize = mBufferSizeInFrames;
+    // Copy all available data from current data queue.
+    uint8_t buffer[getBufferCapacity() * getBytesPerFrame()];
+    android::fifo_frames_t fullFramesAvailable =
+            mAudioEndpoint->read(buffer, getBufferCapacity());
+    mEndPointParcelable.closeDataFileDescriptor();
+    aaudio_result_t result = mServiceInterface.exitStandby(
+            mServiceStreamHandle, endpointParcelable);
+    if (result != AAUDIO_OK) {
+        ALOGE("Failed to exit standby, error=%d", result);
+        goto exit;
+    }
+    // Reconstruct data queue descriptor using new shared file descriptor.
+    mEndPointParcelable.updateDataFileDescriptor(&endpointParcelable);
+    result = mEndPointParcelable.resolveDataQueue(&mEndpointDescriptor.dataQueueDescriptor);
+    if (result != AAUDIO_OK) {
+        ALOGE("Failed to resolve data queue after exiting standby, error=%d", result);
+        goto exit;
+    }
+    // Reconfigure audio endpoint with new data queue descriptor.
+    mAudioEndpoint->configureDataQueue(
+            mEndpointDescriptor.dataQueueDescriptor, getDirection());
+    // Set read and write counters with previous read counter, the later write action
+    // will make the counter at the correct place.
+    mAudioEndpoint->setDataReadCounter(readCounter);
+    mAudioEndpoint->setDataWriteCounter(readCounter);
+    result = configureDataInformation(mCallbackFrames);
+    if (result != AAUDIO_OK) {
+        ALOGE("Failed to configure data information after exiting standby, error=%d", result);
+        goto exit;
+    }
+    // Write data from previous data buffer to new endpoint.
+    if (android::fifo_frames_t framesWritten =
+                mAudioEndpoint->write(buffer, fullFramesAvailable);
+            framesWritten != fullFramesAvailable) {
+        ALOGW("Some data lost after exiting standby, frames written: %d, "
+              "frames to write: %d", framesWritten, fullFramesAvailable);
+    }
+    // Reset previous buffer size as it may be requested by the client.
+    setBufferSize(previousBufferSize);
+
+exit:
+    return result;
+}
+
 /*
  * It normally takes about 20-30 msec to start a stream on the server.
  * But the first time can take as much as 200-300 msec. The HW
@@ -393,8 +445,15 @@
     prepareBuffersForStart(); // tell subclasses to get ready
 
     aaudio_result_t result = mServiceInterface.startStream(mServiceStreamHandle);
-    if (result == AAUDIO_ERROR_INVALID_HANDLE) {
-        ALOGD("%s() INVALID_HANDLE, stream was probably stolen", __func__);
+    if (result == AAUDIO_ERROR_STANDBY) {
+        // The stream is at standby mode. Need to exit standby before starting the stream.
+        result = exitStandby_l();
+        if (result == AAUDIO_OK) {
+            result = mServiceInterface.startStream(mServiceStreamHandle);
+        }
+    }
+    if (result != AAUDIO_OK) {
+        ALOGD("%s() error = %d, stream was probably stolen", __func__, result);
         // Stealing was added in R. Coerce result to improve backward compatibility.
         result = AAUDIO_ERROR_DISCONNECTED;
         setState(AAUDIO_STREAM_STATE_DISCONNECTED);
@@ -414,6 +473,7 @@
         result = createThread_l(periodNanos, aaudio_callback_thread_proc, this);
     }
     if (result != AAUDIO_OK) {
+        // TODO(b/214607638): Do we want to roll back to original state or keep as disconnected?
         setState(originalState);
     }
     return result;
diff --git a/media/libaaudio/src/client/AudioStreamInternal.h b/media/libaaudio/src/client/AudioStreamInternal.h
index eab1382..2367572 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.h
+++ b/media/libaaudio/src/client/AudioStreamInternal.h
@@ -184,9 +184,14 @@
     aaudio_result_t writeNowWithConversion(const void *buffer,
                                      int32_t numFrames);
 
+    // Exit the stream from standby, will reconstruct data path.
+    aaudio_result_t exitStandby_l() REQUIRES(mStreamLock);
+
     // Adjust timing model based on timestamp from service.
     void processTimestamp(uint64_t position, int64_t time);
 
+    aaudio_result_t configureDataInformation(int32_t callbackFrames);
+
     // Thread on other side of FIFO will have wakeup jitter.
     // By delaying slightly we can avoid waking up before other side is ready.
     const int32_t            mWakeupDelayNanos; // delay past typical wakeup jitter