Merge "CSD: Remove A2DP devices for CSD calculation" into udc-dev
diff --git a/media/libaudiofoundation/AudioProfile.cpp b/media/libaudiofoundation/AudioProfile.cpp
index 2170cd8..999e263 100644
--- a/media/libaudiofoundation/AudioProfile.cpp
+++ b/media/libaudiofoundation/AudioProfile.cpp
@@ -327,6 +327,24 @@
     return false;
 }
 
+const SampleRateSet AudioProfileVector::getSampleRatesFor(audio_format_t format) const {
+    for (const auto& profile : *this) {
+        if (profile->getFormat() == format) {
+            return profile->getSampleRates();
+        }
+    }
+    return {};
+}
+
+const ChannelMaskSet AudioProfileVector::getChannelMasksFor(audio_format_t format) const {
+    for (const auto& profile : *this) {
+        if (profile->getFormat() == format) {
+            return profile->getChannels();
+        }
+    }
+    return {};
+}
+
 bool AudioProfileVector::contains(const sp<AudioProfile>& profile, bool ignoreDynamicFlags) const
 {
     for (const auto& audioProfile : *this) {
diff --git a/media/libaudiofoundation/include/media/AudioProfile.h b/media/libaudiofoundation/include/media/AudioProfile.h
index 79dfd12..a668afe 100644
--- a/media/libaudiofoundation/include/media/AudioProfile.h
+++ b/media/libaudiofoundation/include/media/AudioProfile.h
@@ -139,6 +139,9 @@
     bool hasDynamicProfile() const;
     bool hasDynamicRateFor(audio_format_t format) const;
 
+    const SampleRateSet getSampleRatesFor(audio_format_t format) const;
+    const ChannelMaskSet getChannelMasksFor(audio_format_t format) const;
+
     bool contains(const sp<AudioProfile>& profile, bool ignoreDynamicFlags = false) const;
 
     virtual void dump(std::string *dst, int spaces) const;
diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp
index 25ee61a..aafe6e0 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalAidl.cpp
@@ -937,10 +937,13 @@
     return mModule->dump(fd, Args(args).args(), args.size());
 }
 
-int32_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports __unused) {
+int32_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports) {
     TIME_CHECK();
-    ALOGE("%s not implemented yet", __func__);
-    return INVALID_OPERATION;
+    if (!mModule) return NO_INIT;
+    if (supports == nullptr) {
+        return BAD_VALUE;
+    }
+    return statusTFromBinderStatus(mModule->supportsVariableLatency(supports));
 }
 
 status_t DeviceHalAidl::getSoundDoseInterface(const std::string& module,
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
index 5ab7c84..52fed91 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <cstddef>
 #include <cstdint>
 #include <cstring>
 #include <optional>
@@ -44,6 +45,7 @@
 using ::aidl::android::media::audio::common::AudioDeviceDescription;
 using ::aidl::android::media::audio::common::AudioMode;
 using ::aidl::android::media::audio::common::AudioSource;
+using ::android::hardware::EventFlag;
 using android::effect::utils::EffectParamReader;
 using android::effect::utils::EffectParamWriter;
 
@@ -127,6 +129,8 @@
 status_t EffectConversionHelperAidl::handleGetParameter(uint32_t cmdSize, const void* pCmdData,
                                                         uint32_t* replySize, void* pReplyData) {
     if (cmdSize < sizeof(effect_param_t) || !pCmdData || !replySize || !pReplyData) {
+        ALOGE("%s illegal cmdSize %u pCmdData %p replySize %p replyData %p", __func__, cmdSize,
+              pCmdData, replySize, pReplyData);
         return BAD_VALUE;
     }
 
@@ -183,8 +187,9 @@
     }
 
     if (state == State::INIT) {
-        ALOGI("%s at state %s, opening effect", __func__,
-              android::internal::ToString(state).c_str());
+        ALOGI("%s at state %s, opening effect with input %s output %s", __func__,
+              android::internal::ToString(state).c_str(), common.input.toString().c_str(),
+              common.output.toString().c_str());
         IEffect::OpenEffectReturn openReturn;
         RETURN_STATUS_IF_ERROR(
                 statusTFromBinderStatus(mEffect->open(common, std::nullopt, &openReturn)));
@@ -200,6 +205,11 @@
             mInputQ = std::make_shared<DataMQ>(openReturn.inputDataMQ);
             mOutputQ = std::make_shared<DataMQ>(openReturn.outputDataMQ);
         }
+
+        if (status_t status = updateEventFlags(); status != OK) {
+            mEffect->close();
+            return status;
+        }
         mCommon = common;
     } else if (mCommon != common) {
         ALOGI("%s at state %s, setParameter", __func__, android::internal::ToString(state).c_str());
@@ -343,6 +353,7 @@
         mStatusQ = std::make_shared<StatusMQ>(ret->statusMQ);
         mInputQ = std::make_shared<DataMQ>(ret->inputDataMQ);
         mOutputQ = std::make_shared<DataMQ>(ret->outputDataMQ);
+        RETURN_STATUS_IF_ERROR(updateEventFlags());
     }
     return *static_cast<int32_t*>(pReplyData) = OK;
 }
@@ -387,5 +398,20 @@
     return visualizerMeasure(replySize, pReplyData);
 }
 
+status_t EffectConversionHelperAidl::updateEventFlags() {
+    status_t status = BAD_VALUE;
+    EventFlag* efGroup = nullptr;
+    if (mStatusQ->isValid()) {
+        status = EventFlag::createEventFlag(mStatusQ->getEventFlagWord(), &efGroup);
+        if (status != OK || !efGroup) {
+            ALOGE("%s: create EventFlagGroup failed, ret %d, egGroup %p", __func__, status,
+                  efGroup);
+            status = (status == OK) ? BAD_VALUE : status;
+        }
+    }
+    mEfGroup.reset(efGroup, EventFlagDeleter());
+    return status;
+}
+
 }  // namespace effect
 }  // namespace android
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.h b/media/libaudiohal/impl/EffectConversionHelperAidl.h
index 1200264..0c682ff 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.h
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.h
@@ -40,6 +40,7 @@
     std::shared_ptr<StatusMQ> getStatusMQ() { return mStatusQ; }
     std::shared_ptr<DataMQ> getInputMQ() { return mInputQ; }
     std::shared_ptr<DataMQ> getOutputMQ() { return mOutputQ; }
+    std::shared_ptr<android::hardware::EventFlag> getEventFlagGroup() { return mEfGroup; }
 
   protected:
     const int32_t mSessionId;
@@ -85,6 +86,17 @@
     std::shared_ptr<StatusMQ> mStatusQ = nullptr;
     std::shared_ptr<DataMQ> mInputQ = nullptr, mOutputQ = nullptr;
 
+
+    struct EventFlagDeleter {
+        void operator()(::android::hardware::EventFlag* flag) const {
+            if (flag) {
+                ::android::hardware::EventFlag::deleteEventFlag(&flag);
+            }
+        }
+    };
+    std::shared_ptr<android::hardware::EventFlag> mEfGroup = nullptr;
+    status_t updateEventFlags();
+
     status_t handleInit(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
                         void* pReplyData);
     status_t handleSetConfig(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
@@ -121,6 +133,7 @@
     virtual status_t visualizerMeasure(uint32_t* replySize __unused, void* pReplyData __unused) {
         return BAD_VALUE;
     }
+
 };
 
 }  // namespace effect
diff --git a/media/libaudiohal/impl/EffectHalAidl.cpp b/media/libaudiohal/impl/EffectHalAidl.cpp
index d6135af..faf5f45 100644
--- a/media/libaudiohal/impl/EffectHalAidl.cpp
+++ b/media/libaudiohal/impl/EffectHalAidl.cpp
@@ -161,16 +161,17 @@
     return OK;
 }
 
