Merge "CameraService: Remove device HALv2 support, other cleanup"
diff --git a/drm/drmserver/drmserver.rc b/drm/drmserver/drmserver.rc
index c6b8226..42f5fc8 100644
--- a/drm/drmserver/drmserver.rc
+++ b/drm/drmserver/drmserver.rc
@@ -1,4 +1,4 @@
 service drm /system/bin/drmserver
     class main
     user drm
-    group drm system inet drmrpc
+    group drm system inet drmrpc readproc
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
index c4c7b0e..c47a4e7 100644
--- a/include/media/AudioRecord.h
+++ b/include/media/AudioRecord.h
@@ -20,6 +20,7 @@
 #include <cutils/sched_policy.h>
 #include <media/AudioSystem.h>
 #include <media/IAudioRecord.h>
+#include <media/Modulo.h>
 #include <utils/threads.h>
 
 namespace android {
@@ -526,7 +527,7 @@
 
             // caller must hold lock on mLock for all _l methods
 
-            status_t openRecord_l(size_t epoch, const String16& opPackageName);
+            status_t openRecord_l(const Modulo<uint32_t> &epoch, const String16& opPackageName);
 
             // FIXME enum is faster than strcmp() for parameter 'from'
             status_t restoreRecord_l(const char *from);
@@ -556,9 +557,9 @@
     bool                    mRetryOnPartialBuffer;  // sleep and retry after partial obtainBuffer()
     uint32_t                mObservedSequence;      // last observed value of mSequence
 
-    uint32_t                mMarkerPosition;        // in wrapping (overflow) frame units
+    Modulo<uint32_t>        mMarkerPosition;        // in wrapping (overflow) frame units
     bool                    mMarkerReached;
-    uint32_t                mNewPosition;           // in frames
+    Modulo<uint32_t>        mNewPosition;           // in frames
     uint32_t                mUpdatePeriod;          // in frames, zero means no EVENT_NEW_POS
 
     status_t                mStatus;
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index e02f1b7..fe4611c 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -22,6 +22,7 @@
 #include <media/AudioTimestamp.h>
 #include <media/IAudioTrack.h>
 #include <media/AudioResamplerPublic.h>
+#include <media/Modulo.h>
 #include <utils/threads.h>
 
 namespace android {
@@ -798,7 +799,7 @@
                 { return (mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0; }
 
             // increment mPosition by the delta of mServer, and return new value of mPosition
-            uint32_t updateAndGetPosition_l();
+            Modulo<uint32_t> updateAndGetPosition_l();
 
             // check sample rate and speed is compatible with AudioTrack
             bool     isSampleRateSpeedAllowed_l(uint32_t sampleRate, float speed) const;
@@ -885,19 +886,19 @@
     bool                    mRetryOnPartialBuffer;  // sleep and retry after partial obtainBuffer()
     uint32_t                mObservedSequence;      // last observed value of mSequence
 
-    uint32_t                mMarkerPosition;        // in wrapping (overflow) frame units
+    Modulo<uint32_t>        mMarkerPosition;        // in wrapping (overflow) frame units
     bool                    mMarkerReached;
-    uint32_t                mNewPosition;           // in frames
+    Modulo<uint32_t>        mNewPosition;           // in frames
     uint32_t                mUpdatePeriod;          // in frames, zero means no EVENT_NEW_POS
 
-    uint32_t                mServer;                // in frames, last known mProxy->getPosition()
+    Modulo<uint32_t>        mServer;                // in frames, last known mProxy->getPosition()
                                                     // which is count of frames consumed by server,
                                                     // reset by new IAudioTrack,
                                                     // whether it is reset by stop() is TBD
-    uint32_t                mPosition;              // in frames, like mServer except continues
+    Modulo<uint32_t>        mPosition;              // in frames, like mServer except continues
                                                     // monotonically after new IAudioTrack,
                                                     // and could be easily widened to uint64_t
-    uint32_t                mReleased;              // in frames, count of frames released to server
+    Modulo<uint32_t>        mReleased;              // count of frames released to server
                                                     // but not necessarily consumed by server,
                                                     // reset by stop() but continues monotonically
                                                     // after new IAudioTrack to restore mPosition,
diff --git a/include/media/Modulo.h b/include/media/Modulo.h
new file mode 100644
index 0000000..23280ac
--- /dev/null
+++ b/include/media/Modulo.h
@@ -0,0 +1,220 @@
+/*
+ * Copyright 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.
+ */
+
+#ifndef ANDROID_MODULO_H
+#define ANDROID_MODULO_H
+
+namespace android {
+
+// Modulo class is used for intentionally wrapping variables such as
+// counters and timers.
+//
+// It may also be used for variables whose computation depends on the
+// associativity of addition or subtraction.
+//
+// Features:
+// 1) Modulo checks type sizes before performing operations to ensure
+//    that the wrap points match. This is critical for safe modular arithmetic.
+// 2) Modulo returns Modulo types from arithmetic operations, thereby
+//    avoiding unintentional use in a non-modular computation.  A Modulo
+//    type is converted to its base non-Modulo type through the value() function.
+// 3) Modulo separates out overflowable types from non-overflowable types.
+//    A signed overflow is technically undefined in C and C++.
+//    Modulo types do not participate in sanitization.
+// 4) Modulo comparisons are based on signed differences to account for wrap;
+//    this is not the same as the direct comparison of values.
+// 5) Safe use of binary arithmetic operations relies on conversions of
+//    signed operands to unsigned operands (which are modular arithmetic safe).
+//    Conversions which are implementation-defined are assumed to use 2's complement
+//    representation. (See A, B, C, D from the ISO/IEC FDIS 14882
+//    Information technology — Programming languages — C++).
+//
+// A: ISO/IEC 14882:2011(E) p84 section 4.7 Integral conversions
+// (2) If the destination type is unsigned, the resulting value is the least unsigned
+// integer congruent to the source integer (modulo 2^n where n is the number of bits
+// used to represent the unsigned type). [ Note: In a two’s complement representation,
+// this conversion is conceptual and there is no change in the bit pattern (if there
+// is no truncation). — end note ]
+// (3) If the destination type is signed, the value is unchanged if it can be represented
+// in the destination type (and bit-field width); otherwise, the value is
+// implementation-defined.
+//
+// B: ISO/IEC 14882:2011(E) p88 section 5 Expressions
+// (9) Many binary operators that expect operands of arithmetic or enumeration type
+// cause conversions and yield result types in a similar way. The purpose is to
+// yield a common type, which is also the type of the result. This pattern is called
+// the usual arithmetic conversions, which are defined as follows:
+// [...]
+// Otherwise, if both operands have signed integer types or both have unsigned
+// integer types, the operand with the type of lesser integer conversion rank shall be
+// converted to the type of the operand with greater rank.
+// — Otherwise, if the operand that has unsigned integer type has rank greater than
+// or equal to the rank of the type of the other operand, the operand with signed
+// integer type shall be converted to the type of the operand with unsigned integer type.
+//
+// C: ISO/IEC 14882:2011(E) p86 section 4.13 Integer conversion rank
+// [...] The rank of long long int shall be greater than the rank of long int,
+// which shall be greater than the rank of int, which shall be greater than the
+// rank of short int, which shall be greater than the rank of signed char.
+// — The rank of any unsigned integer type shall equal the rank of the corresponding
+// signed integer type.
+//
+// D: ISO/IEC 14882:2011(E) p75 section 3.9.1 Fundamental types
+// [...] Unsigned integers, declared unsigned, shall obey the laws of arithmetic modulo
+// 2^n where n is the number of bits in the value representation of that particular
+// size of integer.
+//
+// Note:
+// Other libraries do exist for safe integer operations which can detect the
+// possibility of overflow (SafeInt from MS and safe-iop in android).
+// Signed safe computation is also possible from the art header safe_math.h.
+
+template <typename T> class Modulo {
+    T mValue;
+
+public:
+    typedef typename std::make_signed<T>::type signedT;
+    typedef typename std::make_unsigned<T>::type unsignedT;
+
+    Modulo() { } // intentionally uninitialized data
+    Modulo(const T &value) { mValue = value; }
+    const T & value() const { return mValue; } // not assignable
+    signedT signedValue() const { return mValue; }
+    unsignedT unsignedValue() const { return mValue; }
+    void getValue(T *value) const { *value = mValue; } // more type safe than value()
+
+    // modular operations valid only if size of T <= size of S.
+    template <typename S>
+    __attribute__((no_sanitize("integer")))
+    Modulo<T> operator +=(const Modulo<S> &other) {
+        static_assert(sizeof(T) <= sizeof(S), "argument size mismatch");
+        mValue += other.unsignedValue();
+        return *this;
+    }
+
+    template <typename S>
+    __attribute__((no_sanitize("integer")))
+    Modulo<T> operator -=(const Modulo<S> &other) {
+        static_assert(sizeof(T) <= sizeof(S), "argument size mismatch");
+        mValue -= other.unsignedValue();
+        return *this;
+    }
+
+    // modular operations resulting in a value valid only at the smaller of the two
+    // Modulo base type sizes, but we only allow equal sizes to avoid confusion.
+    template <typename S>
+    __attribute__((no_sanitize("integer")))
+    const Modulo<T> operator +(const Modulo<S> &other) const {
+        static_assert(sizeof(T) == sizeof(S), "argument size mismatch");
+        return Modulo<T>(mValue + other.unsignedValue());
+    }
+
+    template <typename S>
+    __attribute__((no_sanitize("integer")))
+    const Modulo<T> operator -(const Modulo<S> &other) const {
+        static_assert(sizeof(T) == sizeof(S), "argument size mismatch");
+        return Modulo<T>(mValue - other.unsignedValue());
+    }
+
+    // modular operations that should be checked only at the smaller of
+    // the two type sizes, but we only allow equal sizes to avoid confusion.
+    //
+    // Caution: These relational and comparison operations are not equivalent to
+    // the base type operations.
+    template <typename S>
+    __attribute__((no_sanitize("integer")))
+    bool operator >(const Modulo<S> &other) const {
+        static_assert(sizeof(T) == sizeof(S), "argument size mismatch");
+        return static_cast<signedT>(mValue - other.unsignedValue()) > 0;
+    }
+
+    template <typename S>
+    __attribute__((no_sanitize("integer")))
+    bool operator >=(const Modulo<S> &other) const {
+        static_assert(sizeof(T) == sizeof(S), "argument size mismatch");
+        return static_cast<signedT>(mValue - other.unsignedValue()) >= 0;
+    }
+
+    template <typename S>
+    __attribute__((no_sanitize("integer")))
+    bool operator ==(const Modulo<S> &other) const {
+        static_assert(sizeof(T) == sizeof(S), "argument size mismatch");
+        return static_cast<signedT>(mValue - other.unsignedValue()) == 0;
+    }
+
+    template <typename S>
+    __attribute__((no_sanitize("integer")))
+    bool operator <=(const Modulo<S> &other) const {
+        static_assert(sizeof(T) == sizeof(S), "argument size mismatch");
+        return static_cast<signedT>(mValue - other.unsignedValue()) <= 0;
+    }
+
+    template <typename S>
+    __attribute__((no_sanitize("integer")))
+    bool operator <(const Modulo<S> &other) const {
+        static_assert(sizeof(T) == sizeof(S), "argument size mismatch");
+        return static_cast<signedT>(mValue - other.unsignedValue()) < 0;
+    }
+
+
+    // modular operations with a non-Modulo type allowed with wrapping
+    // because there should be no confusion as to the meaning.
+    template <typename S>
+    __attribute__((no_sanitize("integer")))
+    Modulo<T> operator +=(const S &other) {
+        mValue += unsignedT(other);
+        return *this;
+    }
+
+    template <typename S>
+    __attribute__((no_sanitize("integer")))
+    Modulo<T> operator -=(const S &other) {
+        mValue -= unsignedT(other);
+        return *this;
+    }
+
+    // modular operations with a non-Modulo type allowed with wrapping,
+    // but we restrict this only when size of T is greater than or equal to
+    // the size of S to avoid confusion with the nature of overflow.
+    //
+    // Use of this follows left-associative style.
+    //
+    // Note: a Modulo type may be promoted by using "differences" off of
+    // a larger sized type, but we do not automate this.
+    template <typename S>
+    __attribute__((no_sanitize("integer")))
+    const Modulo<T> operator +(const S &other) const {
+        static_assert(sizeof(T) >= sizeof(S), "argument size mismatch");
+        return Modulo<T>(mValue + unsignedT(other));
+    }
+
+    template <typename S>
+    __attribute__((no_sanitize("integer")))
+    const Modulo<T> operator -(const S &other) const {
+        static_assert(sizeof(T) >= sizeof(S), "argument size mismatch");
+        return Modulo<T>(mValue - unsignedT(other));
+    }
+
+    // multiply is intentionally omitted, but it is a common operator in
+    // modular arithmetic.
+
+    // shift operations are intentionally omitted, but perhaps useful.
+    // For example, left-shifting a negative number is undefined in C++11.
+};
+
+} // namespace android
+
+#endif /* ANDROID_MODULO_H */
diff --git a/include/media/stagefright/FileSource.h b/include/media/stagefright/FileSource.h
index a981d1c..266168b 100644
--- a/include/media/stagefright/FileSource.h
+++ b/include/media/stagefright/FileSource.h
@@ -56,7 +56,7 @@
     sp<DecryptHandle> mDecryptHandle;
     DrmManagerClient *mDrmManagerClient;
     int64_t mDrmBufOffset;
-    size_t mDrmBufSize;
+    ssize_t mDrmBufSize;
     unsigned char *mDrmBuf;
 
     ssize_t readAtDRM(off64_t offset, void *data, size_t size);
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index 1e5064f..1f3880f 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -26,6 +26,7 @@
 #include <utils/RefBase.h>
 #include <audio_utils/roundup.h>
 #include <media/AudioResamplerPublic.h>
+#include <media/Modulo.h>
 #include <media/SingleStateQueue.h>
 
 namespace android {
@@ -280,11 +281,11 @@
     // Call to force an obtainBuffer() to return quickly with -EINTR
     void        interrupt();
 
-    size_t      getPosition() {
+    Modulo<uint32_t> getPosition() {
         return mEpoch + mCblk->mServer;
     }
 
-    void        setEpoch(size_t epoch) {
+    void             setEpoch(const Modulo<uint32_t> &epoch) {
         mEpoch = epoch;
     }
 
@@ -300,14 +301,14 @@
     // in order for the client to be aligned at start of buffer
     virtual size_t  getMisalignment();
 
-    size_t      getEpoch() const {
+    Modulo<uint32_t> getEpoch() const {
         return mEpoch;
     }
 
     size_t      getFramesFilled();
 
 private:
-    size_t      mEpoch;
+    Modulo<uint32_t> mEpoch;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/media/libeffects/preprocessing/Android.mk b/media/libeffects/preprocessing/Android.mk
index 0022fd9..82415d5 100644
--- a/media/libeffects/preprocessing/Android.mk
+++ b/media/libeffects/preprocessing/Android.mk
@@ -11,9 +11,9 @@
     PreProcessing.cpp
 
 LOCAL_C_INCLUDES += \
-    external/webrtc/src \
-    external/webrtc/src/modules/interface \
-    external/webrtc/src/modules/audio_processing/include \
+    external/webrtc \
+    external/webrtc/webrtc/modules/interface \
+    external/webrtc/webrtc/modules/audio_processing/include \
     $(call include-path-for, audio-effects)
 
 LOCAL_C_INCLUDES += $(call include-path-for, speex)
@@ -25,6 +25,10 @@
     liblog
 
 LOCAL_SHARED_LIBRARIES += libdl
+
+LOCAL_CFLAGS += \
+    -DWEBRTC_POSIX
+
 LOCAL_CFLAGS += -fvisibility=hidden
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libeffects/preprocessing/PreProcessing.cpp b/media/libeffects/preprocessing/PreProcessing.cpp
index b88d415..fe41946 100644
--- a/media/libeffects/preprocessing/PreProcessing.cpp
+++ b/media/libeffects/preprocessing/PreProcessing.cpp
@@ -777,14 +777,17 @@
     ALOGV("Session_CreateEffect procId %d, createdMsk %08x", procId, session->createdMsk);
 
     if (session->createdMsk == 0) {
-        session->apm = webrtc::AudioProcessing::Create(session->io);
+        session->apm = webrtc::AudioProcessing::Create();
         if (session->apm == NULL) {
             ALOGW("Session_CreateEffect could not get apm engine");
             goto error;
         }
-        session->apm->set_sample_rate_hz(kPreprocDefaultSr);
-        session->apm->set_num_channels(kPreProcDefaultCnl, kPreProcDefaultCnl);
-        session->apm->set_num_reverse_channels(kPreProcDefaultCnl);
+        const webrtc::ProcessingConfig processing_config = {
+            {{kPreprocDefaultSr, kPreProcDefaultCnl},
+             {kPreprocDefaultSr, kPreProcDefaultCnl},
+             {kPreprocDefaultSr, kPreProcDefaultCnl},
+             {kPreprocDefaultSr, kPreProcDefaultCnl}}};
+        session->apm->Initialize(processing_config);
         session->procFrame = new webrtc::AudioFrame();
         if (session->procFrame == NULL) {
             ALOGW("Session_CreateEffect could not allocate audio frame");
@@ -834,7 +837,7 @@
         session->revFrame = NULL;
         delete session->procFrame;
         session->procFrame = NULL;
-        webrtc::AudioProcessing::Destroy(session->apm);
+        delete session->apm;
         session->apm = NULL;
     }
     return status;
@@ -846,7 +849,7 @@
     ALOGW_IF(Effect_Release(fx) != 0, " Effect_Release() failed for proc ID %d", fx->procId);
     session->createdMsk &= ~(1<<fx->procId);
     if (session->createdMsk == 0) {
-        webrtc::AudioProcessing::Destroy(session->apm);
+        delete session->apm;
         session->apm = NULL;
         delete session->procFrame;
         session->procFrame = NULL;
@@ -914,15 +917,13 @@
     } else if (config->inputCfg.samplingRate >= 8000) {
         session->apmSamplingRate = 8000;
     }
-    status = session->apm->set_sample_rate_hz(session->apmSamplingRate);
-    if (status < 0) {
-        return -EINVAL;
-    }
-    status = session->apm->set_num_channels(inCnl, outCnl);
-    if (status < 0) {
-        return -EINVAL;
-    }
-    status = session->apm->set_num_reverse_channels(inCnl);
+
+    const webrtc::ProcessingConfig processing_config = {
+      {{static_cast<int>(session->apmSamplingRate), static_cast<int>(inCnl)},
+       {static_cast<int>(session->apmSamplingRate), static_cast<int>(outCnl)},
+       {static_cast<int>(session->apmSamplingRate), static_cast<int>(inCnl)},
+       {static_cast<int>(session->apmSamplingRate), static_cast<int>(inCnl)}}};
+    status = session->apm->Initialize(processing_config);
     if (status < 0) {
         return -EINVAL;
     }
@@ -1038,7 +1039,16 @@
         return -EINVAL;
     }
     uint32_t inCnl = audio_channel_count_from_out_mask(config->inputCfg.channels);
-    int status = session->apm->set_num_reverse_channels(inCnl);
+    const webrtc::ProcessingConfig processing_config = {
+       {{static_cast<int>(session->apmSamplingRate),
+         static_cast<int>(session->inChannelCount)},
+        {static_cast<int>(session->apmSamplingRate),
+         static_cast<int>(session->outChannelCount)},
+        {static_cast<int>(session->apmSamplingRate),
+         static_cast<int>(inCnl)},
+        {static_cast<int>(session->apmSamplingRate),
+         static_cast<int>(inCnl)}}};
+    int status = session->apm->Initialize(processing_config);
     if (status < 0) {
         return -EINVAL;
     }
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 8ffcd4b..1c0d904 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -396,7 +396,7 @@
     }
 
     AutoMutex lock(mLock);
-    *marker = mMarkerPosition;
+    mMarkerPosition.getValue(marker);
 
     return NO_ERROR;
 }
@@ -438,7 +438,7 @@
     }
 
     AutoMutex lock(mLock);
-    *position = mProxy->getPosition();
+    mProxy->getPosition().getValue(position);
 
     return NO_ERROR;
 }
@@ -480,7 +480,7 @@
 // -------------------------------------------------------------------------
 
 // must be called with mLock held
-status_t AudioRecord::openRecord_l(size_t epoch, const String16& opPackageName)
+status_t AudioRecord::openRecord_l(const Modulo<uint32_t> &epoch, const String16& opPackageName)
 {
     const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
     if (audioFlinger == 0) {
@@ -890,23 +890,23 @@
     }
 
     // Get current position of server
-    size_t position = mProxy->getPosition();
+    Modulo<uint32_t> position(mProxy->getPosition());
 
     // Manage marker callback
     bool markerReached = false;
-    size_t markerPosition = mMarkerPosition;
+    Modulo<uint32_t> markerPosition(mMarkerPosition);
     // FIXME fails for wraparound, need 64 bits
-    if (!mMarkerReached && (markerPosition > 0) && (position >= markerPosition)) {
+    if (!mMarkerReached && markerPosition.value() > 0 && position >= markerPosition) {
         mMarkerReached = markerReached = true;
     }
 
     // Determine the number of new position callback(s) that will be needed, while locked
     size_t newPosCount = 0;
-    size_t newPosition = mNewPosition;
+    Modulo<uint32_t> newPosition(mNewPosition);
     uint32_t updatePeriod = mUpdatePeriod;
     // FIXME fails for wraparound, need 64 bits
     if (updatePeriod > 0 && position >= newPosition) {
-        newPosCount = ((position - newPosition) / updatePeriod) + 1;
+        newPosCount = ((position - newPosition).value() / updatePeriod) + 1;
         mNewPosition += updatePeriod * newPosCount;
     }
 
@@ -933,7 +933,7 @@
         mCbf(EVENT_MARKER, mUserData, &markerPosition);
     }
     while (newPosCount > 0) {
-        size_t temp = newPosition;
+        size_t temp = newPosition.value(); // FIXME size_t != uint32_t
         mCbf(EVENT_NEW_POS, mUserData, &temp);
         newPosition += updatePeriod;
         newPosCount--;
@@ -951,10 +951,10 @@
     // Compute the estimated time until the next timed event (position, markers)
     uint32_t minFrames = ~0;
     if (!markerReached && position < markerPosition) {
-        minFrames = markerPosition - position;
+        minFrames = (markerPosition - position).value();
     }
     if (updatePeriod > 0) {
-        uint32_t remaining = newPosition - position;
+        uint32_t remaining = (newPosition - position).value();
         if (remaining < minFrames) {
             minFrames = remaining;
         }
@@ -1087,7 +1087,7 @@
     // if the new IAudioRecord is created, openRecord_l() will modify the
     // following member variables: mAudioRecord, mCblkMemory, mCblk, mBufferMemory.
     // It will also delete the strong references on previous IAudioRecord and IMemory
-    size_t position = mProxy->getPosition();
+    Modulo<uint32_t> position(mProxy->getPosition());
     mNewPosition = position + mUpdatePeriod;
     status_t result = openRecord_l(position, mOpPackageName);
     if (result == NO_ERROR) {
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 82b6736..5e14940 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -920,7 +920,7 @@
     }
 
     AutoMutex lock(mLock);
-    *marker = mMarkerPosition;
+    mMarkerPosition.getValue(marker);
 
     return NO_ERROR;
 }
@@ -1018,7 +1018,7 @@
 
         // IAudioTrack::stop() isn't synchronous; we don't know when presentation completes
         *position = (mState == STATE_STOPPED || mState == STATE_FLUSHED) ?
-                0 : updateAndGetPosition_l();
+                0 : updateAndGetPosition_l().value();
     }
     return NO_ERROR;
 }
@@ -1774,23 +1774,23 @@
     }
 
     // Get current position of server
-    size_t position = updateAndGetPosition_l();
+    Modulo<uint32_t> position(updateAndGetPosition_l());
 
     // Manage marker callback
     bool markerReached = false;
-    size_t markerPosition = mMarkerPosition;
-    // FIXME fails for wraparound, need 64 bits
-    if (!mMarkerReached && (markerPosition > 0) && (position >= markerPosition)) {
+    Modulo<uint32_t> markerPosition(mMarkerPosition);
+    // uses 32 bit wraparound for comparison with position.
+    if (!mMarkerReached && markerPosition.value() > 0 && position >= markerPosition) {
         mMarkerReached = markerReached = true;
     }
 
     // Determine number of new position callback(s) that will be needed, while locked
     size_t newPosCount = 0;
-    size_t newPosition = mNewPosition;
-    size_t updatePeriod = mUpdatePeriod;
+    Modulo<uint32_t> newPosition(mNewPosition);
+    uint32_t updatePeriod = mUpdatePeriod;
     // FIXME fails for wraparound, need 64 bits
     if (updatePeriod > 0 && position >= newPosition) {
-        newPosCount = ((position - newPosition) / updatePeriod) + 1;
+        newPosCount = ((position - newPosition).value() / updatePeriod) + 1;
         mNewPosition += updatePeriod * newPosCount;
     }
 
@@ -1891,7 +1891,7 @@
         mCbf(EVENT_MARKER, mUserData, &markerPosition);
     }
     while (newPosCount > 0) {
-        size_t temp = newPosition;
+        size_t temp = newPosition.value(); // FIXME size_t != uint32_t
         mCbf(EVENT_NEW_POS, mUserData, &temp);
         newPosition += updatePeriod;
         newPosCount--;
@@ -1915,14 +1915,14 @@
     // FIXME only for non-compressed audio
     uint32_t minFrames = ~0;
     if (!markerReached && position < markerPosition) {
-        minFrames = markerPosition - position;
+        minFrames = (markerPosition - position).value();
     }
     if (loopPeriod > 0 && loopPeriod < minFrames) {
         // loopPeriod is already adjusted for actual position.
         minFrames = loopPeriod;
     }
     if (updatePeriod > 0) {
-        minFrames = min(minFrames, uint32_t(newPosition - position));
+        minFrames = min(minFrames, (newPosition - position).value());
     }
 
     // If > 0, poll periodically to recover from a stuck server.  A good value is 2.
@@ -2157,11 +2157,11 @@
     return result;
 }
 
-uint32_t AudioTrack::updateAndGetPosition_l()
+Modulo<uint32_t> AudioTrack::updateAndGetPosition_l()
 {
     // This is the sole place to read server consumed frames
-    uint32_t newServer = mProxy->getPosition();
-    uint32_t delta = newServer > mServer ? newServer - mServer : 0;
+    Modulo<uint32_t> newServer(mProxy->getPosition());
+    const int32_t delta = (newServer - mServer).signedValue();
     // TODO There is controversy about whether there can be "negative jitter" in server position.
     //      This should be investigated further, and if possible, it should be addressed.
     //      A more definite failure mode is infrequent polling by client.
@@ -2170,12 +2170,14 @@
     //      That should ensure delta never goes negative for infrequent polling
     //      unless the server has more than 2^31 frames in its buffer,
     //      in which case the use of uint32_t for these counters has bigger issues.
-    if (newServer < mServer) {
-        ALOGE("detected illegal retrograde motion by the server: mServer advanced by %d",
-              (int32_t) newServer - mServer);
-    }
+    ALOGE_IF(delta < 0,
+            "detected illegal retrograde motion by the server: mServer advanced by %d",
+            delta);
     mServer = newServer;
-    return mPosition += delta;
+    if (delta > 0) { // avoid retrograde
+        mPosition += delta;
+    }
+    return mPosition;
 }
 
 bool AudioTrack::isSampleRateSpeedAllowed_l(uint32_t sampleRate, float speed) const
@@ -2197,7 +2199,6 @@
     return mAudioTrack->setParameters(keyValuePairs);
 }
 
-__attribute__((no_sanitize("integer")))
 status_t AudioTrack::getTimestamp(AudioTimestamp& timestamp)
 {
     AutoMutex lock(mLock);
@@ -2310,15 +2311,19 @@
         // If this delta between these is greater than the client position, it means that
         // actually presented is still stuck at the starting line (figuratively speaking),
         // waiting for the first frame to go by.  So we can't report a valid timestamp yet.
-        if ((uint32_t) (mServer - timestamp.mPosition) > mPosition) {
+        // Note: We explicitly use non-Modulo comparison here - potential wrap issue when
+        // mPosition exceeds 32 bits.
+        // TODO Remove when timestamp is updated to contain pipeline status info.
+        const int32_t pipelineDepthInFrames = (mServer - timestamp.mPosition).signedValue();
+        if (pipelineDepthInFrames > 0 /* should be true, but we check anyways */
+                && (uint32_t)pipelineDepthInFrames > mPosition.value()) {
             return INVALID_OPERATION;
         }
         // Convert timestamp position from server time base to client time base.
         // TODO The following code should work OK now because timestamp.mPosition is 32-bit.
         // But if we change it to 64-bit then this could fail.
-        // Split this out instead of using += to prevent unsigned overflow
-        // checks in the outer sum.
-        timestamp.mPosition = timestamp.mPosition + static_cast<int32_t>(mPosition) - mServer;
+        // Use Modulo computation here.
+        timestamp.mPosition = (mPosition - mServer + timestamp.mPosition).value();
         // Immediately after a call to getPosition_l(), mPosition and
         // mServer both represent the same frame position.  mPosition is
         // in client's point of view, and mServer is in server's point of
@@ -2332,9 +2337,9 @@
     // This is sometimes caused by erratic reports of the available space in the ALSA drivers.
     if (status == NO_ERROR) {
         if (previousTimestampValid) {
-#define TIME_TO_NANOS(time) ((uint64_t)time.tv_sec * 1000000000 + time.tv_nsec)
-            const uint64_t previousTimeNanos = TIME_TO_NANOS(mPreviousTimestamp.mTime);
-            const uint64_t currentTimeNanos = TIME_TO_NANOS(timestamp.mTime);
+#define TIME_TO_NANOS(time) ((int64_t)time.tv_sec * 1000000000 + time.tv_nsec)
+            const int64_t previousTimeNanos = TIME_TO_NANOS(mPreviousTimestamp.mTime);
+            const int64_t currentTimeNanos = TIME_TO_NANOS(timestamp.mTime);
 #undef TIME_TO_NANOS
             if (currentTimeNanos < previousTimeNanos) {
                 ALOGW("retrograde timestamp time");
@@ -2343,8 +2348,8 @@
 
             // Looking at signed delta will work even when the timestamps
             // are wrapping around.
-            int32_t deltaPosition = static_cast<int32_t>(timestamp.mPosition
-                    - mPreviousTimestamp.mPosition);
+            int32_t deltaPosition = (Modulo<uint32_t>(timestamp.mPosition)
+                    - mPreviousTimestamp.mPosition).signedValue();
             // position can bobble slightly as an artifact; this hides the bobble
             static const int32_t MINIMUM_POSITION_DELTA = 8;
             if (deltaPosition < 0) {
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 16140e7..a416381 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -286,9 +286,7 @@
     // reset battery stats
     // if the mediaserver has crashed, battery stats could be left
     // in bad state, reset the state upon service start.
-    BatteryNotifier& notifier(BatteryNotifier::getInstance());
-    notifier.noteResetVideo();
-    notifier.noteResetAudio();
+    BatteryNotifier::getInstance().noteResetVideo();
 
     MediaPlayerFactory::registerBuiltinFactories();
 }
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index bf91134..be59bf2 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -1552,10 +1552,9 @@
     mDrainAudioQueuePending = false;
     mDrainVideoQueuePending = false;
 
-    if (mHasAudio) {
-        mAudioSink->pause();
-        startAudioOffloadPauseTimeout();
-    }
+    // Note: audio data may not have been decoded, and the AudioSink may not be opened.
+    mAudioSink->pause();
+    startAudioOffloadPauseTimeout();
 
     ALOGV("now paused audio queue has %zu entries, video has %zu entries",
           mAudioQueue.size(), mVideoQueue.size());
@@ -1566,8 +1565,9 @@
         return;
     }
 
-    if (mHasAudio) {
-        cancelAudioOffloadPauseTimeout();
+    // Note: audio data may not have been decoded, and the AudioSink may not be opened.
+    cancelAudioOffloadPauseTimeout();
+    if (mAudioSink->ready()) {
         status_t err = mAudioSink->start();
         if (err != OK) {
             ALOGE("cannot start AudioSink err %d", err);
diff --git a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
index 0246b59..d4c88de 100644
--- a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
@@ -32,6 +32,8 @@
 
 namespace android {
 
+const int32_t kNumListenerQueuePackets = 80;
+
 NuPlayer::StreamingSource::StreamingSource(
         const sp<AMessage> &notify,
         const sp<IStreamSource> &source)
@@ -84,7 +86,7 @@
 }
 
 void NuPlayer::StreamingSource::onReadBuffer() {
-    for (int32_t i = 0; i < 50; ++i) {
+    for (int32_t i = 0; i < kNumListenerQueuePackets; ++i) {
         char buffer[188];
         sp<AMessage> extra;
         ssize_t n = mStreamListener->read(buffer, sizeof(buffer), &extra);
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index f5e9def..98936ad 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -65,6 +65,8 @@
 
 #define USE_SURFACE_ALLOC 1
 #define FRAME_DROP_FREQ 0
+#define PROPERTY_OFFLOAD_HIWATERMARK "audio.offload.hiwatermark"
+#define PROPERTY_OFFLOAD_LOWATERMARK "audio.offload.lowatermark"
 
 namespace android {
 
@@ -72,7 +74,8 @@
 static int64_t kHighWaterMarkUs = 5000000ll;  // 5secs
 static const size_t kLowWaterMarkBytes = 40000;
 static const size_t kHighWaterMarkBytes = 200000;
-
+static size_t kOffloadLowWaterMarkBytes = kLowWaterMarkBytes;
+static size_t kOffloadHighWaterMarkBytes = kHighWaterMarkBytes;
 // maximum time in paused state when offloading audio decompression. When elapsed, the AudioPlayer
 // is destroyed to allow the audio DSP to power down.
 static int64_t kOffloadPauseMaxUs = 10000000ll;
@@ -640,6 +643,11 @@
 
     mMediaRenderingStartGeneration = 0;
     mStartGeneration = 0;
+
+    kOffloadLowWaterMarkBytes =
+        property_get_int32(PROPERTY_OFFLOAD_LOWATERMARK, kLowWaterMarkBytes);
+    kOffloadHighWaterMarkBytes =
+        property_get_int32(PROPERTY_OFFLOAD_HIWATERMARK, kHighWaterMarkBytes);
 }
 
 void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
@@ -730,6 +738,7 @@
         size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus);
         bool eos = (finalStatus != OK);
 
+        ALOGV("cachedDataRemaining = %zu b, eos=%d", cachedDataRemaining, eos);
         if (eos) {
             if (finalStatus == ERROR_END_OF_STREAM) {
                 notifyListener_l(MEDIA_BUFFERING_UPDATE, 100);
@@ -740,36 +749,42 @@
             }
         } else {
             bool eos2;
+            bool knownDuration = false;
             int64_t cachedDurationUs;
             if (getCachedDuration_l(&cachedDurationUs, &eos2) && mDurationUs > 0) {
+                knownDuration = true;
                 int percentage = 100.0 * (double)cachedDurationUs / mDurationUs;
                 if (percentage > 100) {
                     percentage = 100;
                 }
 
                 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage);
-            } else {
-                // We don't know the bitrate/duration of the stream, use absolute size
-                // limits to maintain the cache.
+            }
+            if (!knownDuration || mOffloadAudio) {
+                // If we don't know the bitrate/duration of the stream, or are offloading
+                // decode, use absolute size limits to maintain the cache.
 
-                if ((mFlags & PLAYING) && !eos
-                        && (cachedDataRemaining < kLowWaterMarkBytes)) {
-                    ALOGI("cache is running low (< %zu) , pausing.",
-                         kLowWaterMarkBytes);
+                size_t lowWatermark =
+                        mOffloadAudio ? kOffloadLowWaterMarkBytes : kLowWaterMarkBytes;
+                size_t highWatermark =
+                        mOffloadAudio ? kOffloadHighWaterMarkBytes : kHighWaterMarkBytes;
+
+                if ((mFlags & PLAYING) && !eos && (cachedDataRemaining < lowWatermark)) {
+                    ALOGI("cache is running low (< %zu) , pausing.", lowWatermark);
                     modifyFlags(CACHE_UNDERRUN, SET);
                     pause_l();
                     ensureCacheIsFetching_l();
                     sendCacheStats();
                     notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
-                } else if (eos || cachedDataRemaining > kHighWaterMarkBytes) {
+                } else if (eos || cachedDataRemaining > highWatermark) {
                     if (mFlags & CACHE_UNDERRUN) {
                         ALOGI("cache has filled up (> %zu), resuming.",
-                             kHighWaterMarkBytes);
+                             highWatermark);
                         modifyFlags(CACHE_UNDERRUN, CLEAR);
                         play_l();
                     } else if (mFlags & PREPARING) {
                         ALOGV("cache has filled up (> %zu), prepare is done",
-                             kHighWaterMarkBytes);
+                             highWatermark);
                         finishAsyncPrepare_l();
                     }
                 }
@@ -803,7 +818,7 @@
 
     int64_t cachedDurationUs;
     bool eos;
-    if (getCachedDuration_l(&cachedDurationUs, &eos)) {
+    if (!mOffloadAudio && getCachedDuration_l(&cachedDurationUs, &eos)) {
         ALOGV("cachedDurationUs = %.2f secs, eos=%d",
              cachedDurationUs / 1E6, eos);
 
@@ -830,7 +845,8 @@
         }
     }
 
-    if (mFlags & (PLAYING | PREPARING | CACHE_UNDERRUN)) {
+    if ( ((mFlags & PLAYING) && !eos) ||
+         (mFlags & (PREPARING | CACHE_UNDERRUN)) ) {
         postBufferingEvent_l();
     }
 }
diff --git a/media/libstagefright/FileSource.cpp b/media/libstagefright/FileSource.cpp
index 92d541f..5d762d8 100644
--- a/media/libstagefright/FileSource.cpp
+++ b/media/libstagefright/FileSource.cpp
@@ -171,7 +171,7 @@
     }
 
     if (mDrmBuf != NULL && mDrmBufSize > 0 && (offset + mOffset) >= mDrmBufOffset
-            && (offset + mOffset + size) <= (mDrmBufOffset + mDrmBufSize)) {
+            && (offset + mOffset + size) <= static_cast<size_t>(mDrmBufOffset + mDrmBufSize)) {
         /* Use buffered data */
         memcpy(data, (void*)(mDrmBuf+(offset+mOffset-mDrmBufOffset)), size);
         return size;
@@ -182,7 +182,7 @@
                 DRM_CACHE_SIZE, offset + mOffset);
         if (mDrmBufSize > 0) {
             int64_t dataRead = 0;
-            dataRead = size > mDrmBufSize ? mDrmBufSize : size;
+            dataRead = size > static_cast<size_t>(mDrmBufSize) ? mDrmBufSize : size;
             memcpy(data, (void*)mDrmBuf, dataRead);
             return dataRead;
         } else {
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index b58b575..38eb352 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -2810,25 +2810,15 @@
 }
 
 void MediaCodec::updateBatteryStat() {
+    if (!mIsVideo) {
+        return;
+    }
+
     if (mState == CONFIGURED && !mBatteryStatNotified) {
-        BatteryNotifier& notifier(BatteryNotifier::getInstance());
-
-        if (mIsVideo) {
-            notifier.noteStartVideo();
-        } else {
-            notifier.noteStartAudio();
-        }
-
+        BatteryNotifier::getInstance().noteStartVideo();
         mBatteryStatNotified = true;
     } else if (mState == UNINITIALIZED && mBatteryStatNotified) {
-        BatteryNotifier& notifier(BatteryNotifier::getInstance());
-
-        if (mIsVideo) {
-            notifier.noteStopVideo();
-        } else {
-            notifier.noteStopAudio();
-        }
-
+        BatteryNotifier::getInstance().noteStopVideo();
         mBatteryStatNotified = false;
     }
 }
diff --git a/media/libstagefright/ProcessInfo.cpp b/media/libstagefright/ProcessInfo.cpp
index b4172b3..353f108 100644
--- a/media/libstagefright/ProcessInfo.cpp
+++ b/media/libstagefright/ProcessInfo.cpp
@@ -32,19 +32,23 @@
     sp<IProcessInfoService> service = interface_cast<IProcessInfoService>(binder);
 
     size_t length = 1;
-    int32_t states;
-    status_t err = service->getProcessStatesFromPids(length, &pid, &states);
+    int32_t state;
+    static const int32_t INVALID_ADJ = -10000;
+    static const int32_t NATIVE_ADJ = -1000;
+    int32_t score = INVALID_ADJ;
+    status_t err = service->getProcessStatesAndOomScoresFromPids(length, &pid, &state, &score);
     if (err != OK) {
-        ALOGE("getProcessStatesFromPids failed");
+        ALOGE("getProcessStatesAndOomScoresFromPids failed");
         return false;
     }
-    ALOGV("pid %d states %d", pid, states);
-    if (states < 0) {
+    ALOGV("pid %d state %d score %d", pid, state, score);
+    if (score <= NATIVE_ADJ) {
+        ALOGE("pid %d invalid OOM adjustments value %d", pid, score);
         return false;
     }
 
-    // Use process state as the priority. Lower the value, higher the priority.
-    *priority = states;
+    // Use OOM adjustments value as the priority. Lower the value, higher the priority.
+    *priority = score;
     return true;
 }
 
diff --git a/media/libstagefright/codecs/amrwbenc/src/c4t64fx.c b/media/libstagefright/codecs/amrwbenc/src/c4t64fx.c
index 1ecc11f..8704ce5 100644
--- a/media/libstagefright/codecs/amrwbenc/src/c4t64fx.c
+++ b/media/libstagefright/codecs/amrwbenc/src/c4t64fx.c
@@ -115,6 +115,7 @@
 		);
 
 
+__attribute__((no_sanitize("integer")))
 void ACELP_4t64_fx(
 		Word16 dn[],                          /* (i) <12b : correlation between target x[] and H[]      */
 		Word16 cn[],                          /* (i) <12b : residual after long term prediction         */
diff --git a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
index 8240f83..f2a4e65 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
+++ b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
@@ -37,6 +37,10 @@
 
 #include <inttypes.h>
 
+#ifndef INT32_MAX
+#define INT32_MAX   2147483647
+#endif
+
 namespace android {
 
 template<class T>
@@ -137,6 +141,11 @@
     if (mColorFormat != OMX_COLOR_FormatYUV420Planar || mInputDataIsMeta) {
         // Color conversion is needed.
         free(mInputFrameData);
+        mInputFrameData = NULL;
+        if (((uint64_t)mWidth * mHeight) > ((uint64_t)INT32_MAX / 3)) {
+            ALOGE("b/25812794, Buffer size is too big.");
+            return OMX_ErrorBadParameter;
+        }
         mInputFrameData =
             (uint8_t *) malloc((mWidth * mHeight * 3 ) >> 1);
         CHECK(mInputFrameData != NULL);
diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
index e654843..410f9d0 100644
--- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
+++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
@@ -26,6 +26,10 @@
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/MediaDefs.h>
 
+#ifndef INT32_MAX
+#define INT32_MAX   2147483647
+#endif
+
 namespace android {
 
 template<class T>
@@ -315,6 +319,11 @@
 
     if (mColorFormat != OMX_COLOR_FormatYUV420Planar || mInputDataIsMeta) {
         free(mConversionBuffer);
+        mConversionBuffer = NULL;
+        if (((uint64_t)mWidth * mHeight) > ((uint64_t)INT32_MAX / 3)) {
+            ALOGE("b/25812794, Buffer size is too big.");
+            return UNKNOWN_ERROR;
+        }
         mConversionBuffer = (uint8_t *)malloc(mWidth * mHeight * 3 / 2);
         if (mConversionBuffer == NULL) {
             ALOGE("Allocating conversion buffer failed.");
diff --git a/media/mtp/MtpDevice.cpp b/media/mtp/MtpDevice.cpp
index 01117e6..f8b913a 100644
--- a/media/mtp/MtpDevice.cpp
+++ b/media/mtp/MtpDevice.cpp
@@ -133,6 +133,10 @@
                     printf("no MTP string\n");
                 }
             }
+#else
+            else {
+                continue;
+            }
 #endif
             // if we got here, then we have a likely MTP or PTP device
 
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index 9b4ba79..87f9aaa 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -47,6 +47,7 @@
     liblog \
     libbinder \
     libmedia \
+    libmediautils \
     libnbaio \
     libhardware \
     libhardware_legacy \
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index fab1ef5..385e0b9 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -63,6 +63,7 @@
 #include <media/nbaio/Pipe.h>
 #include <media/nbaio/PipeReader.h>
 #include <media/AudioParameter.h>
+#include <mediautils/BatteryNotifier.h>
 #include <private/android_filesystem_config.h>
 
 // ----------------------------------------------------------------------------
@@ -191,6 +192,11 @@
                 MemoryHeapBase::READ_ONLY);
     }
 
+    // reset battery stats.
+    // if the audio service has crashed, battery stats could be left
+    // in bad state, reset the state upon service start.
+    BatteryNotifier::getInstance().noteResetAudio();
+
 #ifdef TEE_SINK
     (void) property_get("ro.debuggable", value, "0");
     int debuggable = atoi(value);
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index b9e7a8b..553970b 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -48,6 +48,7 @@
 #include <media/nbaio/Pipe.h>
 #include <media/nbaio/PipeReader.h>
 #include <media/nbaio/SourceAudioBufferProvider.h>
+#include <mediautils/BatteryNotifier.h>
 
 #include <powermanager/PowerManager.h>
 
@@ -357,54 +358,54 @@
         audio_devices_t mDevices;
         const char *    mString;
     } mappingsOut[] = {
-        AUDIO_DEVICE_OUT_EARPIECE,          "EARPIECE",
-        AUDIO_DEVICE_OUT_SPEAKER,           "SPEAKER",
-        AUDIO_DEVICE_OUT_WIRED_HEADSET,     "WIRED_HEADSET",
-        AUDIO_DEVICE_OUT_WIRED_HEADPHONE,   "WIRED_HEADPHONE",
-        AUDIO_DEVICE_OUT_BLUETOOTH_SCO,     "BLUETOOTH_SCO",
-        AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET,     "BLUETOOTH_SCO_HEADSET",
-        AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT,      "BLUETOOTH_SCO_CARKIT",
-        AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,            "BLUETOOTH_A2DP",
-        AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES, "BLUETOOTH_A2DP_HEADPHONES",
-        AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER,    "BLUETOOTH_A2DP_SPEAKER",
-        AUDIO_DEVICE_OUT_AUX_DIGITAL,       "AUX_DIGITAL",
-        AUDIO_DEVICE_OUT_HDMI,              "HDMI",
-        AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET, "ANLG_DOCK_HEADSET",
-        AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET, "DGTL_DOCK_HEADSET",
-        AUDIO_DEVICE_OUT_USB_ACCESSORY,     "USB_ACCESSORY",
-        AUDIO_DEVICE_OUT_USB_DEVICE,        "USB_DEVICE",
-        AUDIO_DEVICE_OUT_TELEPHONY_TX,      "TELEPHONY_TX",
-        AUDIO_DEVICE_OUT_LINE,              "LINE",
-        AUDIO_DEVICE_OUT_HDMI_ARC,          "HDMI_ARC",
-        AUDIO_DEVICE_OUT_SPDIF,             "SPDIF",
-        AUDIO_DEVICE_OUT_FM,                "FM",
-        AUDIO_DEVICE_OUT_AUX_LINE,          "AUX_LINE",
-        AUDIO_DEVICE_OUT_SPEAKER_SAFE,      "SPEAKER_SAFE",
-        AUDIO_DEVICE_OUT_IP,                "IP",
-        AUDIO_DEVICE_NONE,                  "NONE",         // must be last
+        {AUDIO_DEVICE_OUT_EARPIECE,         "EARPIECE"},
+        {AUDIO_DEVICE_OUT_SPEAKER,          "SPEAKER"},
+        {AUDIO_DEVICE_OUT_WIRED_HEADSET,    "WIRED_HEADSET"},
+        {AUDIO_DEVICE_OUT_WIRED_HEADPHONE,  "WIRED_HEADPHONE"},
+        {AUDIO_DEVICE_OUT_BLUETOOTH_SCO,    "BLUETOOTH_SCO"},
+        {AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET,    "BLUETOOTH_SCO_HEADSET"},
+        {AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT,     "BLUETOOTH_SCO_CARKIT"},
+        {AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,           "BLUETOOTH_A2DP"},
+        {AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES,"BLUETOOTH_A2DP_HEADPHONES"},
+        {AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER,   "BLUETOOTH_A2DP_SPEAKER"},
+        {AUDIO_DEVICE_OUT_AUX_DIGITAL,      "AUX_DIGITAL"},
+        {AUDIO_DEVICE_OUT_HDMI,             "HDMI"},
+        {AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET,"ANLG_DOCK_HEADSET"},
+        {AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET,"DGTL_DOCK_HEADSET"},
+        {AUDIO_DEVICE_OUT_USB_ACCESSORY,    "USB_ACCESSORY"},
+        {AUDIO_DEVICE_OUT_USB_DEVICE,       "USB_DEVICE"},
+        {AUDIO_DEVICE_OUT_TELEPHONY_TX,     "TELEPHONY_TX"},
+        {AUDIO_DEVICE_OUT_LINE,             "LINE"},
+        {AUDIO_DEVICE_OUT_HDMI_ARC,         "HDMI_ARC"},
+        {AUDIO_DEVICE_OUT_SPDIF,            "SPDIF"},
+        {AUDIO_DEVICE_OUT_FM,               "FM"},
+        {AUDIO_DEVICE_OUT_AUX_LINE,         "AUX_LINE"},
+        {AUDIO_DEVICE_OUT_SPEAKER_SAFE,     "SPEAKER_SAFE"},
+        {AUDIO_DEVICE_OUT_IP,               "IP"},
+        {AUDIO_DEVICE_NONE,                 "NONE"},       // must be last
     }, mappingsIn[] = {
-        AUDIO_DEVICE_IN_COMMUNICATION,      "COMMUNICATION",
-        AUDIO_DEVICE_IN_AMBIENT,            "AMBIENT",
-        AUDIO_DEVICE_IN_BUILTIN_MIC,        "BUILTIN_MIC",
-        AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,  "BLUETOOTH_SCO_HEADSET",
-        AUDIO_DEVICE_IN_WIRED_HEADSET,      "WIRED_HEADSET",
-        AUDIO_DEVICE_IN_AUX_DIGITAL,        "AUX_DIGITAL",
-        AUDIO_DEVICE_IN_VOICE_CALL,         "VOICE_CALL",
-        AUDIO_DEVICE_IN_TELEPHONY_RX,       "TELEPHONY_RX",
-        AUDIO_DEVICE_IN_BACK_MIC,           "BACK_MIC",
-        AUDIO_DEVICE_IN_REMOTE_SUBMIX,      "REMOTE_SUBMIX",
-        AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET,  "ANLG_DOCK_HEADSET",
-        AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET,  "DGTL_DOCK_HEADSET",
-        AUDIO_DEVICE_IN_USB_ACCESSORY,      "USB_ACCESSORY",
-        AUDIO_DEVICE_IN_USB_DEVICE,         "USB_DEVICE",
-        AUDIO_DEVICE_IN_FM_TUNER,           "FM_TUNER",
-        AUDIO_DEVICE_IN_TV_TUNER,           "TV_TUNER",
-        AUDIO_DEVICE_IN_LINE,               "LINE",
-        AUDIO_DEVICE_IN_SPDIF,              "SPDIF",
-        AUDIO_DEVICE_IN_BLUETOOTH_A2DP,     "BLUETOOTH_A2DP",
-        AUDIO_DEVICE_IN_LOOPBACK,           "LOOPBACK",
-        AUDIO_DEVICE_IN_IP,                 "IP",
-        AUDIO_DEVICE_NONE,                  "NONE",         // must be last
+        {AUDIO_DEVICE_IN_COMMUNICATION,     "COMMUNICATION"},
+        {AUDIO_DEVICE_IN_AMBIENT,           "AMBIENT"},
+        {AUDIO_DEVICE_IN_BUILTIN_MIC,       "BUILTIN_MIC"},
+        {AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, "BLUETOOTH_SCO_HEADSET"},
+        {AUDIO_DEVICE_IN_WIRED_HEADSET,     "WIRED_HEADSET"},
+        {AUDIO_DEVICE_IN_AUX_DIGITAL,       "AUX_DIGITAL"},
+        {AUDIO_DEVICE_IN_VOICE_CALL,        "VOICE_CALL"},
+        {AUDIO_DEVICE_IN_TELEPHONY_RX,      "TELEPHONY_RX"},
+        {AUDIO_DEVICE_IN_BACK_MIC,          "BACK_MIC"},
+        {AUDIO_DEVICE_IN_REMOTE_SUBMIX,     "REMOTE_SUBMIX"},
+        {AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET, "ANLG_DOCK_HEADSET"},
+        {AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET, "DGTL_DOCK_HEADSET"},
+        {AUDIO_DEVICE_IN_USB_ACCESSORY,     "USB_ACCESSORY"},
+        {AUDIO_DEVICE_IN_USB_DEVICE,        "USB_DEVICE"},
+        {AUDIO_DEVICE_IN_FM_TUNER,          "FM_TUNER"},
+        {AUDIO_DEVICE_IN_TV_TUNER,          "TV_TUNER"},
+        {AUDIO_DEVICE_IN_LINE,              "LINE"},
+        {AUDIO_DEVICE_IN_SPDIF,             "SPDIF"},
+        {AUDIO_DEVICE_IN_BLUETOOTH_A2DP,    "BLUETOOTH_A2DP"},
+        {AUDIO_DEVICE_IN_LOOPBACK,          "LOOPBACK"},
+        {AUDIO_DEVICE_IN_IP,                "IP"},
+        {AUDIO_DEVICE_NONE,                 "NONE"},        // must be last
     };
     String8 result;
     audio_devices_t allDevices = AUDIO_DEVICE_NONE;
@@ -442,11 +443,11 @@
         audio_input_flags_t     mFlag;
         const char *            mString;
     } mappings[] = {
-        AUDIO_INPUT_FLAG_FAST,              "FAST",
-        AUDIO_INPUT_FLAG_HW_HOTWORD,        "HW_HOTWORD",
-        AUDIO_INPUT_FLAG_RAW,               "RAW",
-        AUDIO_INPUT_FLAG_SYNC,              "SYNC",
-        AUDIO_INPUT_FLAG_NONE,              "NONE",         // must be last
+        {AUDIO_INPUT_FLAG_FAST,             "FAST"},
+        {AUDIO_INPUT_FLAG_HW_HOTWORD,       "HW_HOTWORD"},
+        {AUDIO_INPUT_FLAG_RAW,              "RAW"},
+        {AUDIO_INPUT_FLAG_SYNC,             "SYNC"},
+        {AUDIO_INPUT_FLAG_NONE,             "NONE"},        // must be last
     };
     String8 result;
     audio_input_flags_t allFlags = AUDIO_INPUT_FLAG_NONE;
@@ -478,17 +479,17 @@
         audio_output_flags_t    mFlag;
         const char *            mString;
     } mappings[] = {
-        AUDIO_OUTPUT_FLAG_DIRECT,           "DIRECT",
-        AUDIO_OUTPUT_FLAG_PRIMARY,          "PRIMARY",
-        AUDIO_OUTPUT_FLAG_FAST,             "FAST",
-        AUDIO_OUTPUT_FLAG_DEEP_BUFFER,      "DEEP_BUFFER",
-        AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD, "COMPRESS_OFFLOAD",
-        AUDIO_OUTPUT_FLAG_NON_BLOCKING,     "NON_BLOCKING",
-        AUDIO_OUTPUT_FLAG_HW_AV_SYNC,       "HW_AV_SYNC",
-        AUDIO_OUTPUT_FLAG_RAW,              "RAW",
-        AUDIO_OUTPUT_FLAG_SYNC,             "SYNC",
-        AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO,  "IEC958_NONAUDIO",
-        AUDIO_OUTPUT_FLAG_NONE,             "NONE",         // must be last
+        {AUDIO_OUTPUT_FLAG_DIRECT,          "DIRECT"},
+        {AUDIO_OUTPUT_FLAG_PRIMARY,         "PRIMARY"},
+        {AUDIO_OUTPUT_FLAG_FAST,            "FAST"},
+        {AUDIO_OUTPUT_FLAG_DEEP_BUFFER,     "DEEP_BUFFER"},
+        {AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD,"COMPRESS_OFFLOAD"},
+        {AUDIO_OUTPUT_FLAG_NON_BLOCKING,    "NON_BLOCKING"},
+        {AUDIO_OUTPUT_FLAG_HW_AV_SYNC,      "HW_AV_SYNC"},
+        {AUDIO_OUTPUT_FLAG_RAW,             "RAW"},
+        {AUDIO_OUTPUT_FLAG_SYNC,            "SYNC"},
+        {AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO, "IEC958_NONAUDIO"},
+        {AUDIO_OUTPUT_FLAG_NONE,            "NONE"},        // must be last
     };
     String8 result;
     audio_output_flags_t allFlags = AUDIO_OUTPUT_FLAG_NONE;
@@ -546,7 +547,8 @@
         mAudioSource(AUDIO_SOURCE_DEFAULT), mId(id),
         // mName will be set by concrete (non-virtual) subclass
         mDeathRecipient(new PMDeathRecipient(this)),
-        mSystemReady(systemReady)
+        mSystemReady(systemReady),
+        mNotifiedBatteryStart(false)
 {
     memset(&mPatch, 0, sizeof(struct audio_patch));
 }
@@ -927,6 +929,11 @@
         }
         ALOGV("acquireWakeLock_l() %s status %d", mThreadName, status);
     }
+
+    if (!mNotifiedBatteryStart) {
+        BatteryNotifier::getInstance().noteStartAudio();
+        mNotifiedBatteryStart = true;
+    }
 }
 
 void AudioFlinger::ThreadBase::releaseWakeLock()
@@ -945,6 +952,11 @@
         }
         mWakeLockToken.clear();
     }
+
+    if (mNotifiedBatteryStart) {
+        BatteryNotifier::getInstance().noteStopAudio();
+        mNotifiedBatteryStart = false;
+    }
 }
 
 void AudioFlinger::ThreadBase::updateWakeLockUids(const SortedVector<int> &uids) {
@@ -3843,7 +3855,10 @@
                     // because we're about to decrement the last sp<> on those tracks.
                     block = FastMixerStateQueue::BLOCK_UNTIL_ACKED;
                 } else {
-                    LOG_ALWAYS_FATAL("fast track %d should have been active", j);
+                    LOG_ALWAYS_FATAL("fast track %d should have been active; "
+                            "mState=%d, mTrackMask=%#x, recentUnderruns=%u, isShared=%d",
+                            j, track->mState, state->mTrackMask, recentUnderruns,
+                            track->sharedBuffer() != 0);
                 }
                 tracksToRemove->add(track);
                 // Avoids a misleading display in dumpsys
@@ -4387,8 +4402,12 @@
     dprintf(fd, "  AudioMixer tracks: 0x%08x\n", mAudioMixer->trackNames());
 
     // Make a non-atomic copy of fast mixer dump state so it won't change underneath us
-    const FastMixerDumpState copy(mFastMixerDumpState);
-    copy.dump(fd);
+    // while we are dumping it.  It may be inconsistent, but it won't mutate!
+    // This is a large object so we place it on the heap.
+    // FIXME 25972958: Need an intelligent copy constructor that does not touch unused pages.
+    const FastMixerDumpState *copy = new FastMixerDumpState(mFastMixerDumpState);
+    copy->dump(fd);
+    delete copy;
 
 #ifdef STATE_QUEUE_DUMP
     // Similar for state queue
@@ -6361,9 +6380,13 @@
     dprintf(fd, "  Fast capture thread: %s\n", hasFastCapture() ? "yes" : "no");
     dprintf(fd, "  Fast track available: %s\n", mFastTrackAvail ? "yes" : "no");
 
-    //  Make a non-atomic copy of fast capture dump state so it won't change underneath us
-    const FastCaptureDumpState copy(mFastCaptureDumpState);
-    copy.dump(fd);
+    // Make a non-atomic copy of fast capture dump state so it won't change underneath us
+    // while we are dumping it.  It may be inconsistent, but it won't mutate!
+    // This is a large object so we place it on the heap.
+    // FIXME 25972958: Need an intelligent copy constructor that does not touch unused pages.
+    const FastCaptureDumpState *copy = new FastCaptureDumpState(mFastCaptureDumpState);
+    copy->dump(fd);
+    delete copy;
 }
 
 void AudioFlinger::RecordThread::dumpTracks(int fd, const Vector<String16>& args __unused)
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 46ac300..114d43c 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -457,6 +457,7 @@
                 static const size_t     kLogSize = 4 * 1024;
                 sp<NBLog::Writer>       mNBLogWriter;
                 bool                    mSystemReady;
