Audio policy: implement configuration file in XML

This patch introduces configuration file of the policy in XML.
Legacy configuration file is used by default and
compilation flag USE_XML_AUDIO_POLICY_CONF must be defined to
use XML file format.

Change-Id: I352b788b5829d42ed82c851a4faef0e526be582e
Signed-off-by: François Gaffie <francois.gaffie@intel.com>
diff --git a/services/audiopolicy/Android.mk b/services/audiopolicy/Android.mk
index 671d7fb..0f3f138 100644
--- a/services/audiopolicy/Android.mk
+++ b/services/audiopolicy/Android.mk
@@ -67,12 +67,16 @@
 
 ifeq ($(USE_CONFIGURABLE_AUDIO_POLICY), 1)
 
+ifneq ($(USE_XML_AUDIO_POLICY_CONF), 1)
+$(error Configurable policy does not support legacy conf file)
+endif #ifneq ($(USE_XML_AUDIO_POLICY_CONF), 1)
+
 LOCAL_REQUIRED_MODULES := \
     parameter-framework.policy \
     audio_policy_criteria.conf \
 
 LOCAL_C_INCLUDES += \
-    $(TOPDIR)frameworks/av/services/audiopolicy/engineconfigurable/include \
+    $(TOPDIR)frameworks/av/services/audiopolicy/engineconfigurable/include
 
 LOCAL_SHARED_LIBRARIES += libaudiopolicyengineconfigurable
 
@@ -85,12 +89,20 @@
 LOCAL_C_INCLUDES += \
     $(TOPDIR)frameworks/av/services/audiopolicy/common/include \
     $(TOPDIR)frameworks/av/services/audiopolicy/engine/interface \
-    $(TOPDIR)frameworks/av/services/audiopolicy/utilities \
+    $(TOPDIR)frameworks/av/services/audiopolicy/utilities
 
 LOCAL_STATIC_LIBRARIES := \
     libmedia_helper \
     libaudiopolicycomponents
 
+ifeq ($(USE_XML_AUDIO_POLICY_CONF), 1)
+LOCAL_STATIC_LIBRARIES += libxml2
+
+LOCAL_SHARED_LIBRARIES += libicuuc
+
+LOCAL_CFLAGS += -DUSE_XML_AUDIO_POLICY_CONF
+endif #ifeq ($(USE_XML_AUDIO_POLICY_CONF), 1)
+
 LOCAL_MODULE:= libaudiopolicymanagerdefault
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/services/audiopolicy/common/managerdefinitions/Android.mk b/services/audiopolicy/common/managerdefinitions/Android.mk
index 0c28fc9..429f20a 100644
--- a/services/audiopolicy/common/managerdefinitions/Android.mk
+++ b/services/audiopolicy/common/managerdefinitions/Android.mk
@@ -17,7 +17,6 @@
     src/AudioOutputDescriptor.cpp \
     src/AudioCollections.cpp \
     src/EffectDescriptor.cpp \
-    src/ConfigParsingUtils.cpp \
     src/SoundTriggerSession.cpp \
     src/SessionRoute.cpp \
     src/AudioSourceDescriptor.cpp \
@@ -29,12 +28,27 @@
     libutils \
     liblog \
 
-LOCAL_C_INCLUDES += \
+LOCAL_C_INCLUDES := \
     $(LOCAL_PATH)/include \
     $(TOPDIR)frameworks/av/services/audiopolicy/common/include \
     $(TOPDIR)frameworks/av/services/audiopolicy \
     $(TOPDIR)frameworks/av/services/audiopolicy/utilities \
 
+ifeq ($(USE_XML_AUDIO_POLICY_CONF), 1)
+LOCAL_SRC_FILES += src/Serializer.cpp
+
+LOCAL_STATIC_LIBRARIES := libxml2
+
+LOCAL_SHARED_LIBRARIES += libicuuc
+
+LOCAL_C_INCLUDES += \
+    $(TOPDIR)external/libxml2/include \
+    $(TOPDIR)external/icu/icu4c/source/common
+
+else
+LOCAL_SRC_FILES += src/ConfigParsingUtils.cpp
+endif #ifeq ($(USE_XML_AUDIO_POLICY_CONF), 1)
+
 LOCAL_EXPORT_C_INCLUDE_DIRS := \
     $(LOCAL_PATH)/include
 
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioCollections.h b/services/audiopolicy/common/managerdefinitions/include/AudioCollections.h
index 814c5c2..8f00d22 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioCollections.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioCollections.h
@@ -38,7 +38,7 @@
 class AudioRouteVector : public Vector<sp<AudioRoute> >
 {
 public:
-    status_t dump(int fd) const;
+    status_t dump(int fd, int spaces) const;
 };
 
 }; // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
index 20c0e36..6959420 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #include <AudioGain.h>
+#include <VolumeCurve.h>
 #include <AudioPort.h>
 #include <AudioPatch.h>
 #include <DeviceDescriptor.h>
@@ -52,6 +53,15 @@
         mHwModules = hwModules;
     }
 
