Merge "Expand nuplayer mutex for mediametrics management" into rvc-dev
diff --git a/camera/ICameraClient.cpp b/camera/ICameraClient.cpp
index 487b8b0..c02c81b 100644
--- a/camera/ICameraClient.cpp
+++ b/camera/ICameraClient.cpp
@@ -139,20 +139,18 @@
             CHECK_INTERFACE(ICameraClient, data, reply);
             int32_t msgType = data.readInt32();
             sp<IMemory> imageData = interface_cast<IMemory>(data.readStrongBinder());
-            camera_frame_metadata_t *metadata = NULL;
+            camera_frame_metadata_t metadata;
             if (data.dataAvail() > 0) {
-                metadata = new camera_frame_metadata_t;
-                metadata->number_of_faces = data.readInt32();
-                if (metadata->number_of_faces <= 0 ||
-                        metadata->number_of_faces > (int32_t)(INT32_MAX / sizeof(camera_face_t))) {
-                    ALOGE("%s: Too large face count: %d", __FUNCTION__, metadata->number_of_faces);
+                metadata.number_of_faces = data.readInt32();
+                if (metadata.number_of_faces <= 0 ||
+                        metadata.number_of_faces > (int32_t)(INT32_MAX / sizeof(camera_face_t))) {
+                    ALOGE("%s: Too large face count: %d", __FUNCTION__, metadata.number_of_faces);
                     return BAD_VALUE;
                 }
-                metadata->faces = (camera_face_t *) data.readInplace(
-                        sizeof(camera_face_t) * metadata->number_of_faces);
+                metadata.faces = (camera_face_t *) data.readInplace(
+                        sizeof(camera_face_t) * metadata.number_of_faces);
             }
-            dataCallback(msgType, imageData, metadata);
-            if (metadata) delete metadata;
+            dataCallback(msgType, imageData, &metadata);
             return NO_ERROR;
         } break;
         case DATA_CALLBACK_TIMESTAMP: {
diff --git a/media/codec2/components/amr_nb_wb/C2SoftAmrDec.cpp b/media/codec2/components/amr_nb_wb/C2SoftAmrDec.cpp
index 6578ad2..f7943be 100644
--- a/media/codec2/components/amr_nb_wb/C2SoftAmrDec.cpp
+++ b/media/codec2/components/amr_nb_wb/C2SoftAmrDec.cpp
@@ -336,11 +336,10 @@
                 memset(output, 0, outSamples * sizeof(int16_t));
             } else {
                 int16_t FT;
-                RX_State_wb rx_state;
                 int16_t numRecSamples;
 
                 mime_unsorting(const_cast<uint8_t *>(&input[1]),
-                               mInputSampleBuffer, &FT, &FM, 1, &rx_state);
+                               mInputSampleBuffer, &FT, &FM, 1, &mRxState);
                 pvDecoder_AmrWb(FM, mInputSampleBuffer, output, &numRecSamples,
                                 mDecoderBuf, FT, mDecoderCookie);
                 if (numRecSamples != outSamples) {
diff --git a/media/codec2/components/amr_nb_wb/C2SoftAmrDec.h b/media/codec2/components/amr_nb_wb/C2SoftAmrDec.h
index 6384450..afe1537 100644
--- a/media/codec2/components/amr_nb_wb/C2SoftAmrDec.h
+++ b/media/codec2/components/amr_nb_wb/C2SoftAmrDec.h
@@ -18,6 +18,8 @@
 #define ANDROID_C2_SOFT_AMR_DEC_H_
 
 #include <SimpleC2Component.h>
+#include "gsmamr_dec.h"
+#include "pvamrwbdecoder.h"
 
 
 namespace android {
@@ -51,6 +53,7 @@
     void *mAmrHandle;
     void *mDecoderBuf;
     int16_t *mDecoderCookie;
+    RX_State_wb mRxState{};
 
     int16_t mInputSampleBuffer[477];
 
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index 1e4560c..a3fff35 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -1379,7 +1379,7 @@
         state->set(STOPPING);
     }
 
-    mChannel->stop();
+    mChannel->reset();
     (new AMessage(kWhatStop, this))->post();
 }
 