+                bool                    mNotifiedBatteryStart;
 };
 
 // --- PlaybackThread ---
diff --git a/services/audiopolicy/Android.mk b/services/audiopolicy/Android.mk
index 5b38e1c..671d7fb 100644
--- a/services/audiopolicy/Android.mk
+++ b/services/audiopolicy/Android.mk
@@ -24,6 +24,7 @@
     $(call include-path-for, audio-utils) \
     $(TOPDIR)frameworks/av/services/audiopolicy/common/include \
     $(TOPDIR)frameworks/av/services/audiopolicy/engine/interface \
+    $(TOPDIR)frameworks/av/services/audiopolicy/utilities \
 
 LOCAL_SHARED_LIBRARIES := \
     libcutils \
@@ -84,6 +85,7 @@
 LOCAL_C_INCLUDES += \
     $(TOPDIR)frameworks/av/services/audiopolicy/common/include \
     $(TOPDIR)frameworks/av/services/audiopolicy/engine/interface \
+    $(TOPDIR)frameworks/av/services/audiopolicy/utilities \
 
 LOCAL_STATIC_LIBRARIES := \
     libmedia_helper \
diff --git a/services/audiopolicy/common/include/Volume.h b/services/audiopolicy/common/include/Volume.h
index 712f7a7..d091179 100755
--- a/services/audiopolicy/common/include/Volume.h
+++ b/services/audiopolicy/common/include/Volume.h
@@ -30,6 +30,17 @@
     float mDBAttenuation;
 };
 