-
 // write to input FMQ here, wait for statusMQ STATUS_OK, and read from output FMQ
 status_t EffectHalAidl::process() {
     auto statusQ = mConversion->getStatusMQ();
     auto inputQ = mConversion->getInputMQ();
     auto outputQ = mConversion->getOutputMQ();
+    auto efGroup = mConversion->getEventFlagGroup();
     if (!statusQ || !statusQ->isValid() || !inputQ || !inputQ->isValid() || !outputQ ||
-        !outputQ->isValid()) {
-        ALOGE("%s invalid FMQ [Status %d I %d O %d]", __func__, statusQ ? statusQ->isValid() : 0,
-              inputQ ? inputQ->isValid() : 0, outputQ ? outputQ->isValid() : 0);
+        !outputQ->isValid() || !efGroup) {
+        ALOGE("%s invalid FMQ [Status %d I %d O %d] efGroup %p", __func__,
+              statusQ ? statusQ->isValid() : 0, inputQ ? inputQ->isValid() : 0,
+              outputQ ? outputQ->isValid() : 0, efGroup.get());
         return INVALID_OPERATION;
     }
 
@@ -187,6 +188,7 @@
               floatsToWrite, mInBuffer->audioBuffer(), inputQ->availableToWrite());
         return INVALID_OPERATION;
     }
+    efGroup->wake(aidl::android::hardware::audio::effect::kEventFlagNotEmpty);
 
     IEffect::Status retStatus{};
     if (!statusQ->readBlocking(&retStatus, 1) || retStatus.status != OK ||
diff --git a/media/libaudiohal/impl/EffectHalAidl.h b/media/libaudiohal/impl/EffectHalAidl.h
index 8966363..47049d7 100644
--- a/media/libaudiohal/impl/EffectHalAidl.h
+++ b/media/libaudiohal/impl/EffectHalAidl.h
@@ -23,6 +23,7 @@
 #include <fmq/AidlMessageQueue.h>
 #include <media/audiohal/EffectHalInterface.h>
 #include <system/audio_effect.h>
+#include <system/audio_effects/aidl_effects_utils.h>
 
 #include "EffectConversionHelperAidl.h"
 
diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp
index 3048580..d40deae 100644
--- a/media/libaudiohal/impl/StreamHalAidl.cpp
+++ b/media/libaudiohal/impl/StreamHalAidl.cpp
@@ -167,9 +167,8 @@
     ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
     TIME_CHECK();
     values->clear();
-    if (!mStream) return NO_INIT;
-    ALOGE("%s not implemented yet", __func__);
-    return OK;
+    // AIDL HAL doesn't support getParameters API.
+    return INVALID_OPERATION;
 }
 
 status_t StreamHalAidl::getFrameSize(size_t *size) {
@@ -478,19 +477,6 @@
     return OK;
 }
 
-status_t StreamHalAidl::getHalPid(pid_t *pid __unused) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
-    TIME_CHECK();
-    if (!mStream) return NO_INIT;
-    ALOGE("%s not implemented yet", __func__);
-    return OK;
-}
-
-bool StreamHalAidl::requestHalThreadPriority(pid_t threadPid __unused, pid_t threadId __unused) {
-    // Obsolete, must be done by the HAL module.
-    return true;
-}
-
 status_t StreamHalAidl::legacyCreateAudioPatch(const struct audio_port_config& port __unused,
                                                std::optional<audio_source_t> source __unused,
                                                audio_devices_t type __unused) {
@@ -612,11 +598,10 @@
     return statusTFromBinderStatus(mStream->setHwVolume({left, right}));
 }
 
-status_t StreamOutHalAidl::selectPresentation(int presentationId __unused, int programId __unused) {
+status_t StreamOutHalAidl::selectPresentation(int presentationId, int programId) {
     TIME_CHECK();
     if (!mStream) return NO_INIT;
-    ALOGE("%s not implemented yet", __func__);
-    return OK;
+    return statusTFromBinderStatus(mStream->selectPresentation(presentationId, programId));
 }
 
 status_t StreamOutHalAidl::write(const void *buffer, size_t bytes, size_t *written) {
@@ -722,48 +707,61 @@
     return statusTFromBinderStatus(mStream->updateMetadata(aidlMetadata));
 }
 
-status_t StreamOutHalAidl::getDualMonoMode(audio_dual_mono_mode_t* mode __unused) {
+status_t StreamOutHalAidl::getDualMonoMode(audio_dual_mono_mode_t* mode) {
     TIME_CHECK();
     if (!mStream) return NO_INIT;
-    ALOGE("%s not implemented yet", __func__);
+    if (mode == nullptr) {
+        return BAD_VALUE;
+    }
+    ::aidl::android::media::audio::common::AudioDualMonoMode aidlMode;
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mStream->getDualMonoMode(&aidlMode)));
+    *mode = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(aidlMode));
     return OK;
 }
 
-status_t StreamOutHalAidl::setDualMonoMode(audio_dual_mono_mode_t mode __unused) {
+status_t StreamOutHalAidl::setDualMonoMode(audio_dual_mono_mode_t mode) {
     TIME_CHECK();
     if (!mStream) return NO_INIT;
-    ALOGE("%s not implemented yet", __func__);
+    ::aidl::android::media::audio::common::AudioDualMonoMode aidlMode = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(mode));
+    return statusTFromBinderStatus(mStream->setDualMonoMode(aidlMode));
+}
+
+status_t StreamOutHalAidl::getAudioDescriptionMixLevel(float* leveldB) {
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    if (leveldB == nullptr) {
+        return BAD_VALUE;
+    }
+    return statusTFromBinderStatus(mStream->getAudioDescriptionMixLevel(leveldB));
+}
+
+status_t StreamOutHalAidl::setAudioDescriptionMixLevel(float leveldB) {
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    return statusTFromBinderStatus(mStream->setAudioDescriptionMixLevel(leveldB));
+}
+
+status_t StreamOutHalAidl::getPlaybackRateParameters(audio_playback_rate_t* playbackRate) {
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    if (playbackRate == nullptr) {
+        return BAD_VALUE;
+    }
+    ::aidl::android::media::audio::common::AudioPlaybackRate aidlRate;
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mStream->getPlaybackRateParameters(&aidlRate)));
+    *playbackRate = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(aidlRate));
     return OK;
 }
 
-status_t StreamOutHalAidl::getAudioDescriptionMixLevel(float* leveldB __unused) {
+status_t StreamOutHalAidl::setPlaybackRateParameters(const audio_playback_rate_t& playbackRate) {
     TIME_CHECK();
     if (!mStream) return NO_INIT;
-    ALOGE("%s not implemented yet", __func__);
-    return OK;
-}
-
-status_t StreamOutHalAidl::setAudioDescriptionMixLevel(float leveldB __unused) {
-    TIME_CHECK();
-    if (!mStream) return NO_INIT;
-    ALOGE("%s not implemented yet", __func__);
-    return OK;
-}
-
-status_t StreamOutHalAidl::getPlaybackRateParameters(
-        audio_playback_rate_t* playbackRate __unused) {
-    TIME_CHECK();
-    if (!mStream) return NO_INIT;
-    ALOGE("%s not implemented yet", __func__);
-    return BAD_VALUE;
-}
-
-status_t StreamOutHalAidl::setPlaybackRateParameters(
-        const audio_playback_rate_t& playbackRate __unused) {
-    TIME_CHECK();
-    if (!mStream) return NO_INIT;
-    ALOGE("%s not implemented yet", __func__);
-    return BAD_VALUE;
+    ::aidl::android::media::audio::common::AudioPlaybackRate aidlRate = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(playbackRate));
+    return statusTFromBinderStatus(mStream->setPlaybackRateParameters(aidlRate));
 }
 
 status_t StreamOutHalAidl::setEventCallback(
@@ -776,18 +774,27 @@
     return OK;
 }
 
-status_t StreamOutHalAidl::setLatencyMode(audio_latency_mode_t mode __unused) {
+status_t StreamOutHalAidl::setLatencyMode(audio_latency_mode_t mode) {
     TIME_CHECK();
     if (!mStream) return NO_INIT;
-    ALOGE("%s not implemented yet", __func__);
-    return OK;
+    ::aidl::android::media::audio::common::AudioLatencyMode aidlMode = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::legacy2aidl_audio_latency_mode_t_AudioLatencyMode(mode));
+    return statusTFromBinderStatus(mStream->setLatencyMode(aidlMode));
 };
 
