Migrate helper functions from managerdefault to common

This patch moves from manager to common:

-parse helper functions of the policy configuration file
-collection helper function on
	-output / input descriptors
	-DeviceDescriptor
	-AudioPatch / Audio Port
	-IO Profile
	-HwModule

Change-Id: If45e53418db75af1af198f43c4ef27884499055f
Signed-off-by: François Gaffie <francois.gaffie@intel.com>
diff --git a/services/audiopolicy/Android.mk b/services/audiopolicy/Android.mk
index fb56fd8..334967e 100644
--- a/services/audiopolicy/Android.mk
+++ b/services/audiopolicy/Android.mk
@@ -16,13 +16,13 @@
 LOCAL_SRC_FILES += \
     service/AudioPolicyInterfaceImpl.cpp \
     service/AudioPolicyClientImpl.cpp
-
 endif
 
 LOCAL_C_INCLUDES := \
     $(TOPDIR)frameworks/av/services/audioflinger \
     $(call include-path-for, audio-effects) \
-    $(call include-path-for, audio-utils)
+    $(call include-path-for, audio-utils) \
+    $(TOPDIR)frameworks/av/services/audiopolicy/common/include
 
 LOCAL_SHARED_LIBRARIES := \
     libcutils \
@@ -63,6 +63,9 @@
     liblog \
     libsoundtrigger
 
+LOCAL_C_INCLUDES += \
+    $(TOPDIR)frameworks/av/services/audiopolicy/common/include \
+
 LOCAL_STATIC_LIBRARIES := \
     libmedia_helper \
     libaudiopolicycomponents
@@ -84,6 +87,9 @@
 LOCAL_STATIC_LIBRARIES := \
     libaudiopolicycomponents
 
+LOCAL_C_INCLUDES += \
+    $(TOPDIR)frameworks/av/services/audiopolicy/common/include \
+
 LOCAL_MODULE:= libaudiopolicymanager
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/services/audiopolicy/common/include/policy.h b/services/audiopolicy/common/include/policy.h
new file mode 100755
index 0000000..a2327ee
--- /dev/null
+++ b/services/audiopolicy/common/include/policy.h
@@ -0,0 +1,84 @@
+/*
+ * 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 <system/audio.h>
+
+// For mixed output and inputs, the policy will use max mixer sampling rates.
+// Do not limit sampling rate otherwise
+#define MAX_MIXER_SAMPLING_RATE 48000
+
+// For mixed output and inputs, the policy will use max mixer channel count.
+// Do not limit channel count otherwise
+#define MAX_MIXER_CHANNEL_COUNT 8
+
+/**
+ * A device mask for all audio input devices that are considered "virtual" when evaluating
+ * active inputs in getActiveInput()
+ */
+#define APM_AUDIO_IN_DEVICE_VIRTUAL_ALL  (AUDIO_DEVICE_IN_REMOTE_SUBMIX|AUDIO_DEVICE_IN_FM_TUNER)
+
+
+/**
+ * A device mask for all audio input and output devices where matching inputs/outputs on device
+ * type alone is not enough: the address must match too
+ */
+#define APM_AUDIO_DEVICE_MATCH_ADDRESS_ALL (AUDIO_DEVICE_IN_REMOTE_SUBMIX | \
+                                            AUDIO_DEVICE_OUT_REMOTE_SUBMIX)
+
+/**
+ * Check if the state given correspond to an in call state.
+ * @TODO find a better name for widely call state
+ *
+ * @param[in] state to consider
+ *
+ * @return true if given state represents a device in a telephony or VoIP call
+ */
+static inline bool is_state_in_call(int state)
+{
+    return (state == AUDIO_MODE_IN_CALL) || (state == AUDIO_MODE_IN_COMMUNICATION);
+}
+
+/**
+ * Check if the input device given is considered as a virtual device.
+ *
+ * @param[in] device to consider
+ *
+ * @return true if the device is a virtual one, false otherwise.
+ */
+static bool is_virtual_input_device(audio_devices_t device)
+{
+    if ((device & AUDIO_DEVICE_BIT_IN) != 0) {
+        device &= ~AUDIO_DEVICE_BIT_IN;
+        if ((popcount(device) == 1) && ((device & ~APM_AUDIO_IN_DEVICE_VIRTUAL_ALL) == 0))
+            return true;
+    }
+    return false;
+}
+
+/**
+ * Check whether the device type is one
+ * where addresses are used to distinguish between one connected device and another
+ *
+ * @param[in] device to consider
+ *
+ * @return true if the device needs distinguish on address, false otherwise..
+ */
+static bool device_distinguishes_on_address(audio_devices_t device)
+{
+    return ((device & APM_AUDIO_DEVICE_MATCH_ADDRESS_ALL & ~AUDIO_DEVICE_BIT_IN) != 0);
+}
diff --git a/services/audiopolicy/common/managerdefinitions/Android.mk b/services/audiopolicy/common/managerdefinitions/Android.mk
index d9d1477..bc6900b 100644
--- a/services/audiopolicy/common/managerdefinitions/Android.mk
+++ b/services/audiopolicy/common/managerdefinitions/Android.mk
@@ -20,6 +20,7 @@
 
 LOCAL_C_INCLUDES += \
     $(LOCAL_PATH)/include \
+    $(TOPDIR)frameworks/av/services/audiopolicy/common/include \
 
 LOCAL_EXPORT_C_INCLUDE_DIRS := \
     $(LOCAL_PATH)/include
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
index 599c295..7536a37 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
@@ -20,6 +20,7 @@
 #include <utils/Errors.h>
 #include <system/audio.h>
 #include <utils/SortedVector.h>
+#include <utils/KeyedVector.h>
 
 namespace android {
 
@@ -34,6 +35,8 @@
     AudioInputDescriptor(const sp<IOProfile>& profile);
     void setIoHandle(audio_io_handle_t ioHandle);
 
+    audio_module_handle_t getModuleHandle() const;
+
     status_t    dump(int fd);
 
     audio_port_handle_t           mId;
@@ -56,4 +59,27 @@
     void toAudioPort(struct audio_port *port) const;
 };
 
+class AudioInputCollection :
+        public DefaultKeyedVector< audio_io_handle_t, sp<AudioInputDescriptor> >
+{
+public:
+    bool isSourceActive(audio_source_t source) const;
+
+    sp<AudioInputDescriptor> getInputFromId(audio_port_handle_t id) const;
+
+    uint32_t activeInputsCount() const;
+
+    /**
+     * return io handle of active input or 0 if no input is active
+     * Only considers inputs from physical devices (e.g. main mic, headset mic) when
+     * ignoreVirtualInputs is true.
+     */
+    audio_io_handle_t getActiveInput(bool ignoreVirtualInputs = true);
+
+    audio_devices_t getSupportedDevices(audio_io_handle_t handle) const;
+
+    status_t dump(int fd) const;
+};
+
+
 }; // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
index 8469b81..e2f1bbf 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
@@ -20,6 +20,7 @@
 #include "ApmImplDefinitions.h"
 #include <utils/Errors.h>
 #include <utils/Timers.h>
+#include <utils/KeyedVector.h>
 #include <system/audio.h>
 
 namespace android {
@@ -54,6 +55,8 @@
     virtual sp<AudioPort> getAudioPort() const { return mProfile; }
     void toAudioPort(struct audio_port *port) const;
 
+    audio_module_handle_t getModuleHandle() const;
+
     audio_port_handle_t mId;
     audio_io_handle_t mIoHandle;              // output handle
     uint32_t mLatency;                  //
@@ -73,4 +76,38 @@
     uint32_t mDirectOpenCount; // number of clients using this output (direct outputs only)
 };
 
+class AudioOutputCollection :
+        public DefaultKeyedVector< audio_io_handle_t, sp<AudioOutputDescriptor> >
+{
+public:
+    bool isStreamActive(audio_stream_type_t stream, uint32_t inPastMs = 0) const;
+
+    /**
+     * return whether a stream is playing remotely, override to change the definition of
+     * local/remote playback, used for instance by notification manager to not make
+     * media players lose audio focus when not playing locally
+     * For the base implementation, "remotely" means playing during screen mirroring which
+     * uses an output for playback with a non-empty, non "0" address.
+     */
+    bool isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs = 0) const;
+
+    /**
+     * returns the A2DP output handle if it is open or 0 otherwise
+     */
+    audio_io_handle_t getA2dpOutput() const;
+
+    sp<AudioOutputDescriptor> getOutputFromId(audio_port_handle_t id) const;
+
+    sp<AudioOutputDescriptor> getPrimaryOutput() const;
+
+    /**
+     * return true if any output is playing anything besides the stream to ignore
+     */
+    bool isAnyOutputActive(audio_stream_type_t streamToIgnore) const;
+
+    audio_devices_t getSupportedDevices(audio_io_handle_t handle) const;
+
+    status_t dump(int fd) const;
+};
+
 }; // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPatch.h b/services/audiopolicy/common/managerdefinitions/include/AudioPatch.h
index 6e8fb32..385f257 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPatch.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPatch.h
@@ -17,8 +17,10 @@
 #pragma once
 
 #include <system/audio.h>
+#include <utils/Errors.h>
 #include <utils/RefBase.h>
 #include <utils/Errors.h>
+#include <utils/KeyedVector.h>
 
 namespace android {
 
@@ -38,4 +40,16 @@
     static volatile int32_t mNextUniqueId;
 };
 
+class AudioPatchCollection : public DefaultKeyedVector<audio_patch_handle_t, sp<AudioPatch> >
+{
+public:
+    status_t addAudioPatch(audio_patch_handle_t handle, const sp<AudioPatch>& patch);
+
+    status_t removeAudioPatch(audio_patch_handle_t handle);
+
+    status_t listAudioPatches(unsigned int *num_patches, struct audio_patch *patches) const;
+
+    status_t dump(int fd) const;
+};
+
 }; // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
index 52e845c..4f7f2bc 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
@@ -23,19 +23,16 @@
 #include <system/audio.h>
 #include <cutils/config_utils.h>
 
-#define MAX_MIXER_SAMPLING_RATE 48000
-#define MAX_MIXER_CHANNEL_COUNT 8
-
 namespace android {
 
 class HwModule;
 class AudioGain;
 
-class AudioPort: public virtual RefBase
+class AudioPort : public virtual RefBase
 {
 public:
     AudioPort(const String8& name, audio_port_type_t type,
-            audio_port_role_t role, const sp<HwModule>& module);
+              audio_port_role_t role, const sp<HwModule>& module);
     virtual ~AudioPort() {}
 
     audio_port_handle_t getHandle() { return mId; }
@@ -78,6 +75,8 @@
     static const audio_format_t sPcmFormatCompareTable[];
     static int compareFormats(audio_format_t format1, audio_format_t format2);
 
+    audio_module_handle_t getModuleHandle() const;
+
     void dump(int fd, int spaces) const;
 
     String8           mName;
@@ -106,7 +105,7 @@
     static volatile int32_t mNextUniqueId;
 };
 
-class AudioPortConfig: public virtual RefBase
+class AudioPortConfig : public virtual RefBase
 {
 public:
     AudioPortConfig();
diff --git a/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h b/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h
index 45e96d9..53cb4a3 100644
--- a/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h
+++ b/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h
@@ -16,8 +16,16 @@
 
 #pragma once
 
+#include "DeviceDescriptor.h"
+#include "HwModule.h"
+#include "audio_policy_conf.h"
 #include <system/audio.h>
-#include <sys/types.h>
+#include <utils/Log.h>
+#include <utils/Vector.h>
+#include <utils/SortedVector.h>
+#include <cutils/config_utils.h>
+#include <utils/RefBase.h>
+#include <system/audio_policy.h>
 
 namespace android {
 
@@ -161,6 +169,32 @@
     static uint32_t parseOutputFlagNames(char *name);
     static uint32_t parseInputFlagNames(char *name);
     static audio_devices_t parseDeviceNames(char *name);
+
+    static void loadHwModules(cnode *root, HwModuleCollection &hwModules,
+                              DeviceVector &availableInputDevices,
+                              DeviceVector &availableOutputDevices,
+                              sp<DeviceDescriptor> &defaultOutputDevices,
+                              bool &isSpeakerDrcEnabled);
+
+    static void loadGlobalConfig(cnode *root, const sp<HwModule>& module,
+                                 DeviceVector &availableInputDevices,
+                                 DeviceVector &availableOutputDevices,
+                                 sp<DeviceDescriptor> &defaultOutputDevices,
+                                 bool &isSpeakerDrcEnabled);
+
+    static status_t loadAudioPolicyConfig(const char *path,
+                                          HwModuleCollection &hwModules,
+                                          DeviceVector &availableInputDevices,
+                                          DeviceVector &availableOutputDevices,
+                                          sp<DeviceDescriptor> &defaultOutputDevices,
+                                          bool &isSpeakerDrcEnabled);
+
+private:
+    static void loadHwModule(cnode *root, HwModuleCollection &hwModules,
+                             DeviceVector &availableInputDevices,
+                             DeviceVector &availableOutputDevices,
+                             sp<DeviceDescriptor> &defaultOutputDevices,
+                             bool &isSpeakerDrcEnabled);
 };
 
 }; // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
index e63ea2b..b9e1d4a 100644
--- a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
@@ -22,10 +22,11 @@
 #include <utils/SortedVector.h>
 #include <cutils/config_utils.h>
 #include <system/audio.h>