+/**
+ * device categories used for volume curve management.
+ */
+enum device_category {
+    DEVICE_CATEGORY_HEADSET,
+    DEVICE_CATEGORY_SPEAKER,
+    DEVICE_CATEGORY_EARPIECE,
+    DEVICE_CATEGORY_EXT_MEDIA,
+    DEVICE_CATEGORY_CNT
+};
+
 class Volume
 {
 public:
@@ -50,17 +61,6 @@
     };
 
     /**
-     * device categories used for volume curve management.
-     */
-    enum device_category {
-        DEVICE_CATEGORY_HEADSET,
-        DEVICE_CATEGORY_SPEAKER,
-        DEVICE_CATEGORY_EARPIECE,
-        DEVICE_CATEGORY_EXT_MEDIA,
-        DEVICE_CATEGORY_CNT
-    };
-
-    /**
      * extract one device relevant for volume control from multiple device selection
      *
      * @param[in] device for which the volume category is associated
diff --git a/services/audiopolicy/common/managerdefinitions/Android.mk b/services/audiopolicy/common/managerdefinitions/Android.mk
index 6cd8b40..dc7eff7 100644
--- a/services/audiopolicy/common/managerdefinitions/Android.mk
+++ b/services/audiopolicy/common/managerdefinitions/Android.mk
@@ -17,7 +17,8 @@
     src/ConfigParsingUtils.cpp \
     src/SoundTriggerSession.cpp \
     src/SessionRoute.cpp \
-    src/AudioSourceDescriptor.cpp
+    src/AudioSourceDescriptor.cpp \
+    src/TypeConverter.cpp
 
 LOCAL_SHARED_LIBRARIES := \
     libcutils \
@@ -27,7 +28,8 @@
 LOCAL_C_INCLUDES += \
     $(LOCAL_PATH)/include \
     $(TOPDIR)frameworks/av/services/audiopolicy/common/include \
-    $(TOPDIR)frameworks/av/services/audiopolicy
+    $(TOPDIR)frameworks/av/services/audiopolicy \
+    $(TOPDIR)frameworks/av/services/audiopolicy/utilities \
 
 LOCAL_EXPORT_C_INCLUDE_DIRS := \
     $(LOCAL_PATH)/include
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioGain.h b/services/audiopolicy/common/managerdefinitions/include/AudioGain.h
index 21fbf9b..cea5c0b 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioGain.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioGain.h
@@ -28,10 +28,39 @@
     AudioGain(int index, bool useInChannelMask);
     virtual ~AudioGain() {}
 
+    void setMode(audio_gain_mode_t mode) { mGain.mode = mode; }
+    const audio_gain_mode_t &getMode() const { return mGain.mode; }
+
+    void setChannelMask(audio_channel_mask_t mask) { mGain.channel_mask = mask; }
+    const audio_channel_mask_t &getChannelMask() const { return mGain.channel_mask; }
+
+    void setMinValueInMb(int minValue) { mGain.min_value = minValue; }
+    int getMinValueInMb() const { return mGain.min_value; }
+
+    void setMaxValueInMb(int maxValue) { mGain.max_value = maxValue; }
+    int getMaxValueInMb() const { return mGain.max_value; }
+
+    void setDefaultValueInMb(int defaultValue) { mGain.default_value = defaultValue; }
+    int getDefaultValueInMb() const { return mGain.default_value; }
+
+    void setStepValueInMb(uint32_t stepValue) { mGain.step_value = stepValue; }
+    int getStepValueInMb() const { return mGain.step_value; }
+
+    void setMinRampInMs(uint32_t minRamp) { mGain.min_ramp_ms = minRamp; }
+    int getMinRampInMs() const { return mGain.min_ramp_ms; }
+
+    void setMaxRampInMs(uint32_t maxRamp) { mGain.max_ramp_ms = maxRamp; }
+    int getMaxRampInMs() const { return mGain.max_ramp_ms; }
+
+    // TODO: remove dump from here (split serialization)
     void dump(int fd, int spaces, int index) const;
 
     void getDefaultConfig(struct audio_gain_config *config);
     status_t checkConfig(const struct audio_gain_config *config);
+
+    const struct audio_gain &getGain() const { return mGain; }
+
+private:
     int               mIndex;
     struct audio_gain mGain;
     bool              mUseInChannelMask;
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
new file mode 100644
index 0000000..5ff0396
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2009 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 <AudioGain.h>
+#include <AudioPort.h>
+#include <AudioPatch.h>
+#include <DeviceDescriptor.h>
+#include <IOProfile.h>
+#include <HwModule.h>
+#include <AudioInputDescriptor.h>
+#include <AudioOutputDescriptor.h>
+#include <AudioPolicyMix.h>
+#include <EffectDescriptor.h>
+#include <SoundTriggerSession.h>
+#include <StreamDescriptor.h>
+#include <SessionRoute.h>
+
+namespace android {
+
+class AudioPolicyConfig
+{
+public:
+    AudioPolicyConfig(HwModuleCollection &hwModules,
+                      DeviceVector &availableOutputDevices,
+                      DeviceVector &availableInputDevices,
+                      sp<DeviceDescriptor> &defaultOutputDevices,
+                      bool &isSpeakerDrcEnabled)
+        : mHwModules(hwModules),
+          mAvailableOutputDevices(availableOutputDevices),
+          mAvailableInputDevices(availableInputDevices),
+          mDefaultOutputDevices(defaultOutputDevices),
+          mIsSpeakerDrcEnabled(isSpeakerDrcEnabled)
+    {}
+
+    void setHwModules(const HwModuleCollection &hwModules)
+    {
+        mHwModules = hwModules;
+    }
+
+    void addAvailableInputDevices(const DeviceVector &availableInputDevices)
+    {
+        mAvailableInputDevices.add(availableInputDevices);
+    }
+
+    void addAvailableOutputDevices(const DeviceVector &availableOutputDevices)
+    {
+        mAvailableOutputDevices.add(availableOutputDevices);
+    }
+
+    void setSpeakerDrcEnabled(bool isSpeakerDrcEnabled)
+    {
+        mIsSpeakerDrcEnabled = isSpeakerDrcEnabled;
+    }
+
+    const HwModuleCollection getHwModules() const { return mHwModules; }
+
+    const DeviceVector &getAvailableInputDevices() const
+    {
+        return mAvailableInputDevices;
+    }
+
+    const DeviceVector &getAvailableOutputDevices() const
+    {
+        return mAvailableOutputDevices;
+    }
+
+    void setDefaultOutputDevice(const sp<DeviceDescriptor> &defaultDevice)
+    {
+        mDefaultOutputDevices = defaultDevice;
+    }
+
+    const sp<DeviceDescriptor> &getDefaultOutputDevice() const { return mDefaultOutputDevices; }
+
+    void setDefault(void)
+    {
+        mDefaultOutputDevices = new DeviceDescriptor(AUDIO_DEVICE_OUT_SPEAKER);
+        sp<HwModule> module;
+        sp<DeviceDescriptor> defaultInputDevice = new DeviceDescriptor(AUDIO_DEVICE_IN_BUILTIN_MIC);
+        mAvailableOutputDevices.add(mDefaultOutputDevices);
+        mAvailableInputDevices.add(defaultInputDevice);
+
+        module = new HwModule("primary");
+
+        sp<OutputProfile> outProfile;
+        outProfile = new OutputProfile(String8("primary"));
+        outProfile->attach(module);
+        outProfile->mSamplingRates.add(44100);
+        outProfile->mFormats.add(AUDIO_FORMAT_PCM_16_BIT);
+        outProfile->mChannelMasks.add(AUDIO_CHANNEL_OUT_STEREO);
+        outProfile->addSupportedDevice(mDefaultOutputDevices);
+        outProfile->setFlags(AUDIO_OUTPUT_FLAG_PRIMARY);
+        module->mOutputProfiles.add(outProfile);
+
+        sp<InputProfile> inProfile;
+        inProfile = new InputProfile(String8("primary"));
+        inProfile->attach(module);
+        inProfile->mSamplingRates.add(8000);
+        inProfile->mFormats.add(AUDIO_FORMAT_PCM_16_BIT);
+        inProfile->mChannelMasks.add(AUDIO_CHANNEL_IN_MONO);
+        inProfile->addSupportedDevice(defaultInputDevice);
+        module->mInputProfiles.add(inProfile);
+
+        mHwModules.add(module);
+    }
+
+private:
+    HwModuleCollection &mHwModules; /**< Collection of Module, with Profiles, i.e. Mix Ports. */
+    DeviceVector &mAvailableOutputDevices;
+    DeviceVector &mAvailableInputDevices;
+    sp<DeviceDescriptor> &mDefaultOutputDevices;
+    bool &mIsSpeakerDrcEnabled;
+};
+
+}; // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
index 4fdf5b4..5666920 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
@@ -27,14 +27,28 @@
 
 class HwModule;
 class AudioGain;
+typedef Vector<sp<AudioGain> > AudioGainCollection;
 
 class AudioPort : public virtual RefBase
 {
 public:
-    AudioPort(const String8& name, audio_port_type_t type,
-              audio_port_role_t role);
+    AudioPort(const String8& name, audio_port_type_t type,  audio_port_role_t role) :
+        mName(name), mType(type), mRole(role), mFlags(AUDIO_OUTPUT_FLAG_NONE) {}
+
     virtual ~AudioPort() {}
 
+    void setName(const String8 &name) { mName = name; }
+    const String8 &getName() const { return mName; }
+
+    audio_port_type_t getType() const { return mType; }
+    audio_port_role_t getRole() const { return mRole; }
+
+    void setGains(const AudioGainCollection &gains) { mGains = gains; }
+    const AudioGainCollection &getGains() const { return mGains; }
+
+    void setFlags(uint32_t flags) { mFlags = flags; }
+    uint32_t getFlags() const { return mFlags; }
+
     virtual void attach(const sp<HwModule>& module);
     bool isAttached() { return mModule != 0; }
 
@@ -45,14 +59,15 @@
     virtual void importAudioPort(const sp<AudioPort> port);
     void clearCapabilities();
 
-    void loadSamplingRates(char *name);
-    void loadFormats(char *name);
-    void loadOutChannels(char *name);
-    void loadInChannels(char *name);
-
-    audio_gain_mode_t loadGainMode(char *name);
-    void loadGain(cnode *root, int index);
-    virtual void loadGains(cnode *root);
+    void setSupportedFormats(const Vector <audio_format_t> &formats);
+    void setSupportedSamplingRates(const Vector <uint32_t> &sampleRates)
+    {
+        mSamplingRates = sampleRates;
+    }
+    void setSupportedChannelMasks(const Vector <audio_channel_mask_t> &channelMasks)
+    {
+        mChannelMasks = channelMasks;
+    }
 
     // searches for an exact match
     status_t checkExactSamplingRate(uint32_t samplingRate) const;
@@ -84,25 +99,29 @@
     uint32_t getModuleVersion() const;
     const char *getModuleName() const;
 
+    bool useInputChannelMask() const
+    {
+        return ((mType == AUDIO_PORT_TYPE_DEVICE) && (mRole == AUDIO_PORT_ROLE_SOURCE)) ||
+                ((mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SINK));
+    }
+
     void dump(int fd, int spaces) const;
     void log(const char* indent) const;
 
-    String8           mName;
-    audio_port_type_t mType;
-    audio_port_role_t mRole;
-    bool              mUseInChannelMask;
     // by convention, "0' in the first entry in mSamplingRates, mChannelMasks or mFormats
     // indicates the supported parameters should be read from the output stream
     // after it is opened for the first time
     Vector <uint32_t> mSamplingRates; // supported sampling rates
     Vector <audio_channel_mask_t> mChannelMasks; // supported channel masks
     Vector <audio_format_t> mFormats; // supported audio formats
-    Vector < sp<AudioGain> > mGains; // gain controllers
+    AudioGainCollection mGains; // gain controllers
     sp<HwModule> mModule;                 // audio HW module exposing this I/O stream
-    uint32_t mFlags; // attribute flags (e.g primary output,
-                     // direct output...).
 
 private:
+    String8           mName;
+    audio_port_type_t mType;
+    audio_port_role_t mRole;
+    uint32_t mFlags; // attribute flags mask (e.g primary output, direct output...).
     static volatile int32_t mNextUniqueId;
 };
 
diff --git a/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h b/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h
index 78d2cdf..1eddab9 100644
--- a/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h
+++ b/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h
@@ -16,6 +16,7 @@
 
 #pragma once
 
+#include "AudioPolicyConfig.h"
 #include "DeviceDescriptor.h"
 #include "HwModule.h"
 #include "audio_policy_conf.h"
@@ -33,243 +34,28 @@
 // Definitions for audio_policy.conf file parsing
 // ----------------------------------------------------------------------------
 
