Merge changes I05611b70,I6cd1a53e,Ic2e08efc,I13ac0673,I0d87fd76
am: 1e415c058a

Change-Id: I44c7cdbc4a57cd681e054b61d602f21d854e48b5
diff --git a/media/libaudiofoundation/Android.bp b/media/libaudiofoundation/Android.bp
index 5045d87..c91b79e 100644
--- a/media/libaudiofoundation/Android.bp
+++ b/media/libaudiofoundation/Android.bp
@@ -10,17 +10,21 @@
 
     srcs: [
         "AudioGain.cpp",
+        "AudioPortBase.cpp",
+        "AudioProfile.cpp",
     ],
 
     shared_libs: [
         "libbase",
         "libbinder",
         "liblog",
+        "libmedia_helper",
         "libutils",
     ],
 
     header_libs: [
         "libaudio_system_headers",
+        "libaudioclient_headers",
         "libaudiofoundation_headers",
     ],
 
diff --git a/media/libaudiofoundation/AudioPortBase.cpp b/media/libaudiofoundation/AudioPortBase.cpp
new file mode 100644
index 0000000..922a82c
--- /dev/null
+++ b/media/libaudiofoundation/AudioPortBase.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <algorithm>
+
+#include <android-base/stringprintf.h>
+#include <media/AudioPortBase.h>
+#include <utils/Log.h>
+
+namespace android {
+
+void AudioPortFoundation::toAudioPort(struct audio_port *port) const {
+    // TODO: update this function once audio_port structure reflects the new profile definition.
+    // For compatibility reason: flatening the AudioProfile into audio_port structure.
+    FormatSet flatenedFormats;
+    SampleRateSet flatenedRates;
+    ChannelMaskSet flatenedChannels;
+    for (const auto& profile : *getAudioProfileVectorBase()) {
+        if (profile->isValid()) {
+            audio_format_t formatToExport = profile->getFormat();
+            const SampleRateSet &ratesToExport = profile->getSampleRates();
+            const ChannelMaskSet &channelsToExport = profile->getChannels();
+
+            flatenedFormats.insert(formatToExport);
+            flatenedRates.insert(ratesToExport.begin(), ratesToExport.end());
+            flatenedChannels.insert(channelsToExport.begin(), channelsToExport.end());
+
+            if (flatenedRates.size() > AUDIO_PORT_MAX_SAMPLING_RATES ||
+                    flatenedChannels.size() > AUDIO_PORT_MAX_CHANNEL_MASKS ||
+                    flatenedFormats.size() > AUDIO_PORT_MAX_FORMATS) {
+                ALOGE("%s: bailing out: cannot export profiles to port config", __func__);
+                return;
+            }
+        }
+    }
+    port->role = mRole;
+    port->type = mType;
+    strlcpy(port->name, mName.c_str(), AUDIO_PORT_MAX_NAME_LEN);
+    port->num_sample_rates = flatenedRates.size();
+    port->num_channel_masks = flatenedChannels.size();
+    port->num_formats = flatenedFormats.size();
+    std::copy(flatenedRates.begin(), flatenedRates.end(), port->sample_rates);
+    std::copy(flatenedChannels.begin(), flatenedChannels.end(), port->channel_masks);
+    std::copy(flatenedFormats.begin(), flatenedFormats.end(), port->formats);
+
+    ALOGV("AudioPort::toAudioPort() num gains %zu", mGains.size());
+
+    port->num_gains = std::min(mGains.size(), (size_t) AUDIO_PORT_MAX_GAINS);
+    for (size_t i = 0; i < port->num_gains; i++) {
+        port->gains[i] = mGains[i]->getGain();
+    }
+}
+
+void AudioPortFoundation::dump(std::string *dst, int spaces, bool verbose) const {
+    if (!mName.empty()) {
+        dst->append(base::StringPrintf("%*s- name: %s\n", spaces, "", mName.c_str()));
+    }
+    if (verbose) {
+        std::string profilesStr;
+        getAudioProfileVectorBase()->dump(&profilesStr, spaces);
+        dst->append(profilesStr);
+
+        if (mGains.size() != 0) {
+            dst->append(base::StringPrintf("%*s- gains:\n", spaces, ""));
+            for (size_t i = 0; i < mGains.size(); i++) {
+                std::string gainStr;
+                mGains[i]->dump(&gainStr, spaces + 2, i);
+                dst->append(gainStr);
+            }
+        }
+    }
+}
+
+}
\ No newline at end of file
diff --git a/media/libaudiofoundation/AudioProfile.cpp b/media/libaudiofoundation/AudioProfile.cpp
new file mode 100644
index 0000000..aaaa7d1
--- /dev/null
+++ b/media/libaudiofoundation/AudioProfile.cpp
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <set>
+
+#define LOG_TAG "AudioProfile"
+//#define LOG_NDEBUG 0
+
+#include <android-base/stringprintf.h>
+#include <media/AudioContainers.h>
+#include <media/AudioProfile.h>
+#include <media/TypeConverter.h>
+#include <utils/Errors.h>
+
+namespace android {
+
+bool operator == (const AudioProfile &left, const AudioProfile &right)
+{
+    return (left.getFormat() == right.getFormat()) &&
+            (left.getChannels() == right.getChannels()) &&
+            (left.getSampleRates() == right.getSampleRates());
+}
+
+// static
+sp<AudioProfile> AudioProfile::createFullDynamic(audio_format_t dynamicFormat)
+{
+    AudioProfile* dynamicProfile = new AudioProfile(dynamicFormat,
+            ChannelMaskSet(), SampleRateSet());
+    dynamicProfile->setDynamicFormat(true);
+    dynamicProfile->setDynamicChannels(true);
+    dynamicProfile->setDynamicRate(true);
+    return dynamicProfile;
+}
+
+AudioProfile::AudioProfile(audio_format_t format,
+                           audio_channel_mask_t channelMasks,
+                           uint32_t samplingRate) :
+        mName(""),
+        mFormat(format)
+{
+    mChannelMasks.insert(channelMasks);
+    mSamplingRates.insert(samplingRate);
+}
+
+AudioProfile::AudioProfile(audio_format_t format,
+                           const ChannelMaskSet &channelMasks,
+                           const SampleRateSet &samplingRateCollection) :
+        mName(""),
+        mFormat(format),
+        mChannelMasks(channelMasks),
+        mSamplingRates(samplingRateCollection) {}
+
+void AudioProfile::setChannels(const ChannelMaskSet &channelMasks)
+{
+    if (mIsDynamicChannels) {
+        mChannelMasks = channelMasks;
+    }
+}
+
+void AudioProfile::setSampleRates(const SampleRateSet &sampleRates)
+{
+    if (mIsDynamicRate) {
+        mSamplingRates = sampleRates;
+    }
+}
+
+void AudioProfile::clear()
+{
+    if (mIsDynamicChannels) {
+        mChannelMasks.clear();
+    }
+    if (mIsDynamicRate) {
+        mSamplingRates.clear();
+    }
+}
+
+void AudioProfile::dump(std::string *dst, int spaces) const
+{
+    dst->append(base::StringPrintf("%s%s%s\n", mIsDynamicFormat ? "[dynamic format]" : "",
+             mIsDynamicChannels ? "[dynamic channels]" : "",
+             mIsDynamicRate ? "[dynamic rates]" : ""));
+    if (mName.length() != 0) {
+        dst->append(base::StringPrintf("%*s- name: %s\n", spaces, "", mName.c_str()));
+    }
+    std::string formatLiteral;
+    if (FormatConverter::toString(mFormat, formatLiteral)) {
+        dst->append(base::StringPrintf("%*s- format: %s\n", spaces, "", formatLiteral.c_str()));
+    }
+    if (!mSamplingRates.empty()) {
+        dst->append(base::StringPrintf("%*s- sampling rates:", spaces, ""));
+        for (auto it = mSamplingRates.begin(); it != mSamplingRates.end();) {
+            dst->append(base::StringPrintf("%d", *it));
+            dst->append(++it == mSamplingRates.end() ? "" : ", ");
+        }
+        dst->append("\n");
+    }
+
+    if (!mChannelMasks.empty()) {
+        dst->append(base::StringPrintf("%*s- channel masks:", spaces, ""));
+        for (auto it = mChannelMasks.begin(); it != mChannelMasks.end();) {
+            dst->append(base::StringPrintf("0x%04x", *it));
+            dst->append(++it == mChannelMasks.end() ? "" : ", ");
+        }
+        dst->append("\n");
+    }
+}
+
+ssize_t AudioProfileVectorBase::add(const sp<AudioProfile> &profile)
+{
+    ssize_t index = size();
+    push_back(profile);
+    return index;
+}
+
+void AudioProfileVectorBase::clearProfiles()
+{
+    for (auto it = begin(); it != end();) {
+        if ((*it)->isDynamicFormat() && (*it)->hasValidFormat()) {
+            it = erase(it);
+        } else {
+            (*it)->clear();
+            ++it;
+        }
+    }
+}
+
+sp<AudioProfile> AudioProfileVectorBase::getFirstValidProfile() const
+{
+    for (const auto &profile : *this) {
+        if (profile->isValid()) {
+            return profile;
+        }
+    }
+    return nullptr;
+}
+
+sp<AudioProfile> AudioProfileVectorBase::getFirstValidProfileFor(audio_format_t format) const
+{
+    for (const auto &profile : *this) {
+        if (profile->isValid() && profile->getFormat() == format) {
+            return profile;
+        }
+    }
+    return nullptr;
+}
+
+FormatVector AudioProfileVectorBase::getSupportedFormats() const
+{
+    FormatVector supportedFormats;
+    for (const auto &profile : *this) {
+        if (profile->hasValidFormat()) {
+            supportedFormats.push_back(profile->getFormat());
+        }
+    }
+    return supportedFormats;
+}
+
+bool AudioProfileVectorBase::hasDynamicChannelsFor(audio_format_t format) const
+{
+    for (const auto &profile : *this) {
+        if (profile->getFormat() == format && profile->isDynamicChannels()) {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool AudioProfileVectorBase::hasDynamicFormat() const
+{
+    for (const auto &profile : *this) {
+        if (profile->isDynamicFormat()) {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool AudioProfileVectorBase::hasDynamicProfile() const
+{
+    for (const auto &profile : *this) {
+        if (profile->isDynamic()) {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool AudioProfileVectorBase::hasDynamicRateFor(audio_format_t format) const
+{
+    for (const auto &profile : *this) {
+        if (profile->getFormat() == format && profile->isDynamicRate()) {
+            return true;
+        }
+    }
+    return false;
+}
+
+void AudioProfileVectorBase::dump(std::string *dst, int spaces) const
+{
+    dst->append(base::StringPrintf("%*s- Profiles:\n", spaces, ""));
+    for (size_t i = 0; i < size(); i++) {
+        dst->append(base::StringPrintf("%*sProfile %zu:", spaces + 4, "", i));
+        std::string profileStr;
+        at(i)->dump(&profileStr, spaces + 8);
+        dst->append(profileStr);
+    }
+}
+
+} // namespace android
diff --git a/media/libaudiofoundation/include/media/AudioPortBase.h b/media/libaudiofoundation/include/media/AudioPortBase.h
new file mode 100644
index 0000000..5812c2c
--- /dev/null
+++ b/media/libaudiofoundation/include/media/AudioPortBase.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <string>
+
+#include <media/AudioGain.h>
+#include <media/AudioProfile.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <system/audio.h>
+#include <cutils/config_utils.h>
+
+namespace android {
+
+class AudioPortFoundation : public virtual RefBase
+{
+public:
+    AudioPortFoundation(const std::string& name, audio_port_type_t type,  audio_port_role_t role) :
+            mName(name), mType(type), mRole(role) {}
+
+    virtual ~AudioPortFoundation() = default;
+
+    void setName(const std::string &name) { mName = name; }
+    const std::string &getName() const { return mName; }
+
+    audio_port_type_t getType() const { return mType; }
+    audio_port_role_t getRole() const { return mRole; }
+
+    virtual const std::string getTagName() const = 0;
+
+    void setGains(const AudioGains &gains) { mGains = gains; }
+    const AudioGains &getGains() const { return mGains; }
+
+    virtual void toAudioPort(struct audio_port *port) const;
+
+    virtual AudioProfileVectorBase* getAudioProfileVectorBase() const = 0;
+    virtual void addAudioProfile(const sp<AudioProfile> &profile) {
+        getAudioProfileVectorBase()->add(profile);
+    }
+    virtual void clearAudioProfiles() {
+        getAudioProfileVectorBase()->clearProfiles();
+    }
+
+    bool hasValidAudioProfile() const { return getAudioProfileVectorBase()->hasValidProfile(); }
+
+    status_t checkGain(const struct audio_gain_config *gainConfig, int index) const {
+        if (index < 0 || (size_t)index >= mGains.size()) {
+            return BAD_VALUE;
+        }
+        return mGains[index]->checkConfig(gainConfig);
+    }
+
+    bool useInputChannelMask() const
+    {
+        return ((mType == AUDIO_PORT_TYPE_DEVICE) && (mRole == AUDIO_PORT_ROLE_SOURCE)) ||
+                ((mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SINK));
+    }
+
+    void dump(std::string *dst, int spaces, bool verbose = true) const;
+
+    AudioGains mGains; // gain controllers
+protected:
+    std::string  mName;
+    audio_port_type_t mType;
+    audio_port_role_t mRole;
+};
+
+template <typename ProfileVector,
+          typename = typename std::enable_if<std::is_base_of<
+                  AudioProfileVectorBase, ProfileVector>::value>::type>
+class AudioPortBase : public AudioPortFoundation
+{
+public:
+    AudioPortBase(const std::string& name, audio_port_type_t type,  audio_port_role_t role) :
+            AudioPortFoundation(name, type, role) {}
+
+    virtual ~AudioPortBase() {}
+
+    AudioProfileVectorBase* getAudioProfileVectorBase() const override {
+        return static_cast<AudioProfileVectorBase*>(const_cast<ProfileVector*>(&mProfiles));
+    }
+
+    void addAudioProfile(const sp<AudioProfile> &profile) override { mProfiles.add(profile); }
+    void clearAudioProfiles() override { return mProfiles.clearProfiles(); }
+
+    void setAudioProfiles(const ProfileVector &profiles) { mProfiles = profiles; }
+    ProfileVector &getAudioProfiles() { return mProfiles; }
+
+protected:
+    ProfileVector mProfiles; // AudioProfiles supported by this port (format, Rates, Channels)
+};
+
+
+class AudioPortConfigBase : public virtual RefBase
+{
+public:
+    virtual ~AudioPortConfigBase() = default;
+
+    virtual status_t applyAudioPortConfig(const struct audio_port_config *config,
+                                          struct audio_port_config *backupConfig = NULL) = 0;
+    virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
+                                   const struct audio_port_config *srcConfig = NULL) const = 0;
+
+    unsigned int getSamplingRate() const { return mSamplingRate; }
+    audio_format_t getFormat() const { return mFormat; }
+    audio_channel_mask_t getChannelMask() const { return mChannelMask; }
+
+protected:
+    unsigned int mSamplingRate = 0u;
+    audio_format_t mFormat = AUDIO_FORMAT_INVALID;
+    audio_channel_mask_t mChannelMask = AUDIO_CHANNEL_NONE;
+    struct audio_gain_config mGain = { .index = -1 };
+};
+
+} // namespace android
diff --git a/media/libaudiofoundation/include/media/AudioProfile.h b/media/libaudiofoundation/include/media/AudioProfile.h
new file mode 100644
index 0000000..20f35eb
--- /dev/null
+++ b/media/libaudiofoundation/include/media/AudioProfile.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include <media/AudioContainers.h>
+#include <system/audio.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+class AudioProfile final : public RefBase
+{
+public:
+    static sp<AudioProfile> createFullDynamic(audio_format_t dynamicFormat = AUDIO_FORMAT_DEFAULT);
+
+    AudioProfile(audio_format_t format, audio_channel_mask_t channelMasks, uint32_t samplingRate);
+    AudioProfile(audio_format_t format,
+                 const ChannelMaskSet &channelMasks,
+                 const SampleRateSet &samplingRateCollection);
+
+    audio_format_t getFormat() const { return mFormat; }
+    const ChannelMaskSet &getChannels() const { return mChannelMasks; }
+    const SampleRateSet &getSampleRates() const { return mSamplingRates; }
+    void setChannels(const ChannelMaskSet &channelMasks);
+    void setSampleRates(const SampleRateSet &sampleRates);
+
+    void clear();
+    bool isValid() const { return hasValidFormat() && hasValidRates() && hasValidChannels(); }
+    bool supportsChannels(audio_channel_mask_t channels) const
+    {
+        return mChannelMasks.count(channels) != 0;
+    }
+    bool supportsRate(uint32_t rate) const { return mSamplingRates.count(rate) != 0; }
+
+    bool hasValidFormat() const { return mFormat != AUDIO_FORMAT_DEFAULT; }
+    bool hasValidRates() const { return !mSamplingRates.empty(); }
+    bool hasValidChannels() const { return !mChannelMasks.empty(); }
+
+    void setDynamicChannels(bool dynamic) { mIsDynamicChannels = dynamic; }
+    bool isDynamicChannels() const { return mIsDynamicChannels; }
+
+    void setDynamicRate(bool dynamic) { mIsDynamicRate = dynamic; }
+    bool isDynamicRate() const { return mIsDynamicRate; }
+
+    void setDynamicFormat(bool dynamic) { mIsDynamicFormat = dynamic; }
+    bool isDynamicFormat() const { return mIsDynamicFormat; }
+
+    bool isDynamic() { return mIsDynamicFormat || mIsDynamicChannels || mIsDynamicRate; }
+
+    void dump(std::string *dst, int spaces) const;
+
+private:
+    std::string  mName;
+    audio_format_t mFormat; // The format for an audio profile should only be set when initialized.
+    ChannelMaskSet mChannelMasks;
+    SampleRateSet mSamplingRates;
+
+    bool mIsDynamicFormat = false;
+    bool mIsDynamicChannels = false;
+    bool mIsDynamicRate = false;
+};
+
+class AudioProfileVectorBase : public std::vector<sp<AudioProfile> >
+{
+public:
+    virtual ~AudioProfileVectorBase() = default;
+
+    virtual ssize_t add(const sp<AudioProfile> &profile);
+
+    // If the profile is dynamic format and has valid format, it will be removed when doing
+    // clearProfiles(). Otherwise, AudioProfile::clear() will be called.
+    virtual void clearProfiles();
+
+    sp<AudioProfile> getFirstValidProfile() const;
+    sp<AudioProfile> getFirstValidProfileFor(audio_format_t format) const;
+    bool hasValidProfile() const { return getFirstValidProfile() != 0; }
+
+    FormatVector getSupportedFormats() const;
+    bool hasDynamicChannelsFor(audio_format_t format) const;
+    bool hasDynamicFormat() const;
+    bool hasDynamicProfile() const;
+    bool hasDynamicRateFor(audio_format_t format) const;
+
+    virtual void dump(std::string *dst, int spaces) const;
+};
+
+bool operator == (const AudioProfile &left, const AudioProfile &right);
+
+} // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/Android.bp b/services/audiopolicy/common/managerdefinitions/Android.bp
index ebfba83..71d5789 100644
--- a/services/audiopolicy/common/managerdefinitions/Android.bp
+++ b/services/audiopolicy/common/managerdefinitions/Android.bp
@@ -8,7 +8,7 @@
         "src/AudioPatch.cpp",
         "src/AudioPolicyMix.cpp",
         "src/AudioPort.cpp",
-        "src/AudioProfile.cpp",
+        "src/AudioProfileVector.cpp",
         "src/AudioRoute.cpp",
         "src/ClientDescriptor.cpp",
         "src/DeviceDescriptor.cpp",
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioCollections.h b/services/audiopolicy/common/managerdefinitions/include/AudioCollections.h
index a948ea9..646ef31 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioCollections.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioCollections.h
@@ -31,7 +31,7 @@
 class AudioPortVector : public Vector<sp<AudioPort> >
 {
 public:
-    sp<AudioPort> findByTagName(const String8 &tagName) const;
+    sp<AudioPort> findByTagName(const std::string &tagName) const;
 };
 
 
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
index 31c5041..c17f308 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
@@ -29,6 +29,7 @@
 #include <AudioPolicyMix.h>
 #include <EffectDescriptor.h>
 #include <SoundTriggerSession.h>
+#include <media/AudioProfile.h>
 
 namespace android {
 
@@ -118,9 +119,9 @@
         mSource = "AudioPolicyConfig::setDefault";
         mEngineLibraryNameSuffix = kDefaultEngineLibraryNameSuffix;
         mDefaultOutputDevice = new DeviceDescriptor(AUDIO_DEVICE_OUT_SPEAKER);
-        mDefaultOutputDevice->addAudioProfile(AudioProfile::createFullDynamic());
+        mDefaultOutputDevice->addAudioProfile(AudioProfile::createFullDynamic(gDynamicFormat));
         sp<DeviceDescriptor> defaultInputDevice = new DeviceDescriptor(AUDIO_DEVICE_IN_BUILTIN_MIC);
-        defaultInputDevice->addAudioProfile(AudioProfile::createFullDynamic());
+        defaultInputDevice->addAudioProfile(AudioProfile::createFullDynamic(gDynamicFormat));
         sp<AudioProfile> micProfile = new AudioProfile(
                 AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_MONO, 8000);
         defaultInputDevice->addAudioProfile(micProfile);
@@ -132,14 +133,14 @@
         mDefaultOutputDevice->attach(module);
         defaultInputDevice->attach(module);
 
-        sp<OutputProfile> outProfile = new OutputProfile(String8("primary"));
+        sp<OutputProfile> outProfile = new OutputProfile("primary");
         outProfile->addAudioProfile(
                 new AudioProfile(AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 44100));
         outProfile->addSupportedDevice(mDefaultOutputDevice);
         outProfile->setFlags(AUDIO_OUTPUT_FLAG_PRIMARY);
         module->addOutputProfile(outProfile);
 
-        sp<InputProfile> inProfile = new InputProfile(String8("primary"));
+        sp<InputProfile> inProfile = new InputProfile("primary");
         inProfile->addAudioProfile(micProfile);
         inProfile->addSupportedDevice(defaultInputDevice);
         module->addInputProfile(inProfile);
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
index 641cebf..c26bffc 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
@@ -17,9 +17,10 @@
 #pragma once
 
 #include "AudioCollections.h"
-#include "AudioProfile.h"
+#include "AudioProfileVector.h"
 #include "HandleGenerator.h"
 #include <media/AudioGain.h>
+#include <media/AudioPortBase.h>
 #include <utils/String8.h>
 #include <utils/Vector.h>
 #include <utils/RefBase.h>
@@ -32,25 +33,15 @@
 class HwModule;
 class AudioRoute;
 
-class AudioPort : public virtual RefBase, private HandleGenerator<audio_port_handle_t>
+class AudioPort : public virtual RefBase, public AudioPortBase<AudioProfileVector>,
+                  private HandleGenerator<audio_port_handle_t>
 {
 public:
-    AudioPort(const String8& name, audio_port_type_t type,  audio_port_role_t role) :
-        mName(name), mType(type), mRole(role), mFlags(AUDIO_OUTPUT_FLAG_NONE) {}
+    AudioPort(const std::string& name, audio_port_type_t type,  audio_port_role_t role) :
+            AudioPortBase(name, type, role), mFlags(AUDIO_OUTPUT_FLAG_NONE) {}
 
     virtual ~AudioPort() {}
 
-    void setName(const String8 &name) { mName = name; }
-    const String8 &getName() const { return mName; }
-
-    audio_port_type_t getType() const { return mType; }
-    audio_port_role_t getRole() const { return mRole; }
-
-    virtual const String8 getTagName() const = 0;
-
-    void setGains(const AudioGains &gains) { mGains = gains; }
-    const AudioGains &getGains() const { return mGains; }
-
     virtual void setFlags(uint32_t flags)
     {
         //force direct flag if offload flag is set: offloading implies a direct output stream
@@ -70,18 +61,9 @@
     // Audio port IDs are in a different namespace than AudioFlinger unique IDs
     static audio_port_handle_t getNextUniqueId();
 
-    virtual void toAudioPort(struct audio_port *port) const;
-
     virtual void importAudioPort(const sp<AudioPort>& port, bool force = false);
 
-    void addAudioProfile(const sp<AudioProfile> &profile) { mProfiles.add(profile); }
-
-    void setAudioProfiles(const AudioProfileVector &profiles) { mProfiles = profiles; }
-    AudioProfileVector &getAudioProfiles() { return mProfiles; }
-
-    bool hasValidAudioProfile() const { return mProfiles.hasValidProfile(); }
-
-    bool hasDynamicAudioProfile() const { return mProfiles.hasDynamicProfile(); }
+    bool hasDynamicAudioProfile() const { return getAudioProfileVectorBase()->hasDynamicProfile(); }
 
     // searches for an exact match
     virtual status_t checkExactAudioProfile(const struct audio_port_config *config) const;
@@ -95,10 +77,6 @@
         return mProfiles.checkCompatibleProfile(samplingRate, channelMask, format, mType, mRole);
     }
 
-    void clearAudioProfiles() { return mProfiles.clearProfiles(); }
-
-    status_t checkGain(const struct audio_gain_config *gainConfig, int index) const;
-
     void pickAudioProfile(uint32_t &samplingRate,
                           audio_channel_mask_t &channelMask,
                           audio_format_t &format) const;
@@ -121,12 +99,6 @@
     const char *getModuleName() const;
     sp<HwModule> getModule() const { return mModule; }
 
-    bool useInputChannelMask() const
-    {
-        return ((mType == AUDIO_PORT_TYPE_DEVICE) && (mRole == AUDIO_PORT_ROLE_SOURCE)) ||
-                ((mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SINK));
-    }
-
     inline bool isDirectOutput() const
     {
         return (mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SOURCE) &&
@@ -136,44 +108,36 @@
     void addRoute(const sp<AudioRoute> &route) { mRoutes.add(route); }
     const AudioRouteVector &getRoutes() const { return mRoutes; }
 
-    void dump(String8 *dst, int spaces, bool verbose = true) const;
-
     void log(const char* indent) const;
 
-    AudioGains mGains; // gain controllers
-
 private:
     void pickChannelMask(audio_channel_mask_t &channelMask,
                          const ChannelMaskSet &channelMasks) const;
     void pickSamplingRate(uint32_t &rate, const SampleRateSet &samplingRates) const;
 
-    sp<HwModule> mModule;                 // audio HW module exposing this I/O stream
-    String8  mName;
-    audio_port_type_t mType;
-    audio_port_role_t mRole;
     uint32_t mFlags; // attribute flags mask (e.g primary output, direct output...).
-    AudioProfileVector mProfiles; // AudioProfiles supported by this port (format, Rates, Channels)
+    sp<HwModule> mModule;     // audio HW module exposing this I/O stream
     AudioRouteVector mRoutes; // Routes involving this port
 };
 
-class AudioPortConfig : public virtual RefBase
+class AudioPortConfig : public AudioPortConfigBase
 {
 public:
     status_t applyAudioPortConfig(const struct audio_port_config *config,
-                                  struct audio_port_config *backupConfig = NULL);
+                                  struct audio_port_config *backupConfig = NULL) override;
+
     virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
-                                   const struct audio_port_config *srcConfig = NULL) const = 0;
+            const struct audio_port_config *srcConfig = NULL) const override;
+
     virtual sp<AudioPort> getAudioPort() const = 0;
+
     virtual bool hasSameHwModuleAs(const sp<AudioPortConfig>& other) const {
         return (other != 0) && (other->getAudioPort() != 0) && (getAudioPort() != 0) &&
                 (other->getAudioPort()->getModuleHandle() == getAudioPort()->getModuleHandle());
     }
+
     bool hasGainController(bool canUseForVolume = false) const;
 
-    unsigned int mSamplingRate = 0u;
-    audio_format_t mFormat = AUDIO_FORMAT_INVALID;
-    audio_channel_mask_t mChannelMask = AUDIO_CHANNEL_NONE;
-    struct audio_gain_config mGain = { .index = -1 };
     union audio_io_flags mFlags = { AUDIO_INPUT_FLAG_NONE };
 };
 
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioProfile.h b/services/audiopolicy/common/managerdefinitions/include/AudioProfile.h
deleted file mode 100644
index ea56729..0000000
--- a/services/audiopolicy/common/managerdefinitions/include/AudioProfile.h
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <media/AudioContainers.h>
-#include <system/audio.h>
-#include <utils/RefBase.h>
-#include <utils/String8.h>
-
-#include "policy.h"
-
-namespace android {
-
-class AudioProfile : public virtual RefBase
-{
-public:
-    static sp<AudioProfile> createFullDynamic();
-
-    AudioProfile(audio_format_t format, audio_channel_mask_t channelMasks, uint32_t samplingRate);
-    AudioProfile(audio_format_t format,
-                 const ChannelMaskSet &channelMasks,
-                 const SampleRateSet &samplingRateCollection);
-
-    audio_format_t getFormat() const { return mFormat; }
-    const ChannelMaskSet &getChannels() const { return mChannelMasks; }
-    const SampleRateSet &getSampleRates() const { return mSamplingRates; }
-    void setChannels(const ChannelMaskSet &channelMasks);
-    void setSampleRates(const SampleRateSet &sampleRates);
-
-    void clear();
-    bool isValid() const { return hasValidFormat() && hasValidRates() && hasValidChannels(); }
-    bool supportsChannels(audio_channel_mask_t channels) const
-    {
-        return mChannelMasks.count(channels) != 0;
-    }
-    bool supportsRate(uint32_t rate) const { return mSamplingRates.count(rate) != 0; }
-
-    status_t checkExact(uint32_t rate, audio_channel_mask_t channels, audio_format_t format) const;
-    status_t checkCompatibleChannelMask(audio_channel_mask_t channelMask,
-                                        audio_channel_mask_t &updatedChannelMask,
-                                        audio_port_type_t portType,
-                                        audio_port_role_t portRole) const;
-    status_t checkCompatibleSamplingRate(uint32_t samplingRate,
-                                         uint32_t &updatedSamplingRate) const;
-
-    bool hasValidFormat() const { return mFormat != AUDIO_FORMAT_DEFAULT; }
-    bool hasValidRates() const { return !mSamplingRates.empty(); }
-    bool hasValidChannels() const { return !mChannelMasks.empty(); }
-
-    void setDynamicChannels(bool dynamic) { mIsDynamicChannels = dynamic; }
-    bool isDynamicChannels() const { return mIsDynamicChannels; }
-
-    void setDynamicRate(bool dynamic) { mIsDynamicRate = dynamic; }
-    bool isDynamicRate() const { return mIsDynamicRate; }
-
-    void setDynamicFormat(bool dynamic) { mIsDynamicFormat = dynamic; }
-    bool isDynamicFormat() const { return mIsDynamicFormat; }
-
-    bool isDynamic() { return mIsDynamicFormat || mIsDynamicChannels || mIsDynamicRate; }
-
-    void dump(String8 *dst, int spaces) const;
-
-private:
-    String8  mName;
-    audio_format_t mFormat;
-    ChannelMaskSet mChannelMasks;
-    SampleRateSet mSamplingRates;
-
-    bool mIsDynamicFormat = false;
-    bool mIsDynamicChannels = false;
-    bool mIsDynamicRate = false;
-};
-
-
-class AudioProfileVector : public std::vector<sp<AudioProfile> >
-{
-public:
-    ssize_t add(const sp<AudioProfile> &profile);
-    // This API is intended to be used by the policy manager once retrieving capabilities
-    // for a profile with dynamic format, rate and channels attributes
-    ssize_t addProfileFromHal(const sp<AudioProfile> &profileToAdd);
-    void appendProfiles(const AudioProfileVector& audioProfiles) {
-        insert(end(), audioProfiles.begin(), audioProfiles.end());
-    }
-
-    status_t checkExactProfile(uint32_t samplingRate, audio_channel_mask_t channelMask,
-                               audio_format_t format) const;
-    status_t checkCompatibleProfile(uint32_t &samplingRate, audio_channel_mask_t &channelMask,
-                                    audio_format_t &format,
-                                    audio_port_type_t portType,
-                                    audio_port_role_t portRole) const;
-    void clearProfiles();
-    // Assuming that this profile vector contains input profiles,
-    // find the best matching config from 'outputProfiles', according to
-    // the given preferences for audio formats and channel masks.
-    // Note: std::vectors are used because specialized containers for formats
-    //       and channels can be sorted and use their own ordering.
-    status_t findBestMatchingOutputConfig(const AudioProfileVector& outputProfiles,
-            const std::vector<audio_format_t>& preferredFormats, // order: most pref -> least pref
-            const std::vector<audio_channel_mask_t>& preferredOutputChannels,
-            bool preferHigherSamplingRates,
-            audio_config_base *bestOutputConfig) const;
-
-    sp<AudioProfile> getFirstValidProfile() const;
-    sp<AudioProfile> getFirstValidProfileFor(audio_format_t format) const;
-    bool hasValidProfile() const { return getFirstValidProfile() != 0; }
-
-    FormatVector getSupportedFormats() const;
-    bool hasDynamicChannelsFor(audio_format_t format) const;
-    bool hasDynamicFormat() const { return getProfileFor(gDynamicFormat) != 0; }
-    bool hasDynamicProfile() const;
-    bool hasDynamicRateFor(audio_format_t format) const;
-
-    // One audio profile will be added for each format supported by Audio HAL
-    void setFormats(const FormatVector &formats);
-
-    void dump(String8 *dst, int spaces) const;
-
-private:
-    sp<AudioProfile> getProfileFor(audio_format_t format) const;
-    void setSampleRatesFor(const SampleRateSet &sampleRates, audio_format_t format);
-    void setChannelsFor(const ChannelMaskSet &channelMasks, audio_format_t format);
-};
-
-bool operator == (const AudioProfile &left, const AudioProfile &right);
-
-} // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioProfileVector.h b/services/audiopolicy/common/managerdefinitions/include/AudioProfileVector.h
new file mode 100644
index 0000000..2e7328d
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioProfileVector.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <media/AudioProfile.h>
+#include <system/audio.h>
+
+namespace android {
+
+class AudioProfileVector : public AudioProfileVectorBase {
+public:
+    virtual ~AudioProfileVector() = default;
+
+    ssize_t add(const sp<AudioProfile> &profile) override;
+
+    // This API is intended to be used by the policy manager once retrieving capabilities
+    // for a profile with dynamic format, rate and channels attributes
+    ssize_t addProfileFromHal(const sp<AudioProfile> &profileToAdd);
+    void appendProfiles(const AudioProfileVectorBase& audioProfiles) {
+        insert(end(), audioProfiles.begin(), audioProfiles.end());
+    }
+
+    status_t checkExactProfile(const uint32_t samplingRate,
+                               audio_channel_mask_t channelMask,
+                               audio_format_t format) const;
+
+    status_t checkCompatibleProfile(uint32_t &samplingRate,
+                                    audio_channel_mask_t &channelMask,
+                                    audio_format_t &format,
+                                    audio_port_type_t portType,
+                                    audio_port_role_t portRole) const;
+
+    // Assuming that this profile vector contains input profiles,
+    // find the best matching config from 'outputProfiles', according to
+    // the given preferences for audio formats and channel masks.
+    // Note: std::vectors are used because specialized containers for formats
+    //       and channels can be sorted and use their own ordering.
+    status_t findBestMatchingOutputConfig(
+            const AudioProfileVector &outputProfiles,
+            const std::vector<audio_format_t> &preferredFormats, // order: most pref -> least pref
+            const std::vector<audio_channel_mask_t> &preferredOutputChannels,
+            bool preferHigherSamplingRates,
+            audio_config_base *bestOutputConfig) const;
+
+    // One audio profile will be added for each format supported by Audio HAL
+    void setFormats(const FormatVector &formats);
+
+private:
+    sp<AudioProfile> getProfileFor(audio_format_t format) const;
+    void setSampleRatesFor(const SampleRateSet &sampleRates, audio_format_t format);
+    void setChannelsFor(const ChannelMaskSet &channelMasks, audio_format_t format);
+};
+
+} // namespace android
\ No newline at end of file
diff --git a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
index 33e506f..c2f1d93 100644
--- a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
@@ -30,13 +30,13 @@
 {
 public:
      // Note that empty name refers by convention to a generic device.
-    explicit DeviceDescriptor(audio_devices_t type, const String8 &tagName = String8(""));
+    explicit DeviceDescriptor(audio_devices_t type, const std::string &tagName = "");
     DeviceDescriptor(audio_devices_t type, const FormatVector &encodedFormats,
-            const String8 &tagName = String8(""));
+            const std::string &tagName = "");
 
     virtual ~DeviceDescriptor() {}
 
-    virtual const String8 getTagName() const { return mTagName; }
+    virtual const std::string getTagName() const { return mTagName; }
 
     audio_devices_t type() const { return mDeviceType; }
     String8 address() const { return mAddress; }
@@ -75,7 +75,7 @@
 
 private:
     String8 mAddress{""};
-    String8 mTagName; // Unique human readable identifier for a device port found in conf file.
+    std::string mTagName; // Unique human readable identifier for a device port found in conf file.
     audio_devices_t     mDeviceType;
     FormatVector        mEncodedFormats;
     audio_port_handle_t mId = AUDIO_PORT_HANDLE_NONE;
@@ -112,10 +112,17 @@
      * equal to AUDIO_PORT_HANDLE_NONE, it also returns a nullptr.
      */
     sp<DeviceDescriptor> getDeviceFromId(audio_port_handle_t id) const;
-    sp<DeviceDescriptor> getDeviceFromTagName(const String8 &tagName) const;
+    sp<DeviceDescriptor> getDeviceFromTagName(const std::string &tagName) const;
     DeviceVector getDevicesFromHwModule(audio_module_handle_t moduleHandle) const;
     audio_devices_t getDeviceTypesFromHwModule(audio_module_handle_t moduleHandle) const;
 
+    DeviceVector getFirstDevicesFromTypes(std::vector<audio_devices_t> orderedTypes) const;
+    sp<DeviceDescriptor> getFirstExistingDevice(std::vector<audio_devices_t> orderedTypes) const;
+
+    // If there are devices with the given type and the devices to add is not empty,
+    // remove all the devices with the given type and add all the devices to add.
+    void replaceDevicesByType(audio_devices_t typeToRemove, const DeviceVector &devicesToAdd);
+
     bool contains(const sp<DeviceDescriptor>& item) const { return indexOf(item) >= 0; }
 
     /**
diff --git a/services/audiopolicy/common/managerdefinitions/include/HwModule.h b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
index eb34da4..65c886a 100644
--- a/services/audiopolicy/common/managerdefinitions/include/HwModule.h
+++ b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
@@ -82,17 +82,17 @@
     status_t addInputProfile(const sp<IOProfile> &profile);
     status_t addProfile(const sp<IOProfile> &profile);
 
-    status_t addOutputProfile(const String8& name, const audio_config_t *config,
+    status_t addOutputProfile(const std::string& name, const audio_config_t *config,
             audio_devices_t device, const String8& address);
-    status_t removeOutputProfile(const String8& name);
-    status_t addInputProfile(const String8& name, const audio_config_t *config,
+    status_t removeOutputProfile(const std::string& name);
+    status_t addInputProfile(const std::string& name, const audio_config_t *config,
             audio_devices_t device, const String8& address);
-    status_t removeInputProfile(const String8& name);
+    status_t removeInputProfile(const std::string& name);
 
     audio_module_handle_t getHandle() const { return mHandle; }
     void setHandle(audio_module_handle_t handle);
 
-    sp<AudioPort> findPortByTagName(const String8 &tagName) const
+    sp<AudioPort> findPortByTagName(const std::string &tagName) const
     {
         return mPorts.findByTagName(tagName);
     }
diff --git a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
index e0b56d4..419dd35 100644
--- a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
+++ b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
@@ -18,6 +18,7 @@
 
 #include "AudioPort.h"
 #include "DeviceDescriptor.h"
+#include "policy.h"
 #include <utils/String8.h>
 #include <system/audio.h>
 
@@ -33,7 +34,7 @@
 class IOProfile : public AudioPort
 {
 public:
-    IOProfile(const String8 &name, audio_port_role_t role)
+    IOProfile(const std::string &name, audio_port_role_t role)
         : AudioPort(name, AUDIO_PORT_TYPE_MIX, role),
           maxOpenCount(1),
           curOpenCount(0),
@@ -41,7 +42,7 @@
           curActiveCount(0) {}
 
     // For a Profile aka MixPort, tag name and name are equivalent.
-    virtual const String8 getTagName() const { return getName(); }
+    virtual const std::string getTagName() const { return getName(); }
 
     // FIXME: this is needed because shared MMAP stream clients use the same audio session.
     // Once capture clients are tracked individually and not per session this can be removed
@@ -183,13 +184,13 @@
 class InputProfile : public IOProfile
 {
 public:
-    explicit InputProfile(const String8 &name) : IOProfile(name, AUDIO_PORT_ROLE_SINK) {}
+    explicit InputProfile(const std::string &name) : IOProfile(name, AUDIO_PORT_ROLE_SINK) {}
 };
 
 class OutputProfile : public IOProfile
 {
 public:
-    explicit OutputProfile(const String8 &name) : IOProfile(name, AUDIO_PORT_ROLE_SOURCE) {}
+    explicit OutputProfile(const std::string &name) : IOProfile(name, AUDIO_PORT_ROLE_SOURCE) {}
 };
 
 } // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioCollections.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioCollections.cpp
index e8cf485..b391a09 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioCollections.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioCollections.cpp
@@ -24,7 +24,7 @@
 
 namespace android {
 
-sp<AudioPort> AudioPortVector::findByTagName(const String8 &tagName) const
+sp<AudioPort> AudioPortVector::findByTagName(const std::string &tagName) const
 {
     for (const auto& port : *this) {
         if (port->getTagName() == tagName) {
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
index a9b87e3..7cb2e10 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
@@ -34,8 +34,8 @@
 {
     if (profile != NULL) {
         profile->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
-        if (profile->mGains.size() > 0) {
-            profile->mGains[0]->getDefaultConfig(&mGain);
+        if (profile->getGains().size() > 0) {
+            profile->getGains()[0]->getDefaultConfig(&mGain);
         }
     }
 }
@@ -212,7 +212,7 @@
     mDevice = device;
 
     ALOGV("opening input for device %s profile %p name %s",
-          mDevice->toString().c_str(), mProfile.get(), mProfile->getName().string());
+          mDevice->toString().c_str(), mProfile.get(), mProfile->getName().c_str());
 
     audio_devices_t deviceType = mDevice->type();
 
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 49524b0..6f0c3f5 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -40,8 +40,8 @@
 {
     if (mPort.get() != nullptr) {
         mPort->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
-        if (mPort->mGains.size() > 0) {
-            mPort->mGains[0]->getDefaultConfig(&mGain);
+        if (mPort->getGains().size() > 0) {
+            mPort->getGains()[0]->getDefaultConfig(&mGain);
         }
     }
 }
@@ -483,7 +483,7 @@
     mFlags = (audio_output_flags_t)(mFlags | flags);
 
     ALOGV("opening output for device %s profile %p name %s",
-          mDevices.toString().c_str(), mProfile.get(), mProfile->getName().string());
+          mDevices.toString().c_str(), mProfile.get(), mProfile->getName().c_str());
 
     status_t status = mClientInterface->openOutput(mProfile->getModuleHandle(),
                                                    output,
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
index ff32284..decfad1 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
@@ -30,7 +30,7 @@
 // --- AudioPort class implementation
 void AudioPort::attach(const sp<HwModule>& module)
 {
-    ALOGV("%s: attaching module %s to port %s", __FUNCTION__, getModuleName(), mName.string());
+    ALOGV("%s: attaching module %s to port %s", __FUNCTION__, getModuleName(), mName.c_str());
     mModule = module;
 }
 
@@ -60,49 +60,6 @@
     return mModule != 0 ? mModule->getName() : "invalid module";
 }
 
-void AudioPort::toAudioPort(struct audio_port *port) const
-{
-    // TODO: update this function once audio_port structure reflects the new profile definition.
-    // For compatibility reason: flatening the AudioProfile into audio_port structure.
-    FormatSet flatenedFormats;
-    SampleRateSet flatenedRates;
-    ChannelMaskSet flatenedChannels;
-    for (const auto& profile : mProfiles) {
-        if (profile->isValid()) {
-            audio_format_t formatToExport = profile->getFormat();
-            const SampleRateSet &ratesToExport = profile->getSampleRates();
-            const ChannelMaskSet &channelsToExport = profile->getChannels();
-
-            flatenedFormats.insert(formatToExport);
-            flatenedRates.insert(ratesToExport.begin(), ratesToExport.end());
-            flatenedChannels.insert(channelsToExport.begin(), channelsToExport.end());
-
-            if (flatenedRates.size() > AUDIO_PORT_MAX_SAMPLING_RATES ||
-                    flatenedChannels.size() > AUDIO_PORT_MAX_CHANNEL_MASKS ||
-                    flatenedFormats.size() > AUDIO_PORT_MAX_FORMATS) {
-                ALOGE("%s: bailing out: cannot export profiles to port config", __FUNCTION__);
-                return;
-            }
-        }
-    }
-    port->role = mRole;
-    port->type = mType;
-    strlcpy(port->name, mName, AUDIO_PORT_MAX_NAME_LEN);
-    port->num_sample_rates = flatenedRates.size();
-    port->num_channel_masks = flatenedChannels.size();
-    port->num_formats = flatenedFormats.size();
-    std::copy(flatenedRates.begin(), flatenedRates.end(), port->sample_rates);
-    std::copy(flatenedChannels.begin(), flatenedChannels.end(), port->channel_masks);
-    std::copy(flatenedFormats.begin(), flatenedFormats.end(), port->formats);
-
-    ALOGV("AudioPort::toAudioPort() num gains %zu", mGains.size());
-
-    port->num_gains = std::min(mGains.size(), (size_t) AUDIO_PORT_MAX_GAINS);
-    for (size_t i = 0; i < port->num_gains; i++) {
-        port->gains[i] = mGains[i]->getGain();
-    }
-}
-
 void AudioPort::importAudioPort(const sp<AudioPort>& port, bool force __unused)
 {
     for (const auto& profileToImport : port->mProfiles) {
@@ -324,40 +281,13 @@
             }
         }
     }
-    ALOGV("%s Port[nm:%s] profile rate=%d, format=%d, channels=%d", __FUNCTION__, mName.string(),
+    ALOGV("%s Port[nm:%s] profile rate=%d, format=%d, channels=%d", __FUNCTION__, mName.c_str(),
           samplingRate, channelMask, format);
 }
 
-status_t AudioPort::checkGain(const struct audio_gain_config *gainConfig, int index) const
-{
-    if (index < 0 || (size_t)index >= mGains.size()) {
-        return BAD_VALUE;
-    }
-    return mGains[index]->checkConfig(gainConfig);
-}
-
-void AudioPort::dump(String8 *dst, int spaces, bool verbose) const
-{
-    if (!mName.isEmpty()) {
-        dst->appendFormat("%*s- name: %s\n", spaces, "", mName.string());
-    }
-    if (verbose) {
-        mProfiles.dump(dst, spaces);
-
-        if (mGains.size() != 0) {
-            dst->appendFormat("%*s- gains:\n", spaces, "");
-            for (size_t i = 0; i < mGains.size(); i++) {
-                std::string gainStr;
-                mGains[i]->dump(&gainStr, spaces + 2, i);
-                dst->append(gainStr.c_str());
-            }
-        }
-    }
-}
-
 void AudioPort::log(const char* indent) const
 {
-    ALOGI("%s Port[nm:%s, type:%d, role:%d]", indent, mName.string(), mType, mRole);
+    ALOGI("%s Port[nm:%s, type:%d, role:%d]", indent, mName.c_str(), mType, mRole);
 }
 
 // --- AudioPortConfig class implementation
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioProfile.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioProfileVector.cpp
similarity index 70%
rename from services/audiopolicy/common/managerdefinitions/src/AudioProfile.cpp
rename to services/audiopolicy/common/managerdefinitions/src/AudioProfileVector.cpp
index d1082e8..c17df37 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioProfile.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioProfileVector.cpp
@@ -26,95 +26,31 @@
 #include <utils/Errors.h>
 
 #include "AudioPort.h"
-#include "AudioProfile.h"
+#include "AudioProfileVector.h"
 #include "HwModule.h"
-#include "TypeConverter.h"
+#include "policy.h"
 
 namespace android {
 
-bool operator == (const AudioProfile &left, const AudioProfile &compareTo)
+status_t checkExact(const sp<AudioProfile> &audioProfile, uint32_t samplingRate,
+        audio_channel_mask_t channelMask, audio_format_t format)
 {
-    return (left.getFormat() == compareTo.getFormat()) &&
-            (left.getChannels() == compareTo.getChannels()) &&
-            (left.getSampleRates() == compareTo.getSampleRates());
-}
-
-static AudioProfile* createFullDynamicImpl()
-{
-    AudioProfile* dynamicProfile = new AudioProfile(gDynamicFormat,
-            ChannelMaskSet(), SampleRateSet());
-    dynamicProfile->setDynamicFormat(true);
-    dynamicProfile->setDynamicChannels(true);
-    dynamicProfile->setDynamicRate(true);
-    return dynamicProfile;
-}
-
-// static
-sp<AudioProfile> AudioProfile::createFullDynamic()
-{
-    static sp<AudioProfile> dynamicProfile = createFullDynamicImpl();
-    return dynamicProfile;
-}
-
-AudioProfile::AudioProfile(audio_format_t format,
-                           audio_channel_mask_t channelMasks,
-                           uint32_t samplingRate) :
-        mName(String8("")),
-        mFormat(format)
-{
-    mChannelMasks.insert(channelMasks);
-    mSamplingRates.insert(samplingRate);
-}
-
-AudioProfile::AudioProfile(audio_format_t format,
-                           const ChannelMaskSet &channelMasks,
-                           const SampleRateSet &samplingRateCollection) :
-        mName(String8("")),
-        mFormat(format),
-        mChannelMasks(channelMasks),
-        mSamplingRates(samplingRateCollection) {}
-
-void AudioProfile::setChannels(const ChannelMaskSet &channelMasks)
-{
-    if (mIsDynamicChannels) {
-        mChannelMasks = channelMasks;
-    }
-}
-
-void AudioProfile::setSampleRates(const SampleRateSet &sampleRates)
-{
-    if (mIsDynamicRate) {
-        mSamplingRates = sampleRates;
-    }
-}
-
-void AudioProfile::clear()
-{
-    if (mIsDynamicChannels) {
-        mChannelMasks.clear();
-    }
-    if (mIsDynamicRate) {
-        mSamplingRates.clear();
-    }
-}
-
-status_t AudioProfile::checkExact(uint32_t samplingRate, audio_channel_mask_t channelMask,
-                                  audio_format_t format) const
-{
-    if (audio_formats_match(format, mFormat) &&
-            supportsChannels(channelMask) &&
-            supportsRate(samplingRate)) {
+    if (audio_formats_match(format, audioProfile->getFormat()) &&
+            audioProfile->supportsChannels(channelMask) &&
+            audioProfile->supportsRate(samplingRate)) {
         return NO_ERROR;
     }
     return BAD_VALUE;
 }
 
-status_t AudioProfile::checkCompatibleSamplingRate(uint32_t samplingRate,
-                                                   uint32_t &updatedSamplingRate) const
+status_t checkCompatibleSamplingRate(const sp<AudioProfile> &audioProfile,
+                                     uint32_t samplingRate,
+                                     uint32_t &updatedSamplingRate)
 {
     ALOG_ASSERT(samplingRate > 0);
 
-    if (mSamplingRates.empty()) {
+    const SampleRateSet sampleRates = audioProfile->getSampleRates();
+    if (sampleRates.empty()) {
         updatedSamplingRate = samplingRate;
         return NO_ERROR;
     }
@@ -122,17 +58,17 @@
     // Search for the closest supported sampling rate that is above (preferred)
     // or below (acceptable) the desired sampling rate, within a permitted ratio.
     // The sampling rates are sorted in ascending order.
-    auto desiredRate = mSamplingRates.lower_bound(samplingRate);
+    auto desiredRate = sampleRates.lower_bound(samplingRate);
 
     // Prefer to down-sample from a higher sampling rate, as we get the desired frequency spectrum.
-    if (desiredRate != mSamplingRates.end()) {
+    if (desiredRate != sampleRates.end()) {
         if (*desiredRate / AUDIO_RESAMPLER_DOWN_RATIO_MAX <= samplingRate) {
             updatedSamplingRate = *desiredRate;
             return NO_ERROR;
         }
     }
     // But if we have to up-sample from a lower sampling rate, that's OK.
-    if (desiredRate != mSamplingRates.begin()) {
+    if (desiredRate != sampleRates.begin()) {
         uint32_t candidate = *(--desiredRate);
         if (candidate * AUDIO_RESAMPLER_UP_RATIO_MAX >= samplingRate) {
             updatedSamplingRate = candidate;
@@ -143,12 +79,14 @@
     return BAD_VALUE;
 }
 
-status_t AudioProfile::checkCompatibleChannelMask(audio_channel_mask_t channelMask,
-                                                  audio_channel_mask_t &updatedChannelMask,
-                                                  audio_port_type_t portType,
-                                                  audio_port_role_t portRole) const
+status_t checkCompatibleChannelMask(const sp<AudioProfile> &audioProfile,
+                                    audio_channel_mask_t channelMask,
+                                    audio_channel_mask_t &updatedChannelMask,
+                                    audio_port_type_t portType,
+                                    audio_port_role_t portRole)
 {
-    if (mChannelMasks.empty()) {
+    const ChannelMaskSet channelMasks = audioProfile->getChannels();
+    if (channelMasks.empty()) {
         updatedChannelMask = channelMask;
         return NO_ERROR;
     }
@@ -157,7 +95,7 @@
             == AUDIO_CHANNEL_REPRESENTATION_INDEX;
     const uint32_t channelCount = audio_channel_count_from_in_mask(channelMask);
     int bestMatch = 0;
-    for (const auto &supported : mChannelMasks) {
+    for (const auto &supported : channelMasks) {
         if (supported == channelMask) {
             // Exact matches always taken.
             updatedChannelMask = channelMask;
@@ -235,37 +173,6 @@
     return bestMatch > 0 ? NO_ERROR : BAD_VALUE;
 }
 
-void AudioProfile::dump(String8 *dst, int spaces) const
-{
-    dst->appendFormat("%s%s%s\n", mIsDynamicFormat ? "[dynamic format]" : "",
-             mIsDynamicChannels ? "[dynamic channels]" : "",
-             mIsDynamicRate ? "[dynamic rates]" : "");
-    if (mName.length() != 0) {
-        dst->appendFormat("%*s- name: %s\n", spaces, "", mName.string());
-    }
-    std::string formatLiteral;
-    if (FormatConverter::toString(mFormat, formatLiteral)) {
-        dst->appendFormat("%*s- format: %s\n", spaces, "", formatLiteral.c_str());
-    }
-    if (!mSamplingRates.empty()) {
-        dst->appendFormat("%*s- sampling rates:", spaces, "");
-        for (auto it = mSamplingRates.begin(); it != mSamplingRates.end();) {
-            dst->appendFormat("%d", *it);
-            dst->append(++it == mSamplingRates.end() ? "" : ", ");
-        }
-        dst->append("\n");
-    }
-
-    if (!mChannelMasks.empty()) {
-        dst->appendFormat("%*s- channel masks:", spaces, "");
-        for (auto it = mChannelMasks.begin(); it != mChannelMasks.end();) {
-            dst->appendFormat("0x%04x", *it);
-            dst->append(++it == mChannelMasks.end() ? "" : ", ");
-        }
-        dst->append("\n");
-    }
-}
-
 ssize_t AudioProfileVector::add(const sp<AudioProfile> &profile)
 {
     ssize_t index = size();
@@ -311,7 +218,7 @@
     return add(profileToAdd);
 }
 
-status_t AudioProfileVector::checkExactProfile(uint32_t samplingRate,
+status_t AudioProfileVector::checkExactProfile(const uint32_t samplingRate,
                                                audio_channel_mask_t channelMask,
                                                audio_format_t format) const
 {
@@ -320,7 +227,7 @@
     }
 
     for (const auto& profile : *this) {
-        if (profile->checkExact(samplingRate, channelMask, format) == NO_ERROR) {
+        if (checkExact(profile, samplingRate, channelMask, format) == NO_ERROR) {
             return NO_ERROR;
         }
     }
@@ -353,9 +260,9 @@
             // rate and channels as well
             audio_channel_mask_t updatedChannels;
             uint32_t updatedRate;
-            if (profile->checkCompatibleChannelMask(channelMask, updatedChannels,
-                                                    portType, portRole) == NO_ERROR &&
-                    profile->checkCompatibleSamplingRate(samplingRate, updatedRate) == NO_ERROR) {
+            if (checkCompatibleChannelMask(profile, channelMask, updatedChannels,
+                                           portType, portRole) == NO_ERROR &&
+                    checkCompatibleSamplingRate(profile, samplingRate, updatedRate) == NO_ERROR) {
                 // for inexact checks we take the first linear pcm format due to sorting.
                 format = formatToCompare;
                 channelMask = updatedChannels;
@@ -367,18 +274,6 @@
     return BAD_VALUE;
 }
 
-void AudioProfileVector::clearProfiles()
-{
-    for (auto it = begin(); it != end();) {
-        if ((*it)->isDynamicFormat() && (*it)->hasValidFormat()) {
-            it = erase(it);
-        } else {
-            (*it)->clear();
-            ++it;
-        }
-    }
-}
-
 // Returns an intersection between two possibly unsorted vectors and the contents of 'order'.
 // The result is ordered according to 'order'.
 template<typename T, typename Order>
@@ -449,67 +344,6 @@
     return BAD_VALUE;
 }
 
-sp<AudioProfile> AudioProfileVector::getFirstValidProfile() const
-{
-    for (const auto &profile : *this) {
-        if (profile->isValid()) {
-            return profile;
-        }
-    }
-    return nullptr;
-}
-
-sp<AudioProfile> AudioProfileVector::getFirstValidProfileFor(audio_format_t format) const
-{
-    for (const auto &profile : *this) {
-        if (profile->isValid() && profile->getFormat() == format) {
-            return profile;
-        }
-    }
-    return nullptr;
-}
-
-FormatVector AudioProfileVector::getSupportedFormats() const
-{
-    FormatVector supportedFormats;
-    for (const auto &profile : *this) {
-        if (profile->hasValidFormat()) {
-            supportedFormats.push_back(profile->getFormat());
-        }
-    }
-    return supportedFormats;
-}
-
-bool AudioProfileVector::hasDynamicChannelsFor(audio_format_t format) const
-{
-    for (const auto &profile : *this) {
-        if (profile->getFormat() == format && profile->isDynamicChannels()) {
-            return true;
-        }
-    }
-    return false;
-}
-
-bool AudioProfileVector::hasDynamicProfile() const
-{
-    for (const auto &profile : *this) {
-        if (profile->isDynamic()) {
-            return true;
-        }
-    }
-    return false;
-}
-
-bool AudioProfileVector::hasDynamicRateFor(audio_format_t format) const
-{
-    for (const auto &profile : *this) {
-        if (profile->getFormat() == format && profile->isDynamicRate()) {
-            return true;
-        }
-    }
-    return false;
-}
-
 void AudioProfileVector::setFormats(const FormatVector &formats)
 {
     // Only allow to change the format of dynamic profile
@@ -528,15 +362,6 @@
     }
 }
 
-void AudioProfileVector::dump(String8 *dst, int spaces) const
-{
-    dst->appendFormat("%*s- Profiles:\n", spaces, "");
-    for (size_t i = 0; i < size(); i++) {
-        dst->appendFormat("%*sProfile %zu:", spaces + 4, "", i);
-        at(i)->dump(dst, spaces + 8);
-    }
-}
-
 sp<AudioProfile> AudioProfileVector::getProfileFor(audio_format_t format) const
 {
     for (const auto &profile : *this) {
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioRoute.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioRoute.cpp
index 92cbe4e..0f35ff8 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioRoute.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioRoute.cpp
@@ -26,11 +26,11 @@
 void AudioRoute::dump(String8 *dst, int spaces) const
 {
     dst->appendFormat("%*s- Type: %s\n", spaces, "", mType == AUDIO_ROUTE_MUX ? "Mux" : "Mix");
-    dst->appendFormat("%*s- Sink: %s\n", spaces, "", mSink->getTagName().string());
+    dst->appendFormat("%*s- Sink: %s\n", spaces, "", mSink->getTagName().c_str());
     if (mSources.size() != 0) {
         dst->appendFormat("%*s- Sources: \n", spaces, "");
         for (size_t i = 0; i < mSources.size(); i++) {
-            dst->appendFormat("%*s%s \n", spaces + 4, "", mSources[i]->getTagName().string());
+            dst->appendFormat("%*s%s \n", spaces + 4, "", mSources[i]->getTagName().c_str());
         }
     }
     dst->append("\n");
@@ -41,10 +41,10 @@
     if (mSink == 0 || dstPort == 0 || dstPort != mSink) {
         return false;
     }
-    ALOGV("%s: sinks %s matching", __FUNCTION__, mSink->getTagName().string());
+    ALOGV("%s: sinks %s matching", __FUNCTION__, mSink->getTagName().c_str());
     for (const auto &sourcePort : mSources) {
         if (sourcePort == srcPort) {
-            ALOGV("%s: sources %s matching", __FUNCTION__, sourcePort->getTagName().string());
+            ALOGV("%s: sources %s matching", __FUNCTION__, sourcePort->getTagName().c_str());
             return true;
         }
     }
diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
index c996cbf..018636d 100644
--- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
@@ -26,14 +26,14 @@
 
 namespace android {
 
-DeviceDescriptor::DeviceDescriptor(audio_devices_t type, const String8 &tagName) :
+DeviceDescriptor::DeviceDescriptor(audio_devices_t type, const std::string &tagName) :
         DeviceDescriptor(type, FormatVector{}, tagName)
 {
 }
 
 DeviceDescriptor::DeviceDescriptor(audio_devices_t type, const FormatVector &encodedFormats,
-        const String8 &tagName) :
-    AudioPort(String8(""), AUDIO_PORT_TYPE_DEVICE,
+        const std::string &tagName) :
+    AudioPort("", AUDIO_PORT_TYPE_DEVICE,
               audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK :
                                              AUDIO_PORT_ROLE_SOURCE),
     mTagName(tagName), mDeviceType(type), mEncodedFormats(encodedFormats)
@@ -255,7 +255,6 @@
         audio_devices_t curType = itemAt(i)->type() & ~AUDIO_DEVICE_BIT_IN;
         if ((isOutput == curIsOutput) && ((type & curType) != 0)) {
             devices.add(itemAt(i));
-            type &= ~curType;
             ALOGV("DeviceVector::%s() for type %08x found %p",
                     __func__, itemAt(i)->type(), itemAt(i).get());
         }
@@ -263,7 +262,7 @@
     return devices;
 }
 
-sp<DeviceDescriptor> DeviceVector::getDeviceFromTagName(const String8 &tagName) const
+sp<DeviceDescriptor> DeviceVector::getDeviceFromTagName(const std::string &tagName) const
 {
     for (const auto& device : *this) {
         if (device->getTagName() == tagName) {
@@ -273,6 +272,38 @@
     return nullptr;
 }
 
+DeviceVector DeviceVector::getFirstDevicesFromTypes(
+        std::vector<audio_devices_t> orderedTypes) const
+{
+    DeviceVector devices;
+    for (auto deviceType : orderedTypes) {
+        if (!(devices = getDevicesFromTypeMask(deviceType)).isEmpty()) {
+            break;
+        }
+    }
+    return devices;
+}
+
+sp<DeviceDescriptor> DeviceVector::getFirstExistingDevice(
+        std::vector<audio_devices_t> orderedTypes) const {
+    sp<DeviceDescriptor> device;
+    for (auto deviceType : orderedTypes) {
+        if ((device = getDevice(deviceType, String8(""), AUDIO_FORMAT_DEFAULT)) != nullptr) {
+            break;
+        }
+    }
+    return device;
+}
+
+void DeviceVector::replaceDevicesByType(
+        audio_devices_t typeToRemove, const DeviceVector &devicesToAdd) {
+    DeviceVector devicesToRemove = getDevicesFromTypeMask(typeToRemove);
+    if (!devicesToRemove.isEmpty() && !devicesToAdd.isEmpty()) {
+        remove(devicesToRemove);
+        add(devicesToAdd);
+    }
+}
+
 void DeviceVector::dump(String8 *dst, const String8 &tag, int spaces, bool verbose) const
 {
     if (isEmpty()) {
@@ -343,8 +374,8 @@
     if (mId != 0) {
         dst->appendFormat("%*s- id: %2d\n", spaces, "", mId);
     }
-    if (!mTagName.isEmpty()) {
-        dst->appendFormat("%*s- tag name: %s\n", spaces, "", mTagName.string());
+    if (!mTagName.empty()) {
+        dst->appendFormat("%*s- tag name: %s\n", spaces, "", mTagName.c_str());
     }
 
     dst->appendFormat("%*s- type: %-48s\n", spaces, "", ::android::toString(mDeviceType).c_str());
@@ -352,7 +383,9 @@
     if (mAddress.size() != 0) {
         dst->appendFormat("%*s- address: %-32s\n", spaces, "", mAddress.string());
     }
-    AudioPort::dump(dst, spaces, verbose);
+    std::string portStr;
+    AudioPort::dump(&portStr, spaces, verbose);
+    dst->append(portStr.c_str());
 }
 
 std::string DeviceDescriptor::toString() const
diff --git a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
index 99e282e..c232775 100644
--- a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
@@ -41,7 +41,7 @@
     }
 }
 
-status_t HwModule::addOutputProfile(const String8& name, const audio_config_t *config,
+status_t HwModule::addOutputProfile(const std::string& name, const audio_config_t *config,
                                     audio_devices_t device, const String8& address)
 {
     sp<IOProfile> profile = new OutputProfile(name);
@@ -95,7 +95,7 @@
     }
 }
 
-status_t HwModule::removeOutputProfile(const String8& name)
+status_t HwModule::removeOutputProfile(const std::string& name)
 {
     for (size_t i = 0; i < mOutputProfiles.size(); i++) {
         if (mOutputProfiles[i]->getName() == name) {
@@ -110,7 +110,7 @@
     return NO_ERROR;
 }
 
-status_t HwModule::addInputProfile(const String8& name, const audio_config_t *config,
+status_t HwModule::addInputProfile(const std::string& name, const audio_config_t *config,
                                    audio_devices_t device, const String8& address)
 {
     sp<IOProfile> profile = new InputProfile(name);
@@ -125,12 +125,12 @@
     profile->addSupportedDevice(devDesc);
 
     ALOGV("addInputProfile() name %s rate %d mask 0x%08x",
-          name.string(), config->sample_rate, config->channel_mask);
+          name.c_str(), config->sample_rate, config->channel_mask);
 
     return addInputProfile(profile);
 }
 
-status_t HwModule::removeInputProfile(const String8& name)
+status_t HwModule::removeInputProfile(const std::string& name)
 {
     for (size_t i = 0; i < mInputProfiles.size(); i++) {
         if (mInputProfiles[i]->getName() == name) {
@@ -193,13 +193,13 @@
             }
             DeviceVector sourceDevicesForRoute = getRouteSourceDevices(route);
             if (sourceDevicesForRoute.isEmpty()) {
-                ALOGE("%s: invalid source devices for %s", __FUNCTION__, stream->getName().string());
+                ALOGE("%s: invalid source devices for %s", __FUNCTION__, stream->getName().c_str());
                 continue;
             }
             sourceDevices.add(sourceDevicesForRoute);
         }
         if (sourceDevices.isEmpty()) {
-            ALOGE("%s: invalid source devices for %s", __FUNCTION__, stream->getName().string());
+            ALOGE("%s: invalid source devices for %s", __FUNCTION__, stream->getName().c_str());
             continue;
         }
         stream->setSupportedDevices(sourceDevices);
@@ -214,7 +214,7 @@
             }
             sp<DeviceDescriptor> sinkDevice = getRouteSinkDevice(route);
             if (sinkDevice == 0) {
-                ALOGE("%s: invalid sink device for %s", __FUNCTION__, stream->getName().string());
+                ALOGE("%s: invalid sink device for %s", __FUNCTION__, stream->getName().c_str());
                 continue;
             }
             sinkDevices.add(sinkDevice);
@@ -335,7 +335,7 @@
             if (allowToCreate) {
                 moduleDevice->attach(hwModule);
                 moduleDevice->setAddress(devAddress);
-                moduleDevice->setName(String8(name));
+                moduleDevice->setName(name);
             }
             return moduleDevice;
         }
@@ -359,8 +359,8 @@
               address);
         return nullptr;
     }
-    sp<DeviceDescriptor> device = new DeviceDescriptor(type, String8(name));
-    device->setName(String8(name));
+    sp<DeviceDescriptor> device = new DeviceDescriptor(type, name);
+    device->setName(name);
     device->setAddress(String8(address));
     device->setEncodedFormat(encodedFormat);
 
diff --git a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
index aefe557..bf1a0f7 100644
--- a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
@@ -107,7 +107,9 @@
 
 void IOProfile::dump(String8 *dst) const
 {
-    AudioPort::dump(dst, 4);
+    std::string portStr;
+    AudioPort::dump(&portStr, 4);
+    dst->append(portStr.c_str());
 
     dst->appendFormat("    - flags: 0x%04x", getFlags());
     std::string flagsLiteral;
diff --git a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
index c699aa7..707169b 100644
--- a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
@@ -430,7 +430,7 @@
     audio_port_role_t portRole = (role == Attributes::roleSource) ?
             AUDIO_PORT_ROLE_SOURCE : AUDIO_PORT_ROLE_SINK;
 
-    Element mixPort = new IOProfile(String8(name.c_str()), portRole);
+    Element mixPort = new IOProfile(name, portRole);
 
     AudioProfileTraits::Collection profiles;
     status_t status = deserializeCollection<AudioProfileTraits>(child, &profiles, NULL);
@@ -438,7 +438,7 @@
         return Status::fromStatusT(status);
     }
     if (profiles.empty()) {
-        profiles.add(AudioProfile::createFullDynamic());
+        profiles.add(AudioProfile::createFullDynamic(gDynamicFormat));
     }
     mixPort->setAudioProfiles(profiles);
 
@@ -508,7 +508,7 @@
     if (!encodedFormatsLiteral.empty()) {
         encodedFormats = formatsFromString(encodedFormatsLiteral, " ");
     }
-    Element deviceDesc = new DeviceDescriptor(type, encodedFormats, String8(name.c_str()));
+    Element deviceDesc = new DeviceDescriptor(type, encodedFormats, name);
 
     std::string address = getXmlAttribute(cur, Attributes::address);
     if (!address.empty()) {
@@ -522,7 +522,7 @@
         return Status::fromStatusT(status);
     }
     if (profiles.empty()) {
-        profiles.add(AudioProfile::createFullDynamic());
+        profiles.add(AudioProfile::createFullDynamic(gDynamicFormat));
     }
     deviceDesc->setAudioProfiles(profiles);
 
@@ -532,7 +532,7 @@
         return Status::fromStatusT(status);
     }
     ALOGV("%s: adding device tag %s type %08x address %s", __func__,
-          deviceDesc->getName().string(), type, deviceDesc->address().string());
+          deviceDesc->getName().c_str(), type, deviceDesc->address().string());
     return deviceDesc;
 }
 
@@ -555,7 +555,7 @@
         return Status::fromStatusT(BAD_VALUE);
     }
     // Convert Sink name to port pointer
-    sp<AudioPort> sink = ctx->findPortByTagName(String8(sinkAttr.c_str()));
+    sp<AudioPort> sink = ctx->findPortByTagName(sinkAttr);
     if (sink == NULL) {
         ALOGE("%s: no sink found with name=%s", __func__, sinkAttr.c_str());
         return Status::fromStatusT(BAD_VALUE);
@@ -574,7 +574,7 @@
     char *devTag = strtok(sourcesLiteral.get(), ",");
     while (devTag != NULL) {
         if (strlen(devTag) != 0) {
-            sp<AudioPort> source = ctx->findPortByTagName(String8(devTag));
+            sp<AudioPort> source = ctx->findPortByTagName(devTag);
             if (source == NULL) {
                 ALOGE("%s: no source found with name=%s", __func__, devTag);
                 return Status::fromStatusT(BAD_VALUE);
@@ -648,7 +648,7 @@
                         ALOGV("%s: %s %s=%s", __func__, tag, childAttachedDeviceTag,
                                 reinterpret_cast<const char*>(attachedDevice.get()));
                         sp<DeviceDescriptor> device = module->getDeclaredDevices().
-                                getDeviceFromTagName(String8(reinterpret_cast<const char*>(
+                                getDeviceFromTagName(std::string(reinterpret_cast<const char*>(
                                                         attachedDevice.get())));
                         ctx->addAvailableDevice(device);
                     }
@@ -663,7 +663,7 @@
                 ALOGV("%s: %s %s=%s", __func__, tag, childDefaultOutputDeviceTag,
                         reinterpret_cast<const char*>(defaultOutputDevice.get()));
                 sp<DeviceDescriptor> device = module->getDeclaredDevices().getDeviceFromTagName(
-                        String8(reinterpret_cast<const char*>(defaultOutputDevice.get())));
+                        std::string(reinterpret_cast<const char*>(defaultOutputDevice.get())));
                 if (device != 0 && ctx->getDefaultOutputDevice() == 0) {
                     ctx->setDefaultOutputDevice(device);
                     ALOGV("%s: default is %08x",
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index c602f3a..b895c2f 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -136,27 +136,23 @@
     return EngineBase::setForceUse(usage, config);
 }
 
-audio_devices_t Engine::getDeviceForStrategyInt(legacy_strategy strategy,
-                                                DeviceVector availableOutputDevices,
-                                                DeviceVector availableInputDevices,
-                                                const SwAudioOutputCollection &outputs,
-                                                uint32_t outputDeviceTypesToIgnore) const
+DeviceVector Engine::getDevicesForStrategyInt(legacy_strategy strategy,
+                                              DeviceVector availableOutputDevices,
+                                              DeviceVector availableInputDevices,
+                                              const SwAudioOutputCollection &outputs) const
 {
-    uint32_t device = AUDIO_DEVICE_NONE;
-    uint32_t availableOutputDevicesType =
-            availableOutputDevices.types() & ~outputDeviceTypesToIgnore;
+    DeviceVector devices;
 
     switch (strategy) {
 
     case STRATEGY_TRANSMITTED_THROUGH_SPEAKER:
-        device = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
+        devices = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER);
         break;
 
     case STRATEGY_SONIFICATION_RESPECTFUL:
         if (isInCall() || outputs.isActiveLocally(toVolumeSource(AUDIO_STREAM_VOICE_CALL))) {
-            device = getDeviceForStrategyInt(
-                    STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs,
-                    outputDeviceTypesToIgnore);
+            devices = getDevicesForStrategyInt(
+                    STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs);
         } else {
             bool media_active_locally =
                     outputs.isActiveLocally(toVolumeSource(AUDIO_STREAM_MUSIC),
@@ -165,17 +161,18 @@
                         toVolumeSource(AUDIO_STREAM_ACCESSIBILITY),
                         SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY);
             // routing is same as media without the "remote" device
-            device = getDeviceForStrategyInt(STRATEGY_MEDIA,
+            availableOutputDevices.remove(availableOutputDevices.getDevicesFromTypeMask(
+                    AUDIO_DEVICE_OUT_REMOTE_SUBMIX));
+            devices = getDevicesForStrategyInt(STRATEGY_MEDIA,
                     availableOutputDevices,
-                    availableInputDevices, outputs,
-                    AUDIO_DEVICE_OUT_REMOTE_SUBMIX | outputDeviceTypesToIgnore);
+                    availableInputDevices, outputs);
             // if no media is playing on the device, check for mandatory use of "safe" speaker
             // when media would have played on speaker, and the safe speaker path is available
-            if (!media_active_locally
-                    && (device & AUDIO_DEVICE_OUT_SPEAKER)
-                    && (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
-                device |= AUDIO_DEVICE_OUT_SPEAKER_SAFE;
-                device &= ~AUDIO_DEVICE_OUT_SPEAKER;
+            if (!media_active_locally) {
+                devices.replaceDevicesByType(
+                        AUDIO_DEVICE_OUT_SPEAKER,
+                        availableOutputDevices.getDevicesFromTypeMask(
+                                AUDIO_DEVICE_OUT_SPEAKER_SAFE));
             }
         }
         break;
@@ -183,9 +180,8 @@
     case STRATEGY_DTMF:
         if (!isInCall()) {
             // when off call, DTMF strategy follows the same rules as MEDIA strategy
-            device = getDeviceForStrategyInt(
-                    STRATEGY_MEDIA, availableOutputDevices, availableInputDevices, outputs,
-                    outputDeviceTypesToIgnore);
+            devices = getDevicesForStrategyInt(
+                    STRATEGY_MEDIA, availableOutputDevices, availableInputDevices, outputs);
             break;
         }
         // when in call, DTMF and PHONE strategies follow the same rules
@@ -197,24 +193,27 @@
         //   - cannot route from voice call RX OR
         //   - audio HAL version is < 3.0 and TX device is on the primary HW module
         if (getPhoneState() == AUDIO_MODE_IN_CALL) {
-            audio_devices_t txDevice = getDeviceForInputSource(AUDIO_SOURCE_VOICE_COMMUNICATION);
+            audio_devices_t txDevice = getDeviceForInputSource(
+                    AUDIO_SOURCE_VOICE_COMMUNICATION)->type();
             sp<AudioOutputDescriptor> primaryOutput = outputs.getPrimaryOutput();
-            audio_devices_t availPrimaryInputDevices =
-                 availableInputDevices.getDeviceTypesFromHwModule(primaryOutput->getModuleHandle());
+            DeviceVector availPrimaryInputDevices =
+                    availableInputDevices.getDevicesFromHwModule(primaryOutput->getModuleHandle());
 
             // TODO: getPrimaryOutput return only devices from first module in
             // audio_policy_configuration.xml, hearing aid is not there, but it's
             // a primary device
             // FIXME: this is not the right way of solving this problem
-            audio_devices_t availPrimaryOutputDevices =
-                (primaryOutput->supportedDevices().types() | AUDIO_DEVICE_OUT_HEARING_AID) &
-                availableOutputDevices.types();
+            DeviceVector availPrimaryOutputDevices = availableOutputDevices.getDevicesFromTypeMask(
+                    primaryOutput->supportedDevices().types());
+            availPrimaryOutputDevices.add(
+                    availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_HEARING_AID));
 
-            if (((availableInputDevices.types() &
-                    AUDIO_DEVICE_IN_TELEPHONY_RX & ~AUDIO_DEVICE_BIT_IN) == 0) ||
-                    (((txDevice & availPrimaryInputDevices & ~AUDIO_DEVICE_BIT_IN) != 0) &&
-                         (primaryOutput->getAudioPort()->getModuleVersionMajor() < 3))) {
-                availableOutputDevicesType = availPrimaryOutputDevices;
+            if ((availableInputDevices.getDevice(AUDIO_DEVICE_IN_TELEPHONY_RX,
+                    String8(""), AUDIO_FORMAT_DEFAULT) == nullptr) ||
+                    ((availPrimaryInputDevices.getDevice(
+                            txDevice, String8(""), AUDIO_FORMAT_DEFAULT) != nullptr) &&
+                            (primaryOutput->getAudioPort()->getModuleVersionMajor() < 3))) {
+                availableOutputDevices = availPrimaryOutputDevices;
             }
         }
         // for phone strategy, we first consider the forced use and then the available devices by
@@ -222,49 +221,40 @@
         switch (getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION)) {
         case AUDIO_POLICY_FORCE_BT_SCO:
             if (!isInCall() || strategy != STRATEGY_DTMF) {
-                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
-                if (device) break;
+                devices = availableOutputDevices.getDevicesFromTypeMask(
+                        AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT);
+                if (!devices.isEmpty()) break;
             }
-            device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
-            if (device) break;
-            device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO;
-            if (device) break;
+            devices = availableOutputDevices.getFirstDevicesFromTypes({
+                    AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET, AUDIO_DEVICE_OUT_BLUETOOTH_SCO});
+            if (!devices.isEmpty()) break;
             // if SCO device is requested but no SCO device is available, fall back to default case
             FALLTHROUGH_INTENDED;
 
         default:    // FORCE_NONE
-            device = availableOutputDevicesType & AUDIO_DEVICE_OUT_HEARING_AID;
-            if (device) break;
+            devices = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_HEARING_AID);
+            if (!devices.isEmpty()) break;
             // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP
             if (!isInCall() &&
                     (getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
                      outputs.isA2dpSupported()) {
-                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
-                if (device) break;
-                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
-                if (device) break;
+                devices = availableOutputDevices.getFirstDevicesFromTypes({
+                        AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
+                        AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES});
+                if (!devices.isEmpty()) break;
             }
-            device = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
-            if (device) break;
-            device = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADSET;
-            if (device) break;
-            device = availableOutputDevicesType & AUDIO_DEVICE_OUT_LINE;
-            if (device) break;
-            device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_HEADSET;
-            if (device) break;
-            device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_DEVICE;
-            if (device) break;
+            devices = availableOutputDevices.getFirstDevicesFromTypes({
+                    AUDIO_DEVICE_OUT_WIRED_HEADPHONE, AUDIO_DEVICE_OUT_WIRED_HEADSET,
+                    AUDIO_DEVICE_OUT_LINE, AUDIO_DEVICE_OUT_USB_HEADSET,
+                    AUDIO_DEVICE_OUT_USB_DEVICE});
+            if (!devices.isEmpty()) break;
             if (!isInCall()) {
-                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_ACCESSORY;
-                if (device) break;
-                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
-                if (device) break;
-                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_DIGITAL;
-                if (device) break;
-                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
-                if (device) break;
+                devices = availableOutputDevices.getFirstDevicesFromTypes({
+                        AUDIO_DEVICE_OUT_USB_ACCESSORY, AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET,
+                        AUDIO_DEVICE_OUT_AUX_DIGITAL, AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET});
+                if (!devices.isEmpty()) break;
             }
-            device = availableOutputDevicesType & AUDIO_DEVICE_OUT_EARPIECE;
+            devices = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_EARPIECE);
             break;
 
         case AUDIO_POLICY_FORCE_SPEAKER:
@@ -273,22 +263,18 @@
             if (!isInCall() &&
                     (getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
                      outputs.isA2dpSupported()) {
-                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
-                if (device) break;
+                devices = availableOutputDevices.getDevicesFromTypeMask(
+                        AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER);
+                if (!devices.isEmpty()) break;
             }
             if (!isInCall()) {
-                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_ACCESSORY;
-                if (device) break;
-                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_DEVICE;
-                if (device) break;
-                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
-                if (device) break;
-                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_DIGITAL;
-                if (device) break;
-                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
-                if (device) break;
+                devices = availableOutputDevices.getFirstDevicesFromTypes({
+                        AUDIO_DEVICE_OUT_USB_ACCESSORY, AUDIO_DEVICE_OUT_USB_DEVICE,
+                        AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET, AUDIO_DEVICE_OUT_AUX_DIGITAL,
+                        AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET});
+                if (!devices.isEmpty()) break;
             }
-            device = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
+            devices = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER);
             break;
         }
     break;
@@ -298,9 +284,8 @@
         // If incall, just select the STRATEGY_PHONE device
         if (isInCall() ||
                 outputs.isActiveLocally(toVolumeSource(AUDIO_STREAM_VOICE_CALL))) {
-            device = getDeviceForStrategyInt(
-                    STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs,
-                    outputDeviceTypesToIgnore);
+            devices = getDevicesForStrategyInt(
+                    STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs);
             break;
         }
         FALLTHROUGH_INTENDED;
@@ -313,41 +298,37 @@
 
         if ((strategy == STRATEGY_SONIFICATION) ||
                 (getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)) {
-            device = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
+            devices = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER);
         }
 
         // if SCO headset is connected and we are told to use it, play ringtone over
         // speaker and BT SCO
-        if ((availableOutputDevicesType & AUDIO_DEVICE_OUT_ALL_SCO) != 0) {
-            uint32_t device2 = AUDIO_DEVICE_NONE;
-            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
-            if (device2 == AUDIO_DEVICE_NONE) {
-                device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
-            }
-            if (device2 == AUDIO_DEVICE_NONE) {
-                device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO;
-            }
+        if (!availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_ALL_SCO).isEmpty()) {
+            DeviceVector devices2;
+            devices2 = availableOutputDevices.getFirstDevicesFromTypes({
+                    AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT, AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET,
+                    AUDIO_DEVICE_OUT_BLUETOOTH_SCO});
             // Use ONLY Bluetooth SCO output when ringing in vibration mode
             if (!((getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)
                     && (strategy == STRATEGY_ENFORCED_AUDIBLE))) {
                 if (getForceUse(AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING)
                         == AUDIO_POLICY_FORCE_BT_SCO) {
-                    if (device2 != AUDIO_DEVICE_NONE) {
-                        device = device2;
+                    if (!devices2.isEmpty()) {
+                        devices = devices2;
                         break;
                     }
                 }
             }
             // Use both Bluetooth SCO and phone default output when ringing in normal mode
             if (getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION) == AUDIO_POLICY_FORCE_BT_SCO) {
-                if ((strategy == STRATEGY_SONIFICATION) &&
-                        (device & AUDIO_DEVICE_OUT_SPEAKER) &&
-                        (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
-                    device |= AUDIO_DEVICE_OUT_SPEAKER_SAFE;
-                    device &= ~AUDIO_DEVICE_OUT_SPEAKER;
+                if (strategy == STRATEGY_SONIFICATION) {
+                    devices.replaceDevicesByType(
+                            AUDIO_DEVICE_OUT_SPEAKER,
+                            availableOutputDevices.getDevicesFromTypeMask(
+                                    AUDIO_DEVICE_OUT_SPEAKER_SAFE));
                 }
-                if (device2 != AUDIO_DEVICE_NONE) {
-                    device |= device2;
+                if (!devices2.isEmpty()) {
+                    devices.add(devices2);
                     break;
                 }
             }
@@ -361,25 +342,20 @@
             // compressed format as they would likely not be mixed and dropped.
             for (size_t i = 0; i < outputs.size(); i++) {
                 sp<AudioOutputDescriptor> desc = outputs.valueAt(i);
-                audio_devices_t devices = desc->devices().types() &
-                    (AUDIO_DEVICE_OUT_HDMI | AUDIO_DEVICE_OUT_SPDIF | AUDIO_DEVICE_OUT_HDMI_ARC);
-                if (desc->isActive() && !audio_is_linear_pcm(desc->mFormat) &&
-                        devices != AUDIO_DEVICE_NONE) {
-                    availableOutputDevicesType = availableOutputDevices.types() & ~devices;
+                if (desc->isActive() && !audio_is_linear_pcm(desc->getFormat())) {
+                    availableOutputDevices.remove(desc->devices().getDevicesFromTypeMask(
+                            AUDIO_DEVICE_OUT_HDMI | AUDIO_DEVICE_OUT_SPDIF
+                            | AUDIO_DEVICE_OUT_HDMI_ARC));
                 }
             }
-            availableOutputDevices =
-                    availableOutputDevices.getDevicesFromTypeMask(availableOutputDevicesType);
             if (outputs.isActive(toVolumeSource(AUDIO_STREAM_RING)) ||
                     outputs.isActive(toVolumeSource(AUDIO_STREAM_ALARM))) {
-                return getDeviceForStrategyInt(
-                    STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs,
-                    outputDeviceTypesToIgnore);
+                return getDevicesForStrategyInt(
+                    STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs);
             }
             if (isInCall()) {
-                return getDeviceForStrategyInt(
-                        STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs,
-                        outputDeviceTypesToIgnore);
+                return getDevicesForStrategyInt(
+                        STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs);
             }
         }
         // For other cases, STRATEGY_ACCESSIBILITY behaves like STRATEGY_MEDIA
@@ -388,128 +364,116 @@
     // FIXME: STRATEGY_REROUTING follow STRATEGY_MEDIA for now
     case STRATEGY_REROUTING:
     case STRATEGY_MEDIA: {
-        uint32_t device2 = AUDIO_DEVICE_NONE;
+        DeviceVector devices2;
         if (strategy != STRATEGY_SONIFICATION) {
             // no sonification on remote submix (e.g. WFD)
-            if (availableOutputDevices.getDevice(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
-                                                 String8("0"), AUDIO_FORMAT_DEFAULT) != 0) {
-                device2 = availableOutputDevices.types() & AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
+            sp<DeviceDescriptor> remoteSubmix;
+            if ((remoteSubmix = availableOutputDevices.getDevice(
+                    AUDIO_DEVICE_OUT_REMOTE_SUBMIX, String8("0"),
+                    AUDIO_FORMAT_DEFAULT)) != nullptr) {
+                devices2.add(remoteSubmix);
             }
         }
         if (isInCall() && (strategy == STRATEGY_MEDIA)) {
-            device = getDeviceForStrategyInt(
-                    STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs,
-                    outputDeviceTypesToIgnore);
+            devices = getDevicesForStrategyInt(
+                    STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs);
             break;
         }
         // FIXME: Find a better solution to prevent routing to BT hearing aid(b/122931261).
-        if ((device2 == AUDIO_DEVICE_NONE) &&
+        if ((devices2.isEmpty()) &&
                 (getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP)) {
-            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_HEARING_AID;
+            devices2 = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_HEARING_AID);
         }
-        if ((device2 == AUDIO_DEVICE_NONE) &&
+        if ((devices2.isEmpty()) &&
                 (getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
                  outputs.isA2dpSupported()) {
-            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
-            if (device2 == AUDIO_DEVICE_NONE) {
-                device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
-            }
-            if (device2 == AUDIO_DEVICE_NONE) {
-                device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
-            }
+            devices2 = availableOutputDevices.getFirstDevicesFromTypes({
+                    AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES,
+                    AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER});
         }
-        if ((device2 == AUDIO_DEVICE_NONE) &&
+        if ((devices2.isEmpty()) &&
             (getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) == AUDIO_POLICY_FORCE_SPEAKER)) {
-            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
+            devices2 = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER);
         }
-        if (device2 == AUDIO_DEVICE_NONE) {
-            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
+        if (devices2.isEmpty()) {
+            devices2 = availableOutputDevices.getFirstDevicesFromTypes({
+                    AUDIO_DEVICE_OUT_WIRED_HEADPHONE, AUDIO_DEVICE_OUT_LINE,
+                    AUDIO_DEVICE_OUT_WIRED_HEADSET, AUDIO_DEVICE_OUT_USB_HEADSET,
+                    AUDIO_DEVICE_OUT_USB_ACCESSORY, AUDIO_DEVICE_OUT_USB_DEVICE,
+                    AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET});
         }
-        if (device2 == AUDIO_DEVICE_NONE) {
-            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_LINE;
-        }
-        if (device2 == AUDIO_DEVICE_NONE) {
-            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADSET;
-        }
-        if (device2 == AUDIO_DEVICE_NONE) {
-            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_HEADSET;
-        }
-        if (device2 == AUDIO_DEVICE_NONE) {
-            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_ACCESSORY;
-        }
-        if (device2 == AUDIO_DEVICE_NONE) {
-            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_DEVICE;
-        }
-        if (device2 == AUDIO_DEVICE_NONE) {
-            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
-        }
-        if ((device2 == AUDIO_DEVICE_NONE) && (strategy != STRATEGY_SONIFICATION)) {
+        if ((devices2.isEmpty()) && (strategy != STRATEGY_SONIFICATION)) {
             // no sonification on aux digital (e.g. HDMI)
-            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_DIGITAL;
+            devices2 = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_AUX_DIGITAL);
         }
-        if ((device2 == AUDIO_DEVICE_NONE) &&
+        if ((devices2.isEmpty()) &&
                 (getForceUse(AUDIO_POLICY_FORCE_FOR_DOCK) == AUDIO_POLICY_FORCE_ANALOG_DOCK)) {
-            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
+            devices2 = availableOutputDevices.getDevicesFromTypeMask(
+                    AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET);
         }
-        if (device2 == AUDIO_DEVICE_NONE) {
-            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
+        if (devices2.isEmpty()) {
+            devices2 = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER);
         }
-        int device3 = AUDIO_DEVICE_NONE;
+        DeviceVector devices3;
         if (strategy == STRATEGY_MEDIA) {
             // ARC, SPDIF and AUX_LINE can co-exist with others.
-            device3 = availableOutputDevicesType & AUDIO_DEVICE_OUT_HDMI_ARC;
-            device3 |= (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPDIF);
-            device3 |= (availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_LINE);
+            devices3 = availableOutputDevices.getDevicesFromTypeMask(
+                    AUDIO_DEVICE_OUT_HDMI_ARC | AUDIO_DEVICE_OUT_SPDIF | AUDIO_DEVICE_OUT_AUX_LINE);
         }
 
-        device2 |= device3;
+        devices2.add(devices3);
         // device is DEVICE_OUT_SPEAKER if we come from case STRATEGY_SONIFICATION or
         // STRATEGY_ENFORCED_AUDIBLE, AUDIO_DEVICE_NONE otherwise
-        device |= device2;
+        devices.add(devices2);
 
         // If hdmi system audio mode is on, remove speaker out of output list.
         if ((strategy == STRATEGY_MEDIA) &&
             (getForceUse(AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO) ==
                 AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED)) {
-            device &= ~AUDIO_DEVICE_OUT_SPEAKER;
+            devices.remove(devices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER));
         }
 
         // for STRATEGY_SONIFICATION:
         // if SPEAKER was selected, and SPEAKER_SAFE is available, use SPEAKER_SAFE instead
-        if ((strategy == STRATEGY_SONIFICATION) &&
-                (device & AUDIO_DEVICE_OUT_SPEAKER) &&
-                (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
-            device |= AUDIO_DEVICE_OUT_SPEAKER_SAFE;
-            device &= ~AUDIO_DEVICE_OUT_SPEAKER;
+        if (strategy == STRATEGY_SONIFICATION) {
+            devices.replaceDevicesByType(
+                    AUDIO_DEVICE_OUT_SPEAKER,
+                    availableOutputDevices.getDevicesFromTypeMask(
+                            AUDIO_DEVICE_OUT_SPEAKER_SAFE));
         }
         } break;
 
     default:
-        ALOGW("getDeviceForStrategy() unknown strategy: %d", strategy);
+        ALOGW("getDevicesForStrategy() unknown strategy: %d", strategy);
         break;
     }
 
-    if (device == AUDIO_DEVICE_NONE) {
-        ALOGV("getDeviceForStrategy() no device found for strategy %d", strategy);
-        device = getApmObserver()->getDefaultOutputDevice()->type();
-        ALOGE_IF(device == AUDIO_DEVICE_NONE,
-                 "getDeviceForStrategy() no default device defined");
+    if (devices.isEmpty()) {
+        ALOGV("getDevicesForStrategy() no device found for strategy %d", strategy);
+        sp<DeviceDescriptor> defaultOutputDevice = getApmObserver()->getDefaultOutputDevice();
+        if (defaultOutputDevice != nullptr) {
+            devices.add(defaultOutputDevice);
+        }
+        ALOGE_IF(devices.isEmpty(),
+                 "getDevicesForStrategy() no default device defined");
     }
-    ALOGVV("getDeviceForStrategy() strategy %d, device %x", strategy, device);
-    return device;
+
+    ALOGVV("getDevices"
+           "ForStrategy() strategy %d, device %x", strategy, devices.types());
+    return devices;
 }
 
 
-audio_devices_t Engine::getDeviceForInputSource(audio_source_t inputSource) const
+sp<DeviceDescriptor> Engine::getDeviceForInputSource(audio_source_t inputSource) const
 {
     const DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
     const DeviceVector availableInputDevices = getApmObserver()->getAvailableInputDevices();
     const SwAudioOutputCollection &outputs = getApmObserver()->getOutputs();
-    audio_devices_t availableDeviceTypes = availableInputDevices.types() & ~AUDIO_DEVICE_BIT_IN;
+    DeviceVector availableDevices = availableInputDevices;
     sp<AudioOutputDescriptor> primaryOutput = outputs.getPrimaryOutput();
-    audio_devices_t availablePrimaryDeviceTypes = availableInputDevices.getDeviceTypesFromHwModule(
-        primaryOutput->getModuleHandle()) & ~AUDIO_DEVICE_BIT_IN;
-    uint32_t device = AUDIO_DEVICE_NONE;
+    DeviceVector availablePrimaryDevices = availableInputDevices.getDevicesFromHwModule(
+            primaryOutput->getModuleHandle());
+    sp<DeviceDescriptor> device;
 
     // when a call is active, force device selection to match source VOICE_COMMUNICATION
     // for most other input sources to avoid rerouting call TX audio
@@ -532,57 +496,47 @@
     switch (inputSource) {
     case AUDIO_SOURCE_DEFAULT:
     case AUDIO_SOURCE_MIC:
-    if (availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_A2DP) {
-        device = AUDIO_DEVICE_IN_BLUETOOTH_A2DP;
-    } else if ((getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) == AUDIO_POLICY_FORCE_BT_SCO) &&
-        (availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET)) {
-        device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
-    } else if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) {
-        device = AUDIO_DEVICE_IN_WIRED_HEADSET;
-    } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_HEADSET) {
-        device = AUDIO_DEVICE_IN_USB_HEADSET;
-    } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
-        device = AUDIO_DEVICE_IN_USB_DEVICE;
-    } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
-        device = AUDIO_DEVICE_IN_BUILTIN_MIC;
-    }
-    break;
+        device = availableDevices.getDevice(
+                AUDIO_DEVICE_IN_BLUETOOTH_A2DP, String8(""), AUDIO_FORMAT_DEFAULT);
+        if (device != nullptr) break;
+        if (getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) == AUDIO_POLICY_FORCE_BT_SCO) {
+            device = availableDevices.getDevice(
+                    AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
+            if (device != nullptr) break;
+        }
+        device = availableDevices.getFirstExistingDevice({
+                AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_USB_HEADSET,
+                AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_BUILTIN_MIC});
+        break;
 
     case AUDIO_SOURCE_VOICE_COMMUNICATION:
         // Allow only use of devices on primary input if in call and HAL does not support routing
         // to voice call path.
         if ((getPhoneState() == AUDIO_MODE_IN_CALL) &&
-                (availableOutputDevices.types() & AUDIO_DEVICE_OUT_TELEPHONY_TX) == 0) {
-            availableDeviceTypes = availablePrimaryDeviceTypes;
+                (availableOutputDevices.getDevice(AUDIO_DEVICE_OUT_TELEPHONY_TX,
+                        String8(""), AUDIO_FORMAT_DEFAULT)) == nullptr) {
+            availableDevices = availablePrimaryDevices;
         }
 
         switch (getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION)) {
         case AUDIO_POLICY_FORCE_BT_SCO:
             // if SCO device is requested but no SCO device is available, fall back to default case
-            if (availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
-                device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
+            device = availableDevices.getDevice(
+                    AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
+            if (device != nullptr) {
                 break;
             }
             FALLTHROUGH_INTENDED;
 
         default:    // FORCE_NONE
-            if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) {
-                device = AUDIO_DEVICE_IN_WIRED_HEADSET;
-            } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_HEADSET) {
-                device = AUDIO_DEVICE_IN_USB_HEADSET;
-            } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
-                device = AUDIO_DEVICE_IN_USB_DEVICE;
-            } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
-                device = AUDIO_DEVICE_IN_BUILTIN_MIC;
-            }
+            device = availableDevices.getFirstExistingDevice({
+                    AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_USB_HEADSET,
+                    AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_BUILTIN_MIC});
             break;
 
         case AUDIO_POLICY_FORCE_SPEAKER:
-            if (availableDeviceTypes & AUDIO_DEVICE_IN_BACK_MIC) {
-                device = AUDIO_DEVICE_IN_BACK_MIC;
-            } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
-                device = AUDIO_DEVICE_IN_BUILTIN_MIC;
-            }
+            device = availableDevices.getFirstExistingDevice({
+                    AUDIO_DEVICE_IN_BACK_MIC, AUDIO_DEVICE_IN_BUILTIN_MIC});
             break;
         }
         break;
@@ -591,77 +545,60 @@
     case AUDIO_SOURCE_UNPROCESSED:
     case AUDIO_SOURCE_HOTWORD:
         if (inputSource == AUDIO_SOURCE_HOTWORD) {
-            availableDeviceTypes = availablePrimaryDeviceTypes;
+            availableDevices = availablePrimaryDevices;
         }
-        if (getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) == AUDIO_POLICY_FORCE_BT_SCO &&
-                availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
-            device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
-        } else if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) {
-            device = AUDIO_DEVICE_IN_WIRED_HEADSET;
-        } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_HEADSET) {
-            device = AUDIO_DEVICE_IN_USB_HEADSET;
-        } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
-            device = AUDIO_DEVICE_IN_USB_DEVICE;
-        } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
-            device = AUDIO_DEVICE_IN_BUILTIN_MIC;
+        if (getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) == AUDIO_POLICY_FORCE_BT_SCO) {
+            device = availableDevices.getDevice(
+                    AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
+            if (device != nullptr) break;
         }
+        device = availableDevices.getFirstExistingDevice({
+                AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_USB_HEADSET,
+                AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_BUILTIN_MIC});
         break;
     case AUDIO_SOURCE_CAMCORDER:
-        if (availableDeviceTypes & AUDIO_DEVICE_IN_BACK_MIC) {
-            device = AUDIO_DEVICE_IN_BACK_MIC;
-        } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
-            device = AUDIO_DEVICE_IN_BUILTIN_MIC;
-        } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
-            // This is specifically for a device without built-in mic
-            device = AUDIO_DEVICE_IN_USB_DEVICE;
-        }
+        // For a device without built-in mic, adding usb device
+        device = availableDevices.getFirstExistingDevice({
+                AUDIO_DEVICE_IN_BACK_MIC, AUDIO_DEVICE_IN_BUILTIN_MIC,
+                AUDIO_DEVICE_IN_USB_DEVICE});
         break;
     case AUDIO_SOURCE_VOICE_DOWNLINK:
     case AUDIO_SOURCE_VOICE_CALL:
     case AUDIO_SOURCE_VOICE_UPLINK:
-        if (availableDeviceTypes & AUDIO_DEVICE_IN_VOICE_CALL) {
-            device = AUDIO_DEVICE_IN_VOICE_CALL;
-        }
+        device = availableDevices.getDevice(
+                AUDIO_DEVICE_IN_VOICE_CALL, String8(""), AUDIO_FORMAT_DEFAULT);
         break;
     case AUDIO_SOURCE_VOICE_PERFORMANCE:
-        if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) {
-            device = AUDIO_DEVICE_IN_WIRED_HEADSET;
-        } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_HEADSET) {
-            device = AUDIO_DEVICE_IN_USB_HEADSET;
-        } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
-            device = AUDIO_DEVICE_IN_USB_DEVICE;
-        } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
-            device = AUDIO_DEVICE_IN_BUILTIN_MIC;
-        }
+        device = availableDevices.getFirstExistingDevice({
+                AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_USB_HEADSET,
+                AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_BUILTIN_MIC});
         break;
     case AUDIO_SOURCE_REMOTE_SUBMIX:
-        if (availableDeviceTypes & AUDIO_DEVICE_IN_REMOTE_SUBMIX) {
-            device = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
-        }
+        device = availableDevices.getDevice(
+                AUDIO_DEVICE_IN_REMOTE_SUBMIX, String8(""), AUDIO_FORMAT_DEFAULT);
         break;
     case AUDIO_SOURCE_FM_TUNER:
-        if (availableDeviceTypes & AUDIO_DEVICE_IN_FM_TUNER) {
-            device = AUDIO_DEVICE_IN_FM_TUNER;
-        }
+        device = availableDevices.getDevice(
+                AUDIO_DEVICE_IN_FM_TUNER, String8(""), AUDIO_FORMAT_DEFAULT);
         break;
     case AUDIO_SOURCE_ECHO_REFERENCE:
-        if (availableDeviceTypes & AUDIO_DEVICE_IN_ECHO_REFERENCE) {
-            device = AUDIO_DEVICE_IN_ECHO_REFERENCE;
-        }
+        device = availableDevices.getDevice(
+                AUDIO_DEVICE_IN_ECHO_REFERENCE, String8(""), AUDIO_FORMAT_DEFAULT);
         break;
     default:
         ALOGW("getDeviceForInputSource() invalid input source %d", inputSource);
         break;
     }
-    if (device == AUDIO_DEVICE_NONE) {
+    if (device == nullptr) {
         ALOGV("getDeviceForInputSource() no device found for source %d", inputSource);
-        if (availableDeviceTypes & AUDIO_DEVICE_IN_STUB) {
-            device = AUDIO_DEVICE_IN_STUB;
-        }
-        ALOGE_IF(device == AUDIO_DEVICE_NONE,
+        device = availableDevices.getDevice(
+                AUDIO_DEVICE_IN_STUB, String8(""), AUDIO_FORMAT_DEFAULT);
+        ALOGE_IF(device == nullptr,
                  "getDeviceForInputSource() no default device defined");
     }
-    ALOGV("getDeviceForInputSource()input source %d, device %08x", inputSource, device);
+    ALOGV_IF(device != nullptr,
+             "getDeviceForInputSource()input source %d, device %08x",
+             inputSource, device->type());
     return device;
 }
 
@@ -684,11 +621,9 @@
 
     auto legacyStrategy = mLegacyStrategyMap.find(strategy) != end(mLegacyStrategyMap) ?
                 mLegacyStrategyMap.at(strategy) : STRATEGY_NONE;
-    audio_devices_t devices = getDeviceForStrategyInt(legacyStrategy,
-                                                      availableOutputDevices,
-                                                      availableInputDevices, outputs,
-                                                      (uint32_t)AUDIO_DEVICE_NONE);
-    return availableOutputDevices.getDevicesFromTypeMask(devices);
+    return getDevicesForStrategyInt(legacyStrategy,
+                                    availableOutputDevices,
+                                    availableInputDevices, outputs);
 }
 
 DeviceVector Engine::getOutputDevicesForAttributes(const audio_attributes_t &attributes,
@@ -747,17 +682,21 @@
     if (device != nullptr) {
         return device;
     }
-    audio_devices_t deviceType = getDeviceForInputSource(attr.source);
 
-    if (audio_is_remote_submix_device(deviceType)) {
-        address = "0";
-        std::size_t pos;
-        std::string tags { attr.tags };
-        if ((pos = tags.find("addr=")) != std::string::npos) {
-            address = tags.substr(pos + std::strlen("addr="));
-        }
+    device = getDeviceForInputSource(attr.source);
+    if (device == nullptr || !audio_is_remote_submix_device(device->type())) {
+        // Return immediately if the device is null or it is not a remote submix device.
+        return device;
     }
-    return availableInputDevices.getDevice(deviceType,
+
+    // For remote submix device, try to find the device by address.
+    address = "0";
+    std::size_t pos;
+    std::string tags { attr.tags };
+    if ((pos = tags.find("addr=")) != std::string::npos) {
+        address = tags.substr(pos + std::strlen("addr="));
+    }
+    return availableInputDevices.getDevice(device->type(),
                                            String8(address.c_str()),
                                            AUDIO_FORMAT_DEFAULT);
 }
diff --git a/services/audiopolicy/enginedefault/src/Engine.h b/services/audiopolicy/enginedefault/src/Engine.h
index dd1b680..4360c6f 100644
--- a/services/audiopolicy/enginedefault/src/Engine.h
+++ b/services/audiopolicy/enginedefault/src/Engine.h
@@ -73,15 +73,14 @@
 
     status_t setDefaultDevice(audio_devices_t device);
 
-    audio_devices_t getDeviceForStrategyInt(legacy_strategy strategy,
-                                            DeviceVector availableOutputDevices,
-                                            DeviceVector availableInputDevices,
-                                            const SwAudioOutputCollection &outputs,
-                                            uint32_t outputDeviceTypesToIgnore) const;
+    DeviceVector getDevicesForStrategyInt(legacy_strategy strategy,
+                                          DeviceVector availableOutputDevices,
+                                          DeviceVector availableInputDevices,
+                                          const SwAudioOutputCollection &outputs) const;
 
     DeviceVector getDevicesForProductStrategy(product_strategy_t strategy) const;
 
-    audio_devices_t getDeviceForInputSource(audio_source_t inputSource) const;
+    sp<DeviceDescriptor> getDeviceForInputSource(audio_source_t inputSource) const;
 
     DeviceStrategyMap mDevicesForStrategies;
 
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 630091e..28eb263 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1206,9 +1206,9 @@
             if (!desc->isDuplicated() && (profile == desc->mProfile)) {
                 // reuse direct output if currently open by the same client
                 // and configured with same parameters
-                if ((config->sample_rate == desc->mSamplingRate) &&
-                    (config->format == desc->mFormat) &&
-                    (channelMask == desc->mChannelMask) &&
+                if ((config->sample_rate == desc->getSamplingRate()) &&
+                    (config->format == desc->getFormat()) &&
+                    (channelMask == desc->getChannelMask()) &&
                     (session == desc->mDirectClientSession)) {
                     desc->mDirectOpenCount++;
                     ALOGI("%s reusing direct output %d for session %d", __func__, 
@@ -1248,13 +1248,13 @@
 
         // only accept an output with the requested parameters
         if (status != NO_ERROR ||
-            (config->sample_rate != 0 && config->sample_rate != outputDesc->mSamplingRate) ||
-            (config->format != AUDIO_FORMAT_DEFAULT && config->format != outputDesc->mFormat) ||
-            (channelMask != 0 && channelMask != outputDesc->mChannelMask)) {
+            (config->sample_rate != 0 && config->sample_rate != outputDesc->getSamplingRate()) ||
+            (config->format != AUDIO_FORMAT_DEFAULT && config->format != outputDesc->getFormat()) ||
+            (channelMask != 0 && channelMask != outputDesc->getChannelMask())) {
             ALOGV("%s failed opening direct output: output %d sample rate %d %d," 
                     "format %d %d, channel mask %04x %04x", __func__, output, config->sample_rate,
-                    outputDesc->mSamplingRate, config->format, outputDesc->mFormat,
-                    channelMask, outputDesc->mChannelMask);
+                    outputDesc->getSamplingRate(), config->format, outputDesc->getFormat(),
+                    channelMask, outputDesc->getChannelMask());
             if (output != AUDIO_IO_HANDLE_NONE) {
                 outputDesc->close();
             }
@@ -1525,13 +1525,13 @@
         // If haptic channel is specified, use the haptic output if present.
         // When using haptic output, same audio format and sample rate are required.
         const uint32_t outputHapticChannelCount = audio_channel_count_from_out_mask(
-            outputDesc->mChannelMask & AUDIO_CHANNEL_HAPTIC_ALL);
+            outputDesc->getChannelMask() & AUDIO_CHANNEL_HAPTIC_ALL);
         if ((hapticChannelCount == 0) != (outputHapticChannelCount == 0)) {
             continue;
         }
         if (outputHapticChannelCount >= hapticChannelCount
-            && format == outputDesc->mFormat
-            && samplingRate == outputDesc->mSamplingRate) {
+            && format == outputDesc->getFormat()
+            && samplingRate == outputDesc->getSamplingRate()) {
                 currentMatchCriteria[0] = outputHapticChannelCount;
         }
 
@@ -1539,12 +1539,13 @@
         currentMatchCriteria[1] = popcount(outputDesc->mFlags & functionalFlags);
 
         // channel mask and channel count match
-        uint32_t outputChannelCount = audio_channel_count_from_out_mask(outputDesc->mChannelMask);
+        uint32_t outputChannelCount = audio_channel_count_from_out_mask(
+                outputDesc->getChannelMask());
         if (channelMask != AUDIO_CHANNEL_NONE && channelCount > 2 &&
             channelCount <= outputChannelCount) {
             if ((audio_channel_mask_get_representation(channelMask) ==
-                    audio_channel_mask_get_representation(outputDesc->mChannelMask)) &&
-                    ((channelMask & outputDesc->mChannelMask) == channelMask)) {
+                    audio_channel_mask_get_representation(outputDesc->getChannelMask())) &&
+                    ((channelMask & outputDesc->getChannelMask()) == channelMask)) {
                 currentMatchCriteria[2] = outputChannelCount;
             }
             currentMatchCriteria[3] = outputChannelCount;
@@ -1552,8 +1553,8 @@
 
         // sampling rate match
         if (samplingRate > SAMPLE_RATE_HZ_DEFAULT &&
-                samplingRate <= outputDesc->mSamplingRate) {
-            currentMatchCriteria[4] = outputDesc->mSamplingRate;
+                samplingRate <= outputDesc->getSamplingRate()) {
+            currentMatchCriteria[4] = outputDesc->getSamplingRate();
         }
 
         // performance flags match
@@ -1563,7 +1564,7 @@
         if (format != AUDIO_FORMAT_INVALID) {
             currentMatchCriteria[6] =
                 AudioPort::kFormatDistanceMax -
-                AudioPort::formatDistance(format, outputDesc->mFormat);
+                AudioPort::formatDistance(format, outputDesc->getFormat());
         }
 
         // primary output match
@@ -2922,9 +2923,9 @@
             // stereo and let audio flinger do the channel conversion if needed.
             outputConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
             inputConfig.channel_mask = AUDIO_CHANNEL_IN_STEREO;
-            rSubmixModule->addOutputProfile(address, &outputConfig,
+            rSubmixModule->addOutputProfile(address.c_str(), &outputConfig,
                     AUDIO_DEVICE_OUT_REMOTE_SUBMIX, address);
-            rSubmixModule->addInputProfile(address, &inputConfig,
+            rSubmixModule->addInputProfile(address.c_str(), &inputConfig,
                     AUDIO_DEVICE_IN_REMOTE_SUBMIX, address);
 
             if ((res = setDeviceConnectionStateInt(deviceTypeToMakeAvailable,
@@ -3020,8 +3021,8 @@
                     }
                 }
             }
-            rSubmixModule->removeOutputProfile(address);
-            rSubmixModule->removeInputProfile(address);
+            rSubmixModule->removeOutputProfile(address.c_str());
+            rSubmixModule->removeInputProfile(address.c_str());
 
         } else if ((mix.mRouteFlags & MIX_ROUTE_FLAG_RENDER) == MIX_ROUTE_FLAG_RENDER) {
             if (mPolicyMixes.unregisterMix(mix) != NO_ERROR) {
@@ -3233,7 +3234,7 @@
     ALOGV("%s() profile %sfound with name: %s, "
         "sample rate: %u, format: 0x%x, channel_mask: 0x%x, output flags: 0x%x",
         __FUNCTION__, profile != 0 ? "" : "NOT ",
-        (profile != 0 ? profile->getTagName().string() : "null"),
+        (profile != 0 ? profile->getTagName().c_str() : "null"),
         config.sample_rate, config.format, config.channel_mask, output_flags);
     return (profile != 0);
 }
@@ -3897,7 +3898,7 @@
     if (srcDevice->hasSameHwModuleAs(sinkDevice) &&
             srcDevice->getModuleVersionMajor() >= 3 &&
             sinkDevice->getModule()->supportsPatch(srcDevice, sinkDevice) &&
-            srcDevice->getAudioPort()->mGains.size() > 0) {
+            srcDevice->getAudioPort()->getGains().size() > 0) {
         ALOGV("%s Device to Device route supported by >=3.0 HAL", __FUNCTION__);
         // TODO: may explicitly specify whether we should use HW or SW patch
         //   create patch between src device and output device
@@ -4137,7 +4138,7 @@
     for (size_t i = 0; i < hdmiOutputDevices.size(); i++) {
         // Simulate reconnection to update enabled surround sound formats.
         String8 address = hdmiOutputDevices[i]->address();
-        String8 name = hdmiOutputDevices[i]->getName();
+        std::string name = hdmiOutputDevices[i]->getName();
         status_t status = setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_HDMI,
                                                       AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
                                                       address.c_str(),
@@ -4159,7 +4160,7 @@
     for (size_t i = 0; i < hdmiInputDevices.size(); i++) {
         // Simulate reconnection to update enabled surround sound formats.
         String8 address = hdmiInputDevices[i]->address();
-        String8 name = hdmiInputDevices[i]->getName();
+        std::string name = hdmiInputDevices[i]->getName();
         status_t status = setDeviceConnectionStateInt(AUDIO_DEVICE_IN_HDMI,
                                                       AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
                                                       address.c_str(),
@@ -4642,7 +4643,7 @@
             }
 
             ALOGV("opening output for device %08x with params %s profile %p name %s",
-                  deviceType, address.string(), profile.get(), profile->getName().string());
+                  deviceType, address.string(), profile.get(), profile->getName().c_str());
             desc = new SwAudioOutputDescriptor(profile, mpClientInterface);
             audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
             status_t status = desc->open(nullptr, DeviceVector(device),
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 02c6171..4270aa8 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -38,7 +38,7 @@
 #include <AudioPolicyConfig.h>
 #include <AudioPort.h>
 #include <AudioPatch.h>
-#include <AudioProfile.h>
+#include <AudioProfileVector.h>
 #include <DeviceDescriptor.h>
 #include <IOProfile.h>
 #include <HwModule.h>
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index 8c30466..48d707a 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -396,12 +396,11 @@
     mMsdOutputDevice->attach(msdModule);
     mMsdInputDevice->attach(msdModule);
 
-    sp<OutputProfile> msdOutputProfile = new OutputProfile(String8("msd input"));
+    sp<OutputProfile> msdOutputProfile = new OutputProfile("msd input");
     msdOutputProfile->addAudioProfile(pcmOutputProfile);
     msdOutputProfile->addSupportedDevice(mMsdOutputDevice);
     msdModule->addOutputProfile(msdOutputProfile);
-    sp<OutputProfile> msdCompressedOutputProfile =
-            new OutputProfile(String8("msd compressed input"));
+    sp<OutputProfile> msdCompressedOutputProfile = new OutputProfile("msd compressed input");
     msdCompressedOutputProfile->addAudioProfile(ac3OutputProfile);
     msdCompressedOutputProfile->setFlags(
             AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD |
@@ -409,7 +408,7 @@
     msdCompressedOutputProfile->addSupportedDevice(mMsdOutputDevice);
     msdModule->addOutputProfile(msdCompressedOutputProfile);
 
-    sp<InputProfile> msdInputProfile = new InputProfile(String8("msd output"));
+    sp<InputProfile> msdInputProfile = new InputProfile("msd output");
     msdInputProfile->addAudioProfile(pcmInputProfile);
     msdInputProfile->addSupportedDevice(mMsdInputDevice);
     msdModule->addInputProfile(msdInputProfile);
@@ -419,7 +418,7 @@
     sp<AudioProfile> dtsOutputProfile = new AudioProfile(
             AUDIO_FORMAT_DTS, AUDIO_CHANNEL_OUT_5POINT1, 48000);
     config->getDefaultOutputDevice()->addAudioProfile(dtsOutputProfile);
-    sp<OutputProfile> primaryEncodedOutputProfile = new OutputProfile(String8("encoded"));
+    sp<OutputProfile> primaryEncodedOutputProfile = new OutputProfile("encoded");
     primaryEncodedOutputProfile->addAudioProfile(dtsOutputProfile);
     primaryEncodedOutputProfile->setFlags(AUDIO_OUTPUT_FLAG_DIRECT);
     primaryEncodedOutputProfile->addSupportedDevice(config->getDefaultOutputDevice());