+    void addAvailableDevice(const sp<DeviceDescriptor> &availableDevice)
+    {
+        if (audio_is_output_device(availableDevice->type())) {
+            mAvailableOutputDevices.add(availableDevice);
+        } else if (audio_is_input_device(availableDevice->type())) {
+            mAvailableInputDevices.add(availableDevice);
+        }
+    }
+
     void addAvailableInputDevices(const DeviceVector &availableInputDevices)
     {
         mAvailableInputDevices.add(availableInputDevices);
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
index 12e42ea..32cb600 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
@@ -51,7 +51,16 @@
     void setGains(const AudioGainCollection &gains) { mGains = gains; }
     const AudioGainCollection &getGains() const { return mGains; }
 
-    void setFlags(uint32_t flags) { mFlags = flags; }
+    void setFlags(uint32_t flags)
+    {
+        //force direct flag if offload flag is set: offloading implies a direct output stream
+        // and all common behaviors are driven by checking only the direct flag
+        // this should normally be set appropriately in the policy configuration file
+        if (mRole == AUDIO_PORT_ROLE_SOURCE && (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
+            flags |= AUDIO_OUTPUT_FLAG_DIRECT;
+        }
+        mFlags = flags;
+    }
     uint32_t getFlags() const { return mFlags; }
 
     virtual void attach(const sp<HwModule>& module);
diff --git a/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h b/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h
index ab23105..ee95ceb 100644
--- a/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h
+++ b/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h
@@ -40,7 +40,6 @@
     static status_t loadConfig(const char *path, AudioPolicyConfig &config);
 
 private:
-    static uint32_t parseOutputFlagNames(const char *name);
     static void loadAudioPortGain(cnode *root, AudioPort &audioPort, int index);
     static void loadAudioPortGains(cnode *root, AudioPort &audioPort);
     static void loadDeviceDescriptorGains(cnode *root, sp<DeviceDescriptor> &deviceDesc);
diff --git a/services/audiopolicy/common/managerdefinitions/include/Serializer.h b/services/audiopolicy/common/managerdefinitions/include/Serializer.h
new file mode 100644
index 0000000..b152dd5
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/include/Serializer.h
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "AudioPolicyConfig.h"
+#include <utils/StrongPointer.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <string>
+#include <sstream>
+#include <fstream>
+
+struct _xmlNode;
+struct _xmlDoc;
+
+namespace android {
+
+struct AudioGainTraits
+{
+    static const char *const tag;
+    static const char *const collectionTag;
+
+    struct Attributes
+    {
+        static const char mode[]; /**< gain modes supported, e.g. AUDIO_GAIN_MODE_CHANNELS. */
+        /** controlled channels, needed if mode AUDIO_GAIN_MODE_CHANNELS. */
+        static const char channelMask[];
+        static const char minValueMB[]; /**< min value in millibel. */
+        static const char maxValueMB[]; /**< max value in millibel. */
+        static const char defaultValueMB[]; /**< default value in millibel. */
+        static const char stepValueMB[]; /**< step value in millibel. */
+        static const char minRampMs[]; /**< needed if mode AUDIO_GAIN_MODE_RAMP. */
+        static const char maxRampMs[]; /**< .needed if mode AUDIO_GAIN_MODE_RAMP */
+    };
+
+    typedef AudioGain Element;
+    typedef sp<Element> PtrElement;
+    typedef AudioGainCollection Collection;
+    typedef void *PtrSerializingCtx;
+
+    static status_t deserialize(_xmlDoc *doc, const _xmlNode *root, PtrElement &element,
+                                PtrSerializingCtx serializingContext);
+
+    // Gain has no child
+};
+
+// A profile section contains a name,  one audio format and the list of supported sampling rates
+// and channel masks for this format
+struct AudioProfileTraits
+{
+    static const char *const tag;
+    static const char *const collectionTag;
+
+    struct Attributes
+    {
+        static const char name[];
+        static const char samplingRates[];
+        static const char format[];
+        static const char channelMasks[];
+    };
+
+    typedef AudioProfile Element;
+    typedef sp<AudioProfile> PtrElement;
+    typedef AudioProfileVector Collection;
+    typedef void *PtrSerializingCtx;
+
+    static status_t deserialize(_xmlDoc *doc, const _xmlNode *root, PtrElement &element,
+                                PtrSerializingCtx serializingContext);
+};
+
+struct MixPortTraits
+{
+    static const char *const tag;
+    static const char *const collectionTag;
+
+    struct Attributes
+    {
+        static const char name[];
+        static const char role[];
+        static const char flags[];
+    };
+
+    typedef IOProfile Element;
+    typedef sp<Element> PtrElement;
+    typedef IOProfileCollection Collection;
+    typedef void *PtrSerializingCtx;
+
+    static status_t deserialize(_xmlDoc *doc, const _xmlNode *root, PtrElement &element,
+                                PtrSerializingCtx serializingContext);
+
+    // Children are: GainTraits
+};
+
+struct DevicePortTraits
+{
+    static const char *const tag;
+    static const char *const collectionTag;
+
+    struct Attributes
+    {
+        static const char tagName[]; /**<  <device tag name>: any string without space. */
+        static const char type[]; /**< <device type>. */
+        static const char role[]; /**< <device role: sink or source>. */
+        static const char roleSource[]; /**< <attribute role source value>. */
+        static const char address[]; /**< optional: device address, char string less than 64. */
+    };
+    typedef DeviceDescriptor Element;
+    typedef sp<DeviceDescriptor> PtrElement;
+    typedef DeviceVector Collection;
+    typedef void *PtrSerializingCtx;
+
+    static status_t deserialize(_xmlDoc *doc, const _xmlNode *root, PtrElement &element,
+                                PtrSerializingCtx serializingContext);
+    // Children are: GainTraits (optionnal)
+};
+
+struct RouteTraits
+{
+    static const char *const tag;
+    static const char *const collectionTag;
+
+    struct Attributes
+    {
+        static const char type[]; /**< <route type>: mix or mux. */
+        static const char typeMix[]; /**< type attribute mix value. */
+        static const char sink[]; /**< <sink: involved in this route>. */
+        static const char sources[]; /**< sources: all source that can be involved in this route. */
+    };
+    typedef AudioRoute Element;
+    typedef sp<AudioRoute> PtrElement;
+    typedef AudioRouteVector Collection;
+    typedef HwModule *PtrSerializingCtx;
+
+    static status_t deserialize(_xmlDoc *doc, const _xmlNode *root, PtrElement &element,
+                                PtrSerializingCtx ctx);
+};
+
+struct ModuleTraits
+{
+    static const char *const tag;
+    static const char *const collectionTag;
+
+    static const char *const childAttachedDevicesTag;
+    static const char *const childAttachedDeviceTag;
+    static const char *const childDefaultOutputDeviceTag;
+
+    struct Attributes
+    {
+        static const char name[];
+        static const char version[];
+    };
+
+    typedef HwModule Element;
+    typedef sp<Element> PtrElement;
+    typedef HwModuleCollection Collection;
+    typedef AudioPolicyConfig *PtrSerializingCtx;
+
+    static status_t deserialize(_xmlDoc *doc, const _xmlNode *root, PtrElement &element,
+                                PtrSerializingCtx serializingContext);
+
+    // Children are: mixPortTraits, devicePortTraits and routeTraits
+    // Need to call deserialize on each child
+};
+
+struct GlobalConfigTraits
+{
+    static const char *const tag;
+
+    struct Attributes
+    {
+        static const char speakerDrcEnabled[];
+    };
+
+    static status_t deserialize(const _xmlNode *root, AudioPolicyConfig &config);
+};
+
+struct VolumeTraits
+{
+    static const char *const tag;
+    static const char *const collectionTag;
+    static const char *const volumePointTag;
+
+    struct Attributes
+    {
+        static const char stream[];
+        static const char deviceCategory[];
+    };
+
+    typedef VolumeCurve Element;
+    typedef sp<VolumeCurve> PtrElement;
+    typedef VolumeCurveCollection Collection;
+    typedef void *PtrSerializingCtx;
+
+    static status_t deserialize(_xmlDoc *doc, const _xmlNode *root, PtrElement &element,
+                                PtrSerializingCtx serializingContext);
+
+    // No Child
+};
+
+class PolicySerializer
+{
+private:
+    static const char *const rootName;
+
+    static const char *const versionAttribute;
+    static const uint32_t gMajor; /**< the major number of the policy xml format version. */
+    static const uint32_t gMinor; /**< the minor number of the policy xml format version. */
+
+public:
+    PolicySerializer();
+    status_t deserialize(const char *str, AudioPolicyConfig &config);
+
+private:
+    typedef AudioPolicyConfig Element;
+
+    std::string mRootElementName;
+    std::string mVersion;
+
+    // Children are: ModulesTraits, VolumeTraits
+};
+
+}; // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/TypeConverter.h b/services/audiopolicy/common/managerdefinitions/include/TypeConverter.h
index 14e2ecc..b828f81 100644
--- a/services/audiopolicy/common/managerdefinitions/include/TypeConverter.h
+++ b/services/audiopolicy/common/managerdefinitions/include/TypeConverter.h
@@ -149,6 +149,9 @@
 static audio_format_t formatFromString(const std::string &literalFormat)
 {
     audio_format_t format;
+    if (literalFormat.empty()) {
+        return gDynamicFormat;
+    }
     FormatConverter::fromString(literalFormat, format);
     return format;
 }
diff --git a/services/audiopolicy/common/managerdefinitions/include/VolumeCurve.h b/services/audiopolicy/common/managerdefinitions/include/VolumeCurve.h
new file mode 100644
index 0000000..cccf1c8
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/include/VolumeCurve.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <Volume.h>
+#include <hardware/audio.h>
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+#include <utils/Errors.h>
+#include <utils/Vector.h>
+#include <system/audio.h>
+#include <cutils/config_utils.h>
+#include <string>
+#include <utility>
+
+namespace android {
+
+typedef std::pair<uint32_t, uint32_t> CurvePoint;
+typedef Vector<CurvePoint> CurvePoints;
+
+class VolumeCurve : public RefBase
+{
+public:
+    void setStreamType(audio_stream_type_t streamType) { mStreamType = streamType; }
+    audio_stream_type_t getStreamType() const { return mStreamType; }
+
+    void setDeviceCategory(device_category devCat) { mDeviceCategory = devCat; }
+    device_category getDeviceCategory() const { return mDeviceCategory; }
+
+    void setCurvePoints(const CurvePoints &points) { mCurvePoints = points; }
+
+private:
+    CurvePoints mCurvePoints;
+    device_category mDeviceCategory;
+    audio_stream_type_t mStreamType;
+};
+
+typedef Vector<sp<VolumeCurve> > VolumeCurveCollection;
+
+}; // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioCollections.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioCollections.cpp
index f66af6b..635fe4d 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioCollections.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioCollections.cpp
@@ -37,15 +37,18 @@
     return port;
 }
 
-status_t AudioRouteVector::dump(int fd) const
+status_t AudioRouteVector::dump(int fd, int spaces) const
 {
+    if (isEmpty()) {
+        return NO_ERROR;
+    }
     const size_t SIZE = 256;
     char buffer[SIZE];
 
-    snprintf(buffer, SIZE, "\nAudio Route dump (%zu):\n", size());
+    snprintf(buffer, SIZE, "\n%*sAudio Routes (%zu):\n", spaces, "", size());
     write(fd, buffer, strlen(buffer));
     for (size_t i = 0; i < size(); i++) {
-        snprintf(buffer, SIZE, "- Route %zu:\n", i + 1);
+        snprintf(buffer, SIZE, "%*s- Route %zu:\n", spaces, "", i + 1);
         write(fd, buffer, strlen(buffer));
         itemAt(i)->dump(fd, 4);
     }
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
index cde0923..191439e 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
@@ -308,6 +308,8 @@
             }
         }
     }