-struct StringToEnum {
-    const char *name;
-    uint32_t value;
-};
-
-// TODO: move to a separate file. Should be in sync with audio.h.
-#define STRING_TO_ENUM(string) { #string, (uint32_t)string } // uint32_t cast removes warning
-#define NAME_TO_ENUM(name, value) { name, value }
-#ifndef ARRAY_SIZE
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
-#endif
-
-const StringToEnum sDeviceTypeToEnumTable[] = {
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_EARPIECE),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_SPEAKER),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_SPEAKER_SAFE),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_WIRED_HEADSET),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_WIRED_HEADPHONE),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_SCO),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_ALL_SCO),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_ALL_A2DP),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_AUX_DIGITAL),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_HDMI),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_USB_ACCESSORY),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_USB_DEVICE),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_ALL_USB),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_REMOTE_SUBMIX),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_TELEPHONY_TX),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_LINE),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_HDMI_ARC),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_SPDIF),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_FM),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_AUX_LINE),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_IP),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_AMBIENT),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_BUILTIN_MIC),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_ALL_SCO),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_WIRED_HEADSET),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_AUX_DIGITAL),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_HDMI),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_TELEPHONY_RX),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_VOICE_CALL),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_BACK_MIC),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_REMOTE_SUBMIX),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_USB_ACCESSORY),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_USB_DEVICE),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_FM_TUNER),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_TV_TUNER),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_LINE),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_SPDIF),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_A2DP),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_LOOPBACK),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_IP),
-};
-
-const StringToEnum sDeviceNameToEnumTable[] = {
-    NAME_TO_ENUM("Earpiece", AUDIO_DEVICE_OUT_EARPIECE),
-    NAME_TO_ENUM("Speaker", AUDIO_DEVICE_OUT_SPEAKER),
-    NAME_TO_ENUM("Speaker Protected", AUDIO_DEVICE_OUT_SPEAKER_SAFE),
-    NAME_TO_ENUM("Wired Headset", AUDIO_DEVICE_OUT_WIRED_HEADSET),
-    NAME_TO_ENUM("Wired Headphones", AUDIO_DEVICE_OUT_WIRED_HEADPHONE),
-    NAME_TO_ENUM("BT SCO", AUDIO_DEVICE_OUT_BLUETOOTH_SCO),
-    NAME_TO_ENUM("BT SCO Headset", AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET),
-    NAME_TO_ENUM("BT SCO Car Kit", AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT),
-    NAME_TO_ENUM("", AUDIO_DEVICE_OUT_ALL_SCO),
-    NAME_TO_ENUM("BT A2DP Out", AUDIO_DEVICE_OUT_BLUETOOTH_A2DP),
-    NAME_TO_ENUM("BT A2DP Headphones", AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES),
-    NAME_TO_ENUM("BT A2DP Speaker", AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER),
-    NAME_TO_ENUM("", AUDIO_DEVICE_OUT_ALL_A2DP),
-    NAME_TO_ENUM("HDMI Out", AUDIO_DEVICE_OUT_AUX_DIGITAL),
-    NAME_TO_ENUM("HDMI Out", AUDIO_DEVICE_OUT_HDMI),
-    NAME_TO_ENUM("Analog Dock Out", AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET),
-    NAME_TO_ENUM("Digital Dock Out", AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET),
-    NAME_TO_ENUM("USB Host Out", AUDIO_DEVICE_OUT_USB_ACCESSORY),
-    NAME_TO_ENUM("USB Device Out", AUDIO_DEVICE_OUT_USB_DEVICE),
-    NAME_TO_ENUM("", AUDIO_DEVICE_OUT_ALL_USB),
-    NAME_TO_ENUM("Reroute Submix Out", AUDIO_DEVICE_OUT_REMOTE_SUBMIX),
-    NAME_TO_ENUM("Telephony Tx", AUDIO_DEVICE_OUT_TELEPHONY_TX),
-    NAME_TO_ENUM("Line Out", AUDIO_DEVICE_OUT_LINE),
-    NAME_TO_ENUM("HDMI ARC Out", AUDIO_DEVICE_OUT_HDMI_ARC),
-    NAME_TO_ENUM("S/PDIF Out", AUDIO_DEVICE_OUT_SPDIF),
-    NAME_TO_ENUM("FM transceiver Out", AUDIO_DEVICE_OUT_FM),
-    NAME_TO_ENUM("Aux Line Out", AUDIO_DEVICE_OUT_AUX_LINE),
-    NAME_TO_ENUM("IP Out", AUDIO_DEVICE_OUT_IP),
-    NAME_TO_ENUM("Ambient Mic", AUDIO_DEVICE_IN_AMBIENT),
-    NAME_TO_ENUM("Built-In Mic", AUDIO_DEVICE_IN_BUILTIN_MIC),
-    NAME_TO_ENUM("BT SCO Headset Mic", AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET),
-    NAME_TO_ENUM("", AUDIO_DEVICE_IN_ALL_SCO),
-    NAME_TO_ENUM("Wired Headset Mic", AUDIO_DEVICE_IN_WIRED_HEADSET),
-    NAME_TO_ENUM("HDMI In", AUDIO_DEVICE_IN_AUX_DIGITAL),
-    NAME_TO_ENUM("HDMI In", AUDIO_DEVICE_IN_HDMI),
-    NAME_TO_ENUM("Telephony Rx", AUDIO_DEVICE_IN_TELEPHONY_RX),
-    NAME_TO_ENUM("Telephony Rx", AUDIO_DEVICE_IN_VOICE_CALL),
-    NAME_TO_ENUM("Built-In Back Mic", AUDIO_DEVICE_IN_BACK_MIC),
-    NAME_TO_ENUM("Reroute Submix In", AUDIO_DEVICE_IN_REMOTE_SUBMIX),
-    NAME_TO_ENUM("Analog Dock In", AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET),
-    NAME_TO_ENUM("Digital Dock In", AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET),
-    NAME_TO_ENUM("USB Host In", AUDIO_DEVICE_IN_USB_ACCESSORY),
-    NAME_TO_ENUM("USB Device In", AUDIO_DEVICE_IN_USB_DEVICE),
-    NAME_TO_ENUM("FM Tuner In", AUDIO_DEVICE_IN_FM_TUNER),
-    NAME_TO_ENUM("TV Tuner In", AUDIO_DEVICE_IN_TV_TUNER),
-    NAME_TO_ENUM("Line In", AUDIO_DEVICE_IN_LINE),
-    NAME_TO_ENUM("S/PDIF In", AUDIO_DEVICE_IN_SPDIF),
-    NAME_TO_ENUM("BT A2DP In", AUDIO_DEVICE_IN_BLUETOOTH_A2DP),
-    NAME_TO_ENUM("Loopback In", AUDIO_DEVICE_IN_LOOPBACK),
-    NAME_TO_ENUM("IP In", AUDIO_DEVICE_IN_IP),
-};
-
-const StringToEnum sOutputFlagNameToEnumTable[] = {
-    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DIRECT),
-    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_PRIMARY),
-    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_FAST),
-    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DEEP_BUFFER),
-    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD),
-    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_NON_BLOCKING),
-    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_HW_AV_SYNC),
-    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_TTS),
-    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_RAW),
-    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_SYNC),
-};
-
-const StringToEnum sInputFlagNameToEnumTable[] = {
-    STRING_TO_ENUM(AUDIO_INPUT_FLAG_FAST),
-    STRING_TO_ENUM(AUDIO_INPUT_FLAG_HW_HOTWORD),
-    STRING_TO_ENUM(AUDIO_INPUT_FLAG_RAW),
-    STRING_TO_ENUM(AUDIO_INPUT_FLAG_SYNC),
-};
-
-const StringToEnum sFormatNameToEnumTable[] = {
-    STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
-    STRING_TO_ENUM(AUDIO_FORMAT_PCM_8_BIT),
-    STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
-    STRING_TO_ENUM(AUDIO_FORMAT_PCM_8_24_BIT),
-    STRING_TO_ENUM(AUDIO_FORMAT_PCM_FLOAT),
-    STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
-    STRING_TO_ENUM(AUDIO_FORMAT_MP3),
-    STRING_TO_ENUM(AUDIO_FORMAT_AAC),
-    STRING_TO_ENUM(AUDIO_FORMAT_AAC_MAIN),
-    STRING_TO_ENUM(AUDIO_FORMAT_AAC_LC),
-    STRING_TO_ENUM(AUDIO_FORMAT_AAC_SSR),
-    STRING_TO_ENUM(AUDIO_FORMAT_AAC_LTP),
-    STRING_TO_ENUM(AUDIO_FORMAT_AAC_HE_V1),
-    STRING_TO_ENUM(AUDIO_FORMAT_AAC_SCALABLE),
-    STRING_TO_ENUM(AUDIO_FORMAT_AAC_ERLC),
-    STRING_TO_ENUM(AUDIO_FORMAT_AAC_LD),
-    STRING_TO_ENUM(AUDIO_FORMAT_AAC_HE_V2),
-    STRING_TO_ENUM(AUDIO_FORMAT_AAC_ELD),
-    STRING_TO_ENUM(AUDIO_FORMAT_VORBIS),
-    STRING_TO_ENUM(AUDIO_FORMAT_HE_AAC_V1),
-    STRING_TO_ENUM(AUDIO_FORMAT_HE_AAC_V2),
-    STRING_TO_ENUM(AUDIO_FORMAT_OPUS),
-    STRING_TO_ENUM(AUDIO_FORMAT_AC3),
-    STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
-    STRING_TO_ENUM(AUDIO_FORMAT_DTS),
-    STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
-};
-
-const StringToEnum sOutChannelsNameToEnumTable[] = {
-    STRING_TO_ENUM(AUDIO_CHANNEL_OUT_MONO),
-    STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
-    STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
-    STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
-    STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
-};
-
-const StringToEnum sInChannelsNameToEnumTable[] = {
-    STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
-    STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
-    STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
-};
-
-const StringToEnum sIndexChannelsNameToEnumTable[] = {
-    STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
-    STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
-    STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
-    STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
-    STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
-    STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
-    STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
-    STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
-};
-
-const StringToEnum sGainModeNameToEnumTable[] = {
-    STRING_TO_ENUM(AUDIO_GAIN_MODE_JOINT),
-    STRING_TO_ENUM(AUDIO_GAIN_MODE_CHANNELS),
-    STRING_TO_ENUM(AUDIO_GAIN_MODE_RAMP),
-};
-
 class ConfigParsingUtils
 {
 public:
-    static uint32_t stringToEnum(const struct StringToEnum *table,
-            size_t size,
-            const char *name);
-    static const char *enumToString(const struct StringToEnum *table,
-            size_t size,
-            uint32_t value);
-    static bool stringToBool(const char *value);
-    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);
+    static status_t loadConfig(const char *path, AudioPolicyConfig &config);
 
 private:
-    static void loadHwModule(cnode *root, HwModuleCollection &hwModules,
-                             DeviceVector &availableInputDevices,
-                             DeviceVector &availableOutputDevices,
-                             sp<DeviceDescriptor> &defaultOutputDevices,
-                             bool &isSpeakerDrcEnabled);
+    static uint32_t parseOutputFlagNames(const char *name);
+    static void loadAudioPortGain(cnode *root, AudioPort &audioPort, int index);
+    static void loadAudioPortGains(cnode *root, AudioPort &audioPort);
+    static void loadDeviceDescriptorGains(cnode *root, sp<DeviceDescriptor> &deviceDesc);
+    static status_t loadHwModuleDevice(cnode *root, DeviceVector &devices);
+    static status_t loadHwModuleInput(cnode *root, sp<HwModule> &module);
+    static status_t loadHwModuleOutput(cnode *root, sp<HwModule> &module);
+    static void loadDevicesFromTag(const char *tag, DeviceVector &devices,
+                            const DeviceVector &declaredDevices);
+    static void loadHwModules(cnode *root, HwModuleCollection &hwModules,
+                              AudioPolicyConfig &config);
+    static void loadGlobalConfig(cnode *root, AudioPolicyConfig &config,
+                                 const sp<HwModule> &primaryModule);
+    static void loadModuleGlobalConfig(cnode *root, const sp<HwModule> &module,
+                                       AudioPolicyConfig &config);
+    static status_t loadHwModule(cnode *root, sp<HwModule> &module, AudioPolicyConfig &config);
 };
 
 }; // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
index c42ece6..3f43963 100644
--- a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
@@ -29,10 +29,14 @@
 class DeviceDescriptor : public AudioPort, public AudioPortConfig
 {
 public:
-    DeviceDescriptor(audio_devices_t type);
+     // Note that empty name refers by convention to a generic device.
+    DeviceDescriptor(audio_devices_t type, const String8 &tagName = String8(""));
 
     virtual ~DeviceDescriptor() {}
 
+    audio_devices_t type() const { return mDeviceType; }
+    const String8 getTagName() const { return mTagName; }
+
     bool equals(const sp<DeviceDescriptor>& other) const;
 
     // AudioPortConfig
@@ -42,43 +46,39 @@
 
     // AudioPort
     virtual void attach(const sp<HwModule>& module);
-    virtual void loadGains(cnode *root);
     virtual void toAudioPort(struct audio_port *port) const;
     virtual void importAudioPort(const sp<AudioPort> port);
 
     audio_port_handle_t getId() const;
-    audio_devices_t type() const { return mDeviceType; }
     status_t dump(int fd, int spaces, int index) const;
     void log() const;
 
-    String8 mTag;
     String8 mAddress;
 
 private:
+    String8 mTagName;
     audio_devices_t     mDeviceType;
     audio_port_handle_t mId;
 
 friend class DeviceVector;
 };
 
-class DeviceVector : public SortedVector< sp<DeviceDescriptor> >
+class DeviceVector : public SortedVector<sp<DeviceDescriptor> >
 {
 public:
     DeviceVector() : SortedVector(), mDeviceTypes(AUDIO_DEVICE_NONE) {}
 
     ssize_t add(const sp<DeviceDescriptor>& item);
+    void add(const DeviceVector &devices);
     ssize_t remove(const sp<DeviceDescriptor>& item);
     ssize_t indexOf(const sp<DeviceDescriptor>& item) const;
 
     audio_devices_t types() const { return mDeviceTypes; }
 
-    void loadDevicesFromType(audio_devices_t types);
-    void loadDevicesFromTag(char *tag, const DeviceVector& declaredDevices);
-
     sp<DeviceDescriptor> getDevice(audio_devices_t type, String8 address) const;
     DeviceVector getDevicesFromType(audio_devices_t types) const;
     sp<DeviceDescriptor> getDeviceFromId(audio_port_handle_t id) const;
-    sp<DeviceDescriptor> getDeviceFromTag(const String8& tag) const;
+    sp<DeviceDescriptor> getDeviceFromTagName(const String8 &tagName) const;
     DeviceVector getDevicesFromTypeAddr(audio_devices_t type, String8 address) const;
 
     audio_devices_t getDevicesFromHwModule(audio_module_handle_t moduleHandle) const;
diff --git a/services/audiopolicy/common/managerdefinitions/include/HwModule.h b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
index 92c3ea2..f71a1a4 100644
--- a/services/audiopolicy/common/managerdefinitions/include/HwModule.h
+++ b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
@@ -17,26 +17,49 @@
 #pragma once
 
 #include "DeviceDescriptor.h"
+#include <hardware/audio.h>
 #include <utils/RefBase.h>
 #include <utils/String8.h>
 #include <utils/Errors.h>
 #include <utils/Vector.h>
 #include <system/audio.h>
 #include <cutils/config_utils.h>
+#include <string>
 
 namespace android {
 
 class IOProfile;
+class InputProfile;
+class OutputProfile;
+
+typedef Vector<sp<IOProfile> > InputProfileCollection;
+typedef Vector<sp<IOProfile> > OutputProfileCollection;
+typedef Vector<sp<IOProfile> > IOProfileCollection;
 
 class HwModule : public RefBase
 {
 public:
-    HwModule(const char *name);
+    HwModule(const char *name, uint32_t halVersion = AUDIO_DEVICE_API_VERSION_MIN);
     ~HwModule();
 
-    status_t loadOutput(cnode *root);
-    status_t loadInput(cnode *root);
-    status_t loadDevice(cnode *root);
+    const char *getName() const { return mName.string(); }
+
+
+    const DeviceVector &getDeclaredDevices() const { return mDeclaredDevices; }
+    void setDeclaredDevices(const DeviceVector &devices) { mDeclaredDevices = devices; }
+
+    const InputProfileCollection &getInputProfiles() const { return mInputProfiles; }
+
+    const OutputProfileCollection &getOutputProfiles() const { return mOutputProfiles; }
+
+    void setProfiles(const IOProfileCollection &profiles);
+
+    void setHalVersion(uint32_t halVersion) { mHalVersion = halVersion; }
+    uint32_t getHalVersion() const { return mHalVersion; }
+
+    status_t addOutputProfile(const sp<IOProfile> &profile);
+    status_t addInputProfile(const sp<IOProfile> &profile);
+    status_t addProfile(const sp<IOProfile> &profile);
 
     status_t addOutputProfile(String8 name, const audio_config_t *config,
             audio_devices_t device, String8 address);
@@ -47,26 +70,29 @@
 
     audio_module_handle_t getHandle() const { return mHandle; }
 
+    // TODO remove from here (split serialization)
     void dump(int fd);
 
-    const char *const        mName; // base name of the audio HW module (primary, a2dp ...)
-    uint32_t                 mHalVersion; // audio HAL API version
-    audio_module_handle_t    mHandle;
-    Vector < sp<IOProfile> > mOutputProfiles; // output profiles exposed by this module
-    Vector < sp<IOProfile> > mInputProfiles;  // input profiles exposed by this module
-    DeviceVector             mDeclaredDevices; // devices declared in audio_policy.conf
+    const String8 mName; // base name of the audio HW module (primary, a2dp ...)
+    audio_module_handle_t mHandle;
+    OutputProfileCollection mOutputProfiles; // output profiles exposed by this module
+    InputProfileCollection mInputProfiles;  // input profiles exposed by this module
+
+private:
+    uint32_t mHalVersion; // audio HAL API version
+    DeviceVector mDeclaredDevices; // devices declared in audio_policy configuration file.
 };
 
-class HwModuleCollection : public Vector< sp<HwModule> >
+class HwModuleCollection : public Vector<sp<HwModule> >
 {
 public:
     sp<HwModule> getModuleFromName(const char *name) const;
 
-    sp <HwModule> getModuleForDevice(audio_devices_t device) 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;
+    sp<DeviceDescriptor> getDeviceDescriptor(const audio_devices_t device,
+                                             const char *device_address,
+                                             const char *device_name) const;
 
     status_t dump(int fd) const;
 };
diff --git a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
index ab6fcc1..310acff 100644
--- a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
+++ b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
@@ -33,7 +33,7 @@
 class IOProfile : public AudioPort
 {
 public:
-    IOProfile(const String8& name, audio_port_role_t role);
+    IOProfile(const String8 &name, audio_port_role_t role);
     virtual ~IOProfile();
 
     // This method is used for both output and input.
@@ -53,8 +53,68 @@
     void dump(int fd);
     void log();
 
+    bool hasSupportedDevices() const { return !mSupportedDevices.isEmpty(); }
+
+    bool supportDevice(audio_devices_t device) const
+    {
+        if (audio_is_output_devices(device)) {
+            return mSupportedDevices.types() & device;
+        }
+        return mSupportedDevices.types() & (device & ~AUDIO_DEVICE_BIT_IN);
+    }
+
+    bool supportDeviceAddress(const String8 &address) const
+    {
+        return mSupportedDevices[0]->mAddress == address;
+    }
+
+    // chose first device present in mSupportedDevices also part of deviceType
+    audio_devices_t getSupportedDeviceForType(audio_devices_t deviceType) const
+    {
+        for (size_t k = 0; k  < mSupportedDevices.size(); k++) {
+            audio_devices_t profileType = mSupportedDevices[k]->type();
+            if (profileType & deviceType) {
+                return profileType;
+            }
+        }
+        return AUDIO_DEVICE_NONE;
+    }
+
+    audio_devices_t getSupportedDevicesType() const { return mSupportedDevices.types(); }
+
+    void clearSupportedDevices() { mSupportedDevices.clear(); }
+    void addSupportedDevice(const sp<DeviceDescriptor> &device)
+    {
+        mSupportedDevices.add(device);
+    }
+
+    void setSupportedDevices(const DeviceVector &devices)
+    {
+        mSupportedDevices = devices;
+    }
+
+    sp<DeviceDescriptor> getSupportedDeviceByAddress(audio_devices_t type, String8 address) const
+    {
+        return mSupportedDevices.getDevice(type, address);
+    }
+
+    const DeviceVector &getSupportedDevices() const { return mSupportedDevices; }
+
+private:
     DeviceVector  mSupportedDevices; // supported devices
                                      // (devices this output can be routed to)
 };
 
+class InputProfile : public IOProfile
+{
+public:
+    InputProfile(const String8 &name) : IOProfile(name, AUDIO_PORT_ROLE_SINK) {}
+};
+
+class OutputProfile : public IOProfile
+{
+public:
+    OutputProfile(const String8 &name) : IOProfile(name, AUDIO_PORT_ROLE_SOURCE) {}
+};
+
 }; // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/StreamDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/StreamDescriptor.h
index 84db5ab..fbc942c 100644
--- a/services/audiopolicy/common/managerdefinitions/include/StreamDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/StreamDescriptor.h
@@ -41,14 +41,14 @@
 
     void dump(int fd) const;
 
-    void setVolumeCurvePoint(Volume::device_category deviceCategory, const VolumeCurvePoint *point);
-    const VolumeCurvePoint *getVolumeCurvePoint(Volume::device_category deviceCategory) const
+    void setVolumeCurvePoint(device_category deviceCategory, const VolumeCurvePoint *point);
+    const VolumeCurvePoint *getVolumeCurvePoint(device_category deviceCategory) const
     {
         return mVolumeCurve[deviceCategory];
     }
 
 private:
-    const VolumeCurvePoint *mVolumeCurve[Volume::DEVICE_CATEGORY_CNT];
+    const VolumeCurvePoint *mVolumeCurve[DEVICE_CATEGORY_CNT];
     KeyedVector<audio_devices_t, int> mIndexCur; /**< current volume index per device. */
     int mIndexMin; /**< min volume index. */
     int mIndexMax; /**< max volume index. */
@@ -71,11 +71,11 @@
     status_t dump(int fd) const;
 
     void setVolumeCurvePoint(audio_stream_type_t stream,
-                             Volume::device_category deviceCategory,
+                             device_category deviceCategory,
                              const VolumeCurvePoint *point);
 
     const VolumeCurvePoint *getVolumeCurvePoint(audio_stream_type_t stream,
-                                                Volume::device_category deviceCategory) const;
+                                                device_category deviceCategory) const;
 
     void setVolumeIndexMin(audio_stream_type_t stream,int volIndexMin);
     void setVolumeIndexMax(audio_stream_type_t stream,int volIndexMax);
diff --git a/services/audiopolicy/common/managerdefinitions/include/TypeConverter.h b/services/audiopolicy/common/managerdefinitions/include/TypeConverter.h
new file mode 100644
index 0000000..85db863
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/include/TypeConverter.h
@@ -0,0 +1,141 @@
+/*
+ * 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>
+#include <convert/convert.h>
+#include <utils/Log.h>
+#include <string>
+#include <utils/Vector.h>
+
+namespace android {
+
+/**
+ * As far as we do not have real type (only typedef on uint32_t for some types, we
+ * will need this trick to handle template specialization.
+ */
+class Devices;
+class InputFlags;
+class OutputFlags;
+class Formats;
+class OutputChannel;
+class InputChannel;
+class ChannelIndex;
+class GainMode;
+
+#define DYNAMIC_VALUE_TAG "dynamic" // special value for "channel_masks", "sampling_rates" and
+                                    // "formats" in outputs descriptors indicating that supported
+                                    // values should be queried after opening the output.
+
+template <typename T>
+static void collectionFromString(const std::string &str, Vector<T> &collection)
+{
+    char *literal = strdup(str.c_str());
+    for (const char *cstr = strtok(literal, "|"); cstr != NULL; cstr = strtok(NULL, "|")) {
+        T value;
+        if (utilities::convertTo<std::string, T>(cstr, value)) {
+            collection.add(value);
+        }
+    }
+    free(literal);
+}
+
+template <typename T, typename SupportedType>
+class TypeConverter
+{
+public:
+    static bool toString(const T &value, std::string &str);
+
+    static bool fromString(const std::string &str, T &result);
+
+    static void collectionFromString(const std::string &str, Vector<T> &collection);
+
+    static uint32_t maskFromString(const std::string &str);
+
+protected:
+    struct Table {
+        const char *literal;
+        T value;
+    };
+
+    static const Table mTable[];
+    static const size_t mSize;
+};
+
+typedef TypeConverter<audio_devices_t, Devices> DeviceConverter;
+typedef TypeConverter<audio_output_flags_t, OutputFlags> OutputFlagConverter;
+typedef TypeConverter<audio_input_flags_t, InputFlags> InputFlagConverter;
+typedef TypeConverter<audio_format_t, Formats> FormatConverter;
+typedef TypeConverter<audio_channel_mask_t, OutputChannel> OutputChannelConverter;
+typedef TypeConverter<audio_channel_mask_t, InputChannel> InputChannelConverter;
+typedef TypeConverter<audio_channel_mask_t, ChannelIndex> ChannelIndexConverter;
+typedef TypeConverter<audio_gain_mode_t, GainMode> GainModeConverter;
+
+static Vector<uint32_t> samplingRatesFromString(const std::string &samplingRates)
+{
+    Vector<uint32_t> samplingRateCollection;
+    // by convention, "0' in the first entry in mSamplingRates indicates the supported sampling
+    // rates should be read from the output stream after it is opened for the first time
+    if (samplingRates == DYNAMIC_VALUE_TAG) {
+        samplingRateCollection.add(0);
+    } else {
+        collectionFromString<uint32_t>(samplingRates, samplingRateCollection);
+    }
+    return samplingRateCollection;
+}
+
+static Vector<audio_format_t> formatsFromString(const std::string &formats)
+{
+    Vector<audio_format_t> formatCollection;
+    // by convention, "0' in the first entry in mFormats indicates the supported formats
+    // should be read from the output stream after it is opened for the first time
+    if (formats == DYNAMIC_VALUE_TAG) {
+        formatCollection.add(AUDIO_FORMAT_DEFAULT);
+    } else {
+        FormatConverter::collectionFromString(formats, formatCollection);
+    }
+    return formatCollection;
+}
+
+static Vector<audio_channel_mask_t> inputChannelMasksFromString(const std::string &inChannels)
+{
+    Vector <audio_channel_mask_t> inputChannelMaskCollection;
+    if (inChannels == DYNAMIC_VALUE_TAG) {
+        inputChannelMaskCollection.add(0);
+    } else {
+        InputChannelConverter::collectionFromString(inChannels, inputChannelMaskCollection);
+        ChannelIndexConverter::collectionFromString(inChannels, inputChannelMaskCollection);
+    }
+    return inputChannelMaskCollection;
+}
+
+static Vector<audio_channel_mask_t> outputChannelMasksFromString(const std::string &outChannels)
+{
+    Vector <audio_channel_mask_t> outputChannelMaskCollection;
+    // by convention, "0' in the first entry in mChannelMasks indicates the supported channel
+    // masks should be read from the output stream after it is opened for the first time
+    if (outChannels == DYNAMIC_VALUE_TAG) {
+        outputChannelMaskCollection.add(0);
+    } else {
+        OutputChannelConverter::collectionFromString(outChannels, outputChannelMaskCollection);
+        ChannelIndexConverter::collectionFromString(outChannels, outputChannelMaskCollection);
+    }
+    return outputChannelMaskCollection;
+}
+
+}; // namespace android
+
diff --git a/services/audiopolicy/common/managerdefinitions/include/audio_policy_conf.h b/services/audiopolicy/common/managerdefinitions/include/audio_policy_conf.h
index a393e3b..aac9e4d 100644
--- a/services/audiopolicy/common/managerdefinitions/include/audio_policy_conf.h
+++ b/services/audiopolicy/common/managerdefinitions/include/audio_policy_conf.h
@@ -47,10 +47,6 @@
 #define DEVICES_TAG "devices"
 #define FLAGS_TAG "flags"
 
