Merge "BluetoothAudio HAL: flip to be enabled by default"
diff --git a/media/libaudioclient/AudioAttributes.cpp b/media/libaudioclient/AudioAttributes.cpp
index 0f327cf..1ee6930 100644
--- a/media/libaudioclient/AudioAttributes.cpp
+++ b/media/libaudioclient/AudioAttributes.cpp
@@ -43,7 +43,7 @@
         strcpy(mAttributes.tags, "");
     }
     mStreamType = static_cast<audio_stream_type_t>(parcel->readInt32());
-    mGroupId = parcel->readUint32();
+    mGroupId = static_cast<volume_group_t>(parcel->readUint32());
     return NO_ERROR;
 }
 
@@ -60,7 +60,7 @@
         parcel->writeUtf8AsUtf16(mAttributes.tags);
     }
     parcel->writeInt32(static_cast<int32_t>(mStreamType));
-    parcel->writeUint32(mGroupId);
+    parcel->writeUint32(static_cast<uint32_t>(mGroupId));
     return NO_ERROR;
 }
 
diff --git a/media/libaudioclient/include/media/AudioAttributes.h b/media/libaudioclient/include/media/AudioAttributes.h
index edf26eb..0a35e9e 100644
--- a/media/libaudioclient/include/media/AudioAttributes.h
+++ b/media/libaudioclient/include/media/AudioAttributes.h
@@ -17,6 +17,7 @@
 
 #pragma once
 
+#include <media/AudioCommonTypes.h>
 #include <system/audio.h>
 #include <system/audio_policy.h>
 #include <binder/Parcelable.h>
@@ -28,7 +29,7 @@
 public:
     AudioAttributes() = default;
     AudioAttributes(const audio_attributes_t &attributes) : mAttributes(attributes) {}
-    AudioAttributes(uint32_t groupId,
+    AudioAttributes(volume_group_t groupId,
                     audio_stream_type_t stream,
                     const audio_attributes_t &attributes) :
          mAttributes(attributes), mStreamType(stream), mGroupId(groupId) {}
@@ -39,7 +40,7 @@
     status_t writeToParcel(Parcel *parcel) const override;
 
     audio_stream_type_t getStreamType() const { return mStreamType; }
-    uint32_t getGroupId() const { return mGroupId; }
+    volume_group_t getGroupId() const { return mGroupId; }
 
 private:
     audio_attributes_t mAttributes = AUDIO_ATTRIBUTES_INITIALIZER;
@@ -53,7 +54,7 @@
      * @brief mGroupId: for future volume management, define groups within a strategy that follows
      * the same curves of volume (extension of stream types to manage volume)
      */
-    uint32_t mGroupId = 0;
+    volume_group_t mGroupId = VOLUME_GROUP_NONE;
 };
 
 } // namespace android
diff --git a/media/libaudioclient/include/media/AudioCommonTypes.h b/media/libaudioclient/include/media/AudioCommonTypes.h
index 5188da1..8e446ea 100644
--- a/media/libaudioclient/include/media/AudioCommonTypes.h
+++ b/media/libaudioclient/include/media/AudioCommonTypes.h
@@ -27,7 +27,7 @@
 const product_strategy_t PRODUCT_STRATEGY_NONE = static_cast<product_strategy_t>(-1);
 
 using AttributesVector = std::vector<audio_attributes_t>;
-using StreamTypes = std::vector<audio_stream_type_t>;
+using StreamTypeVector = std::vector<audio_stream_type_t>;
 
 constexpr bool operator==(const audio_attributes_t &lhs, const audio_attributes_t &rhs)
 {
@@ -38,5 +38,9 @@
 {
     return !(lhs==rhs);
 }
+
+enum volume_group_t : uint32_t;
+static const volume_group_t VOLUME_GROUP_NONE = static_cast<volume_group_t>(-1);
+
 } // namespace android
 
diff --git a/media/ndk/Android.bp b/media/ndk/Android.bp
index a9254c7..0b274a7 100644
--- a/media/ndk/Android.bp
+++ b/media/ndk/Android.bp
@@ -76,7 +76,7 @@
         "libbinder",
         "libmedia",
         "libmedia_omx",
-        "libmedia_jni",
+        "libmedia_jni_utils",
         "libmediadrm",
         "libstagefright",
         "libstagefright_foundation",
diff --git a/media/ndk/NdkImage.cpp b/media/ndk/NdkImage.cpp
index 20b1667..1883f63 100644
--- a/media/ndk/NdkImage.cpp
+++ b/media/ndk/NdkImage.cpp
@@ -23,7 +23,7 @@
 #include "NdkImageReaderPriv.h"
 
 #include <android_media_Utils.h>
-#include <android_runtime/android_hardware_HardwareBuffer.h>
+#include <private/android/AHardwareBufferHelpers.h>
 #include <utils/Log.h>
 #include "hardware/camera3.h"
 
@@ -190,7 +190,7 @@
 
     auto lockedBuffer = std::make_unique<CpuConsumer::LockedBuffer>();
 
-    uint64_t grallocUsage = android_hardware_HardwareBuffer_convertToGrallocUsageBits(mUsage);
+    uint64_t grallocUsage = AHardwareBuffer_convertToGrallocUsageBits(mUsage);
 
     status_t ret =
             lockImageFromBuffer(mBuffer, grallocUsage, mBuffer->mFence->dup(), lockedBuffer.get());
diff --git a/media/ndk/NdkImageReader.cpp b/media/ndk/NdkImageReader.cpp
index c3eb437..b929f7f 100644
--- a/media/ndk/NdkImageReader.cpp
+++ b/media/ndk/NdkImageReader.cpp
@@ -26,7 +26,7 @@
 #include <utils/Log.h>
 #include <android_media_Utils.h>
 #include <android_runtime/android_view_Surface.h>
-#include <android_runtime/android_hardware_HardwareBuffer.h>
+#include <private/android/AHardwareBufferHelpers.h>
 #include <grallocusage/GrallocUsageConversion.h>
 #include <media/stagefright/bqhelper/WGraphicBufferProducer.h>
 
@@ -272,7 +272,7 @@
     PublicFormat publicFormat = static_cast<PublicFormat>(mFormat);
     mHalFormat = android_view_Surface_mapPublicFormatToHalFormat(publicFormat);
     mHalDataSpace = android_view_Surface_mapPublicFormatToHalDataspace(publicFormat);
-    mHalUsage = android_hardware_HardwareBuffer_convertToGrallocUsageBits(mUsage);
+    mHalUsage = AHardwareBuffer_convertToGrallocUsageBits(mUsage);
 
     sp<IGraphicBufferProducer> gbProducer;
     sp<IGraphicBufferConsumer> gbConsumer;
diff --git a/services/audiopolicy/common/include/Volume.h b/services/audiopolicy/common/include/Volume.h
index a3b6b36..48b5271 100644
--- a/services/audiopolicy/common/include/Volume.h
+++ b/services/audiopolicy/common/include/Volume.h
@@ -21,6 +21,7 @@
 #include <math.h>
 
 namespace android {
+
 /**
  * VolumeSource is the discriminent for volume management on an output.
  * It used to be the stream type by legacy, it may be host volume group or a volume curves if
diff --git a/services/audiopolicy/common/managerdefinitions/include/IVolumeCurves.h b/services/audiopolicy/common/managerdefinitions/include/IVolumeCurves.h
index 93022fb..d408446 100644
--- a/services/audiopolicy/common/managerdefinitions/include/IVolumeCurves.h
+++ b/services/audiopolicy/common/managerdefinitions/include/IVolumeCurves.h
@@ -38,6 +38,8 @@
     virtual float volIndexToDb(device_category device, int indexInUi) const = 0;
     virtual bool hasVolumeIndexForDevice(audio_devices_t device) const = 0;
     virtual status_t initVolume(int indexMin, int indexMax) = 0;
+    virtual std::vector<audio_attributes_t> getAttributes() const = 0;
+    virtual std::vector<audio_stream_type_t> getStreamTypes() const = 0;
     virtual void dump(String8 *dst, int spaces = 0, bool curvePoints = false) const = 0;
 };
 
diff --git a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
index e0b233d..ec7ff57 100644
--- a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
@@ -341,7 +341,7 @@
         }
     }
     if (!allowToCreate) {
-        ALOGE("%s: could not find HW module for device %s %04x address %s", __FUNCTION__,
+        ALOGV("%s: could not find HW module for device %s %04x address %s", __FUNCTION__,
               name, deviceType, address);
         return nullptr;
     }
diff --git a/services/audiopolicy/engine/common/include/EngineBase.h b/services/audiopolicy/engine/common/include/EngineBase.h
index bc027e2..35d86ee 100644
--- a/services/audiopolicy/engine/common/include/EngineBase.h
+++ b/services/audiopolicy/engine/common/include/EngineBase.h
@@ -19,7 +19,7 @@
 #include <EngineConfig.h>
 #include <AudioPolicyManagerInterface.h>
 #include <ProductStrategy.h>
-#include <StreamVolumeCurves.h>
+#include <VolumeGroup.h>
 
 namespace android {
 namespace audio_policy {
@@ -68,9 +68,25 @@
 
     status_t listAudioProductStrategies(AudioProductStrategyVector &strategies) const override;
 
-    VolumeCurves *getVolumeCurvesForAttributes(const audio_attributes_t &attr) override;
+    VolumeCurves *getVolumeCurvesForAttributes(const audio_attributes_t &attr) const override;
 
-    VolumeCurves *getVolumeCurvesForStreamType(audio_stream_type_t stream) override;
+    VolumeCurves *getVolumeCurvesForStreamType(audio_stream_type_t stream) const override;
+
+    IVolumeCurves *getVolumeCurvesForVolumeGroup(volume_group_t group) const override
+    {
+       return mVolumeGroups.find(group) != end(mVolumeGroups) ?
+                   mVolumeGroups.at(group)->getVolumeCurves() : nullptr;
+    }
+
+    VolumeGroupVector getVolumeGroups() const override;
+
+    volume_group_t getVolumeGroupForAttributes(const audio_attributes_t &attr) const override;
+
+    volume_group_t getVolumeGroupForStreamType(audio_stream_type_t stream) const override;
+
+    StreamTypeVector getStreamTypesForVolumeGroup(volume_group_t volumeGroup) const override;
+
+    AttributesVector getAllAttributesForVolumeGroup(volume_group_t volumeGroup) const override;
 
     void dump(String8 *dst) const override;
 
@@ -105,12 +121,11 @@
     AudioPolicyManagerObserver *mApmObserver = nullptr;
 
     ProductStrategyMap mProductStrategies;
+    VolumeGroupMap mVolumeGroups;
     audio_mode_t mPhoneState = AUDIO_MODE_NORMAL;  /**< current phone state. */
 
     /** current forced use configuration. */
     audio_policy_forced_cfg_t mForceUse[AUDIO_POLICY_FORCE_USE_CNT] = {};
-
-    StreamVolumeCurves mStreamVolumeCurves;
 };
 
 } // namespace audio_policy
diff --git a/services/audiopolicy/engine/common/include/ProductStrategy.h b/services/audiopolicy/engine/common/include/ProductStrategy.h
index 72505b2..767a8ed 100644
--- a/services/audiopolicy/engine/common/include/ProductStrategy.h
+++ b/services/audiopolicy/engine/common/include/ProductStrategy.h
@@ -16,6 +16,8 @@
 
 #pragma once
 
+#include "VolumeGroup.h"
+
 #include <system/audio.h>
 #include <AudioPolicyManagerInterface.h>
 #include <utils/RefBase.h>
@@ -38,7 +40,7 @@
 private:
     struct AudioAttributes {
         audio_stream_type_t mStream = AUDIO_STREAM_DEFAULT;
-        uint32_t mGroupId = 0;
+        volume_group_t mVolumeGroup = VOLUME_GROUP_NONE;
         audio_attributes_t mAttributes = AUDIO_ATTRIBUTES_INITIALIZER;
     };
 
@@ -85,6 +87,12 @@
     audio_attributes_t getAttributesForStreamType(audio_stream_type_t stream) const;
     audio_stream_type_t getStreamTypeForAttributes(const audio_attributes_t &attr) const;
 