+    ALOGV("%s Port[nm:%s] profile rate=%d, format=%d, channels=%d", __FUNCTION__, mName.string(),
+          samplingRate, channelMask, format);
 }
 
 status_t AudioPort::checkGain(const struct audio_gain_config *gainConfig, int index) const
@@ -324,7 +326,7 @@
     char buffer[SIZE];
     String8 result;
 
-    if (mName.length() != 0) {
+    if (!mName.isEmpty()) {
         snprintf(buffer, SIZE, "%*s- name: %s\n", spaces, "", mName.string());
         result.append(buffer);
         write(fd, result.string(), result.size());
@@ -334,7 +336,8 @@
 
         if (mGains.size() != 0) {
             snprintf(buffer, SIZE, "%*s- gains:\n", spaces, "");
-            write(fd, buffer, strlen(buffer) + 1);
+            result = buffer;
+            write(fd, result.string(), result.size());
             for (size_t i = 0; i < mGains.size(); i++) {
                 mGains[i]->dump(fd, spaces + 2, i);
             }
diff --git a/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp b/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp
index b187857..e3ff9ae 100644
--- a/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp
@@ -29,18 +29,6 @@
 namespace android {
 
 // --- audio_policy.conf file parsing
-//static
-uint32_t ConfigParsingUtils::parseOutputFlagNames(const char *name)
-{
-    uint32_t flag = OutputFlagConverter::maskFromString(name);
-    //force direct flag if offload flag is set: offloading implies a direct output stream
-    // and all common behaviors are driven by checking only the direct flag
-    // this should normally be set appropriately in the policy configuration file
-    if ((flag & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
-        flag |= AUDIO_OUTPUT_FLAG_DIRECT;
-    }
-    return flag;
-}
 
 //static
 void ConfigParsingUtils::loadAudioPortGain(cnode *root, AudioPort &audioPort, int index)
@@ -193,7 +181,7 @@
             if (role == AUDIO_PORT_ROLE_SINK) {
                 profile->setFlags(InputFlagConverter::maskFromString(node->value));
             } else {
-                profile->setFlags(ConfigParsingUtils::parseOutputFlagNames(node->value));
+                profile->setFlags(OutputFlagConverter::maskFromString(node->value));
             }
         } else if (strcmp(node->name, GAINS_TAG) == 0) {
             loadAudioPortGains(node, *profile);
diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
index 538876c..787f53f 100644
--- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
@@ -215,10 +215,10 @@
     const size_t SIZE = 256;
     char buffer[SIZE];
 
-    snprintf(buffer, SIZE, "%*s %s devices:\n", spaces, "", tag.string());
+    snprintf(buffer, SIZE, "%*s- %s devices:\n", spaces, "", tag.string());
     write(fd, buffer, strlen(buffer));
     for (size_t i = 0; i < size(); i++) {
-        itemAt(i)->dump(fd, spaces + 4, i, verbose);
+        itemAt(i)->dump(fd, spaces + 2, i, verbose);
     }
     return NO_ERROR;
 }
diff --git a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
index 93ab9c7..5bfe957 100644
--- a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
@@ -247,10 +247,7 @@
         }
     }
     mDeclaredDevices.dump(fd, String8("Declared"),  2, true);
-    if (!mRoutes.empty()) {
-        write(fd, "  - Audio Route:\n", strlen("  - Audio Route:\n"));
-        mRoutes.dump(fd);
-    }
+    mRoutes.dump(fd, 2);
 }
 
 sp <HwModule> HwModuleCollection::getModuleFromName(const char *name) const
diff --git a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
index 6e0a071..204eb04 100644
--- a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
@@ -111,7 +111,7 @@
     snprintf(buffer, SIZE, "    - flags: 0x%04x\n", getFlags());
     result.append(buffer);
     write(fd, result.string(), result.size());
-    mSupportedDevices.dump(fd, String8("- Supported"), 2, false);
+    mSupportedDevices.dump(fd, String8("Supported"), 4, false);
 }
 
 void IOProfile::log()