-#define DYNAMIC_VALUE_TAG "dynamic" // special value for "channel_masks", "sampling_rates" and
-                                    // "formats" in outputs descriptors indicating that supported
-                                    // values should be queried after opening the output.
-
 #define APM_DEVICES_TAG "devices"
 #define APM_DEVICE_TYPE "type"
 #define APM_DEVICE_ADDRESS "address"
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
index 626fdae..362c645 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
@@ -192,7 +192,7 @@
 audio_devices_t AudioInputCollection::getSupportedDevices(audio_io_handle_t handle) const
 {
     sp<AudioInputDescriptor> inputDesc = valueFor(handle);
-    audio_devices_t devices = inputDesc->mProfile->mSupportedDevices.types();
+    audio_devices_t devices = inputDesc->mProfile->getSupportedDevicesType();
     return devices;
 }
 
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 17f2b92..223fe80 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -228,7 +228,7 @@
     mOutput1(0), mOutput2(0), mDirectOpenCount(0), mGlobalRefCount(0)
 {
     if (profile != NULL) {
-        mFlags = (audio_output_flags_t)profile->mFlags;
+        mFlags = (audio_output_flags_t)profile->getFlags();
     }
 }
 
@@ -283,7 +283,7 @@
     if (isDuplicated()) {
         return (audio_devices_t)(mOutput1->supportedDevices() | mOutput2->supportedDevices());
     } else {
-        return mProfile->mSupportedDevices.types() ;
+        return mProfile->getSupportedDevicesType();
     }
 }
 
@@ -529,7 +529,7 @@
 audio_devices_t SwAudioOutputCollection::getSupportedDevices(audio_io_handle_t handle) const
 {
     sp<SwAudioOutputDescriptor> outputDesc = valueFor(handle);
-    audio_devices_t devices = outputDesc->mProfile->mSupportedDevices.types();
+    audio_devices_t devices = outputDesc->mProfile->getSupportedDevicesType();
     return devices;
 }
 
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp
index a06d867..9c28e8f 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp
@@ -19,7 +19,7 @@
 
 #include "AudioPatch.h"
 #include "AudioGain.h"
-#include "ConfigParsingUtils.h"
+#include "TypeConverter.h"
 #include <cutils/log.h>
 #include <utils/String8.h>
 
@@ -53,10 +53,11 @@
     result.append(buffer);
     for (size_t i = 0; i < mPatch.num_sources; i++) {
         if (mPatch.sources[i].type == AUDIO_PORT_TYPE_DEVICE) {
+            std::string device;
+            DeviceConverter::toString(mPatch.sources[i].ext.device.type, device);
             snprintf(buffer, SIZE, "%*s- Device ID %d %s\n", spaces + 2, "",
-                     mPatch.sources[i].id, ConfigParsingUtils::enumToString(sDeviceTypeToEnumTable,
-                                                        ARRAY_SIZE(sDeviceTypeToEnumTable),
-                                                        mPatch.sources[i].ext.device.type));
+                     mPatch.sources[i].id,
+                     device.c_str());
         } else {
             snprintf(buffer, SIZE, "%*s- Mix ID %d I/O handle %d\n", spaces + 2, "",
                      mPatch.sources[i].id, mPatch.sources[i].ext.mix.handle);
@@ -67,10 +68,11 @@
     result.append(buffer);
     for (size_t i = 0; i < mPatch.num_sinks; i++) {
         if (mPatch.sinks[i].type == AUDIO_PORT_TYPE_DEVICE) {
+            std::string device;
+            DeviceConverter::toString(mPatch.sinks[i].ext.device.type, device);
             snprintf(buffer, SIZE, "%*s- Device ID %d %s\n", spaces + 2, "",
-                     mPatch.sinks[i].id, ConfigParsingUtils::enumToString(sDeviceTypeToEnumTable,
-                                                        ARRAY_SIZE(sDeviceTypeToEnumTable),
-                                                        mPatch.sinks[i].ext.device.type));
+                     mPatch.sinks[i].id,
+                     device.c_str());
         } else {
             snprintf(buffer, SIZE, "%*s- Mix ID %d I/O handle %d\n", spaces + 2, "",
                      mPatch.sinks[i].id, mPatch.sinks[i].ext.mix.handle);
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
index 723cb81..1713095 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
@@ -17,27 +17,21 @@
 #define LOG_TAG "APM::AudioPort"
 //#define LOG_NDEBUG 0
 #include <media/AudioResamplerPublic.h>
+#include "TypeConverter.h"
 #include "AudioPort.h"
 #include "HwModule.h"
 #include "AudioGain.h"
-#include "ConfigParsingUtils.h"
-#include "audio_policy_conf.h"
 #include <policy.h>
 
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+#endif
+
 namespace android {
 
 int32_t volatile AudioPort::mNextUniqueId = 1;
 
 // --- AudioPort class implementation
-
-AudioPort::AudioPort(const String8& name, audio_port_type_t type,
-                     audio_port_role_t role) :
-    mName(name), mType(type), mRole(role), mFlags(0)
-{
-    mUseInChannelMask = ((type == AUDIO_PORT_TYPE_DEVICE) && (role == AUDIO_PORT_ROLE_SOURCE)) ||
-                    ((type == AUDIO_PORT_TYPE_MIX) && (role == AUDIO_PORT_ROLE_SINK));
-}
-
 void AudioPort::attach(const sp<HwModule>& module)
 {
     mModule = module;
@@ -61,15 +55,15 @@
     if (mModule == 0) {
         return 0;
     }
-    return mModule->mHalVersion;
+    return mModule->getHalVersion();
 }
 
 const char *AudioPort::getModuleName() const
 {
     if (mModule == 0) {
-        return "";
+        return "invalid module";
     }
-    return mModule->mName;
+    return mModule->getName();
 }
 
 void AudioPort::toAudioPort(struct audio_port *port) const
@@ -100,7 +94,7 @@
     ALOGV("AudioPort::toAudioPort() num gains %zu", mGains.size());
 
     for (i = 0; i < mGains.size() && i < AUDIO_PORT_MAX_GAINS; i++) {
-        port->gains[i] = mGains[i]->mGain;
+        port->gains[i] = mGains[i]->getGain();
     }
     port->num_gains = i;
 }
@@ -159,47 +153,9 @@
     mSamplingRates.clear();
 }
 
-void AudioPort::loadSamplingRates(char *name)
+void AudioPort::setSupportedFormats(const Vector <audio_format_t> &formats)
 {
-    char *str = strtok(name, "|");
-
-    // by convention, "0' in the first entry in mSamplingRates indicates the supported sampling
-    // rates should be read from the output stream after it is opened for the first time
-    if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) {
-        mSamplingRates.add(0);
-        return;
-    }
-
-    while (str != NULL) {
-        uint32_t rate = atoi(str);
-        if (rate != 0) {
-            ALOGV("loadSamplingRates() adding rate %d", rate);
-            mSamplingRates.add(rate);
-        }
-        str = strtok(NULL, "|");
-    }
-}
-
-void AudioPort::loadFormats(char *name)
-{
-    char *str = strtok(name, "|");
-
-    // by convention, "0' in the first entry in mFormats indicates the supported formats
-    // should be read from the output stream after it is opened for the first time
-    if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) {
-        mFormats.add(AUDIO_FORMAT_DEFAULT);
-        return;
-    }
-
-    while (str != NULL) {
-        audio_format_t format = (audio_format_t)ConfigParsingUtils::stringToEnum(sFormatNameToEnumTable,
-                                                             ARRAY_SIZE(sFormatNameToEnumTable),
-                                                             str);
-        if (format != AUDIO_FORMAT_DEFAULT) {
-            mFormats.add(format);
-        }
-        str = strtok(NULL, "|");
-    }
+    mFormats = formats;
     // we sort from worst to best, so that AUDIO_FORMAT_DEFAULT is always the first entry.
     // TODO: compareFormats could be a lambda to convert between pointer-to-format to format:
     // [](const audio_format_t *format1, const audio_format_t *format2) {
@@ -208,140 +164,6 @@
     mFormats.sort(compareFormats);
 }
 