+#include <system/audio_policy.h>
 
 namespace android {
 
-class DeviceDescriptor: public AudioPort, public AudioPortConfig
+class DeviceDescriptor : public AudioPort, public AudioPortConfig
 {
 public:
     DeviceDescriptor(const String8& name, audio_devices_t type);
@@ -43,12 +44,16 @@
     virtual void loadGains(cnode *root);
     virtual void toAudioPort(struct audio_port *port) const;
 
+    audio_devices_t type() const { return mDeviceType; }
     status_t dump(int fd, int spaces, int index) const;
 
-    audio_devices_t mDeviceType;
     String8 mAddress;
+    audio_port_handle_t mId;
 
     static String8  emptyNameStr;
+
+private:
+    audio_devices_t mDeviceType;
 };
 
 class DeviceVector : public SortedVector< sp<DeviceDescriptor> >
@@ -56,9 +61,9 @@
 public:
     DeviceVector() : SortedVector(), mDeviceTypes(AUDIO_DEVICE_NONE) {}
 
-    ssize_t         add(const sp<DeviceDescriptor>& item);
-    ssize_t         remove(const sp<DeviceDescriptor>& item);
-    ssize_t         indexOf(const sp<DeviceDescriptor>& item) const;
+    ssize_t add(const sp<DeviceDescriptor>& item);
+    ssize_t remove(const sp<DeviceDescriptor>& item);
+    ssize_t indexOf(const sp<DeviceDescriptor>& item) const;
 
     audio_devices_t types() const { return mDeviceTypes; }
 
@@ -69,8 +74,13 @@
     DeviceVector getDevicesFromType(audio_devices_t types) const;
     sp<DeviceDescriptor> getDeviceFromId(audio_port_handle_t id) const;
     sp<DeviceDescriptor> getDeviceFromName(const String8& name) const;
-    DeviceVector getDevicesFromTypeAddr(audio_devices_t type, String8 address)
-    const;
+    DeviceVector getDevicesFromTypeAddr(audio_devices_t type, String8 address) const;
+
+    audio_devices_t getDevicesFromHwModule(audio_module_handle_t moduleHandle) const;
+
+    audio_policy_dev_state_t getDeviceConnectionState(const sp<DeviceDescriptor> &devDesc) const;
+
+    status_t dump(int fd, const String8 &direction) const;
 
 private:
     void refreshTypes();
diff --git a/services/audiopolicy/common/managerdefinitions/include/HwModule.h b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
index 3d4e2ad..92c3ea2 100644
--- a/services/audiopolicy/common/managerdefinitions/include/HwModule.h
+++ b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
@@ -45,6 +45,8 @@
             audio_devices_t device, String8 address);
     status_t removeInputProfile(String8 name);
 
+    audio_module_handle_t getHandle() const { return mHandle; }
+
     void dump(int fd);
 
     const char *const        mName; // base name of the audio HW module (primary, a2dp ...)
@@ -55,4 +57,18 @@
     DeviceVector             mDeclaredDevices; // devices declared in audio_policy.conf
 };
 
+class HwModuleCollection : public Vector< sp<HwModule> >
+{
+public:
+    sp<HwModule> getModuleFromName(const char *name) const;
+
+    sp <HwModule> getModuleForDevice(audio_devices_t device) const;
+
+    sp<DeviceDescriptor>  getDeviceDescriptor(const audio_devices_t device,
+                                              const char *device_address,
+                                              const char *device_name) const;
+
+    status_t dump(int fd) const;
+};
+
 }; // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
index fa7761a..fa66728 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
@@ -22,6 +22,7 @@
 #include "AudioGain.h"
 #include "HwModule.h"
 #include <media/AudioPolicy.h>
+#include <policy.h>
 
 namespace android {
 
@@ -46,9 +47,13 @@
     mIoHandle = ioHandle;
 }
 
-void AudioInputDescriptor::toAudioPortConfig(
-                                                   struct audio_port_config *dstConfig,
-                                                   const struct audio_port_config *srcConfig) const
+audio_module_handle_t AudioInputDescriptor::getModuleHandle() const
+{
+    return mProfile->getModuleHandle();
+}
+
+void AudioInputDescriptor::toAudioPortConfig(struct audio_port_config *dstConfig,
+                                             const struct audio_port_config *srcConfig) const
 {
     ALOG_ASSERT(mProfile != 0,
                 "toAudioPortConfig() called on input with null profile %d", mIoHandle);
@@ -68,8 +73,7 @@
     dstConfig->ext.mix.usecase.source = mInputSource;
 }
 
-void AudioInputDescriptor::toAudioPort(
-                                                    struct audio_port *port) const
+void AudioInputDescriptor::toAudioPort(struct audio_port *port) const
 {
     ALOG_ASSERT(mProfile != 0, "toAudioPort() called on input with null profile %d", mIoHandle);
 
@@ -107,4 +111,77 @@
     return NO_ERROR;
 }
 
+bool AudioInputCollection::isSourceActive(audio_source_t source) const
+{
+    for (size_t i = 0; i < size(); i++) {
+        const sp<AudioInputDescriptor>  inputDescriptor = valueAt(i);
+        if (inputDescriptor->mRefCount == 0) {
+            continue;
+        }
+        if (inputDescriptor->mInputSource == (int)source) {
+            return true;
+        }
+    }
+    return false;
+}
+
+sp<AudioInputDescriptor> AudioInputCollection::getInputFromId(audio_port_handle_t id) const
+{
+    sp<AudioInputDescriptor> inputDesc = NULL;
+    for (size_t i = 0; i < size(); i++) {
+        inputDesc = valueAt(i);
+        if (inputDesc->mId == id) {
+            break;
+        }
+    }
+    return inputDesc;
+}
+
+uint32_t AudioInputCollection::activeInputsCount() const
+{
+    uint32_t count = 0;
+    for (size_t i = 0; i < size(); i++) {
+        const sp<AudioInputDescriptor>  desc = valueAt(i);
+        if (desc->mRefCount > 0) {
+            count++;
+        }
+    }
+    return count;
+}
+
+audio_io_handle_t AudioInputCollection::getActiveInput(bool ignoreVirtualInputs)
+{
+    for (size_t i = 0; i < size(); i++) {
+        const sp<AudioInputDescriptor>  input_descriptor = valueAt(i);
+        if ((input_descriptor->mRefCount > 0)
+                && (!ignoreVirtualInputs || !is_virtual_input_device(input_descriptor->mDevice))) {
+            return keyAt(i);
+        }
+    }
+    return 0;
+}
+
+audio_devices_t AudioInputCollection::getSupportedDevices(audio_io_handle_t handle) const
+{
+    sp<AudioInputDescriptor> inputDesc = valueFor(handle);
+    audio_devices_t devices = inputDesc->mProfile->mSupportedDevices.types();
+    return devices;
+}
+
+status_t AudioInputCollection::dump(int fd) const
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+
+    snprintf(buffer, SIZE, "\nInputs dump:\n");
+    write(fd, buffer, strlen(buffer));
+    for (size_t i = 0; i < size(); i++) {
+        snprintf(buffer, SIZE, "- Input %d dump:\n", keyAt(i));
+        write(fd, buffer, strlen(buffer));
+        valueAt(i)->dump(fd);
+    }
+
+    return NO_ERROR;
+}
+
 }; //namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 4c5509d..cdb5b51 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -23,10 +23,13 @@
 #include "HwModule.h"
 #include <media/AudioPolicy.h>
 
+// A device mask for all audio output devices that are considered "remote" when evaluating
+// active output devices in isStreamActiveRemotely()
+#define APM_AUDIO_OUT_DEVICE_REMOTE_ALL  AUDIO_DEVICE_OUT_REMOTE_SUBMIX
+
 namespace android {
 
-AudioOutputDescriptor::AudioOutputDescriptor(
-        const sp<IOProfile>& profile)
+AudioOutputDescriptor::AudioOutputDescriptor(const sp<IOProfile>& profile)
     : mId(0), mIoHandle(0), mLatency(0),
     mFlags((audio_output_flags_t)0), mDevice(AUDIO_DEVICE_NONE), mPolicyMix(NULL),
     mPatchHandle(0),
@@ -53,6 +56,11 @@
     }
 }
 