diff --git a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
new file mode 100644
index 0000000..77824df
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
@@ -0,0 +1,604 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "APM::Serializer"
+//#define LOG_NDEBUG 0
+
+#include "Serializer.h"
+#include <convert/convert.h>
+#include "TypeConverter.h"
+#include <libxml/parser.h>
+#include <libxml/xinclude.h>
+#include <string>
+#include <sstream>
+#include <istream>
+
+using std::string;
+
+namespace android {
+
+string getXmlAttribute(const xmlNode *cur, const char *attribute)
+{
+    xmlChar *xmlValue = xmlGetProp(cur, (const xmlChar*)attribute);
+    if (xmlValue == NULL) {
+        return "";
+    }
+    string value((const char*)xmlValue);
+    xmlFree(xmlValue);
+    return value;
+}
+
+using utilities::convertTo;
+
+const char *const PolicySerializer::rootName = "audioPolicyConfiguration";
+const char *const PolicySerializer::versionAttribute = "version";
+const uint32_t PolicySerializer::gMajor = 1;
+const uint32_t PolicySerializer::gMinor = 0;
+
+template <class Trait>
+static status_t deserializeCollection(_xmlDoc *doc, const _xmlNode *cur,
+                                      typename Trait::Collection &collection,
+                                      typename Trait::PtrSerializingCtx serializingContext)
+{
+    const xmlNode *root = cur->xmlChildrenNode;
+    while (root != NULL) {
+        if (xmlStrcmp(root->name, (const xmlChar *)Trait::collectionTag) &&
+                xmlStrcmp(root->name, (const xmlChar *)Trait::tag)) {
+            root = root->next;
+            continue;
+        }
+        if (!xmlStrcmp(root->name, (const xmlChar *)Trait::collectionTag)) {
+            root = root->xmlChildrenNode;
+        }
+        while (root != NULL) {
+            if (!xmlStrcmp(root->name, (const xmlChar *)Trait::tag)) {
+                typename Trait::PtrElement element;
+                status_t status = Trait::deserialize(doc, root, element, serializingContext);
+                if (status != NO_ERROR) {
+                    return status;
+                }
+                if (collection.add(element) < 0) {
+                    ALOGE("%s: could not add element to %s collection", __FUNCTION__,
+                          Trait::collectionTag);
+                }
+            }
+            root = root->next;
+        }
+        return NO_ERROR;
+    }
+    ALOGV("%s: No %s collection found", __FUNCTION__, Trait::collectionTag);
+    return BAD_VALUE;
+}
+
+const char *const AudioGainTraits::tag = "gain";
+const char *const AudioGainTraits::collectionTag = "gains";
+
+const char AudioGainTraits::Attributes::mode[] = "mode";
+const char AudioGainTraits::Attributes::channelMask[] = "channel_mask";
+const char AudioGainTraits::Attributes::minValueMB[] = "minValueMB";
+const char AudioGainTraits::Attributes::maxValueMB[] = "maxValueMB";
+const char AudioGainTraits::Attributes::defaultValueMB[] = "defaultValueMB";
+const char AudioGainTraits::Attributes::stepValueMB[] = "stepValueMB";
+const char AudioGainTraits::Attributes::minRampMs[] = "minRampMs";
+const char AudioGainTraits::Attributes::maxRampMs[] = "maxRampMs";
+
+status_t AudioGainTraits::deserialize(_xmlDoc */*doc*/, const _xmlNode *root, PtrElement &gain,
+                                      PtrSerializingCtx /*serializingContext*/)
+{
+    static uint32_t index = 0;
+    gain = new Element(index++, true);
+
+    string mode = getXmlAttribute(root, Attributes::mode);
+    if (!mode.empty()) {
+        gain->setMode(GainModeConverter::maskFromString(mode));
+    }
+
+    string channelsLiteral = getXmlAttribute(root, Attributes::channelMask);
+    if (!channelsLiteral.empty()) {
+        gain->setChannelMask(channelMaskFromString(channelsLiteral));
+    }
+
+    string minValueMBLiteral = getXmlAttribute(root, Attributes::minValueMB);
+    uint32_t minValueMB;
+    if (!minValueMBLiteral.empty() && convertTo(minValueMBLiteral, minValueMB)) {
+        gain->setMinValueInMb(minValueMB);
+    }
+
+    string maxValueMBLiteral = getXmlAttribute(root, Attributes::maxValueMB);
+    uint32_t maxValueMB;
+    if (!maxValueMBLiteral.empty() && convertTo(maxValueMBLiteral, maxValueMB)) {
+        gain->setMaxValueInMb(maxValueMB);
+    }
+
+    string defaultValueMBLiteral = getXmlAttribute(root, Attributes::defaultValueMB);
+    uint32_t defaultValueMB;
+    if (!defaultValueMBLiteral.empty() && convertTo(defaultValueMBLiteral, defaultValueMB)) {
+        gain->setDefaultValueInMb(defaultValueMB);
+    }
+
+    string stepValueMBLiteral = getXmlAttribute(root, Attributes::stepValueMB);
+    uint32_t stepValueMB;
+    if (!stepValueMBLiteral.empty() && convertTo(stepValueMBLiteral, stepValueMB)) {
+        gain->setStepValueInMb(stepValueMB);
+    }
+
+    string minRampMsLiteral = getXmlAttribute(root, Attributes::minRampMs);
+    uint32_t minRampMs;
+    if (!minRampMsLiteral.empty() && convertTo(minRampMsLiteral, minRampMs)) {
+        gain->setMinRampInMs(minRampMs);
+    }
+
+    string maxRampMsLiteral = getXmlAttribute(root, Attributes::maxRampMs);
+    uint32_t maxRampMs;
+    if (!maxRampMsLiteral.empty() && convertTo(maxRampMsLiteral, maxRampMs)) {
+        gain->setMaxRampInMs(maxRampMs);
+    }
+    ALOGV("%s: adding new gain mode %08x channel mask %08x min mB %d max mB %d", __FUNCTION__,
+          gain->getMode(), gain->getChannelMask(), gain->getMinValueInMb(),
+          gain->getMaxValueInMb());
+
+    if (gain->getMode() == 0) {
+        return BAD_VALUE;
+    }
+    return NO_ERROR;
+}
+
+const char *const AudioProfileTraits::collectionTag = "profiles";
+const char *const AudioProfileTraits::tag = "profile";
+
+const char AudioProfileTraits::Attributes::name[] = "name";
+const char AudioProfileTraits::Attributes::samplingRates[] = "samplingRates";
+const char AudioProfileTraits::Attributes::format[] = "format";
+const char AudioProfileTraits::Attributes::channelMasks[] = "channelMasks";
+
+status_t AudioProfileTraits::deserialize(_xmlDoc */*doc*/, const _xmlNode *root, PtrElement &profile,
+                                         PtrSerializingCtx /*serializingContext*/)
+{
+    string samplingRates = getXmlAttribute(root, Attributes::samplingRates);
+    string format = getXmlAttribute(root, Attributes::format);
+    string channels = getXmlAttribute(root, Attributes::channelMasks);
+
+    profile = new Element(formatFromString(format), channelMasksFromString(channels, ","),
+                          samplingRatesFromString(samplingRates, ","));
+
+    profile->setDynamicFormat(profile->getFormat() == gDynamicFormat);
+    profile->setDynamicChannels(profile->getChannels().isEmpty());
+    profile->setDynamicRate(profile->getSampleRates().isEmpty());
+
+    return NO_ERROR;
+}
+
+
+const char *const MixPortTraits::collectionTag = "mixPorts";
+const char *const MixPortTraits::tag = "mixPort";
+
+const char MixPortTraits::Attributes::name[] = "name";
+const char MixPortTraits::Attributes::role[] = "role";
+const char MixPortTraits::Attributes::flags[] = "flags";
+
+status_t MixPortTraits::deserialize(_xmlDoc *doc, const _xmlNode *child, PtrElement &mixPort,
+                                    PtrSerializingCtx /*serializingContext*/)
+{
+    string name = getXmlAttribute(child, Attributes::name);
+    if (name.empty()) {
+        ALOGE("%s: No %s found", __FUNCTION__, Attributes::name);
+        return BAD_VALUE;
+    }
+    ALOGV("%s: %s %s=%s", __FUNCTION__, tag, Attributes::name, name.c_str());
+    string role = getXmlAttribute(child, Attributes::role);
+    if (role.empty()) {
+        ALOGE("%s: No %s found", __FUNCTION__, Attributes::role);
+        return BAD_VALUE;
+    }
+    ALOGV("%s: Role=%s", __FUNCTION__, role.c_str());
+    audio_port_role_t portRole = role == "source" ? AUDIO_PORT_ROLE_SOURCE : AUDIO_PORT_ROLE_SINK;
+
+    mixPort = new Element(String8(name.c_str()), portRole);
+
+    AudioProfileTraits::Collection profiles;
+    deserializeCollection<AudioProfileTraits>(doc, child, profiles, NULL);
+    if (profiles.isEmpty()) {
+        sp <AudioProfile> dynamicProfile = new AudioProfile(gDynamicFormat,
+                                                            ChannelsVector(), SampleRateVector());
+        dynamicProfile->setDynamicFormat(true);
+        dynamicProfile->setDynamicChannels(true);
+        dynamicProfile->setDynamicRate(true);
+        profiles.add(dynamicProfile);
+    }
+    mixPort->setAudioProfiles(profiles);
+
+    string flags = getXmlAttribute(child, Attributes::flags);
+    if (!flags.empty()) {
+        // Source role
+        if (portRole == AUDIO_PORT_ROLE_SOURCE) {
+            mixPort->setFlags(OutputFlagConverter::maskFromString(flags));
+        } else {
+            // Sink role
+            mixPort->setFlags(InputFlagConverter::maskFromString(flags));
+        }
+    }
+    // Deserialize children
+    AudioGainTraits::Collection gains;
+    deserializeCollection<AudioGainTraits>(doc, child, gains, NULL);
+    mixPort->setGains(gains);
+
+    return NO_ERROR;
+}
+
+const char *const DevicePortTraits::tag = "devicePort";
+const char *const DevicePortTraits::collectionTag = "devicePorts";
+
+const char DevicePortTraits::Attributes::tagName[] = "tagName";
+const char DevicePortTraits::Attributes::type[] = "type";
+const char DevicePortTraits::Attributes::role[] = "role";
+const char DevicePortTraits::Attributes::address[] = "address";
+const char DevicePortTraits::Attributes::roleSource[] = "source";
+
+status_t DevicePortTraits::deserialize(_xmlDoc *doc, const _xmlNode *root, PtrElement &deviceDesc,
+                                       PtrSerializingCtx /*serializingContext*/)
+{
+    string name = getXmlAttribute(root, Attributes::tagName);
+    if (name.empty()) {
+        ALOGE("%s: No %s found", __FUNCTION__, Attributes::tagName);
+        return BAD_VALUE;
+    }
+    ALOGV("%s: %s %s=%s", __FUNCTION__, tag, Attributes::tagName, name.c_str());
+    string typeName = getXmlAttribute(root, Attributes::type);
+    if (typeName.empty()) {
+        ALOGE("%s: no type for %s", __FUNCTION__, name.c_str());
+        return BAD_VALUE;
+    }
+    ALOGV("%s: %s %s=%s", __FUNCTION__, tag, Attributes::type, typeName.c_str());
+    string role = getXmlAttribute(root, Attributes::role);
+    if (role.empty()) {
+        ALOGE("%s: No %s found", __FUNCTION__, Attributes::role);
+        return BAD_VALUE;
+    }
+    ALOGV("%s: %s %s=%s", __FUNCTION__, tag, Attributes::role, role.c_str());
+    audio_port_role_t portRole = (role == Attributes::roleSource) ?
+                AUDIO_PORT_ROLE_SOURCE : AUDIO_PORT_ROLE_SINK;
+
+    audio_devices_t type = AUDIO_DEVICE_NONE;
+    if (!DeviceConverter::fromString(typeName, type) ||
+            (!audio_is_input_device(type) && portRole == AUDIO_PORT_ROLE_SOURCE) ||
+            (!audio_is_output_devices(type) && portRole == AUDIO_PORT_ROLE_SINK)) {
+        ALOGW("%s: bad type %08x", __FUNCTION__, type);
+        return BAD_VALUE;
+    }
+    deviceDesc = new Element(type, String8(name.c_str()));
+
+    string address = getXmlAttribute(root, Attributes::address);
+    if (!address.empty()) {
+        ALOGV("%s: address=%s for %s", __FUNCTION__, address.c_str(), name.c_str());
+        deviceDesc->mAddress = String8(address.c_str());
+    }
+
+    AudioProfileTraits::Collection profiles;
+    deserializeCollection<AudioProfileTraits>(doc, root, profiles, NULL);
+    if (profiles.isEmpty()) {
+        sp <AudioProfile> dynamicProfile = new AudioProfile(gDynamicFormat,
+                                                            ChannelsVector(), SampleRateVector());
+        dynamicProfile->setDynamicFormat(true);
+        dynamicProfile->setDynamicChannels(true);
+        dynamicProfile->setDynamicRate(true);
+        profiles.add(dynamicProfile);
+    }
+    deviceDesc->setAudioProfiles(profiles);
+
+    // Deserialize AudioGain children
+    deserializeCollection<AudioGainTraits>(doc, root, deviceDesc->mGains, NULL);
+    ALOGV("%s: adding device tag %s type %08x address %s", __FUNCTION__,
+          deviceDesc->getName().string(), type, deviceDesc->mAddress.string());
+    return NO_ERROR;
+}
+
+const char *const RouteTraits::tag = "route";
+const char *const RouteTraits::collectionTag = "routes";
+
+const char RouteTraits::Attributes::type[] = "type";
+const char RouteTraits::Attributes::typeMix[] = "mix";
+const char RouteTraits::Attributes::sink[] = "sink";
+const char RouteTraits::Attributes::sources[] = "sources";
+
+
+status_t RouteTraits::deserialize(_xmlDoc */*doc*/, const _xmlNode *root, PtrElement &element,
+                                  PtrSerializingCtx ctx)
+{
+    string type = getXmlAttribute(root, Attributes::type);
+    if (type.empty()) {
+        ALOGE("%s: No %s found", __FUNCTION__, Attributes::type);
+        return BAD_VALUE;
+    }
+    audio_route_type_t routeType = (type == Attributes::typeMix) ?
+                AUDIO_ROUTE_MIX : AUDIO_ROUTE_MUX;
+
+    ALOGV("%s: %s %s=%s", __FUNCTION__, tag, Attributes::type, type.c_str());
+    element = new Element(routeType);
+
+    string sinkAttr = getXmlAttribute(root, Attributes::sink);
+    if (sinkAttr.empty()) {
+        ALOGE("%s: No %s found", __FUNCTION__, Attributes::sink);
+        return BAD_VALUE;
+    }
+    // Convert Sink name to port pointer
+    sp<AudioPort> sink = ctx->findPortByTagName(String8(sinkAttr.c_str()));
+    if (sink == NULL) {
+        ALOGE("%s: no sink found with name=%s", __FUNCTION__, sinkAttr.c_str());
+        return BAD_VALUE;
+    }
+    element->setSink(sink);
+
+    string sourcesAttr = getXmlAttribute(root, Attributes::sources);
+    if (sourcesAttr.empty()) {
+        ALOGE("%s: No %s found", __FUNCTION__, Attributes::sources);
+        return BAD_VALUE;
+    }
+    // Tokenize and Convert Sources name to port pointer
+    AudioPortVector sources;
+    char *sourcesLiteral = strndup(sourcesAttr.c_str(), strlen(sourcesAttr.c_str()));
+    char *devTag = strtok(sourcesLiteral, ",");
+    while (devTag != NULL) {
+        if (strlen(devTag) != 0) {
+            sp<AudioPort> source = ctx->findPortByTagName(String8(devTag));
+            if (source == NULL) {
+                ALOGE("%s: no source found with name=%s", __FUNCTION__, devTag);
+                return BAD_VALUE;
+            }
+            sources.add(source);
+        }
+        devTag = strtok(NULL, ",");
+    }
+    free(sourcesLiteral);
+
+    sink->addRoute(element);
+    for (size_t i = 0; i < sources.size(); i++) {
+        sp<AudioPort> source = sources.itemAt(i);
+        source->addRoute(element);
+    }
+    element->setSources(sources);
+    return NO_ERROR;
+}
+
+const char *const ModuleTraits::childAttachedDevicesTag = "attachedDevices";
+const char *const ModuleTraits::childAttachedDeviceTag = "item";
+const char *const ModuleTraits::childDefaultOutputDeviceTag = "defaultOutputDevice";
+
+const char *const ModuleTraits::tag = "module";
+const char *const ModuleTraits::collectionTag = "modules";
+
+const char ModuleTraits::Attributes::name[] = "name";
+const char ModuleTraits::Attributes::version[] = "halVersion";
+
+status_t ModuleTraits::deserialize(xmlDocPtr doc, const xmlNode *root, PtrElement &module,
+                                   PtrSerializingCtx ctx)
+{
+    string name = getXmlAttribute(root, Attributes::name);
+    if (name.empty()) {
+        ALOGE("%s: No %s found", __FUNCTION__, Attributes::name);
+        return BAD_VALUE;
+    }
+    uint32_t version = AUDIO_DEVICE_API_VERSION_MIN;
+    string versionLiteral = getXmlAttribute(root, Attributes::version);
+    if (!versionLiteral.empty()) {
+        uint32_t major, minor;
+        sscanf(versionLiteral.c_str(), "%u.%u", &major, &minor);
+        version = HARDWARE_DEVICE_API_VERSION(major, minor);
+        ALOGV("%s: mHalVersion = %04x major %u minor %u",  __FUNCTION__,
+              version, major, minor);
+    }
+
+    ALOGV("%s: %s %s=%s", __FUNCTION__, tag, Attributes::name, name.c_str());
+
+    module = new Element(name.c_str(), version);
+
+    // Deserialize childrens: Audio Mix Port, Audio Device Ports (Source/Sink), Audio Routes
+    MixPortTraits::Collection mixPorts;
+    deserializeCollection<MixPortTraits>(doc, root, mixPorts, NULL);
+    module->setProfiles(mixPorts);
+
+    DevicePortTraits::Collection devicePorts;
+    deserializeCollection<DevicePortTraits>(doc, root, devicePorts, NULL);
+    module->setDeclaredDevices(devicePorts);
+
+    RouteTraits::Collection routes;
+    deserializeCollection<RouteTraits>(doc, root, routes, module.get());
+    module->setRoutes(routes);
+
+    const xmlNode *children = root->xmlChildrenNode;
+    while (children != NULL) {
+        if (!xmlStrcmp(children->name, (const xmlChar *)childAttachedDevicesTag)) {
+            ALOGV("%s: %s %s found", __FUNCTION__, tag, childAttachedDevicesTag);
+            const xmlNode *child = children->xmlChildrenNode;
+            while (child != NULL) {
+                if (!xmlStrcmp(child->name, (const xmlChar *)childAttachedDeviceTag)) {
+                    xmlChar *attachedDevice = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
+                    if (attachedDevice != NULL) {
+                        ALOGV("%s: %s %s=%s", __FUNCTION__, tag, childAttachedDeviceTag,
+                              (const char*)attachedDevice);
+                        sp<DeviceDescriptor> device =
+                                module->getDeclaredDevices().getDeviceFromTagName(String8((const char*)attachedDevice));
+                        ctx->addAvailableDevice(device);
+                        xmlFree(attachedDevice);
+                    }
+                }
+                child = child->next;
+            }
+        }
+        if (!xmlStrcmp(children->name, (const xmlChar *)childDefaultOutputDeviceTag)) {
+            xmlChar *defaultOutputDevice = xmlNodeListGetString(doc, children->xmlChildrenNode, 1);;
+            if (defaultOutputDevice != NULL) {
+                ALOGV("%s: %s %s=%s", __FUNCTION__, tag, childDefaultOutputDeviceTag,
+                      (const char*)defaultOutputDevice);
+                sp<DeviceDescriptor> device =
+                        module->getDeclaredDevices().getDeviceFromTagName(String8((const char*)defaultOutputDevice));
+                if (device != 0 && ctx->getDefaultOutputDevice() == 0) {
+                    ctx->setDefaultOutputDevice(device);
+                    ALOGV("%s: default is %08x", __FUNCTION__, ctx->getDefaultOutputDevice()->type());
+                }
+                xmlFree(defaultOutputDevice);
+            }
+        }
+        children = children->next;
+    }
+    return NO_ERROR;
+}
+
+const char *const GlobalConfigTraits::tag = "globalConfiguration";
+
+const char GlobalConfigTraits::Attributes::speakerDrcEnabled[] = "speaker_drc_enabled";
+
+
+status_t GlobalConfigTraits::deserialize(const xmlNode *cur, AudioPolicyConfig &config)
+{
+    const xmlNode *root = cur->xmlChildrenNode;
+    while (root != NULL) {
+        if (!xmlStrcmp(root->name, (const xmlChar *)tag)) {
+            string speakerDrcEnabled =
+                    getXmlAttribute(root, Attributes::speakerDrcEnabled);
+            bool isSpeakerDrcEnabled;
+            if (!speakerDrcEnabled.empty() &&
+                    convertTo<string, bool>(speakerDrcEnabled, isSpeakerDrcEnabled)) {
+                config.setSpeakerDrcEnabled(isSpeakerDrcEnabled);
+            }
+            return NO_ERROR;
+        }
+        root = root->next;
+    }
+    return NO_ERROR;
+}
+
+
+const char *const VolumeTraits::tag = "volume";
+const char *const VolumeTraits::collectionTag = "volumes";
+const char *const VolumeTraits::volumePointTag = "point";
+
+const char VolumeTraits::Attributes::stream[] = "stream";
+const char VolumeTraits::Attributes::deviceCategory[] = "deviceCategory";
+
+
+status_t VolumeTraits::deserialize(_xmlDoc *doc, const _xmlNode *root, PtrElement &element,
+                                   PtrSerializingCtx /*serializingContext*/)
+{
+    string streamTypeLiteral = getXmlAttribute(root, Attributes::stream);
+    if (streamTypeLiteral.empty()) {
+        ALOGE("%s: No %s found", __FUNCTION__, Attributes::stream);
+        return BAD_VALUE;
+    }
+    audio_stream_type_t streamType;
+    if (!StreamTypeConverter::fromString(streamTypeLiteral, streamType)) {
+        ALOGE("%s: Invalid %s", __FUNCTION__, Attributes::stream);
+        return BAD_VALUE;
+    }
+    string deviceCategoryLiteral = getXmlAttribute(root, Attributes::deviceCategory);
+    if (deviceCategoryLiteral.empty()) {
+        ALOGE("%s: No %s found", __FUNCTION__, Attributes::deviceCategory);
+        return BAD_VALUE;
+    }
+    device_category deviceCategory;
+    if (!DeviceCategoryConverter::fromString(deviceCategoryLiteral, deviceCategory)) {
+        ALOGE("%s: Invalid %s=%s", __FUNCTION__, Attributes::deviceCategory,
+              deviceCategoryLiteral.c_str());
+        return BAD_VALUE;
+    }
+    CurvePoints points;
+    const xmlNode *child = root->xmlChildrenNode;
+    while (child != NULL) {
+        if (!xmlStrcmp(child->name, (const xmlChar *)volumePointTag)) {
+            xmlChar *pointDefinition = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);;
+            if (pointDefinition == NULL) {
+                return BAD_VALUE;
+            }
+            ALOGV("%s: %s=%s", __FUNCTION__, tag, (const char*)pointDefinition);
+            Vector<int32_t> point;
+            collectionFromString<DefaultTraits<int32_t> >((const char*)pointDefinition, point, ",");
+            if (point.size() != 2) {
+                ALOGE("%s: Invalid %s: %s", __FUNCTION__, volumePointTag,
+                      (const char*)pointDefinition);
+                return BAD_VALUE;
+            }
+            points.add(std::make_pair(point[0], point[1]));
+            xmlFree(pointDefinition);
+        }
+        child = child->next;
+    }
+    element = new Element();
+    element->setDeviceCategory(deviceCategory);
+    element->setStreamType(streamType);
+    element->setCurvePoints(points);
+    return NO_ERROR;
+}
+
+PolicySerializer::PolicySerializer() : mRootElementName(rootName)
+{
+    std::ostringstream oss;
+    oss << gMajor << "." << gMinor;
+    mVersion = oss.str();
+    ALOGV("%s: Version=%s Root=%s", __FUNCTION__, mVersion.c_str(), mRootElementName.c_str());
+}
+
+status_t PolicySerializer::deserialize(const char *configFile, AudioPolicyConfig &config)
+{
+    xmlDocPtr doc;
+    doc = xmlParseFile(configFile);
+    if (doc == NULL) {
+        ALOGE("%s: Could not parse %s document.", __FUNCTION__, configFile);
+        return BAD_VALUE;
+    }
+    xmlNodePtr cur = xmlDocGetRootElement(doc);
+    if (cur == NULL) {
+        ALOGE("%s: Could not parse %s document: empty.", __FUNCTION__, configFile);
+        xmlFreeDoc(doc);
+        return BAD_VALUE;
+    }
+    if (xmlXIncludeProcess(doc) < 0) {
+         ALOGE("%s: libxml failed to resolve XIncludes on %s document.", __FUNCTION__, configFile);
+    }
+
+    if (xmlStrcmp(cur->name, (const xmlChar *) mRootElementName.c_str()))  {
+        ALOGE("%s: No %s root element found in xml data %s.", __FUNCTION__, mRootElementName.c_str(),
+              (const char *)cur->name);
+        xmlFreeDoc(doc);
+        return BAD_VALUE;
+    }
+
+    string version = getXmlAttribute(cur, versionAttribute);
+    if (version.empty()) {
+        ALOGE("%s: No version found in root node %s", __FUNCTION__, mRootElementName.c_str());
+        return BAD_VALUE;
+    }
+    if (version != mVersion) {
+        ALOGE("%s: Version does not match; expect %s got %s", __FUNCTION__, mVersion.c_str(),
+              version.c_str());
+        return BAD_VALUE;
+    }
+    // Lets deserialize children
+    // Modules
+    ModuleTraits::Collection modules;
+    deserializeCollection<ModuleTraits>(doc, cur, modules, &config);
+    config.setHwModules(modules);
+
+    // deserialize volume section
+    VolumeTraits::Collection volumes;
+    deserializeCollection<VolumeTraits>(doc, cur, volumes, NULL);
+
+    // Global Configuration
+    GlobalConfigTraits::deserialize(cur, config);
+
+    xmlFreeDoc(doc);
+    return android::OK;
+}
+
+}; // namespace android
diff --git a/services/audiopolicy/config/a2dp_audio_policy_configuration.xml b/services/audiopolicy/config/a2dp_audio_policy_configuration.xml
new file mode 100644
index 0000000..ced7463
--- /dev/null
+++ b/services/audiopolicy/config/a2dp_audio_policy_configuration.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- A2dp Audio HAL Audio Policy Configuration file -->
+<module name="a2dp" halVersion="2.0">
+    <mixPorts>
+        <mixPort name="a2dp output" role="source">
+            <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                     samplingRates="44100"
+                     channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+        </mixPort>
+        <mixPort name="a2dp input" role="sink">
+            <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                     samplingRates="44100,48000"
+                     channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO"/>
+        </mixPort>
+    </mixPorts>
+    <devicePorts>
+        <devicePort tagName="BT A2DP Out" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP" role="sink">
+            <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                     samplingRates="44100"
+                     channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+        </devicePort>
+        <devicePort tagName="BT A2DP Headphones" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES" role="sink">
+            <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                     samplingRates="44100"
+                     channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+        </devicePort>
+        <devicePort tagName="BT A2DP Speaker" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER" role="sink">
+            <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                     samplingRates="44100"
+                     channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+        </devicePort>
+        <devicePort tagName="BT A2DP In" type="AUDIO_DEVICE_IN_BLUETOOTH_A2DP" role="source">
+            <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                     samplingRates="44100,48000"
+                     channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO"/>
+        </devicePort>
+    </devicePorts>
+    <routes>
+        <route type="mix" sink="BT A2DP Out"
+               sources="a2dp output"/>
+        <route type="mix" sink="BT A2DP Headphones"
+               sources="a2dp output"/>
+        <route type="mix" sink="BT A2DP Speaker"
+               sources="a2dp output"/>
+        <route type="mix" sink="a2dp input"
+               sources="BT A2DP In"/>
+    </routes>
+</module>
diff --git a/services/audiopolicy/config/audio_policy_configuration.xml b/services/audiopolicy/config/audio_policy_configuration.xml
new file mode 100644
index 0000000..dccc3a8
--- /dev/null
+++ b/services/audiopolicy/config/audio_policy_configuration.xml
@@ -0,0 +1,233 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <!-- version section contains a “version” tag in the form “major.minor” e.g version=”1.0” -->
+
+    <!-- Global configuration Decalaration -->
+    <globalConfiguration speaker_drc_enabled="true"/>
+
+
+    <!-- Modules section:
+        There is one section per audio HW module present on the platform.
+        Each module section will contains two mandatory tags for audio HAL “halVersion” and “name”.
+        The module names are the same as in current .conf file:
+                “primary”, “A2DP”, “remote_submix”, “USB”
+        Each module will contain the following sections:
+        “devicePorts”: a list of device descriptors for all input and output devices accessible via this
+        module.
+        This contains both permanently attached devices and removable devices.
+        “mixPorts”: listing all output and input streams exposed by the audio HAL
+        “routes”: list of possible connections between input and output devices or between stream and
+        devices.
+            "route": is defined by an attribute:
+                -"type": <mux|mix> means all sources are mutual exclusive (mux) or can be mixed (mix)
+                -"sink": the sink involved in this route
+                -"sources": all the sources than can be connected to the sink via vis route
+        “attachedDevices”: permanently attached devices.
+        The attachedDevices section is a list of devices names. The names correspond to device names
+        defined in <devicePorts> section.
+        “defaultOutputDevice”: device to be used by default when no policy rule applies
+    -->
+    <modules>
+        <!-- Primary Audio HAL -->
+        <module name="primary" halVersion="3.0">
+            <attachedDevices>
+                <item>Speaker</item>
+                <item>Built-In Mic</item>
+                <item>Built-In Back Mic</item>
+            </attachedDevices>
+            <defaultOutputDevice>Speaker</defaultOutputDevice>
+            <mixPorts>
+                <mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </mixPort>
+                <mixPort name="deep_buffer" role="source"
+                        flags="AUDIO_OUTPUT_FLAG_DEEP_BUFFER">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </mixPort>
+                <mixPort name="compressed_offload" role="source"
+                         flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING">
+                    <profile name="" format="AUDIO_FORMAT_MP3"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+                             channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
+                    <profile name="" format="AUDIO_FORMAT_AAC"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+                             channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
+                    <profile name="" format="AUDIO_FORMAT_AAC_LC"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+                             channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
+                </mixPort>
+                <mixPort name="voice_tx" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+                </mixPort>
+                <mixPort name="primary input" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
+                </mixPort>
+                <mixPort name="voice_rx" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+                </mixPort>
+            </mixPorts>
+            <devicePorts>
+                <!-- Output devices declaration, i.e. Sink DEVICE PORT -->
+                <devicePort tagName="Earpiece" type="AUDIO_DEVICE_OUT_EARPIECE" role="sink">
+                   <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                            samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+                </devicePort>
+                <devicePort tagName="Speaker" role="sink" type="AUDIO_DEVICE_OUT_SPEAKER" address="">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                    <gains>
+                        <gain name="gain_1" mode="AUDIO_GAIN_MODE_JOINT"
+                              minValueMB="-8400"
+                              maxValueMB="4000"
+                              defaultValueMB="0"
+                              stepValueMB="100"/>
+                    </gains>
+                </devicePort>
+                <devicePort tagName="Wired Headset" type="AUDIO_DEVICE_OUT_WIRED_HEADSET" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </devicePort>
+                <devicePort tagName="Wired Headphones" type="AUDIO_DEVICE_OUT_WIRED_HEADPHONE" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </devicePort>
+                <devicePort tagName="BT SCO" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+                </devicePort>
+                <devicePort tagName="BT SCO Headset" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+                </devicePort>
+                <devicePort tagName="BT SCO Car Kit" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+                </devicePort>
+                <devicePort tagName="Telephony Tx" type="AUDIO_DEVICE_OUT_TELEPHONY_TX" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+                </devicePort>
+
+                <devicePort tagName="Built-In Mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
+                </devicePort>
+                <devicePort tagName="Built-In Back Mic" type="AUDIO_DEVICE_IN_BACK_MIC" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
+                </devicePort>
+                <devicePort tagName="Wired Headset Mic" type="AUDIO_DEVICE_IN_WIRED_HEADSET" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
+                </devicePort>
+                <devicePort tagName="BT SCO Headset Mic" type="AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+                </devicePort>
+                <devicePort tagName="Telephony Rx" type="AUDIO_DEVICE_IN_TELEPHONY_RX" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+                </devicePort>
+            </devicePorts>
+            <!-- route declaration, i.e. list all available sources for a given sink -->
+            <routes>
+                <route type="mix" sink="Earpiece"
+                       sources="primary output,deep_buffer,BT SCO Headset Mic"/>
+                <route type="mix" sink="Speaker"
+                       sources="primary output,deep_buffer,compressed_offload,BT SCO Headset Mic,Telephony Rx"/>
+                <route type="mix" sink="Wired Headset"
+                       sources="primary output,deep_buffer,compressed_offload,BT SCO Headset Mic,Telephony Rx"/>
+                <route type="mix" sink="Wired Headphones"
+                       sources="primary output,deep_buffer,compressed_offload,BT SCO Headset Mic,Telephony Rx"/>
+                <route type="mix" sink="Telephony Tx"
+                       sources="voice_tx"/>
+                <route type="mix" sink="primary input"
+                       sources="Built-In Mic,Built-In Back Mic,Wired Headset Mic,BT SCO Headset Mic"/>
+                <route type="mix" sink="Telephony Tx"
+                       sources="Built-In Mic,Built-In Back Mic,Wired Headset Mic,BT SCO Headset Mic"/>
+                <route type="mix" sink="voice_rx"
+                       sources="Telephony Rx"/>
+            </routes>
+
+        </module>
+
+        <!-- HDMI Audio HAL -->
+        <module description="HDMI Audio HAL" name="hdmi" version="2.0">
+            <mixPorts>
+                <mixPort name="hdmi output" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="48000"/>
+                </mixPort>
+            </mixPorts>
+            <devicePorts>
+                <devicePort tagName="HDMI Out" type="AUDIO_DEVICE_OUT_AUX_DIGITAL" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </devicePort>
+            </devicePorts>
+            <routes>
+                <route type="mix" sink="HDMI Out"
+                       sources="hdmi output"/>
+            </routes>
+        </module>
+
+        <!-- A2dp Audio HAL -->
+        <xi:include href="a2dp_audio_policy_configuration.xml"/>
+
+        <!-- Usb Audio HAL -->
+        <xi:include href="usb_audio_policy_configuration.xml"/>
+
+        <!-- Remote Submix Audio HAL -->
+        <xi:include href="r_submix_audio_policy_configuration.xml"/>
+
+    </modules>
+    <!-- End of Modules section -->
+
+    <!-- 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=””>
+    <point>0, -9600</point>
+    <point>100, 0</point>
+    </volume>
+    -->
+    <volumes>
+        <volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_SPEAKER">
+            <point>0,-9600</point>
+            <point>100,0</point>
+        </volume>
+        <volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_EARPIECE">
+            <point>0,-9800</point>
+            <point>50,-1000</point>
+            <point>100,0</point>
+        </volume>
+    </volumes>
+
+    <!-- End of Volume section -->
+
+
+
+</audioPolicyConfiguration>
diff --git a/services/audiopolicy/config/r_submix_audio_policy_configuration.xml b/services/audiopolicy/config/r_submix_audio_policy_configuration.xml
new file mode 100644
index 0000000..dc2a5ec
--- /dev/null
+++ b/services/audiopolicy/config/r_submix_audio_policy_configuration.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<!-- Remote Submix Audio Policy Configuration file -->
+<module name="r_submix" halVersion="2.0">
+    <attachedDevices>
+        <item>Remote Submix In</item>
+    </attachedDevices>
+    <mixPorts>
+        <mixPort name="r_submix output" role="source">
+            <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                     samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+        </mixPort>
+        <mixPort name="r_submix input" role="sink">
+           <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                    samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
+        </mixPort>
+   </mixPorts>
+   <devicePorts>
+       <devicePort tagName="Remote Submix Out" type="AUDIO_DEVICE_OUT_REMOTE_SUBMIX"  role="sink">
+           <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                    samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+       </devicePort>
+       <devicePort tagName="Remote Submix In" type="AUDIO_DEVICE_IN_REMOTE_SUBMIX"  role="source">
+           <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                    samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
+        </devicePort>
+    </devicePorts>
+    <routes>
+        <route type="mix" sink="Remote Submix Out"
+               sources="r_submix output"/>
+        <route type="mix" sink="r_submix input"
+               sources="Remote Submix In"/>
+    </routes>
+</module>
diff --git a/services/audiopolicy/config/usb_audio_policy_configuration.xml b/services/audiopolicy/config/usb_audio_policy_configuration.xml
new file mode 100644
index 0000000..1630a94
--- /dev/null
+++ b/services/audiopolicy/config/usb_audio_policy_configuration.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<!-- USB Audio HAL Audio Policy Configuration file -->
+
+<module name="usb" halVersion="2.0">
+    <mixPorts>
+        <mixPort name="usb_accessory output" role="source">
+            <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                     samplingRates="44100" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+        </mixPort>
+        <mixPort name="usb_device output" role="source"/>
+        <mixPort name="usb_device input" role="sink"/>
+    </mixPorts>
+    <devicePorts>
+        <devicePort tagName="USB Host Out" type="AUDIO_DEVICE_OUT_USB_ACCESSORY" role="sink">
+            <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                     samplingRates="44100" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+        </devicePort>
+        <devicePort tagName="USB Device Out" type="AUDIO_DEVICE_OUT_USB_DEVICE" role="sink"/>
+        <devicePort tagName="USB Device In" type="AUDIO_DEVICE_IN_USB_DEVICE" role="source"/>
+    </devicePorts>
+    <routes>
+        <route type="mix" sink="USB Host Out"
+               sources="usb_accessory output"/>
+        <route type="mix" sink="USB Device Out"
+               sources="usb_device output"/>
+        <route type="mix" sink="usb_device input"
+               sources="USB Device In"/>
+    </routes>
+</module>
diff --git a/services/audiopolicy/engineconfigurable/Android.mk b/services/audiopolicy/engineconfigurable/Android.mk
index b18c520..06d00ca 100755
--- a/services/audiopolicy/engineconfigurable/Android.mk
+++ b/services/audiopolicy/engineconfigurable/Android.mk
@@ -41,7 +41,11 @@
 LOCAL_STATIC_LIBRARIES := \
     libmedia_helper \
     libaudiopolicypfwwrapper \