-status_t StreamOutHalAidl::getRecommendedLatencyModes(
-        std::vector<audio_latency_mode_t> *modes __unused) {
+status_t StreamOutHalAidl::getRecommendedLatencyModes(std::vector<audio_latency_mode_t> *modes) {
     TIME_CHECK();
     if (!mStream) return NO_INIT;
-    ALOGE("%s not implemented yet", __func__);
+    if (modes == nullptr) {
+        return BAD_VALUE;
+    }
+    std::vector<::aidl::android::media::audio::common::AudioLatencyMode> aidlModes;
+    RETURN_STATUS_IF_ERROR(
+            statusTFromBinderStatus(mStream->getRecommendedLatencyModes(&aidlModes)));
+    *modes = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::convertContainer<std::vector<audio_latency_mode_t>>(
+                    aidlModes,
+                    ::aidl::android::aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
     return OK;
 };
 
diff --git a/media/libaudiohal/impl/StreamHalAidl.h b/media/libaudiohal/impl/StreamHalAidl.h
index 147c131..75a1dd9 100644
--- a/media/libaudiohal/impl/StreamHalAidl.h
+++ b/media/libaudiohal/impl/StreamHalAidl.h
@@ -199,10 +199,6 @@
 
     ~StreamHalAidl() override;
 
-    status_t getHalPid(pid_t *pid);
-
-    bool requestHalThreadPriority(pid_t threadPid, pid_t threadId);
-
     status_t getLatency(uint32_t *latency);
 
     status_t getObservablePosition(int64_t *frames, int64_t *timestamp);
diff --git a/media/libaudioprocessing/include/media/BufferProviders.h b/media/libaudioprocessing/include/media/BufferProviders.h
index 7a41002..a0b025f 100644
--- a/media/libaudioprocessing/include/media/BufferProviders.h
+++ b/media/libaudioprocessing/include/media/BufferProviders.h
@@ -143,7 +143,7 @@
     bool isValid() const { return mIsValid; }
 
 protected:
-    audio_utils::channels::ChannelMix mChannelMix;
+    audio_utils::channels::ChannelMix<AUDIO_CHANNEL_OUT_STEREO> mChannelMix;
     bool mIsValid = false;
 };
 
diff --git a/media/libeffects/downmix/EffectDownmix.cpp b/media/libeffects/downmix/EffectDownmix.cpp
index d8f5787..7f8455a 100644
--- a/media/libeffects/downmix/EffectDownmix.cpp
+++ b/media/libeffects/downmix/EffectDownmix.cpp
@@ -40,7 +40,7 @@
     downmix_type_t type;
     bool apply_volume_correction;
     uint8_t input_channel_count;
-    android::audio_utils::channels::ChannelMix channelMix;
+    android::audio_utils::channels::ChannelMix<AUDIO_CHANNEL_OUT_STEREO> channelMix;
 };
 
 typedef struct downmix_module_s {
diff --git a/media/libeffects/downmix/aidl/DownmixContext.h b/media/libeffects/downmix/aidl/DownmixContext.h
index 9a9f2da..1571c38 100644
--- a/media/libeffects/downmix/aidl/DownmixContext.h
+++ b/media/libeffects/downmix/aidl/DownmixContext.h
@@ -56,7 +56,7 @@
     DownmixState mState;
     Downmix::Type mType;
     ::aidl::android::media::audio::common::AudioChannelLayout mChMask;
-    ::android::audio_utils::channels::ChannelMix mChannelMix;
+    ::android::audio_utils::channels::ChannelMix<AUDIO_CHANNEL_OUT_STEREO> mChannelMix;
 
     // Common Params
     void init_params(const Parameter::Common& common);
diff --git a/media/libeffects/downmix/benchmark/downmix_benchmark.cpp b/media/libeffects/downmix/benchmark/downmix_benchmark.cpp
index d9d40ed..c4e0d65 100644
--- a/media/libeffects/downmix/benchmark/downmix_benchmark.cpp
+++ b/media/libeffects/downmix/benchmark/downmix_benchmark.cpp
@@ -60,34 +60,35 @@
 static constexpr size_t kFrameCount = 1000;
 
 /*
-Pixel 4XL
-$ adb shell /data/benchmarktest/downmix_benchmark/vendor/downmix_benchmark
+Pixel 7
+$ atest downmix_benchmark
 
 --------------------------------------------------------
 Benchmark              Time             CPU   Iterations
 --------------------------------------------------------
-BM_Downmix/0        3638 ns         3624 ns       197517 AUDIO_CHANNEL_OUT_MONO
-BM_Downmix/1        4040 ns         4024 ns       178766
-BM_Downmix/2        4759 ns         4740 ns       134741 AUDIO_CHANNEL_OUT_STEREO
-BM_Downmix/3        6042 ns         6017 ns       129546 AUDIO_CHANNEL_OUT_2POINT1
-BM_Downmix/4        6897 ns         6868 ns        96316 AUDIO_CHANNEL_OUT_2POINT0POINT2
-BM_Downmix/5        2117 ns         2109 ns       331705 AUDIO_CHANNEL_OUT_QUAD
-BM_Downmix/6        2097 ns         2088 ns       335421 AUDIO_CHANNEL_OUT_QUAD_SIDE
-BM_Downmix/7        7291 ns         7263 ns        96256 AUDIO_CHANNEL_OUT_SURROUND
-BM_Downmix/8        8246 ns         8206 ns        84318 AUDIO_CHANNEL_OUT_2POINT1POINT2
-BM_Downmix/9        8341 ns         8303 ns        84298 AUDIO_CHANNEL_OUT_3POINT0POINT2
-BM_Downmix/10       7549 ns         7517 ns        84293 AUDIO_CHANNEL_OUT_PENTA
-BM_Downmix/11       9395 ns         9354 ns        75209 AUDIO_CHANNEL_OUT_3POINT1POINT2
-BM_Downmix/12       3267 ns         3253 ns       215596 AUDIO_CHANNEL_OUT_5POINT1
-BM_Downmix/13       3178 ns         3163 ns       220132 AUDIO_CHANNEL_OUT_5POINT1_SIDE
-BM_Downmix/14      10245 ns        10199 ns        67486 AUDIO_CHANNEL_OUT_6POINT1
-BM_Downmix/15      10975 ns        10929 ns        61359 AUDIO_CHANNEL_OUT_5POINT1POINT2
-BM_Downmix/16       3796 ns         3780 ns       184728 AUDIO_CHANNEL_OUT_7POINT1
-BM_Downmix/17      13562 ns        13503 ns        51823 AUDIO_CHANNEL_OUT_5POINT1POINT4
-BM_Downmix/18      13573 ns        13516 ns        51800 AUDIO_CHANNEL_OUT_7POINT1POINT2
-BM_Downmix/19      15502 ns        15435 ns        47147 AUDIO_CHANNEL_OUT_7POINT1POINT4
-BM_Downmix/20      16693 ns        16624 ns        42109 AUDIO_CHANNEL_OUT_13POINT_360RA
-BM_Downmix/21      28267 ns        28116 ns        24982 AUDIO_CHANNEL_OUT_22POINT2
+downmix_benchmark:
+  #BM_Downmix/0     2216 ns    2208 ns       308323
+  #BM_Downmix/1     2237 ns    2228 ns       314730
+  #BM_Downmix/2      270 ns     268 ns      2681469
+  #BM_Downmix/3     3016 ns    2999 ns       234146
+  #BM_Downmix/4     3331 ns    3313 ns       212026
+  #BM_Downmix/5      816 ns     809 ns       864395
+  #BM_Downmix/6      813 ns     809 ns       863876
+  #BM_Downmix/7     3336 ns    3319 ns       211938
+  #BM_Downmix/8     3786 ns    3762 ns       185047
+  #BM_Downmix/9     3810 ns    3797 ns       186840
+  #BM_Downmix/10    3767 ns    3746 ns       187015
+  #BM_Downmix/11    4212 ns    4191 ns       166119
+  #BM_Downmix/12    1245 ns    1231 ns       574388
+  #BM_Downmix/13    1234 ns    1228 ns       574743
+  #BM_Downmix/14    4795 ns    4771 ns       147157
+  #BM_Downmix/15    1334 ns    1327 ns       527728
+  #BM_Downmix/16    1346 ns    1332 ns       525444
+  #BM_Downmix/17    2144 ns    2121 ns       333343
+  #BM_Downmix/18    2133 ns    2118 ns       330391
+  #BM_Downmix/19    2527 ns    2513 ns       278553
+  #BM_Downmix/20    8148 ns    8113 ns        86136
+  #BM_Downmix/21    6332 ns    6301 ns       111134
 */
 
 static void BM_Downmix(benchmark::State& state) {
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp
index f1619a8..1fed9a5 100644
--- a/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp
@@ -67,7 +67,7 @@
                 DynamicsProcessing::engineArchitecture>(DynamicsProcessing::EngineArchitecture(
                 {.resolutionPreference =
                          DynamicsProcessing::ResolutionPreference::FAVOR_FREQUENCY_RESOLUTION,
-                 .preferredProcessingDurationMs = 0,
+                 .preferredProcessingDurationMs = 1.0f,
                  .preEqStage = {.inUse = false, .bandCount = 0},
                  .postEqStage = {.inUse = false, .bandCount = 0},
                  .mbcStage = {.inUse = false, .bandCount = 0},
@@ -75,11 +75,11 @@
         .max = DynamicsProcessing::make<
                 DynamicsProcessing::engineArchitecture>(DynamicsProcessing::EngineArchitecture(
                 {.resolutionPreference =
-                         DynamicsProcessing::ResolutionPreference::FAVOR_FREQUENCY_RESOLUTION,
-                 .preferredProcessingDurationMs = std::numeric_limits<float>::max(),
-                 .preEqStage = {.inUse = true, .bandCount = std::numeric_limits<int>::max()},
-                 .postEqStage = {.inUse = true, .bandCount = std::numeric_limits<int>::max()},
-                 .mbcStage = {.inUse = true, .bandCount = std::numeric_limits<int>::max()},
+                         DynamicsProcessing::ResolutionPreference::FAVOR_TIME_RESOLUTION,
+                 .preferredProcessingDurationMs = 1000.0f,
+                 .preEqStage = {.inUse = true, .bandCount = 128},
+                 .postEqStage = {.inUse = true, .bandCount = 128},
+                 .mbcStage = {.inUse = true, .bandCount = 128},
                  .limiterInUse = true}))};
 
 static const DynamicsProcessing::ChannelConfig kChannelConfigMin =
@@ -105,15 +105,15 @@
         DynamicsProcessing::EqBandConfig({.channel = 0,
                                           .band = 0,
                                           .enable = false,
-                                          .cutoffFrequencyHz = 220,
-                                          .gainDb = std::numeric_limits<float>::lowest()});
+                                          .cutoffFrequencyHz = 20,
+                                          .gainDb = -200});
 
 static const DynamicsProcessing::EqBandConfig kEqBandConfigMax =
         DynamicsProcessing::EqBandConfig({.channel = std::numeric_limits<int>::max(),
                                           .band = std::numeric_limits<int>::max(),
                                           .enable = true,
                                           .cutoffFrequencyHz = 20000,
-                                          .gainDb = std::numeric_limits<float>::max()});
+                                          .gainDb = 200});
 
 static const Range::DynamicsProcessingRange kPreEqBandConfigRange = {
         .min = DynamicsProcessing::make<DynamicsProcessing::preEqBand>({kEqBandConfigMin}),
@@ -129,39 +129,39 @@
                         {.channel = 0,
                          .band = 0,
                          .enable = false,
-                         .cutoffFrequencyHz = 220,
+                         .cutoffFrequencyHz = 20,
                          .attackTimeMs = 0,
                          .releaseTimeMs = 0,
-                         .ratio = 0,
-                         .thresholdDb = std::numeric_limits<float>::lowest(),
+                         .ratio = 1,
+                         .thresholdDb = -200,
                          .kneeWidthDb = 0,
-                         .noiseGateThresholdDb = std::numeric_limits<float>::lowest(),
-                         .expanderRatio = 0,
-                         .preGainDb = std::numeric_limits<float>::lowest(),
-                         .postGainDb = std::numeric_limits<float>::lowest()})}),
+                         .noiseGateThresholdDb = -200,
+                         .expanderRatio = 1,
+                         .preGainDb = -200,
+                         .postGainDb = -200})}),
         .max = DynamicsProcessing::make<DynamicsProcessing::mbcBand>(
                 {DynamicsProcessing::MbcBandConfig(
                         {.channel = std::numeric_limits<int>::max(),
                          .band = std::numeric_limits<int>::max(),
                          .enable = true,
                          .cutoffFrequencyHz = 20000,
-                         .attackTimeMs = std::numeric_limits<float>::max(),
-                         .releaseTimeMs = std::numeric_limits<float>::max(),
-                         .ratio = std::numeric_limits<float>::max(),
-                         .thresholdDb = 0,
-                         .kneeWidthDb = std::numeric_limits<float>::max(),
-                         .noiseGateThresholdDb = 0,
-                         .expanderRatio = std::numeric_limits<float>::max(),
-                         .preGainDb = std::numeric_limits<float>::max(),
-                         .postGainDb = std::numeric_limits<float>::max()})})};
+                         .attackTimeMs = 60000,
+                         .releaseTimeMs = 60000,
+                         .ratio = 50,
+                         .thresholdDb = 200,
+                         .kneeWidthDb = 100,
+                         .noiseGateThresholdDb = 200,
+                         .expanderRatio = 50,
+                         .preGainDb = 200,
+                         .postGainDb = 200})})};
 
 static const Range::DynamicsProcessingRange kInputGainRange = {
         .min = DynamicsProcessing::make<DynamicsProcessing::inputGain>(
                 {DynamicsProcessing::InputGain(
-                        {.channel = 0, .gainDb = std::numeric_limits<float>::lowest()})}),
+                        {.channel = 0, .gainDb = -200.0f})}),
         .max = DynamicsProcessing::make<DynamicsProcessing::inputGain>(
                 {DynamicsProcessing::InputGain({.channel = std::numeric_limits<int>::max(),
-                                                .gainDb = std::numeric_limits<float>::max()})})};
+                                                .gainDb = 200.0f})})};
 
 static const Range::DynamicsProcessingRange kLimiterRange = {
         .min = DynamicsProcessing::make<DynamicsProcessing::limiter>(
@@ -171,19 +171,19 @@
                          .linkGroup = std::numeric_limits<int>::min(),
                          .attackTimeMs = 0,
                          .releaseTimeMs = 0,
-                         .ratio = 0,
-                         .thresholdDb = std::numeric_limits<float>::min(),
-                         .postGainDb = std::numeric_limits<float>::min()})}),
+                         .ratio = 1,
+                         .thresholdDb = -200,
+                         .postGainDb = -200})}),
         .max = DynamicsProcessing::make<DynamicsProcessing::limiter>(
                 {DynamicsProcessing::LimiterConfig(
                         {.channel = std::numeric_limits<int>::max(),
                          .enable = true,
                          .linkGroup = std::numeric_limits<int>::max(),
-                         .attackTimeMs = std::numeric_limits<float>::max(),
-                         .releaseTimeMs = std::numeric_limits<float>::max(),
-                         .ratio = std::numeric_limits<float>::max(),
-                         .thresholdDb = 0,
-                         .postGainDb = std::numeric_limits<float>::max()})})};
+                         .attackTimeMs = 60000,
+                         .releaseTimeMs = 60000,
+                         .ratio = 50,
+                         .thresholdDb = 200,
+                         .postGainDb = 200})})};
 
 const std::vector<Range::DynamicsProcessingRange> kRanges = {
         kEngineConfigRange,     kPreEqChannelConfigRange, kPostEqChannelConfigRange,
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 569a25f..ec6a00a 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -79,6 +79,7 @@
     },
 }
 