@@ -1406,9 +1406,6 @@
         // TODO: convert err into status_t
         mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
     }
-    // Assure buffers are not owned when stop() was called without flush().
-    std::list<std::unique_ptr<C2Work>> flushedWork;
-    mChannel->flush(flushedWork);
 
     {
         Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
@@ -1468,7 +1465,7 @@
         }
     }
 
-    mChannel->stop();
+    mChannel->reset();
     // thiz holds strong ref to this while the thread is running.
     sp<CCodec> thiz(this);
     std::thread([thiz, sendCallback] { thiz->release(sendCallback); }).detach();
@@ -1495,6 +1492,7 @@
         state->set(RELEASED);
         state->comp.reset();
     }
+    (new AMessage(kWhatRelease, this))->post();
     if (sendCallback) {
         mCallback->onReleaseCompleted();
     }
@@ -1759,6 +1757,12 @@
             flush();
             break;
         }
+        case kWhatRelease: {
+            mChannel->release();
+            mClient.reset();
+            mClientListener.reset();
+            break;
+        }
         case kWhatCreateInputSurface: {
             // Surface operations may be briefly blocking.
             setDeadline(now, 1500ms, "createInputSurface");
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index 553c013..7d80ef3 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -713,7 +713,7 @@
         return;
     } else {
         Mutexed<Output>::Locked output(mOutput);
-        if (output->buffers->numClientBuffers() >= output->numSlots) {
+        if (!output->buffers || output->buffers->numClientBuffers() >= output->numSlots) {
             return;
         }
     }
@@ -1401,6 +1401,30 @@
     }
 }
 