-    libaudiopolicycomponents
+    libaudiopolicycomponents \
+
+ifeq ($(USE_XML_AUDIO_POLICY_CONF), 1)
+LOCAL_STATIC_LIBRARIES += libxml2
+endif
 
 LOCAL_SHARED_LIBRARIES := \
     libcutils \
diff --git a/services/audiopolicy/enginedefault/Android.mk b/services/audiopolicy/enginedefault/Android.mk
index 8d43b89..b3b3dde 100755
--- a/services/audiopolicy/enginedefault/Android.mk
+++ b/services/audiopolicy/enginedefault/Android.mk
@@ -34,9 +34,15 @@
 
 LOCAL_MODULE := libaudiopolicyenginedefault
 LOCAL_MODULE_TAGS := optional
+
 LOCAL_STATIC_LIBRARIES := \
     libmedia_helper \
-    libaudiopolicycomponents
+    libaudiopolicycomponents \
+
+ifeq ($(USE_XML_AUDIO_POLICY_CONF), 1)
+LOCAL_STATIC_LIBRARIES += libxml2
+endif #ifeq ($(USE_XML_AUDIO_POLICY_CONF), 1)
+
 
 LOCAL_SHARED_LIBRARIES += \
     libcutils \
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 04af88d..2aed7b1 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -24,6 +24,8 @@
 #define ALOGVV(a...) do { } while(0)
 #endif
 