+// this library gets wrapped into libstagefright as well as modules
 cc_library_static {
     name: "libstagefright_mpeg2extractor",
     apex_available: [
@@ -241,7 +242,6 @@
         "CodecErrorLog.cpp",
         "CryptoAsync.cpp",
         "FrameDecoder.cpp",
-        "HevcUtils.cpp",
         "InterfaceUtils.cpp",
         "JPEGSource.cpp",
         "MPEG2TSWriter.cpp",
@@ -255,7 +255,6 @@
         "MediaCodecSource.cpp",
         "MediaExtractor.cpp",
         "MediaExtractorFactory.cpp",
-        "MediaSource.cpp",
         "MediaSync.cpp",
         "MediaTrack.cpp",
         "MediaMuxer.cpp",
@@ -269,7 +268,6 @@
         "StagefrightMediaScanner.cpp",
         "SurfaceUtils.cpp",
         "ThrottledSource.cpp",
-        "Utils.cpp",
         "VideoFrameSchedulerBase.cpp",
         "VideoFrameScheduler.cpp",
     ],
@@ -328,6 +326,11 @@
         "libmedia_ndkformatpriv",
     ],
 
+    // to get Utils, MediaSource, HevcUtils
+    whole_static_libs: [
+        "libstagefright_mpeg2extractor",
+    ],
+
     header_libs:[
         "libmediadrm_headers",
         "libnativeloader-headers",
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index d736734..28ca9ff 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -298,6 +298,9 @@
     size_t psshsize;
     if (meta->findData(kKeyPssh, &type, &pssh, &psshsize)) {
         sp<ABuffer> buf = new ABuffer(psshsize);
+        if (buf->data() == nullptr) {
+            return -ENOMEM;
+        }
         memcpy(buf->data(), pssh, psshsize);
         (*format)->setBuffer("pssh", buf);
     }
@@ -308,6 +311,9 @@
     if (meta->findData(kKeySlowMotionMarkers, &type, &slomoMarkers, &slomoMarkersSize)
             && slomoMarkersSize > 0) {
         sp<ABuffer> buf = new ABuffer(slomoMarkersSize);
+        if (buf->data() == nullptr) {
+            return -ENOMEM;
+        }
         memcpy(buf->data(), slomoMarkers, slomoMarkersSize);
         (*format)->setBuffer("slow-motion-markers", buf);
     }
@@ -639,6 +645,7 @@
         numPageSamples = -1;
     }
 