-void AudioPort::loadInChannels(char *name)
-{
-    const char *str = strtok(name, "|");
-
-    ALOGV("loadInChannels() %s", name);
-
-    if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) {
-        mChannelMasks.add(0);
-        return;
-    }
-
-    while (str != NULL) {
-        audio_channel_mask_t channelMask =
-                (audio_channel_mask_t)ConfigParsingUtils::stringToEnum(sInChannelsNameToEnumTable,
-                                                   ARRAY_SIZE(sInChannelsNameToEnumTable),
-                                                   str);
-        if (channelMask == 0) { // if not found, check the channel index table
-            channelMask = (audio_channel_mask_t)
-                      ConfigParsingUtils::stringToEnum(sIndexChannelsNameToEnumTable,
-                              ARRAY_SIZE(sIndexChannelsNameToEnumTable),
-                              str);
-        }
-        if (channelMask != 0) {
-            ALOGV("loadInChannels() adding channelMask %#x", channelMask);
-            mChannelMasks.add(channelMask);
-        }
-        str = strtok(NULL, "|");
-    }
-}
-
-void AudioPort::loadOutChannels(char *name)
-{
-    const char *str = strtok(name, "|");
-
-    ALOGV("loadOutChannels() %s", name);
-
-    // by convention, "0' in the first entry in mChannelMasks indicates the supported channel
-    // masks should be read from the output stream after it is opened for the first time
-    if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) {
-        mChannelMasks.add(0);
-        return;
-    }
-
-    while (str != NULL) {
-        audio_channel_mask_t channelMask =
-                (audio_channel_mask_t)ConfigParsingUtils::stringToEnum(sOutChannelsNameToEnumTable,
-                                                   ARRAY_SIZE(sOutChannelsNameToEnumTable),
-                                                   str);
-        if (channelMask == 0) { // if not found, check the channel index table
-            channelMask = (audio_channel_mask_t)
-                      ConfigParsingUtils::stringToEnum(sIndexChannelsNameToEnumTable,
-                              ARRAY_SIZE(sIndexChannelsNameToEnumTable),
-                              str);
-        }
-        if (channelMask != 0) {
-            mChannelMasks.add(channelMask);
-        }
-        str = strtok(NULL, "|");
-    }
-    return;
-}
-
-audio_gain_mode_t AudioPort::loadGainMode(char *name)
-{
-    const char *str = strtok(name, "|");
-
-    ALOGV("loadGainMode() %s", name);
-    audio_gain_mode_t mode = 0;
-    while (str != NULL) {
-        mode |= (audio_gain_mode_t)ConfigParsingUtils::stringToEnum(sGainModeNameToEnumTable,
-                                                ARRAY_SIZE(sGainModeNameToEnumTable),
-                                                str);
-        str = strtok(NULL, "|");
-    }
-    return mode;
-}
-
-void AudioPort::loadGain(cnode *root, int index)
-{
-    cnode *node = root->first_child;
-
-    sp<AudioGain> gain = new AudioGain(index, mUseInChannelMask);
-
-    while (node) {
-        if (strcmp(node->name, GAIN_MODE) == 0) {
-            gain->mGain.mode = loadGainMode((char *)node->value);
-        } else if (strcmp(node->name, GAIN_CHANNELS) == 0) {
-            if (mUseInChannelMask) {
-                gain->mGain.channel_mask =
-                        (audio_channel_mask_t)ConfigParsingUtils::stringToEnum(sInChannelsNameToEnumTable,
-                                                           ARRAY_SIZE(sInChannelsNameToEnumTable),
-                                                           (char *)node->value);
-            } else {
-                gain->mGain.channel_mask =
-                        (audio_channel_mask_t)ConfigParsingUtils::stringToEnum(sOutChannelsNameToEnumTable,
-                                                           ARRAY_SIZE(sOutChannelsNameToEnumTable),
-                                                           (char *)node->value);
-            }
-        } else if (strcmp(node->name, GAIN_MIN_VALUE) == 0) {
-            gain->mGain.min_value = atoi((char *)node->value);
-        } else if (strcmp(node->name, GAIN_MAX_VALUE) == 0) {
-            gain->mGain.max_value = atoi((char *)node->value);
-        } else if (strcmp(node->name, GAIN_DEFAULT_VALUE) == 0) {
-            gain->mGain.default_value = atoi((char *)node->value);
-        } else if (strcmp(node->name, GAIN_STEP_VALUE) == 0) {
-            gain->mGain.step_value = atoi((char *)node->value);
-        } else if (strcmp(node->name, GAIN_MIN_RAMP_MS) == 0) {
-            gain->mGain.min_ramp_ms = atoi((char *)node->value);
-        } else if (strcmp(node->name, GAIN_MAX_RAMP_MS) == 0) {
-            gain->mGain.max_ramp_ms = atoi((char *)node->value);
-        }
-        node = node->next;
-    }
-
-    ALOGV("loadGain() adding new gain mode %08x channel mask %08x min mB %d max mB %d",
-          gain->mGain.mode, gain->mGain.channel_mask, gain->mGain.min_value, gain->mGain.max_value);
-
-    if (gain->mGain.mode == 0) {
-        return;
-    }
-    mGains.add(gain);
-}
-
-void AudioPort::loadGains(cnode *root)
-{
-    cnode *node = root->first_child;
-    int index = 0;
-    while (node) {
-        ALOGV("loadGains() loading gain %s", node->name);
-        loadGain(node, index++);
-        node = node->next;
-    }
-}
-
 status_t AudioPort::checkExactSamplingRate(uint32_t samplingRate) const
 {
     if (mSamplingRates.isEmpty()) {
@@ -626,7 +448,7 @@
         uint32_t channelCount = UINT_MAX;
         for (size_t i = 0; i < mChannelMasks.size(); i ++) {
             uint32_t cnlCount;
-            if (mUseInChannelMask) {
+            if (useInputChannelMask()) {
                 cnlCount = audio_channel_count_from_in_mask(mChannelMasks[i]);
             } else {
                 cnlCount = audio_channel_count_from_out_mask(mChannelMasks[i]);
@@ -649,7 +471,7 @@
     }
     for (size_t i = 0; i < mChannelMasks.size(); i ++) {
         uint32_t cnlCount;
-        if (mUseInChannelMask) {
+        if (useInputChannelMask()) {
             cnlCount = audio_channel_count_from_in_mask(mChannelMasks[i]);
         } else {
             cnlCount = audio_channel_count_from_out_mask(mChannelMasks[i]);
@@ -787,17 +609,15 @@
         snprintf(buffer, SIZE, "%*s- formats: ", spaces, "");
         result.append(buffer);
         for (size_t i = 0; i < mFormats.size(); i++) {
-            const char *formatStr = ConfigParsingUtils::enumToString(sFormatNameToEnumTable,
-                                                 ARRAY_SIZE(sFormatNameToEnumTable),
-                                                 mFormats[i]);
-            const bool isEmptyStr = formatStr[0] == 0;
-            if (i == 0 && isEmptyStr) {
+            std::string formatLiteral;
+            bool success = FormatConverter::toString(mFormats[i], formatLiteral);
+            if (i == 0 && !success) {
                 snprintf(buffer, SIZE, "Dynamic");
             } else {
-                if (isEmptyStr) {
+                if (!success) {
                     snprintf(buffer, SIZE, "%#x", mFormats[i]);
                 } else {
-                    snprintf(buffer, SIZE, "%s", formatStr);
+                    snprintf(buffer, SIZE, "%s", formatLiteral.c_str());
                 }
             }
             result.append(buffer);
diff --git a/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp b/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp
index 89ef045..786c4e8 100644
--- a/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp
@@ -18,139 +18,257 @@
 //#define LOG_NDEBUG 0
 
 #include "ConfigParsingUtils.h"
+#include <convert/convert.h>
 #include "AudioGain.h"
+#include "IOProfile.h"
+#include "TypeConverter.h"
 #include <hardware/audio.h>
 #include <utils/Log.h>
 #include <cutils/misc.h>
 
 namespace android {
 
-//static
-uint32_t ConfigParsingUtils::stringToEnum(const struct StringToEnum *table,
-                                              size_t size,
-                                              const char *name)
-{
-    for (size_t i = 0; i < size; i++) {
-        if (strcmp(table[i].name, name) == 0) {
-            ALOGV("stringToEnum() found %s", table[i].name);
-            return table[i].value;
-        }
-    }
-    return 0;
-}
-
-//static
-const char *ConfigParsingUtils::enumToString(const struct StringToEnum *table,
-                                              size_t size,
-                                              uint32_t value)
-{
-    for (size_t i = 0; i < size; i++) {
-        if (table[i].value == value) {
-            return table[i].name;
-        }
-    }
-    return "";
-}
-
-//static
-bool ConfigParsingUtils::stringToBool(const char *value)
-{
-    return ((strcasecmp("true", value) == 0) || (strcmp("1", value) == 0));
-}
-
-
 // --- audio_policy.conf file parsing
 //static
-uint32_t ConfigParsingUtils::parseOutputFlagNames(char *name)
+uint32_t ConfigParsingUtils::parseOutputFlagNames(const char *name)
 {
-    uint32_t flag = 0;
-
-    // it is OK to cast name to non const here as we are not going to use it after
-    // strtok() modifies it
-    char *flagName = strtok(name, "|");
-    while (flagName != NULL) {
-        if (strlen(flagName) != 0) {
-            flag |= ConfigParsingUtils::stringToEnum(sOutputFlagNameToEnumTable,
-                               ARRAY_SIZE(sOutputFlagNameToEnumTable),
-                               flagName);
-        }
-        flagName = strtok(NULL, "|");
-    }
+    uint32_t flag = OutputFlagConverter::maskFromString(name);
     //force direct flag if offload flag is set: offloading implies a direct output stream
     // and all common behaviors are driven by checking only the direct flag
     // this should normally be set appropriately in the policy configuration file
     if ((flag & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
         flag |= AUDIO_OUTPUT_FLAG_DIRECT;
     }
-
     return flag;
 }
 
 //static
-uint32_t ConfigParsingUtils::parseInputFlagNames(char *name)
+void ConfigParsingUtils::loadAudioPortGain(cnode *root, AudioPort &audioPort, int index)
 {
-    uint32_t flag = 0;
+    cnode *node = root->first_child;
 
-    // it is OK to cast name to non const here as we are not going to use it after
-    // strtok() modifies it
-    char *flagName = strtok(name, "|");
-    while (flagName != NULL) {
-        if (strlen(flagName) != 0) {
-            flag |= stringToEnum(sInputFlagNameToEnumTable,
-                               ARRAY_SIZE(sInputFlagNameToEnumTable),
-                               flagName);
+    sp<AudioGain> gain = new AudioGain(index, audioPort.useInputChannelMask());
+
+    while (node) {
+        if (strcmp(node->name, GAIN_MODE) == 0) {
+            gain->setMode(GainModeConverter::maskFromString(node->value));
+        } else if (strcmp(node->name, GAIN_CHANNELS) == 0) {
+            audio_channel_mask_t mask;
+            if (audioPort.useInputChannelMask()) {
+                if (InputChannelConverter::fromString(node->value, mask)) {
+                    gain->setChannelMask(mask);
+                }
+            } else {
+                if (OutputChannelConverter::fromString(node->value, mask)) {
+                    gain->setChannelMask(mask);
+                }
+            }
+        } else if (strcmp(node->name, GAIN_MIN_VALUE) == 0) {
+            gain->setMinValueInMb(atoi(node->value));
+        } else if (strcmp(node->name, GAIN_MAX_VALUE) == 0) {
+            gain->setMaxValueInMb(atoi(node->value));
+        } else if (strcmp(node->name, GAIN_DEFAULT_VALUE) == 0) {
+            gain->setDefaultValueInMb(atoi(node->value));
+        } else if (strcmp(node->name, GAIN_STEP_VALUE) == 0) {
+            gain->setStepValueInMb(atoi(node->value));
+        } else if (strcmp(node->name, GAIN_MIN_RAMP_MS) == 0) {
+            gain->setMinRampInMs(atoi(node->value));
+        } else if (strcmp(node->name, GAIN_MAX_RAMP_MS) == 0) {
+            gain->setMaxRampInMs(atoi(node->value));
         }
-        flagName = strtok(NULL, "|");
+        node = node->next;
     }
-    return flag;
+
+    ALOGV("loadGain() adding new gain mode %08x channel mask %08x min mB %d max mB %d",
+          gain->getMode(), gain->getChannelMask(), gain->getMinValueInMb(),
+          gain->getMaxValueInMb());
+
+    if (gain->getMode() == 0) {
+        return;
+    }
+    audioPort.mGains.add(gain);
 }
 
-//static
-audio_devices_t ConfigParsingUtils::parseDeviceNames(char *name)
+void ConfigParsingUtils::loadAudioPortGains(cnode *root, AudioPort &audioPort)
 {
-    uint32_t device = 0;
-
-    char *devName = strtok(name, "|");
-    while (devName != NULL) {
-        if (strlen(devName) != 0) {
-            device |= stringToEnum(sDeviceTypeToEnumTable,
-                                 ARRAY_SIZE(sDeviceTypeToEnumTable),
-                                 devName);
-         }
-        devName = strtok(NULL, "|");
-     }
-    return device;
+    cnode *node = root->first_child;
+    int index = 0;
+    while (node) {
+        ALOGV("loadGains() loading gain %s", node->name);
+        loadAudioPortGain(node, audioPort, index++);
+        node = node->next;
+    }
 }
 
 //static
-void ConfigParsingUtils::loadHwModule(cnode *root, HwModuleCollection &hwModules,
-                                      DeviceVector &availableInputDevices,
-                                      DeviceVector &availableOutputDevices,
-                                      sp<DeviceDescriptor> &defaultOutputDevices,
-                                      bool &isSpeakerDrcEnable)
+void ConfigParsingUtils::loadDeviceDescriptorGains(cnode *root, sp<DeviceDescriptor> &deviceDesc)
+{
+    loadAudioPortGains(root, *deviceDesc);
+    if (deviceDesc->mGains.size() > 0) {
+        deviceDesc->mGains[0]->getDefaultConfig(&deviceDesc->mGain);
+    }
+}
+
+//static
+status_t ConfigParsingUtils::loadHwModuleDevice(cnode *root, DeviceVector &devices)
+{
+    cnode *node = root->first_child;
+
+    audio_devices_t type = AUDIO_DEVICE_NONE;
+    while (node) {
+        if (strcmp(node->name, APM_DEVICE_TYPE) == 0) {
+            DeviceConverter::fromString(node->value, type);
+            break;
+        }
+        node = node->next;
+    }
+    if (type == AUDIO_DEVICE_NONE ||
+            (!audio_is_input_device(type) && !audio_is_output_device(type))) {
+        ALOGW("loadDevice() bad type %08x", type);
+        return BAD_VALUE;
+    }
+    sp<DeviceDescriptor> deviceDesc = new DeviceDescriptor(type, String8(root->name));
+
+    node = root->first_child;
+    while (node) {
+        if (strcmp(node->name, APM_DEVICE_ADDRESS) == 0) {
+            deviceDesc->mAddress = String8((char *)node->value);
+        } else if (strcmp(node->name, CHANNELS_TAG) == 0) {
+            if (audio_is_input_device(type)) {
+                deviceDesc->setSupportedChannelMasks(inputChannelMasksFromString(node->value));
+            } else {
+                deviceDesc->setSupportedChannelMasks(outputChannelMasksFromString(node->value));
+            }
+        } else if (strcmp(node->name, GAINS_TAG) == 0) {
+            loadDeviceDescriptorGains(node, deviceDesc);
+        }
+        node = node->next;
+    }
+
+    ALOGV("loadDevice() adding device tag (literal type) %s type %08x address %s",
+          deviceDesc->getTagName().string(), type, deviceDesc->mAddress.string());
+
+    devices.add(deviceDesc);
+    return NO_ERROR;
+}
+
+//static
+status_t ConfigParsingUtils::loadHwModuleInput(cnode *root, sp<HwModule> &module)
+{
+    cnode *node = root->first_child;
+
+    sp<InputProfile> profile = new InputProfile(String8(root->name));
+
+    while (node) {
+        if (strcmp(node->name, SAMPLING_RATES_TAG) == 0) {
+            profile->setSupportedSamplingRates(samplingRatesFromString(node->value));
+        } else if (strcmp(node->name, FORMATS_TAG) == 0) {
+            profile->setSupportedFormats(formatsFromString(node->value));
+        } else if (strcmp(node->name, CHANNELS_TAG) == 0) {
+            profile->setSupportedChannelMasks(inputChannelMasksFromString(node->value));
+        } else if (strcmp(node->name, DEVICES_TAG) == 0) {
+            DeviceVector devices;
+            loadDevicesFromTag(node->value, devices, module->getDeclaredDevices());
+            profile->setSupportedDevices(devices);
+        } else if (strcmp(node->name, FLAGS_TAG) == 0) {
+            profile->setFlags(InputFlagConverter::maskFromString(node->value));
+        } else if (strcmp(node->name, GAINS_TAG) == 0) {
+            loadAudioPortGains(node, *profile);
+        }
+        node = node->next;
+    }
+    ALOGW_IF(profile->getSupportedDevices().isEmpty(),
+            "loadInput() invalid supported devices");
+    ALOGW_IF(profile->mChannelMasks.size() == 0,
+            "loadInput() invalid supported channel masks");
+    ALOGW_IF(profile->mSamplingRates.size() == 0,
+            "loadInput() invalid supported sampling rates");
+    ALOGW_IF(profile->mFormats.size() == 0,
+            "loadInput() invalid supported formats");
+    if (!profile->getSupportedDevices().isEmpty() &&
+            (profile->mChannelMasks.size() != 0) &&
+            (profile->mSamplingRates.size() != 0) &&
+            (profile->mFormats.size() != 0)) {
+
+        ALOGV("loadInput() adding input Supported Devices %04x",
+              profile->getSupportedDevices().types());
+        return module->addInputProfile(profile);
+    } else {
+        return BAD_VALUE;
+    }
+}
+
+//static
+status_t ConfigParsingUtils::loadHwModuleOutput(cnode *root, sp<HwModule> &module)
+{
+    cnode *node = root->first_child;
+
+    sp<OutputProfile> profile = new OutputProfile(String8(root->name));
+
+    while (node) {
+        if (strcmp(node->name, SAMPLING_RATES_TAG) == 0) {
+            profile->setSupportedSamplingRates(samplingRatesFromString(node->value));
+        } else if (strcmp(node->name, FORMATS_TAG) == 0) {
+            profile->setSupportedFormats(formatsFromString(node->value));
+        } else if (strcmp(node->name, CHANNELS_TAG) == 0) {
+            profile->setSupportedChannelMasks(outputChannelMasksFromString(node->value));
+        } else if (strcmp(node->name, DEVICES_TAG) == 0) {
+            DeviceVector devices;
+            loadDevicesFromTag(node->value, devices, module->getDeclaredDevices());
+            profile->setSupportedDevices(devices);
+        } else if (strcmp(node->name, FLAGS_TAG) == 0) {
+            profile->setFlags(ConfigParsingUtils::parseOutputFlagNames(node->value));
+        } else if (strcmp(node->name, GAINS_TAG) == 0) {
+            loadAudioPortGains(node, *profile);
+        }
+        node = node->next;
+    }
+    ALOGW_IF(profile->getSupportedDevices().isEmpty(),
+            "loadOutput() invalid supported devices");
+    ALOGW_IF(profile->mChannelMasks.size() == 0,
+            "loadOutput() invalid supported channel masks");
+    ALOGW_IF(profile->mSamplingRates.size() == 0,
+            "loadOutput() invalid supported sampling rates");
+    ALOGW_IF(profile->mFormats.size() == 0,
+            "loadOutput() invalid supported formats");
+    if (!profile->getSupportedDevices().isEmpty() &&
+            (profile->mChannelMasks.size() != 0) &&
+            (profile->mSamplingRates.size() != 0) &&
+            (profile->mFormats.size() != 0)) {
+
+        ALOGV("loadOutput() adding output Supported Devices %04x, mFlags %04x",
+              profile->getSupportedDevices().types(), profile->getFlags());
+        return module->addOutputProfile(profile);
+    } else {
+        return BAD_VALUE;
+    }
+}
+
+//static
+status_t ConfigParsingUtils::loadHwModule(cnode *root, sp<HwModule> &module,
+                                          AudioPolicyConfig &config)
 {
     status_t status = NAME_NOT_FOUND;
-    cnode *node;
-    sp<HwModule> module = new HwModule(root->name);
-
-    node = config_find(root, DEVICES_TAG);
+    cnode *node = config_find(root, DEVICES_TAG);
     if (node != NULL) {
         node = node->first_child;
+        DeviceVector devices;
         while (node) {
             ALOGV("loadHwModule() loading device %s", node->name);
-            status_t tmpStatus = module->loadDevice(node);
+            status_t tmpStatus = loadHwModuleDevice(node, devices);
             if (status == NAME_NOT_FOUND || status == NO_ERROR) {
                 status = tmpStatus;
             }
             node = node->next;
         }
+        module->setDeclaredDevices(devices);
     }
     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);
+            status_t tmpStatus = loadHwModuleOutput(node, module);
             if (status == NAME_NOT_FOUND || status == NO_ERROR) {
                 status = tmpStatus;
             }
@@ -162,27 +280,20 @@
         node = node->first_child;
         while (node) {
             ALOGV("loadHwModule() loading input %s", node->name);
-            status_t tmpStatus = module->loadInput(node);
+            status_t tmpStatus = loadHwModuleInput(node, module);
             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);
-    }
+    loadModuleGlobalConfig(root, module, config);
+    return status;
 }
 
 //static
 void ConfigParsingUtils::loadHwModules(cnode *root, HwModuleCollection &hwModules,
-                                       DeviceVector &availableInputDevices,
-                                       DeviceVector &availableOutputDevices,
-                                       sp<DeviceDescriptor> &defaultOutputDevices,
-                                       bool &isSpeakerDrcEnabled)
+                                       AudioPolicyConfig &config)
 {
     cnode *node = config_find(root, AUDIO_HW_MODULE_TAG);
     if (node == NULL) {
@@ -192,18 +303,42 @@
     node = node->first_child;
     while (node) {
         ALOGV("loadHwModules() loading module %s", node->name);
-        loadHwModule(node, hwModules, availableInputDevices, availableOutputDevices,
-                     defaultOutputDevices, isSpeakerDrcEnabled);
+        sp<HwModule> module = new HwModule(node->name);
+        if (loadHwModule(node, module, config) == NO_ERROR) {
+            hwModules.add(module);
+        }
         node = node->next;
     }
 }
 
 //static
-void ConfigParsingUtils::loadGlobalConfig(cnode *root, const sp<HwModule>& module,
-                                          DeviceVector &availableInputDevices,
-                                          DeviceVector &availableOutputDevices,
-                                          sp<DeviceDescriptor> &defaultOutputDevice,
-                                          bool &speakerDrcEnabled)
+void ConfigParsingUtils::loadDevicesFromTag(const char *tag, DeviceVector &devices,
+                                            const DeviceVector &declaredDevices)
+{
+    char *tagLiteral = strndup(tag, strlen(tag));
+    char *devTag = strtok(tagLiteral, "|");
+    while (devTag != NULL) {
+        if (strlen(devTag) != 0) {
+            audio_devices_t type;
+            if (DeviceConverter::fromString(devTag, type)) {
+                sp<DeviceDescriptor> dev = new DeviceDescriptor(type);
+                devices.add(dev);
+            } else {
+                sp<DeviceDescriptor> deviceDesc =
+                        declaredDevices.getDeviceFromTagName(String8(devTag));
+                if (deviceDesc != 0) {
+                    devices.add(deviceDesc);
+                }
+            }
+        }
+        devTag = strtok(NULL, "|");
+    }
+    free(tagLiteral);
+}
+
+//static
+void ConfigParsingUtils::loadModuleGlobalConfig(cnode *root, const sp<HwModule> &module,
+                                                AudioPolicyConfig &config)
 {
     cnode *node = config_find(root, GLOBAL_CONFIG_TAG);
 
@@ -212,52 +347,68 @@
     }
     DeviceVector declaredDevices;
     if (module != NULL) {
-        declaredDevices = module->mDeclaredDevices;
+        declaredDevices = module->getDeclaredDevices();
     }
 
     node = node->first_child;
     while (node) {
         if (strcmp(ATTACHED_OUTPUT_DEVICES_TAG, node->name) == 0) {
-            availableOutputDevices.loadDevicesFromTag((char *)node->value,
-                                                        declaredDevices);
+            DeviceVector availableOutputDevices;
+            loadDevicesFromTag(node->value, availableOutputDevices, declaredDevices);
             ALOGV("loadGlobalConfig() Attached Output Devices %08x",
                   availableOutputDevices.types());
+            config.addAvailableOutputDevices(availableOutputDevices);
         } else if (strcmp(DEFAULT_OUTPUT_DEVICE_TAG, node->name) == 0) {
-            audio_devices_t device = (audio_devices_t)stringToEnum(
-                    sDeviceTypeToEnumTable,
-                    ARRAY_SIZE(sDeviceTypeToEnumTable),
-                    (char *)node->value);
+            audio_devices_t device = AUDIO_DEVICE_NONE;
+            DeviceConverter::fromString(node->value, device);
             if (device != AUDIO_DEVICE_NONE) {
-                defaultOutputDevice = new DeviceDescriptor(device);
+                sp<DeviceDescriptor> defaultOutputDevice = new DeviceDescriptor(device);
+                config.setDefaultOutputDevice(defaultOutputDevice);
+                ALOGV("loadGlobalConfig() mDefaultOutputDevice %08x", defaultOutputDevice->type());
             } else {
                 ALOGW("loadGlobalConfig() default device not specified");
             }
-            ALOGV("loadGlobalConfig() mDefaultOutputDevice %08x", defaultOutputDevice->type());
         } else if (strcmp(ATTACHED_INPUT_DEVICES_TAG, node->name) == 0) {
-            availableInputDevices.loadDevicesFromTag((char *)node->value,
-                                                       declaredDevices);
+            DeviceVector availableInputDevices;
+            loadDevicesFromTag(node->value, availableInputDevices, 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);
+            config.addAvailableInputDevices(availableInputDevices);
         } 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);
+            module->setHalVersion(HARDWARE_DEVICE_API_VERSION(major, minor));
             ALOGV("loadGlobalConfig() mHalVersion = %04x major %u minor %u",
-                  module->mHalVersion, major, minor);
+                  module->getHalVersion(), major, minor);
         }
         node = node->next;
     }
 }
 
 //static
-status_t ConfigParsingUtils::loadAudioPolicyConfig(const char *path,
-                                                   HwModuleCollection &hwModules,
-                                                   DeviceVector &availableInputDevices,
-                                                   DeviceVector &availableOutputDevices,
-                                                   sp<DeviceDescriptor> &defaultOutputDevices,
-                                                   bool &isSpeakerDrcEnabled)
+void ConfigParsingUtils::loadGlobalConfig(cnode *root, AudioPolicyConfig &config,
+                                          const sp<HwModule>& primaryModule)
+{
+    cnode *node = config_find(root, GLOBAL_CONFIG_TAG);
+
+    if (node == NULL) {
+        return;
+    }
+    node = node->first_child;
+    while (node) {
+        if (strcmp(SPEAKER_DRC_ENABLED_TAG, node->name) == 0) {
+            bool speakerDrcEnabled;
+            if (utilities::convertTo<std::string, bool>(node->value, speakerDrcEnabled)) {
+                ALOGV("loadGlobalConfig() mSpeakerDrcEnabled = %d", speakerDrcEnabled);
+                config.setSpeakerDrcEnabled(speakerDrcEnabled);
+            }
+        }
+        node = node->next;
+    }
+    loadModuleGlobalConfig(root, primaryModule, config);
+}
+
+//static
+status_t ConfigParsingUtils::loadConfig(const char *path, AudioPolicyConfig &config)
 {
     cnode *root;
     char *data;
@@ -269,13 +420,14 @@
     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);
+    HwModuleCollection hwModules;
+    loadHwModules(root, hwModules, config);
+
+    // legacy audio_policy.conf files have one global_configuration section, attached to primary.
+    loadGlobalConfig(root, config, hwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY));
+
+    config.setHwModules(hwModules);
+
     config_free(root);
     free(root);
     free(data);
diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
index 1f1fca3..f7ddb35 100644
--- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
@@ -18,19 +18,21 @@
 //#define LOG_NDEBUG 0
 
 #include "DeviceDescriptor.h"
+#include "TypeConverter.h"
 #include "AudioGain.h"
 #include "HwModule.h"
-#include "ConfigParsingUtils.h"
 
 namespace android {
 
-DeviceDescriptor::DeviceDescriptor(audio_devices_t type) :
+DeviceDescriptor::DeviceDescriptor(audio_devices_t type, const String8 &tagName) :
     AudioPort(String8(""), AUDIO_PORT_TYPE_DEVICE,
               audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK :
                                              AUDIO_PORT_ROLE_SOURCE),
-    mTag(""), mAddress(""), mDeviceType(type), mId(0)
+    mAddress(""), mTagName(tagName), mDeviceType(type), mId(0)
 {
-
+    if (type == AUDIO_DEVICE_IN_REMOTE_SUBMIX || type == AUDIO_DEVICE_OUT_REMOTE_SUBMIX ) {
+        mAddress = String8("0");
+    }
 }
 
 audio_port_handle_t DeviceDescriptor::getId() const
@@ -59,14 +61,6 @@
                 mChannelMask == other->mChannelMask);
 }
 
-void DeviceDescriptor::loadGains(cnode *root)
-{
-    AudioPort::loadGains(root);
-    if (mGains.size() > 0) {
-        mGains[0]->getDefaultConfig(&mGain);
-    }
-}
-
 void DeviceVector::refreshTypes()
 {
     mDeviceTypes = AUDIO_DEVICE_NONE;
@@ -86,6 +80,16 @@
     return -1;
 }
 
+void DeviceVector::add(const DeviceVector &devices)
+{
+    for (size_t i = 0; i < devices.size(); i++) {
+        sp<DeviceDescriptor> device = devices.itemAt(i);
+        if (indexOf(device) < 0 && SortedVector::add(device) >= 0) {
+            refreshTypes();
+        }
+    }
+}
+
 ssize_t DeviceVector::add(const sp<DeviceDescriptor>& item)
 {
     ssize_t ret = indexOf(item);
@@ -129,49 +133,6 @@
     return devices;
 }
 
-void DeviceVector::loadDevicesFromType(audio_devices_t types)
-{
-    DeviceVector deviceList;
-
-    uint32_t role_bit = AUDIO_DEVICE_BIT_IN & types;
-    types &= ~role_bit;
-
-    while (types) {
-        uint32_t i = 31 - __builtin_clz(types);
-        uint32_t type = 1 << i;
-        types &= ~type;
-        add(new DeviceDescriptor(type | role_bit));
-    }
-}
-
-void DeviceVector::loadDevicesFromTag(char *tag,
-                                       const DeviceVector& declaredDevices)
-{
-    char *devTag = strtok(tag, "|");
-    while (devTag != NULL) {
-        if (strlen(devTag) != 0) {
-            audio_devices_t type = ConfigParsingUtils::stringToEnum(sDeviceTypeToEnumTable,
-                                 ARRAY_SIZE(sDeviceTypeToEnumTable),
-                                 devTag);
-            if (type != AUDIO_DEVICE_NONE) {
-                sp<DeviceDescriptor> dev = new DeviceDescriptor(type);
-                if (type == AUDIO_DEVICE_IN_REMOTE_SUBMIX ||
-                        type == AUDIO_DEVICE_OUT_REMOTE_SUBMIX ) {
-                    dev->mAddress = String8("0");
-                }
-                add(dev);
-            } else {
-                sp<DeviceDescriptor> deviceDesc =
-                        declaredDevices.getDeviceFromTag(String8(devTag));
-                if (deviceDesc != 0) {
-                    add(deviceDesc);
-                }
-            }
-         }
-         devTag = strtok(NULL, "|");
-     }
-}
-
 sp<DeviceDescriptor> DeviceVector::getDevice(audio_devices_t type, String8 address) const
 {
     sp<DeviceDescriptor> device;
@@ -234,11 +195,11 @@
     return devices;
 }
 
-sp<DeviceDescriptor> DeviceVector::getDeviceFromTag(const String8& tag) const
+sp<DeviceDescriptor> DeviceVector::getDeviceFromTagName(const String8 &tagName) const
 {
     sp<DeviceDescriptor> device;
     for (size_t i = 0; i < size(); i++) {
-        if (itemAt(i)->mTag == tag) {
+        if (itemAt(i)->getTagName() == tagName) {
             device = itemAt(i);
             break;
         }
@@ -246,7 +207,6 @@
     return device;
 }
 
-
 status_t DeviceVector::dump(int fd, const String8 &direction) const
 {
     const size_t SIZE = 256;
@@ -320,11 +280,11 @@
         snprintf(buffer, SIZE, "%*s- id: %2d\n", spaces, "", mId);
         result.append(buffer);
     }
-    snprintf(buffer, SIZE, "%*s- type: %-48s\n", spaces, "",
-            ConfigParsingUtils::enumToString(sDeviceTypeToEnumTable,
-                    ARRAY_SIZE(sDeviceTypeToEnumTable),
-                    mDeviceType));
-    result.append(buffer);
+    std::string deviceLiteral;
+    if (DeviceConverter::toString(mDeviceType, deviceLiteral)) {
+        snprintf(buffer, SIZE, "%*s- type: %-48s\n", spaces, "", deviceLiteral.c_str());
+        result.append(buffer);
+    }
     if (mAddress.size() != 0) {
         snprintf(buffer, SIZE, "%*s- address: %-32s\n", spaces, "", mAddress.string());
         result.append(buffer);
@@ -337,11 +297,9 @@
 
 void DeviceDescriptor::log() const
 {
-    ALOGI("Device id:%d type:0x%X:%s, addr:%s",
-          mId,
-          mDeviceType,
-          ConfigParsingUtils::enumToString(
-             sDeviceNameToEnumTable, ARRAY_SIZE(sDeviceNameToEnumTable), mDeviceType),
+    std::string device;
+    DeviceConverter::toString(mDeviceType, device);
+    ALOGI("Device id:%d type:0x%X:%s, addr:%s", mId,  mDeviceType, device.c_str(),
           mAddress.string());
 
     AudioPort::log("  ");
diff --git a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
index 7e2050b..b02eb6a 100644
--- a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
@@ -20,171 +20,32 @@
 #include "HwModule.h"
 #include "IOProfile.h"
 #include "AudioGain.h"
-#include "ConfigParsingUtils.h"
-#include "audio_policy_conf.h"
 #include <hardware/audio.h>
 #include <policy.h>
 
 namespace android {
 
-HwModule::HwModule(const char *name)
-    : mName(strndup(name, AUDIO_HARDWARE_MODULE_ID_MAX_LEN)),
-      mHalVersion(AUDIO_DEVICE_API_VERSION_MIN), mHandle(0)
+HwModule::HwModule(const char *name, uint32_t halVersion)
+    : mName(String8(name)),
+      mHandle(0),
+      mHalVersion(halVersion)
 {
 }
 
 HwModule::~HwModule()
 {
     for (size_t i = 0; i < mOutputProfiles.size(); i++) {
-        mOutputProfiles[i]->mSupportedDevices.clear();
+        mOutputProfiles[i]->clearSupportedDevices();
     }
     for (size_t i = 0; i < mInputProfiles.size(); i++) {
-        mInputProfiles[i]->mSupportedDevices.clear();
+        mInputProfiles[i]->clearSupportedDevices();
     }
-    free((void *)mName);
-}
-
-status_t HwModule::loadInput(cnode *root)
-{
-    cnode *node = root->first_child;
-
-    sp<IOProfile> profile = new IOProfile(String8(root->name), AUDIO_PORT_ROLE_SINK);
-
-    while (node) {
-        if (strcmp(node->name, SAMPLING_RATES_TAG) == 0) {
-            profile->loadSamplingRates((char *)node->value);
-        } else if (strcmp(node->name, FORMATS_TAG) == 0) {
-            profile->loadFormats((char *)node->value);
-        } else if (strcmp(node->name, CHANNELS_TAG) == 0) {
-            profile->loadInChannels((char *)node->value);
-        } else if (strcmp(node->name, DEVICES_TAG) == 0) {
-            profile->mSupportedDevices.loadDevicesFromTag((char *)node->value,
-                                                           mDeclaredDevices);
-        } else if (strcmp(node->name, FLAGS_TAG) == 0) {
-            profile->mFlags = ConfigParsingUtils::parseInputFlagNames((char *)node->value);
-        } else if (strcmp(node->name, GAINS_TAG) == 0) {
-            profile->loadGains(node);
-        }
-        node = node->next;
-    }
-    ALOGW_IF(profile->mSupportedDevices.isEmpty(),
-            "loadInput() invalid supported devices");
-    ALOGW_IF(profile->mChannelMasks.size() == 0,
-            "loadInput() invalid supported channel masks");
-    ALOGW_IF(profile->mSamplingRates.size() == 0,
-            "loadInput() invalid supported sampling rates");
-    ALOGW_IF(profile->mFormats.size() == 0,
-            "loadInput() invalid supported formats");
-    if (!profile->mSupportedDevices.isEmpty() &&
-            (profile->mChannelMasks.size() != 0) &&
-            (profile->mSamplingRates.size() != 0) &&
-            (profile->mFormats.size() != 0)) {
-
-        ALOGV("loadInput() adding input Supported Devices %04x",
-              profile->mSupportedDevices.types());
-
-        profile->attach(this);
-        mInputProfiles.add(profile);
-        return NO_ERROR;
-    } else {
-        return BAD_VALUE;
-    }
-}
-
-status_t HwModule::loadOutput(cnode *root)
-{
-    cnode *node = root->first_child;
-
-    sp<IOProfile> profile = new IOProfile(String8(root->name), AUDIO_PORT_ROLE_SOURCE);
-
-    while (node) {
-        if (strcmp(node->name, SAMPLING_RATES_TAG) == 0) {
-            profile->loadSamplingRates((char *)node->value);
-        } else if (strcmp(node->name, FORMATS_TAG) == 0) {
-            profile->loadFormats((char *)node->value);
-        } else if (strcmp(node->name, CHANNELS_TAG) == 0) {
-            profile->loadOutChannels((char *)node->value);
-        } else if (strcmp(node->name, DEVICES_TAG) == 0) {
-            profile->mSupportedDevices.loadDevicesFromTag((char *)node->value,
-                                                           mDeclaredDevices);
-        } else if (strcmp(node->name, FLAGS_TAG) == 0) {
-            profile->mFlags = ConfigParsingUtils::parseOutputFlagNames((char *)node->value);
-        } else if (strcmp(node->name, GAINS_TAG) == 0) {
-            profile->loadGains(node);
-        }
-        node = node->next;
-    }
-    ALOGW_IF(profile->mSupportedDevices.isEmpty(),
-            "loadOutput() invalid supported devices");
-    ALOGW_IF(profile->mChannelMasks.size() == 0,
-            "loadOutput() invalid supported channel masks");
-    ALOGW_IF(profile->mSamplingRates.size() == 0,
-            "loadOutput() invalid supported sampling rates");
-    ALOGW_IF(profile->mFormats.size() == 0,
-            "loadOutput() invalid supported formats");
-    if (!profile->mSupportedDevices.isEmpty() &&
-            (profile->mChannelMasks.size() != 0) &&
-            (profile->mSamplingRates.size() != 0) &&
-            (profile->mFormats.size() != 0)) {
-
-        ALOGV("loadOutput() adding output Supported Devices %04x, mFlags %04x",
-              profile->mSupportedDevices.types(), profile->mFlags);
-        profile->attach(this);
-        mOutputProfiles.add(profile);
-        return NO_ERROR;
-    } else {
-        return BAD_VALUE;
-    }
-}
-
-status_t HwModule::loadDevice(cnode *root)
-{
-    cnode *node = root->first_child;
-
-    audio_devices_t type = AUDIO_DEVICE_NONE;
-    while (node) {
-        if (strcmp(node->name, APM_DEVICE_TYPE) == 0) {
-            type = ConfigParsingUtils::parseDeviceNames((char *)node->value);
-            break;
-        }
-        node = node->next;
-    }
-    if (type == AUDIO_DEVICE_NONE ||
-            (!audio_is_input_device(type) && !audio_is_output_device(type))) {
-        ALOGW("loadDevice() bad type %08x", type);
-        return BAD_VALUE;
-    }
-    sp<DeviceDescriptor> deviceDesc = new DeviceDescriptor(type);
-    deviceDesc->mTag = String8(root->name);
-
-    node = root->first_child;
-    while (node) {
-        if (strcmp(node->name, APM_DEVICE_ADDRESS) == 0) {
-            deviceDesc->mAddress = String8((char *)node->value);
-        } else if (strcmp(node->name, CHANNELS_TAG) == 0) {
-            if (audio_is_input_device(type)) {
-                deviceDesc->loadInChannels((char *)node->value);
-            } else {
-                deviceDesc->loadOutChannels((char *)node->value);
-            }
-        } else if (strcmp(node->name, GAINS_TAG) == 0) {
-            deviceDesc->loadGains(node);
-        }
-        node = node->next;
-    }
-
-    ALOGV("loadDevice() adding device tag %s type %08x address %s",
-          deviceDesc->mTag.string(), type, deviceDesc->mAddress.string());
-
-    mDeclaredDevices.add(deviceDesc);
-
-    return NO_ERROR;
 }
 
 status_t HwModule::addOutputProfile(String8 name, const audio_config_t *config,
                                                   audio_devices_t device, String8 address)
 {
-    sp<IOProfile> profile = new IOProfile(name, AUDIO_PORT_ROLE_SOURCE);
+    sp<IOProfile> profile = new OutputProfile(name);
 
     profile->mSamplingRates.add(config->sample_rate);
     profile->mChannelMasks.add(config->channel_mask);
@@ -192,18 +53,49 @@
 
     sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device);
     devDesc->mAddress = address;
-    profile->mSupportedDevices.add(devDesc);
+    profile->addSupportedDevice(devDesc);
 
+    return addOutputProfile(profile);
+}
+
+status_t HwModule::addOutputProfile(const sp<IOProfile> &profile)
+{
     profile->attach(this);
     mOutputProfiles.add(profile);
-
     return NO_ERROR;
 }
 
+status_t HwModule::addInputProfile(const sp<IOProfile> &profile)
+{
+    profile->attach(this);
+    mInputProfiles.add(profile);
+    return NO_ERROR;
+}
+
+status_t HwModule::addProfile(const sp<IOProfile> &profile)
+{
+    switch (profile->getRole()) {
+    case AUDIO_PORT_ROLE_SOURCE:
+        return addOutputProfile(profile);
+    case AUDIO_PORT_ROLE_SINK:
+        return addInputProfile(profile);
+    case AUDIO_PORT_ROLE_NONE:
+        return BAD_VALUE;
+    }
+    return BAD_VALUE;
+}
+
+void HwModule::setProfiles(const IOProfileCollection &profiles)
+{
+    for (size_t i = 0; i < profiles.size(); i++) {
+        addProfile(profiles[i]);
+    }
+}
+
 status_t HwModule::removeOutputProfile(String8 name)
 {
     for (size_t i = 0; i < mOutputProfiles.size(); i++) {
-        if (mOutputProfiles[i]->mName == name) {
+        if (mOutputProfiles[i]->getName() == name) {
             mOutputProfiles.removeAt(i);
             break;
         }
@@ -215,7 +107,7 @@
 status_t HwModule::addInputProfile(String8 name, const audio_config_t *config,
                                                   audio_devices_t device, String8 address)
 {
-    sp<IOProfile> profile = new IOProfile(name, AUDIO_PORT_ROLE_SINK);
+    sp<IOProfile> profile = new InputProfile(name);
 
     profile->mSamplingRates.add(config->sample_rate);
     profile->mChannelMasks.add(config->channel_mask);
@@ -223,20 +115,17 @@
 
     sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device);
     devDesc->mAddress = address;
-    profile->mSupportedDevices.add(devDesc);
+    profile->addSupportedDevice(devDesc);
 
     ALOGV("addInputProfile() name %s rate %d mask 0x08", name.string(), config->sample_rate, config->channel_mask);
 
-    profile->attach(this);
-    mInputProfiles.add(profile);
-
-    return NO_ERROR;
+    return addInputProfile(profile);
 }
 
 status_t HwModule::removeInputProfile(String8 name)
 {
     for (size_t i = 0; i < mInputProfiles.size(); i++) {
-        if (mInputProfiles[i]->mName == name) {
+        if (mInputProfiles[i]->getName() == name) {
             mInputProfiles.removeAt(i);
             break;
         }
@@ -252,7 +141,7 @@
     char buffer[SIZE];
     String8 result;
 
-    snprintf(buffer, SIZE, "  - name: %s\n", mName);
+    snprintf(buffer, SIZE, "  - name: %s\n", getName());
     result.append(buffer);
     snprintf(buffer, SIZE, "  - handle: %d\n", mHandle);
     result.append(buffer);
@@ -289,7 +178,7 @@
 
     for (size_t i = 0; i < size(); i++)
     {
-        if (strcmp(itemAt(i)->mName, name) == 0) {
+        if (strcmp(itemAt(i)->getName(), name) == 0) {
             return itemAt(i);
         }
     }
@@ -302,20 +191,19 @@
     sp <HwModule> module;
 
     for (size_t i = 0; i < size(); i++) {
-        if (itemAt(i)->mHandle == 0) {
+        if (itemAt(i)->getHandle() == 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) {
+                if (itemAt(i)->mOutputProfiles[j]->supportDevice(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) {
+                if (itemAt(i)->mInputProfiles[j]->supportDevice(device)) {
                     return itemAt(i);
                 }
             }
@@ -340,19 +228,18 @@
             continue;
         }
         DeviceVector deviceList =
-                hwModule->mDeclaredDevices.getDevicesFromTypeAddr(device, address);
+                hwModule->getDeclaredDevices().getDevicesFromTypeAddr(device, address);
         if (!deviceList.isEmpty()) {
             return deviceList.itemAt(0);
         }
-        deviceList = hwModule->mDeclaredDevices.getDevicesFromType(device);
+        deviceList = hwModule->getDeclaredDevices().getDevicesFromType(device);
         if (!deviceList.isEmpty()) {
             return deviceList.itemAt(0);
         }
     }
 
-    sp<DeviceDescriptor> devDesc =
-            new DeviceDescriptor(device);
-    devDesc->mName = device_name;
+    sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device);
+    devDesc->setName(String8(device_name));
     devDesc->mAddress = address;
     return devDesc;
 }
diff --git a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
index 7b6d51d..d41d239 100644
--- a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
@@ -23,7 +23,7 @@
 
 namespace android {
 
-IOProfile::IOProfile(const String8& name, audio_port_role_t role)
+IOProfile::IOProfile(const String8 &name, audio_port_role_t role)
     : AudioPort(name, AUDIO_PORT_TYPE_MIX, role)
 {
 }
@@ -45,8 +45,10 @@
                                     audio_channel_mask_t *updatedChannelMask,
                                     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;
+    const bool isPlaybackThread =
+            getType() == AUDIO_PORT_TYPE_MIX && getRole() == AUDIO_PORT_ROLE_SOURCE;
+    const bool isRecordThread =
+            getType() == AUDIO_PORT_TYPE_MIX && getRole() == AUDIO_PORT_ROLE_SINK;
     ALOG_ASSERT(isPlaybackThread != isRecordThread);
 
 
@@ -94,14 +96,14 @@
         return false;
     }
 
-    if (isPlaybackThread && (mFlags & flags) != flags) {
+    if (isPlaybackThread && (getFlags() & flags) != flags) {
         return false;
     }
     // The only input flag that is allowed to be different is the fast flag.
     // An existing fast stream is compatible with a normal track request.
     // An existing normal stream is compatible with a fast track request,
     // but the fast request will be denied by AudioFlinger and converted to normal track.
-    if (isRecordThread && ((mFlags ^ flags) &
+    if (isRecordThread && ((getFlags() ^ flags) &
             ~AUDIO_INPUT_FLAG_FAST)) {
         return false;
     }
@@ -126,7 +128,7 @@
 
     AudioPort::dump(fd, 4);
 
-    snprintf(buffer, SIZE, "    - flags: 0x%04x\n", mFlags);
+    snprintf(buffer, SIZE, "    - flags: 0x%04x\n", getFlags());
     result.append(buffer);
     snprintf(buffer, SIZE, "    - devices:\n");
     result.append(buffer);
@@ -158,7 +160,7 @@
     }
 
     ALOGV("    - devices: 0x%04x\n", mSupportedDevices.types());
-    ALOGV("    - flags: 0x%04x\n", mFlags);
+    ALOGV("    - flags: 0x%04x\n", getFlags());
 }
 
 }; // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/StreamDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/StreamDescriptor.cpp
index 4ca27c2..12c7930 100644
--- a/services/audiopolicy/common/managerdefinitions/src/StreamDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/StreamDescriptor.cpp
@@ -71,7 +71,7 @@
     mIndexMax = volIndexMax;
 }
 
-void StreamDescriptor::setVolumeCurvePoint(Volume::device_category deviceCategory,
+void StreamDescriptor::setVolumeCurvePoint(device_category deviceCategory,
                                            const VolumeCurvePoint *point)
 {
     mVolumeCurve[deviceCategory] = point;
@@ -121,14 +121,14 @@
 }
 
 void StreamDescriptorCollection::setVolumeCurvePoint(audio_stream_type_t stream,
-                                                     Volume::device_category deviceCategory,
+                                                     device_category deviceCategory,
                                                      const VolumeCurvePoint *point)
 {
     editValueAt(stream).setVolumeCurvePoint(deviceCategory, point);
 }
 
 const VolumeCurvePoint *StreamDescriptorCollection::getVolumeCurvePoint(audio_stream_type_t stream,
-                                                                        Volume::device_category deviceCategory) const
+                                                                        device_category deviceCategory) const
 {
     return valueAt(stream).getVolumeCurvePoint(deviceCategory);
 }
diff --git a/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp b/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp
new file mode 100644
index 0000000..d66f6bf
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "TypeConverter.h"
+
+namespace android {
+
+#define MAKE_STRING_FROM_ENUM(string) { #string, string }
+
+template <>
+const DeviceConverter::Table DeviceConverter::mTable[] = {
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_EARPIECE),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_SPEAKER),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_SPEAKER_SAFE),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_WIRED_HEADSET),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_WIRED_HEADPHONE),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_SCO),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_ALL_SCO),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_ALL_A2DP),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_AUX_DIGITAL),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_HDMI),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_USB_ACCESSORY),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_USB_DEVICE),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_ALL_USB),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_REMOTE_SUBMIX),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_TELEPHONY_TX),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_LINE),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_HDMI_ARC),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_SPDIF),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_FM),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_AUX_LINE),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_IP),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_AMBIENT),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BUILTIN_MIC),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_ALL_SCO),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_WIRED_HEADSET),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_AUX_DIGITAL),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_HDMI),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_TELEPHONY_RX),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_VOICE_CALL),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BACK_MIC),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_REMOTE_SUBMIX),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_USB_ACCESSORY),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_USB_DEVICE),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_FM_TUNER),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_TV_TUNER),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_LINE),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_SPDIF),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_A2DP),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_LOOPBACK),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_IP),
+};
+
+template<>
+const size_t DeviceConverter::mSize = sizeof(DeviceConverter::mTable) /
+        sizeof(DeviceConverter::mTable[0]);
+
+
+template <>
+const OutputFlagConverter::Table OutputFlagConverter::mTable[] = {
+    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_DIRECT),
+    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_PRIMARY),
+    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_FAST),
+    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_DEEP_BUFFER),
+    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD),
+    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_NON_BLOCKING),
+    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_HW_AV_SYNC),
+    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_TTS),
+    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_RAW),
+    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_SYNC),
+};
+template<>
+const size_t OutputFlagConverter::mSize = sizeof(OutputFlagConverter::mTable) /
+        sizeof(OutputFlagConverter::mTable[0]);
+
+
+template <>
+const InputFlagConverter::Table InputFlagConverter::mTable[] = {
+    MAKE_STRING_FROM_ENUM(AUDIO_INPUT_FLAG_FAST),
+    MAKE_STRING_FROM_ENUM(AUDIO_INPUT_FLAG_HW_HOTWORD),
+    MAKE_STRING_FROM_ENUM(AUDIO_INPUT_FLAG_RAW),
+    MAKE_STRING_FROM_ENUM(AUDIO_INPUT_FLAG_SYNC),
+};
+template<>
+const size_t InputFlagConverter::mSize = sizeof(InputFlagConverter::mTable) /
+        sizeof(InputFlagConverter::mTable[0]);
+
+
+template <>
+const FormatConverter::Table FormatConverter::mTable[] = {
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_PCM_16_BIT),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_PCM_8_BIT),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_PCM_32_BIT),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_PCM_8_24_BIT),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_PCM_FLOAT),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_MP3),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_MAIN),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_LC),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_SSR),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_LTP),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_HE_V1),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_SCALABLE),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ERLC),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_LD),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_HE_V2),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ELD),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_VORBIS),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_HE_AAC_V1),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_HE_AAC_V2),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_OPUS),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AC3),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_E_AC3),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_DTS),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_DTS_HD),
+};
+template<>
+const size_t FormatConverter::mSize = sizeof(FormatConverter::mTable) /
+        sizeof(FormatConverter::mTable[0]);
+
+
+template <>
+const OutputChannelConverter::Table OutputChannelConverter::mTable[] = {
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_MONO),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_STEREO),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_QUAD),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
+};
+template<>
+const size_t OutputChannelConverter::mSize = sizeof(OutputChannelConverter::mTable) /
+        sizeof(OutputChannelConverter::mTable[0]);
+
+
+template <>
+const InputChannelConverter::Table InputChannelConverter::mTable[] = {
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_MONO),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_STEREO),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
+};
+template<>
+const size_t InputChannelConverter::mSize = sizeof(InputChannelConverter::mTable) /
+        sizeof(InputChannelConverter::mTable[0]);
+
+
+template <>
+const ChannelIndexConverter::Table ChannelIndexConverter::mTable[] = {
+    "AUDIO_CHANNEL_INDEX_MASK_1", static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_INDEX_MASK_1),
+    "AUDIO_CHANNEL_INDEX_MASK_2", static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_INDEX_MASK_2),
+    "AUDIO_CHANNEL_INDEX_MASK_3", static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_INDEX_MASK_3),
+    "AUDIO_CHANNEL_INDEX_MASK_4", static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_INDEX_MASK_4),
+    "AUDIO_CHANNEL_INDEX_MASK_5", static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_INDEX_MASK_5),
+    "AUDIO_CHANNEL_INDEX_MASK_6", static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_INDEX_MASK_6),
+    "AUDIO_CHANNEL_INDEX_MASK_7", static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_INDEX_MASK_7),
+    "AUDIO_CHANNEL_INDEX_MASK_8", static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_INDEX_MASK_8),
+};
+template<>
+const size_t ChannelIndexConverter::mSize = sizeof(ChannelIndexConverter::mTable) /
+        sizeof(ChannelIndexConverter::mTable[0]);
+
+
+template <>
+const GainModeConverter::Table GainModeConverter::mTable[] = {
+    MAKE_STRING_FROM_ENUM(AUDIO_GAIN_MODE_JOINT),
+    MAKE_STRING_FROM_ENUM(AUDIO_GAIN_MODE_CHANNELS),
+    MAKE_STRING_FROM_ENUM(AUDIO_GAIN_MODE_RAMP),
+};
+
+template<>
+const size_t GainModeConverter::mSize = sizeof(GainModeConverter::mTable) /
+        sizeof(GainModeConverter::mTable[0]);
+
+
+template <typename T, typename SupportedType>
+bool TypeConverter<T, SupportedType>::toString(const T &value, std::string &str)
+{
+    for (size_t i = 0; i < mSize; i++) {
+        if (mTable[i].value == value) {
+            str = mTable[i].literal;
+            return true;
+        }
+    }
+    return false;
+}
+
+template <typename T, typename SupportedType>
+bool TypeConverter<T, SupportedType>::fromString(const std::string &str, T &result)
+{
+    for (size_t i = 0; i < mSize; i++) {
+        if (strcmp(mTable[i].literal, str.c_str()) == 0) {
+            ALOGV("stringToEnum() found %s", mTable[i].literal);
+            result = mTable[i].value;
+            return true;
+        }
+    }
+    return false;
+}
+
+template <typename T, typename SupportedType>
+void TypeConverter<T, SupportedType>::collectionFromString(const std::string &str,
+                                                           Vector<T> &collection)
+{
+    char *literal = strdup(str.c_str());
+
+    for (const char *cstr = strtok(literal, "|"); cstr != NULL; cstr = strtok(NULL, "|")) {
+        T value;
+        if (fromString(cstr, value)) {
+            collection.add(value);
+        }
+    }
+    free(literal);
+}
+
+template <typename T, typename SupportedType>
+uint32_t TypeConverter<T, SupportedType>::maskFromString(const std::string &str)
+{
+    char *literal = strdup(str.c_str());
+    uint32_t value = 0;
+    for (const char *cstr = strtok(literal, "|"); cstr != NULL; cstr = strtok(NULL, "|")) {
+        T type;
+        if (fromString(cstr, type)) {
+            value |= static_cast<uint32_t>(type);
+        }
+    }
+    free(literal);
+    return value;
+}
+
+template class TypeConverter<audio_devices_t, Devices>;
+template class TypeConverter<audio_output_flags_t, OutputFlags>;
+template class TypeConverter<audio_input_flags_t, InputFlags>;
+template class TypeConverter<audio_format_t, Formats>;
+template class TypeConverter<audio_channel_mask_t, OutputChannel>;
+template class TypeConverter<audio_channel_mask_t, InputChannel>;
+template class TypeConverter<audio_channel_mask_t, ChannelIndex>;
+template class TypeConverter<audio_gain_mode_t, GainMode>;
+
+}; // namespace android
+
diff --git a/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h b/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h
index e73e543..3a3bdbf 100755
--- a/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h
+++ b/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h
@@ -143,7 +143,7 @@
      *
      * @return amplification value in dB matching the UI index for this given device and stream.
      */