+audio_module_handle_t AudioOutputDescriptor::getModuleHandle() const
+{
+    return mProfile->getModuleHandle();
+}
+
 audio_devices_t AudioOutputDescriptor::device() const
 {
     if (isDuplicated()) {
@@ -134,8 +142,8 @@
 }
 
 bool AudioOutputDescriptor::isStreamActive(audio_stream_type_t stream,
-                                                                       uint32_t inPastMs,
-                                                                       nsecs_t sysTime) const
+                                           uint32_t inPastMs,
+                                           nsecs_t sysTime) const
 {
     if (mRefCount[stream] != 0) {
         return true;
@@ -218,6 +226,108 @@
     return NO_ERROR;
 }
 
+bool AudioOutputCollection::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const
+{
+    nsecs_t sysTime = systemTime();
+    for (size_t i = 0; i < this->size(); i++) {
+        const sp<AudioOutputDescriptor> outputDesc = this->valueAt(i);
+        if (outputDesc->isStreamActive(stream, inPastMs, sysTime)) {
+            return true;
+        }
+    }
+    return false;
+}
 
+bool AudioOutputCollection::isStreamActiveRemotely(audio_stream_type_t stream,
+                                                   uint32_t inPastMs) const
+{
+    nsecs_t sysTime = systemTime();
+    for (size_t i = 0; i < size(); i++) {
+        const sp<AudioOutputDescriptor> outputDesc = valueAt(i);
+        if (((outputDesc->device() & APM_AUDIO_OUT_DEVICE_REMOTE_ALL) != 0) &&
+                outputDesc->isStreamActive(stream, inPastMs, sysTime)) {
+            // do not consider re routing (when the output is going to a dynamic policy)
+            // as "remote playback"
+            if (outputDesc->mPolicyMix == NULL) {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+audio_io_handle_t AudioOutputCollection::getA2dpOutput() const
+{
+    for (size_t i = 0; i < size(); i++) {
+        sp<AudioOutputDescriptor> outputDesc = valueAt(i);
+        if (!outputDesc->isDuplicated() && outputDesc->device() & AUDIO_DEVICE_OUT_ALL_A2DP) {
+            return this->keyAt(i);
+        }
+    }
+    return 0;
+}
+
+sp<AudioOutputDescriptor> AudioOutputCollection::getPrimaryOutput() const
+{
+    for (size_t i = 0; i < size(); i++) {
+        const sp<AudioOutputDescriptor> outputDesc = valueAt(i);
+        if (outputDesc->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY) {
+            return outputDesc;
+        }
+    }
+    return NULL;
+}
+
+sp<AudioOutputDescriptor> AudioOutputCollection::getOutputFromId(audio_port_handle_t id) const
+{
+    sp<AudioOutputDescriptor> outputDesc = NULL;
+    for (size_t i = 0; i < size(); i++) {
+        outputDesc = valueAt(i);
+        if (outputDesc->mId == id) {
+            break;
+        }
+    }
+    return outputDesc;
+}
+
+bool AudioOutputCollection::isAnyOutputActive(audio_stream_type_t streamToIgnore) const
+{
+    for (size_t s = 0 ; s < AUDIO_STREAM_CNT ; s++) {
+        if (s == (size_t) streamToIgnore) {
+            continue;
+        }
+        for (size_t i = 0; i < size(); i++) {
+            const sp<AudioOutputDescriptor> outputDesc = valueAt(i);
+            if (outputDesc->mRefCount[s] != 0) {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+audio_devices_t AudioOutputCollection::getSupportedDevices(audio_io_handle_t handle) const
+{
+    sp<AudioOutputDescriptor> outputDesc = valueFor(handle);
+    audio_devices_t devices = outputDesc->mProfile->mSupportedDevices.types();
+    return devices;
+}
+
+
+status_t AudioOutputCollection::dump(int fd) const
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+
+    snprintf(buffer, SIZE, "\nOutputs dump:\n");
+    write(fd, buffer, strlen(buffer));
+    for (size_t i = 0; i < size(); i++) {
+        snprintf(buffer, SIZE, "- Output %d dump:\n", keyAt(i));
+        write(fd, buffer, strlen(buffer));
+        valueAt(i)->dump(fd);
+    }
+
+    return NO_ERROR;
+}
 
 }; //namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp
index 89e7f81..3a317fa 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp
@@ -18,6 +18,7 @@
 //#define LOG_NDEBUG 0
 
 #include "AudioPatch.h"
+#include "AudioGain.h"
 #include "ConfigParsingUtils.h"
 #include <cutils/log.h>
 #include <utils/String8.h>
@@ -81,4 +82,73 @@
     return NO_ERROR;
 }
 
+status_t AudioPatchCollection::addAudioPatch(audio_patch_handle_t handle,
+                                             const sp<AudioPatch>& patch)
+{
+    ssize_t index = indexOfKey(handle);
+
+    if (index >= 0) {
+        ALOGW("addAudioPatch() patch %d already in", handle);
+        return ALREADY_EXISTS;
+    }
+    add(handle, patch);
+    ALOGV("addAudioPatch() handle %d af handle %d num_sources %d num_sinks %d source handle %d"
+            "sink handle %d",
+          handle, patch->mAfPatchHandle, patch->mPatch.num_sources, patch->mPatch.num_sinks,
+          patch->mPatch.sources[0].id, patch->mPatch.sinks[0].id);
+    return NO_ERROR;
+}
+
+status_t AudioPatchCollection::removeAudioPatch(audio_patch_handle_t handle)
+{
+    ssize_t index = indexOfKey(handle);
+
+    if (index < 0) {
+        ALOGW("removeAudioPatch() patch %d not in", handle);
+        return ALREADY_EXISTS;
+    }
+    ALOGV("removeAudioPatch() handle %d af handle %d", handle, valueAt(index)->mAfPatchHandle);
+    removeItemsAt(index);
+    return NO_ERROR;
+}
+
+status_t AudioPatchCollection::listAudioPatches(unsigned int *num_patches,
+                                                struct audio_patch *patches) const
+{
+    if (num_patches == NULL || (*num_patches != 0 && patches == NULL)) {
+        return BAD_VALUE;
+    }
+    ALOGV("listAudioPatches() num_patches %d patches %p available patches %zu",
+          *num_patches, patches, size());
+    if (patches == NULL) {
+        *num_patches = 0;
+    }
+
+    size_t patchesWritten = 0;
+    size_t patchesMax = *num_patches;
+    for (size_t i = 0; i  < size() && patchesWritten < patchesMax; i++) {
+        const sp<AudioPatch>  patch = valueAt(i);
+        patches[patchesWritten] = patch->mPatch;
+        patches[patchesWritten++].id = patch->mHandle;
+        ALOGV("listAudioPatches() patch %zu num_sources %d num_sinks %d",
+              i, patch->mPatch.num_sources, patch->mPatch.num_sinks);
+    }
+    *num_patches = size();
+
+    ALOGV("listAudioPatches() got %zu patches needed %d", patchesWritten, *num_patches);
+    return NO_ERROR;
+}
+
+status_t AudioPatchCollection::dump(int fd) const
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    snprintf(buffer, SIZE, "\nAudio Patches:\n");
+    write(fd, buffer, strlen(buffer));
+    for (size_t i = 0; i < size(); i++) {
+        valueAt(i)->dump(fd, 2, i);
+    }
+    return NO_ERROR;
+}
+
 }; // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
index d34aac1..46a119e 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
@@ -22,6 +22,7 @@
 #include "AudioGain.h"
 #include "ConfigParsingUtils.h"
 #include "audio_policy_conf.h"
+#include <policy.h>
 
 namespace android {
 
@@ -30,7 +31,7 @@
 // --- AudioPort class implementation
 
 AudioPort::AudioPort(const String8& name, audio_port_type_t type,
-          audio_port_role_t role, const sp<HwModule>& module) :
+                     audio_port_role_t role, const sp<HwModule>& module) :
     mName(name), mType(type), mRole(role), mModule(module), mFlags(0), mId(0)
 {
     mUseInChannelMask = ((type == AUDIO_PORT_TYPE_DEVICE) && (role == AUDIO_PORT_ROLE_SOURCE)) ||
@@ -48,6 +49,11 @@
     return static_cast<audio_port_handle_t>(android_atomic_inc(&mNextUniqueId));
 }
 
+audio_module_handle_t AudioPort::getModuleHandle() const
+{
+    return mModule->mHandle;
+}
+
 void AudioPort::toAudioPort(struct audio_port *port) const
 {
     port->role = mRole;
diff --git a/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp b/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp
index 300f35a..fe5bc5f 100644
--- a/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp
@@ -18,7 +18,10 @@
 //#define LOG_NDEBUG 0
 
 #include "ConfigParsingUtils.h"
+#include "AudioGain.h"
+#include <hardware/audio.h>
 #include <utils/Log.h>
+#include <cutils/misc.h>
 
 namespace android {
 
@@ -119,4 +122,167 @@
     return device;
 }
 
+//static
+void ConfigParsingUtils::loadHwModule(cnode *root, HwModuleCollection &hwModules,
+                                      DeviceVector &availableInputDevices,
+                                      DeviceVector &availableOutputDevices,
+                                      sp<DeviceDescriptor> &defaultOutputDevices,
+                                      bool &isSpeakerDrcEnable)
+{
+    status_t status = NAME_NOT_FOUND;
+    cnode *node;
+    sp<HwModule> module = new HwModule(root->name);
+
+    node = config_find(root, DEVICES_TAG);
+    if (node != NULL) {
+        node = node->first_child;
+        while (node) {
+            ALOGV("loadHwModule() loading device %s", node->name);
+            status_t tmpStatus = module->loadDevice(node);
+            if (status == NAME_NOT_FOUND || status == NO_ERROR) {
+                status = tmpStatus;
+            }
+            node = node->next;
+        }
+    }
+    node = config_find(root, OUTPUTS_TAG);
+    if (node != NULL) {
+        node = node->first_child;
+        while (node) {
+            ALOGV("loadHwModule() loading output %s", node->name);
+            status_t tmpStatus = module->loadOutput(node);
+            if (status == NAME_NOT_FOUND || status == NO_ERROR) {
+                status = tmpStatus;
+            }
+            node = node->next;
+        }
+    }
+    node = config_find(root, INPUTS_TAG);
+    if (node != NULL) {
+        node = node->first_child;
+        while (node) {
+            ALOGV("loadHwModule() loading input %s", node->name);
+            status_t tmpStatus = module->loadInput(node);
+            if (status == NAME_NOT_FOUND || status == NO_ERROR) {
+                status = tmpStatus;
+            }
+            node = node->next;
+        }
+    }
+    loadGlobalConfig(root, module, availableInputDevices, availableOutputDevices,
+                     defaultOutputDevices, isSpeakerDrcEnable);
+
+    if (status == NO_ERROR) {
+        hwModules.add(module);
+    }
+}
+
+//static
+void ConfigParsingUtils::loadHwModules(cnode *root, HwModuleCollection &hwModules,
+                                       DeviceVector &availableInputDevices,
+                                       DeviceVector &availableOutputDevices,
+                                       sp<DeviceDescriptor> &defaultOutputDevices,
+                                       bool &isSpeakerDrcEnabled)
+{
+    cnode *node = config_find(root, AUDIO_HW_MODULE_TAG);
+    if (node == NULL) {
+        return;
+    }
+
+    node = node->first_child;
+    while (node) {
+        ALOGV("loadHwModules() loading module %s", node->name);
+        loadHwModule(node, hwModules, availableInputDevices, availableOutputDevices,
+                     defaultOutputDevices, isSpeakerDrcEnabled);
+        node = node->next;
+    }
+}
+
+//static
+void ConfigParsingUtils::loadGlobalConfig(cnode *root, const sp<HwModule>& module,
+                                          DeviceVector &availableInputDevices,
+                                          DeviceVector &availableOutputDevices,
+                                          sp<DeviceDescriptor> &defaultOutputDevice,
+                                          bool &speakerDrcEnabled)
+{
+    cnode *node = config_find(root, GLOBAL_CONFIG_TAG);
+
+    if (node == NULL) {
+        return;
+    }
+    DeviceVector declaredDevices;
+    if (module != NULL) {
+        declaredDevices = module->mDeclaredDevices;
+    }
+
+    node = node->first_child;
+    while (node) {
+        if (strcmp(ATTACHED_OUTPUT_DEVICES_TAG, node->name) == 0) {
+            availableOutputDevices.loadDevicesFromName((char *)node->value,
+                                                        declaredDevices);
+            ALOGV("loadGlobalConfig() Attached Output Devices %08x",
+                  availableOutputDevices.types());
+        } else if (strcmp(DEFAULT_OUTPUT_DEVICE_TAG, node->name) == 0) {
+            audio_devices_t device = (audio_devices_t)stringToEnum(
+                    sDeviceNameToEnumTable,
+                    ARRAY_SIZE(sDeviceNameToEnumTable),
+                    (char *)node->value);
+            if (device != AUDIO_DEVICE_NONE) {
+                defaultOutputDevice = new DeviceDescriptor(String8("default-output"), device);
+            } else {
+                ALOGW("loadGlobalConfig() default device not specified");
+            }
+            ALOGV("loadGlobalConfig() mDefaultOutputDevice %08x", defaultOutputDevice->type());
+        } else if (strcmp(ATTACHED_INPUT_DEVICES_TAG, node->name) == 0) {
+            availableInputDevices.loadDevicesFromName((char *)node->value,
+                                                       declaredDevices);
+            ALOGV("loadGlobalConfig() Available InputDevices %08x", availableInputDevices.types());
+        } else if (strcmp(SPEAKER_DRC_ENABLED_TAG, node->name) == 0) {
+            speakerDrcEnabled = stringToBool((char *)node->value);
+            ALOGV("loadGlobalConfig() mSpeakerDrcEnabled = %d", speakerDrcEnabled);
+        } else if (strcmp(AUDIO_HAL_VERSION_TAG, node->name) == 0) {
+            uint32_t major, minor;
+            sscanf((char *)node->value, "%u.%u", &major, &minor);
+            module->mHalVersion = HARDWARE_DEVICE_API_VERSION(major, minor);
+            ALOGV("loadGlobalConfig() mHalVersion = %04x major %u minor %u",
+                  module->mHalVersion, major, minor);
+        }
+        node = node->next;
+    }
+}
+
+//static
+status_t ConfigParsingUtils::loadAudioPolicyConfig(const char *path,
+                                                   HwModuleCollection &hwModules,
+                                                   DeviceVector &availableInputDevices,
+                                                   DeviceVector &availableOutputDevices,
+                                                   sp<DeviceDescriptor> &defaultOutputDevices,
+                                                   bool &isSpeakerDrcEnabled)
+{
+    cnode *root;
+    char *data;
+
+    data = (char *)load_file(path, NULL);
+    if (data == NULL) {
+        return -ENODEV;
+    }
+    root = config_node("", "");
+    config_load(root, data);
+
+    loadHwModules(root, hwModules,
+                  availableInputDevices, availableOutputDevices,
+                  defaultOutputDevices, isSpeakerDrcEnabled);
+    // legacy audio_policy.conf files have one global_configuration section
+    loadGlobalConfig(root, hwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY),
+                     availableInputDevices, availableOutputDevices,
+                     defaultOutputDevices, isSpeakerDrcEnabled);
+    config_free(root);
+    free(root);
+    free(data);
+
+    ALOGI("loadAudioPolicyConfig() loaded %s\n", path);
+
+    return NO_ERROR;
+}
+
 }; // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
index 7f098ab..7df7d75 100644
--- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
@@ -27,11 +27,11 @@
 String8 DeviceDescriptor::emptyNameStr = String8("");
 
 DeviceDescriptor::DeviceDescriptor(const String8& name, audio_devices_t type) :
-                     AudioPort(name, AUDIO_PORT_TYPE_DEVICE,
-                               audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK :
-                                                              AUDIO_PORT_ROLE_SOURCE,
-                             NULL),
-                     mDeviceType(type), mAddress("")
+    AudioPort(name, AUDIO_PORT_TYPE_DEVICE,
+              audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK :
+                                             AUDIO_PORT_ROLE_SOURCE,
+              NULL),
+    mAddress(""), mDeviceType(type)
 {
 
 }
@@ -60,7 +60,7 @@
 {
     mDeviceTypes = AUDIO_DEVICE_NONE;
     for(size_t i = 0; i < size(); i++) {
-        mDeviceTypes |= itemAt(i)->mDeviceType;
+        mDeviceTypes |= itemAt(i)->type();
     }
     ALOGV("DeviceVector::refreshTypes() mDeviceTypes %08x", mDeviceTypes);
 }
@@ -85,7 +85,7 @@
             refreshTypes();
         }
     } else {
-        ALOGW("DeviceVector::add device %08x already in", item->mDeviceType);
+        ALOGW("DeviceVector::add device %08x already in", item->type());
         ret = -1;
     }
     return ret;
@@ -97,7 +97,7 @@
     ssize_t ret = indexOf(item);
 
     if (ret < 0) {
-        ALOGW("DeviceVector::remove device %08x not in", item->mDeviceType);
+        ALOGW("DeviceVector::remove device %08x not in", item->type());
     } else {
         ret = SortedVector::removeAt(ret);
         if (ret >= 0) {
@@ -107,6 +107,17 @@
     return ret;
 }
 
+audio_devices_t DeviceVector::getDevicesFromHwModule(audio_module_handle_t moduleHandle) const
+{
+    audio_devices_t devices = AUDIO_DEVICE_NONE;
+    for (size_t i = 0; i < size(); i++) {
+        if (itemAt(i)->getModuleHandle() == moduleHandle) {
+            devices |= itemAt(i)->type();
+        }
+    }
+    return devices;
+}
+
 void DeviceVector::loadDevicesFromType(audio_devices_t types)
 {
     DeviceVector deviceList;
@@ -154,7 +165,7 @@
 {
     sp<DeviceDescriptor> device;
     for (size_t i = 0; i < size(); i++) {
-        if (itemAt(i)->mDeviceType == type) {
+        if (itemAt(i)->type() == type) {
             if (address == "" || itemAt(i)->mAddress == address) {
                 device = itemAt(i);
                 if (itemAt(i)->mAddress == address) {
@@ -192,7 +203,7 @@
             devices.add(itemAt(i));
             type &= ~curType;
             ALOGV("DeviceVector::getDevicesFromType() for type %x found %p",
-                  itemAt(i)->mDeviceType, itemAt(i).get());
+                  itemAt(i)->type(), itemAt(i).get());
         }
     }
     return devices;
@@ -203,7 +214,7 @@
 {
     DeviceVector devices;
     for (size_t i = 0; i < size(); i++) {
-        if (itemAt(i)->mDeviceType == type) {
+        if (itemAt(i)->type() == type) {
             if (itemAt(i)->mAddress == address) {
                 devices.add(itemAt(i));
             }
@@ -224,6 +235,26 @@
     return device;
 }
 
+
+status_t DeviceVector::dump(int fd, const String8 &direction) const
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+
+    snprintf(buffer, SIZE, "\n Available %s devices:\n", direction.string());
+    write(fd, buffer, strlen(buffer));
+    for (size_t i = 0; i < size(); i++) {
+        itemAt(i)->dump(fd, 2, i);
+    }
+    return NO_ERROR;
+}
+
+audio_policy_dev_state_t DeviceVector::getDeviceConnectionState(const sp<DeviceDescriptor> &devDesc) const
+{
+    ssize_t index = indexOf(devDesc);
+    return index >= 0 ? AUDIO_POLICY_DEVICE_STATE_AVAILABLE : AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
+}
+
 void DeviceDescriptor::toAudioPortConfig(struct audio_port_config *dstConfig,
                                          const struct audio_port_config *srcConfig) const
 {
diff --git a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
index a0ea185..8004303 100644
--- a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
@@ -23,6 +23,7 @@
 #include "ConfigParsingUtils.h"
 #include "audio_policy_conf.h"
 #include <hardware/audio.h>
+#include <policy.h>
 
 namespace android {
 
@@ -279,4 +280,92 @@
     }
 }
 
+sp <HwModule> HwModuleCollection::getModuleFromName(const char *name) const
+{
+    sp <HwModule> module;
+
+    for (size_t i = 0; i < size(); i++)
+    {
+        if (strcmp(itemAt(i)->mName, name) == 0) {
+            return itemAt(i);
+        }
+    }
+    return module;
+}
+
+
+sp <HwModule> HwModuleCollection::getModuleForDevice(audio_devices_t device) const
+{
+    sp <HwModule> module;
+
+    for (size_t i = 0; i < size(); i++) {
+        if (itemAt(i)->mHandle == 0) {
+            continue;
+        }
+        if (audio_is_output_device(device)) {
+            for (size_t j = 0; j < itemAt(i)->mOutputProfiles.size(); j++)
+            {
+                if (itemAt(i)->mOutputProfiles[j]->mSupportedDevices.types() & device) {
+                    return itemAt(i);
+                }
+            }
+        } else {
+            for (size_t j = 0; j < itemAt(i)->mInputProfiles.size(); j++) {
+                if (itemAt(i)->mInputProfiles[j]->mSupportedDevices.types() &
+                        device & ~AUDIO_DEVICE_BIT_IN) {
+                    return itemAt(i);
+                }
+            }
+        }
+    }
+    return module;
+}
+
+sp<DeviceDescriptor>  HwModuleCollection::getDeviceDescriptor(const audio_devices_t device,
+                                                              const char *device_address,
+                                                              const char *device_name) const
+{
+    String8 address = (device_address == NULL) ? String8("") : String8(device_address);
+    // handle legacy remote submix case where the address was not always specified
+    if (device_distinguishes_on_address(device) && (address.length() == 0)) {
+        address = String8("0");
+    }
+
+    for (size_t i = 0; i < size(); i++) {
+        const sp<HwModule> hwModule = itemAt(i);
+        if (hwModule->mHandle == 0) {
+            continue;
+        }
+        DeviceVector deviceList =
+                hwModule->mDeclaredDevices.getDevicesFromTypeAddr(device, address);
+        if (!deviceList.isEmpty()) {
+            return deviceList.itemAt(0);
+        }
+        deviceList = hwModule->mDeclaredDevices.getDevicesFromType(device);
+        if (!deviceList.isEmpty()) {
+            return deviceList.itemAt(0);
+        }
+    }
+
+    sp<DeviceDescriptor> devDesc =
+            new DeviceDescriptor(String8(device_name != NULL ? device_name : ""), device);
+    devDesc->mAddress = address;
+    return devDesc;
+}
+
+status_t HwModuleCollection::dump(int fd) const
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+
+    snprintf(buffer, SIZE, "\nHW Modules dump:\n");
+    write(fd, buffer, strlen(buffer));
+    for (size_t i = 0; i < size(); i++) {
+        snprintf(buffer, SIZE, "- HW Module %zu:\n", i + 1);
+        write(fd, buffer, strlen(buffer));
+        itemAt(i)->dump(fd);
+    }
+    return NO_ERROR;
+}
+
 } //namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
index 0214a2b..376dd22 100644
--- a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
@@ -37,12 +37,12 @@
 // Sampling rate, format and channel mask must be specified in order to
 // get a valid a match
 bool IOProfile::isCompatibleProfile(audio_devices_t device,
-                                                        String8 address,
-                                                        uint32_t samplingRate,
-                                                        uint32_t *updatedSamplingRate,
-                                                        audio_format_t format,
-                                                        audio_channel_mask_t channelMask,
-                                                        uint32_t flags) const
+                                    String8 address,
+                                    uint32_t samplingRate,
+                                    uint32_t *updatedSamplingRate,
+                                    audio_format_t format,
+                                    audio_channel_mask_t channelMask,
+                                    uint32_t flags) const
 {
     const bool isPlaybackThread = mType == AUDIO_PORT_TYPE_MIX && mRole == AUDIO_PORT_ROLE_SOURCE;
     const bool isRecordThread = mType == AUDIO_PORT_TYPE_MIX && mRole == AUDIO_PORT_ROLE_SINK;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index a110ada..033ae49 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -24,17 +24,6 @@
 #define ALOGVV(a...) do { } while(0)
 #endif
 
-// A device mask for all audio input devices that are considered "virtual" when evaluating
-// active inputs in getActiveInput()
-#define APM_AUDIO_IN_DEVICE_VIRTUAL_ALL  (AUDIO_DEVICE_IN_REMOTE_SUBMIX|AUDIO_DEVICE_IN_FM_TUNER)
-// A device mask for all audio output devices that are considered "remote" when evaluating
-// active output devices in isStreamActiveRemotely()
-#define APM_AUDIO_OUT_DEVICE_REMOTE_ALL  AUDIO_DEVICE_OUT_REMOTE_SUBMIX
-// A device mask for all audio input and output devices where matching inputs/outputs on device
-// type alone is not enough: the address must match too
-#define APM_AUDIO_DEVICE_MATCH_ADDRESS_ALL (AUDIO_DEVICE_IN_REMOTE_SUBMIX | \
-                                            AUDIO_DEVICE_OUT_REMOTE_SUBMIX)
-
 #include <inttypes.h>
 #include <math.h>
 
@@ -47,6 +36,8 @@
 #include <soundtrigger/SoundTrigger.h>
 #include "AudioPolicyManager.h"
 #include "audio_policy_conf.h"
+#include <ConfigParsingUtils.h>
+#include <policy.h>
 
 namespace android {
 
@@ -73,7 +64,8 @@
     // connect/disconnect only 1 device at a time
     if (!audio_is_output_device(device) && !audio_is_input_device(device)) return BAD_VALUE;
 
-    sp<DeviceDescriptor> devDesc = getDeviceDescriptor(device, device_address, device_name);
+    sp<DeviceDescriptor> devDesc =
+            mHwModules.getDeviceDescriptor(device, device_address, device_name);
 
     // handle output devices
     if (audio_is_output_device(device)) {
@@ -97,7 +89,7 @@
             // register new device as available
             index = mAvailableOutputDevices.add(devDesc);
             if (index >= 0) {
-                sp<HwModule> module = getModuleForDevice(device);
+                sp<HwModule> module = mHwModules.getModuleForDevice(device);
                 if (module == 0) {
                     ALOGD("setDeviceConnectionState() could not find HW module for device %08x",
                           device);
@@ -184,7 +176,7 @@
                 // also force a device 0 for the two outputs it is duplicated to which may override
                 // a valid device selection on those outputs.
                 bool force = !mOutputs.valueAt(i)->isDuplicated()
-                        && (!deviceDistinguishesOnAddress(device)
+                        && (!device_distinguishes_on_address(device)
                                 // always force when disconnecting (a non-duplicated device)
                                 || (state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE));
                 setOutputDevice(output, newDevice, force, 0);
@@ -208,7 +200,7 @@
                 ALOGW("setDeviceConnectionState() device already connected: %d", device);
                 return INVALID_OPERATION;
             }
-            sp<HwModule> module = getModuleForDevice(device);
+            sp<HwModule> module = mHwModules.getModuleForDevice(device);
             if (module == NULL) {
                 ALOGW("setDeviceConnectionState(): could not find HW module for device %08x",
                       device);
@@ -272,9 +264,10 @@
 }
 
 audio_policy_dev_state_t AudioPolicyManager::getDeviceConnectionState(audio_devices_t device,
-                                                  const char *device_address)
+                                                                      const char *device_address)
 {
-    sp<DeviceDescriptor> devDesc = getDeviceDescriptor(device, device_address, "");
+    sp<DeviceDescriptor> devDesc = mHwModules.getDeviceDescriptor(device, device_address, "");
+
     DeviceVector *deviceVector;
 
     if (audio_is_output_device(device)) {
@@ -285,44 +278,7 @@
         ALOGW("getDeviceConnectionState() invalid device type %08x", device);
         return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
     }
-
-    ssize_t index = deviceVector->indexOf(devDesc);
-    if (index >= 0) {
-        return AUDIO_POLICY_DEVICE_STATE_AVAILABLE;
-    } else {
-        return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
-    }
-}
-
-sp<DeviceDescriptor>  AudioPolicyManager::getDeviceDescriptor(const audio_devices_t device,
-                                                              const char *device_address,
-                                                              const char *device_name)
-{
-    String8 address = (device_address == NULL) ? String8("") : String8(device_address);
-    // handle legacy remote submix case where the address was not always specified
-    if (deviceDistinguishesOnAddress(device) && (address.length() == 0)) {
-        address = String8("0");
-    }
-
-    for (size_t i = 0; i < mHwModules.size(); i++) {
-        if (mHwModules[i]->mHandle == 0) {
-            continue;
-        }
-        DeviceVector deviceList =
-                mHwModules[i]->mDeclaredDevices.getDevicesFromTypeAddr(device, address);
-        if (!deviceList.isEmpty()) {
-            return deviceList.itemAt(0);
-        }
-        deviceList = mHwModules[i]->mDeclaredDevices.getDevicesFromType(device);
-        if (!deviceList.isEmpty()) {
-            return deviceList.itemAt(0);
-        }
-    }
-
-    sp<DeviceDescriptor> devDesc =
-            new DeviceDescriptor(String8(device_name != NULL ? device_name : ""), device);
-    devDesc->mAddress = address;
-    return devDesc;
+    return deviceVector->getDeviceConnectionState(devDesc);
 }
 
 void AudioPolicyManager::updateCallRouting(audio_devices_t rxDevice, int delayMs)
@@ -664,7 +620,7 @@
         }
     }
 
-    audio_io_handle_t activeInput = getActiveInput();
+    audio_io_handle_t activeInput = mInputs.getActiveInput();
     if (activeInput != 0) {
         setInputDevice(activeInput, getNewInputDevice(activeInput));
     }
@@ -709,11 +665,11 @@
 }
 
 audio_io_handle_t AudioPolicyManager::getOutput(audio_stream_type_t stream,
-                                    uint32_t samplingRate,
-                                    audio_format_t format,
-                                    audio_channel_mask_t channelMask,
-                                    audio_output_flags_t flags,
-                                    const audio_offload_info_t *offloadInfo)
+                                                uint32_t samplingRate,
+                                                audio_format_t format,
+                                                audio_channel_mask_t channelMask,
+                                                audio_output_flags_t flags,
+                                                const audio_offload_info_t *offloadInfo)
 {
     routing_strategy strategy = getStrategy(stream);
     audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/);
@@ -797,7 +753,7 @@
     }
 
     ALOGV("getOutputForAttr() usage=%d, content=%d, tag=%s flags=%08x",
-            attributes.usage, attributes.content_type, attributes.tags, attributes.flags);
+          attributes.usage, attributes.content_type, attributes.tags, attributes.flags);
 
     routing_strategy strategy = (routing_strategy) getStrategyForAttr(&attributes);
     audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/);
@@ -1093,7 +1049,7 @@
     uint32_t beaconMuteLatency = 0;
     if (stream == AUDIO_STREAM_TTS) {
         ALOGV("\t found BEACON stream");
-        if (isAnyOutputActive(AUDIO_STREAM_TTS /*streamToIgnore*/)) {
+        if (mOutputs.isAnyOutputActive(AUDIO_STREAM_TTS /*streamToIgnore*/)) {
             return INVALID_OPERATION;
         } else {
             beaconMuteLatency = handleEventForBeacon(STARTING_BEACON);
@@ -1272,7 +1228,7 @@
         sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(index);
         if (outputDesc->isActive()) {
             mpClientInterface->closeOutput(output);
-            mOutputs.removeItem(output);
+            removeOutput(output);
             mTestOutputs[testIndex] = 0;
         }
         return;
@@ -1480,10 +1436,10 @@
     }
 
     // virtual input devices are compatible with other input devices
-    if (!isVirtualInputDevice(inputDesc->mDevice)) {
+    if (!is_virtual_input_device(inputDesc->mDevice)) {
 
         // for a non-virtual input device, check if there is another (non-virtual) active input
-        audio_io_handle_t activeInput = getActiveInput();
+        audio_io_handle_t activeInput = mInputs.getActiveInput();
         if (activeInput != 0 && activeInput != input) {
 
             // If the already active input uses AUDIO_SOURCE_HOTWORD then it is closed,
@@ -1501,7 +1457,7 @@
     }
 
     if (inputDesc->mRefCount == 0) {
-        if (activeInputsCount() == 0) {
+        if (mInputs.activeInputsCount() == 0) {
             SoundTrigger::setCaptureState(true);
         }
         setInputDevice(input, getNewInputDevice(input), true /* force */);
@@ -1573,7 +1529,7 @@
 
         resetInputDevice(input);
 
-        if (activeInputsCount() == 0) {
+        if (mInputs.activeInputsCount() == 0) {
             SoundTrigger::setCaptureState(false);
         }
     }
@@ -1654,8 +1610,8 @@
 }
 
 status_t AudioPolicyManager::setStreamVolumeIndex(audio_stream_type_t stream,
-                                                      int index,
-                                                      audio_devices_t device)
+                                                  int index,
+                                                  audio_devices_t device)
 {
 
     if ((index < mStreams[stream].mIndexMin) || (index > mStreams[stream].mIndexMax)) {
@@ -1906,36 +1862,6 @@
     return false;
 }
 
-bool AudioPolicyManager::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const
-{
-    nsecs_t sysTime = systemTime();
-    for (size_t i = 0; i < mOutputs.size(); i++) {
-        const sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(i);
-        if (outputDesc->isStreamActive(stream, inPastMs, sysTime)) {
-            return true;
-        }
-    }
-    return false;
-}
-
-bool AudioPolicyManager::isStreamActiveRemotely(audio_stream_type_t stream,
-                                                    uint32_t inPastMs) const
-{
-    nsecs_t sysTime = systemTime();
-    for (size_t i = 0; i < mOutputs.size(); i++) {
-        const sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(i);
-        if (((outputDesc->device() & APM_AUDIO_OUT_DEVICE_REMOTE_ALL) != 0) &&
-                outputDesc->isStreamActive(stream, inPastMs, sysTime)) {
-            // do not consider re routing (when the output is going to a dynamic policy)
-            // as "remote playback"
-            if (outputDesc->mPolicyMix == NULL) {
-                return true;
-            }
-        }
-    }
-    return false;
-}
-
 bool AudioPolicyManager::isSourceActive(audio_source_t source) const
 {
     for (size_t i = 0; i < mInputs.size(); i++) {
@@ -2111,41 +2037,11 @@
             mForceUse[AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO]);
     result.append(buffer);
 
-    snprintf(buffer, SIZE, " Available output devices:\n");
-    result.append(buffer);
-    write(fd, result.string(), result.size());
-    for (size_t i = 0; i < mAvailableOutputDevices.size(); i++) {
-        mAvailableOutputDevices[i]->dump(fd, 2, i);
-    }
-    snprintf(buffer, SIZE, "\n Available input devices:\n");
-    write(fd, buffer, strlen(buffer));
-    for (size_t i = 0; i < mAvailableInputDevices.size(); i++) {
-        mAvailableInputDevices[i]->dump(fd, 2, i);
-    }
-
-    snprintf(buffer, SIZE, "\nHW Modules dump:\n");
-    write(fd, buffer, strlen(buffer));
-    for (size_t i = 0; i < mHwModules.size(); i++) {
-        snprintf(buffer, SIZE, "- HW Module %zu:\n", i + 1);
-        write(fd, buffer, strlen(buffer));
-        mHwModules[i]->dump(fd);
-    }
-
-    snprintf(buffer, SIZE, "\nOutputs dump:\n");
-    write(fd, buffer, strlen(buffer));
-    for (size_t i = 0; i < mOutputs.size(); i++) {
-        snprintf(buffer, SIZE, "- Output %d dump:\n", mOutputs.keyAt(i));
-        write(fd, buffer, strlen(buffer));
-        mOutputs.valueAt(i)->dump(fd);
-    }
-
-    snprintf(buffer, SIZE, "\nInputs dump:\n");
-    write(fd, buffer, strlen(buffer));
-    for (size_t i = 0; i < mInputs.size(); i++) {
-        snprintf(buffer, SIZE, "- Input %d dump:\n", mInputs.keyAt(i));
-        write(fd, buffer, strlen(buffer));
-        mInputs.valueAt(i)->dump(fd);
-    }
+    mAvailableOutputDevices.dump(fd, String8("output"));
+    mAvailableInputDevices.dump(fd, String8("input"));
+    mHwModules.dump(fd);
+    mOutputs.dump(fd);
+    mInputs.dump(fd);
 
     snprintf(buffer, SIZE, "\nStreams dump:\n");
     write(fd, buffer, strlen(buffer));
@@ -2170,11 +2066,7 @@
         mEffects.valueAt(i)->dump(fd);
     }
 
-    snprintf(buffer, SIZE, "\nAudio Patches:\n");
-    write(fd, buffer, strlen(buffer));
-    for (size_t i = 0; i < mAudioPatches.size(); i++) {
-        mAudioPatches[i]->dump(fd, 2, i);
-    }
+    mAudioPatches.dump(fd);
 
     return NO_ERROR;
 }
@@ -2310,93 +2202,6 @@
     return NO_ERROR;
 }
 
-sp<AudioOutputDescriptor> AudioPolicyManager::getOutputFromId(
-                                                                    audio_port_handle_t id) const
-{
-    sp<AudioOutputDescriptor> outputDesc = NULL;
-    for (size_t i = 0; i < mOutputs.size(); i++) {
-        outputDesc = mOutputs.valueAt(i);
-        if (outputDesc->mId == id) {
-            break;
-        }
-    }
-    return outputDesc;
-}
-
-sp<AudioInputDescriptor> AudioPolicyManager::getInputFromId(
-                                                                    audio_port_handle_t id) const
-{
-    sp<AudioInputDescriptor> inputDesc = NULL;
-    for (size_t i = 0; i < mInputs.size(); i++) {
-        inputDesc = mInputs.valueAt(i);
-        if (inputDesc->mId == id) {
-            break;
-        }
-    }
-    return inputDesc;
-}
-
-sp <HwModule> AudioPolicyManager::getModuleForDevice(
-                                                                    audio_devices_t device) const
-{
-    sp <HwModule> module;
-
-    for (size_t i = 0; i < mHwModules.size(); i++) {
-        if (mHwModules[i]->mHandle == 0) {
-            continue;
-        }
-        if (audio_is_output_device(device)) {
-            for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++)
-            {
-                if (mHwModules[i]->mOutputProfiles[j]->mSupportedDevices.types() & device) {
-                    return mHwModules[i];
-                }
-            }
-        } else {
-            for (size_t j = 0; j < mHwModules[i]->mInputProfiles.size(); j++) {
-                if (mHwModules[i]->mInputProfiles[j]->mSupportedDevices.types() &
-                        device & ~AUDIO_DEVICE_BIT_IN) {
-                    return mHwModules[i];
-                }
-            }
-        }
-    }
-    return module;
-}
-
-sp <HwModule> AudioPolicyManager::getModuleFromName(const char *name) const
-{
-    sp <HwModule> module;
-
-    for (size_t i = 0; i < mHwModules.size(); i++)
-    {
-        if (strcmp(mHwModules[i]->mName, name) == 0) {
-            return mHwModules[i];
-        }
-    }
-    return module;
-}
-
-audio_devices_t AudioPolicyManager::availablePrimaryOutputDevices()
-{
-    sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(mPrimaryOutput);
-    audio_devices_t devices = outputDesc->mProfile->mSupportedDevices.types();
-    return devices & mAvailableOutputDevices.types();
-}
-
-audio_devices_t AudioPolicyManager::availablePrimaryInputDevices()
-{
-    audio_module_handle_t primaryHandle =
-                                mOutputs.valueFor(mPrimaryOutput)->mProfile->mModule->mHandle;
-    audio_devices_t devices = AUDIO_DEVICE_NONE;
-    for (size_t i = 0; i < mAvailableInputDevices.size(); i++) {
-        if (mAvailableInputDevices[i]->mModule->mHandle == primaryHandle) {
-            devices |= mAvailableInputDevices[i]->mDeviceType;
-        }
-    }
-    return devices;
-}
-
 status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch,
                                                audio_patch_handle_t *handle,
                                                uid_t uid)
@@ -2452,7 +2257,7 @@
     }
 
     if (patch->sources[0].type == AUDIO_PORT_TYPE_MIX) {
-        sp<AudioOutputDescriptor> outputDesc = getOutputFromId(patch->sources[0].id);
+        sp<AudioOutputDescriptor> outputDesc = mOutputs.getOutputFromId(patch->sources[0].id);
         if (outputDesc == NULL) {
             ALOGV("createAudioPatch() output not found for id %d", patch->sources[0].id);
             return BAD_VALUE;
@@ -2481,15 +2286,14 @@
                 return BAD_VALUE;
             }
 
-            if (!outputDesc->mProfile->isCompatibleProfile(devDesc->mDeviceType,
+            if (!outputDesc->mProfile->isCompatibleProfile(devDesc->type(),
                                                            devDesc->mAddress,
                                                            patch->sources[0].sample_rate,
-                                                         NULL,  // updatedSamplingRate
-                                                         patch->sources[0].format,
-                                                         patch->sources[0].channel_mask,
-                                                         AUDIO_OUTPUT_FLAG_NONE /*FIXME*/)) {
-                ALOGV("createAudioPatch() profile not supported for device %08x",
-                      devDesc->mDeviceType);
+                                                           NULL,  // updatedSamplingRate
+                                                           patch->sources[0].format,
+                                                           patch->sources[0].channel_mask,
+                                                           AUDIO_OUTPUT_FLAG_NONE /*FIXME*/)) {
+                ALOGV("createAudioPatch() profile not supported for device %08x", devDesc->type());
                 return INVALID_OPERATION;
             }
             devices.add(devDesc);
@@ -2521,7 +2325,7 @@
             if (patch->num_sinks > 1) {
                 return INVALID_OPERATION;
             }
-            sp<AudioInputDescriptor> inputDesc = getInputFromId(patch->sinks[0].id);
+            sp<AudioInputDescriptor> inputDesc = mInputs.getInputFromId(patch->sinks[0].id);
             if (inputDesc == NULL) {
                 return BAD_VALUE;
             }
@@ -2536,7 +2340,7 @@
                 return BAD_VALUE;
             }
 
-            if (!inputDesc->mProfile->isCompatibleProfile(devDesc->mDeviceType,
+            if (!inputDesc->mProfile->isCompatibleProfile(devDesc->type(),
                                                           devDesc->mAddress,
                                                           patch->sinks[0].sample_rate,
                                                           NULL, /*updatedSampleRate*/
@@ -2550,8 +2354,8 @@
             }
             // TODO: reconfigure output format and channels here
             ALOGV("createAudioPatch() setting device %08x on output %d",
-                                                  devDesc->mDeviceType, inputDesc->mIoHandle);
-            setInputDevice(inputDesc->mIoHandle, devDesc->mDeviceType, true, handle);
+                                                  devDesc->type(), inputDesc->mIoHandle);
+            setInputDevice(inputDesc->mIoHandle, devDesc->type(), true, handle);
             index = mAudioPatches.indexOfKey(*handle);
             if (index >= 0) {
                 if (patchDesc != 0 && patchDesc != mAudioPatches.valueAt(index)) {
@@ -2601,8 +2405,7 @@
                         return INVALID_OPERATION;
                     }
                     SortedVector<audio_io_handle_t> outputs =
-                                            getOutputsForDevice(sinkDeviceDesc->mDeviceType,
-                                                                mOutputs);
+                                            getOutputsForDevice(sinkDeviceDesc->type(), mOutputs);
                     // if the sink device is reachable via an opened output stream, request to go via
                     // this output stream by adding a second source to the patch description
                     audio_io_handle_t output = selectOutput(outputs,
@@ -2675,7 +2478,7 @@
     struct audio_patch *patch = &patchDesc->mPatch;
     patchDesc->mUid = mUidCached;
     if (patch->sources[0].type == AUDIO_PORT_TYPE_MIX) {
-        sp<AudioOutputDescriptor> outputDesc = getOutputFromId(patch->sources[0].id);
+        sp<AudioOutputDescriptor> outputDesc = mOutputs.getOutputFromId(patch->sources[0].id);
         if (outputDesc == NULL) {
             ALOGV("releaseAudioPatch() output not found for id %d", patch->sources[0].id);
             return BAD_VALUE;
@@ -2688,7 +2491,7 @@
                        NULL);
     } else if (patch->sources[0].type == AUDIO_PORT_TYPE_DEVICE) {
         if (patch->sinks[0].type == AUDIO_PORT_TYPE_MIX) {
-            sp<AudioInputDescriptor> inputDesc = getInputFromId(patch->sinks[0].id);
+            sp<AudioInputDescriptor> inputDesc = mInputs.getInputFromId(patch->sinks[0].id);
             if (inputDesc == NULL) {
                 ALOGV("releaseAudioPatch() input not found for id %d", patch->sinks[0].id);
                 return BAD_VALUE;
@@ -2718,30 +2521,11 @@
                                               struct audio_patch *patches,
                                               unsigned int *generation)
 {
-    if (num_patches == NULL || (*num_patches != 0 && patches == NULL) ||
-            generation == NULL) {
+    if (generation == NULL) {
         return BAD_VALUE;
     }
-    ALOGV("listAudioPatches() num_patches %d patches %p available patches %zu",
-          *num_patches, patches, mAudioPatches.size());
-    if (patches == NULL) {
-        *num_patches = 0;
-    }
-
-    size_t patchesWritten = 0;
-    size_t patchesMax = *num_patches;
-    for (size_t i = 0;
-            i  < mAudioPatches.size() && patchesWritten < patchesMax; i++) {
-        patches[patchesWritten] = mAudioPatches[i]->mPatch;
-        patches[patchesWritten++].id = mAudioPatches[i]->mHandle;
-        ALOGV("listAudioPatches() patch %zu num_sources %d num_sinks %d",
-              i, mAudioPatches[i]->mPatch.num_sources, mAudioPatches[i]->mPatch.num_sinks);
-    }
-    *num_patches = mAudioPatches.size();
-
     *generation = curAudioPortGeneration();
-    ALOGV("listAudioPatches() got %zu patches needed %d", patchesWritten, *num_patches);
-    return NO_ERROR;
+    return mAudioPatches.listAudioPatches(num_patches, patches);
 }
 
 status_t AudioPolicyManager::setAudioPortConfig(const struct audio_port_config *config)
@@ -2760,7 +2544,7 @@
     sp<AudioPortConfig> audioPortConfig;
     if (config->type == AUDIO_PORT_TYPE_MIX) {
         if (config->role == AUDIO_PORT_ROLE_SOURCE) {
-            sp<AudioOutputDescriptor> outputDesc = getOutputFromId(config->id);
+            sp<AudioOutputDescriptor> outputDesc = mOutputs.getOutputFromId(config->id);
             if (outputDesc == NULL) {
                 return BAD_VALUE;
             }
@@ -2769,7 +2553,7 @@
                         outputDesc->mIoHandle);
             audioPortConfig = outputDesc;
         } else if (config->role == AUDIO_PORT_ROLE_SINK) {
-            sp<AudioInputDescriptor> inputDesc = getInputFromId(config->id);
+            sp<AudioInputDescriptor> inputDesc = mInputs.getInputFromId(config->id);
             if (inputDesc == NULL) {
                 return BAD_VALUE;
             }
@@ -2843,37 +2627,6 @@
     return NO_ERROR;
 }
 
-status_t AudioPolicyManager::addAudioPatch(audio_patch_handle_t handle,
-                                           const sp<AudioPatch>& patch)
-{
-    ssize_t index = mAudioPatches.indexOfKey(handle);
-
-    if (index >= 0) {
-        ALOGW("addAudioPatch() patch %d already in", handle);
-        return ALREADY_EXISTS;
-    }
-    mAudioPatches.add(handle, patch);
-    ALOGV("addAudioPatch() handle %d af handle %d num_sources %d num_sinks %d source handle %d"
-            "sink handle %d",
-          handle, patch->mAfPatchHandle, patch->mPatch.num_sources, patch->mPatch.num_sinks,
-          patch->mPatch.sources[0].id, patch->mPatch.sinks[0].id);
-    return NO_ERROR;
-}
-
-status_t AudioPolicyManager::removeAudioPatch(audio_patch_handle_t handle)
-{
-    ssize_t index = mAudioPatches.indexOfKey(handle);
-
-    if (index < 0) {
-        ALOGW("removeAudioPatch() patch %d not in", handle);
-        return ALREADY_EXISTS;
-    }
-    ALOGV("removeAudioPatch() handle %d af handle %d", handle,
-                      mAudioPatches.valueAt(index)->mAfPatchHandle);
-    mAudioPatches.removeItemsAt(index);
-    return NO_ERROR;
-}
-
 // ----------------------------------------------------------------------------
 // AudioPolicyManager
 // ----------------------------------------------------------------------------
@@ -2906,8 +2659,12 @@
     }
 
     mDefaultOutputDevice = new DeviceDescriptor(String8("Speaker"), AUDIO_DEVICE_OUT_SPEAKER);
-    if (loadAudioPolicyConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE) != NO_ERROR) {
-        if (loadAudioPolicyConfig(AUDIO_POLICY_CONFIG_FILE) != NO_ERROR) {
+    if (ConfigParsingUtils::loadAudioPolicyConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE,
+                 mHwModules, mAvailableInputDevices, mAvailableOutputDevices,
+                 mDefaultOutputDevice, mSpeakerDrcEnabled) != NO_ERROR) {
+        if (ConfigParsingUtils::loadAudioPolicyConfig(AUDIO_POLICY_CONFIG_FILE,
+                                  mHwModules, mAvailableInputDevices, mAvailableOutputDevices,
+                                  mDefaultOutputDevice, mSpeakerDrcEnabled) != NO_ERROR) {
             ALOGE("could not load audio policy configuration file, setting defaults");
             defaultAudioPolicyConfig();
         }
@@ -2943,13 +2700,13 @@
                 continue;
             }
             audio_devices_t profileType = outProfile->mSupportedDevices.types();
-            if ((profileType & mDefaultOutputDevice->mDeviceType) != AUDIO_DEVICE_NONE) {
-                profileType = mDefaultOutputDevice->mDeviceType;
+            if ((profileType & mDefaultOutputDevice->type()) != AUDIO_DEVICE_NONE) {
+                profileType = mDefaultOutputDevice->type();
             } else {
                 // chose first device present in mSupportedDevices also part of
                 // outputDeviceTypes
                 for (size_t k = 0; k  < outProfile->mSupportedDevices.size(); k++) {
-                    profileType = outProfile->mSupportedDevices[k]->mDeviceType;
+                    profileType = outProfile->mSupportedDevices[k]->type();
                     if ((profileType & outputDeviceTypes) != 0) {
                         break;
                     }
@@ -2984,7 +2741,7 @@
                 outputDesc->mFormat = config.format;
 
                 for (size_t k = 0; k  < outProfile->mSupportedDevices.size(); k++) {
-                    audio_devices_t type = outProfile->mSupportedDevices[k]->mDeviceType;
+                    audio_devices_t type = outProfile->mSupportedDevices[k]->type();
                     ssize_t index =
                             mAvailableOutputDevices.indexOf(outProfile->mSupportedDevices[k]);
                     // give a valid ID to an attached device once confirmed it is reachable
@@ -3016,7 +2773,7 @@
             // inputDeviceTypes
             audio_devices_t profileType = AUDIO_DEVICE_NONE;
             for (size_t k = 0; k  < inProfile->mSupportedDevices.size(); k++) {
-                profileType = inProfile->mSupportedDevices[k]->mDeviceType;
+                profileType = inProfile->mSupportedDevices[k]->type();
                 if (profileType & inputDeviceTypes) {
                     break;
                 }
@@ -3052,7 +2809,7 @@
 
             if (status == NO_ERROR) {
                 for (size_t k = 0; k  < inProfile->mSupportedDevices.size(); k++) {
-                    audio_devices_t type = inProfile->mSupportedDevices[k]->mDeviceType;
+                    audio_devices_t type = inProfile->mSupportedDevices[k]->type();
                     ssize_t index =
                             mAvailableInputDevices.indexOf(inProfile->mSupportedDevices[k]);
                     // give a valid ID to an attached device once confirmed it is reachable
@@ -3071,7 +2828,7 @@
     // make sure all attached devices have been allocated a unique ID
     for (size_t i = 0; i  < mAvailableOutputDevices.size();) {
         if (!mAvailableOutputDevices[i]->isAttached()) {
-            ALOGW("Input device %08x unreachable", mAvailableOutputDevices[i]->mDeviceType);
+            ALOGW("Input device %08x unreachable", mAvailableOutputDevices[i]->type());
             mAvailableOutputDevices.remove(mAvailableOutputDevices[i]);
             continue;
         }
@@ -3079,7 +2836,7 @@
     }
     for (size_t i = 0; i  < mAvailableInputDevices.size();) {
         if (!mAvailableInputDevices[i]->isAttached()) {
-            ALOGW("Input device %08x unreachable", mAvailableInputDevices[i]->mDeviceType);
+            ALOGW("Input device %08x unreachable", mAvailableInputDevices[i]->type());
             mAvailableInputDevices.remove(mAvailableInputDevices[i]);
             continue;
         }
@@ -3087,7 +2844,7 @@
     }
     // make sure default device is reachable
     if (mAvailableOutputDevices.indexOf(mDefaultOutputDevice) < 0) {
-        ALOGE("Default device %08x is unreachable", mDefaultOutputDevice->mDeviceType);
+        ALOGE("Default device %08x is unreachable", mDefaultOutputDevice->type());
     }
 
     ALOGE_IF((mPrimaryOutput == 0), "Failed to open primary output");
@@ -3243,8 +3000,7 @@
 
                 audio_module_handle_t moduleHandle = outputDesc->mModule->mHandle;
 
-                mOutputs.removeItem(mPrimaryOutput);
-
+                removeOutput(mPrimaryOutput);
                 sp<AudioOutputDescriptor> outputDesc = new AudioOutputDescriptor(NULL);
                 outputDesc->mDevice = AUDIO_DEVICE_OUT_SPEAKER;
                 audio_config_t config = AUDIO_CONFIG_INITIALIZER;
@@ -3308,6 +3064,11 @@
     nextAudioPortGeneration();
 }
 
+void AudioPolicyManager::removeOutput(audio_io_handle_t output)
+{
+    mOutputs.removeItem(output);
+}
+
 void AudioPolicyManager::addInput(audio_io_handle_t input, sp<AudioInputDescriptor> inputDesc)
 {
     inputDesc->setIoHandle(input);
@@ -3329,11 +3090,11 @@
 }
 
 status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor> devDesc,
-                                                       audio_policy_dev_state_t state,
-                                                       SortedVector<audio_io_handle_t>& outputs,
-                                                       const String8 address)
+                                                   audio_policy_dev_state_t state,
+                                                   SortedVector<audio_io_handle_t>& outputs,
+                                                   const String8 address)
 {
-    audio_devices_t device = devDesc->mDeviceType;
+    audio_devices_t device = devDesc->type();
     sp<AudioOutputDescriptor> desc;
     // erase all current sample rates, formats and channel masks
     devDesc->clearCapabilities();
@@ -3343,7 +3104,7 @@
         for (size_t i = 0; i < mOutputs.size(); i++) {
             desc = mOutputs.valueAt(i);
             if (!desc->isDuplicated() && (desc->mProfile->mSupportedDevices.types() & device)) {
-                if (!deviceDistinguishesOnAddress(device)) {
+                if (!device_distinguishes_on_address(device)) {
                     ALOGV("checkOutputsForDevice(): adding opened output %d", mOutputs.keyAt(i));
                     outputs.add(mOutputs.keyAt(i));
                 } else {
@@ -3363,7 +3124,7 @@
             {
                 sp<IOProfile> profile = mHwModules[i]->mOutputProfiles[j];
                 if (profile->mSupportedDevices.types() & device) {
-                    if (!deviceDistinguishesOnAddress(device) ||
+                    if (!device_distinguishes_on_address(device) ||
                             address == profile->mSupportedDevices[0]->mAddress) {
                         profiles.add(profile);
                         ALOGV("checkOutputsForDevice(): adding profile %zu from module %zu", j, i);
@@ -3499,7 +3260,7 @@
 
                 if (output != AUDIO_IO_HANDLE_NONE) {
                     addOutput(output, desc);
-                    if (deviceDistinguishesOnAddress(device) && address != "0") {
+                    if (device_distinguishes_on_address(device) && address != "0") {
                         ssize_t index = mPolicyMixes.indexOfKey(address);
                         if (index >= 0) {
                             mPolicyMixes[index]->mOutput = desc;
@@ -3537,7 +3298,7 @@
                             ALOGW("checkOutputsForDevice() could not open dup output for %d and %d",
                                     mPrimaryOutput, output);
                             mpClientInterface->closeOutput(output);
-                            mOutputs.removeItem(output);
+                            removeOutput(output);
                             nextAudioPortGeneration();
                             output = AUDIO_IO_HANDLE_NONE;
                         }
@@ -3554,7 +3315,7 @@
                 outputs.add(output);
                 devDesc->importAudioPort(profile);
 
-                if (deviceDistinguishesOnAddress(device)) {
+                if (device_distinguishes_on_address(device)) {
                     ALOGV("checkOutputsForDevice(): setOutputDevice(dev=0x%x, addr=%s)",
                             device, address.string());
                     setOutputDevice(output, device, true/*force*/, 0/*delay*/,
@@ -3574,7 +3335,7 @@
             desc = mOutputs.valueAt(i);
             if (!desc->isDuplicated()) {
                 // exact match on device
-                if (deviceDistinguishesOnAddress(device) &&
+                if (device_distinguishes_on_address(device) &&
                         (desc->mProfile->mSupportedDevices.types() == device)) {
                     findIoHandlesByAddress(desc, device, address, outputs);
                 } else if (!(desc->mProfile->mSupportedDevices.types()
@@ -3617,9 +3378,9 @@
 }
 
 status_t AudioPolicyManager::checkInputsForDevice(audio_devices_t device,
-                                                      audio_policy_dev_state_t state,
-                                                      SortedVector<audio_io_handle_t>& inputs,
-                                                      const String8 address)
+                                                  audio_policy_dev_state_t state,
+                                                  SortedVector<audio_io_handle_t>& inputs,
+                                                  const String8 address)
 {
     sp<AudioInputDescriptor> desc;
     if (state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
@@ -3646,7 +3407,7 @@
                 sp<IOProfile> profile = mHwModules[module_idx]->mInputProfiles[profile_index];
 
                 if (profile->mSupportedDevices.types() & (device & ~AUDIO_DEVICE_BIT_IN)) {
-                    if (!deviceDistinguishesOnAddress(device) ||
+                    if (!device_distinguishes_on_address(device) ||
                             address == profile->mSupportedDevices[0]->mAddress) {
                         profiles.add(profile);
                         ALOGV("checkInputsForDevice(): adding profile %zu from module %zu",
@@ -3849,7 +3610,7 @@
             ALOGV("closeOutput() closing also duplicated output %d", duplicatedOutput);
 
             mpClientInterface->closeOutput(duplicatedOutput);
-            mOutputs.removeItem(duplicatedOutput);
+            removeOutput(duplicatedOutput);
         }
     }
 
@@ -3868,7 +3629,7 @@
     mpClientInterface->setParameters(output, param.toString());
 
     mpClientInterface->closeOutput(output);
-    mOutputs.removeItem(output);
+    removeOutput(output);
     mPreviousOutputs = mOutputs;
 }
 
@@ -3897,7 +3658,7 @@
 }
 
 SortedVector<audio_io_handle_t> AudioPolicyManager::getOutputsForDevice(audio_devices_t device,
-                        DefaultKeyedVector<audio_io_handle_t, sp<AudioOutputDescriptor> > openOutputs)
+                                                                        AudioOutputCollection openOutputs)
 {
     SortedVector<audio_io_handle_t> outputs;
 
@@ -3914,7 +3675,7 @@
 }
 
 bool AudioPolicyManager::vectorsEqual(SortedVector<audio_io_handle_t>& outputs1,
-                                   SortedVector<audio_io_handle_t>& outputs2)
+                                      SortedVector<audio_io_handle_t>& outputs2)
 {
     if (outputs1.size() != outputs2.size()) {
         return false;
@@ -4010,21 +3771,9 @@
     checkOutputForStrategy(STRATEGY_REROUTING);
 }
 
-audio_io_handle_t AudioPolicyManager::getA2dpOutput()
-{
-    for (size_t i = 0; i < mOutputs.size(); i++) {
-        sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(i);
-        if (!outputDesc->isDuplicated() && outputDesc->device() & AUDIO_DEVICE_OUT_ALL_A2DP) {
-            return mOutputs.keyAt(i);
-        }
-    }
-
-    return 0;
-}
-
 void AudioPolicyManager::checkA2dpSuspend()
 {
-    audio_io_handle_t a2dpOutput = getA2dpOutput();
+    audio_io_handle_t a2dpOutput = mOutputs.getA2dpOutput();
     if (a2dpOutput == 0) {
         mA2dpSuspended = false;
         return;
@@ -4280,21 +4029,6 @@
     }
 }
 
-bool AudioPolicyManager::isAnyOutputActive(audio_stream_type_t streamToIgnore) {
-    for (size_t s = 0 ; s < AUDIO_STREAM_CNT ; s++) {
-        if (s == (size_t) streamToIgnore) {
-            continue;
-        }
-        for (size_t i = 0; i < mOutputs.size(); i++) {
-            const sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(i);
-            if (outputDesc->mRefCount[s] != 0) {
-                return true;
-            }
-        }
-    }
-    return false;
-}
-
 uint32_t AudioPolicyManager::handleEventForBeacon(int event) {
     switch(event) {
     case STARTING_OUTPUT:
@@ -4349,7 +4083,7 @@
 }
 
 audio_devices_t AudioPolicyManager::getDeviceForStrategy(routing_strategy strategy,
-                                                             bool fromCache)
+                                                         bool fromCache)
 {
     uint32_t device = AUDIO_DEVICE_NONE;
 
@@ -4442,7 +4176,7 @@
             // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP
             if (!isInCall() &&
                     (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
-                    (getA2dpOutput() != 0)) {
+                    (mOutputs.getA2dpOutput() != 0)) {
                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
                 if (device) break;
                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
@@ -4466,7 +4200,7 @@
             }
             device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_EARPIECE;
             if (device) break;
-            device = mDefaultOutputDevice->mDeviceType;
+            device = mDefaultOutputDevice->type();
             if (device == AUDIO_DEVICE_NONE) {
                 ALOGE("getDeviceForStrategy() no device found for STRATEGY_PHONE");
             }
@@ -4477,7 +4211,7 @@
             // A2DP speaker when forcing to speaker output
             if (!isInCall() &&
                     (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
-                    (getA2dpOutput() != 0)) {
+                    (mOutputs.getA2dpOutput() != 0)) {
                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
                 if (device) break;
             }
@@ -4497,7 +4231,7 @@
             if (device) break;
             device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPEAKER;
             if (device) break;
-            device = mDefaultOutputDevice->mDeviceType;
+            device = mDefaultOutputDevice->type();
             if (device == AUDIO_DEVICE_NONE) {
                 ALOGE("getDeviceForStrategy() no device found for STRATEGY_PHONE, FORCE_SPEAKER");
             }
@@ -4559,7 +4293,7 @@
         }
         if ((device2 == AUDIO_DEVICE_NONE) &&
                 (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
-                (getA2dpOutput() != 0)) {
+                (mOutputs.getA2dpOutput() != 0)) {
             device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
             if (device2 == AUDIO_DEVICE_NONE) {
                 device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
@@ -4622,7 +4356,7 @@
         }
 
         if (device) break;
-        device = mDefaultOutputDevice->mDeviceType;
+        device = mDefaultOutputDevice->type();
         if (device == AUDIO_DEVICE_NONE) {
             ALOGE("getDeviceForStrategy() no device found for STRATEGY_MEDIA");
         }
@@ -4833,7 +4567,7 @@
         // inform all input as well
         for (size_t i = 0; i < mInputs.size(); i++) {
             const sp<AudioInputDescriptor>  inputDescriptor = mInputs.valueAt(i);
-            if (!isVirtualInputDevice(inputDescriptor->mDevice)) {
+            if (!is_virtual_input_device(inputDescriptor->mDevice)) {
                 AudioParameter inputCmd = AudioParameter();
                 ALOGV("%s: inform input %d of device:%d", __func__,
                       inputDescriptor->mIoHandle, device);
@@ -4963,11 +4697,11 @@
 }
 
 sp<IOProfile> AudioPolicyManager::getInputProfile(audio_devices_t device,
-                                                   String8 address,
-                                                   uint32_t& samplingRate,
-                                                   audio_format_t format,
-                                                   audio_channel_mask_t channelMask,
-                                                   audio_input_flags_t flags)
+                                                  String8 address,
+                                                  uint32_t& samplingRate,
+                                                  audio_format_t format,
+                                                  audio_channel_mask_t channelMask,
+                                                  audio_input_flags_t flags)
 {
     // Choose an input profile based on the requested capture parameters: select the first available
     // profile supporting all requested parameters.
@@ -4994,7 +4728,7 @@
 
 
 audio_devices_t AudioPolicyManager::getDeviceAndMixForInputSource(audio_source_t inputSource,
-                                                            AudioMix **policyMix)
+                                                                  AudioMix **policyMix)
 {
     audio_devices_t availableDeviceTypes = mAvailableInputDevices.types() &
                                             ~AUDIO_DEVICE_BIT_IN;
@@ -5133,45 +4867,6 @@
     return device;
 }
 
-bool AudioPolicyManager::isVirtualInputDevice(audio_devices_t device)
-{
-    if ((device & AUDIO_DEVICE_BIT_IN) != 0) {
-        device &= ~AUDIO_DEVICE_BIT_IN;
-        if ((popcount(device) == 1) && ((device & ~APM_AUDIO_IN_DEVICE_VIRTUAL_ALL) == 0))
-            return true;
-    }
-    return false;
-}
-
-bool AudioPolicyManager::deviceDistinguishesOnAddress(audio_devices_t device) {
-    return ((device & APM_AUDIO_DEVICE_MATCH_ADDRESS_ALL & ~AUDIO_DEVICE_BIT_IN) != 0);
-}
-
-audio_io_handle_t AudioPolicyManager::getActiveInput(bool ignoreVirtualInputs)
-{
-    for (size_t i = 0; i < mInputs.size(); i++) {
-        const sp<AudioInputDescriptor>  input_descriptor = mInputs.valueAt(i);
-        if ((input_descriptor->mRefCount > 0)
-                && (!ignoreVirtualInputs || !isVirtualInputDevice(input_descriptor->mDevice))) {
-            return mInputs.keyAt(i);
-        }
-    }
-    return 0;
-}
-
-uint32_t AudioPolicyManager::activeInputsCount() const
-{
-    uint32_t count = 0;
-    for (size_t i = 0; i < mInputs.size(); i++) {
-        const sp<AudioInputDescriptor>  desc = mInputs.valueAt(i);
-        if (desc->mRefCount > 0) {
-            count++;
-        }
-    }
-    return count;
-}
-
-
 void AudioPolicyManager::initializeVolumeCurves()
 {
     for (int i = 0; i < AUDIO_STREAM_CNT; i++) {
@@ -5199,9 +4894,9 @@
 }
 
 float AudioPolicyManager::computeVolume(audio_stream_type_t stream,
-                                            int index,
-                                            audio_io_handle_t output,
-                                            audio_devices_t device)
+                                        int index,
+                                        audio_io_handle_t output,
+                                        audio_devices_t device)
 {
     float volume = 1.0;
     sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
@@ -5253,11 +4948,11 @@
 }
 
 status_t AudioPolicyManager::checkAndSetVolume(audio_stream_type_t stream,
-                                                   int index,
-                                                   audio_io_handle_t output,
-                                                   audio_devices_t device,
-                                                   int delayMs,
-                                                   bool force)
+                                               int index,
+                                               audio_io_handle_t output,
+                                               audio_devices_t device,
+                                               int delayMs,
+                                               bool force)
 {
 
     // do not change actual stream volume if the stream is muted
@@ -5325,9 +5020,9 @@
 }
 
 void AudioPolicyManager::applyStreamVolumes(audio_io_handle_t output,
-                                                audio_devices_t device,
-                                                int delayMs,
-                                                bool force)
+                                            audio_devices_t device,
+                                            int delayMs,
+                                            bool force)
 {
     ALOGVV("applyStreamVolumes() for output %d and device %x", output, device);
 
@@ -5345,10 +5040,10 @@
 }
 
 void AudioPolicyManager::setStrategyMute(routing_strategy strategy,
-                                             bool on,
-                                             audio_io_handle_t output,
-                                             int delayMs,
-                                             audio_devices_t device)
+                                         bool on,
+                                         audio_io_handle_t output,
+                                         int delayMs,
+                                         audio_devices_t device)
 {
     ALOGVV("setStrategyMute() strategy %d, mute %d, output %d", strategy, on, output);
     for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) {
@@ -5362,10 +5057,10 @@
 }
 
 void AudioPolicyManager::setStreamMute(audio_stream_type_t stream,
-                                           bool on,
-                                           audio_io_handle_t output,
-                                           int delayMs,
-                                           audio_devices_t device)
+                                       bool on,
+                                       audio_io_handle_t output,
+                                       int delayMs,
+                                       audio_devices_t device)
 {
     StreamDescriptor &streamDesc = mStreams[stream];
     sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
@@ -5491,147 +5186,6 @@
 }
 
 
-// --- audio_policy.conf file parsing
-// TODO candidate to be moved to ConfigParsingUtils
-void AudioPolicyManager::loadHwModule(cnode *root)
-{
-    status_t status = NAME_NOT_FOUND;
-    cnode *node;
-    sp<HwModule> module = new HwModule(root->name);
-
-    node = config_find(root, DEVICES_TAG);
-    if (node != NULL) {
-        node = node->first_child;
-        while (node) {
-            ALOGV("loadHwModule() loading device %s", node->name);
-            status_t tmpStatus = module->loadDevice(node);
-            if (status == NAME_NOT_FOUND || status == NO_ERROR) {
-                status = tmpStatus;
-            }
-            node = node->next;
-        }
-    }
-    node = config_find(root, OUTPUTS_TAG);
-    if (node != NULL) {
-        node = node->first_child;
-        while (node) {
-            ALOGV("loadHwModule() loading output %s", node->name);
-            status_t tmpStatus = module->loadOutput(node);
-            if (status == NAME_NOT_FOUND || status == NO_ERROR) {
-                status = tmpStatus;
-            }
-            node = node->next;
-        }
-    }
-    node = config_find(root, INPUTS_TAG);
-    if (node != NULL) {
-        node = node->first_child;
-        while (node) {
-            ALOGV("loadHwModule() loading input %s", node->name);
-            status_t tmpStatus = module->loadInput(node);
-            if (status == NAME_NOT_FOUND || status == NO_ERROR) {
-                status = tmpStatus;
-            }
-            node = node->next;
-        }
-    }
-    loadGlobalConfig(root, module);
-
-    if (status == NO_ERROR) {
-        mHwModules.add(module);
-    }
-}
-
-// TODO candidate to be moved to ConfigParsingUtils
-void AudioPolicyManager::loadHwModules(cnode *root)
-{
-    cnode *node = config_find(root, AUDIO_HW_MODULE_TAG);
-    if (node == NULL) {
-        return;
-    }
-
-    node = node->first_child;
-    while (node) {
-        ALOGV("loadHwModules() loading module %s", node->name);
-        loadHwModule(node);
-        node = node->next;
-    }
-}
-
-// TODO candidate to be moved to ConfigParsingUtils
-void AudioPolicyManager::loadGlobalConfig(cnode *root, const sp<HwModule>& module)
-{
-    cnode *node = config_find(root, GLOBAL_CONFIG_TAG);
-
-    if (node == NULL) {
-        return;
-    }
-    DeviceVector declaredDevices;
-    if (module != NULL) {
-        declaredDevices = module->mDeclaredDevices;
-    }
-
-    node = node->first_child;
-    while (node) {
-        if (strcmp(ATTACHED_OUTPUT_DEVICES_TAG, node->name) == 0) {
-            mAvailableOutputDevices.loadDevicesFromName((char *)node->value,
-                                                        declaredDevices);
-            ALOGV("loadGlobalConfig() Attached Output Devices %08x",
-                  mAvailableOutputDevices.types());
-        } else if (strcmp(DEFAULT_OUTPUT_DEVICE_TAG, node->name) == 0) {
-            audio_devices_t device = (audio_devices_t)ConfigParsingUtils::stringToEnum(
-                    sDeviceNameToEnumTable,
-                    ARRAY_SIZE(sDeviceNameToEnumTable),
-                    (char *)node->value);
-            if (device != AUDIO_DEVICE_NONE) {
-                mDefaultOutputDevice = new DeviceDescriptor(String8("default-output"), device);
-            } else {
-                ALOGW("loadGlobalConfig() default device not specified");
-            }
-            ALOGV("loadGlobalConfig() mDefaultOutputDevice %08x", mDefaultOutputDevice->mDeviceType);
-        } else if (strcmp(ATTACHED_INPUT_DEVICES_TAG, node->name) == 0) {
-            mAvailableInputDevices.loadDevicesFromName((char *)node->value,
-                                                       declaredDevices);
-            ALOGV("loadGlobalConfig() Available InputDevices %08x", mAvailableInputDevices.types());
-        } else if (strcmp(SPEAKER_DRC_ENABLED_TAG, node->name) == 0) {
-            mSpeakerDrcEnabled = ConfigParsingUtils::stringToBool((char *)node->value);
-            ALOGV("loadGlobalConfig() mSpeakerDrcEnabled = %d", mSpeakerDrcEnabled);
-        } else if (strcmp(AUDIO_HAL_VERSION_TAG, node->name) == 0) {
-            uint32_t major, minor;
-            sscanf((char *)node->value, "%u.%u", &major, &minor);
-            module->mHalVersion = HARDWARE_DEVICE_API_VERSION(major, minor);
-            ALOGV("loadGlobalConfig() mHalVersion = %04x major %u minor %u",
-                  module->mHalVersion, major, minor);
-        }
-        node = node->next;
-    }
-}
-
-// TODO candidate to be moved to ConfigParsingUtils
-status_t AudioPolicyManager::loadAudioPolicyConfig(const char *path)
-{
-    cnode *root;
-    char *data;
-
-    data = (char *)load_file(path, NULL);
-    if (data == NULL) {
-        return -ENODEV;
-    }
-    root = config_node("", "");
-    config_load(root, data);
-
-    loadHwModules(root);
-    // legacy audio_policy.conf files have one global_configuration section
-    loadGlobalConfig(root, getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY));
-    config_free(root);
-    free(root);
-    free(data);
-
-    ALOGI("loadAudioPolicyConfig() loaded %s\n", path);
-
-    return NO_ERROR;
-}
-
 void AudioPolicyManager::defaultAudioPolicyConfig(void)
 {
     sp<HwModule> module;
@@ -5717,7 +5271,8 @@
     }
 }
 
-bool AudioPolicyManager::isValidAttributes(const audio_attributes_t *paa) {
+bool AudioPolicyManager::isValidAttributes(const audio_attributes_t *paa)
+{
     // has flags that map to a strategy?
     if ((paa->flags & (AUDIO_FLAG_AUDIBILITY_ENFORCED | AUDIO_FLAG_SCO | AUDIO_FLAG_BEACON)) != 0) {
         return true;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 279dc93..ce9c69c 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -160,13 +160,19 @@
         virtual status_t unregisterEffect(int id);
         virtual status_t setEffectEnabled(int id, bool enabled);
 
-        virtual bool isStreamActive(audio_stream_type_t stream, uint32_t inPastMs = 0) const;
+        virtual bool isStreamActive(audio_stream_type_t stream, uint32_t inPastMs = 0) const
+        {
+            return mOutputs.isStreamActive(stream, inPastMs);
+        }
         // return whether a stream is playing remotely, override to change the definition of
         //   local/remote playback, used for instance by notification manager to not make
         //   media players lose audio focus when not playing locally
         //   For the base implementation, "remotely" means playing during screen mirroring which
         //   uses an output for playback with a non-empty, non "0" address.
-        virtual bool isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs = 0) const;
+        virtual bool isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs = 0) const
+        {
+            return mOutputs.isStreamActiveRemotely(stream, inPastMs);
+        }
         virtual bool isSourceActive(audio_source_t source) const;
 
         virtual status_t dump(int fd);
@@ -201,10 +207,6 @@
 
         // Audio policy configuration file parsing (audio_policy.conf)
         // TODO candidates to be moved to ConfigParsingUtils
-                void loadHwModule(cnode *root);
-                void loadHwModules(cnode *root);
-                void loadGlobalConfig(cnode *root, const sp<HwModule>& module);
-                status_t loadAudioPolicyConfig(const char *path);
                 void defaultAudioPolicyConfig(void);
 
                 // return the strategy corresponding to a given stream type
@@ -225,6 +227,7 @@
         };
 
         void addOutput(audio_io_handle_t output, sp<AudioOutputDescriptor> outputDesc);
+        void removeOutput(audio_io_handle_t output);
         void addInput(audio_io_handle_t input, sp<AudioInputDescriptor> inputDesc);
 
         // return appropriate device for streams handled by the specified strategy according to current
@@ -262,13 +265,6 @@
         // select input device corresponding to requested audio source
         virtual audio_devices_t getDeviceForInputSource(audio_source_t inputSource);
 
-        // return io handle of active input or 0 if no input is active
-        //    Only considers inputs from physical devices (e.g. main mic, headset mic) when
-        //    ignoreVirtualInputs is true.
-        audio_io_handle_t getActiveInput(bool ignoreVirtualInputs = true);
-
-        uint32_t activeInputsCount() const;
-
         // initialize volume curves for each strategy and device category
         void initializeVolumeCurves();
 
@@ -344,9 +340,6 @@
         // manages A2DP output suspend/restore according to phone state and BT SCO usage
         void checkA2dpSuspend();
 
-        // returns the A2DP output handle if it is open or 0 otherwise
-        audio_io_handle_t getA2dpOutput();
-
         // selects the most appropriate device on output for current state
         // must be called every time a condition that affects the device choice for a given output is
         // changed: connected device, phone state, force use, output start, output stop..
@@ -374,7 +367,7 @@
         status_t setEffectEnabled(const sp<EffectDescriptor>& effectDesc, bool enabled);
 
         SortedVector<audio_io_handle_t> getOutputsForDevice(audio_devices_t device,
-                        DefaultKeyedVector<audio_io_handle_t, sp<AudioOutputDescriptor> > openOutputs);
+                                                            AudioOutputCollection openOutputs);
         bool vectorsEqual(SortedVector<audio_io_handle_t>& outputs1,
                                            SortedVector<audio_io_handle_t>& outputs2);
 
@@ -406,29 +399,36 @@
 
         bool isNonOffloadableEffectEnabled();
 
-        virtual status_t addAudioPatch(audio_patch_handle_t handle,
-                               const sp<AudioPatch>& patch);
-        virtual status_t removeAudioPatch(audio_patch_handle_t handle);
+        virtual status_t addAudioPatch(audio_patch_handle_t handle, const sp<AudioPatch>& patch)
+        {
+            return mAudioPatches.addAudioPatch(handle, patch);
+        }
+        virtual status_t removeAudioPatch(audio_patch_handle_t handle)
+        {
+            return mAudioPatches.removeAudioPatch(handle);
+        }
 
-        sp<AudioOutputDescriptor> getOutputFromId(audio_port_handle_t id) const;
-        sp<AudioInputDescriptor> getInputFromId(audio_port_handle_t id) const;
-        sp<HwModule> getModuleForDevice(audio_devices_t device) const;
-        sp<HwModule> getModuleFromName(const char *name) const;
-        audio_devices_t availablePrimaryOutputDevices();
-        audio_devices_t availablePrimaryInputDevices();
+        audio_devices_t availablePrimaryOutputDevices() const
+        {
+            return mOutputs.getSupportedDevices(mPrimaryOutput) & mAvailableOutputDevices.types();
+        }
+        audio_devices_t availablePrimaryInputDevices() const
+        {
+            return mAvailableInputDevices.getDevicesFromHwModule(
+                        mOutputs.valueFor(mPrimaryOutput)->getModuleHandle());
+        }
 
         void updateCallRouting(audio_devices_t rxDevice, int delayMs = 0);
 
-
         uid_t mUidCached;
         AudioPolicyClientInterface *mpClientInterface;  // audio policy client interface
         audio_io_handle_t mPrimaryOutput;              // primary output handle
         // list of descriptors for outputs currently opened
-        DefaultKeyedVector<audio_io_handle_t, sp<AudioOutputDescriptor> > mOutputs;
+        AudioOutputCollection mOutputs;
         // copy of mOutputs before setDeviceConnectionState() opens new outputs
         // reset to mOutputs when updateDevicesAndOutputs() is called.
-        DefaultKeyedVector<audio_io_handle_t, sp<AudioOutputDescriptor> > mPreviousOutputs;
-        DefaultKeyedVector<audio_io_handle_t, sp<AudioInputDescriptor> > mInputs;     // list of input descriptors
+        AudioOutputCollection mPreviousOutputs;
+        AudioInputCollection mInputs;     // list of input descriptors
         DeviceVector  mAvailableOutputDevices; // all available output devices
         DeviceVector  mAvailableInputDevices;  // all available input devices
         int mPhoneState;                                                    // current phone state
@@ -451,10 +451,11 @@
         bool mSpeakerDrcEnabled;// true on devices that use DRC on the DEVICE_CATEGORY_SPEAKER path
                                 // to boost soft sounds, used to adjust volume curves accordingly
 
-        Vector < sp<HwModule> > mHwModules;
+        HwModuleCollection mHwModules;
+
         volatile int32_t mAudioPortGeneration;
 
-        DefaultKeyedVector<audio_patch_handle_t, sp<AudioPatch> > mAudioPatches;
+        AudioPatchCollection mAudioPatches;
 
         DefaultKeyedVector<audio_session_t, audio_io_handle_t> mSoundTriggerSessions;
 
@@ -499,14 +500,11 @@
         uint32_t        mTestLatencyMs;
 #endif //AUDIO_POLICY_TEST
 
-        static bool isVirtualInputDevice(audio_devices_t device);
-
         uint32_t nextAudioPortGeneration();
 private:
         // updates device caching and output for streams that can influence the
         //    routing of notifications
         void handleNotificationRoutingForStream(audio_stream_type_t stream);
-        static bool deviceDistinguishesOnAddress(audio_devices_t device);
         // find the outputs on a given output descriptor that have the given address.
         // to be called on an AudioOutputDescriptor whose supported devices (as defined
         //   in mProfile->mSupportedDevices) matches the device whose address is to be matched.
@@ -529,8 +527,6 @@
                 const audio_offload_info_t *offloadInfo);
         // internal function to derive a stream type value from audio attributes
         audio_stream_type_t streamTypefromAttributesInt(const audio_attributes_t *attr);
-        // return true if any output is playing anything besides the stream to ignore
-        bool isAnyOutputActive(audio_stream_type_t streamToIgnore);
         // event is one of STARTING_OUTPUT, STARTING_BEACON, STOPPING_OUTPUT, STOPPING_BEACON
         // returns 0 if no mute/unmute event happened, the largest latency of the device where
         //   the mute/unmute happened
@@ -548,9 +544,6 @@
                                                           audio_policy_dev_state_t state,
                                                           const char *device_address,
                                                           const char *device_name);
-        sp<DeviceDescriptor>  getDeviceDescriptor(const audio_devices_t device,
-                                                  const char *device_address,
-                                                  const char *device_name);
 
         bool isStrategyActive(const sp<AudioOutputDescriptor> outputDesc, routing_strategy strategy,
                               uint32_t inPastMs = 0, nsecs_t sysTime = 0) const;