+    // caller has verified there is sufficient space
     // insert, including accounting for the space used.
     memcpy((uint8_t *)buffer->data() + mbuf->range_length(),
            &numPageSamples,
diff --git a/media/utils/include/mediautils/SharedMemoryAllocator.h b/media/utils/include/mediautils/SharedMemoryAllocator.h
index 17c1ac9..79621e2 100644
--- a/media/utils/include/mediautils/SharedMemoryAllocator.h
+++ b/media/utils/include/mediautils/SharedMemoryAllocator.h
@@ -22,6 +22,7 @@
 
 #include <iomanip>
 #include <limits>
+#include <mutex>
 #include <sstream>
 #include <string>
 #include <type_traits>
@@ -109,13 +110,14 @@
 // TODO is there some way to avoid paying this cost?
 template <typename Allocator>
 class ScopedAllocator;
-template <typename AllocationT, typename AllocatorHandleType>
+
 class ScopedAllocation : public BnMemory {
   public:
     template <typename T>
     friend class ScopedAllocator;
-    ScopedAllocation(const AllocationT& allocation, const AllocatorHandleType& handle)
-        : mAllocation(allocation), mHandle(handle) {}
+    template <typename Deallocator>
+    ScopedAllocation(const AllocationType& allocation, Deallocator&& deallocator)
+        : mAllocation(allocation), mDeallocator(std::forward<Deallocator>(deallocator)) {}
 
     // Defer the implementation to the underlying mAllocation
 
@@ -125,10 +127,10 @@
     }
 
   private:
-    ~ScopedAllocation() override { mHandle->deallocate(mAllocation); }
+    ~ScopedAllocation() override { mDeallocator(mAllocation); }
 
-    const AllocationT mAllocation;
-    const AllocatorHandleType mHandle;
+    const AllocationType mAllocation;
+    const std::function<void(const AllocationType&)> mDeallocator;
 };
 
 // Allocations are only deallocated when going out of scope.
@@ -136,7 +138,6 @@
 template <typename Allocator>
 class ScopedAllocator {
   public:
-    using HandleT = std::shared_ptr<Allocator>;
     static constexpr size_t alignment() { return Allocator::alignment(); }
 
     explicit ScopedAllocator(const std::shared_ptr<Allocator>& allocator) : mAllocator(allocator) {}
@@ -145,11 +146,16 @@
 
     template <typename T>
     auto allocate(T&& request) {
+        std::lock_guard l{*mLock};
         const auto allocation = mAllocator->allocate(std::forward<T>(request));
         if (!allocation) {
-            return sp<ScopedAllocation<AllocationType, HandleT>>{};
+            return sp<ScopedAllocation>{};
         }
-        return sp<ScopedAllocation<AllocationType, HandleT>>::make(allocation, mAllocator);
+        return sp<ScopedAllocation>::make(allocation,
+                [allocator = mAllocator, lock = mLock] (const AllocationType& allocation) {
+                    std::lock_guard l{*lock};
+                    allocator->deallocate(allocation);
+                });
     }
 
     // Deallocate and deallocate_all are implicitly unsafe due to double
@@ -159,20 +165,23 @@
     //
     // Owns is only safe to pseudo-impl due to static cast reqs
     template <typename Enable = bool>
-    auto owns(const sp<ScopedAllocation<AllocationType, HandleT>>& allocation) const
+    auto owns(const sp<ScopedAllocation>& allocation) const
             -> std::enable_if_t<shared_allocator_impl::has_owns<Allocator>, Enable> {
+        std::lock_guard l{*mLock};
         return mAllocator->owns(allocation->mAllocation);
     }
 
     template <typename Enable = std::string>
     auto dump() const -> std::enable_if_t<shared_allocator_impl::has_dump<Allocator>, Enable> {
+        std::lock_guard l{*mLock};
         return mAllocator->dump();
     }
 
   private:
     // We store a shared pointer in order to ensure that the allocator outlives
     // allocations (which call back to become dereferenced).
-    const HandleT mAllocator;
+    const std::shared_ptr<Allocator> mAllocator;
+    const std::shared_ptr<std::mutex> mLock = std::make_shared<std::mutex>();
 };
 
 // A simple policy for PolicyAllocator which enforces a pool size and an allocation