-    virtual float volIndexToDb(Volume::device_category deviceCategory, audio_stream_type_t stream,
+    virtual float volIndexToDb(device_category deviceCategory, audio_stream_type_t stream,
                                  int indexInUi) = 0;
 
     /**
diff --git a/services/audiopolicy/engineconfigurable/interface/AudioPolicyPluginInterface.h b/services/audiopolicy/engineconfigurable/interface/AudioPolicyPluginInterface.h
index 74daba5..43d441e 100755
--- a/services/audiopolicy/engineconfigurable/interface/AudioPolicyPluginInterface.h
+++ b/services/audiopolicy/engineconfigurable/interface/AudioPolicyPluginInterface.h
@@ -116,7 +116,7 @@
      * @return true if the strategy were set correclty for this stream, false otherwise.
      */
     virtual bool setVolumeProfileForStream(const audio_stream_type_t &stream,
-                                           Volume::device_category category,
+                                           device_category category,
                                            const VolumeCurvePoints &points) = 0;
 
     /**
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/VolumeProfile.cpp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/VolumeProfile.cpp
index 5c155c8..1469c3f 100755
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/VolumeProfile.cpp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/VolumeProfile.cpp
@@ -36,10 +36,10 @@
       mPolicyPluginInterface(mPolicySubsystem->getPolicyPluginInterface())
 {
     uint32_t categoryKey = context.getItemAsInteger(MappingKeyCategory);
-    if (categoryKey >= Volume::DEVICE_CATEGORY_CNT) {
-        mCategory = Volume::DEVICE_CATEGORY_SPEAKER;
+    if (categoryKey >= DEVICE_CATEGORY_CNT) {
+        mCategory = DEVICE_CATEGORY_SPEAKER;
     } else {
-        mCategory = static_cast<Volume::device_category>(categoryKey);
+        mCategory = static_cast<device_category>(categoryKey);
     }
     mId = static_cast<audio_stream_type_t>(context.getItemAsInteger(MappingKeyIdentifier));
 
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/VolumeProfile.h b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/VolumeProfile.h
index a00ae84..3c2d9bc 100755
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/VolumeProfile.h
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/VolumeProfile.h
@@ -58,7 +58,7 @@
     audio_stream_type_t mId;
 
     size_t mPoints;
-    Volume::device_category mCategory;
+    device_category mCategory;
 
     static const uint32_t gFractional = 8; /**< Beware to align with the structure. */
 };
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.cpp b/services/audiopolicy/engineconfigurable/src/Engine.cpp
index 733cdf6..32341ec 100755
--- a/services/audiopolicy/engineconfigurable/src/Engine.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Engine.cpp
@@ -116,7 +116,7 @@
 }
 
 bool Engine::setVolumeProfileForStream(const audio_stream_type_t &streamType,
-                                       Volume::device_category deviceCategory,
+                                       device_category deviceCategory,
                                        const VolumeCurvePoints &points)
 {
     Stream *stream = getFromCollection<audio_stream_type_t>(streamType);
@@ -199,9 +199,9 @@
     return element->template set<Property>(property) == NO_ERROR;
 }
 
-float Engine::volIndexToDb(Volume::device_category category,
-                             audio_stream_type_t streamType,
-                             int indexInUi)
+float Engine::volIndexToDb(device_category category,
+                           audio_stream_type_t streamType,
+                           int indexInUi)
 {
     Stream *stream = getFromCollection<audio_stream_type_t>(streamType);
     if (stream == NULL) {
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.h b/services/audiopolicy/engineconfigurable/src/Engine.h
index 6fa7a13..79bc8ff 100755
--- a/services/audiopolicy/engineconfigurable/src/Engine.h
+++ b/services/audiopolicy/engineconfigurable/src/Engine.h
@@ -97,9 +97,9 @@
 
         virtual void initializeVolumeCurves(bool /*isSpeakerDrcEnabled*/) {}
 
-        virtual float volIndexToDb(Volume::device_category deviceCategory,
-                                     audio_stream_type_t stream,
-                                     int indexInUi)
+        virtual float volIndexToDb(device_category deviceCategory,
+                                   audio_stream_type_t stream,
+                                   int indexInUi)
         {
             return mPolicyEngine->volIndexToDb(deviceCategory, stream, indexInUi);
         }
@@ -142,7 +142,7 @@
                                                                                            stream);
         }
         virtual bool setVolumeProfileForStream(const audio_stream_type_t &stream,
-                                               Volume::device_category deviceCategory,
+                                               device_category deviceCategory,
                                                const VolumeCurvePoints &points)
         {
             return mPolicyEngine->setVolumeProfileForStream(stream, deviceCategory, points);
@@ -172,7 +172,7 @@
     void setObserver(AudioPolicyManagerObserver *observer);
 
     bool setVolumeProfileForStream(const audio_stream_type_t &stream,
-                                   Volume::device_category deviceCategory,
+                                   device_category deviceCategory,
                                    const VolumeCurvePoints &points);
 
     status_t initCheck();
@@ -183,9 +183,7 @@
     status_t setDeviceConnectionState(audio_devices_t devices, audio_policy_dev_state_t state,
                                       const char *deviceAddress);
 
-    float volIndexToDb(Volume::device_category category,
-                       audio_stream_type_t stream,
-                       int indexInUi);
+    float volIndexToDb(device_category category, audio_stream_type_t stream, int indexInUi);
     status_t initStreamVolume(audio_stream_type_t stream, int indexMin, int indexMax);
 
     StrategyCollection mStrategyCollection; /**< Strategies indexed by their enum id. */
diff --git a/services/audiopolicy/engineconfigurable/src/Stream.cpp b/services/audiopolicy/engineconfigurable/src/Stream.cpp
index bea2c19..418c94c 100755
--- a/services/audiopolicy/engineconfigurable/src/Stream.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Stream.cpp
@@ -62,7 +62,7 @@
     return mApplicableStrategy;
 }
 