+#define AUDIO_POLICY_XML_CONFIG_FILE "/system/etc/audio_policy_configuration.xml"
+
 #include <inttypes.h>
 #include <math.h>
 
@@ -37,7 +39,11 @@
 #include <media/AudioPolicyHelper.h>
 #include <soundtrigger/SoundTrigger.h>
 #include "AudioPolicyManager.h"
+#ifdef USE_XML_AUDIO_POLICY_CONF
+#include <Serializer.h>
+#else
 #include <ConfigParsingUtils.h>
+#endif
 #include "TypeConverter.h"
 #include <policy.h>
 
@@ -3014,9 +3020,13 @@
     AudioPolicyConfig config(mHwModules, mAvailableOutputDevices, mAvailableInputDevices,
                              mDefaultOutputDevice, mSpeakerDrcEnabled);
 
+#ifdef USE_XML_AUDIO_POLICY_CONF
+    PolicySerializer serializer;
+    if (serializer.deserialize(AUDIO_POLICY_XML_CONFIG_FILE, config) != NO_ERROR) {
+#else
     if ((ConfigParsingUtils::loadConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE, config) != NO_ERROR) &&
-        (ConfigParsingUtils::loadConfig(AUDIO_POLICY_CONFIG_FILE, config) != NO_ERROR)) {
-
+            (ConfigParsingUtils::loadConfig(AUDIO_POLICY_CONFIG_FILE, config) != NO_ERROR)) {
+#endif
         ALOGE("could not load audio policy configuration file, setting defaults");
         config.setDefault();
     }