diff --git a/services/audiopolicy/common/include/policy.h b/services/audiopolicy/common/include/policy.h
index de8e77f..d266e63 100644
--- a/services/audiopolicy/common/include/policy.h
+++ b/services/audiopolicy/common/include/policy.h
@@ -218,12 +218,15 @@
         return *(deviceTypes.begin());
     } else {
         // Multiple device selection is either:
+        //  - dock + one other device: give priority to dock in this case.
         //  - speaker + one other device: give priority to speaker in this case.
         //  - one A2DP device + another device: happens with duplicated output. In this case
         // retain the device on the A2DP output as the other must not correspond to an active
         // selection if not the speaker.
         //  - HDMI-CEC system audio mode only output: give priority to available item in order.
-        if (deviceTypes.count(AUDIO_DEVICE_OUT_SPEAKER) != 0) {
+        if (deviceTypes.count(AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) != 0) {
+            return AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
+        } else if (deviceTypes.count(AUDIO_DEVICE_OUT_SPEAKER) != 0) {
             return AUDIO_DEVICE_OUT_SPEAKER;
         } else if (deviceTypes.count(AUDIO_DEVICE_OUT_SPEAKER_SAFE) != 0) {
             return AUDIO_DEVICE_OUT_SPEAKER_SAFE;
diff --git a/services/audiopolicy/engine/common/include/EngineBase.h b/services/audiopolicy/engine/common/include/EngineBase.h
index bc780f1..7ff0301 100644
--- a/services/audiopolicy/engine/common/include/EngineBase.h
+++ b/services/audiopolicy/engine/common/include/EngineBase.h
@@ -169,6 +169,12 @@
 
     void updateDeviceSelectionCache() override;
 
+protected:
+    DeviceVector getPreferredAvailableDevicesForProductStrategy(
+        const DeviceVector& availableOutputDevices, product_strategy_t strategy) const;
+    DeviceVector getDisabledDevicesForProductStrategy(
+        const DeviceVector& availableOutputDevices, product_strategy_t strategy) const;
+
 private:
     /**
      * Get media devices as the given role
diff --git a/services/audiopolicy/engine/common/src/EngineBase.cpp b/services/audiopolicy/engine/common/src/EngineBase.cpp
index 471424c..5769a97 100644
--- a/services/audiopolicy/engine/common/src/EngineBase.cpp
+++ b/services/audiopolicy/engine/common/src/EngineBase.cpp
@@ -705,6 +705,38 @@
     }
 }
 
+DeviceVector EngineBase::getPreferredAvailableDevicesForProductStrategy(
+        const DeviceVector& availableOutputDevices, product_strategy_t strategy) const {
+    DeviceVector preferredAvailableDevVec = {};
+    AudioDeviceTypeAddrVector preferredStrategyDevices;
+    const status_t status = getDevicesForRoleAndStrategy(
+            strategy, DEVICE_ROLE_PREFERRED, preferredStrategyDevices);
+    if (status == NO_ERROR) {
+        // there is a preferred device, is it available?
+        preferredAvailableDevVec =
+                availableOutputDevices.getDevicesFromDeviceTypeAddrVec(preferredStrategyDevices);
+        if (preferredAvailableDevVec.size() == preferredStrategyDevices.size()) {
+            ALOGV("%s using pref device %s for strategy %u",
+                   __func__, preferredAvailableDevVec.toString().c_str(), strategy);
+            return preferredAvailableDevVec;
+        }
+    }
+    return preferredAvailableDevVec;
+}
+
+DeviceVector EngineBase::getDisabledDevicesForProductStrategy(
+        const DeviceVector &availableOutputDevices, product_strategy_t strategy) const {
+    DeviceVector disabledDevices = {};
+    AudioDeviceTypeAddrVector disabledDevicesTypeAddr;
+    const status_t status = getDevicesForRoleAndStrategy(
+            strategy, DEVICE_ROLE_DISABLED, disabledDevicesTypeAddr);
+    if (status == NO_ERROR) {
+        disabledDevices =
+                availableOutputDevices.getDevicesFromDeviceTypeAddrVec(disabledDevicesTypeAddr);
+    }
+    return disabledDevices;
+}
+
 void EngineBase::dumpCapturePresetDevicesRoleMap(String8 *dst, int spaces) const
 {
     dst->appendFormat("\n%*sDevice role per capture preset dump:", spaces, "");
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.cpp b/services/audiopolicy/engineconfigurable/src/Engine.cpp
index 64f6cb4..a7f92cd 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Engine.cpp
@@ -165,6 +165,21 @@
     return mPolicyParameterMgr->getForceUse(usage);
 }
 
+status_t Engine::setOutputDevicesConnectionState(const DeviceVector &devices,
+                                                 audio_policy_dev_state_t state)
+{
+    for (const auto &device : devices) {
+        mPolicyParameterMgr->setDeviceConnectionState(device->type(), device->address(), state);
+    }
+    DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
+    if (state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) {
+        availableOutputDevices.remove(devices);
+    } else {
+        availableOutputDevices.add(devices);
+    }
+    return mPolicyParameterMgr->setAvailableOutputDevices(availableOutputDevices.types());
+}
+
 status_t Engine::setDeviceConnectionState(const sp<DeviceDescriptor> device,
                                           audio_policy_dev_state_t state)
 {
@@ -205,17 +220,126 @@
     return result.nbSkippedElement == 0? NO_ERROR : BAD_VALUE;
 }
 
+status_t Engine::setDevicesRoleForStrategy(product_strategy_t strategy, device_role_t role,
+                                           const AudioDeviceTypeAddrVector &devices)
+{
+    DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
+    DeviceVector prevDisabledDevices =
+            getDisabledDevicesForProductStrategy(availableOutputDevices, strategy);
+    status_t status = EngineBase::setDevicesRoleForStrategy(strategy, role, devices);
+    if (status != NO_ERROR) {
+        return status;
+    }
+    DeviceVector newDisabledDevices =
+            getDisabledDevicesForProductStrategy(availableOutputDevices, strategy);
+    if (role == DEVICE_ROLE_PREFERRED) {
+        DeviceVector reenabledDevices = prevDisabledDevices;
+        reenabledDevices.remove(newDisabledDevices);
+        if (reenabledDevices.empty()) {
+            ALOGD("%s DEVICE_ROLE_PREFERRED empty renabled devices", __func__);
+            return status;
+        }
+        // some devices were moved from disabled to preferred, need to force a resync for these
+        enableDevicesForStrategy(strategy, prevDisabledDevices);
+    }
+    if (newDisabledDevices.empty()) {
+        return status;
+    }
+    return disableDevicesForStrategy(strategy, newDisabledDevices);
+}
+
+status_t Engine::removeDevicesRoleForStrategy(product_strategy_t strategy, device_role_t role,
+        const AudioDeviceTypeAddrVector &devices)
+{
+    const auto productStrategies = getProductStrategies();
+    if (productStrategies.find(strategy) == end(productStrategies)) {
+        ALOGE("%s invalid %d", __func__, strategy);
+        return BAD_VALUE;
+    }
+    DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
+    DeviceVector prevDisabledDevices =
+            getDisabledDevicesForProductStrategy(availableOutputDevices, strategy);
+    status_t status = EngineBase::removeDevicesRoleForStrategy(strategy, role, devices);
+    if (status != NO_ERROR || role == DEVICE_ROLE_PREFERRED) {
+        return status;
+    }
+    // Removing ROLE_DISABLED for given devices, need to force a resync for these
+    enableDevicesForStrategy(strategy, prevDisabledDevices);
+
+    DeviceVector remainingDisabledDevices = getDisabledDevicesForProductStrategy(
+            availableOutputDevices, strategy);
+    if (remainingDisabledDevices.empty()) {
+        return status;
+    }
+    return disableDevicesForStrategy(strategy, remainingDisabledDevices);
+}
+
+status_t Engine::clearDevicesRoleForStrategy(product_strategy_t strategy, device_role_t role)
+{
+    const auto productStrategies = getProductStrategies();
+    if (productStrategies.find(strategy) == end(productStrategies)) {
+        ALOGE("%s invalid %d", __func__, strategy);
+        return BAD_VALUE;
+    }
+    DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
+    DeviceVector prevDisabledDevices =
+            getDisabledDevicesForProductStrategy(availableOutputDevices, strategy);
+    status_t status = EngineBase::clearDevicesRoleForStrategy(strategy, role);
+    if (status != NO_ERROR || role == DEVICE_ROLE_PREFERRED || prevDisabledDevices.empty()) {
+        return status;
+    }
+    // Disabled devices were removed, need to force a resync for these
+    enableDevicesForStrategy(strategy, prevDisabledDevices);
+    return NO_ERROR;
+}
+
+void Engine::enableDevicesForStrategy(product_strategy_t strategy __unused,
+        const DeviceVector &devicesToEnable) {
+    // devices were (re)enabled, need to force a resync for these
+    setOutputDevicesConnectionState(devicesToEnable, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE);
+    setOutputDevicesConnectionState(devicesToEnable, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
+}
+
+status_t Engine::disableDevicesForStrategy(product_strategy_t strategy,
+        const DeviceVector &devicesToDisable) {
+    // Filter out disabled devices for this strategy.
+    // However, to update the output device decision, availability criterion shall be updated,
+    // which may impact other strategies. So, as a WA, reconsider now and later to prevent from
+    // altering decision for other strategies;
+    setOutputDevicesConnectionState(devicesToDisable, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE);
+
+    DeviceTypeSet deviceTypes = getProductStrategies().getDeviceTypesForProductStrategy(strategy);
+    const std::string address(getProductStrategies().getDeviceAddressForProductStrategy(strategy));
+
+    setOutputDevicesConnectionState(devicesToDisable, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
+
+    // Force reapply devices for given strategy
+    getProductStrategies().at(strategy)->setDeviceTypes(deviceTypes);
+    setDeviceAddressForProductStrategy(strategy, address);
+    return NO_ERROR;
+}
+
 DeviceVector Engine::getDevicesForProductStrategy(product_strategy_t ps) const
 {
+    DeviceVector selectedDevices = {};
+    DeviceVector disabledDevices = {};
     const auto productStrategies = getProductStrategies();
     if (productStrategies.find(ps) == productStrategies.end()) {
         ALOGE("%s: Trying to get device on invalid strategy %d", __FUNCTION__, ps);
-        return {};
+        return selectedDevices;
     }
-    const DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
+    DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
     const SwAudioOutputCollection &outputs = getApmObserver()->getOutputs();
     DeviceTypeSet availableOutputDevicesTypes = availableOutputDevices.types();
 
+    // check if this strategy has a preferred device that is available,
+    // if yes, give priority to it.
+    DeviceVector preferredAvailableDevVec =
+            getPreferredAvailableDevicesForProductStrategy(availableOutputDevices, ps);
+    if (!preferredAvailableDevVec.isEmpty()) {
+        return preferredAvailableDevVec;
+    }
+
     /** This is the only case handled programmatically because the PFW is unable to know the
      * activity of streams.
      *
@@ -227,33 +351,34 @@
      * -When media is not playing anymore, fall back on the sonification behavior
      */
     DeviceTypeSet deviceTypes;
+    product_strategy_t psOrFallback = ps;
     if (ps == getProductStrategyForStream(AUDIO_STREAM_NOTIFICATION) &&
             !is_state_in_call(getPhoneState()) &&
             !outputs.isActiveRemotely(toVolumeSource(AUDIO_STREAM_MUSIC),
                                       SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY) &&
             outputs.isActive(toVolumeSource(AUDIO_STREAM_MUSIC),
                              SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) {
-        product_strategy_t strategyForMedia =
-                getProductStrategyForStream(AUDIO_STREAM_MUSIC);
-        deviceTypes = productStrategies.getDeviceTypesForProductStrategy(strategyForMedia);
+        psOrFallback = getProductStrategyForStream(AUDIO_STREAM_MUSIC);
     } else if (ps == getProductStrategyForStream(AUDIO_STREAM_ACCESSIBILITY) &&
         (outputs.isActive(toVolumeSource(AUDIO_STREAM_RING)) ||
          outputs.isActive(toVolumeSource(AUDIO_STREAM_ALARM)))) {
             // do not route accessibility prompts to a digital output currently configured with a
             // compressed format as they would likely not be mixed and dropped.
             // Device For Sonification conf file has HDMI, SPDIF and HDMI ARC unreacheable.
-        product_strategy_t strategyNotification = getProductStrategyForStream(AUDIO_STREAM_RING);
-        deviceTypes = productStrategies.getDeviceTypesForProductStrategy(strategyNotification);
-    } else {
-        deviceTypes = productStrategies.getDeviceTypesForProductStrategy(ps);
+        psOrFallback = getProductStrategyForStream(AUDIO_STREAM_RING);
     }
+    disabledDevices = getDisabledDevicesForProductStrategy(availableOutputDevices, psOrFallback);
+    deviceTypes = productStrategies.getDeviceTypesForProductStrategy(psOrFallback);
+    // In case a fallback is decided on other strategy, prevent from selecting this device if
+    // disabled for current strategy.
+    availableOutputDevices.remove(disabledDevices);
+
     if (deviceTypes.empty() ||
             Intersection(deviceTypes, availableOutputDevicesTypes).empty()) {
         auto defaultDevice = getApmObserver()->getDefaultOutputDevice();
         ALOG_ASSERT(defaultDevice != nullptr, "no valid default device defined");
-        return DeviceVector(defaultDevice);
-    }
-    if (/*device_distinguishes_on_address(*deviceTypes.begin())*/ isSingleDeviceType(
+        selectedDevices = DeviceVector(defaultDevice);
+    } else if (/*device_distinguishes_on_address(*deviceTypes.begin())*/ isSingleDeviceType(
             deviceTypes, AUDIO_DEVICE_OUT_BUS)) {
         // We do expect only one device for these types of devices
         // Criterion device address garantee this one is available
@@ -268,12 +393,15 @@
                   dumpDeviceTypes(deviceTypes).c_str(), address.c_str());
             auto defaultDevice = getApmObserver()->getDefaultOutputDevice();
             ALOG_ASSERT(defaultDevice != nullptr, "Default Output Device NOT available");
-            return DeviceVector(defaultDevice);
+            selectedDevices = DeviceVector(defaultDevice);
+        } else {
+            selectedDevices = DeviceVector(busDevice);
         }
-        return DeviceVector(busDevice);
+    } else {
+        ALOGV("%s:device %s %d", __FUNCTION__, dumpDeviceTypes(deviceTypes).c_str(), ps);
+        selectedDevices = availableOutputDevices.getDevicesFromTypes(deviceTypes);
     }
-    ALOGV("%s:device %s %d", __FUNCTION__, dumpDeviceTypes(deviceTypes).c_str(), ps);
-    return availableOutputDevices.getDevicesFromTypes(deviceTypes);
+    return selectedDevices;
 }
 
 DeviceVector Engine::getOutputDevicesForAttributes(const audio_attributes_t &attributes,
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.h b/services/audiopolicy/engineconfigurable/src/Engine.h
index d97efc7..8ea8052 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.h
+++ b/services/audiopolicy/engineconfigurable/src/Engine.h
@@ -67,6 +67,13 @@
                                                      sp<AudioPolicyMix> *mix = nullptr)
                                                      const override;
 
+    status_t setDevicesRoleForStrategy(product_strategy_t strategy, device_role_t role,
+                                       const AudioDeviceTypeAddrVector &devices) override;
+
+    status_t removeDevicesRoleForStrategy(product_strategy_t strategy, device_role_t role,
+                const AudioDeviceTypeAddrVector &devices) override;
+    status_t clearDevicesRoleForStrategy(product_strategy_t strategy, device_role_t role) override;
+
     ///
     /// from AudioPolicyPluginInterface
     ///
@@ -94,6 +101,12 @@
     }
 
 private:
+    android::status_t disableDevicesForStrategy(product_strategy_t strategy,
+            const DeviceVector &devicesToDisable);
+    void enableDevicesForStrategy(product_strategy_t strategy, const DeviceVector &devicesToEnable);
+    android::status_t setOutputDevicesConnectionState(const DeviceVector &devices,
+                                                      audio_policy_dev_state_t state);
+
     /* Copy facilities are put private to disable copy. */
     Engine(const Engine &object);
     Engine &operator=(const Engine &object);
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index ea56486..84e7cb8 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -730,38 +730,6 @@
     return AUDIO_DEVICE_NONE;
 }
 