-status_t Element<audio_stream_type_t>::setVolumeProfile(Volume::device_category category,
+status_t Element<audio_stream_type_t>::setVolumeProfile(device_category category,
                                                         const VolumeCurvePoints &points)
 {
     ALOGD("%s: adding volume profile for %s for device category %d, points nb =%d", __FUNCTION__,
@@ -91,20 +91,19 @@
     return NO_ERROR;
 }
 
-float Element<audio_stream_type_t>::volIndexToDb(Volume::device_category deviceCategory,
-                                                   int indexInUi)
+float Element<audio_stream_type_t>::volIndexToDb(device_category deviceCategory, int indexInUi)
 {
     VolumeProfileConstIterator it = mVolumeProfiles.find(deviceCategory);
     if (it == mVolumeProfiles.end()) {
         ALOGE("%s: device category %d not found for stream %s", __FUNCTION__, deviceCategory,
               getName().c_str());
-        return 1.0f;
+        return 0.0f;
     }
     const VolumeCurvePoints curve = mVolumeProfiles[deviceCategory];
     if (curve.size() != Volume::VOLCNT) {
         ALOGE("%s: invalid profile for category %d and for stream %s", __FUNCTION__, deviceCategory,
               getName().c_str());
-        return 1.0f;
+        return 0.0f;
     }
 
     // the volume index in the UI is relative to the min and max volume indices for this stream type
@@ -113,7 +112,7 @@
 
     if (mIndexMax - mIndexMin == 0) {
         ALOGE("%s: Invalid volume indexes Min=Max=%d", __FUNCTION__, mIndexMin);
-        return 1.0f;
+        return 0.0f;
     }
     int volIdx = (nbSteps * (indexInUi - mIndexMin)) /
             (mIndexMax - mIndexMin);
@@ -121,7 +120,7 @@
     // find what part of the curve this index volume belongs to, or if it's out of bounds
     int segment = 0;
     if (volIdx < curve[Volume::VOLMIN].mIndex) {         // out of bounds
-        return 0.0f;
+        return VOLUME_MIN_DB;
     } else if (volIdx < curve[Volume::VOLKNEE1].mIndex) {
         segment = 0;
     } else if (volIdx < curve[Volume::VOLKNEE2].mIndex) {
@@ -129,7 +128,7 @@
     } else if (volIdx <= curve[Volume::VOLMAX].mIndex) {
         segment = 2;
     } else {                                                               // out of bounds
-        return 1.0f;
+        return 0.0f;
     }
 
     // linear interpolation in the attenuation table in dB
diff --git a/services/audiopolicy/engineconfigurable/src/Stream.h b/services/audiopolicy/engineconfigurable/src/Stream.h
index 8c39dc6..b103f89 100755
--- a/services/audiopolicy/engineconfigurable/src/Stream.h
+++ b/services/audiopolicy/engineconfigurable/src/Stream.h
@@ -33,7 +33,7 @@
 class Element<audio_stream_type_t>
 {
 private:
-    typedef std::map<Volume::device_category, VolumeCurvePoints> VolumeProfiles;
+    typedef std::map<device_category, VolumeCurvePoints> VolumeProfiles;
     typedef VolumeProfiles::iterator VolumeProfileIterator;
     typedef VolumeProfiles::const_iterator VolumeProfileConstIterator;
 
@@ -79,9 +79,9 @@
     template <typename Property>
     status_t set(Property property);
 
-    status_t setVolumeProfile(Volume::device_category category, const VolumeCurvePoints &points);
+    status_t setVolumeProfile(device_category category, const VolumeCurvePoints &points);
 
-    float volIndexToDb(Volume::device_category deviceCategory, int indexInUi);
+    float volIndexToDb(device_category deviceCategory, int indexInUi);
 
     status_t initVolume(int indexMin, int indexMax);
 
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index 0686414..a66be09 100755
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -63,8 +63,7 @@
     return (mApmObserver != NULL) ?  NO_ERROR : NO_INIT;
 }
 
-float Engine::volIndexToDb(Volume::device_category category, audio_stream_type_t streamType,
-                             int indexInUi)
+float Engine::volIndexToDb(device_category category, audio_stream_type_t streamType, int indexInUi)
 {
     const StreamDescriptor &streamDesc = mApmObserver->getStreamDescriptors().valueAt(streamType);
     return Gains::volIndexToDb(category, streamDesc, indexInUi);
@@ -89,26 +88,26 @@
     StreamDescriptorCollection &streams = mApmObserver->getStreamDescriptors();
 
     for (int i = 0; i < AUDIO_STREAM_CNT; i++) {
-        for (int j = 0; j < Volume::DEVICE_CATEGORY_CNT; j++) {
+        for (int j = 0; j < DEVICE_CATEGORY_CNT; j++) {
             streams.setVolumeCurvePoint(static_cast<audio_stream_type_t>(i),
-                                         static_cast<Volume::device_category>(j),
+                                         static_cast<device_category>(j),
                                          Gains::sVolumeProfiles[i][j]);
         }
     }
 
     // Check availability of DRC on speaker path: if available, override some of the speaker curves
     if (isSpeakerDrcEnabled) {
-        streams.setVolumeCurvePoint(AUDIO_STREAM_SYSTEM, Volume::DEVICE_CATEGORY_SPEAKER,
+        streams.setVolumeCurvePoint(AUDIO_STREAM_SYSTEM, DEVICE_CATEGORY_SPEAKER,
                 Gains::sDefaultSystemVolumeCurveDrc);
-        streams.setVolumeCurvePoint(AUDIO_STREAM_RING, Volume::DEVICE_CATEGORY_SPEAKER,
+        streams.setVolumeCurvePoint(AUDIO_STREAM_RING, DEVICE_CATEGORY_SPEAKER,
                 Gains::sSpeakerSonificationVolumeCurveDrc);
-        streams.setVolumeCurvePoint(AUDIO_STREAM_ALARM, Volume::DEVICE_CATEGORY_SPEAKER,
+        streams.setVolumeCurvePoint(AUDIO_STREAM_ALARM, DEVICE_CATEGORY_SPEAKER,
                 Gains::sSpeakerSonificationVolumeCurveDrc);
-        streams.setVolumeCurvePoint(AUDIO_STREAM_NOTIFICATION, Volume::DEVICE_CATEGORY_SPEAKER,
+        streams.setVolumeCurvePoint(AUDIO_STREAM_NOTIFICATION, DEVICE_CATEGORY_SPEAKER,
                 Gains::sSpeakerSonificationVolumeCurveDrc);
-        streams.setVolumeCurvePoint(AUDIO_STREAM_MUSIC, Volume::DEVICE_CATEGORY_SPEAKER,
+        streams.setVolumeCurvePoint(AUDIO_STREAM_MUSIC, DEVICE_CATEGORY_SPEAKER,
                 Gains::sSpeakerMediaVolumeCurveDrc);
-        streams.setVolumeCurvePoint(AUDIO_STREAM_ACCESSIBILITY, Volume::DEVICE_CATEGORY_SPEAKER,
+        streams.setVolumeCurvePoint(AUDIO_STREAM_ACCESSIBILITY, DEVICE_CATEGORY_SPEAKER,
                 Gains::sSpeakerMediaVolumeCurveDrc);
     }
 }
@@ -135,14 +134,14 @@
     // are we entering or starting a call
     if (!is_state_in_call(oldState) && is_state_in_call(state)) {
         ALOGV("  Entering call in setPhoneState()");
-        for (int j = 0; j < Volume::DEVICE_CATEGORY_CNT; j++) {
-            streams.setVolumeCurvePoint(AUDIO_STREAM_DTMF, static_cast<Volume::device_category>(j),
+        for (int j = 0; j < DEVICE_CATEGORY_CNT; j++) {
+            streams.setVolumeCurvePoint(AUDIO_STREAM_DTMF, static_cast<device_category>(j),
                                          Gains::sVolumeProfiles[AUDIO_STREAM_VOICE_CALL][j]);
         }
     } else if (is_state_in_call(oldState) && !is_state_in_call(state)) {
         ALOGV("  Exiting call in setPhoneState()");
-        for (int j = 0; j < Volume::DEVICE_CATEGORY_CNT; j++) {
-            streams.setVolumeCurvePoint(AUDIO_STREAM_DTMF, static_cast<Volume::device_category>(j),
+        for (int j = 0; j < DEVICE_CATEGORY_CNT; j++) {
+            streams.setVolumeCurvePoint(AUDIO_STREAM_DTMF, static_cast<device_category>(j),
                                          Gains::sVolumeProfiles[AUDIO_STREAM_DTMF][j]);
         }
     }
diff --git a/services/audiopolicy/enginedefault/src/Engine.h b/services/audiopolicy/enginedefault/src/Engine.h
index 56a4748..697f19b 100755
--- a/services/audiopolicy/enginedefault/src/Engine.h
+++ b/services/audiopolicy/enginedefault/src/Engine.h
@@ -101,8 +101,8 @@
         {
             return mPolicyEngine->initializeVolumeCurves(isSpeakerDrcEnabled);
         }
-        virtual float volIndexToDb(Volume::device_category deviceCategory,
-                                     audio_stream_type_t stream,int indexInUi)
+        virtual float volIndexToDb(device_category deviceCategory,
+                                   audio_stream_type_t stream, int indexInUi)
         {
             return mPolicyEngine->volIndexToDb(deviceCategory, stream, indexInUi);
         }
@@ -141,8 +141,7 @@
     audio_devices_t getDeviceForStrategy(routing_strategy strategy) const;
     audio_devices_t getDeviceForInputSource(audio_source_t inputSource) const;
 
-    float volIndexToDb(Volume::device_category category,
-                         audio_stream_type_t stream, int indexInUi);
+    float volIndexToDb(device_category category, audio_stream_type_t stream, int indexInUi);
     status_t initStreamVolume(audio_stream_type_t stream, int indexMin, int indexMax);
     void initializeVolumeCurves(bool isSpeakerDrcEnabled);
 
diff --git a/services/audiopolicy/enginedefault/src/Gains.cpp b/services/audiopolicy/enginedefault/src/Gains.cpp
index d06365c..0aace36 100644
--- a/services/audiopolicy/enginedefault/src/Gains.cpp
+++ b/services/audiopolicy/enginedefault/src/Gains.cpp
@@ -114,7 +114,7 @@
 };
 
 const VolumeCurvePoint *Gains::sVolumeProfiles[AUDIO_STREAM_CNT]
-                                                  [Volume::DEVICE_CATEGORY_CNT] = {
+                                                  [DEVICE_CATEGORY_CNT] = {
     { // AUDIO_STREAM_VOICE_CALL
         Gains::sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_HEADSET
         Gains::sSpeakerVoiceVolumeCurve, // DEVICE_CATEGORY_SPEAKER
@@ -197,7 +197,7 @@
 };
 
 //static
-float Gains::volIndexToDb(Volume::device_category deviceCategory,
+float Gains::volIndexToDb(device_category deviceCategory,
                           const StreamDescriptor& streamDesc,
                           int indexInUi)
 {
@@ -243,7 +243,7 @@
 
 
 //static
-float Gains::volIndexToAmpl(Volume::device_category deviceCategory,
+float Gains::volIndexToAmpl(device_category deviceCategory,
                             const StreamDescriptor& streamDesc,
                             int indexInUi)
 {
diff --git a/services/audiopolicy/enginedefault/src/Gains.h b/services/audiopolicy/enginedefault/src/Gains.h
index 7620b7d..4bd5edd 100644
--- a/services/audiopolicy/enginedefault/src/Gains.h
+++ b/services/audiopolicy/enginedefault/src/Gains.h
@@ -29,11 +29,11 @@
 class Gains
 {
 public :
-    static float volIndexToAmpl(Volume::device_category deviceCategory,
+    static float volIndexToAmpl(device_category deviceCategory,
                                 const StreamDescriptor& streamDesc,
                                 int indexInUi);
 
-    static float volIndexToDb(Volume::device_category deviceCategory,
+    static float volIndexToDb(device_category deviceCategory,
                               const StreamDescriptor& streamDesc,
                               int indexInUi);
 
@@ -58,7 +58,7 @@
     static const VolumeCurvePoint sSilentVolumeCurve[Volume::VOLCNT];
     static const VolumeCurvePoint sFullScaleVolumeCurve[Volume::VOLCNT];
     // default volume curves per stream and device category. See initializeVolumeCurves()
-    static const VolumeCurvePoint *sVolumeProfiles[AUDIO_STREAM_CNT][Volume::DEVICE_CATEGORY_CNT];
+    static const VolumeCurvePoint *sVolumeProfiles[AUDIO_STREAM_CNT][DEVICE_CATEGORY_CNT];
 };
 
 }; // namespace android
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 538addf..4d90546 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -37,8 +37,8 @@
 #include <media/AudioPolicyHelper.h>
 #include <soundtrigger/SoundTrigger.h>
 #include "AudioPolicyManager.h"
-#include "audio_policy_conf.h"
 #include <ConfigParsingUtils.h>
+#include "TypeConverter.h"
 #include <policy.h>
 
 namespace android {
@@ -591,7 +591,7 @@
         sp<AudioInputDescriptor> activeDesc = mInputs.valueFor(activeInput);
         audio_devices_t newDevice = getNewInputDevice(activeInput);
         // Force new input selection if the new device can not be reached via current input
-        if (activeDesc->mProfile->mSupportedDevices.types() & (newDevice & ~AUDIO_DEVICE_BIT_IN)) {
+        if (activeDesc->mProfile->getSupportedDevices().types() & (newDevice & ~AUDIO_DEVICE_BIT_IN)) {
             setInputDevice(activeInput, newDevice);
         } else {
             closeInput(activeInput);
@@ -636,15 +636,15 @@
                 continue;
             }
             // reject profiles not corresponding to a device currently available
-            if ((mAvailableOutputDevices.types() & curProfile->mSupportedDevices.types()) == 0) {
+            if ((mAvailableOutputDevices.types() & curProfile->getSupportedDevicesType()) == 0) {
                 continue;
             }
             // if several profiles are compatible, give priority to one with offload capability
-            if (profile != 0 && ((curProfile->mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0)) {
+            if (profile != 0 && ((curProfile->getFlags() & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0)) {
                 continue;
             }
             profile = curProfile;
-            if ((profile->mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
+            if ((profile->getFlags() & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
                 break;
             }
         }
@@ -881,7 +881,7 @@
         // if the selected profile is offloaded and no offload info was specified,
         // create a default one
         audio_offload_info_t defaultOffloadInfo = AUDIO_INFO_INITIALIZER;
-        if ((profile->mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) && !offloadInfo) {
+        if ((profile->getFlags() & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) && !offloadInfo) {
             flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD);
             defaultOffloadInfo.sample_rate = samplingRate;
             defaultOffloadInfo.channel_mask = channelMask;
@@ -1009,13 +1009,13 @@
                 }
             }
 
-            int commonFlags = popcount(outputDesc->mProfile->mFlags & flags);
+            int commonFlags = popcount(outputDesc->mProfile->getFlags() & flags);
             if (commonFlags > maxCommonFlags) {
                 outputFlags = outputs[i];
                 maxCommonFlags = commonFlags;
                 ALOGV("selectOutput() commonFlags for output %d, %04x", outputs[i], commonFlags);
             }
-            if (outputDesc->mProfile->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY) {
+            if (outputDesc->mProfile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) {
                 outputPrimary = outputs[i];
             }
         }
@@ -2387,7 +2387,7 @@
                 // - source and sink devices are on differnt HW modules OR
                 // - audio HAL version is < 3.0
                 if ((srcDeviceDesc->getModuleHandle() != sinkDeviceDesc->getModuleHandle()) ||
-                        (srcDeviceDesc->mModule->mHalVersion < AUDIO_DEVICE_API_VERSION_3_0)) {
+                        (srcDeviceDesc->mModule->getHalVersion() < AUDIO_DEVICE_API_VERSION_3_0)) {
                     // support only one sink device for now to simplify output selection logic
                     if (patch->num_sinks > 1) {
                         return INVALID_OPERATION;
@@ -2753,7 +2753,7 @@
 
     if (srcDeviceDesc->getAudioPort()->mModule->getHandle() ==
             sinkDeviceDesc->getAudioPort()->mModule->getHandle() &&
-            srcDeviceDesc->getAudioPort()->mModule->mHalVersion >= AUDIO_DEVICE_API_VERSION_3_0 &&
+            srcDeviceDesc->getAudioPort()->mModule->getHalVersion() >= AUDIO_DEVICE_API_VERSION_3_0 &&
             srcDeviceDesc->getAudioPort()->mGains.size() > 0) {
         ALOGV("%s AUDIO_DEVICE_API_VERSION_3_0", __FUNCTION__);
         //   create patch between src device and output device
@@ -2910,16 +2910,14 @@
     mUidCached = getuid();
     mpClientInterface = clientInterface;
 
-    mDefaultOutputDevice = new DeviceDescriptor(AUDIO_DEVICE_OUT_SPEAKER);
-    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();
-        }
+    AudioPolicyConfig config(mHwModules, mAvailableOutputDevices, mAvailableInputDevices,
+                             mDefaultOutputDevice, mSpeakerDrcEnabled);
+
+    if ((ConfigParsingUtils::loadConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE, config) != NO_ERROR) &&
+        (ConfigParsingUtils::loadConfig(AUDIO_POLICY_CONFIG_FILE, config) != NO_ERROR)) {
+
+        ALOGE("could not load audio policy configuration file, setting defaults");
+        config.setDefault();
     }
     // mAvailableOutputDevices and mAvailableInputDevices now contain all attached devices
 
@@ -2930,9 +2928,9 @@
     audio_devices_t outputDeviceTypes = mAvailableOutputDevices.types();
     audio_devices_t inputDeviceTypes = mAvailableInputDevices.types() & ~AUDIO_DEVICE_BIT_IN;
     for (size_t i = 0; i < mHwModules.size(); i++) {
-        mHwModules[i]->mHandle = mpClientInterface->loadHwModule(mHwModules[i]->mName);
+        mHwModules[i]->mHandle = mpClientInterface->loadHwModule(mHwModules[i]->getName());
         if (mHwModules[i]->mHandle == 0) {
-            ALOGW("could not open HW module %s", mHwModules[i]->mName);
+            ALOGW("could not open HW module %s", mHwModules[i]->getName());
             continue;
         }
         // open all output streams needed to access attached devices
@@ -2943,29 +2941,24 @@
         {
             const sp<IOProfile> outProfile = mHwModules[i]->mOutputProfiles[j];
 
-            if (outProfile->mSupportedDevices.isEmpty()) {
-                ALOGW("Output profile contains no device on module %s", mHwModules[i]->mName);
+            if (!outProfile->hasSupportedDevices()) {
+                ALOGW("Output profile contains no device on module %s", mHwModules[i]->getName());
                 continue;
             }
-            if ((outProfile->mFlags & AUDIO_OUTPUT_FLAG_TTS) != 0) {
+            if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_TTS) != 0) {
                 mTtsOutputAvailable = true;
             }
 
-            if ((outProfile->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) {
+            if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_DIRECT) != 0) {
                 continue;
             }
-            audio_devices_t profileType = outProfile->mSupportedDevices.types();
+            audio_devices_t profileType = outProfile->getSupportedDevicesType();
             if ((profileType & mDefaultOutputDevice->type()) != AUDIO_DEVICE_NONE) {
                 profileType = mDefaultOutputDevice->type();
             } else {
-                // chose first device present in mSupportedDevices also part of
+                // chose first device present in profile's SupportedDevices also part of
                 // outputDeviceTypes
-                for (size_t k = 0; k  < outProfile->mSupportedDevices.size(); k++) {
-                    profileType = outProfile->mSupportedDevices[k]->type();
-                    if ((profileType & outputDeviceTypes) != 0) {
-                        break;
-                    }
-                }
+                profileType = outProfile->getSupportedDeviceForType(outputDeviceTypes);
             }
             if ((profileType & outputDeviceTypes) == 0) {
                 continue;
@@ -2990,23 +2983,22 @@
             if (status != NO_ERROR) {
                 ALOGW("Cannot open output stream for device %08x on hw module %s",
                       outputDesc->mDevice,
-                      mHwModules[i]->mName);
+                      mHwModules[i]->getName());
             } else {
                 outputDesc->mSamplingRate = config.sample_rate;
                 outputDesc->mChannelMask = config.channel_mask;
                 outputDesc->mFormat = config.format;
 
-                for (size_t k = 0; k  < outProfile->mSupportedDevices.size(); k++) {
-                    audio_devices_t type = outProfile->mSupportedDevices[k]->type();
-                    ssize_t index =
-                            mAvailableOutputDevices.indexOf(outProfile->mSupportedDevices[k]);
+                const DeviceVector &supportedDevices = outProfile->getSupportedDevices();
+                for (size_t k = 0; k  < supportedDevices.size(); k++) {
+                    ssize_t index = mAvailableOutputDevices.indexOf(supportedDevices[k]);
                     // give a valid ID to an attached device once confirmed it is reachable
                     if (index >= 0 && !mAvailableOutputDevices[index]->isAttached()) {
                         mAvailableOutputDevices[index]->attach(mHwModules[i]);
                     }
                 }
                 if (mPrimaryOutput == 0 &&
-                        outProfile->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY) {
+                        outProfile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) {
                     mPrimaryOutput = outputDesc;
                 }
                 addOutput(output, outputDesc);
@@ -3021,19 +3013,14 @@
         {
             const sp<IOProfile> inProfile = mHwModules[i]->mInputProfiles[j];
 
-            if (inProfile->mSupportedDevices.isEmpty()) {
-                ALOGW("Input profile contains no device on module %s", mHwModules[i]->mName);
+            if (!inProfile->hasSupportedDevices()) {
+                ALOGW("Input profile contains no device on module %s", mHwModules[i]->getName());
                 continue;
             }
-            // chose first device present in mSupportedDevices also part of
+            // chose first device present in profile's SupportedDevices also part of
             // inputDeviceTypes
-            audio_devices_t profileType = AUDIO_DEVICE_NONE;
-            for (size_t k = 0; k  < inProfile->mSupportedDevices.size(); k++) {
-                profileType = inProfile->mSupportedDevices[k]->type();
-                if (profileType & inputDeviceTypes) {
-                    break;
-                }
-            }
+            audio_devices_t profileType = inProfile->getSupportedDeviceForType(inputDeviceTypes);
+
             if ((profileType & inputDeviceTypes) == 0) {
                 continue;
             }
@@ -3064,10 +3051,9 @@
                                                            AUDIO_INPUT_FLAG_NONE);
 
             if (status == NO_ERROR) {
-                for (size_t k = 0; k  < inProfile->mSupportedDevices.size(); k++) {
-                    audio_devices_t type = inProfile->mSupportedDevices[k]->type();
-                    ssize_t index =
-                            mAvailableInputDevices.indexOf(inProfile->mSupportedDevices[k]);
+                const DeviceVector &supportedDevices = inProfile->getSupportedDevices();
+                for (size_t k = 0; k  < supportedDevices.size(); k++) {
+                    ssize_t index =  mAvailableInputDevices.indexOf(supportedDevices[k]);
                     // give a valid ID to an attached device once confirmed it is reachable
                     if (index >= 0) {
                         sp<DeviceDescriptor> devDesc = mAvailableInputDevices[index];
@@ -3081,14 +3067,14 @@
             } else {
                 ALOGW("Cannot open input stream for device %08x on hw module %s",
                       inputDesc->mDevice,
-                      mHwModules[i]->mName);
+                      mHwModules[i]->getName());
             }
         }
     }
     // 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]->type());
+            ALOGW("Output device %08x unreachable", mAvailableOutputDevices[i]->type());
             mAvailableOutputDevices.remove(mAvailableOutputDevices[i]);
             continue;
         }
@@ -3109,7 +3095,7 @@
         i++;
     }
     // make sure default device is reachable
-    if (mAvailableOutputDevices.indexOf(mDefaultOutputDevice) < 0) {
+    if (mDefaultOutputDevice == 0 || mAvailableOutputDevices.indexOf(mDefaultOutputDevice) < 0) {
         ALOGE("Default device %08x is unreachable", mDefaultOutputDevice->type());
     }
 
@@ -3349,7 +3335,7 @@
         const String8 address /*in*/,
         SortedVector<audio_io_handle_t>& outputs /*out*/) {
     sp<DeviceDescriptor> devDesc =
-        desc->mProfile->mSupportedDevices.getDevice(device, address);
+        desc->mProfile->getSupportedDeviceByAddress(device, address);
     if (devDesc != 0) {
         ALOGV("findIoHandlesByAddress(): adding opened output %d on same address %s",
               desc->mIoHandle, address.string());
@@ -3394,9 +3380,9 @@
             for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++)
             {
                 sp<IOProfile> profile = mHwModules[i]->mOutputProfiles[j];
-                if (profile->mSupportedDevices.types() & device) {
+                if (profile->supportDevice(device)) {
                     if (!device_distinguishes_on_address(device) ||
-                            address == profile->mSupportedDevices[0]->mAddress) {
+                            profile->supportDeviceAddress(address)) {
                         profiles.add(profile);
                         ALOGV("checkOutputsForDevice(): adding profile %zu from module %zu", j, i);
                     }
@@ -3474,7 +3460,7 @@
                               reply.string());
                     value = strpbrk((char *)reply.string(), "=");
                     if (value != NULL) {
-                        profile->loadSamplingRates(value + 1);
+                        profile->setSupportedSamplingRates(samplingRatesFromString(value + 1));
                     }
                 }
                 if (profile->mFormats[0] == AUDIO_FORMAT_DEFAULT) {
@@ -3484,7 +3470,7 @@
                               reply.string());
                     value = strpbrk((char *)reply.string(), "=");
                     if (value != NULL) {
-                        profile->loadFormats(value + 1);
+                        profile->setSupportedFormats(formatsFromString(value + 1));
                     }
                 }
                 if (profile->mChannelMasks[0] == 0) {
@@ -3494,7 +3480,7 @@
                               reply.string());
                     value = strpbrk((char *)reply.string(), "=");
                     if (value != NULL) {
-                        profile->loadOutChannels(value + 1);
+                        profile->setSupportedChannelMasks(outputChannelMasksFromString(value + 1));
                     }
                 }
                 if (((profile->mSamplingRates[0] == 0) &&
@@ -3632,7 +3618,7 @@
             for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++)
             {
                 sp<IOProfile> profile = mHwModules[i]->mOutputProfiles[j];
-                if (profile->mSupportedDevices.types() & device) {
+                if (profile->supportDevice(device)) {
                     ALOGV("checkOutputsForDevice(): "
                             "clearing direct output profile %zu on module %zu", j, i);
                     if (profile->mSamplingRates[0] == 0) {
@@ -3671,7 +3657,7 @@
         // first list already open inputs that can be routed to this device
         for (size_t input_index = 0; input_index < mInputs.size(); input_index++) {
             desc = mInputs.valueAt(input_index);
-            if (desc->mProfile->mSupportedDevices.types() & (device & ~AUDIO_DEVICE_BIT_IN)) {
+            if (desc->mProfile->supportDevice(device)) {
                 ALOGV("checkInputsForDevice(): adding opened input %d", mInputs.keyAt(input_index));
                inputs.add(mInputs.keyAt(input_index));
             }
@@ -3690,9 +3676,9 @@
             {
                 sp<IOProfile> profile = mHwModules[module_idx]->mInputProfiles[profile_index];
 
-                if (profile->mSupportedDevices.types() & (device & ~AUDIO_DEVICE_BIT_IN)) {
+                if (profile->supportDevice(device)) {
                     if (!device_distinguishes_on_address(device) ||
-                            address == profile->mSupportedDevices[0]->mAddress) {
+                            profile->supportDeviceAddress(address)) {
                         profiles.add(profile);
                         ALOGV("checkInputsForDevice(): adding profile %zu from module %zu",
                               profile_index, module_idx);
@@ -3763,7 +3749,7 @@
                               reply.string());
                     value = strpbrk((char *)reply.string(), "=");
                     if (value != NULL) {
-                        profile->loadSamplingRates(value + 1);
+                        profile->setSupportedSamplingRates(samplingRatesFromString(value + 1));
                     }
                 }
                 if (profile->mFormats[0] == AUDIO_FORMAT_DEFAULT) {
@@ -3772,7 +3758,7 @@
                     ALOGV("checkInputsForDevice() direct input sup formats %s", reply.string());
                     value = strpbrk((char *)reply.string(), "=");
                     if (value != NULL) {
-                        profile->loadFormats(value + 1);
+                        profile->setSupportedFormats(formatsFromString(value + 1));
                     }
                 }
                 if (profile->mChannelMasks[0] == 0) {
@@ -3782,7 +3768,7 @@
                               reply.string());
                     value = strpbrk((char *)reply.string(), "=");
                     if (value != NULL) {
-                        profile->loadInChannels(value + 1);
+                        profile->setSupportedChannelMasks(inputChannelMasksFromString(value + 1));
                     }
                 }
                 if (((profile->mSamplingRates[0] == 0) && (profile->mSamplingRates.size() < 2)) ||
@@ -3820,8 +3806,7 @@
         // check if one opened input is not needed any more after disconnecting one device
         for (size_t input_index = 0; input_index < mInputs.size(); input_index++) {
             desc = mInputs.valueAt(input_index);
-            if (!(desc->mProfile->mSupportedDevices.types() & mAvailableInputDevices.types() &
-                    ~AUDIO_DEVICE_BIT_IN)) {
+            if (!(desc->mProfile->supportDevice(mAvailableInputDevices.types()))) {
                 ALOGV("checkInputsForDevice(): disconnecting adding input %d",
                       mInputs.keyAt(input_index));
                 inputs.add(mInputs.keyAt(input_index));
@@ -3836,7 +3821,7 @@
                  profile_index < mHwModules[module_index]->mInputProfiles.size();
                  profile_index++) {
                 sp<IOProfile> profile = mHwModules[module_index]->mInputProfiles[profile_index];
-                if (profile->mSupportedDevices.types() & (device & ~AUDIO_DEVICE_BIT_IN)) {
+                if (profile->supportDevice(device)) {
                     ALOGV("checkInputsForDevice(): clearing direct input profile %zu on module %zu",
                           profile_index, module_index);
                     if (profile->mSamplingRates[0] == 0) {
@@ -4953,39 +4938,6 @@
     }
 }
 
-
-
-void AudioPolicyManager::defaultAudioPolicyConfig(void)
-{
-    sp<HwModule> module;
-    sp<IOProfile> profile;
-    sp<DeviceDescriptor> defaultInputDevice =
-                    new DeviceDescriptor(AUDIO_DEVICE_IN_BUILTIN_MIC);
-    mAvailableOutputDevices.add(mDefaultOutputDevice);
-    mAvailableInputDevices.add(defaultInputDevice);
-
-    module = new HwModule("primary");
-
-    profile = new IOProfile(String8("primary"), AUDIO_PORT_ROLE_SOURCE);
-    profile->attach(module);
-    profile->mSamplingRates.add(44100);
-    profile->mFormats.add(AUDIO_FORMAT_PCM_16_BIT);
-    profile->mChannelMasks.add(AUDIO_CHANNEL_OUT_STEREO);
-    profile->mSupportedDevices.add(mDefaultOutputDevice);
-    profile->mFlags = AUDIO_OUTPUT_FLAG_PRIMARY;
-    module->mOutputProfiles.add(profile);
-
-    profile = new IOProfile(String8("primary"), AUDIO_PORT_ROLE_SINK);
-    profile->attach(module);
-    profile->mSamplingRates.add(8000);
-    profile->mFormats.add(AUDIO_FORMAT_PCM_16_BIT);
-    profile->mChannelMasks.add(AUDIO_CHANNEL_IN_MONO);
-    profile->mSupportedDevices.add(defaultInputDevice);
-    module->mInputProfiles.add(profile);
-
-    mHwModules.add(module);
-}
-
 audio_stream_type_t AudioPolicyManager::streamTypefromAttributesInt(const audio_attributes_t *attr)
 {
     // flags to stream type mapping