+    volume_group_t getVolumeGroupForAttributes(const audio_attributes_t &attr) const;
+
+    volume_group_t getVolumeGroupForStreamType(audio_stream_type_t stream) const;
+
+    volume_group_t getDefaultVolumeGroup() const;
+
     bool isDefault() const;
 
     void dump(String8 *dst, int spaces = 0) const;
@@ -108,6 +116,10 @@
 {
 public:
     /**
+     * @brief initialize: set default product strategy in cache.
+     */
+    void initialize();
+    /**
      * @brief getProductStrategyForAttribute. The order of the vector is dimensionning.
      * @param attr
      * @return applicable product strategy for the given attribute, default if none applicable.
@@ -136,9 +148,16 @@
 
     std::string getDeviceAddressForProductStrategy(product_strategy_t strategy) const;
 
+    volume_group_t getVolumeGroupForAttributes(const audio_attributes_t &attr) const;
+
+    volume_group_t getVolumeGroupForStreamType(audio_stream_type_t stream) const;
+
     product_strategy_t getDefault() const;
 
     void dump(String8 *dst, int spaces = 0) const;
+
+private:
+    product_strategy_t mDefaultStrategy = PRODUCT_STRATEGY_NONE;
 };
 
 } // namespace android
diff --git a/services/audiopolicy/engine/common/include/StreamVolumeCurves.h b/services/audiopolicy/engine/common/include/StreamVolumeCurves.h
deleted file mode 100644
index 5b0b7d6..0000000
--- a/services/audiopolicy/engine/common/include/StreamVolumeCurves.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2018 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 <VolumeCurve.h>
-#include <map>
-
-namespace android {
-
-class StreamVolumeCurves
-{
-public:
-    StreamVolumeCurves() = default;
-
-    /**
-     * @brief switchVolumeCurve control API for Engine, allows to switch the volume curves
-     * from one stream type to another.
-     * @param src source stream type
-     * @param dst destination stream type
-     */
-    status_t switchVolumeCurve(audio_stream_type_t streamSrc, audio_stream_type_t streamDst)
-    {
-        if (!hasCurvesFor(streamSrc) || !hasCurvesFor(streamDst)) {
-            ALOGE("%s: No curves defined for streams %d %d", __FUNCTION__, streamSrc, streamDst);
-            return NO_INIT;
-        }
-        const VolumeCurves &sourceCurves = getCurvesFor(streamSrc);
-        VolumeCurves &dstCurves = editCurvesFor(streamDst);
-        return dstCurves.switchCurvesFrom(sourceCurves);
-    }
-    void dump(String8 *dst, int spaces = 0) const;
-
-    void add(const VolumeCurves &curves, audio_stream_type_t streamType)
-    {
-        mCurves.emplace(streamType, curves);
-    }
-
-    bool hasCurvesFor(audio_stream_type_t stream)
-    {
-        return mCurves.find(stream) != end(mCurves);
-    }
-
-    VolumeCurves &editCurvesFor(audio_stream_type_t stream)
-    {
-        ALOG_ASSERT(mCurves.find(stream) != end(mCurves), "Invalid stream type for Volume Curve");
-        return mCurves[stream];
-    }
-    const VolumeCurves &getCurvesFor(audio_stream_type_t stream) const
-    {
-        ALOG_ASSERT(mCurves.find(stream) != end(mCurves), "Invalid stream type for Volume Curve");
-        return mCurves.at(stream);
-    }
-    /**
-     * @brief getVolumeCurvesForStream
-     * @param stream type for which the volume curves interface is requested
-     * @return the VolumeCurves for a given stream type.
-     */
-    VolumeCurves &getVolumeCurvesForStream(audio_stream_type_t stream)
-    {
-        ALOG_ASSERT(mCurves.find(stream) != end(mCurves), "Invalid stream type for Volume Curve");
-        return mCurves[stream];
-    }
-    /**
-     * @brief restoreOriginVolumeCurve helper control API for engine to restore the original volume
-     * curves for a given stream type
-     * @param stream for which the volume curves will be restored.
-     */
-    status_t restoreOriginVolumeCurve(audio_stream_type_t stream)
-    {
-        if (!hasCurvesFor(stream)) {
-            ALOGE("%s: No curves defined for streams", __FUNCTION__);
-            return NO_INIT;
-        }
-        return switchVolumeCurve(stream, stream);
-    }
-
-private:
-    std::map<audio_stream_type_t, VolumeCurves> mCurves;
-};
-
-} // namespace android
diff --git a/services/audiopolicy/engine/common/include/VolumeCurve.h b/services/audiopolicy/engine/common/include/VolumeCurve.h
index 0ec63e1..54314e3 100644
--- a/services/audiopolicy/engine/common/include/VolumeCurve.h
+++ b/services/audiopolicy/engine/common/include/VolumeCurve.h
@@ -18,7 +18,9 @@
 
 #include "IVolumeCurves.h"
 #include <policy.h>
+#include <AudioPolicyManagerInterface.h>
 #include <utils/RefBase.h>
+#include <HandleGenerator.h>
 #include <utils/String8.h>
 #include <utils/SortedVector.h>
 #include <utils/KeyedVector.h>
@@ -71,18 +73,11 @@
 {
 public:
     VolumeCurves(int indexMin = 0, int indexMax = 100) :
-        mIndexMin(indexMin), mIndexMax(indexMax), mStream(AUDIO_STREAM_DEFAULT)
+        mIndexMin(indexMin), mIndexMax(indexMax)
     {
         addCurrentVolumeIndex(AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME, 0);
     }
-    VolumeCurves(audio_stream_type_t stream, int indexMin, int indexMax) :
-        mIndexMin(indexMin), mIndexMax(indexMax), mStream(stream)
-    {
-        addCurrentVolumeIndex(AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME, 0);
-    }
-
-    // Once XML has been parsed, must be call first to sanity check table and initialize indexes
-    virtual status_t initVolume(int indexMin, int indexMax)
+    status_t initVolume(int indexMin, int indexMax) override
     {
         mIndexMin = indexMin;
         mIndexMax = indexMax;
@@ -174,8 +169,16 @@
             return 0.0f;
         }
     }
-
-    audio_stream_type_t getStreamType() const { return mStream; }
+    void addAttributes(const audio_attributes_t &attr)
+    {
+        mAttributes.push_back(attr);
+    }
+    AttributesVector getAttributes() const override { return mAttributes; }
+    void addStreamType(audio_stream_type_t stream)
+    {
+        mStreams.push_back(stream);
+    }
+    StreamTypeVector getStreamTypes() const override { return mStreams; }
 
     void dump(String8 *dst, int spaces = 0, bool curvePoints = false) const override;
 
@@ -186,7 +189,8 @@
     int mIndexMax; /**< max volume index. */
     const bool mCanBeMuted = true; /**< true is the stream can be muted. */
 
-    const audio_stream_type_t mStream; /**< Keep it for legacy. */
+    AttributesVector mAttributes;
+    StreamTypeVector mStreams; /**< Keep it for legacy. */
 };
 
 } // namespace android
diff --git a/services/audiopolicy/engine/common/include/VolumeGroup.h b/services/audiopolicy/engine/common/include/VolumeGroup.h
new file mode 100644
index 0000000..c34b406
--- /dev/null
+++ b/services/audiopolicy/engine/common/include/VolumeGroup.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2018 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 <AudioPolicyManagerInterface.h>
+#include <VolumeCurve.h>
+#include <system/audio.h>
+#include <utils/RefBase.h>
+#include <HandleGenerator.h>
+#include <string>
+#include <vector>
+#include <map>
+#include <utils/Errors.h>
+
+namespace android {
+
+class VolumeGroup : public virtual RefBase, private HandleGenerator<uint32_t>
+{
+public:
+    VolumeGroup(const std::string &name, int indexMin, int indexMax);
+    std::string getName() const { return mName; }
+    volume_group_t getId() const { return mId; }
+
+    void add(const sp<VolumeCurve> &curve);
+
+    VolumeCurves *getVolumeCurves() { return &mGroupVolumeCurves; }
+
+    void addSupportedAttributes(const audio_attributes_t &attr);
+    AttributesVector getSupportedAttributes() const { return mGroupVolumeCurves.getAttributes(); }
+
+    void addSupportedStream(audio_stream_type_t stream);
+    StreamTypeVector getStreamTypes() const { return mGroupVolumeCurves.getStreamTypes(); }
+
+    void dump(String8 *dst, int spaces = 0) const;
+
+private:
+    const std::string mName;
+    const volume_group_t mId;
+    VolumeCurves mGroupVolumeCurves;
+};
+
+class VolumeGroupMap : public std::map<volume_group_t, sp<VolumeGroup> >
+{
+public:
+    void dump(String8 *dst, int spaces = 0) const;
+};
+
+} // namespace android
diff --git a/services/audiopolicy/engine/common/src/EngineBase.cpp b/services/audiopolicy/engine/common/src/EngineBase.cpp
index 6e2ab4c..4d7c4a0 100644
--- a/services/audiopolicy/engine/common/src/EngineBase.cpp
+++ b/services/audiopolicy/engine/common/src/EngineBase.cpp
@@ -15,7 +15,7 @@
  */
 
 #define LOG_TAG "APM::AudioPolicyEngine/Base"
-#define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
 
 #include "EngineBase.h"
 #include "EngineDefaultConfig.h"