-DeviceVector Engine::getPreferredAvailableDevicesForProductStrategy(
-        const DeviceVector& availableOutputDevices, product_strategy_t strategy) const {
-    DeviceVector preferredAvailableDevVec = {};
-    AudioDeviceTypeAddrVector preferredStrategyDevices;
-    const status_t status = getDevicesForRoleAndStrategy(
-            strategy, DEVICE_ROLE_PREFERRED, preferredStrategyDevices);
-    if (status == NO_ERROR) {
-        // there is a preferred device, is it available?
-        preferredAvailableDevVec =
-                availableOutputDevices.getDevicesFromDeviceTypeAddrVec(preferredStrategyDevices);
-        if (preferredAvailableDevVec.size() == preferredStrategyDevices.size()) {
-            ALOGVV("%s using pref device %s for strategy %u",
-                   __func__, preferredAvailableDevVec.toString().c_str(), strategy);
-            return preferredAvailableDevVec;
-        }
-    }
-    return preferredAvailableDevVec;
-}
-
-DeviceVector Engine::getDisabledDevicesForProductStrategy(
-        const DeviceVector &availableOutputDevices, product_strategy_t strategy) const {
-    DeviceVector disabledDevices = {};
-    AudioDeviceTypeAddrVector disabledDevicesTypeAddr;
-    const status_t status = getDevicesForRoleAndStrategy(
-            strategy, DEVICE_ROLE_DISABLED, disabledDevicesTypeAddr);
-    if (status == NO_ERROR) {
-        disabledDevices =
-                availableOutputDevices.getDevicesFromDeviceTypeAddrVec(disabledDevicesTypeAddr);
-    }
-    return disabledDevices;
-}
-
 DeviceVector Engine::getDevicesForProductStrategy(product_strategy_t strategy) const {
     const SwAudioOutputCollection& outputs = getApmObserver()->getOutputs();
 
diff --git a/services/audiopolicy/enginedefault/src/Engine.h b/services/audiopolicy/enginedefault/src/Engine.h
index 714fef8..2e4decf 100644
--- a/services/audiopolicy/enginedefault/src/Engine.h
+++ b/services/audiopolicy/enginedefault/src/Engine.h
@@ -96,10 +96,6 @@
     product_strategy_t getProductStrategyFromLegacy(legacy_strategy legacyStrategy) const;
     audio_devices_t getPreferredDeviceTypeForLegacyStrategy(
         const DeviceVector& availableOutputDevices, legacy_strategy legacyStrategy) const;
-    DeviceVector getPreferredAvailableDevicesForProductStrategy(
-        const DeviceVector& availableOutputDevices, product_strategy_t strategy) const;
-    DeviceVector getDisabledDevicesForProductStrategy(
-        const DeviceVector& availableOutputDevices, product_strategy_t strategy) const;
     DeviceVector getPreferredAvailableDevicesForInputSource(
             const DeviceVector& availableInputDevices, audio_source_t inputSource) const;
     DeviceVector getDisabledDevicesForInputSource(
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index cc8b1a1..56a692b 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -6471,6 +6471,14 @@
     }
 
     if (state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
+        // first call getAudioPort to get the supported attributes from the HAL
+        struct audio_port_v7 port = {};
+        device->toAudioPort(&port);
+        status_t status = mpClientInterface->getAudioPort(&port);
+        if (status == NO_ERROR) {
+            device->importAudioPort(port);
+        }
+
         // look for input profiles that can be routed to this device
         SortedVector< sp<IOProfile> > profiles;
         for (const auto& hwModule : mHwModules) {
@@ -6522,11 +6530,7 @@
 
             desc = new AudioInputDescriptor(profile, mpClientInterface);
             audio_io_handle_t input = AUDIO_IO_HANDLE_NONE;
-            status_t status = desc->open(nullptr,
-                                         device,
-                                         AUDIO_SOURCE_MIC,
-                                         AUDIO_INPUT_FLAG_NONE,
-                                         &input);
+            status = desc->open(nullptr, device, AUDIO_SOURCE_MIC, AUDIO_INPUT_FLAG_NONE, &input);
 
             if (status == NO_ERROR) {
                 const String8& address = String8(device->address().c_str());
@@ -8073,12 +8077,17 @@
                 ioHandle, String8(AudioParameter::keyStreamSupportedFormats));
         ALOGV("%s: supported formats %d, %s", __FUNCTION__, ioHandle, reply.string());
         AudioParameter repliedParameters(reply);
+        FormatVector formats;
         if (repliedParameters.get(
-                String8(AudioParameter::keyStreamSupportedFormats), reply) != NO_ERROR) {
-            ALOGE("%s: failed to retrieve format, bailing out", __FUNCTION__);
+                String8(AudioParameter::keyStreamSupportedFormats), reply) == NO_ERROR) {
+            formats = formatsFromString(reply.string());
+        } else if (devDesc->hasValidAudioProfile()) {
+            ALOGD("%s: using the device profiles", __func__);
+            formats = devDesc->getAudioProfiles().getSupportedFormats();
+        } else {
+            ALOGE("%s: failed to retrieve format, bailing out", __func__);
             return;
         }
-        FormatVector formats = formatsFromString(reply.string());
         mReportedFormatsMap[devDesc] = formats;
         if (device == AUDIO_DEVICE_OUT_HDMI
                 || isDeviceOfModule(devDesc, AUDIO_HARDWARE_MODULE_ID_MSD)) {
@@ -8088,7 +8097,7 @@
     }
 
     for (audio_format_t format : profiles.getSupportedFormats()) {
-        ChannelMaskSet channelMasks;
+        std::optional<ChannelMaskSet> channelMasks;
         SampleRateSet samplingRates;
         AudioParameter requestedParameters;
         requestedParameters.addInt(String8(AudioParameter::keyFormat), format);
@@ -8103,6 +8112,8 @@
             if (repliedParameters.get(
                     String8(AudioParameter::keyStreamSupportedSamplingRates), reply) == NO_ERROR) {
                 samplingRates = samplingRatesFromString(reply.string());
+            } else {
+                samplingRates = devDesc->getAudioProfiles().getSampleRatesFor(format);
             }
         }
         if (profiles.hasDynamicChannelsFor(format)) {
@@ -8114,14 +8125,17 @@
             if (repliedParameters.get(
                     String8(AudioParameter::keyStreamSupportedChannels), reply) == NO_ERROR) {
                 channelMasks = channelMasksFromString(reply.string());
-                if (device == AUDIO_DEVICE_OUT_HDMI
-                        || isDeviceOfModule(devDesc, AUDIO_HARDWARE_MODULE_ID_MSD)) {
-                    modifySurroundChannelMasks(&channelMasks);
-                }
+            } else {
+                channelMasks = devDesc->getAudioProfiles().getChannelMasksFor(format);
+            }
+            if (channelMasks.has_value() && (device == AUDIO_DEVICE_OUT_HDMI
+                    || isDeviceOfModule(devDesc, AUDIO_HARDWARE_MODULE_ID_MSD))) {
+                modifySurroundChannelMasks(&channelMasks.value());
             }
         }
         addDynamicAudioProfileAndSort(
-                profiles, new AudioProfile(format, channelMasks, samplingRates));
+                profiles, new AudioProfile(
+                        format, channelMasks.value_or(ChannelMaskSet()), samplingRates));
     }
 }
 