+void CCodecBufferChannel::reset() {
+    stop();
+    {
+        Mutexed<Input>::Locked input(mInput);
+        input->buffers.reset(new DummyInputBuffers(""));
+    }
+    {
+        Mutexed<Output>::Locked output(mOutput);
+        output->buffers.reset();
+    }
+}
+
+void CCodecBufferChannel::release() {
+    mComponent.reset();
+    mInputAllocator.reset();
+    mOutputSurface.lock()->surface.clear();
+    {
+        Mutexed<BlockPools>::Locked blockPools{mBlockPools};
+        blockPools->inputPool.reset();
+        blockPools->outputPoolIntf.reset();
+    }
+}
+
+
 void CCodecBufferChannel::flush(const std::list<std::unique_ptr<C2Work>> &flushedWork) {
     ALOGV("[%s] flush", mName);
     {
@@ -1431,7 +1455,9 @@
     }
     {
         Mutexed<Output>::Locked output(mOutput);
-        output->buffers->flush(flushedWork);
+        if (output->buffers) {
+            output->buffers->flush(flushedWork);
+        }
     }
     mReorderStash.lock()->flush();
     mPipelineWatcher.lock()->flush();
@@ -1469,20 +1495,25 @@
         std::unique_ptr<C2Work> work,
         const sp<AMessage> &outputFormat,
         const C2StreamInitDataInfo::output *initData) {
-    if (outputFormat != nullptr) {
+    {
         Mutexed<Output>::Locked output(mOutput);
-        ALOGD("[%s] onWorkDone: output format changed to %s",
-                mName, outputFormat->debugString().c_str());
-        output->buffers->setFormat(outputFormat);
+        if (!output->buffers) {
+            return false;
+        }
+        if (outputFormat != nullptr) {
+            ALOGD("[%s] onWorkDone: output format changed to %s",
+                    mName, outputFormat->debugString().c_str());
+            output->buffers->setFormat(outputFormat);
 
-        AString mediaType;
-        if (outputFormat->findString(KEY_MIME, &mediaType)
-                && mediaType == MIMETYPE_AUDIO_RAW) {
-            int32_t channelCount;
-            int32_t sampleRate;
-            if (outputFormat->findInt32(KEY_CHANNEL_COUNT, &channelCount)
-                    && outputFormat->findInt32(KEY_SAMPLE_RATE, &sampleRate)) {
-                output->buffers->updateSkipCutBuffer(sampleRate, channelCount);
+            AString mediaType;
+            if (outputFormat->findString(KEY_MIME, &mediaType)
+                    && mediaType == MIMETYPE_AUDIO_RAW) {
+                int32_t channelCount;
+                int32_t sampleRate;
+                if (outputFormat->findInt32(KEY_CHANNEL_COUNT, &channelCount)
+                        && outputFormat->findInt32(KEY_SAMPLE_RATE, &sampleRate)) {
+                    output->buffers->updateSkipCutBuffer(sampleRate, channelCount);
+                }
             }
         }
     }
@@ -1606,6 +1637,9 @@
                         size_t numInputSlots = mInput.lock()->numSlots;
                         {
                             Mutexed<Output>::Locked output(mOutput);
+                            if (!output->buffers) {
+                                return false;
+                            }
                             output->outputDelay = outputDelay.value;
                             numOutputSlots = outputDelay.value + kSmoothnessFactor;
                             if (output->numSlots < numOutputSlots) {
@@ -1695,7 +1729,7 @@
 
     if (initData != nullptr) {
         Mutexed<Output>::Locked output(mOutput);
-        if (output->buffers->registerCsd(initData, &index, &outBuffer) == OK) {
+        if (output->buffers && output->buffers->registerCsd(initData, &index, &outBuffer) == OK) {
             outBuffer->meta()->setInt64("timeUs", timestamp.peek());
             outBuffer->meta()->setInt32("flags", MediaCodec::BUFFER_FLAG_CODECCONFIG);
             ALOGV("[%s] onWorkDone: csd index = %zu [%p]", mName, index, outBuffer.get());
@@ -1758,6 +1792,9 @@
         }
 
         Mutexed<Output>::Locked output(mOutput);
+        if (!output->buffers) {
+            return;
+        }
         status_t err = output->buffers->registerBuffer(entry.buffer, &index, &outBuffer);
         if (err != OK) {
             bool outputBuffersChanged = false;
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.h b/media/codec2/sfplugin/CCodecBufferChannel.h
index 0263211..f6e7024 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.h
+++ b/media/codec2/sfplugin/CCodecBufferChannel.h
@@ -138,6 +138,16 @@
      */
     void stop();
 
+    /**
+     * Stop queueing buffers to the component and release all buffers.
+     */
+    void reset();
+
+    /**
+     * Release all resources.
+     */
+    void release();
+
     void flush(const std::list<std::unique_ptr<C2Work>> &flushedWork);
 
     /**
diff --git a/media/codec2/sfplugin/CCodecBuffers.h b/media/codec2/sfplugin/CCodecBuffers.h
index 6244acd..eec79f1 100644
--- a/media/codec2/sfplugin/CCodecBuffers.h
+++ b/media/codec2/sfplugin/CCodecBuffers.h
@@ -416,7 +416,7 @@
             size_t *index,
             sp<Codec2Buffer> *buffer,
             std::function<bool(const sp<Codec2Buffer> &)> match =
-                [](const sp<Codec2Buffer> &) { return true; });
+                [](const sp<Codec2Buffer> &buffer) { return (buffer != nullptr); });
 
     /**
      * Return the buffer from the client, and get the C2Buffer object back from
diff --git a/media/libaudiofoundation/DeviceDescriptorBase.cpp b/media/libaudiofoundation/DeviceDescriptorBase.cpp
index ef7576e..3dbe37d 100644
--- a/media/libaudiofoundation/DeviceDescriptorBase.cpp
+++ b/media/libaudiofoundation/DeviceDescriptorBase.cpp
@@ -80,9 +80,28 @@
     toAudioPortConfig(&port->active_config);
     port->id = mId;
     port->ext.device.type = mDeviceTypeAddr.mType;
+    port->ext.device.encapsulation_modes = mEncapsulationModes;
+    port->ext.device.encapsulation_metadata_types = mEncapsulationMetadataTypes;
     (void)audio_utils_strlcpy_zerofill(port->ext.device.address, mDeviceTypeAddr.getAddress());
 }
 
+status_t DeviceDescriptorBase::setEncapsulationModes(uint32_t encapsulationModes) {
+    if ((encapsulationModes & ~AUDIO_ENCAPSULATION_MODE_ALL_POSITION_BITS) != 0) {
+        return BAD_VALUE;
+    }
+    mEncapsulationModes = encapsulationModes & ~(1 << AUDIO_ENCAPSULATION_MODE_NONE);
+    return NO_ERROR;
+}
+
+status_t DeviceDescriptorBase::setEncapsulationMetadataTypes(uint32_t encapsulationMetadataTypes) {
+    if ((encapsulationMetadataTypes & ~AUDIO_ENCAPSULATION_METADATA_TYPE_ALL_POSITION_BITS) != 0) {
+        return BAD_VALUE;
+    }
+    mEncapsulationMetadataTypes =
+            encapsulationMetadataTypes & ~(1 << AUDIO_ENCAPSULATION_METADATA_TYPE_NONE);
+    return NO_ERROR;
+}
+
 void DeviceDescriptorBase::dump(std::string *dst, int spaces, int index,
                                 const char* extraInfo, bool verbose) const
 {
@@ -98,6 +117,12 @@
     dst->append(base::StringPrintf("%*s- type: %-48s\n",
             spaces, "", ::android::toString(mDeviceTypeAddr.mType).c_str()));
 
+    dst->append(base::StringPrintf(
+            "%*s- supported encapsulation modes: %u", spaces, "", mEncapsulationModes));
+    dst->append(base::StringPrintf(
+            "%*s- supported encapsulation metadata types: %u",
+            spaces, "", mEncapsulationMetadataTypes));
+
     if (mDeviceTypeAddr.mAddress.size() != 0) {
         dst->append(base::StringPrintf(
                 "%*s- address: %-32s\n", spaces, "", mDeviceTypeAddr.getAddress()));
@@ -135,6 +160,8 @@
     if ((status = AudioPort::writeToParcel(parcel)) != NO_ERROR) return status;
     if ((status = AudioPortConfig::writeToParcel(parcel)) != NO_ERROR) return status;
     if ((status = parcel->writeParcelable(mDeviceTypeAddr)) != NO_ERROR) return status;
+    if ((status = parcel->writeUint32(mEncapsulationModes)) != NO_ERROR) return status;
+    if ((status = parcel->writeUint32(mEncapsulationMetadataTypes)) != NO_ERROR) return status;
     return status;
 }
 
@@ -144,6 +171,8 @@
     if ((status = AudioPort::readFromParcel(parcel)) != NO_ERROR) return status;
     if ((status = AudioPortConfig::readFromParcel(parcel)) != NO_ERROR) return status;
     if ((status = parcel->readParcelable(&mDeviceTypeAddr)) != NO_ERROR) return status;
+    if ((status = parcel->readUint32(&mEncapsulationModes)) != NO_ERROR) return status;
+    if ((status = parcel->readUint32(&mEncapsulationMetadataTypes)) != NO_ERROR) return status;
     return status;
 }
 
diff --git a/media/libaudiofoundation/include/media/DeviceDescriptorBase.h b/media/libaudiofoundation/include/media/DeviceDescriptorBase.h
index 4c03667..af04721 100644
--- a/media/libaudiofoundation/include/media/DeviceDescriptorBase.h
+++ b/media/libaudiofoundation/include/media/DeviceDescriptorBase.h
@@ -55,6 +55,9 @@
     // AudioPort
     virtual void toAudioPort(struct audio_port *port) const;
 
+    status_t setEncapsulationModes(uint32_t encapsulationModes);
+    status_t setEncapsulationMetadataTypes(uint32_t encapsulationMetadataTypes);
+
     void dump(std::string *dst, int spaces, int index,
               const char* extraInfo = nullptr, bool verbose = true) const;
     void log() const;
@@ -67,6 +70,8 @@
 
 protected:
     AudioDeviceTypeAddr mDeviceTypeAddr;
+    uint32_t mEncapsulationModes = 0;
+    uint32_t mEncapsulationMetadataTypes = 0;
 };
 
 using DeviceDescriptorBaseVector = std::vector<sp<DeviceDescriptorBase>>;
diff --git a/media/libaudiofoundation/tests/audiofoundation_parcelable_test.cpp b/media/libaudiofoundation/tests/audiofoundation_parcelable_test.cpp
index 5baa072..068b5d8 100644
--- a/media/libaudiofoundation/tests/audiofoundation_parcelable_test.cpp
+++ b/media/libaudiofoundation/tests/audiofoundation_parcelable_test.cpp
@@ -131,6 +131,9 @@
     desc->setAudioProfiles(getAudioProfileVectorForTest());
     desc->applyAudioPortConfig(&TEST_AUDIO_PORT_CONFIG);
     desc->setAddress("DeviceDescriptorBaseTestAddress");
+    ASSERT_EQ(desc->setEncapsulationModes(1 << AUDIO_ENCAPSULATION_MODE_HANDLE), NO_ERROR);
+    ASSERT_EQ(desc->setEncapsulationMetadataTypes(
+            AUDIO_ENCAPSULATION_METADATA_TYPE_ALL_POSITION_BITS), NO_ERROR);
 
     ASSERT_EQ(data.writeParcelable(*desc), NO_ERROR);
     data.setDataPosition(0);
diff --git a/media/libaudiohal/impl/ConversionHelperHidl.cpp b/media/libaudiohal/impl/ConversionHelperHidl.cpp
index f29b0f3..ebed5fd 100644
--- a/media/libaudiohal/impl/ConversionHelperHidl.cpp
+++ b/media/libaudiohal/impl/ConversionHelperHidl.cpp
@@ -41,16 +41,25 @@
     bool keepFormatValue = halKeys.size() == 2 &&
          (halKeys.get(String8(AudioParameter::keyStreamSupportedChannels), value) == NO_ERROR ||
          halKeys.get(String8(AudioParameter::keyStreamSupportedSamplingRates), value) == NO_ERROR);
+    // When querying encapsulation capabilities, "keyRouting=<value>" pair is used to identify
+    // the device. We need to transform it into a single key string so that it is carried over to
+    // the legacy HAL via HIDL.
+    bool keepRoutingValue =
+            halKeys.get(String8(AUDIO_PARAMETER_DEVICE_SUP_ENCAPSULATION_MODES),
+                        value) == NO_ERROR ||
+            halKeys.get(String8(AUDIO_PARAMETER_DEVICE_SUP_ENCAPSULATION_METADATA_TYPES),
+                        value) == NO_ERROR;
 
     for (size_t i = 0; i < halKeys.size(); ++i) {
         String8 key;
         status_t status = halKeys.getAt(i, key);
         if (status != OK) return status;
-        if (keepFormatValue && key == AudioParameter::keyFormat) {
-            AudioParameter formatParam;
+        if ((keepFormatValue && key == AudioParameter::keyFormat) ||
+            (keepRoutingValue && key == AudioParameter::keyRouting)) {
+            AudioParameter keepValueParam;
             halKeys.getAt(i, key, value);
-            formatParam.add(key, value);
-            key = formatParam.toString();
+            keepValueParam.add(key, value);
+            key = keepValueParam.toString();
         }
         (*hidlKeys)[i] = key.string();
     }
diff --git a/media/libmediahelper/AudioParameter.cpp b/media/libmediahelper/AudioParameter.cpp
index 9f34035..fc8306c 100644
--- a/media/libmediahelper/AudioParameter.cpp
+++ b/media/libmediahelper/AudioParameter.cpp
@@ -53,6 +53,10 @@
 const char * const AudioParameter::valueListSeparator = AUDIO_PARAMETER_VALUE_LIST_SEPARATOR;
 const char * const AudioParameter::keyReconfigA2dp = AUDIO_PARAMETER_RECONFIG_A2DP;
 const char * const AudioParameter::keyReconfigA2dpSupported = AUDIO_PARAMETER_A2DP_RECONFIG_SUPPORTED;
+// const char * const AudioParameter::keyDeviceSupportedEncapsulationModes =
+//        AUDIO_PARAMETER_DEVICE_SUP_ENCAPSULATION_MODES;
+// const char * const AudioParameter::keyDeviceSupportedEncapsulationMetadataTypes =
+//        AUDIO_PARAMETER_DEVICE_SUP_ENCAPSULATION_METADATA_TYPES;
 
 AudioParameter::AudioParameter(const String8& keyValuePairs)
 {
diff --git a/media/libmediahelper/include/media/AudioParameter.h b/media/libmediahelper/include/media/AudioParameter.h
index 3c190f2..66d8dfb 100644
--- a/media/libmediahelper/include/media/AudioParameter.h
+++ b/media/libmediahelper/include/media/AudioParameter.h
@@ -92,6 +92,18 @@
     static const char * const keyReconfigA2dp;
     static const char * const keyReconfigA2dpSupported;
 
+    // For querying device supported encapsulation capabilities. All returned values are integer,
+    // which are bit fields composed from using encapsulation capability values as position bits.
+    // Encapsulation capability values are defined in audio_encapsulation_mode_t and
+    // audio_encapsulation_metadata_type_t. For instance, if the supported encapsulation mode is
+    // AUDIO_ENCAPSULATION_MODE_ELEMENTARY_STREAM, the returned value is
+    // "supEncapsulationModes=1 << AUDIO_ENCAPSULATION_MODE_HANDLE".
+    // When querying device supported encapsulation capabilities, the key should use with device
+    // type and address so that it is able to identify the device. The device will be a key. The
+    // device type will be the value of key AUDIO_PARAMETER_STREAM_ROUTING.
+    // static const char * const keyDeviceSupportedEncapsulationModes;
+    // static const char * const keyDeviceSupportedEncapsulationMetadataTypes;
+
     String8 toString() const { return toStringImpl(true); }
     String8 keysToString() const { return toStringImpl(false); }
 
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 11f2f38..e748b01 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -2641,6 +2641,7 @@
                     }
 
                     mResourceManagerProxy->removeClient();
+                    mReleaseSurface.reset();
 
                     if (mReplyID != nullptr) {
                         (new AMessage)->postReply(mReplyID);
diff --git a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
index 34dd011..cdfc03a 100644
--- a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
+++ b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
@@ -20,9 +20,6 @@
 
 #include "SoftAMR.h"
 
-#include "gsmamr_dec.h"
-#include "pvamrwbdecoder.h"
-
 #include <media/stagefright/foundation/ADebug.h>
 
 namespace android {
@@ -470,11 +467,10 @@
                 memset(outPtr, 0, kNumSamplesPerFrameWB * sizeof(int16_t));
             } else if (mode < 9) {
                 int16 frameType;
-                RX_State_wb rx_state;
                 mime_unsorting(
                         const_cast<uint8_t *>(&inputPtr[1]),
                         mInputSampleBuffer,
-                        &frameType, &mode, 1, &rx_state);
+                        &frameType, &mode, 1, &mRxState);
 
                 int16_t numSamplesOutput;
                 pvDecoder_AmrWb(
diff --git a/media/libstagefright/codecs/amrnb/dec/SoftAMR.h b/media/libstagefright/codecs/amrnb/dec/SoftAMR.h
index 869b81d..d5aaed3 100644
--- a/media/libstagefright/codecs/amrnb/dec/SoftAMR.h
+++ b/media/libstagefright/codecs/amrnb/dec/SoftAMR.h
@@ -19,6 +19,8 @@
 #define SOFT_AMR_H_
 
 #include <media/stagefright/omx/SimpleSoftOMXComponent.h>
+#include "gsmamr_dec.h"
+#include "pvamrwbdecoder.h"
 
 namespace android {
 
@@ -60,6 +62,7 @@
     void *mState;
     void *mDecoderBuf;
     int16_t *mDecoderCookie;
+    RX_State_wb mRxState{};
 
     size_t mInputBufferCount;
     int64_t mAnchorTimeUs;
diff --git a/media/libstagefright/codecs/amrwb/fuzzer/amrwb_dec_fuzzer.cpp b/media/libstagefright/codecs/amrwb/fuzzer/amrwb_dec_fuzzer.cpp
index 6dc0270..592a6ec 100644
--- a/media/libstagefright/codecs/amrwb/fuzzer/amrwb_dec_fuzzer.cpp
+++ b/media/libstagefright/codecs/amrwb/fuzzer/amrwb_dec_fuzzer.cpp
@@ -65,6 +65,7 @@
 }
 
 void Codec::decodeFrames(const uint8_t *data, size_t size) {
+  RX_State_wb rx_state{};
   while (size > 0) {
     uint8_t modeByte = *data;
     bool quality = modeByte & 0x01;
@@ -81,7 +82,6 @@
     memcpy(inputBuf, data, minSize);
     int16 frameMode = mode;
     int16 frameType;
-    RX_State_wb rx_state;
     mime_unsorting(inputBuf, inputSampleBuf, &frameType, &frameMode, quality, &rx_state);
 
     int16_t numSamplesOutput;
diff --git a/media/libstagefright/codecs/amrwb/test/AmrwbDecoderTest.cpp b/media/libstagefright/codecs/amrwb/test/AmrwbDecoderTest.cpp
index 2aad81b..7221b92 100644
--- a/media/libstagefright/codecs/amrwb/test/AmrwbDecoderTest.cpp
+++ b/media/libstagefright/codecs/amrwb/test/AmrwbDecoderTest.cpp
@@ -74,6 +74,7 @@
     uint8_t inputBuf[kInputBufferSize];
     int16_t inputSampleBuf[kMaxSourceDataUnitSize];
     int16_t outputBuf[kOutputBufferSize];
+    RX_State_wb rx_state{};
 
     while (frameCount > 0) {
         uint8_t modeByte;
@@ -98,7 +99,6 @@
 
             int16 frameMode = mode;
             int16 frameType;
-            RX_State_wb rx_state;
             mime_unsorting(inputBuf, inputSampleBuf, &frameType, &frameMode, 1, &rx_state);
 
             int16_t numSamplesOutput;
diff --git a/media/libstagefright/codecs/amrwb/test/amrwbdec_test.cpp b/media/libstagefright/codecs/amrwb/test/amrwbdec_test.cpp
index b04bafd..1bc90e8 100644
--- a/media/libstagefright/codecs/amrwb/test/amrwbdec_test.cpp
+++ b/media/libstagefright/codecs/amrwb/test/amrwbdec_test.cpp
@@ -110,6 +110,7 @@
 
     // Decode loop.
     int retVal = EXIT_SUCCESS;
+    RX_State_wb rx_state{};
     while (1) {
         // Read mode.
         uint8_t modeByte;
@@ -134,7 +135,6 @@
             if (bytesRead != frameSize) break;
 
             int16 frameType, frameMode;
-            RX_State_wb rx_state;
             frameMode = mode;
             mime_unsorting(
                     (uint8_t *)inputBuf,
diff --git a/services/audioflinger/DeviceEffectManager.cpp b/services/audioflinger/DeviceEffectManager.cpp
index a3c3b84..5ff7215 100644
--- a/services/audioflinger/DeviceEffectManager.cpp
+++ b/services/audioflinger/DeviceEffectManager.cpp
@@ -144,7 +144,8 @@
         write(fd, result.string(), result.size());
     }
 
-    write(fd, "\nDevice Effects:\n", sizeof("\nDevice Effects:\n"));
+    String8 heading("\nDevice Effects:\n");
+    write(fd, heading.string(), heading.size());
     for (const auto& iter : mDeviceEffects) {
         String8 outStr;
         outStr.appendFormat("%*sEffect for device %s address %s:\n", 2, "",
diff --git a/services/audiopolicy/common/managerdefinitions/Android.bp b/services/audiopolicy/common/managerdefinitions/Android.bp
index fad3c5b..57f0b5b 100644
--- a/services/audiopolicy/common/managerdefinitions/Android.bp
+++ b/services/audiopolicy/common/managerdefinitions/Android.bp
@@ -25,12 +25,14 @@
         "libhidlbase",
         "liblog",
         "libmedia",
+        "libmedia_helper",
         "libutils",
         "libxml2",
     ],
     export_shared_lib_headers: [
         "libaudiofoundation",
         "libmedia",
+        "libmedia_helper",
     ],
     static_libs: [
         "libaudioutils",
diff --git a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
index a6562d7..dd1499c 100644
--- a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
@@ -28,6 +28,8 @@
 
 namespace android {
 
+class AudioPolicyClientInterface;
+
 class DeviceDescriptor : public DeviceDescriptorBase,
                          public PolicyAudioPort, public PolicyAudioPortConfig
 {
@@ -87,6 +89,8 @@
     void importAudioPortAndPickAudioProfile(const sp<PolicyAudioPort>& policyPort,
                                             bool force = false);
 
+    void setEncapsulationInfoFromHal(AudioPolicyClientInterface *clientInterface);
+
     void dump(String8 *dst, int spaces, int index, bool verbose = true) const;
 
 private:
diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
index 86dbba8..a29e60e 100644
--- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
@@ -17,9 +17,12 @@
 #define LOG_TAG "APM::Devices"
 //#define LOG_NDEBUG 0
 
-#include <audio_utils/string.h>
-#include <media/TypeConverter.h>
 #include <set>
+
+#include <AudioPolicyInterface.h>
+#include <audio_utils/string.h>
+#include <media/AudioParameter.h>
+#include <media/TypeConverter.h>
 #include "DeviceDescriptor.h"
 #include "TypeConverter.h"
 #include "HwModule.h"
@@ -165,6 +168,29 @@
     policyPort->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
 }
 
+void DeviceDescriptor::setEncapsulationInfoFromHal(
+        AudioPolicyClientInterface *clientInterface) {
+    AudioParameter param(String8(mDeviceTypeAddr.getAddress()));
+    param.addInt(String8(AudioParameter::keyRouting), mDeviceTypeAddr.mType);
+    param.addKey(String8(AUDIO_PARAMETER_DEVICE_SUP_ENCAPSULATION_MODES));
+    param.addKey(String8(AUDIO_PARAMETER_DEVICE_SUP_ENCAPSULATION_METADATA_TYPES));
+    String8 reply = clientInterface->getParameters(AUDIO_IO_HANDLE_NONE, param.toString());
+    AudioParameter repliedParameters(reply);
+    int value;
+    if (repliedParameters.getInt(
+            String8(AUDIO_PARAMETER_DEVICE_SUP_ENCAPSULATION_MODES), value) == NO_ERROR) {
+        if (setEncapsulationModes(value) != NO_ERROR) {
+            ALOGE("Failed to set encapsulation mode(%d)", value);
+        }
+    }
+    if (repliedParameters.getInt(
+            String8(AUDIO_PARAMETER_DEVICE_SUP_ENCAPSULATION_METADATA_TYPES), value) == NO_ERROR) {
+        if (setEncapsulationMetadataTypes(value) != NO_ERROR) {
+            ALOGE("Failed to set encapsulation metadata types(%d)", value);
+        }
+    }
+}
+
 void DeviceDescriptor::dump(String8 *dst, int spaces, int index, bool verbose) const
 {
     String8 extraInfo;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index bcf6f38..2a9a4c4 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -178,6 +178,9 @@
                 return INVALID_OPERATION;
             }
 
+            // Populate encapsulation information when a output device is connected.
+            device->setEncapsulationInfoFromHal(mpClientInterface);
+
             // outputs should never be empty here
             ALOG_ASSERT(outputs.size() != 0, "setDeviceConnectionState():"
                     "checkOutputsForDevice() returned no outputs but status OK");
@@ -4635,6 +4638,7 @@
                 if (!device->isAttached()) {
                     device->attach(hwModule);
                     mAvailableOutputDevices.add(device);
+                    device->setEncapsulationInfoFromHal(mpClientInterface);
                     if (newDevices) newDevices->add(device);
                     setEngineDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
                 }