@@ -96,46 +96,47 @@
 engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig()
 {
     auto loadProductStrategies =
-            [](auto& strategyConfigs, auto& productStrategies) {
-        uint32_t groupid = 0;
+            [](auto& strategyConfigs, auto& productStrategies, auto& volumeGroups) {
         for (auto& strategyConfig : strategyConfigs) {
             sp<ProductStrategy> strategy = new ProductStrategy(strategyConfig.name);
             for (const auto &group : strategyConfig.attributesGroups) {
-                for (const auto &attr : group.attributesVect) {
-                    strategy->addAttributes({group.stream, groupid, attr});
+                const auto &iter = std::find_if(begin(volumeGroups), end(volumeGroups),
+                                         [&group](const auto &volumeGroup) {
+                        return group.volumeGroup == volumeGroup.second->getName(); });
+                ALOG_ASSERT(iter != end(volumeGroups), "Invalid Volume Group Name %s",
+                            group.volumeGroup.c_str());
+                if (group.stream != AUDIO_STREAM_DEFAULT) {
+                    iter->second->addSupportedStream(group.stream);
                 }
-                groupid += 1;
+                for (const auto &attr : group.attributesVect) {
+                    strategy->addAttributes({group.stream, iter->second->getId(), attr});
+                    iter->second->addSupportedAttributes(attr);
+                }
             }
             product_strategy_t strategyId = strategy->getId();
             productStrategies[strategyId] = strategy;
         }
     };
-    auto loadVolumeCurves = [](const auto &configVolumes, auto &streamVolumeCollection) {
-        for (auto &configVolume : configVolumes) {
-            audio_stream_type_t streamType = AUDIO_STREAM_DEFAULT;
-            if (configVolume.stream.empty() ||
-                    !StreamTypeConverter::fromString(configVolume.stream, streamType)) {
-                ALOGE("%s: Invalid stream type", __FUNCTION__);
-                continue;
-            }
-            VolumeCurves volumeCurves(streamType, configVolume.indexMin, configVolume.indexMax);
-            for (auto &configCurve : configVolume.volumeCurves) {
-                device_category deviceCategory = DEVICE_CATEGORY_SPEAKER;
-                if (!DeviceCategoryConverter::fromString(configCurve.deviceCategory,
-                                                         deviceCategory)) {
+    auto loadVolumeGroups = [](auto &volumeConfigs, auto &volumeGroups) {
+        for (auto &volumeConfig : volumeConfigs) {
+            sp<VolumeGroup> volumeGroup = new VolumeGroup(volumeConfig.name, volumeConfig.indexMin,
+                                                          volumeConfig.indexMax);
+            volumeGroups[volumeGroup->getId()] = volumeGroup;
+
+            for (auto &configCurve : volumeConfig.volumeCurves) {
+                device_category deviceCat = DEVICE_CATEGORY_SPEAKER;
+                if (!DeviceCategoryConverter::fromString(configCurve.deviceCategory, deviceCat)) {
                     ALOGE("%s: Invalid %s", __FUNCTION__, configCurve.deviceCategory.c_str());
                     continue;
                 }
-                sp<VolumeCurve> curve = new VolumeCurve(deviceCategory);
+                sp<VolumeCurve> curve = new VolumeCurve(deviceCat);
                 for (auto &point : configCurve.curvePoints) {
                     curve->add({point.index, point.attenuationInMb});
                 }
-                volumeCurves.add(curve);
+                volumeGroup->add(curve);
             }
-            streamVolumeCollection.add(volumeCurves, streamType);
         }
     };
-
     auto result = engineConfig::parse();
     if (result.parsedConfig == nullptr) {
         ALOGW("%s: No configuration found, using default matching phone experience.", __FUNCTION__);
@@ -145,8 +146,10 @@
                   static_cast<size_t>(ret == NO_ERROR ? 0 : 1)};
     }
     ALOGE_IF(result.nbSkippedElement != 0, "skipped %zu elements", result.nbSkippedElement);
-    loadProductStrategies(result.parsedConfig->productStrategies, mProductStrategies);
-    loadVolumeCurves(result.parsedConfig->volumeGroups, mStreamVolumeCurves);
+    loadVolumeGroups(result.parsedConfig->volumeGroups, mVolumeGroups);
+    loadProductStrategies(result.parsedConfig->productStrategies, mProductStrategies,
+                          mVolumeGroups);
+    mProductStrategies.initialize();
     return result;
 }
 
@@ -204,30 +207,77 @@
     return NO_ERROR;
 }
 
-VolumeCurves *EngineBase::getVolumeCurvesForAttributes(const audio_attributes_t &attr)
+VolumeCurves *EngineBase::getVolumeCurvesForAttributes(const audio_attributes_t &attr) const
 {
-    return &mStreamVolumeCurves.getVolumeCurvesForStream(getStreamTypeForAttributes(attr));
+    volume_group_t volGr = mProductStrategies.getVolumeGroupForAttributes(attr);
+    const auto &iter = mVolumeGroups.find(volGr);
+    LOG_ALWAYS_FATAL_IF(iter == std::end(mVolumeGroups), "No volume groups for %s", toString(attr).c_str());
+    return mVolumeGroups.at(volGr)->getVolumeCurves();
 }
 
-VolumeCurves *EngineBase::getVolumeCurvesForStreamType(audio_stream_type_t stream)
+VolumeCurves *EngineBase::getVolumeCurvesForStreamType(audio_stream_type_t stream) const
 {
-    return &mStreamVolumeCurves.getVolumeCurvesForStream(stream);
+    volume_group_t volGr = mProductStrategies.getVolumeGroupForStreamType(stream);
+    const auto &iter = mVolumeGroups.find(volGr);
+    LOG_ALWAYS_FATAL_IF(iter == std::end(mVolumeGroups), "No volume groups for %s",
+                toString(stream).c_str());
+    return mVolumeGroups.at(volGr)->getVolumeCurves();
 }
 
 status_t EngineBase::switchVolumeCurve(audio_stream_type_t streamSrc, audio_stream_type_t streamDst)
 {
-    return mStreamVolumeCurves.switchVolumeCurve(streamSrc, streamDst);;
+    auto srcCurves = getVolumeCurvesForStreamType(streamSrc);
+    auto dstCurves = getVolumeCurvesForStreamType(streamDst);
+
+    if (srcCurves == nullptr || dstCurves == nullptr) {
+        return BAD_VALUE;
+    }
+    return dstCurves->switchCurvesFrom(*srcCurves);
 }
 
 status_t EngineBase::restoreOriginVolumeCurve(audio_stream_type_t stream)
 {
-    return mStreamVolumeCurves.restoreOriginVolumeCurve(stream);
+    VolumeCurves *curves = getVolumeCurvesForStreamType(stream);
+    return curves != nullptr ? curves->switchCurvesFrom(*curves) : BAD_VALUE;
+}
+
+VolumeGroupVector EngineBase::getVolumeGroups() const
+{
+    VolumeGroupVector group;
+    for (const auto &iter : mVolumeGroups) {
+        group.push_back(iter.first);
+    }
+    return group;
+}
+
+volume_group_t EngineBase::getVolumeGroupForAttributes(const audio_attributes_t &attr) const
+{
+    return mProductStrategies.getVolumeGroupForAttributes(attr);
+}
+
+volume_group_t EngineBase::getVolumeGroupForStreamType(audio_stream_type_t stream) const
+{
+    return mProductStrategies.getVolumeGroupForStreamType(stream);
+}
+
+StreamTypeVector EngineBase::getStreamTypesForVolumeGroup(volume_group_t volumeGroup) const
+{
+    // @TODO default music stream to control volume if no group?
+    return (mVolumeGroups.find(volumeGroup) != end(mVolumeGroups)) ?
+                mVolumeGroups.at(volumeGroup)->getStreamTypes() :
+                StreamTypeVector(AUDIO_STREAM_MUSIC);
+}
+
+AttributesVector EngineBase::getAllAttributesForVolumeGroup(volume_group_t volumeGroup) const
+{
+    return (mVolumeGroups.find(volumeGroup) != end(mVolumeGroups)) ?
+                mVolumeGroups.at(volumeGroup)->getSupportedAttributes() : AttributesVector();
 }
 
 void EngineBase::dump(String8 *dst) const
 {
     mProductStrategies.dump(dst, 2);
-    mStreamVolumeCurves.dump(dst, 2);
+    mVolumeGroups.dump(dst, 2);
 }
 
 } // namespace audio_policy
diff --git a/services/audiopolicy/engine/common/src/EngineDefaultConfig.h b/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
index f1642c5..fede0d9 100644
--- a/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
+++ b/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
@@ -25,11 +25,11 @@
 const engineConfig::ProductStrategies gOrderedStrategies = {
     {"STRATEGY_PHONE",
      {
-         {"phone", AUDIO_STREAM_VOICE_CALL,
+         {"phone", AUDIO_STREAM_VOICE_CALL, "AUDIO_STREAM_VOICE_CALL",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_SOURCE_DEFAULT, 0,
             ""}},
          },
-         {"sco", AUDIO_STREAM_BLUETOOTH_SCO,
+         {"sco", AUDIO_STREAM_BLUETOOTH_SCO, "AUDIO_STREAM_BLUETOOTH_SCO",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_SCO,
             ""}},
          }
@@ -37,18 +37,18 @@
     },
     {"STRATEGY_SONIFICATION",
      {
-         {"ring", AUDIO_STREAM_RING,
+         {"ring", AUDIO_STREAM_RING, "AUDIO_STREAM_RING",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE,
             AUDIO_SOURCE_DEFAULT, 0, ""}}
          },
-         {"alarm", AUDIO_STREAM_ALARM,
+         {"alarm", AUDIO_STREAM_ALARM, "AUDIO_STREAM_ALARM",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_ALARM, AUDIO_SOURCE_DEFAULT, 0, ""}},
          }
      },
     },
     {"STRATEGY_ENFORCED_AUDIBLE",
      {
-         {"", AUDIO_STREAM_ENFORCED_AUDIBLE,
+         {"", AUDIO_STREAM_ENFORCED_AUDIBLE, "AUDIO_STREAM_ENFORCED_AUDIBLE",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT,
             AUDIO_FLAG_AUDIBILITY_ENFORCED, ""}}
          }
@@ -56,7 +56,7 @@
     },
     {"STRATEGY_ACCESSIBILITY",
      {
-         {"", AUDIO_STREAM_ACCESSIBILITY,
+         {"", AUDIO_STREAM_ACCESSIBILITY, "AUDIO_STREAM_ACCESSIBILITY",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY,
             AUDIO_SOURCE_DEFAULT, 0, ""}}
          }
@@ -64,7 +64,7 @@
     },
     {"STRATEGY_SONIFICATION_RESPECTFUL",
      {
-         {"", AUDIO_STREAM_NOTIFICATION,
+         {"", AUDIO_STREAM_NOTIFICATION, "AUDIO_STREAM_NOTIFICATION",
           {
               {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_NOTIFICATION, AUDIO_SOURCE_DEFAULT, 0, ""},
               {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST,
@@ -81,7 +81,7 @@
     },
     {"STRATEGY_MEDIA",
      {
-         {"music", AUDIO_STREAM_MUSIC,
+         {"music", AUDIO_STREAM_MUSIC, "AUDIO_STREAM_MUSIC",
           {
               {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_MEDIA, AUDIO_SOURCE_DEFAULT, 0, ""},
               {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_GAME, AUDIO_SOURCE_DEFAULT, 0, ""},
@@ -91,7 +91,7 @@
               {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT, 0, ""}
           },
          },
-         {"system", AUDIO_STREAM_SYSTEM,
+         {"system", AUDIO_STREAM_SYSTEM, "AUDIO_STREAM_SYSTEM",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_ASSISTANCE_SONIFICATION,
             AUDIO_SOURCE_DEFAULT, 0, ""}}
          }
@@ -99,7 +99,7 @@
     },
     {"STRATEGY_DTMF",
      {
-         {"", AUDIO_STREAM_DTMF,
+         {"", AUDIO_STREAM_DTMF, "AUDIO_STREAM_DTMF",
           {
               {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING,
                AUDIO_SOURCE_DEFAULT, 0, ""}
@@ -109,7 +109,7 @@
     },
     {"STRATEGY_TRANSMITTED_THROUGH_SPEAKER",
      {
-         {"", AUDIO_STREAM_TTS,
+         {"", AUDIO_STREAM_TTS, "AUDIO_STREAM_TTS",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT,
             AUDIO_FLAG_BEACON, ""}}
          }
@@ -117,14 +117,14 @@
     },
     {"STRATEGY_REROUTING",
      {
-         {"", AUDIO_STREAM_REROUTING,
+         {"", AUDIO_STREAM_REROUTING, "AUDIO_STREAM_REROUTING",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT, 0, ""}}
          }
      },
     },
     {"STRATEGY_PATCH",
      {
-         {"", AUDIO_STREAM_PATCH,
+         {"", AUDIO_STREAM_PATCH, "AUDIO_STREAM_PATCH",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT, 0, ""}}
          }
      },
diff --git a/services/audiopolicy/engine/common/src/ProductStrategy.cpp b/services/audiopolicy/engine/common/src/ProductStrategy.cpp
index 71607d1..16e6690 100644
--- a/services/audiopolicy/engine/common/src/ProductStrategy.cpp
+++ b/services/audiopolicy/engine/common/src/ProductStrategy.cpp
@@ -44,7 +44,7 @@
 {
     std::vector<android::AudioAttributes> androidAa;
     for (const auto &attr : mAttributesVector) {
-        androidAa.push_back({attr.mGroupId, attr.mStream, attr.mAttributes});
+        androidAa.push_back({attr.mVolumeGroup, attr.mStream, attr.mAttributes});
     }
     return androidAa;
 }
@@ -69,7 +69,8 @@
     }) != end(mAttributesVector);
 }
 
-audio_stream_type_t ProductStrategy::getStreamTypeForAttributes(const audio_attributes_t &attr) const
+audio_stream_type_t ProductStrategy::getStreamTypeForAttributes(
+        const audio_attributes_t &attr) const
 {
     const auto iter = std::find_if(begin(mAttributesVector), end(mAttributesVector),
                                    [&attr](const auto &supportedAttr) {
@@ -110,6 +111,33 @@
         return supportedAttr.mStream == streamType; }) != end(mAttributesVector);
 }
 
+volume_group_t ProductStrategy::getVolumeGroupForAttributes(const audio_attributes_t &attr) const
+{
+    for (const auto &supportedAttr : mAttributesVector) {
+        if (AudioProductStrategy::attributesMatches(supportedAttr.mAttributes, attr)) {
+            return supportedAttr.mVolumeGroup;
+        }
+    }
+    return VOLUME_GROUP_NONE;
+}
+
+volume_group_t ProductStrategy::getVolumeGroupForStreamType(audio_stream_type_t stream) const
+{
+    for (const auto &supportedAttr : mAttributesVector) {
+        if (supportedAttr.mStream == stream) {
+            return supportedAttr.mVolumeGroup;
+        }
+    }
+    return VOLUME_GROUP_NONE;
+}
+
+volume_group_t ProductStrategy::getDefaultVolumeGroup() const
+{
+    const auto &iter = std::find_if(begin(mAttributesVector), end(mAttributesVector),
+                                    [](const auto &attr) {return attr.mAttributes == defaultAttr;});
+    return iter != end(mAttributesVector) ? iter->mVolumeGroup : VOLUME_GROUP_NONE;
+}
+
 void ProductStrategy::dump(String8 *dst, int spaces) const
 {
     dst->appendFormat("\n%*s-%s (id: %d)\n", spaces, "", mName.c_str(), mId);
@@ -121,7 +149,7 @@
                        deviceLiteral.c_str(), mDeviceAddress.c_str());
 
     for (const auto &attr : mAttributesVector) {
-        dst->appendFormat("%*sGroup: %d stream: %s\n", spaces + 3, "", attr.mGroupId,
+        dst->appendFormat("%*sGroup: %d stream: %s\n", spaces + 3, "", attr.mVolumeGroup,
                           android::toString(attr.mStream).c_str());
         dst->appendFormat("%*s Attributes: ", spaces + 3, "");
         std::string attStr =
@@ -172,6 +200,9 @@
 
 product_strategy_t ProductStrategyMap::getDefault() const
 {
+    if (mDefaultStrategy != PRODUCT_STRATEGY_NONE) {
+        return mDefaultStrategy;
+    }
     for (const auto &iter : *this) {
         if (iter.second->isDefault()) {
             ALOGV("%s: using default %s", __FUNCTION__, iter.second->getName().c_str());
@@ -231,6 +262,42 @@
     return at(psId)->getDeviceAddress();
 }
 
+volume_group_t ProductStrategyMap::getVolumeGroupForAttributes(const audio_attributes_t &attr) const
+{
+    for (const auto &iter : *this) {
+        volume_group_t group = iter.second->getVolumeGroupForAttributes(attr);
+        if (group != VOLUME_GROUP_NONE) {
+            return group;
+        }
+    }
+    product_strategy_t defaultStrategy = getDefault();
+    if (defaultStrategy == PRODUCT_STRATEGY_NONE) {
+        return VOLUME_GROUP_NONE;
+    }
+    return at(defaultStrategy)->getDefaultVolumeGroup();
+}
+
+volume_group_t ProductStrategyMap::getVolumeGroupForStreamType(audio_stream_type_t stream) const
+{
+    for (const auto &iter : *this) {
+        volume_group_t group = iter.second->getVolumeGroupForStreamType(stream);
+        if (group != VOLUME_GROUP_NONE) {
+            return group;
+        }
+    }
+    product_strategy_t defaultStrategy = getDefault();
+    if (defaultStrategy == PRODUCT_STRATEGY_NONE) {
+        return VOLUME_GROUP_NONE;
+    }
+    return at(defaultStrategy)->getDefaultVolumeGroup();
+}
+
+void ProductStrategyMap::initialize()
+{
+    mDefaultStrategy = getDefault();
+    ALOG_ASSERT(mDefaultStrategy != PRODUCT_STRATEGY_NONE, "No default product strategy found");
+}
+
 void ProductStrategyMap::dump(String8 *dst, int spaces) const
 {
     dst->appendFormat("%*sProduct Strategies dump:", spaces, "");
diff --git a/services/audiopolicy/engine/common/src/StreamVolumeCurves.cpp b/services/audiopolicy/engine/common/src/StreamVolumeCurves.cpp
deleted file mode 100644
index fe3b000..0000000
--- a/services/audiopolicy/engine/common/src/StreamVolumeCurves.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-#define LOG_TAG "APM::Engine::StreamVolumeCurves"
-//#define LOG_NDEBUG 0
-
-#include "StreamVolumeCurves.h"
-#include <TypeConverter.h>
-
-namespace android {
-
-void StreamVolumeCurves::dump(String8 *dst, int spaces) const
-{
-    if (mCurves.empty()) {
-        return;
-    }
-    dst->appendFormat("\n%*sStreams dump:\n", spaces, "");
-    dst->appendFormat(
-                "%*sStream  Can be muted  Index Min  Index Max  Index Cur [device : index]...\n", spaces + 2, "");
-    for (const auto &streamCurve : mCurves) {
-        streamCurve.second.dump(dst, spaces + 2, false);
-    }
-    dst->appendFormat("\n%*sVolume Curves for Use Cases (aka Stream types) dump:\n", spaces, "");
-    for (const auto &streamCurve : mCurves) {
-        std::string streamTypeLiteral;
-        StreamTypeConverter::toString(streamCurve.first, streamTypeLiteral);
-        dst->appendFormat(
-                    " %s (%02d): Curve points for device category (index, attenuation in millibel)\n",
-                    streamTypeLiteral.c_str(), streamCurve.first);
-        streamCurve.second.dump(dst, spaces + 2, true);
-    }
-}
-
-} // namespace android
diff --git a/services/audiopolicy/engine/common/src/VolumeCurve.cpp b/services/audiopolicy/engine/common/src/VolumeCurve.cpp
index be2ca73..c352578 100644
--- a/services/audiopolicy/engine/common/src/VolumeCurve.cpp
+++ b/services/audiopolicy/engine/common/src/VolumeCurve.cpp
@@ -19,13 +19,17 @@
 
 #include "VolumeCurve.h"
 #include "TypeConverter.h"
+#include <media/TypeConverter.h>
 
 namespace android {
 
 float VolumeCurve::volIndexToDb(int indexInUi, int volIndexMin, int volIndexMax) const
 {
     ALOG_ASSERT(!mCurvePoints.isEmpty(), "Invalid volume curve");
-
+    if (volIndexMin < 0 || volIndexMax < 0) {
+        // In order to let AudioService initialize the min and max, convention is to use -1
+        return NAN;
+    }
     if (indexInUi < volIndexMin) {
         // an index of 0 means mute request when volIndexMin > 0
         if (indexInUi == 0) {
@@ -80,8 +84,8 @@
     }
     dst->append(" {");
     for (size_t i = 0; i < mCurvePoints.size(); i++) {
-        dst->appendFormat("%*s (%3d, %5d)", spaces, "",
-                 mCurvePoints[i].mIndex, mCurvePoints[i].mAttenuationInMb);
+        dst->appendFormat("%*s(%3d, %5d)", spaces, "", mCurvePoints[i].mIndex,
+                          mCurvePoints[i].mAttenuationInMb);
         dst->appendFormat(i == (mCurvePoints.size() - 1) ? " }\n" : ", ");
     }
 }
@@ -89,19 +93,36 @@
 void VolumeCurves::dump(String8 *dst, int spaces, bool curvePoints) const
 {
     if (!curvePoints) {
-        dst->appendFormat("%*s%02d      %s         %03d        %03d        ", spaces, "",
-                          mStream, mCanBeMuted ? "true " : "false", mIndexMin, mIndexMax);
+//        dst->appendFormat("%*s%02d      %s         %03d        %03d        ", spaces, "",
+//                          mStream, mCanBeMuted ? "true " : "false", mIndexMin, mIndexMax);
+        dst->appendFormat("%*s Can be muted  Index Min  Index Max  Index Cur [device : index]...\n",
+                          spaces + 1, "");
+        dst->appendFormat("%*s %s         %02d         %02d         ", spaces + 1, "",
+                          mCanBeMuted ? "true " : "false", mIndexMin, mIndexMax);
         for (const auto &pair : mIndexCur) {
-            dst->appendFormat("%*s %04x : %02d, ", spaces, "", pair.first, pair.second);
+            dst->appendFormat("%04x : %02d, ", pair.first, pair.second);
         }
         dst->appendFormat("\n");
         return;
     }
+    std::string streamNames;
+    for (const auto &stream : mStreams) {
+        streamNames += android::toString(stream) + "("+std::to_string(stream)+") ";
+    }
+    dst->appendFormat("%*sVolume Curves Streams/Attributes, Curve points Streams for device"
+                      " category (index, attenuation in millibel)\n", spaces, "");
+    dst->appendFormat("%*s Streams: %s \n", spaces, "", streamNames.c_str());
+    if (!mAttributes.empty()) dst->appendFormat("%*s Attributes:", spaces, "");
+    for (const auto &attributes : mAttributes) {
+        std::string attStr = attributes == defaultAttr ? "{ Any }" : android::toString(attributes);
+        dst->appendFormat("%*s %s\n", attributes == mAttributes.front() ? 0 : spaces + 13, "",
+                          attStr.c_str());
+    }
     for (size_t i = 0; i < size(); i++) {
         std::string deviceCatLiteral;
         DeviceCategoryConverter::toString(keyAt(i), deviceCatLiteral);
         dst->appendFormat("%*s %s :", spaces, "", deviceCatLiteral.c_str());
-        valueAt(i)->dump(dst, 2, true);
+        valueAt(i)->dump(dst, 1, true);
     }
 }
 
diff --git a/services/audiopolicy/engine/common/src/VolumeGroup.cpp b/services/audiopolicy/engine/common/src/VolumeGroup.cpp
new file mode 100644
index 0000000..e189807
--- /dev/null
+++ b/services/audiopolicy/engine/common/src/VolumeGroup.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#define LOG_TAG "APM::AudioPolicyEngine/VolumeGroup"
+//#define LOG_NDEBUG 0
+
+#include "VolumeGroup.h"
+#include <media/TypeConverter.h>
+#include <utils/String8.h>
+#include <cstdint>
+#include <string>
+
+#include <log/log.h>
+
+
+namespace android {
+
+//
+// VolumeGroup implementation
+//
+VolumeGroup::VolumeGroup(const std::string &name, int indexMin, int indexMax) :
+    mName(name), mId(static_cast<volume_group_t>(HandleGenerator<uint32_t>::getNextHandle())),
+    mGroupVolumeCurves(VolumeCurves(indexMin, indexMax))
+{
+}
+
+void VolumeGroup::dump(String8 *dst, int spaces) const
+{
+    dst->appendFormat("\n%*s-%s (id: %d)\n", spaces, "", mName.c_str(), mId);
+    mGroupVolumeCurves.dump(dst, spaces + 2, true);
+    mGroupVolumeCurves.dump(dst, spaces + 2, false);
+    dst->appendFormat("\n");
+}
+
+void VolumeGroup::add(const sp<VolumeCurve> &curve)
+{
+    mGroupVolumeCurves.add(curve);
+}
+
+void VolumeGroup::addSupportedAttributes(const audio_attributes_t &attr)
+{
+    mGroupVolumeCurves.addAttributes(attr);
+}
+
+void VolumeGroup::addSupportedStream(audio_stream_type_t stream)
+{
+    mGroupVolumeCurves.addStreamType(stream);
+}
+
+//
+// VolumeGroupMap implementation
+//
+void VolumeGroupMap::dump(String8 *dst, int spaces) const
+{
+    dst->appendFormat("\n%*sVolume Groups dump:", spaces, "");
+    for (const auto &iter : *this) {
+        iter.second->dump(dst, spaces + 2);
+    }
+}
+
+} // namespace android
+
diff --git a/services/audiopolicy/engine/config/include/EngineConfig.h b/services/audiopolicy/engine/config/include/EngineConfig.h
index a188115..7f5ed5e 100644
--- a/services/audiopolicy/engine/config/include/EngineConfig.h
+++ b/services/audiopolicy/engine/config/include/EngineConfig.h
@@ -40,6 +40,7 @@
 struct AttributesGroup {
     std::string name;
     audio_stream_type_t stream;
+    std::string volumeGroup;
     AttributesVector attributesVect;
 };
 
@@ -59,7 +60,6 @@
 
 struct VolumeGroup {
     std::string name;
-    std::string stream;
     int indexMin;
     int indexMax;
     VolumeCurves volumeCurves;
diff --git a/services/audiopolicy/engine/config/src/EngineConfig.cpp b/services/audiopolicy/engine/config/src/EngineConfig.cpp
index 00fbac4..1ad7739 100644
--- a/services/audiopolicy/engine/config/src/EngineConfig.cpp
+++ b/services/audiopolicy/engine/config/src/EngineConfig.cpp
@@ -59,6 +59,7 @@
     struct Attributes {
         static constexpr const char *name = "name";
         static constexpr const char *streamType = "streamType";
+        static constexpr const char *volumeGroup = "volumeGroup";
     };
     static android::status_t deserialize(_xmlDoc *doc, const _xmlNode *root, Collection &ps);
 };
@@ -116,6 +117,7 @@
 
     struct Attributes {
         static constexpr const char *deviceCategory = "deviceCategory";
+        static constexpr const char *stream = "stream"; // For legacy volume curves
         static constexpr const char *reference = "ref"; /**< For volume curves factorization. */
     };
 
@@ -139,8 +141,6 @@
 
 using xmlCharUnique = std::unique_ptr<xmlChar, decltype(xmlFree)>;
 
-using xmlCharUnique = std::unique_ptr<xmlChar, decltype(xmlFree)>;
-
 std::string getXmlAttribute(const xmlNode *cur, const char *attribute)
 {
     xmlCharUnique charPtr(xmlGetProp(cur, reinterpret_cast<const xmlChar *>(attribute)), xmlFree);
@@ -304,6 +304,12 @@
     }
     ALOGV("%s: %s = %s", __FUNCTION__, Attributes::name, name.c_str());
 
+    std::string volumeGroup = getXmlAttribute(child, Attributes::volumeGroup);
+    if (volumeGroup.empty()) {
+        ALOGE("%s: No attribute %s found", __FUNCTION__, Attributes::volumeGroup);
+    }
+    ALOGV("%s: %s = %s", __FUNCTION__, Attributes::volumeGroup, volumeGroup.c_str());
+
     audio_stream_type_t streamType = AUDIO_STREAM_DEFAULT;
     std::string streamTypeXml = getXmlAttribute(child, Attributes::streamType);
     if (streamTypeXml.empty()) {
@@ -318,7 +324,7 @@
     AttributesVector attributesVect;
     deserializeAttributesCollection(doc, child, attributesVect);
 
-    attributesGroup.push_back({name, streamType, attributesVect});
+    attributesGroup.push_back({name, streamType, volumeGroup, attributesVect});
     return NO_ERROR;
 }
 
@@ -420,7 +426,6 @@
     if (deviceCategory.empty()) {
         ALOGW("%s: No %s found", __FUNCTION__, Attributes::deviceCategory);
     }
-
     std::string referenceName = getXmlAttribute(root, Attributes::reference);
     const _xmlNode *ref = NULL;
     if (!referenceName.empty()) {
@@ -458,9 +463,10 @@
 status_t VolumeGroupTraits::deserialize(_xmlDoc *doc, const _xmlNode *root, Collection &volumes)
 {
     std::string name;
-    std::string stream = {};
     int indexMin = 0;
     int indexMax = 0;
+    StreamVector streams = {};
+    AttributesVector attributesVect = {};
 
     for (const xmlNode *child = root->xmlChildrenNode; child != NULL; child = child->next) {
         if (not xmlStrcmp(child->name, (const xmlChar *)Attributes::name)) {
@@ -470,13 +476,6 @@
             }
             name = reinterpret_cast<const char*>(nameXml.get());
         }
-        if (not xmlStrcmp(child->name, (const xmlChar *)Attributes::stream)) {
-            xmlCharUnique streamXml(xmlNodeListGetString(doc, child->xmlChildrenNode, 1), xmlFree);
-            if (streamXml == nullptr) {
-                return BAD_VALUE;
-            }
-            stream = reinterpret_cast<const char*>(streamXml.get());
-        }
         if (not xmlStrcmp(child->name, (const xmlChar *)Attributes::indexMin)) {
             xmlCharUnique indexMinXml(xmlNodeListGetString(doc, child->xmlChildrenNode, 1), xmlFree);
             if (indexMinXml == nullptr) {
@@ -498,13 +497,23 @@
             }
         }
     }
-    ALOGV("%s: group=%s stream=%s indexMin=%d, indexMax=%d",
-          __func__, name.c_str(), stream.c_str(), indexMin, indexMax);
+    deserializeAttributesCollection(doc, root, attributesVect);
+
+    std::string streamNames;
+    for (const auto &stream : streams) {
+        streamNames += android::toString(stream) + " ";
+    }
+    std::string attrmNames;
+    for (const auto &attr : attributesVect) {
+        attrmNames += android::toString(attr) + "\n";
+    }
+    ALOGV("%s: group=%s indexMin=%d, indexMax=%d streams=%s attributes=%s",
+          __func__, name.c_str(), indexMin, indexMax, streamNames.c_str(), attrmNames.c_str( ));
 
     VolumeCurves groupVolumeCurves;
     size_t skipped = 0;
     deserializeCollection<VolumeTraits>(doc, root, groupVolumeCurves, skipped);
-    volumes.push_back({ name, stream, indexMin, indexMax, groupVolumeCurves });
+    volumes.push_back({ name, indexMin, indexMax, groupVolumeCurves });
     return NO_ERROR;
 }
 
@@ -580,8 +589,16 @@
         }
     }
     for (const auto &volumeMapIter : legacyVolumeMap) {
-        volumeGroups.push_back({ volumeMapIter.first, volumeMapIter.first, 0, 100,
-                                 volumeMapIter.second });
+        // In order to let AudioService setting the min and max (compatibility), set Min and Max
+        // to -1 except for private streams
+        audio_stream_type_t streamType;
+        if (!StreamTypeConverter::fromString(volumeMapIter.first, streamType)) {
+            ALOGE("%s: Invalid stream %s", __func__, volumeMapIter.first.c_str());
+            return BAD_VALUE;
+        }
+        int indexMin = streamType >= AUDIO_STREAM_PUBLIC_CNT ? 0 : -1;
+        int indexMax = streamType >= AUDIO_STREAM_PUBLIC_CNT ? 100 : -1;
+        volumeGroups.push_back({ volumeMapIter.first, indexMin, indexMax, volumeMapIter.second });
     }
     return NO_ERROR;
 }
diff --git a/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h b/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h
index c9e9507..07acd2e 100644
--- a/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h
+++ b/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h
@@ -32,7 +32,7 @@
 
 using DeviceStrategyMap = std::map<product_strategy_t, DeviceVector>;
 using StrategyVector = std::vector<product_strategy_t>;
-
+using VolumeGroupVector = std::vector<volume_group_t>;
 
 /**
  * This interface is dedicated to the policy manager that a Policy Engine shall implement.
@@ -182,6 +182,7 @@
 
     /**
      * @brief getAttributesForStream get the audio attributes from legacy stream type
+     * Attributes returned might only be used to check upon routing decision, not volume decisions.
      * @param stream to consider
      * @return audio attributes matching the legacy stream type
      */
@@ -241,14 +242,49 @@
      * @param attr to be considered
      * @return IVolumeCurves interface pointer if found, nullptr otherwise
      */
-    virtual IVolumeCurves *getVolumeCurvesForAttributes(const audio_attributes_t &attr) = 0;
+    virtual IVolumeCurves *getVolumeCurvesForAttributes(const audio_attributes_t &attr) const = 0;
 
     /**
      * @brief getVolumeCurvesForStreamType retrieves the Volume Curves interface for the stream
      * @param stream to be considered
      * @return IVolumeCurves interface pointer if found, nullptr otherwise
      */
-    virtual IVolumeCurves *getVolumeCurvesForStreamType(audio_stream_type_t stream) = 0;
+    virtual IVolumeCurves *getVolumeCurvesForStreamType(audio_stream_type_t stream) const = 0;
+
+    /**
+     * @brief getVolumeCurvesForVolumeGroup retrieves the Volume Curves interface for volume group
+     * @param group to be considered
+     * @return IVolumeCurves interface pointer if found, nullptr otherwise
+     */
+    virtual IVolumeCurves *getVolumeCurvesForVolumeGroup(volume_group_t group) const = 0;
+
+    /**
+     * @brief getVolumeGroups retrieves the collection of volume groups.
+     * @return vector of volume groups
+     */
+    virtual VolumeGroupVector getVolumeGroups() const = 0;
+
+    /**
+     * @brief getVolumeGroupForAttributes gets the appropriate volume group to be used for a given
+     * Audio Attributes.
+     * @param attr to be considered
+     * @return volume group associated to the given audio attributes, default group if none
+     * applicable, VOLUME_GROUP_NONE if no default group defined.
+     */
+    virtual volume_group_t getVolumeGroupForAttributes(const audio_attributes_t &attr) const = 0;
+
+    /**
+     * @brief getVolumeGroupForStreamType gets the appropriate volume group to be used for a given
+     * legacy stream type
+     * @param stream type to be considered
+     * @return volume group associated to the given stream type, default group if none applicable,
+     * VOLUME_GROUP_NONE if no default group defined.
+     */
+    virtual volume_group_t getVolumeGroupForStreamType(audio_stream_type_t stream) const = 0;
+
+    virtual StreamTypeVector getStreamTypesForVolumeGroup(volume_group_t volumeGroup) const = 0;
+
+    virtual AttributesVector getAllAttributesForVolumeGroup(volume_group_t volumeGroup) const = 0;
 
     virtual void dump(String8 *dst) const = 0;
 
diff --git a/services/audiopolicy/engineconfigurable/Android.mk b/services/audiopolicy/engineconfigurable/Android.mk
index 2b7e4c8..4eff6e6 100644
--- a/services/audiopolicy/engineconfigurable/Android.mk
+++ b/services/audiopolicy/engineconfigurable/Android.mk
@@ -13,7 +13,7 @@
     src/Stream.cpp \
     src/InputSource.cpp \
     ../engine/common/src/VolumeCurve.cpp \
-    ../engine/common/src/StreamVolumeCurves.cpp \
+    ../engine/common/src/VolumeGroup.cpp \
     ../engine/common/src/ProductStrategy.cpp \
     ../engine/common/src/EngineBase.cpp
 
diff --git a/services/audiopolicy/engineconfigurable/config/example/Android.mk b/services/audiopolicy/engineconfigurable/config/example/Android.mk
index ef476f7..45419f0 100644
--- a/services/audiopolicy/engineconfigurable/config/example/Android.mk
+++ b/services/audiopolicy/engineconfigurable/config/example/Android.mk
@@ -72,7 +72,8 @@
 LOCAL_REQUIRED_MODULES := \
     audio_policy_engine_product_strategies_automotive.xml \
     audio_policy_engine_criteria.xml \
-    audio_policy_engine_criterion_types.xml
+    audio_policy_engine_criterion_types.xml \
+    audio_policy_engine_volumes.xml
 
 include $(BUILD_PREBUILT)
 
@@ -89,6 +90,14 @@
 LOCAL_SRC_FILES := automotive/$(LOCAL_MODULE_STEM)
 include $(BUILD_PREBUILT)
 
+include $(CLEAR_VARS)
+LOCAL_MODULE := audio_policy_engine_volumes.xml
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := ETC
+LOCAL_VENDOR_MODULE := true
+LOCAL_SRC_FILES := automotive/$(LOCAL_MODULE)
+include $(BUILD_PREBUILT)
+
 endif #ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), automotive_configurable)
 
 ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),$(filter $(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),phone_configurable automotive_configurable))
diff --git a/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_configuration.xml b/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_configuration.xml
index e2fb02b..28a140a 100644
--- a/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_configuration.xml
+++ b/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_configuration.xml
@@ -19,6 +19,7 @@
     <xi:include href="audio_policy_engine_product_strategies.xml"/>
     <xi:include href="audio_policy_engine_criterion_types.xml"/>
     <xi:include href="audio_policy_engine_criteria.xml"/>
+    <xi:include href="audio_policy_engine_volumes.xml"/>
 
 </configuration>
 
diff --git a/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_product_strategies.xml b/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_product_strategies.xml
index 543a2f0..c487da9 100644
--- a/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_product_strategies.xml
+++ b/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_product_strategies.xml
@@ -31,7 +31,7 @@
     -->
 
     <ProductStrategy name="oem_traffic_anouncement">
-        <AttributesGroup>
+        <AttributesGroup volumeGroup="oem_traffic_anouncement">
             <ContentType value="AUDIO_CONTENT_TYPE_SPEECH"/>
             <Usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/>
             <!--  traffic_annoucement = 1 -->
@@ -39,14 +39,14 @@
         </AttributesGroup>
     </ProductStrategy>
     <ProductStrategy name="oem_strategy_1">
-        <AttributesGroup>
+        <AttributesGroup volumeGroup="oem_adas_2">
             <ContentType value="AUDIO_CONTENT_TYPE_SPEECH"/>
             <Usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/>
             <Bundle key="oem" value="2"/>
         </AttributesGroup>
     </ProductStrategy>
     <ProductStrategy name="oem_strategy_2">
-        <AttributesGroup>
+        <AttributesGroup volumeGroup="oem_adas_3">
             <ContentType value="AUDIO_CONTENT_TYPE_SPEECH"/>
             <Usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/>
             <Bundle key="oem" value="3"/>
@@ -70,21 +70,21 @@
         ( type == CAR_AUDIO_TYPE_RADIO ) )
         -->
     <ProductStrategy name="radio">
-        <AttributesGroup>
+        <AttributesGroup volumeGroup="media_car_audio_type_3">
             <ContentType value="AUDIO_CONTENT_TYPE_MUSIC"/>
             <Usage value="AUDIO_USAGE_MEDIA"/>
             <Bundle key="car_audio_type" value="3"/>
         </AttributesGroup>
     </ProductStrategy>
     <ProductStrategy name="ext_audio_source">
-        <AttributesGroup>
+        <AttributesGroup volumeGroup="media_car_audio_type_7">
             <ContentType value="AUDIO_CONTENT_TYPE_MUSIC"/>
             <Usage value="AUDIO_USAGE_MEDIA"/>
             <Bundle key="car_audio_type" value="7"/>
         </AttributesGroup>
     </ProductStrategy>
     <ProductStrategy name="voice_command">
-        <AttributesGroup>
+        <AttributesGroup volumeGroup="speech">
             <Attributes>
                 <ContentType value="AUDIO_CONTENT_TYPE_SPEECH"/>
                 <Usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/>
@@ -96,7 +96,7 @@
         </AttributesGroup>
     </ProductStrategy>
     <ProductStrategy name="safety_alert">
-        <AttributesGroup>
+        <AttributesGroup volumeGroup="system">
             <ContentType value="AUDIO_CONTENT_TYPE_SONIFICATION"/>
             <Usage value="AUDIO_USAGE_NOTIFICATION"/>
             <!--  CAR_AUDIO_TYPE_SAFETY_ALERT = 2 -->
@@ -112,7 +112,7 @@
 
     <!-- Generic Usages -->
     <ProductStrategy name="music">
-        <AttributesGroup streamType="AUDIO_STREAM_MUSIC">
+        <AttributesGroup streamType="AUDIO_STREAM_MUSIC" volumeGroup="media">
             <Attributes> <Usage value="AUDIO_USAGE_MEDIA"/> </Attributes>
             <Attributes> <Usage value="AUDIO_USAGE_GAME"/> </Attributes>
             <!-- Default product strategy has empty attributes -->
@@ -121,29 +121,31 @@
     </ProductStrategy>
 
     <ProductStrategy name="nav_guidance">
-        <AttributesGroup>
+        <AttributesGroup volumeGroup="speech">
             <Usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/>
         </AttributesGroup>
     </ProductStrategy>
     <ProductStrategy name="voice_call">
-        <AttributesGroup streamType="AUDIO_STREAM_VOICE_CALL">
+        <AttributesGroup streamType="AUDIO_STREAM_VOICE_CALL" volumeGroup="phone">
             <Attributes> <Usage value="AUDIO_USAGE_VOICE_COMMUNICATION"/> </Attributes>
             <Attributes> <Usage value="AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING"/> </Attributes>
+        </AttributesGroup>
+        <AttributesGroup streamType="AUDIO_STREAM_BLUETOOTH_SCO" volumeGroup="phone">
             <Attributes> <Flags value="AUDIO_FLAG_SCO"/> </Attributes>
         </AttributesGroup>
     </ProductStrategy>
     <ProductStrategy name="alarm">
-        <AttributesGroup streamType="AUDIO_STREAM_ALARM">
+        <AttributesGroup streamType="AUDIO_STREAM_ALARM" volumeGroup="ring">
             <Usage value="AUDIO_USAGE_ALARM"/>
         </AttributesGroup>
     </ProductStrategy>
     <ProductStrategy name="ring">
-        <AttributesGroup streamType="AUDIO_STREAM_RING">
+        <AttributesGroup streamType="AUDIO_STREAM_RING" volumeGroup="ring">
             <Usage value="AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE"/>
         </AttributesGroup>
     </ProductStrategy>
     <ProductStrategy name="notification">
-        <AttributesGroup streamType="AUDIO_STREAM_NOTIFICATION">
+        <AttributesGroup streamType="AUDIO_STREAM_NOTIFICATION" volumeGroup="ring">
             <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION"/> </Attributes>
             <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT"/> </Attributes>
             <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED"/> </Attributes>
@@ -152,10 +154,17 @@
         </AttributesGroup>
     </ProductStrategy>
     <ProductStrategy name="system">
-        <AttributesGroup streamType="AUDIO_STREAM_SYSTEM">
+        <AttributesGroup streamType="AUDIO_STREAM_SYSTEM" volumeGroup="system">
             <Usage value="AUDIO_USAGE_ASSISTANCE_SONIFICATION"/>
         </AttributesGroup>
     </ProductStrategy>
-
+    <ProductStrategy name="tts">
+        <!-- TTS stream MUST BE MANAGED OUTSIDE default product strategy if NO DEDICATED OUTPUT
+             for TTS, otherwise when beacon happens, default strategy is ... muted.
+             If it is media, it is annoying... -->
+        <AttributesGroup streamType="AUDIO_STREAM_TTS" volumeGroup="tts">
+            <Attributes> <Flags value="AUDIO_FLAG_BEACON"/> </Attributes>
+        </AttributesGroup>
+    </ProductStrategy>
 </ProductStrategies>
 
diff --git a/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_volumes.xml b/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_volumes.xml
new file mode 100644
index 0000000..b326b50
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_volumes.xml
@@ -0,0 +1,192 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Copyright (C) 2018 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.
+     -->
+
+<!-- Volume Groups Tables included by Audio Policy Configuration file -->
+<!-- Note:
+        It is VALID to have a group without attributes if a product strategy is following
+        this group for all attributes.
+        Otherwise, attributes must be specified
+-->
+
+<volumeGroups>
+    <volumeGroup>
+        <name>oem_traffic_anouncement</name>
+        <indexMin>0</indexMin>
+        <indexMax>40</indexMax>
+        <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+            <point>0,-4200</point>
+            <point>33,-2800</point>
+            <point>66,-1400</point>
+            <point>100,0</point>
+        </volume>
+        <volume deviceCategory="DEVICE_CATEGORY_HEADSET">
+            <point>0,-4200</point>
+            <point>33,-2800</point>
+            <point>66,-1400</point>
+            <point>100,0</point>
+        </volume>
+        <volume deviceCategory="DEVICE_CATEGORY_EARPIECE">
+            <point>0,-4200</point>
+            <point>33,-2800</point>
+            <point>66,-1400</point>
+            <point>100,0</point>
+        </volume>
+        <volume deviceCategory="DEVICE_CATEGORY_EXT_MEDIA">
+            <point>0,-4200</point>
+            <point>33,-2800</point>
+            <point>66,-1400</point>
+            <point>100,0</point>
+        </volume>
+    </volumeGroup>
+
+<!-- OEM ADAS is a volume group that has a single port gain (this is the reason why it is a group
+     but may host different streams.
+     A priority must be given among them (either they are multualy excluisve, so the volume
+     will be the one of the currently acitve stream, otherwise a priority must be given by
+     any mean. -->
+    <volumeGroup>
+        <name>oem_adas_2</name>
+        <indexMin>0</indexMin>
+        <indexMax>40</indexMax>
+        <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+            <point>0,-4200</point>
+            <point>33,-2800</point>
+            <point>66,-1400</point>
+            <point>100,0</point>
+        </volume>
+        <volume deviceCategory="DEVICE_CATEGORY_HEADSET">
+            <point>0,-4200</point>
+            <point>33,-2800</point>
+            <point>66,-1400</point>
+            <point>100,0</point>
+        </volume>
+    </volumeGroup>
+    <volumeGroup>
+        <name>oem_adas_3</name>
+        <indexMin>0</indexMin>
+        <indexMax>40</indexMax>
+        <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+            <point>0,-2400</point>
+            <point>33,-1600</point>
+            <point>66,-800</point>
+            <point>100,0</point>
+        </volume>
+        <volume deviceCategory="DEVICE_CATEGORY_EARPIECE">
+            <point>0,-2400</point>
+            <point>33,-1600</point>
+            <point>66,-800</point>
+            <point>100,0</point>
+        </volume>
+    </volumeGroup>
+
+<!-- MEDIA is a volume group that has a single port gain (this is the reason why it is a group
+     but may host different streams.
+     A priority must be given among them (either they are multualy exclusive, so the volume
+     will be the one of the active stream with highest priority (ORDER MATTERS) unless the curves
+     followed will the the curves for the requested attributes.-->
+    <volumeGroup>
+        <name>media_car_audio_type_3</name>
+        <indexMin>0</indexMin>
+        <indexMax>40</indexMax>
+        <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+            <point>0,-4200</point>
+            <point>33,-2800</point>
+            <point>66,-1400</point>
+            <point>100,0</point>
+        </volume>
+    </volumeGroup>
+    <volumeGroup>
+        <name>media_car_audio_type_7</name>
+        <indexMin>0</indexMin>
+        <indexMax>40</indexMax>
+        <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+            <point>0,-2400</point>
+            <point>33,-1600</point>
+            <point>66,-800</point>
+            <point>100,0</point>
+        </volume>
+    </volumeGroup>
+    <volumeGroup>
+        <name>media</name>
+        <indexMin>0</indexMin>
+        <indexMax>40</indexMax>
+        <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+            <point>0,-2400</point>
+            <point>33,-1600</point>
+            <point>66,-800</point>
+            <point>100,0</point>
+        </volume>
+    </volumeGroup>
+
+    <volumeGroup>
+        <name>speech</name>
+        <indexMin>1</indexMin>
+        <indexMax>40</indexMax>
+        <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+            <point>0,-4200</point>
+            <point>33,-2800</point>
+            <point>66,-1400</point>
+            <point>100,0</point>
+        </volume>
+    </volumeGroup>
+
+    <volumeGroup>
+        <name>system</name>
+        <indexMin>0</indexMin>
+        <indexMax>40</indexMax>
+        <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+            <point>0,-4200</point>
+            <point>33,-2800</point>
+            <point>66,-1400</point>
+            <point>100,0</point>
+        </volume>
+    </volumeGroup>
+
+    <volumeGroup>
+        <name>phone</name>
+        <indexMin>1</indexMin>
+        <indexMax>40</indexMax>
+        <volume  deviceCategory="DEVICE_CATEGORY_SPEAKER">
+            <point>0,-4200</point>
+            <point>33,-2800</point>
+            <point>66,-1400</point>
+            <point>100,0</point>
+        </volume>
+    </volumeGroup>
+
+    <volumeGroup>
+        <name>ring</name>
+        <indexMin>0</indexMin>
+        <indexMax>40</indexMax>
+        <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+            <point>0,-4200</point>
+            <point>33,-2800</point>
+            <point>66,-1400</point>
+            <point>100,0</point>
+        </volume>
+    </volumeGroup>
+
+    <volumeGroup>
+        <name>tts</name>
+        <indexMin>0</indexMin>
+        <indexMax>15</indexMax>
+        <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+            <point>0,-0</point>
+            <point>100,0</point>
+        </volume>
+    </volumeGroup>
+</volumeGroups>
+
diff --git a/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_product_strategies.xml b/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_product_strategies.xml
index f72e379..9398743 100644
--- a/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_product_strategies.xml
+++ b/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_product_strategies.xml
@@ -25,37 +25,37 @@
          enforced. -->
 
     <ProductStrategy name="STRATEGY_PHONE">
-        <AttributesGroup streamType="AUDIO_STREAM_VOICE_CALL">
+        <AttributesGroup streamType="AUDIO_STREAM_VOICE_CALL" volumeGroup="voice_call">
             <Attributes> <Usage value="AUDIO_USAGE_VOICE_COMMUNICATION"/> </Attributes>
         </AttributesGroup>
-        <AttributesGroup streamType="AUDIO_STREAM_BLUETOOTH_SCO">
+        <AttributesGroup streamType="AUDIO_STREAM_BLUETOOTH_SCO" volumeGroup="bluetooth_sco">
             <Attributes> <Flags value="AUDIO_FLAG_SCO"/> </Attributes>
         </AttributesGroup>
     </ProductStrategy>
 
     <ProductStrategy name="STRATEGY_SONIFICATION">
-        <AttributesGroup streamType="AUDIO_STREAM_RING">
+        <AttributesGroup streamType="AUDIO_STREAM_RING" volumeGroup="ring">
             <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE"/> </Attributes>
         </AttributesGroup>
-        <AttributesGroup streamType="AUDIO_STREAM_ALARM">
+        <AttributesGroup streamType="AUDIO_STREAM_ALARM" volumeGroup="alarm">
             <Attributes> <Usage value="AUDIO_USAGE_ALARM"/> </Attributes>
         </AttributesGroup>
     </ProductStrategy>
 
     <ProductStrategy name="STRATEGY_ENFORCED_AUDIBLE">
-        <AttributesGroup streamType="AUDIO_STREAM_ENFORCED_AUDIBLE">
+        <AttributesGroup streamType="AUDIO_STREAM_ENFORCED_AUDIBLE" volumeGroup="enforced_audible">
             <Attributes> <Flags value="AUDIO_FLAG_AUDIBILITY_ENFORCED"/> </Attributes>
         </AttributesGroup>
     </ProductStrategy>
 
     <ProductStrategy name="STRATEGY_ACCESSIBILITY">
-        <AttributesGroup streamType="AUDIO_STREAM_ACCESSIBILITY">
+        <AttributesGroup streamType="AUDIO_STREAM_ACCESSIBILITY" volumeGroup="accessibility">
             <Attributes> <Usage value="AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY"/> </Attributes>
         </AttributesGroup>
     </ProductStrategy>
 
     <ProductStrategy name="STRATEGY_SONIFICATION_RESPECTFUL">
-        <AttributesGroup streamType="AUDIO_STREAM_NOTIFICATION">
+        <AttributesGroup streamType="AUDIO_STREAM_NOTIFICATION" volumeGroup="notification">
             <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION"/> </Attributes>
             <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST"/> </Attributes>
             <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT"/> </Attributes>
@@ -65,20 +65,20 @@
     </ProductStrategy>
 
     <ProductStrategy name="STRATEGY_MEDIA">
-         <AttributesGroup streamType="AUDIO_STREAM_MUSIC">
+         <AttributesGroup streamType="AUDIO_STREAM_MUSIC" volumeGroup="music">
             <Attributes> <Usage value="AUDIO_USAGE_MEDIA"/> </Attributes>
             <Attributes> <Usage value="AUDIO_USAGE_GAME"/> </Attributes>
             <Attributes> <Usage value="AUDIO_USAGE_ASSISTANT"/> </Attributes>
             <Attributes> <Usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/> </Attributes>
             <Attributes></Attributes>
         </AttributesGroup>
-        <AttributesGroup streamType="AUDIO_STREAM_SYSTEM">
+        <AttributesGroup streamType="AUDIO_STREAM_SYSTEM" volumeGroup="system">
             <Attributes> <Usage value="AUDIO_USAGE_ASSISTANCE_SONIFICATION"/> </Attributes>
         </AttributesGroup>
     </ProductStrategy>
 
     <ProductStrategy name="STRATEGY_DTMF">
-        <AttributesGroup streamType="AUDIO_STREAM_DTMF">
+        <AttributesGroup streamType="AUDIO_STREAM_DTMF" volumeGroup="dtmf">
             <Attributes> <Usage value="AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING"/> </Attributes>
         </AttributesGroup>
     </ProductStrategy>
@@ -86,21 +86,21 @@
     <!-- Used to identify the volume of audio streams exclusively transmitted through the  speaker
          (TTS) of the device -->
     <ProductStrategy name="STRATEGY_TRANSMITTED_THROUGH_SPEAKER">
-        <AttributesGroup streamType="AUDIO_STREAM_TTS">
+        <AttributesGroup streamType="AUDIO_STREAM_TTS" volumeGroup="tts">
             <Attributes> <Flags value="AUDIO_FLAG_BEACON"/> </Attributes>
         </AttributesGroup>
     </ProductStrategy>
 
     <!-- Routing Strategy rerouting may be removed as following media??? -->
     <ProductStrategy name="STRATEGY_REROUTING">
-        <AttributesGroup streamType="AUDIO_STREAM_REROUTING">
+        <AttributesGroup streamType="AUDIO_STREAM_REROUTING" volumeGroup="rerouting">
             <Attributes></Attributes>
         </AttributesGroup>
     </ProductStrategy>
 
     <!-- Default product strategy has empty attributes -->
     <ProductStrategy name="STRATEGY_PATCH">
-        <AttributesGroup streamType="AUDIO_STREAM_PATCH">
+        <AttributesGroup streamType="AUDIO_STREAM_PATCH" volumeGroup="patch">
             <Attributes></Attributes>
         </AttributesGroup>
     </ProductStrategy>
diff --git a/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_stream_volumes.xml b/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_stream_volumes.xml
index 73bde1f..707a184 100644
--- a/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_stream_volumes.xml
+++ b/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_stream_volumes.xml
@@ -16,7 +16,7 @@
 <!-- Volume section defines a volume curve for a given use case and device category.
 It contains a list of points of this curve expressing the attenuation in Millibels for a given
 volume index from 0 to 100.
-<volume stream=”AUDIO_STREAM_MUSIC” deviceCategory=””>
+<volume deviceCategory=””>
 <point>0,-9600</point>
 <point>100,0</point>
 </volume>
@@ -24,7 +24,7 @@
 
 <volumeGroups>
     <volumeGroup>
-        <stream>AUDIO_STREAM_VOICE_CALL</stream>
+        <name>voice_call</name>
         <indexMin>1</indexMin>
         <indexMax>7</indexMax>
         <volume deviceCategory="DEVICE_CATEGORY_HEADSET">
@@ -50,7 +50,7 @@
     </volumeGroup>
 
     <volumeGroup>
-        <stream>AUDIO_STREAM_SYSTEM</stream>
+        <name>system</name>
         <indexMin>0</indexMin>
         <indexMax>7</indexMax>
         <volume deviceCategory="DEVICE_CATEGORY_HEADSET">
@@ -73,7 +73,7 @@
     </volumeGroup>
 
     <volumeGroup>
-        <stream>AUDIO_STREAM_RING</stream>
+        <name>ring</name>
         <indexMin>0</indexMin>
         <indexMax>7</indexMax>
         <volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_DEVICE_CATEGORY_HEADSET_VOLUME_CURVE"/>
@@ -84,7 +84,7 @@
     </volumeGroup>
 
     <volumeGroup>
-        <stream>AUDIO_STREAM_MUSIC</stream>
+        <name>music</name>
         <indexMin>0</indexMin>
         <indexMax>25</indexMax>
         <volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
@@ -95,7 +95,7 @@
     </volumeGroup>
 
     <volumeGroup>
-        <stream>AUDIO_STREAM_ALARM</stream>
+        <name>alarm</name>
         <indexMin>1</indexMin>
         <indexMax>7</indexMax>
         <volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_NON_MUTABLE_HEADSET_VOLUME_CURVE"/>
@@ -106,7 +106,7 @@
     </volumeGroup>
 
     <volumeGroup>
-        <stream>AUDIO_STREAM_NOTIFICATION</stream>
+        <name>notification</name>
         <indexMin>0</indexMin>
         <indexMax>7</indexMax>
         <volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_DEVICE_CATEGORY_HEADSET_VOLUME_CURVE"/>
@@ -117,7 +117,7 @@
     </volumeGroup>
 
     <volumeGroup>
-        <stream>AUDIO_STREAM_BLUETOOTH_SCO</stream>
+        <name>bluetooth_sco</name>
         <indexMin>0</indexMin>
         <indexMax>15</indexMax>
         <volume deviceCategory="DEVICE_CATEGORY_HEADSET">
@@ -143,7 +143,7 @@
     </volumeGroup>
 
     <volumeGroup>
-        <stream>AUDIO_STREAM_ENFORCED_AUDIBLE</stream>
+        <name>enforced_audible</name>
         <indexMin>0</indexMin>
         <indexMax>7</indexMax>
         <volume deviceCategory="DEVICE_CATEGORY_HEADSET">
@@ -164,7 +164,7 @@
     </volumeGroup>
 
     <volumeGroup>
-        <stream>AUDIO_STREAM_DTMF</stream>
+        <name>dtmf</name>
         <indexMin>0</indexMin>
         <indexMax>15</indexMax>
         <volume deviceCategory="DEVICE_CATEGORY_HEADSET">
@@ -185,7 +185,7 @@
     </volumeGroup>
 
     <volumeGroup>
-        <stream>AUDIO_STREAM_TTS</stream>
+        <name>tts</name>
         <indexMin>0</indexMin>
         <indexMax>15</indexMax>
         <volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="SILENT_VOLUME_CURVE"/>
@@ -196,7 +196,7 @@
     </volumeGroup>
 
     <volumeGroup>
-        <stream>AUDIO_STREAM_ACCESSIBILITY</stream>
+        <name>accessibility</name>
         <indexMin>1</indexMin>
         <indexMax>15</indexMax>
         <volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_NON_MUTABLE_VOLUME_CURVE"/>
@@ -207,7 +207,7 @@
     </volumeGroup>
 
     <volumeGroup>
-        <stream>AUDIO_STREAM_REROUTING</stream>
+        <name>rerouting</name>
         <indexMin>0</indexMin>
         <indexMax>1</indexMax>
         <volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="FULL_SCALE_VOLUME_CURVE"/>
@@ -218,7 +218,7 @@
     </volumeGroup>
 
     <volumeGroup>
-        <stream>AUDIO_STREAM_PATCH</stream>
+        <name>patch</name>
         <indexMin>0</indexMin>
         <indexMax>1</indexMax>
         <volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="FULL_SCALE_VOLUME_CURVE"/>
diff --git a/services/audiopolicy/enginedefault/Android.mk b/services/audiopolicy/enginedefault/Android.mk
index 94fa788..ebf383b 100644
--- a/services/audiopolicy/enginedefault/Android.mk
+++ b/services/audiopolicy/enginedefault/Android.mk
@@ -9,9 +9,9 @@
     src/Engine.cpp \
     src/EngineInstance.cpp \
     ../engine/common/src/VolumeCurve.cpp \
-    ../engine/common/src/StreamVolumeCurves.cpp \
     ../engine/common/src/ProductStrategy.cpp \
-    ../engine/common/src/EngineBase.cpp
+    ../engine/common/src/EngineBase.cpp \
+    ../engine/common/src/VolumeGroup.cpp
 
 audio_policy_engine_includes_common := \
     $(LOCAL_PATH)/include
diff --git a/services/audiopolicy/enginedefault/config/example/phone/audio_policy_engine_product_strategies.xml b/services/audiopolicy/enginedefault/config/example/phone/audio_policy_engine_product_strategies.xml
index f72e379..9398743 100644
--- a/services/audiopolicy/enginedefault/config/example/phone/audio_policy_engine_product_strategies.xml
+++ b/services/audiopolicy/enginedefault/config/example/phone/audio_policy_engine_product_strategies.xml
@@ -25,37 +25,37 @@
          enforced. -->
 
     <ProductStrategy name="STRATEGY_PHONE">
-        <AttributesGroup streamType="AUDIO_STREAM_VOICE_CALL">
+        <AttributesGroup streamType="AUDIO_STREAM_VOICE_CALL" volumeGroup="voice_call">
             <Attributes> <Usage value="AUDIO_USAGE_VOICE_COMMUNICATION"/> </Attributes>
         </AttributesGroup>
-        <AttributesGroup streamType="AUDIO_STREAM_BLUETOOTH_SCO">
+        <AttributesGroup streamType="AUDIO_STREAM_BLUETOOTH_SCO" volumeGroup="bluetooth_sco">
             <Attributes> <Flags value="AUDIO_FLAG_SCO"/> </Attributes>
         </AttributesGroup>
     </ProductStrategy>
 
     <ProductStrategy name="STRATEGY_SONIFICATION">
-        <AttributesGroup streamType="AUDIO_STREAM_RING">
+        <AttributesGroup streamType="AUDIO_STREAM_RING" volumeGroup="ring">
             <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE"/> </Attributes>
         </AttributesGroup>
-        <AttributesGroup streamType="AUDIO_STREAM_ALARM">
+        <AttributesGroup streamType="AUDIO_STREAM_ALARM" volumeGroup="alarm">
             <Attributes> <Usage value="AUDIO_USAGE_ALARM"/> </Attributes>
         </AttributesGroup>
     </ProductStrategy>
 
     <ProductStrategy name="STRATEGY_ENFORCED_AUDIBLE">
-        <AttributesGroup streamType="AUDIO_STREAM_ENFORCED_AUDIBLE">
+        <AttributesGroup streamType="AUDIO_STREAM_ENFORCED_AUDIBLE" volumeGroup="enforced_audible">
             <Attributes> <Flags value="AUDIO_FLAG_AUDIBILITY_ENFORCED"/> </Attributes>
         </AttributesGroup>
     </ProductStrategy>
 
     <ProductStrategy name="STRATEGY_ACCESSIBILITY">
-        <AttributesGroup streamType="AUDIO_STREAM_ACCESSIBILITY">
+        <AttributesGroup streamType="AUDIO_STREAM_ACCESSIBILITY" volumeGroup="accessibility">
             <Attributes> <Usage value="AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY"/> </Attributes>
         </AttributesGroup>
     </ProductStrategy>
 
     <ProductStrategy name="STRATEGY_SONIFICATION_RESPECTFUL">
-        <AttributesGroup streamType="AUDIO_STREAM_NOTIFICATION">
+        <AttributesGroup streamType="AUDIO_STREAM_NOTIFICATION" volumeGroup="notification">
             <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION"/> </Attributes>
             <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST"/> </Attributes>
             <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT"/> </Attributes>
@@ -65,20 +65,20 @@
     </ProductStrategy>
 
     <ProductStrategy name="STRATEGY_MEDIA">
-         <AttributesGroup streamType="AUDIO_STREAM_MUSIC">
+         <AttributesGroup streamType="AUDIO_STREAM_MUSIC" volumeGroup="music">
             <Attributes> <Usage value="AUDIO_USAGE_MEDIA"/> </Attributes>
             <Attributes> <Usage value="AUDIO_USAGE_GAME"/> </Attributes>
             <Attributes> <Usage value="AUDIO_USAGE_ASSISTANT"/> </Attributes>
             <Attributes> <Usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/> </Attributes>
             <Attributes></Attributes>
         </AttributesGroup>
-        <AttributesGroup streamType="AUDIO_STREAM_SYSTEM">
+        <AttributesGroup streamType="AUDIO_STREAM_SYSTEM" volumeGroup="system">
             <Attributes> <Usage value="AUDIO_USAGE_ASSISTANCE_SONIFICATION"/> </Attributes>
         </AttributesGroup>
     </ProductStrategy>
 
     <ProductStrategy name="STRATEGY_DTMF">
-        <AttributesGroup streamType="AUDIO_STREAM_DTMF">
+        <AttributesGroup streamType="AUDIO_STREAM_DTMF" volumeGroup="dtmf">
             <Attributes> <Usage value="AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING"/> </Attributes>
         </AttributesGroup>
     </ProductStrategy>
@@ -86,21 +86,21 @@
     <!-- Used to identify the volume of audio streams exclusively transmitted through the  speaker
          (TTS) of the device -->
     <ProductStrategy name="STRATEGY_TRANSMITTED_THROUGH_SPEAKER">
-        <AttributesGroup streamType="AUDIO_STREAM_TTS">
+        <AttributesGroup streamType="AUDIO_STREAM_TTS" volumeGroup="tts">
             <Attributes> <Flags value="AUDIO_FLAG_BEACON"/> </Attributes>
         </AttributesGroup>
     </ProductStrategy>
 
     <!-- Routing Strategy rerouting may be removed as following media??? -->
     <ProductStrategy name="STRATEGY_REROUTING">
-        <AttributesGroup streamType="AUDIO_STREAM_REROUTING">
+        <AttributesGroup streamType="AUDIO_STREAM_REROUTING" volumeGroup="rerouting">
             <Attributes></Attributes>
         </AttributesGroup>
     </ProductStrategy>
 
     <!-- Default product strategy has empty attributes -->
     <ProductStrategy name="STRATEGY_PATCH">
-        <AttributesGroup streamType="AUDIO_STREAM_PATCH">
+        <AttributesGroup streamType="AUDIO_STREAM_PATCH" volumeGroup="patch">
             <Attributes></Attributes>
         </AttributesGroup>
     </ProductStrategy>
diff --git a/services/audiopolicy/enginedefault/config/example/phone/audio_policy_engine_stream_volumes.xml b/services/audiopolicy/enginedefault/config/example/phone/audio_policy_engine_stream_volumes.xml
index 73bde1f..707a184 100644
--- a/services/audiopolicy/enginedefault/config/example/phone/audio_policy_engine_stream_volumes.xml
+++ b/services/audiopolicy/enginedefault/config/example/phone/audio_policy_engine_stream_volumes.xml
@@ -16,7 +16,7 @@
 <!-- Volume section defines a volume curve for a given use case and device category.
 It contains a list of points of this curve expressing the attenuation in Millibels for a given
 volume index from 0 to 100.
-<volume stream=”AUDIO_STREAM_MUSIC” deviceCategory=””>
+<volume deviceCategory=””>
 <point>0,-9600</point>
 <point>100,0</point>
 </volume>
@@ -24,7 +24,7 @@
 
 <volumeGroups>
     <volumeGroup>
-        <stream>AUDIO_STREAM_VOICE_CALL</stream>
+        <name>voice_call</name>
         <indexMin>1</indexMin>
         <indexMax>7</indexMax>
         <volume deviceCategory="DEVICE_CATEGORY_HEADSET">
@@ -50,7 +50,7 @@
     </volumeGroup>
 
     <volumeGroup>
-        <stream>AUDIO_STREAM_SYSTEM</stream>
+        <name>system</name>
         <indexMin>0</indexMin>
         <indexMax>7</indexMax>
         <volume deviceCategory="DEVICE_CATEGORY_HEADSET">
@@ -73,7 +73,7 @@
     </volumeGroup>
 
     <volumeGroup>
-        <stream>AUDIO_STREAM_RING</stream>
+        <name>ring</name>
         <indexMin>0</indexMin>
         <indexMax>7</indexMax>
         <volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_DEVICE_CATEGORY_HEADSET_VOLUME_CURVE"/>
@@ -84,7 +84,7 @@
     </volumeGroup>
 
     <volumeGroup>
-        <stream>AUDIO_STREAM_MUSIC</stream>
+        <name>music</name>
         <indexMin>0</indexMin>
         <indexMax>25</indexMax>
         <volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
@@ -95,7 +95,7 @@
     </volumeGroup>
 
     <volumeGroup>
-        <stream>AUDIO_STREAM_ALARM</stream>
+        <name>alarm</name>
         <indexMin>1</indexMin>
         <indexMax>7</indexMax>
         <volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_NON_MUTABLE_HEADSET_VOLUME_CURVE"/>
@@ -106,7 +106,7 @@
     </volumeGroup>
 
     <volumeGroup>
-        <stream>AUDIO_STREAM_NOTIFICATION</stream>
+        <name>notification</name>
         <indexMin>0</indexMin>
         <indexMax>7</indexMax>
         <volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_DEVICE_CATEGORY_HEADSET_VOLUME_CURVE"/>
@@ -117,7 +117,7 @@
     </volumeGroup>
 
     <volumeGroup>
-        <stream>AUDIO_STREAM_BLUETOOTH_SCO</stream>
+        <name>bluetooth_sco</name>
         <indexMin>0</indexMin>
         <indexMax>15</indexMax>
         <volume deviceCategory="DEVICE_CATEGORY_HEADSET">
@@ -143,7 +143,7 @@
     </volumeGroup>
 
     <volumeGroup>
-        <stream>AUDIO_STREAM_ENFORCED_AUDIBLE</stream>
+        <name>enforced_audible</name>
         <indexMin>0</indexMin>
         <indexMax>7</indexMax>
         <volume deviceCategory="DEVICE_CATEGORY_HEADSET">
@@ -164,7 +164,7 @@
     </volumeGroup>
 
     <volumeGroup>
-        <stream>AUDIO_STREAM_DTMF</stream>
+        <name>dtmf</name>
         <indexMin>0</indexMin>
         <indexMax>15</indexMax>
         <volume deviceCategory="DEVICE_CATEGORY_HEADSET">
@@ -185,7 +185,7 @@
     </volumeGroup>
 
     <volumeGroup>
-        <stream>AUDIO_STREAM_TTS</stream>
+        <name>tts</name>
         <indexMin>0</indexMin>
         <indexMax>15</indexMax>
         <volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="SILENT_VOLUME_CURVE"/>
@@ -196,7 +196,7 @@
     </volumeGroup>
 
     <volumeGroup>
-        <stream>AUDIO_STREAM_ACCESSIBILITY</stream>
+        <name>accessibility</name>
         <indexMin>1</indexMin>
         <indexMax>15</indexMax>
         <volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_NON_MUTABLE_VOLUME_CURVE"/>
@@ -207,7 +207,7 @@
     </volumeGroup>
 
     <volumeGroup>
-        <stream>AUDIO_STREAM_REROUTING</stream>
+        <name>rerouting</name>
         <indexMin>0</indexMin>
         <indexMax>1</indexMax>
         <volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="FULL_SCALE_VOLUME_CURVE"/>
@@ -218,7 +218,7 @@
     </volumeGroup>
 
     <volumeGroup>
-        <stream>AUDIO_STREAM_PATCH</stream>
+        <name>patch</name>
         <indexMin>0</indexMin>
         <indexMax>1</indexMax>
         <volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="FULL_SCALE_VOLUME_CURVE"/>
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index dc5b801..4540c4d 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -377,7 +377,7 @@
                                            (strlen(device_address) != 0)/*matchAddress*/);
 
     if (devDesc == 0) {
-        ALOGW("getDeviceConnectionState() undeclared device, type %08x, address: %s",
+        ALOGV("getDeviceConnectionState() undeclared device, type %08x, address: %s",
               device, device_address);
         return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
     }
@@ -2373,16 +2373,13 @@
     }
 }
 
-void AudioPolicyManager::initStreamVolume(audio_stream_type_t stream,
-                                            int indexMin,
-                                            int indexMax)
+void AudioPolicyManager::initStreamVolume(audio_stream_type_t stream, int indexMin, int indexMax)
 {
     ALOGV("initStreamVolume() stream %d, min %d, max %d", stream , indexMin, indexMax);
     if (indexMin < 0 || indexMax < 0) {
         ALOGE("%s for stream %d: invalid min %d or max %d", __func__, stream , indexMin, indexMax);
         return;
     }
-    // @todo: our proposal now use XML to store Indexes Min & Max
     getVolumeCurves(stream).initVolume(indexMin, indexMax);
 
     // initialize other private stream volumes which follow this one
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 06a1f3e..3e4d885 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -143,9 +143,17 @@
         virtual status_t stopInput(audio_port_handle_t portId);
         virtual void releaseInput(audio_port_handle_t portId);
         virtual void closeAllInputs();
-        virtual void initStreamVolume(audio_stream_type_t stream,
-                                                    int indexMin,
-                                                    int indexMax);
+        /**
+         * @brief initStreamVolume: even if the engine volume files provides min and max, keep this
+         * api for compatibility reason.
+         * AudioServer will get the min and max and may overwrite them if:
+         *      -using property (highest priority)
+         *      -not defined (-1 by convention), case when still using apm volume tables XML files
+         * @param stream to be considered
+         * @param indexMin to set
+         * @param indexMax to set
+         */
+        virtual void initStreamVolume(audio_stream_type_t stream, int indexMin, int indexMax);
         virtual status_t setStreamVolumeIndex(audio_stream_type_t stream,
                                               int index,
                                               audio_devices_t device);