diff --git a/services/camera/libcameraservice/api2/JpegRCompositeStream.cpp b/services/camera/libcameraservice/api2/JpegRCompositeStream.cpp
index 5794747..8a65a67 100644
--- a/services/camera/libcameraservice/api2/JpegRCompositeStream.cpp
+++ b/services/camera/libcameraservice/api2/JpegRCompositeStream.cpp
@@ -299,14 +299,11 @@
     p010.height = inputFrame.p010Buffer.height;
     p010.width = inputFrame.p010Buffer.width;
     p010.colorGamut = jpegrecoverymap::jpegr_color_gamut::JPEGR_COLORGAMUT_BT2100;
-    size_t yChannelSizeInByte = p010.width * p010.height * 2;
-    size_t uvChannelSizeInByte = p010.width * p010.height;
-    p010.data = new uint8_t[yChannelSizeInByte + uvChannelSizeInByte];
-    std::unique_ptr<uint8_t[]> p010_data;
-    p010_data.reset(reinterpret_cast<uint8_t*>(p010.data));
-    memcpy((uint8_t*)p010.data, inputFrame.p010Buffer.data, yChannelSizeInByte);
-    memcpy((uint8_t*)p010.data + yChannelSizeInByte, inputFrame.p010Buffer.dataCb,
-           uvChannelSizeInByte);
+    p010.data = inputFrame.p010Buffer.data;
+    p010.chroma_data = inputFrame.p010Buffer.dataCb;
+    // Strides are expected to be in pixels not bytes
+    p010.luma_stride = inputFrame.p010Buffer.stride / 2;
+    p010.chroma_stride = inputFrame.p010Buffer.chromaStride / 2;
 
     jpegR.data = dstBuffer;
     jpegR.maxLength = maxJpegRBufferSize;
@@ -367,7 +364,6 @@
     }
 
     actualJpegRSize = jpegR.length;
-    p010_data.release();
 
     size_t finalJpegRSize = actualJpegRSize + sizeof(CameraBlob);
     if (finalJpegRSize > maxJpegRBufferSize) {
diff --git a/services/tuner/mediatuner.rc b/services/tuner/mediatuner.rc
index 90a0090..8e5d100 100644
--- a/services/tuner/mediatuner.rc
+++ b/services/tuner/mediatuner.rc
@@ -4,6 +4,7 @@
 service media.tuner /system/bin/mediatuner
     class main
     group media
+    user root
     ioprio rt 4
     task_profiles ProcessCapacityHigh HighPerformance
     interface aidl media.tuner