Merge "Merge commit 'a8f3cafa4f81e3c38c4d0882031a246a36be1299' into merge"
diff --git a/camera/ICameraService.cpp b/camera/ICameraService.cpp
index 63c82cc..51a775b 100644
--- a/camera/ICameraService.cpp
+++ b/camera/ICameraService.cpp
@@ -302,6 +302,15 @@
         status_t res = data.readInt32();
         return res;
     }
+
+    virtual void notifySystemEvent(int eventId, int arg0) {
+        Parcel data, reply;
+        data.writeInt32(eventId);
+        data.writeInt32(arg0);
+        remote()->transact(BnCameraService::NOTIFY_SYSTEM_EVENT, data, &reply,
+                IBinder::FLAG_ONEWAY);
+    }
+
 };
 
 IMPLEMENT_META_INTERFACE(CameraService, "android.hardware.ICameraService");
@@ -470,6 +479,13 @@
             reply->writeInt32(status);
             return NO_ERROR;
         } break;
+        case NOTIFY_SYSTEM_EVENT: {
+            CHECK_INTERFACE(ICameraService, data, reply);
+            int eventId = data.readInt32();
+            int arg0 = data.readInt32();
+            notifySystemEvent(eventId, arg0);
+            return NO_ERROR;
+        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/include/camera/ICameraService.h b/include/camera/ICameraService.h
index c8d3d19..cad275e 100644
--- a/include/camera/ICameraService.h
+++ b/include/camera/ICameraService.h
@@ -51,6 +51,7 @@
         SUPPORTS_CAMERA_API,
         CONNECT_LEGACY,
         SET_TORCH_MODE,
+        NOTIFY_SYSTEM_EVENT,
     };
 
     enum {
@@ -64,7 +65,18 @@
 
     enum {
         CAMERA_HAL_API_VERSION_UNSPECIFIED = -1
-      };
+    };
+
+    /**
+     * Keep up-to-date with declarations in
+     * frameworks/base/services/core/java/com/android/server/camera/CameraService.java
+     *
+     * These event codes are intended to be used with the notifySystemEvent call.
+     */
+    enum {
+        NO_EVENT = 0,
+        USER_SWITCHED,
+    };
 
 public:
     DECLARE_META_INTERFACE(CameraService);
@@ -148,6 +160,11 @@
      */
     virtual status_t setTorchMode(const String16& cameraId, bool enabled,
             const sp<IBinder>& clientBinder) = 0;
+
+    /**
+     * Notify the camera service of a system event.  Should only be called from system_server.
+     */
+    virtual void notifySystemEvent(int eventId, int arg0) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index ad5d6ed..f5db1bb 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -346,7 +346,8 @@
 
     };
 
-    static void setAudioPortCallback(sp<AudioPortCallback> callBack);
+    static status_t addAudioPortCallback(const sp<AudioPortCallback>& callBack);
+    static status_t removeAudioPortCallback(const sp<AudioPortCallback>& callBack);
 
 private:
 
@@ -373,12 +374,19 @@
         AudioPolicyServiceClient() {
         }
 
+        status_t addAudioPortCallback(const sp<AudioPortCallback>& callBack);
+        status_t removeAudioPortCallback(const sp<AudioPortCallback>& callBack);
+
         // DeathRecipient
         virtual void binderDied(const wp<IBinder>& who);
 
         // IAudioPolicyServiceClient
         virtual void onAudioPortListUpdate();
         virtual void onAudioPatchListUpdate();
+
+    private:
+        Mutex                               mLock;
+        Vector <sp <AudioPortCallback> >    mAudioPortCallbacks;
     };
 
     static sp<AudioFlingerClient> gAudioFlingerClient;
@@ -390,7 +398,6 @@
     static Mutex gLockCache; // protects gOutputs, gPrevInSamplingRate, gPrevInFormat,
                              // gPrevInChannelMask and gInBuffSize
     static Mutex gLockAPS;   // protects gAudioPolicyService and gAudioPolicyServiceClient
-    static Mutex gLockAPC;   // protects gAudioPortCallback
     static sp<IAudioFlinger> gAudioFlinger;
     static audio_error_callback gAudioErrorCallback;
 
@@ -405,8 +412,6 @@
     // list of output descriptors containing cached parameters
     // (sampling rate, framecount, channel count...)
     static DefaultKeyedVector<audio_io_handle_t, OutputDescriptor *> gOutputs;
-
-    static sp<AudioPortCallback> gAudioPortCallback;
 };
 
 };  // namespace android
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index c6b34a7..9150a94 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -34,7 +34,6 @@
 Mutex AudioSystem::gLock;
 Mutex AudioSystem::gLockCache;
 Mutex AudioSystem::gLockAPS;
-Mutex AudioSystem::gLockAPC;
 sp<IAudioFlinger> AudioSystem::gAudioFlinger;
 sp<AudioSystem::AudioFlingerClient> AudioSystem::gAudioFlingerClient;
 audio_error_callback AudioSystem::gAudioErrorCallback = NULL;
@@ -48,8 +47,6 @@
 audio_channel_mask_t AudioSystem::gPrevInChannelMask;
 size_t AudioSystem::gInBuffSize = 0;    // zero indicates cache is invalid
 
-sp<AudioSystem::AudioPortCallback> AudioSystem::gAudioPortCallback;
-
 // establish binder interface to AudioFlinger service
 const sp<IAudioFlinger> AudioSystem::get_audio_flinger()
 {
@@ -873,7 +870,6 @@
         Mutex::Autolock _l(gLockAPS);
         gAudioPolicyService.clear();
     }
-    // Do not clear gAudioPortCallback
 }
 
 bool AudioSystem::isOffloadSupported(const audio_offload_info_t& info)
@@ -933,12 +929,31 @@
     return aps->setAudioPortConfig(config);
 }
 
-void AudioSystem::setAudioPortCallback(sp<AudioPortCallback> callBack)
+status_t AudioSystem::addAudioPortCallback(const sp<AudioPortCallback>& callBack)
 {
-    Mutex::Autolock _l(gLockAPC);
-    gAudioPortCallback = callBack;
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+
+    Mutex::Autolock _l(gLockAPS);
+    if (gAudioPolicyServiceClient == 0) {
+        return NO_INIT;
+    }
+    return gAudioPolicyServiceClient->addAudioPortCallback(callBack);
 }
 
+status_t AudioSystem::removeAudioPortCallback(const sp<AudioPortCallback>& callBack)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+
+    Mutex::Autolock _l(gLockAPS);
+    if (gAudioPolicyServiceClient == 0) {
+        return NO_INIT;
+    }
+    return gAudioPolicyServiceClient->removeAudioPortCallback(callBack);
+}
+
+
 status_t AudioSystem::acquireSoundTriggerSession(audio_session_t *session,
                                        audio_io_handle_t *ioHandle,
                                        audio_devices_t *device)
@@ -971,12 +986,58 @@
 
 // ---------------------------------------------------------------------------
 
+status_t AudioSystem::AudioPolicyServiceClient::addAudioPortCallback(
+        const sp<AudioPortCallback>& callBack)
+{
+    Mutex::Autolock _l(mLock);
+    for (size_t i = 0; i < mAudioPortCallbacks.size(); i++) {
+        if (mAudioPortCallbacks[i] == callBack) {
+            return INVALID_OPERATION;
+        }
+    }
+    mAudioPortCallbacks.add(callBack);
+    return NO_ERROR;
+}
+
+status_t AudioSystem::AudioPolicyServiceClient::removeAudioPortCallback(
+        const sp<AudioPortCallback>& callBack)
+{
+    Mutex::Autolock _l(mLock);
+    size_t i;
+    for (i = 0; i < mAudioPortCallbacks.size(); i++) {
+        if (mAudioPortCallbacks[i] == callBack) {
+            break;
+        }
+    }
+    if (i == mAudioPortCallbacks.size()) {
+        return INVALID_OPERATION;
+    }
+    mAudioPortCallbacks.removeAt(i);
+    return NO_ERROR;
+}
+
+void AudioSystem::AudioPolicyServiceClient::onAudioPortListUpdate()
+{
+    Mutex::Autolock _l(mLock);
+    for (size_t i = 0; i < mAudioPortCallbacks.size(); i++) {
+        mAudioPortCallbacks[i]->onAudioPortListUpdate();
+    }
+}
+
+void AudioSystem::AudioPolicyServiceClient::onAudioPatchListUpdate()
+{
+    Mutex::Autolock _l(mLock);
+    for (size_t i = 0; i < mAudioPortCallbacks.size(); i++) {
+        mAudioPortCallbacks[i]->onAudioPatchListUpdate();
+    }
+}
+
 void AudioSystem::AudioPolicyServiceClient::binderDied(const wp<IBinder>& who __unused)
 {
     {
-        Mutex::Autolock _l(gLockAPC);
-        if (gAudioPortCallback != 0) {
-            gAudioPortCallback->onServiceDied();
+        Mutex::Autolock _l(mLock);
+        for (size_t i = 0; i < mAudioPortCallbacks.size(); i++) {
+            mAudioPortCallbacks[i]->onServiceDied();
         }
     }
     {
@@ -987,20 +1048,4 @@
     ALOGW("AudioPolicyService server died!");
 }
 
-void AudioSystem::AudioPolicyServiceClient::onAudioPortListUpdate()
-{
-    Mutex::Autolock _l(gLockAPC);
-    if (gAudioPortCallback != 0) {
-        gAudioPortCallback->onAudioPortListUpdate();
-    }
-}
-
-void AudioSystem::AudioPolicyServiceClient::onAudioPatchListUpdate()
-{
-    Mutex::Autolock _l(gLockAPC);
-    if (gAudioPortCallback != 0) {
-        gAudioPortCallback->onAudioPatchListUpdate();
-    }
-}
-
 } // namespace android
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 98f64fe..ce30c62 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -667,14 +667,18 @@
 
 status_t AudioTrack::setSampleRate(uint32_t rate)
 {
-    if (mIsTimed || isOffloadedOrDirect()) {
+    AutoMutex lock(mLock);
+    if (rate == mSampleRate) {
+        return NO_ERROR;
+    }
+    if (mIsTimed || isOffloadedOrDirect_l() || (mFlags & AUDIO_OUTPUT_FLAG_FAST)) {
         return INVALID_OPERATION;
     }
-
-    AutoMutex lock(mLock);
     if (mOutput == AUDIO_IO_HANDLE_NONE) {
         return NO_INIT;
     }
+    // NOTE: it is theoretically possible, but highly unlikely, that a device change
+    // could mean a previously allowed sampling rate is no longer allowed.
     uint32_t afSamplingRate;
     if (AudioSystem::getSamplingRate(mOutput, &afSamplingRate) != NO_ERROR) {
         return NO_INIT;
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index a040343..5a31b74 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -265,6 +265,12 @@
         }
     }
 
+    mBitrate = totalBitrate;
+
+    return OK;
+}
+
+status_t NuPlayer::GenericSource::startSources() {
     // Start the selected A/V tracks now before we start buffering.
     // Widevine sources might re-initialize crypto when starting, if we delay
     // this to start(), all data buffered during prepare would be wasted.
@@ -279,8 +285,6 @@
         return UNKNOWN_ERROR;
     }
 
-    mBitrate = totalBitrate;
-
     return OK;
 }
 
@@ -415,6 +419,32 @@
             | FLAG_CAN_SEEK_FORWARD
             | FLAG_CAN_SEEK);
 
+    if (mIsSecure) {
+        // secure decoders must be instantiated before starting widevine source
+        sp<AMessage> reply = new AMessage(kWhatSecureDecodersInstantiated, this);
+        notifyInstantiateSecureDecoders(reply);
+    } else {
+        finishPrepareAsync();
+    }
+}
+
+void NuPlayer::GenericSource::onSecureDecodersInstantiated(status_t err) {
+    if (err != OK) {
+        ALOGE("Failed to instantiate secure decoders!");
+        notifyPreparedAndCleanup(err);
+        return;
+    }
+    finishPrepareAsync();
+}
+
+void NuPlayer::GenericSource::finishPrepareAsync() {
+    status_t err = startSources();
+    if (err != OK) {
+        ALOGE("Failed to init start data source!");
+        notifyPreparedAndCleanup(err);
+        return;
+    }
+
     if (mIsStreaming) {
         mPrepareBuffering = true;
 
@@ -430,6 +460,7 @@
         mDataSource.clear();
         mCachedSource.clear();
         mHttpSource.clear();
+        mBitrate = -1;
 
         cancelPollBuffering();
     }
@@ -805,6 +836,14 @@
           break;
       }
 
+      case kWhatSecureDecodersInstantiated:
+      {
+          int32_t err;
+          CHECK(msg->findInt32("err", &err));
+          onSecureDecodersInstantiated(err);
+          break;
+      }
+
       case kWhatStopWidevine:
       {
           // mStopRead is only used for Widevine to prevent the video source
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.h b/media/libmediaplayerservice/nuplayer/GenericSource.h
index 5fc41ec..862ee5f 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.h
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.h
@@ -96,6 +96,7 @@
         kWhatStopWidevine,
         kWhatStart,
         kWhatResume,
+        kWhatSecureDecodersInstantiated,
     };
 
     struct Track {
@@ -158,6 +159,9 @@
     void setDrmPlaybackStatusIfNeeded(int playbackStatus, int64_t position);
 
     void notifyPreparedAndCleanup(status_t err);
+    void onSecureDecodersInstantiated(status_t err);
+    void finishPrepareAsync();
+    status_t startSources();
 
     void onGetFormatMeta(sp<AMessage> msg) const;
     sp<MetaData> doGetFormatMeta(bool audio) const;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index f4d3794..cfa5258 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -1021,23 +1021,41 @@
     }
 }
 
+status_t NuPlayer::onInstantiateSecureDecoders() {
+    status_t err;
+    if (!(mSourceFlags & Source::FLAG_SECURE)) {
+        return BAD_TYPE;
+    }
+
+    if (mRenderer != NULL) {
+        ALOGE("renderer should not be set when instantiating secure decoders");
+        return UNKNOWN_ERROR;
+    }
+
+    // TRICKY: We rely on mRenderer being null, so that decoder does not start requesting
+    // data on instantiation.
+    if (mNativeWindow != NULL) {
+        err = instantiateDecoder(false, &mVideoDecoder);
+        if (err != OK) {
+            return err;
+        }
+    }
+
+    if (mAudioSink != NULL) {
+        err = instantiateDecoder(true, &mAudioDecoder);
+        if (err != OK) {
+            return err;
+        }
+    }
+    return OK;
+}
+
 void NuPlayer::onStart() {
     mOffloadAudio = false;
     mAudioEOS = false;
     mVideoEOS = false;
     mStarted = true;
 
-    /* instantiate decoders now for secure playback */
-    if (mSourceFlags & Source::FLAG_SECURE) {
-        if (mNativeWindow != NULL) {
-            instantiateDecoder(false, &mVideoDecoder);
-        }
-
-        if (mAudioSink != NULL) {
-            instantiateDecoder(true, &mAudioDecoder);
-        }
-    }
-
     mSource->start();
 
     uint32_t flags = 0;
@@ -1390,7 +1408,7 @@
     FlushStatus newStatus =
         needShutdown ? FLUSHING_DECODER_SHUTDOWN : FLUSHING_DECODER;
 
-    mFlushComplete[audio][false /* isDecoder */] = false;
+    mFlushComplete[audio][false /* isDecoder */] = (mRenderer == NULL);
     mFlushComplete[audio][true /* isDecoder */] = false;
     if (audio) {
         ALOGE_IF(mFlushingAudio != NONE,
@@ -1675,6 +1693,23 @@
     CHECK(msg->findInt32("what", &what));
 
     switch (what) {
+        case Source::kWhatInstantiateSecureDecoders:
+        {
+            if (mSource == NULL) {
+                // This is a stale notification from a source that was
+                // asynchronously preparing when the client called reset().
+                // We handled the reset, the source is gone.
+                break;
+            }
+
+            sp<AMessage> reply;
+            CHECK(msg->findMessage("reply", &reply));
+            status_t err = onInstantiateSecureDecoders();
+            reply->setInt32("err", err);
+            reply->post();
+            break;
+        }
+
         case Source::kWhatPrepared:
         {
             if (mSource == NULL) {
@@ -1687,6 +1722,14 @@
             int32_t err;
             CHECK(msg->findInt32("err", &err));
 
+            if (err != OK) {
+                // shut down potential secure codecs in case client never calls reset
+                mDeferredActions.push_back(
+                        new FlushDecoderAction(FLUSH_CMD_SHUTDOWN /* audio */,
+                                               FLUSH_CMD_SHUTDOWN /* video */));
+                processDeferredActions();
+            }
+
             sp<NuPlayerDriver> driver = mDriver.promote();
             if (driver != NULL) {
                 // notify duration first, so that it's definitely set when
@@ -1971,6 +2014,13 @@
     notify->post();
 }
 
+void NuPlayer::Source::notifyInstantiateSecureDecoders(const sp<AMessage> &reply) {
+    sp<AMessage> notify = dupNotify();
+    notify->setInt32("what", kWhatInstantiateSecureDecoders);
+    notify->setMessage("reply", reply);
+    notify->post();
+}
+
 void NuPlayer::Source::onMessageReceived(const sp<AMessage> & /* msg */) {
     TRESPASS();
 }
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index a2cb53e..2bc20d7 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -204,6 +204,8 @@
 
     status_t instantiateDecoder(bool audio, sp<DecoderBase> *decoder);
 
+    status_t onInstantiateSecureDecoders();
+
     void updateVideoSize(
             const sp<AMessage> &inputFormat,
             const sp<AMessage> &outputFormat = NULL);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
index 5a8beb1..d9f14a2 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
@@ -55,6 +55,7 @@
         kWhatTimedTextData,
         kWhatQueueDecoderShutdown,
         kWhatDrmNoLicense,
+        kWhatInstantiateSecureDecoders,
     };
 
     // The provides message is used to notify the player about various
@@ -125,6 +126,7 @@
 
     void notifyFlagsChanged(uint32_t flags);
     void notifyVideoSizeChanged(const sp<AMessage> &format = NULL);
+    void notifyInstantiateSecureDecoders(const sp<AMessage> &reply);
     void notifyPrepared(status_t err = OK);
 
 private:
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index 4ac2fb2..118c174 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -50,6 +50,17 @@
 
 namespace android {
 
+// static
+// Bandwidth Switch Mark Defaults
+const int64_t LiveSession::kUpSwitchMarkUs = 25000000ll;
+const int64_t LiveSession::kDownSwitchMarkUs = 18000000ll;
+const int64_t LiveSession::kUpSwitchMarginUs = 5000000ll;
+
+// Buffer Prepare/Ready/Underflow Marks
+const int64_t LiveSession::kReadyMarkUs = 5000000ll;
+const int64_t LiveSession::kPrepareMarkUs = 1500000ll;
+const int64_t LiveSession::kUnderflowMarkUs = 1000000ll;
+
 struct LiveSession::BandwidthEstimator : public RefBase {
     BandwidthEstimator();
 
@@ -153,9 +164,9 @@
       mRealTimeBaseUs(0ll),
       mReconfigurationInProgress(false),
       mSwitchInProgress(false),
-      mUpSwitchMark(kUpSwitchMark),
-      mDownSwitchMark(kDownSwitchMark),
-      mUpSwitchMargin(kUpSwitchMargin),
+      mUpSwitchMark(kUpSwitchMarkUs),
+      mDownSwitchMark(kDownSwitchMarkUs),
+      mUpSwitchMargin(kUpSwitchMarginUs),
       mFirstTimeUsValid(false),
       mFirstTimeUs(0),
       mLastSeekTimeUs(0) {
@@ -563,9 +574,9 @@
                 {
                     int64_t targetDurationUs;
                     CHECK(msg->findInt64("targetDurationUs", &targetDurationUs));
-                    mUpSwitchMark = min(kUpSwitchMark, targetDurationUs * 3);
-                    mDownSwitchMark = min(kDownSwitchMark, targetDurationUs * 9 / 4);
-                    mUpSwitchMargin = min(kUpSwitchMargin, targetDurationUs);
+                    mUpSwitchMark = min(kUpSwitchMarkUs, targetDurationUs * 3);
+                    mDownSwitchMark = min(kDownSwitchMarkUs, targetDurationUs * 9 / 4);
+                    mUpSwitchMargin = min(kUpSwitchMarginUs, targetDurationUs);
                     break;
                 }
 
@@ -656,7 +667,7 @@
                     // If switching up, require a cushion bigger than kUnderflowMark
                     // to avoid buffering immediately after the switch.
                     // (If we don't have that cushion we'd rather cancel and try again.)
-                    int64_t delayUs = switchUp ? (kUnderflowMark + 1000000ll) : 0;
+                    int64_t delayUs = switchUp ? (kUnderflowMarkUs + 1000000ll) : 0;
                     bool needResumeUntil = false;
                     sp<AMessage> stopParams = msg;
                     if (checkSwitchProgress(stopParams, delayUs, &needResumeUntil)) {
@@ -2068,13 +2079,13 @@
         }
 
         ++activeCount;
-        int64_t readyMark = mInPreparationPhase ? kPrepareMark : kReadyMark;
+        int64_t readyMark = mInPreparationPhase ? kPrepareMarkUs : kReadyMarkUs;
         if (bufferedDurationUs > readyMark
                 || mPacketSources[i]->isFinished(0)) {
             ++readyCount;
         }
         if (!mPacketSources[i]->isFinished(0)) {
-            if (bufferedDurationUs < kUnderflowMark) {
+            if (bufferedDurationUs < kUnderflowMarkUs) {
                 ++underflowCount;
             }
             if (bufferedDurationUs > mUpSwitchMark) {
diff --git a/media/libstagefright/httplive/LiveSession.h b/media/libstagefright/httplive/LiveSession.h
index d11675b..3d62cab 100644
--- a/media/libstagefright/httplive/LiveSession.h
+++ b/media/libstagefright/httplive/LiveSession.h
@@ -122,14 +122,14 @@
     };
 
     // Bandwidth Switch Mark Defaults
-    static const int64_t kUpSwitchMark = 25000000ll;
-    static const int64_t kDownSwitchMark = 18000000ll;
-    static const int64_t kUpSwitchMargin = 5000000ll;
+    static const int64_t kUpSwitchMarkUs;
+    static const int64_t kDownSwitchMarkUs;
+    static const int64_t kUpSwitchMarginUs;
 
     // Buffer Prepare/Ready/Underflow Marks
-    static const int64_t kReadyMark = 5000000ll;
-    static const int64_t kPrepareMark = 1500000ll;
-    static const int64_t kUnderflowMark = 1000000ll;
+    static const int64_t kReadyMarkUs;
+    static const int64_t kPrepareMarkUs;
+    static const int64_t kUnderflowMarkUs;
 
     struct BandwidthEstimator;
     struct BandwidthItem {
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index 6786506..01c3dd6 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -166,10 +166,12 @@
     PSISection();
 
     status_t append(const void *data, size_t size);
+    void setSkipBytes(uint8_t skip);
     void clear();
 
     bool isComplete() const;
     bool isEmpty() const;
+    bool isCRCOkay() const;
 
     const uint8_t *data() const;
     size_t size() const;
@@ -179,6 +181,8 @@
 
 private:
     sp<ABuffer> mBuffer;
+    uint8_t mSkipBytes;
+    static uint32_t CRC_TABLE[];
 
     DISALLOW_EVIL_CONSTRUCTORS(PSISection);
 };
@@ -1171,6 +1175,7 @@
             }
 
             unsigned skip = br->getBits(8);
+            section->setSkipBytes(skip + 1);  // skip filler bytes + pointer field itself
             br->skipBits(skip * 8);
         }
 
@@ -1185,6 +1190,9 @@
             return OK;
         }
 
+        if (!section->isCRCOkay()) {
+            return BAD_VALUE;
+        }
         ABitReader sectionBits(section->data(), section->size());
 
         if (PID == 0) {
@@ -1407,7 +1415,79 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-ATSParser::PSISection::PSISection() {
+
+// CRC32 used for PSI section. The table was generated by following command:
+// $ python pycrc.py --model crc-32-mpeg --algorithm table-driven --generate c
+// Visit http://www.tty1.net/pycrc/index_en.html for more details.
+uint32_t ATSParser::PSISection::CRC_TABLE[] = {
+    0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
+    0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
+    0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
+    0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
+    0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
+    0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
+    0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
+    0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
+    0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
+    0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
+    0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
+    0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
+    0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
+    0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
+    0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
+    0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
+    0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
+    0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
+    0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
+    0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
+    0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
+    0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
+    0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
+    0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
+    0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
+    0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
+    0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
+    0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
+    0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
+    0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
+    0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
+    0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
+    0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
+    0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
+    0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
+    0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
+    0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
+    0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
+    0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
+    0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
+    0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
+    0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
+    0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
+    0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
+    0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
+    0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
+    0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
+    0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
+    0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
+    0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
+    0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
+    0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
+    0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
+    0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
+    0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
+    0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
+    0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
+    0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
+    0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
+    0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
+    0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
+    0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
+    0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
+    0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
+    };
+
+ATSParser::PSISection::PSISection() :
+    mSkipBytes(0) {
 }
 
 ATSParser::PSISection::~PSISection() {
@@ -1438,10 +1518,15 @@
     return OK;
 }
 
+void ATSParser::PSISection::setSkipBytes(uint8_t skip) {
+    mSkipBytes = skip;
+}
+
 void ATSParser::PSISection::clear() {
     if (mBuffer != NULL) {
         mBuffer->setRange(0, 0);
     }
+    mSkipBytes = 0;
 }
 
 bool ATSParser::PSISection::isComplete() const {
@@ -1465,4 +1550,30 @@
     return mBuffer == NULL ? 0 : mBuffer->size();
 }
 
+bool ATSParser::PSISection::isCRCOkay() const {
+    if (!isComplete()) {
+        return false;
+    }
+    uint8_t* data = mBuffer->data();
+
+    // Return true if section_syntax_indicator says no section follows the field section_length.
+    if ((data[1] & 0x80) == 0) {
+        return true;
+    }
+
+    unsigned sectionLength = U16_AT(data + 1) & 0xfff;
+    ALOGV("sectionLength %u, skip %u", sectionLength, mSkipBytes);
+
+    // Skip the preceding field present when payload start indicator is on.
+    sectionLength -= mSkipBytes;
+
+    uint32_t crc = 0xffffffff;
+    for(unsigned i = 0; i < sectionLength + 4 /* crc */; i++) {
+        uint8_t b = data[i];
+        int index = ((crc >> 24) ^ (b & 0xff)) & 0xff;
+        crc = CRC_TABLE[index] ^ (crc << 8);
+    }
+    ALOGV("crc: %08x\n", crc);
+    return (crc == 0);
+}
 }  // namespace android
diff --git a/media/mediaserver/Android.mk b/media/mediaserver/Android.mk
index baf65f6..0e2e48c 100644
--- a/media/mediaserver/Android.mk
+++ b/media/mediaserver/Android.mk
@@ -31,13 +31,16 @@
 	libradioservice
 
 LOCAL_STATIC_LIBRARIES := \
-	libregistermsext
+        libregistermsext
 
 LOCAL_C_INCLUDES := \
     frameworks/av/media/libmediaplayerservice \
     frameworks/av/services/medialog \
     frameworks/av/services/audioflinger \
     frameworks/av/services/audiopolicy \
+    frameworks/av/services/audiopolicy/common/managerdefinitions/include \
+    frameworks/av/services/audiopolicy/common/include \
+    frameworks/av/services/audiopolicy/engine/interface \
     frameworks/av/services/camera/libcameraservice \
     frameworks/av/services/mediaresourcemanager \
     $(call include-path-for, audio-utils) \
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 5988d2c..4efb3d7 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -4316,6 +4316,10 @@
             }
             if (track->isStopping_1()) {
                 track->mState = TrackBase::STOPPING_2;
+                if (last && mHwPaused) {
+                     doHwResume = true;
+                     mHwPaused = false;
+                 }
             }
             if ((track->sharedBuffer() != 0) || track->isStopped() ||
                     track->isStopping_2() || track->isPaused()) {
@@ -4455,14 +4459,17 @@
 bool AudioFlinger::DirectOutputThread::shouldStandby_l()
 {
     bool trackPaused = false;
+    bool trackStopped = false;
 
     // do not put the HAL in standby when paused. AwesomePlayer clear the offloaded AudioTrack
     // after a timeout and we will enter standby then.
     if (mTracks.size() > 0) {
         trackPaused = mTracks[mTracks.size() - 1]->isPaused();
+        trackStopped = mTracks[mTracks.size() - 1]->isStopped() ||
+                           mTracks[mTracks.size() - 1]->mState == TrackBase::IDLE;
     }
 
-    return !mStandby && !(trackPaused || (usesHwAvSync() && mHwPaused));
+    return !mStandby && !(trackPaused || (usesHwAvSync() && mHwPaused && !trackStopped));
 }
 
 // getTrackName_l() must be called with ThreadBase::mLock held
@@ -4565,7 +4572,10 @@
 
     // use shorter standby delay as on normal output to release
     // hardware resources as soon as possible
-    if (audio_is_linear_pcm(mFormat)) {
+    // no delay on outputs with HW A/V sync
+    if (usesHwAvSync()) {
+        standbyDelay = 0;
+    } else if (audio_is_linear_pcm(mFormat)) {
         standbyDelay = microseconds(activeSleepTime*2);
     } else {
         standbyDelay = kOffloadStandbyDelayNs;
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 7692315..dc9f249 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -745,6 +745,7 @@
                 // move to STOPPING_2 when drain completes and then STOPPED
                 mState = STOPPING_1;
             }
+            playbackThread->broadcast_l();
             ALOGV("not stopping/stopped => stopping/stopped (%d) on thread %p", mName,
                     playbackThread);
         }
diff --git a/services/audiopolicy/Android.mk b/services/audiopolicy/Android.mk
index 351ed79..d4ce86a 100644
--- a/services/audiopolicy/Android.mk
+++ b/services/audiopolicy/Android.mk
@@ -21,7 +21,9 @@
 LOCAL_C_INCLUDES := \
     $(TOPDIR)frameworks/av/services/audioflinger \
     $(call include-path-for, audio-effects) \
-    $(call include-path-for, audio-utils)
+    $(call include-path-for, audio-utils) \
+    $(TOPDIR)frameworks/av/services/audiopolicy/common/include \
+    $(TOPDIR)frameworks/av/services/audiopolicy/engine/interface \
 
 LOCAL_SHARED_LIBRARIES := \
     libcutils \
@@ -39,7 +41,8 @@
 endif
 
 LOCAL_STATIC_LIBRARIES := \
-    libmedia_helper
+    libmedia_helper \
+    libaudiopolicycomponents
 
 LOCAL_MODULE:= libaudiopolicyservice
 
@@ -54,14 +57,6 @@
 
 LOCAL_SRC_FILES:= \
     managerdefault/AudioPolicyManager.cpp \
-    managerdefault/ConfigParsingUtils.cpp \
-    managerdefault/Devices.cpp \
-    managerdefault/Gains.cpp \
-    managerdefault/HwModule.cpp \
-    managerdefault/IOProfile.cpp \
-    managerdefault/Ports.cpp \
-    managerdefault/AudioInputDescriptor.cpp \
-    managerdefault/AudioOutputDescriptor.cpp
 
 LOCAL_SHARED_LIBRARIES := \
     libcutils \
@@ -69,8 +64,15 @@
     liblog \
     libsoundtrigger
 
+LOCAL_SHARED_LIBRARIES += libaudiopolicyenginedefault
+
+LOCAL_C_INCLUDES += \
+    $(TOPDIR)frameworks/av/services/audiopolicy/common/include \
+    $(TOPDIR)frameworks/av/services/audiopolicy/engine/interface \
+
 LOCAL_STATIC_LIBRARIES := \
-    libmedia_helper
+    libmedia_helper \
+    libaudiopolicycomponents
 
 LOCAL_MODULE:= libaudiopolicymanagerdefault
 
@@ -86,9 +88,21 @@
 LOCAL_SHARED_LIBRARIES := \
     libaudiopolicymanagerdefault
 
+LOCAL_STATIC_LIBRARIES := \
+    libaudiopolicycomponents
+
+LOCAL_C_INCLUDES += \
+    $(TOPDIR)frameworks/av/services/audiopolicy/common/include \
+    $(TOPDIR)frameworks/av/services/audiopolicy/engine/interface \
+
 LOCAL_MODULE:= libaudiopolicymanager
 
 include $(BUILD_SHARED_LIBRARY)
 
 endif
 endif
+
+#######################################################################
+# Recursive call sub-folder Android.mk
+#
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/services/audiopolicy/common/Android.mk b/services/audiopolicy/common/Android.mk
new file mode 100644
index 0000000..dcce8e3
--- /dev/null
+++ b/services/audiopolicy/common/Android.mk
@@ -0,0 +1,9 @@
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+#######################################################################
+# Recursive call sub-folder Android.mk
+#
+include $(call all-makefiles-under,$(LOCAL_PATH))
+
diff --git a/services/audiopolicy/managerdefault/ApmImplDefinitions.h b/services/audiopolicy/common/include/RoutingStrategy.h
similarity index 79%
rename from services/audiopolicy/managerdefault/ApmImplDefinitions.h
rename to services/audiopolicy/common/include/RoutingStrategy.h
index 620979b..d38967e 100644
--- a/services/audiopolicy/managerdefault/ApmImplDefinitions.h
+++ b/services/audiopolicy/common/include/RoutingStrategy.h
@@ -14,8 +14,14 @@
  * limitations under the License.
  */
 
+#pragma once
+
 namespace android {
 
+// Time in milliseconds after media stopped playing during which we consider that the
+// sonification should be as unobtrusive as during the time media was playing.
+#define SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY 5000
+
 enum routing_strategy {
     STRATEGY_MEDIA,
     STRATEGY_PHONE,
diff --git a/services/audiopolicy/common/include/Volume.h b/services/audiopolicy/common/include/Volume.h
new file mode 100755
index 0000000..a4cc759
--- /dev/null
+++ b/services/audiopolicy/common/include/Volume.h
@@ -0,0 +1,137 @@
+/*
+ * 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 <utils/Log.h>
+
+class VolumeCurvePoint
+{
+public:
+    int mIndex;
+    float mDBAttenuation;
+};
+
+class Volume
+{
+public:
+    /**
+     * 4 points to define the volume attenuation curve, each characterized by the volume
+     * index (from 0 to 100) at which they apply, and the attenuation in dB at that index.
+     * we use 100 steps to avoid rounding errors when computing the volume in volIndexToAmpl()
+     *
+     * @todo shall become configurable
+     */
+    enum {
+        VOLMIN = 0,
+        VOLKNEE1 = 1,
+        VOLKNEE2 = 2,
+        VOLMAX = 3,
+
+        VOLCNT = 4
+    };
+
+    /**
+     * 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
+     *
+     * @return subset of device required to limit the number of volume category per device
+     */
+    static audio_devices_t getDeviceForVolume(audio_devices_t device)
+    {
+        if (device == AUDIO_DEVICE_NONE) {
+            // this happens when forcing a route update and no track is active on an output.
+            // In this case the returned category is not important.
+            device =  AUDIO_DEVICE_OUT_SPEAKER;
+        } else if (popcount(device) > 1) {
+            // Multiple device selection is either:
+            //  - speaker + one other device: give priority to speaker in this case.
+            //  - one A2DP device + another device: happens with duplicated output. In this case
+            // retain the device on the A2DP output as the other must not correspond to an active
+            // selection if not the speaker.
+            //  - HDMI-CEC system audio mode only output: give priority to available item in order.
+            if (device & AUDIO_DEVICE_OUT_SPEAKER) {
+                device = AUDIO_DEVICE_OUT_SPEAKER;
+            } else if (device & AUDIO_DEVICE_OUT_HDMI_ARC) {
+                device = AUDIO_DEVICE_OUT_HDMI_ARC;
+            } else if (device & AUDIO_DEVICE_OUT_AUX_LINE) {
+                device = AUDIO_DEVICE_OUT_AUX_LINE;
+            } else if (device & AUDIO_DEVICE_OUT_SPDIF) {
+                device = AUDIO_DEVICE_OUT_SPDIF;
+            } else {
+                device = (audio_devices_t)(device & AUDIO_DEVICE_OUT_ALL_A2DP);
+            }
+        }
+
+        /*SPEAKER_SAFE is an alias of SPEAKER for purposes of volume control*/
+        if (device == AUDIO_DEVICE_OUT_SPEAKER_SAFE)
+            device = AUDIO_DEVICE_OUT_SPEAKER;
+
+        ALOGW_IF(popcount(device) != 1,
+                 "getDeviceForVolume() invalid device combination: %08x",
+                 device);
+
+        return device;
+    }
+
+    /**
+     * returns the category the device belongs to with regard to volume curve management
+     *
+     * @param[in] device to check upon the category to whom it belongs to.
+     *
+     * @return device category.
+     */
+    static device_category getDeviceCategory(audio_devices_t device)
+    {
+        switch(getDeviceForVolume(device)) {
+        case AUDIO_DEVICE_OUT_EARPIECE:
+            return DEVICE_CATEGORY_EARPIECE;
+        case AUDIO_DEVICE_OUT_WIRED_HEADSET:
+        case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
+        case AUDIO_DEVICE_OUT_BLUETOOTH_SCO:
+        case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET:
+        case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
+        case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
+            return DEVICE_CATEGORY_HEADSET;
+        case AUDIO_DEVICE_OUT_LINE:
+        case AUDIO_DEVICE_OUT_AUX_DIGITAL:
+            /*USB?  Remote submix?*/
+            return DEVICE_CATEGORY_EXT_MEDIA;
+        case AUDIO_DEVICE_OUT_SPEAKER:
+        case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT:
+        case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:
+        case AUDIO_DEVICE_OUT_USB_ACCESSORY:
+        case AUDIO_DEVICE_OUT_USB_DEVICE:
+        case AUDIO_DEVICE_OUT_REMOTE_SUBMIX:
+        default:
+            return DEVICE_CATEGORY_SPEAKER;
+        }
+    }
+
+};
diff --git a/services/audiopolicy/common/include/policy.h b/services/audiopolicy/common/include/policy.h
new file mode 100755
index 0000000..a2327ee
--- /dev/null
+++ b/services/audiopolicy/common/include/policy.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <system/audio.h>
+
+// For mixed output and inputs, the policy will use max mixer sampling rates.
+// Do not limit sampling rate otherwise
+#define MAX_MIXER_SAMPLING_RATE 48000
+
+// For mixed output and inputs, the policy will use max mixer channel count.
+// Do not limit channel count otherwise
+#define MAX_MIXER_CHANNEL_COUNT 8
+
+/**
+ * A device mask for all audio input devices that are considered "virtual" when evaluating
+ * active inputs in getActiveInput()
+ */
+#define APM_AUDIO_IN_DEVICE_VIRTUAL_ALL  (AUDIO_DEVICE_IN_REMOTE_SUBMIX|AUDIO_DEVICE_IN_FM_TUNER)
+
+
+/**
+ * A device mask for all audio input and output devices where matching inputs/outputs on device
+ * type alone is not enough: the address must match too
+ */
+#define APM_AUDIO_DEVICE_MATCH_ADDRESS_ALL (AUDIO_DEVICE_IN_REMOTE_SUBMIX | \
+                                            AUDIO_DEVICE_OUT_REMOTE_SUBMIX)
+
+/**
+ * Check if the state given correspond to an in call state.
+ * @TODO find a better name for widely call state
+ *
+ * @param[in] state to consider
+ *
+ * @return true if given state represents a device in a telephony or VoIP call
+ */
+static inline bool is_state_in_call(int state)
+{
+    return (state == AUDIO_MODE_IN_CALL) || (state == AUDIO_MODE_IN_COMMUNICATION);
+}
+
+/**
+ * Check if the input device given is considered as a virtual device.
+ *
+ * @param[in] device to consider
+ *
+ * @return true if the device is a virtual one, false otherwise.
+ */
+static bool is_virtual_input_device(audio_devices_t device)
+{
+    if ((device & AUDIO_DEVICE_BIT_IN) != 0) {
+        device &= ~AUDIO_DEVICE_BIT_IN;
+        if ((popcount(device) == 1) && ((device & ~APM_AUDIO_IN_DEVICE_VIRTUAL_ALL) == 0))
+            return true;
+    }
+    return false;
+}
+
+/**
+ * Check whether the device type is one
+ * where addresses are used to distinguish between one connected device and another
+ *
+ * @param[in] device to consider
+ *
+ * @return true if the device needs distinguish on address, false otherwise..
+ */
+static bool device_distinguishes_on_address(audio_devices_t device)
+{
+    return ((device & APM_AUDIO_DEVICE_MATCH_ADDRESS_ALL & ~AUDIO_DEVICE_BIT_IN) != 0);
+}
diff --git a/services/audiopolicy/common/managerdefinitions/Android.mk b/services/audiopolicy/common/managerdefinitions/Android.mk
new file mode 100644
index 0000000..71ba1cb
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/Android.mk
@@ -0,0 +1,34 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+    src/DeviceDescriptor.cpp \
+    src/AudioGain.cpp \
+    src/StreamDescriptor.cpp \
+    src/HwModule.cpp \
+    src/IOProfile.cpp \
+    src/AudioPort.cpp \
+    src/AudioPolicyMix.cpp \
+    src/AudioPatch.cpp \
+    src/AudioInputDescriptor.cpp \
+    src/AudioOutputDescriptor.cpp \
+    src/EffectDescriptor.cpp \
+    src/ConfigParsingUtils.cpp \
+    src/SoundTriggerSession.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+    libcutils \
+    libutils \
+    liblog \
+
+LOCAL_C_INCLUDES += \
+    $(LOCAL_PATH)/include \
+    $(TOPDIR)frameworks/av/services/audiopolicy/common/include \
+
+LOCAL_EXPORT_C_INCLUDE_DIRS := \
+    $(LOCAL_PATH)/include
+
+LOCAL_MODULE := libaudiopolicycomponents
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioGain.h b/services/audiopolicy/common/managerdefinitions/include/AudioGain.h
new file mode 100644
index 0000000..21fbf9b
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioGain.h
@@ -0,0 +1,40 @@
+/*
+ * 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 <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <system/audio.h>
+
+namespace android {
+
+class AudioGain: public RefBase
+{
+public:
+    AudioGain(int index, bool useInChannelMask);
+    virtual ~AudioGain() {}
+
+    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);
+    int               mIndex;
+    struct audio_gain mGain;
+    bool              mUseInChannelMask;
+};
+
+}; // namespace android
diff --git a/services/audiopolicy/managerdefault/AudioInputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
similarity index 68%
rename from services/audiopolicy/managerdefault/AudioInputDescriptor.h
rename to services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
index 02579e6..7536a37 100644
--- a/services/audiopolicy/managerdefault/AudioInputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
@@ -14,14 +14,28 @@
  * limitations under the License.
  */
 
+#pragma once
+
+#include "AudioPort.h"
+#include <utils/Errors.h>
+#include <system/audio.h>
+#include <utils/SortedVector.h>
+#include <utils/KeyedVector.h>
+
 namespace android {
 
+class IOProfile;
+class AudioMix;
+
 // descriptor for audio inputs. Used to maintain current configuration of each opened audio input
 // and keep track of the usage of this input.
 class AudioInputDescriptor: public AudioPortConfig
 {
 public:
     AudioInputDescriptor(const sp<IOProfile>& profile);
+    void setIoHandle(audio_io_handle_t ioHandle);
+
+    audio_module_handle_t getModuleHandle() const;
 
     status_t    dump(int fd);
 
@@ -45,4 +59,27 @@
     void toAudioPort(struct audio_port *port) const;
 };
 
+class AudioInputCollection :
+        public DefaultKeyedVector< audio_io_handle_t, sp<AudioInputDescriptor> >
+{
+public:
+    bool isSourceActive(audio_source_t source) const;
+
+    sp<AudioInputDescriptor> getInputFromId(audio_port_handle_t id) const;
+
+    uint32_t activeInputsCount() const;
+
+    /**
+     * return io handle of active input or 0 if no input is active
+     * Only considers inputs from physical devices (e.g. main mic, headset mic) when
+     * ignoreVirtualInputs is true.
+     */
+    audio_io_handle_t getActiveInput(bool ignoreVirtualInputs = true);
+
+    audio_devices_t getSupportedDevices(audio_io_handle_t handle) const;
+
+    status_t dump(int fd) const;
+};
+
+
 }; // namespace android
diff --git a/services/audiopolicy/managerdefault/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
similarity index 65%
rename from services/audiopolicy/managerdefault/AudioOutputDescriptor.h
rename to services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
index 32f46e4..43ee691 100644
--- a/services/audiopolicy/managerdefault/AudioOutputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
@@ -14,10 +14,20 @@
  * limitations under the License.
  */
 
-#include "ApmImplDefinitions.h"
+#pragma once
+
+#include "AudioPort.h"
+#include <RoutingStrategy.h>
+#include <utils/Errors.h>
+#include <utils/Timers.h>
+#include <utils/KeyedVector.h>
+#include <system/audio.h>
 
 namespace android {
 
+class IOProfile;
+class AudioMix;
+
 // descriptor for audio outputs. Used to maintain current configuration of each opened audio output
 // and keep track of the usage of this output by each audio stream type.
 class AudioOutputDescriptor: public AudioPortConfig
@@ -30,6 +40,7 @@
     audio_devices_t device() const;
     void changeRefCount(audio_stream_type_t stream, int delta);
 
+    void setIoHandle(audio_io_handle_t ioHandle);
     bool isDuplicated() const { return (mOutput1 != NULL && mOutput2 != NULL); }
     audio_devices_t supportedDevices();
     uint32_t latency();
@@ -38,15 +49,14 @@
     bool isStreamActive(audio_stream_type_t stream,
                         uint32_t inPastMs = 0,
                         nsecs_t sysTime = 0) const;
-    bool isStrategyActive(routing_strategy strategy,
-                     uint32_t inPastMs = 0,
-                     nsecs_t sysTime = 0) const;
 
     virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
                            const struct audio_port_config *srcConfig = NULL) const;
     virtual sp<AudioPort> getAudioPort() const { return mProfile; }
     void toAudioPort(struct audio_port *port) const;
 
+    audio_module_handle_t getModuleHandle() const;
+
     audio_port_handle_t mId;
     audio_io_handle_t mIoHandle;              // output handle
     uint32_t mLatency;                  //
@@ -66,4 +76,38 @@
     uint32_t mDirectOpenCount; // number of clients using this output (direct outputs only)
 };
 
+class AudioOutputCollection :
+        public DefaultKeyedVector< audio_io_handle_t, sp<AudioOutputDescriptor> >
+{
+public:
+    bool isStreamActive(audio_stream_type_t stream, uint32_t inPastMs = 0) const;
+
+    /**
+     * return whether a stream is playing remotely, override to change the definition of
+     * local/remote playback, used for instance by notification manager to not make
+     * media players lose audio focus when not playing locally
+     * For the base implementation, "remotely" means playing during screen mirroring which
+     * uses an output for playback with a non-empty, non "0" address.
+     */
+    bool isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs = 0) const;
+
+    /**
+     * returns the A2DP output handle if it is open or 0 otherwise
+     */
+    audio_io_handle_t getA2dpOutput() const;
+
+    sp<AudioOutputDescriptor> getOutputFromId(audio_port_handle_t id) const;
+
+    sp<AudioOutputDescriptor> getPrimaryOutput() const;
+
+    /**
+     * return true if any output is playing anything besides the stream to ignore
+     */
+    bool isAnyOutputActive(audio_stream_type_t streamToIgnore) const;
+
+    audio_devices_t getSupportedDevices(audio_io_handle_t handle) const;
+
+    status_t dump(int fd) const;
+};
+
 }; // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPatch.h b/services/audiopolicy/common/managerdefinitions/include/AudioPatch.h
new file mode 100644
index 0000000..385f257
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPatch.h
@@ -0,0 +1,55 @@
+/*
+ * 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 <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <utils/Errors.h>
+#include <utils/KeyedVector.h>
+
+namespace android {
+
+class AudioPatch : public RefBase
+{
+public:
+    AudioPatch(const struct audio_patch *patch, uid_t uid);
+
+    status_t dump(int fd, int spaces, int index) const;
+
+    audio_patch_handle_t mHandle;
+    struct audio_patch mPatch;
+    uid_t mUid;
+    audio_patch_handle_t mAfPatchHandle;
+
+private:
+    static volatile int32_t mNextUniqueId;
+};
+
+class AudioPatchCollection : public DefaultKeyedVector<audio_patch_handle_t, sp<AudioPatch> >
+{
+public:
+    status_t addAudioPatch(audio_patch_handle_t handle, const sp<AudioPatch>& patch);
+
+    status_t removeAudioPatch(audio_patch_handle_t handle);
+
+    status_t listAudioPatches(unsigned int *num_patches, struct audio_patch *patches) const;
+
+    status_t dump(int fd) const;
+};
+
+}; // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
new file mode 100644
index 0000000..988aed6
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
@@ -0,0 +1,81 @@
+/*
+ * 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 <utils/RefBase.h>
+#include <media/AudioPolicy.h>
+#include <utils/KeyedVector.h>
+#include <hardware/audio.h>
+#include <utils/String8.h>
+
+namespace android {
+
+class AudioOutputDescriptor;
+
+/**
+ * custom mix entry in mPolicyMixes
+ */
+class AudioPolicyMix : public RefBase {
+public:
+    AudioPolicyMix() {}
+
+    const sp<AudioOutputDescriptor> &getOutput() const;
+
+    void setOutput(sp<AudioOutputDescriptor> &output);
+
+    void clearOutput();
+
+    android::AudioMix &getMix();
+
+    void setMix(AudioMix &mix);
+
+private:
+    AudioMix    mMix;                   // Audio policy mix descriptor
+    sp<AudioOutputDescriptor> mOutput;  // Corresponding output stream
+};
+
+
+class AudioPolicyMixCollection : public DefaultKeyedVector<String8, sp<AudioPolicyMix> >
+{
+public:
+    status_t getAudioPolicyMix(String8 address, sp<AudioPolicyMix> &policyMix) const;
+
+    status_t registerMix(String8 address, AudioMix mix);
+
+    status_t unregisterMix(String8 address);
+
+    void closeOutput(sp<AudioOutputDescriptor> &desc);
+
+    /**
+     * Try to find an output descriptor for the given attributes.
+     *
+     * @param[in] attributes to consider for the research of output descriptor.
+     * @param[out] desc to return if an output could be found.
+     *
+     * @return NO_ERROR if an output was found for the given attribute (in this case, the
+     *                  descriptor output param is initialized), error code otherwise.
+     */
+    status_t getOutputForAttr(audio_attributes_t attributes, sp<AudioOutputDescriptor> &desc);
+
+    audio_devices_t getDeviceAndMixForInputSource(audio_source_t inputSource,
+                                                  audio_devices_t availableDeviceTypes,
+                                                  AudioMix **policyMix);
+
+    status_t getInputMixForAttr(audio_attributes_t attr, AudioMix *&policyMix);
+};
+
+}; // namespace android
diff --git a/services/audiopolicy/managerdefault/Ports.h b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
similarity index 88%
rename from services/audiopolicy/managerdefault/Ports.h
rename to services/audiopolicy/common/managerdefinitions/include/AudioPort.h
index f6e0e93..4f7f2bc 100644
--- a/services/audiopolicy/managerdefault/Ports.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
@@ -14,15 +14,25 @@
  * limitations under the License.
  */
 
+#pragma once
+
+#include <utils/String8.h>
+#include <utils/Vector.h>
+#include <utils/RefBase.h>
+#include <utils/Errors.h>
+#include <system/audio.h>
+#include <cutils/config_utils.h>
+
 namespace android {
 
 class HwModule;
+class AudioGain;
 
-class AudioPort: public virtual RefBase
+class AudioPort : public virtual RefBase
 {
 public:
     AudioPort(const String8& name, audio_port_type_t type,
-            audio_port_role_t role, const sp<HwModule>& module);
+              audio_port_role_t role, const sp<HwModule>& module);
     virtual ~AudioPort() {}
 
     audio_port_handle_t getHandle() { return mId; }
@@ -30,6 +40,8 @@
     void attach(const sp<HwModule>& module);
     bool isAttached() { return mId != 0; }
 
+    static audio_port_handle_t getNextUniqueId();
+
     virtual void toAudioPort(struct audio_port *port) const;
 
     void importAudioPort(const sp<AudioPort> port);
@@ -63,6 +75,8 @@
     static const audio_format_t sPcmFormatCompareTable[];
     static int compareFormats(audio_format_t format1, audio_format_t format2);
 
+    audio_module_handle_t getModuleHandle() const;
+
     void dump(int fd, int spaces) const;
 
     String8           mName;
@@ -86,9 +100,12 @@
     // and a unique ID for identifying a port to the (upcoming) selection API,
     // and its relationship to the mId in AudioOutputDescriptor and AudioInputDescriptor.
     audio_port_handle_t mId;
+
+private:
+    static volatile int32_t mNextUniqueId;
 };
 
-class AudioPortConfig: public virtual RefBase
+class AudioPortConfig : public virtual RefBase
 {
 public:
     AudioPortConfig();
@@ -105,18 +122,4 @@
     struct audio_gain_config mGain;
 };
 
-
-class AudioPatch: public RefBase
-{
-public:
-    AudioPatch(audio_patch_handle_t handle, const struct audio_patch *patch, uid_t uid);
-
-    status_t dump(int fd, int spaces, int index) const;
-
-    audio_patch_handle_t mHandle;
-    struct audio_patch mPatch;
-    uid_t mUid;
-    audio_patch_handle_t mAfPatchHandle;
-};
-
 }; // namespace android
diff --git a/services/audiopolicy/managerdefault/ConfigParsingUtils.h b/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h
similarity index 77%
rename from services/audiopolicy/managerdefault/ConfigParsingUtils.h
rename to services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h
index b2d9763..53cb4a3 100644
--- a/services/audiopolicy/managerdefault/ConfigParsingUtils.h
+++ b/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h
@@ -14,6 +14,19 @@
  * limitations under the License.
  */
 
+#pragma once
+
+#include "DeviceDescriptor.h"
+#include "HwModule.h"
+#include "audio_policy_conf.h"
+#include <system/audio.h>
+#include <utils/Log.h>
+#include <utils/Vector.h>
+#include <utils/SortedVector.h>
+#include <cutils/config_utils.h>
+#include <utils/RefBase.h>
+#include <system/audio_policy.h>
+
 namespace android {
 
 // ----------------------------------------------------------------------------
@@ -156,6 +169,32 @@
     static uint32_t parseOutputFlagNames(char *name);
     static uint32_t parseInputFlagNames(char *name);
     static audio_devices_t parseDeviceNames(char *name);
+
+    static void loadHwModules(cnode *root, HwModuleCollection &hwModules,
+                              DeviceVector &availableInputDevices,
+                              DeviceVector &availableOutputDevices,
+                              sp<DeviceDescriptor> &defaultOutputDevices,
+                              bool &isSpeakerDrcEnabled);
+
+    static void loadGlobalConfig(cnode *root, const sp<HwModule>& module,
+                                 DeviceVector &availableInputDevices,
+                                 DeviceVector &availableOutputDevices,
+                                 sp<DeviceDescriptor> &defaultOutputDevices,
+                                 bool &isSpeakerDrcEnabled);
+
+    static status_t loadAudioPolicyConfig(const char *path,
+                                          HwModuleCollection &hwModules,
+                                          DeviceVector &availableInputDevices,
+                                          DeviceVector &availableOutputDevices,
+                                          sp<DeviceDescriptor> &defaultOutputDevices,
+                                          bool &isSpeakerDrcEnabled);
+
+private:
+    static void loadHwModule(cnode *root, HwModuleCollection &hwModules,
+                             DeviceVector &availableInputDevices,
+                             DeviceVector &availableOutputDevices,
+                             sp<DeviceDescriptor> &defaultOutputDevices,
+                             bool &isSpeakerDrcEnabled);
 };
 
 }; // namespace android
diff --git a/services/audiopolicy/managerdefault/Devices.h b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
similarity index 71%
rename from services/audiopolicy/managerdefault/Devices.h
rename to services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
index af2fbda..d15f6b4 100644
--- a/services/audiopolicy/managerdefault/Devices.h
+++ b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
@@ -14,12 +14,19 @@
  * limitations under the License.
  */
 
+#pragma once
+
+#include "AudioPort.h"
+#include <utils/Errors.h>
+#include <utils/String8.h>
+#include <utils/SortedVector.h>
+#include <cutils/config_utils.h>
+#include <system/audio.h>
+#include <system/audio_policy.h>
+
 namespace android {
 
-class AudioPort;
-class AudioPortConfig;
-
-class DeviceDescriptor: public AudioPort, public AudioPortConfig
+class DeviceDescriptor : public AudioPort, public AudioPortConfig
 {
 public:
     DeviceDescriptor(const String8& name, audio_devices_t type);
@@ -37,12 +44,18 @@
     virtual void loadGains(cnode *root);
     virtual void toAudioPort(struct audio_port *port) const;
 
+    audio_devices_t type() const { return mDeviceType; }
     status_t dump(int fd, int spaces, int index) const;
 
-    audio_devices_t mDeviceType;
     String8 mAddress;
+    audio_port_handle_t mId;
 
     static String8  emptyNameStr;
+
+private:
+    audio_devices_t mDeviceType;
+
+friend class DeviceVector;
 };
 
 class DeviceVector : public SortedVector< sp<DeviceDescriptor> >
@@ -50,9 +63,9 @@
 public:
     DeviceVector() : SortedVector(), mDeviceTypes(AUDIO_DEVICE_NONE) {}
 
-    ssize_t         add(const sp<DeviceDescriptor>& item);
-    ssize_t         remove(const sp<DeviceDescriptor>& item);
-    ssize_t         indexOf(const sp<DeviceDescriptor>& item) const;
+    ssize_t add(const sp<DeviceDescriptor>& item);
+    ssize_t remove(const sp<DeviceDescriptor>& item);
+    ssize_t indexOf(const sp<DeviceDescriptor>& item) const;
 
     audio_devices_t types() const { return mDeviceTypes; }
 
@@ -63,8 +76,13 @@
     DeviceVector getDevicesFromType(audio_devices_t types) const;
     sp<DeviceDescriptor> getDeviceFromId(audio_port_handle_t id) const;
     sp<DeviceDescriptor> getDeviceFromName(const String8& name) const;
-    DeviceVector getDevicesFromTypeAddr(audio_devices_t type, String8 address)
-    const;
+    DeviceVector getDevicesFromTypeAddr(audio_devices_t type, String8 address) const;
+
+    audio_devices_t getDevicesFromHwModule(audio_module_handle_t moduleHandle) const;
+
+    audio_policy_dev_state_t getDeviceConnectionState(const sp<DeviceDescriptor> &devDesc) const;
+
+    status_t dump(int fd, const String8 &direction) const;
 
 private:
     void refreshTypes();
diff --git a/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
new file mode 100644
index 0000000..c9783a1
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
@@ -0,0 +1,71 @@
+/*
+ * 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 <RoutingStrategy.h>
+#include <hardware/audio_effect.h>
+#include <utils/KeyedVector.h>
+#include <utils/RefBase.h>
+#include <utils/Errors.h>
+
+namespace android {
+
+
+class EffectDescriptor : public RefBase
+{
+public:
+    status_t dump(int fd);
+
+    int mIo;                // io the effect is attached to
+    routing_strategy mStrategy; // routing strategy the effect is associated to
+    int mSession;               // audio session the effect is on
+    effect_descriptor_t mDesc;  // effect descriptor
+    bool mEnabled;              // enabled state: CPU load being used or not
+};
+
+class EffectDescriptorCollection : public KeyedVector<int, sp<EffectDescriptor> >
+{
+public:
+    EffectDescriptorCollection();
+
+    status_t registerEffect(const effect_descriptor_t *desc, audio_io_handle_t io,
+                            uint32_t strategy, int session, int id);
+    status_t unregisterEffect(int id);
+    status_t setEffectEnabled(int id, bool enabled);
+    uint32_t getMaxEffectsCpuLoad() const;
+    uint32_t getMaxEffectsMemory() const;
+    bool isNonOffloadableEffectEnabled();
+
+    status_t dump(int fd);
+
+private:
+    status_t setEffectEnabled(const sp<EffectDescriptor> &effectDesc, bool enabled);
+
+    uint32_t mTotalEffectsCpuLoad; // current CPU load used by effects
+    uint32_t mTotalEffectsMemory;  // current memory used by effects
+
+    /**
+     * Maximum CPU load allocated to audio effects in 0.1 MIPS (ARMv5TE, 0 WS memory) units
+     */
+    static const uint32_t MAX_EFFECTS_CPU_LOAD = 1000;
+    /**
+     * Maximum memory allocated to audio effects in KB
+     */
+    static const uint32_t MAX_EFFECTS_MEMORY = 512;
+};
+
+}; // namespace android
diff --git a/services/audiopolicy/managerdefault/HwModule.h b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
similarity index 69%
rename from services/audiopolicy/managerdefault/HwModule.h
rename to services/audiopolicy/common/managerdefinitions/include/HwModule.h
index f814dd9..92c3ea2 100644
--- a/services/audiopolicy/managerdefault/HwModule.h
+++ b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
@@ -14,8 +14,20 @@
  * limitations under the License.
  */
 
+#pragma once
+
+#include "DeviceDescriptor.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>
+
 namespace android {
 
+class IOProfile;
+
 class HwModule : public RefBase
 {
 public:
@@ -33,6 +45,8 @@
             audio_devices_t device, String8 address);
     status_t removeInputProfile(String8 name);
 
+    audio_module_handle_t getHandle() const { return mHandle; }
+
     void dump(int fd);
 
     const char *const        mName; // base name of the audio HW module (primary, a2dp ...)
@@ -43,4 +57,18 @@
     DeviceVector             mDeclaredDevices; // devices declared in audio_policy.conf
 };
 
+class HwModuleCollection : public Vector< sp<HwModule> >
+{
+public:
+    sp<HwModule> getModuleFromName(const char *name) const;
+
+    sp <HwModule> getModuleForDevice(audio_devices_t device) const;
+
+    sp<DeviceDescriptor>  getDeviceDescriptor(const audio_devices_t device,
+                                              const char *device_address,
+                                              const char *device_name) const;
+
+    status_t dump(int fd) const;
+};
+
 }; // namespace android
diff --git a/services/audiopolicy/managerdefault/IOProfile.h b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
similarity index 94%
rename from services/audiopolicy/managerdefault/IOProfile.h
rename to services/audiopolicy/common/managerdefinitions/include/IOProfile.h
index 3317969..095e759 100644
--- a/services/audiopolicy/managerdefault/IOProfile.h
+++ b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
@@ -14,6 +14,13 @@
  * limitations under the License.
  */
 
+#pragma once
+
+#include "AudioPort.h"
+#include "DeviceDescriptor.h"
+#include <utils/String8.h>
+#include <system/audio.h>
+
 namespace android {
 
 class HwModule;
diff --git a/services/audiopolicy/managerdefault/ApmImplDefinitions.h b/services/audiopolicy/common/managerdefinitions/include/SoundTriggerSession.h
similarity index 63%
copy from services/audiopolicy/managerdefault/ApmImplDefinitions.h
copy to services/audiopolicy/common/managerdefinitions/include/SoundTriggerSession.h
index 620979b..420e6d7 100644
--- a/services/audiopolicy/managerdefault/ApmImplDefinitions.h
+++ b/services/audiopolicy/common/managerdefinitions/include/SoundTriggerSession.h
@@ -14,19 +14,20 @@
  * limitations under the License.
  */
 
+#pragma once
+
+#include <system/audio.h>
+#include <utils/Errors.h>
+#include <utils/KeyedVector.h>
+
 namespace android {
 
-enum routing_strategy {
-    STRATEGY_MEDIA,
-    STRATEGY_PHONE,
-    STRATEGY_SONIFICATION,
-    STRATEGY_SONIFICATION_RESPECTFUL,
-    STRATEGY_DTMF,
-    STRATEGY_ENFORCED_AUDIBLE,
-    STRATEGY_TRANSMITTED_THROUGH_SPEAKER,
-    STRATEGY_ACCESSIBILITY,
-    STRATEGY_REROUTING,
-    NUM_STRATEGIES
+class SoundTriggerSessionCollection : public DefaultKeyedVector<audio_session_t, audio_io_handle_t>
+{
+public:
+    status_t releaseSession(audio_session_t session);
+
+    status_t acquireSession(audio_session_t session, audio_io_handle_t ioHandle);
 };
 
-}; //namespace android
+}; // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/StreamDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/StreamDescriptor.h
new file mode 100644
index 0000000..84db5ab
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/include/StreamDescriptor.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <Volume.h>
+#include <utils/KeyedVector.h>
+#include <utils/StrongPointer.h>
+#include <utils/SortedVector.h>
+#include <hardware/audio.h>
+
+namespace android {
+
+// stream descriptor used for volume control
+class StreamDescriptor
+{
+public:
+    StreamDescriptor();
+
+    int getVolumeIndex(audio_devices_t device) const;
+    bool canBeMuted() const { return mCanBeMuted; }
+    void clearCurrentVolumeIndex();
+    void addCurrentVolumeIndex(audio_devices_t device, int index);
+    int getVolumeIndexMin() const { return mIndexMin; }
+    int getVolumeIndexMax() const { return mIndexMax; }
+    void setVolumeIndexMin(int volIndexMin);
+    void setVolumeIndexMax(int volIndexMax);
+
+    void dump(int fd) const;
+
+    void setVolumeCurvePoint(Volume::device_category deviceCategory, const VolumeCurvePoint *point);
+    const VolumeCurvePoint *getVolumeCurvePoint(Volume::device_category deviceCategory) const
+    {
+        return mVolumeCurve[deviceCategory];
+    }
+
+private:
+    const VolumeCurvePoint *mVolumeCurve[Volume::DEVICE_CATEGORY_CNT];
+    KeyedVector<audio_devices_t, int> mIndexCur; /**< current volume index per device. */
+    int mIndexMin; /**< min volume index. */
+    int mIndexMax; /**< max volume index. */
+    bool mCanBeMuted; /**< true is the stream can be muted. */
+};
+
+/**
+ * stream descriptors collection for volume control
+ */
+class StreamDescriptorCollection : public DefaultKeyedVector<audio_stream_type_t, StreamDescriptor>
+{
+public:
+    StreamDescriptorCollection();
+
+    void clearCurrentVolumeIndex(audio_stream_type_t stream);
+    void addCurrentVolumeIndex(audio_stream_type_t stream, audio_devices_t device, int index);
+
+    bool canBeMuted(audio_stream_type_t stream);
+
+    status_t dump(int fd) const;
+
+    void setVolumeCurvePoint(audio_stream_type_t stream,
+                             Volume::device_category deviceCategory,
+                             const VolumeCurvePoint *point);
+
+    const VolumeCurvePoint *getVolumeCurvePoint(audio_stream_type_t stream,
+                                                Volume::device_category deviceCategory) const;
+
+    void setVolumeIndexMin(audio_stream_type_t stream,int volIndexMin);
+    void setVolumeIndexMax(audio_stream_type_t stream,int volIndexMax);
+
+};
+
+}; // namespace android
diff --git a/services/audiopolicy/managerdefault/audio_policy_conf.h b/services/audiopolicy/common/managerdefinitions/include/audio_policy_conf.h
similarity index 91%
rename from services/audiopolicy/managerdefault/audio_policy_conf.h
rename to services/audiopolicy/common/managerdefinitions/include/audio_policy_conf.h
index 2535a67..a393e3b 100644
--- a/services/audiopolicy/managerdefault/audio_policy_conf.h
+++ b/services/audiopolicy/common/managerdefinitions/include/audio_policy_conf.h
@@ -14,9 +14,7 @@
  * limitations under the License.
  */
 
-
-#ifndef ANDROID_AUDIO_POLICY_CONF_H
-#define ANDROID_AUDIO_POLICY_CONF_H
+#pragma once
 
 
 /////////////////////////////////////////////////
@@ -53,9 +51,9 @@
                                     // "formats" in outputs descriptors indicating that supported
                                     // values should be queried after opening the output.
 
-#define DEVICES_TAG "devices"
-#define DEVICE_TYPE "type"
-#define DEVICE_ADDRESS "address"
+#define APM_DEVICES_TAG "devices"
+#define APM_DEVICE_TYPE "type"
+#define APM_DEVICE_ADDRESS "address"
 
 #define MIXERS_TAG "mixers"
 #define MIXER_TYPE "type"
@@ -71,7 +69,3 @@
 #define GAIN_STEP_VALUE "step_value_mB"
 #define GAIN_MIN_RAMP_MS "min_ramp_ms"
 #define GAIN_MAX_RAMP_MS "max_ramp_ms"
-
-
-
-#endif  // ANDROID_AUDIO_POLICY_CONF_H
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioGain.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioGain.cpp
new file mode 100644
index 0000000..fc7b0cc
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioGain.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "APM::AudioGain"
+//#define LOG_NDEBUG 0
+
+//#define VERY_VERBOSE_LOGGING
+#ifdef VERY_VERBOSE_LOGGING
+#define ALOGVV ALOGV
+#else
+#define ALOGVV(a...) do { } while(0)
+#endif
+
+#include "AudioGain.h"
+#include "StreamDescriptor.h"
+#include <utils/Log.h>
+#include <utils/String8.h>
+
+#include <math.h>
+
+namespace android {
+
+AudioGain::AudioGain(int index, bool useInChannelMask)
+{
+    mIndex = index;
+    mUseInChannelMask = useInChannelMask;
+    memset(&mGain, 0, sizeof(struct audio_gain));
+}
+
+void AudioGain::getDefaultConfig(struct audio_gain_config *config)
+{
+    config->index = mIndex;
+    config->mode = mGain.mode;
+    config->channel_mask = mGain.channel_mask;
+    if ((mGain.mode & AUDIO_GAIN_MODE_JOINT) == AUDIO_GAIN_MODE_JOINT) {
+        config->values[0] = mGain.default_value;
+    } else {
+        uint32_t numValues;
+        if (mUseInChannelMask) {
+            numValues = audio_channel_count_from_in_mask(mGain.channel_mask);
+        } else {
+            numValues = audio_channel_count_from_out_mask(mGain.channel_mask);
+        }
+        for (size_t i = 0; i < numValues; i++) {
+            config->values[i] = mGain.default_value;
+        }
+    }
+    if ((mGain.mode & AUDIO_GAIN_MODE_RAMP) == AUDIO_GAIN_MODE_RAMP) {
+        config->ramp_duration_ms = mGain.min_ramp_ms;
+    }
+}
+
+status_t AudioGain::checkConfig(const struct audio_gain_config *config)
+{
+    if ((config->mode & ~mGain.mode) != 0) {
+        return BAD_VALUE;
+    }
+    if ((config->mode & AUDIO_GAIN_MODE_JOINT) == AUDIO_GAIN_MODE_JOINT) {
+        if ((config->values[0] < mGain.min_value) ||
+                    (config->values[0] > mGain.max_value)) {
+            return BAD_VALUE;
+        }
+    } else {
+        if ((config->channel_mask & ~mGain.channel_mask) != 0) {
+            return BAD_VALUE;
+        }
+        uint32_t numValues;
+        if (mUseInChannelMask) {
+            numValues = audio_channel_count_from_in_mask(config->channel_mask);
+        } else {
+            numValues = audio_channel_count_from_out_mask(config->channel_mask);
+        }
+        for (size_t i = 0; i < numValues; i++) {
+            if ((config->values[i] < mGain.min_value) ||
+                    (config->values[i] > mGain.max_value)) {
+                return BAD_VALUE;
+            }
+        }
+    }
+    if ((config->mode & AUDIO_GAIN_MODE_RAMP) == AUDIO_GAIN_MODE_RAMP) {
+        if ((config->ramp_duration_ms < mGain.min_ramp_ms) ||
+                    (config->ramp_duration_ms > mGain.max_ramp_ms)) {
+            return BAD_VALUE;
+        }
+    }
+    return NO_ERROR;
+}
+
+void AudioGain::dump(int fd, int spaces, int index) const
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    snprintf(buffer, SIZE, "%*sGain %d:\n", spaces, "", index+1);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "%*s- mode: %08x\n", spaces, "", mGain.mode);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "%*s- channel_mask: %08x\n", spaces, "", mGain.channel_mask);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "%*s- min_value: %d mB\n", spaces, "", mGain.min_value);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "%*s- max_value: %d mB\n", spaces, "", mGain.max_value);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "%*s- default_value: %d mB\n", spaces, "", mGain.default_value);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "%*s- step_value: %d mB\n", spaces, "", mGain.step_value);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "%*s- min_ramp_ms: %d ms\n", spaces, "", mGain.min_ramp_ms);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "%*s- max_ramp_ms: %d ms\n", spaces, "", mGain.max_ramp_ms);
+    result.append(buffer);
+
+    write(fd, result.string(), result.size());
+}
+
+}; // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
new file mode 100644
index 0000000..fa66728
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "APM::AudioInputDescriptor"
+//#define LOG_NDEBUG 0
+
+#include "AudioInputDescriptor.h"
+#include "IOProfile.h"
+#include "AudioGain.h"
+#include "HwModule.h"
+#include <media/AudioPolicy.h>
+#include <policy.h>
+
+namespace android {
+
+AudioInputDescriptor::AudioInputDescriptor(const sp<IOProfile>& profile)
+    : mId(0), mIoHandle(0),
+      mDevice(AUDIO_DEVICE_NONE), mPolicyMix(NULL), mPatchHandle(0), mRefCount(0),
+      mInputSource(AUDIO_SOURCE_DEFAULT), mProfile(profile), mIsSoundTrigger(false)
+{
+    if (profile != NULL) {
+        mSamplingRate = profile->pickSamplingRate();
+        mFormat = profile->pickFormat();
+        mChannelMask = profile->pickChannelMask();
+        if (profile->mGains.size() > 0) {
+            profile->mGains[0]->getDefaultConfig(&mGain);
+        }
+    }
+}
+
+void AudioInputDescriptor::setIoHandle(audio_io_handle_t ioHandle)
+{
+    mId = AudioPort::getNextUniqueId();
+    mIoHandle = ioHandle;
+}
+
+audio_module_handle_t AudioInputDescriptor::getModuleHandle() const
+{
+    return mProfile->getModuleHandle();
+}
+
+void AudioInputDescriptor::toAudioPortConfig(struct audio_port_config *dstConfig,
+                                             const struct audio_port_config *srcConfig) const
+{
+    ALOG_ASSERT(mProfile != 0,
+                "toAudioPortConfig() called on input with null profile %d", mIoHandle);
+    dstConfig->config_mask = AUDIO_PORT_CONFIG_SAMPLE_RATE|AUDIO_PORT_CONFIG_CHANNEL_MASK|
+                            AUDIO_PORT_CONFIG_FORMAT|AUDIO_PORT_CONFIG_GAIN;
+    if (srcConfig != NULL) {
+        dstConfig->config_mask |= srcConfig->config_mask;
+    }
+
+    AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig);
+
+    dstConfig->id = mId;
+    dstConfig->role = AUDIO_PORT_ROLE_SINK;
+    dstConfig->type = AUDIO_PORT_TYPE_MIX;
+    dstConfig->ext.mix.hw_module = mProfile->mModule->mHandle;
+    dstConfig->ext.mix.handle = mIoHandle;
+    dstConfig->ext.mix.usecase.source = mInputSource;
+}
+
+void AudioInputDescriptor::toAudioPort(struct audio_port *port) const
+{
+    ALOG_ASSERT(mProfile != 0, "toAudioPort() called on input with null profile %d", mIoHandle);
+
+    mProfile->toAudioPort(port);
+    port->id = mId;
+    toAudioPortConfig(&port->active_config);
+    port->ext.mix.hw_module = mProfile->mModule->mHandle;
+    port->ext.mix.handle = mIoHandle;
+    port->ext.mix.latency_class = AUDIO_LATENCY_NORMAL;
+}
+
+status_t AudioInputDescriptor::dump(int fd)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    snprintf(buffer, SIZE, " ID: %d\n", mId);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Format: %d\n", mFormat);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Channels: %08x\n", mChannelMask);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Devices %08x\n", mDevice);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Ref Count %d\n", mRefCount);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Open Ref Count %d\n", mOpenRefCount);
+    result.append(buffer);
+
+    write(fd, result.string(), result.size());
+
+    return NO_ERROR;
+}
+
+bool AudioInputCollection::isSourceActive(audio_source_t source) const
+{
+    for (size_t i = 0; i < size(); i++) {
+        const sp<AudioInputDescriptor>  inputDescriptor = valueAt(i);
+        if (inputDescriptor->mRefCount == 0) {
+            continue;
+        }
+        if (inputDescriptor->mInputSource == (int)source) {
+            return true;
+        }
+    }
+    return false;
+}
+
+sp<AudioInputDescriptor> AudioInputCollection::getInputFromId(audio_port_handle_t id) const
+{
+    sp<AudioInputDescriptor> inputDesc = NULL;
+    for (size_t i = 0; i < size(); i++) {
+        inputDesc = valueAt(i);
+        if (inputDesc->mId == id) {
+            break;
+        }
+    }
+    return inputDesc;
+}
+
+uint32_t AudioInputCollection::activeInputsCount() const
+{
+    uint32_t count = 0;
+    for (size_t i = 0; i < size(); i++) {
+        const sp<AudioInputDescriptor>  desc = valueAt(i);
+        if (desc->mRefCount > 0) {
+            count++;
+        }
+    }
+    return count;
+}
+
+audio_io_handle_t AudioInputCollection::getActiveInput(bool ignoreVirtualInputs)
+{
+    for (size_t i = 0; i < size(); i++) {
+        const sp<AudioInputDescriptor>  input_descriptor = valueAt(i);
+        if ((input_descriptor->mRefCount > 0)
+                && (!ignoreVirtualInputs || !is_virtual_input_device(input_descriptor->mDevice))) {
+            return keyAt(i);
+        }
+    }
+    return 0;
+}
+
+audio_devices_t AudioInputCollection::getSupportedDevices(audio_io_handle_t handle) const
+{
+    sp<AudioInputDescriptor> inputDesc = valueFor(handle);
+    audio_devices_t devices = inputDesc->mProfile->mSupportedDevices.types();
+    return devices;
+}
+
+status_t AudioInputCollection::dump(int fd) const
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+
+    snprintf(buffer, SIZE, "\nInputs dump:\n");
+    write(fd, buffer, strlen(buffer));
+    for (size_t i = 0; i < size(); i++) {
+        snprintf(buffer, SIZE, "- Input %d dump:\n", keyAt(i));
+        write(fd, buffer, strlen(buffer));
+        valueAt(i)->dump(fd);
+    }
+
+    return NO_ERROR;
+}
+
+}; //namespace android
diff --git a/services/audiopolicy/managerdefault/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
similarity index 61%
rename from services/audiopolicy/managerdefault/AudioOutputDescriptor.cpp
rename to services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 4b85972..cdb5b51 100644
--- a/services/audiopolicy/managerdefault/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -17,12 +17,19 @@
 #define LOG_TAG "APM::AudioOutputDescriptor"
 //#define LOG_NDEBUG 0
 
-#include "AudioPolicyManager.h"
+#include "AudioOutputDescriptor.h"
+#include "IOProfile.h"
+#include "AudioGain.h"
+#include "HwModule.h"
+#include <media/AudioPolicy.h>
+
+// A device mask for all audio output devices that are considered "remote" when evaluating
+// active output devices in isStreamActiveRemotely()
+#define APM_AUDIO_OUT_DEVICE_REMOTE_ALL  AUDIO_DEVICE_OUT_REMOTE_SUBMIX
 
 namespace android {
 
-AudioOutputDescriptor::AudioOutputDescriptor(
-        const sp<IOProfile>& profile)
+AudioOutputDescriptor::AudioOutputDescriptor(const sp<IOProfile>& profile)
     : mId(0), mIoHandle(0), mLatency(0),
     mFlags((audio_output_flags_t)0), mDevice(AUDIO_DEVICE_NONE), mPolicyMix(NULL),
     mPatchHandle(0),
@@ -49,6 +56,11 @@
     }
 }
 
+audio_module_handle_t AudioOutputDescriptor::getModuleHandle() const
+{
+    return mProfile->getModuleHandle();
+}
+
 audio_devices_t AudioOutputDescriptor::device() const
 {
     if (isDuplicated()) {
@@ -58,6 +70,12 @@
     }
 }
 
+void AudioOutputDescriptor::setIoHandle(audio_io_handle_t ioHandle)
+{
+    mId = AudioPort::getNextUniqueId();
+    mIoHandle = ioHandle;
+}
+
 uint32_t AudioOutputDescriptor::latency()
 {
     if (isDuplicated()) {
@@ -108,23 +126,15 @@
 
 bool AudioOutputDescriptor::isActive(uint32_t inPastMs) const
 {
-    return isStrategyActive(NUM_STRATEGIES, inPastMs);
-}
-
-bool AudioOutputDescriptor::isStrategyActive(routing_strategy strategy,
-                                                                       uint32_t inPastMs,
-                                                                       nsecs_t sysTime) const
-{
-    if ((sysTime == 0) && (inPastMs != 0)) {
+    nsecs_t sysTime = 0;
+    if (inPastMs != 0) {
         sysTime = systemTime();
     }
     for (int i = 0; i < (int)AUDIO_STREAM_CNT; i++) {
         if (i == AUDIO_STREAM_PATCH) {
             continue;
         }
-        if (((AudioPolicyManager::getStrategy((audio_stream_type_t)i) == strategy) ||
-                (NUM_STRATEGIES == strategy)) &&
-                isStreamActive((audio_stream_type_t)i, inPastMs, sysTime)) {
+        if (isStreamActive((audio_stream_type_t)i, inPastMs, sysTime)) {
             return true;
         }
     }
@@ -132,8 +142,8 @@
 }
 
 bool AudioOutputDescriptor::isStreamActive(audio_stream_type_t stream,
-                                                                       uint32_t inPastMs,
-                                                                       nsecs_t sysTime) const
+                                           uint32_t inPastMs,
+                                           nsecs_t sysTime) const
 {
     if (mRefCount[stream] != 0) {
         return true;
@@ -216,6 +226,108 @@
     return NO_ERROR;
 }
 
+bool AudioOutputCollection::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const
+{
+    nsecs_t sysTime = systemTime();
+    for (size_t i = 0; i < this->size(); i++) {
+        const sp<AudioOutputDescriptor> outputDesc = this->valueAt(i);
+        if (outputDesc->isStreamActive(stream, inPastMs, sysTime)) {
+            return true;
+        }
+    }
+    return false;
+}
 
+bool AudioOutputCollection::isStreamActiveRemotely(audio_stream_type_t stream,
+                                                   uint32_t inPastMs) const
+{
+    nsecs_t sysTime = systemTime();
+    for (size_t i = 0; i < size(); i++) {
+        const sp<AudioOutputDescriptor> outputDesc = valueAt(i);
+        if (((outputDesc->device() & APM_AUDIO_OUT_DEVICE_REMOTE_ALL) != 0) &&
+                outputDesc->isStreamActive(stream, inPastMs, sysTime)) {
+            // do not consider re routing (when the output is going to a dynamic policy)
+            // as "remote playback"
+            if (outputDesc->mPolicyMix == NULL) {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+audio_io_handle_t AudioOutputCollection::getA2dpOutput() const
+{
+    for (size_t i = 0; i < size(); i++) {
+        sp<AudioOutputDescriptor> outputDesc = valueAt(i);
+        if (!outputDesc->isDuplicated() && outputDesc->device() & AUDIO_DEVICE_OUT_ALL_A2DP) {
+            return this->keyAt(i);
+        }
+    }
+    return 0;
+}
+
+sp<AudioOutputDescriptor> AudioOutputCollection::getPrimaryOutput() const
+{
+    for (size_t i = 0; i < size(); i++) {
+        const sp<AudioOutputDescriptor> outputDesc = valueAt(i);
+        if (outputDesc->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY) {
+            return outputDesc;
+        }
+    }
+    return NULL;
+}
+
+sp<AudioOutputDescriptor> AudioOutputCollection::getOutputFromId(audio_port_handle_t id) const
+{
+    sp<AudioOutputDescriptor> outputDesc = NULL;
+    for (size_t i = 0; i < size(); i++) {
+        outputDesc = valueAt(i);
+        if (outputDesc->mId == id) {
+            break;
+        }
+    }
+    return outputDesc;
+}
+
+bool AudioOutputCollection::isAnyOutputActive(audio_stream_type_t streamToIgnore) const
+{
+    for (size_t s = 0 ; s < AUDIO_STREAM_CNT ; s++) {
+        if (s == (size_t) streamToIgnore) {
+            continue;
+        }
+        for (size_t i = 0; i < size(); i++) {
+            const sp<AudioOutputDescriptor> outputDesc = valueAt(i);
+            if (outputDesc->mRefCount[s] != 0) {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+audio_devices_t AudioOutputCollection::getSupportedDevices(audio_io_handle_t handle) const
+{
+    sp<AudioOutputDescriptor> outputDesc = valueFor(handle);
+    audio_devices_t devices = outputDesc->mProfile->mSupportedDevices.types();
+    return devices;
+}
+
+
+status_t AudioOutputCollection::dump(int fd) const
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+
+    snprintf(buffer, SIZE, "\nOutputs dump:\n");
+    write(fd, buffer, strlen(buffer));
+    for (size_t i = 0; i < size(); i++) {
+        snprintf(buffer, SIZE, "- Output %d dump:\n", keyAt(i));
+        write(fd, buffer, strlen(buffer));
+        valueAt(i)->dump(fd);
+    }
+
+    return NO_ERROR;
+}
 
 }; //namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp
new file mode 100644
index 0000000..3a317fa
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "APM::AudioPatch"
+//#define LOG_NDEBUG 0
+
+#include "AudioPatch.h"
+#include "AudioGain.h"
+#include "ConfigParsingUtils.h"
+#include <cutils/log.h>
+#include <utils/String8.h>
+
+namespace android {
+
+int32_t volatile AudioPatch::mNextUniqueId = 1;
+
+AudioPatch::AudioPatch(const struct audio_patch *patch, uid_t uid) :
+    mHandle(static_cast<audio_patch_handle_t>(android_atomic_inc(&mNextUniqueId))),
+    mPatch(*patch),
+    mUid(uid),
+    mAfPatchHandle(0)
+{
+}
+
+status_t AudioPatch::dump(int fd, int spaces, int index) const
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    snprintf(buffer, SIZE, "%*sAudio patch %d:\n", spaces, "", index+1);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "%*s- handle: %2d\n", spaces, "", mHandle);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "%*s- audio flinger handle: %2d\n", spaces, "", mAfPatchHandle);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "%*s- owner uid: %2d\n", spaces, "", mUid);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "%*s- %d sources:\n", spaces, "", mPatch.num_sources);
+    result.append(buffer);
+    for (size_t i = 0; i < mPatch.num_sources; i++) {
+        if (mPatch.sources[i].type == AUDIO_PORT_TYPE_DEVICE) {
+            snprintf(buffer, SIZE, "%*s- Device ID %d %s\n", spaces + 2, "",
+                     mPatch.sources[i].id, ConfigParsingUtils::enumToString(sDeviceNameToEnumTable,
+                                                        ARRAY_SIZE(sDeviceNameToEnumTable),
+                                                        mPatch.sources[i].ext.device.type));
+        } 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);
+        }
+        result.append(buffer);
+    }
+    snprintf(buffer, SIZE, "%*s- %d sinks:\n", spaces, "", mPatch.num_sinks);
+    result.append(buffer);
+    for (size_t i = 0; i < mPatch.num_sinks; i++) {
+        if (mPatch.sinks[i].type == AUDIO_PORT_TYPE_DEVICE) {
+            snprintf(buffer, SIZE, "%*s- Device ID %d %s\n", spaces + 2, "",
+                     mPatch.sinks[i].id, ConfigParsingUtils::enumToString(sDeviceNameToEnumTable,
+                                                        ARRAY_SIZE(sDeviceNameToEnumTable),
+                                                        mPatch.sinks[i].ext.device.type));
+        } 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);
+        }
+        result.append(buffer);
+    }
+
+    write(fd, result.string(), result.size());
+    return NO_ERROR;
+}
+
+status_t AudioPatchCollection::addAudioPatch(audio_patch_handle_t handle,
+                                             const sp<AudioPatch>& patch)
+{
+    ssize_t index = indexOfKey(handle);
+
+    if (index >= 0) {
+        ALOGW("addAudioPatch() patch %d already in", handle);
+        return ALREADY_EXISTS;
+    }
+    add(handle, patch);
+    ALOGV("addAudioPatch() handle %d af handle %d num_sources %d num_sinks %d source handle %d"
+            "sink handle %d",
+          handle, patch->mAfPatchHandle, patch->mPatch.num_sources, patch->mPatch.num_sinks,
+          patch->mPatch.sources[0].id, patch->mPatch.sinks[0].id);
+    return NO_ERROR;
+}
+
+status_t AudioPatchCollection::removeAudioPatch(audio_patch_handle_t handle)
+{
+    ssize_t index = indexOfKey(handle);
+
+    if (index < 0) {
+        ALOGW("removeAudioPatch() patch %d not in", handle);
+        return ALREADY_EXISTS;
+    }
+    ALOGV("removeAudioPatch() handle %d af handle %d", handle, valueAt(index)->mAfPatchHandle);
+    removeItemsAt(index);
+    return NO_ERROR;
+}
+
+status_t AudioPatchCollection::listAudioPatches(unsigned int *num_patches,
+                                                struct audio_patch *patches) const
+{
+    if (num_patches == NULL || (*num_patches != 0 && patches == NULL)) {
+        return BAD_VALUE;
+    }
+    ALOGV("listAudioPatches() num_patches %d patches %p available patches %zu",
+          *num_patches, patches, size());
+    if (patches == NULL) {
+        *num_patches = 0;
+    }
+
+    size_t patchesWritten = 0;
+    size_t patchesMax = *num_patches;
+    for (size_t i = 0; i  < size() && patchesWritten < patchesMax; i++) {
+        const sp<AudioPatch>  patch = valueAt(i);
+        patches[patchesWritten] = patch->mPatch;
+        patches[patchesWritten++].id = patch->mHandle;
+        ALOGV("listAudioPatches() patch %zu num_sources %d num_sinks %d",
+              i, patch->mPatch.num_sources, patch->mPatch.num_sinks);
+    }
+    *num_patches = size();
+
+    ALOGV("listAudioPatches() got %zu patches needed %d", patchesWritten, *num_patches);
+    return NO_ERROR;
+}
+
+status_t AudioPatchCollection::dump(int fd) const
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    snprintf(buffer, SIZE, "\nAudio Patches:\n");
+    write(fd, buffer, strlen(buffer));
+    for (size_t i = 0; i < size(); i++) {
+        valueAt(i)->dump(fd, 2, i);
+    }
+    return NO_ERROR;
+}
+
+}; // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
new file mode 100644
index 0000000..84a53ebd
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "APM::AudioPolicyMix"
+//#define LOG_NDEBUG 0
+
+#include "AudioPolicyMix.h"
+#include "HwModule.h"
+#include "AudioPort.h"
+#include "IOProfile.h"
+#include "AudioGain.h"
+#include <AudioOutputDescriptor.h>
+
+namespace android {
+
+void AudioPolicyMix::setOutput(sp<AudioOutputDescriptor> &output)
+{
+    mOutput = output;
+}
+
+const sp<AudioOutputDescriptor> &AudioPolicyMix::getOutput() const
+{
+    return mOutput;
+}
+
+void AudioPolicyMix::clearOutput()
+{
+    mOutput.clear();
+}
+
+void AudioPolicyMix::setMix(AudioMix &mix)
+{
+    mMix = mix;
+}
+
+android::AudioMix &AudioPolicyMix::getMix()
+{
+    return mMix;
+}
+
+status_t AudioPolicyMixCollection::registerMix(String8 address, AudioMix mix)
+{
+    ssize_t index = indexOfKey(address);
+    if (index >= 0) {
+        ALOGE("registerPolicyMixes(): mix for address %s already registered", address.string());
+        return BAD_VALUE;
+    }
+    sp<AudioPolicyMix> policyMix = new AudioPolicyMix();
+    policyMix->setMix(mix);
+    add(address, policyMix);
+    return NO_ERROR;
+}
+
+status_t AudioPolicyMixCollection::unregisterMix(String8 address)
+{
+    ssize_t index = indexOfKey(address);
+    if (index < 0) {
+        ALOGE("unregisterPolicyMixes(): mix for address %s not registered", address.string());
+        return BAD_VALUE;
+    }
+
+    removeItemsAt(index);
+    return NO_ERROR;
+}
+
+status_t AudioPolicyMixCollection::getAudioPolicyMix(String8 address,
+                                                     sp<AudioPolicyMix> &policyMix) const
+{
+    ssize_t index = indexOfKey(address);
+    if (index < 0) {
+        ALOGE("unregisterPolicyMixes(): mix for address %s not registered", address.string());
+        return BAD_VALUE;
+    }
+    policyMix = valueAt(index);
+    return NO_ERROR;
+}
+
+void AudioPolicyMixCollection::closeOutput(sp<AudioOutputDescriptor> &desc)
+{
+    for (size_t i = 0; i < size(); i++) {
+        sp<AudioPolicyMix> policyMix = valueAt(i);
+        if (policyMix->getOutput() == desc) {
+            policyMix->clearOutput();
+        }
+    }
+}
+
+status_t AudioPolicyMixCollection::getOutputForAttr(audio_attributes_t attributes,
+                                                    sp<AudioOutputDescriptor> &desc)
+{
+    for (size_t i = 0; i < size(); i++) {
+        sp<AudioPolicyMix> policyMix = valueAt(i);
+        AudioMix mix = policyMix->getMix();
+
+        if (mix.mMixType == MIX_TYPE_PLAYERS) {
+            for (size_t j = 0; j < mix.mCriteria.size(); j++) {
+                if ((RULE_MATCH_ATTRIBUTE_USAGE == mix.mCriteria[j].mRule &&
+                     mix.mCriteria[j].mAttr.mUsage == attributes.usage) ||
+                        (RULE_EXCLUDE_ATTRIBUTE_USAGE == mix.mCriteria[j].mRule &&
+                         mix.mCriteria[j].mAttr.mUsage != attributes.usage)) {
+                    desc = policyMix->getOutput();
+                    break;
+                }
+                if (strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 &&
+                        strncmp(attributes.tags + strlen("addr="),
+                                mix.mRegistrationId.string(),
+                                AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) {
+                    desc = policyMix->getOutput();
+                    break;
+                }
+            }
+        } else if (mix.mMixType == MIX_TYPE_RECORDERS) {
+            if (attributes.usage == AUDIO_USAGE_VIRTUAL_SOURCE &&
+                    strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 &&
+                    strncmp(attributes.tags + strlen("addr="),
+                            mix.mRegistrationId.string(),
+                            AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) {
+                desc = policyMix->getOutput();
+            }
+        }
+        if (desc != 0) {
+            desc->mPolicyMix = &mix;
+            return NO_ERROR;
+        }
+    }
+    return BAD_VALUE;
+}
+
+audio_devices_t AudioPolicyMixCollection::getDeviceAndMixForInputSource(audio_source_t inputSource,
+                                                                        audio_devices_t availDevices,
+                                                                        AudioMix **policyMix)
+{
+    for (size_t i = 0; i < size(); i++) {
+        AudioMix mix = valueAt(i)->getMix();
+
+        if (mix.mMixType != MIX_TYPE_RECORDERS) {
+            continue;
+        }
+        for (size_t j = 0; j < mix.mCriteria.size(); j++) {
+            if ((RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET == mix.mCriteria[j].mRule &&
+                    mix.mCriteria[j].mAttr.mSource == inputSource) ||
+               (RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET == mix.mCriteria[j].mRule &&
+                    mix.mCriteria[j].mAttr.mSource != inputSource)) {
+                if (availDevices & AUDIO_DEVICE_IN_REMOTE_SUBMIX) {
+                    if (policyMix != NULL) {
+                        *policyMix = &mix;
+                    }
+                    return AUDIO_DEVICE_IN_REMOTE_SUBMIX;
+                }
+                break;
+            }
+        }
+    }
+    return AUDIO_DEVICE_NONE;
+}
+
+status_t AudioPolicyMixCollection::getInputMixForAttr(audio_attributes_t attr, AudioMix *&policyMix)
+{
+    if (strncmp(attr.tags, "addr=", strlen("addr=")) != 0) {
+        return BAD_VALUE;
+    }
+    String8 address(attr.tags + strlen("addr="));
+
+    ssize_t index = indexOfKey(address);
+    if (index < 0) {
+        ALOGW("getInputForAttr() no policy for address %s", address.string());
+        return BAD_VALUE;
+    }
+    sp<AudioPolicyMix> audioPolicyMix = valueAt(index);
+    AudioMix mix = audioPolicyMix->getMix();
+
+    if (mix.mMixType != MIX_TYPE_PLAYERS) {
+        ALOGW("getInputForAttr() bad policy mix type for address %s", address.string());
+        return BAD_VALUE;
+    }
+    policyMix = &mix;
+    return NO_ERROR;
+}
+
+}; //namespace android
diff --git a/services/audiopolicy/managerdefault/Ports.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
similarity index 90%
rename from services/audiopolicy/managerdefault/Ports.cpp
rename to services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
index 3e55cee..46a119e 100644
--- a/services/audiopolicy/managerdefault/Ports.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
@@ -14,30 +14,46 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "APM::Ports"
+#define LOG_TAG "APM::AudioPort"
 //#define LOG_NDEBUG 0
 
-#include "AudioPolicyManager.h"
-
+#include "AudioPort.h"
+#include "HwModule.h"
+#include "AudioGain.h"
+#include "ConfigParsingUtils.h"
 #include "audio_policy_conf.h"
+#include <policy.h>
 
 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, const sp<HwModule>& module) :
+                     audio_port_role_t role, const sp<HwModule>& module) :
     mName(name), mType(type), mRole(role), mModule(module), mFlags(0), mId(0)
 {
     mUseInChannelMask = ((type == AUDIO_PORT_TYPE_DEVICE) && (role == AUDIO_PORT_ROLE_SOURCE)) ||
                     ((type == AUDIO_PORT_TYPE_MIX) && (role == AUDIO_PORT_ROLE_SINK));
 }
 
-void AudioPort::attach(const sp<HwModule>& module) {
-    mId = AudioPolicyManager::nextUniqueId();
+void AudioPort::attach(const sp<HwModule>& module)
+{
+    mId = getNextUniqueId();
     mModule = module;
 }
 
+audio_port_handle_t AudioPort::getNextUniqueId()
+{
+    return static_cast<audio_port_handle_t>(android_atomic_inc(&mNextUniqueId));
+}
+
+audio_module_handle_t AudioPort::getModuleHandle() const
+{
+    return mModule->mHandle;
+}
+
 void AudioPort::toAudioPort(struct audio_port *port) const
 {
     port->role = mRole;
@@ -785,60 +801,4 @@
     }
 }
 
-
-// --- AudioPatch class implementation
-
-AudioPatch::AudioPatch(audio_patch_handle_t handle,
-            const struct audio_patch *patch, uid_t uid) :
-                mHandle(handle), mPatch(*patch), mUid(uid), mAfPatchHandle(0)
-{}
-
-status_t AudioPatch::dump(int fd, int spaces, int index) const
-{
-    const size_t SIZE = 256;
-    char buffer[SIZE];
-    String8 result;
-
-    snprintf(buffer, SIZE, "%*sAudio patch %d:\n", spaces, "", index+1);
-    result.append(buffer);
-    snprintf(buffer, SIZE, "%*s- handle: %2d\n", spaces, "", mHandle);
-    result.append(buffer);
-    snprintf(buffer, SIZE, "%*s- audio flinger handle: %2d\n", spaces, "", mAfPatchHandle);
-    result.append(buffer);
-    snprintf(buffer, SIZE, "%*s- owner uid: %2d\n", spaces, "", mUid);
-    result.append(buffer);
-    snprintf(buffer, SIZE, "%*s- %d sources:\n", spaces, "", mPatch.num_sources);
-    result.append(buffer);
-    for (size_t i = 0; i < mPatch.num_sources; i++) {
-        if (mPatch.sources[i].type == AUDIO_PORT_TYPE_DEVICE) {
-            snprintf(buffer, SIZE, "%*s- Device ID %d %s\n", spaces + 2, "",
-                     mPatch.sources[i].id, ConfigParsingUtils::enumToString(sDeviceNameToEnumTable,
-                                                        ARRAY_SIZE(sDeviceNameToEnumTable),
-                                                        mPatch.sources[i].ext.device.type));
-        } 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);
-        }
-        result.append(buffer);
-    }
-    snprintf(buffer, SIZE, "%*s- %d sinks:\n", spaces, "", mPatch.num_sinks);
-    result.append(buffer);
-    for (size_t i = 0; i < mPatch.num_sinks; i++) {
-        if (mPatch.sinks[i].type == AUDIO_PORT_TYPE_DEVICE) {
-            snprintf(buffer, SIZE, "%*s- Device ID %d %s\n", spaces + 2, "",
-                     mPatch.sinks[i].id, ConfigParsingUtils::enumToString(sDeviceNameToEnumTable,
-                                                        ARRAY_SIZE(sDeviceNameToEnumTable),
-                                                        mPatch.sinks[i].ext.device.type));
-        } 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);
-        }
-        result.append(buffer);
-    }
-
-    write(fd, result.string(), result.size());
-    return NO_ERROR;
-}
-
-
 }; // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp b/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp
new file mode 100644
index 0000000..fe5bc5f
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "APM::ConfigParsingUtils"
+//#define LOG_NDEBUG 0
+
+#include "ConfigParsingUtils.h"
+#include "AudioGain.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 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, "|");
+    }
+    //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)
+{
+    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 |= stringToEnum(sInputFlagNameToEnumTable,
+                               ARRAY_SIZE(sInputFlagNameToEnumTable),
+                               flagName);
+        }
+        flagName = strtok(NULL, "|");
+    }
+    return flag;
+}
+
+//static
+audio_devices_t ConfigParsingUtils::parseDeviceNames(char *name)
+{
+    uint32_t device = 0;
+
+    char *devName = strtok(name, "|");
+    while (devName != NULL) {
+        if (strlen(devName) != 0) {
+            device |= stringToEnum(sDeviceNameToEnumTable,
+                                 ARRAY_SIZE(sDeviceNameToEnumTable),
+                                 devName);
+         }
+        devName = strtok(NULL, "|");
+     }
+    return device;
+}
+
+//static
+void ConfigParsingUtils::loadHwModule(cnode *root, HwModuleCollection &hwModules,
+                                      DeviceVector &availableInputDevices,
+                                      DeviceVector &availableOutputDevices,
+                                      sp<DeviceDescriptor> &defaultOutputDevices,
+                                      bool &isSpeakerDrcEnable)
+{
+    status_t status = NAME_NOT_FOUND;
+    cnode *node;
+    sp<HwModule> module = new HwModule(root->name);
+
+    node = config_find(root, DEVICES_TAG);
+    if (node != NULL) {
+        node = node->first_child;
+        while (node) {
+            ALOGV("loadHwModule() loading device %s", node->name);
+            status_t tmpStatus = module->loadDevice(node);
+            if (status == NAME_NOT_FOUND || status == NO_ERROR) {
+                status = tmpStatus;
+            }
+            node = node->next;
+        }
+    }
+    node = config_find(root, OUTPUTS_TAG);
+    if (node != NULL) {
+        node = node->first_child;
+        while (node) {
+            ALOGV("loadHwModule() loading output %s", node->name);
+            status_t tmpStatus = module->loadOutput(node);
+            if (status == NAME_NOT_FOUND || status == NO_ERROR) {
+                status = tmpStatus;
+            }
+            node = node->next;
+        }
+    }
+    node = config_find(root, INPUTS_TAG);
+    if (node != NULL) {
+        node = node->first_child;
+        while (node) {
+            ALOGV("loadHwModule() loading input %s", node->name);
+            status_t tmpStatus = module->loadInput(node);
+            if (status == NAME_NOT_FOUND || status == NO_ERROR) {
+                status = tmpStatus;
+            }
+            node = node->next;
+        }
+    }
+    loadGlobalConfig(root, module, availableInputDevices, availableOutputDevices,
+                     defaultOutputDevices, isSpeakerDrcEnable);
+
+    if (status == NO_ERROR) {
+        hwModules.add(module);
+    }
+}
+
+//static
+void ConfigParsingUtils::loadHwModules(cnode *root, HwModuleCollection &hwModules,
+                                       DeviceVector &availableInputDevices,
+                                       DeviceVector &availableOutputDevices,
+                                       sp<DeviceDescriptor> &defaultOutputDevices,
+                                       bool &isSpeakerDrcEnabled)
+{
+    cnode *node = config_find(root, AUDIO_HW_MODULE_TAG);
+    if (node == NULL) {
+        return;
+    }
+
+    node = node->first_child;
+    while (node) {
+        ALOGV("loadHwModules() loading module %s", node->name);
+        loadHwModule(node, hwModules, availableInputDevices, availableOutputDevices,
+                     defaultOutputDevices, isSpeakerDrcEnabled);
+        node = node->next;
+    }
+}
+
+//static
+void ConfigParsingUtils::loadGlobalConfig(cnode *root, const sp<HwModule>& module,
+                                          DeviceVector &availableInputDevices,
+                                          DeviceVector &availableOutputDevices,
+                                          sp<DeviceDescriptor> &defaultOutputDevice,
+                                          bool &speakerDrcEnabled)
+{
+    cnode *node = config_find(root, GLOBAL_CONFIG_TAG);
+
+    if (node == NULL) {
+        return;
+    }
+    DeviceVector declaredDevices;
+    if (module != NULL) {
+        declaredDevices = module->mDeclaredDevices;
+    }
+
+    node = node->first_child;
+    while (node) {
+        if (strcmp(ATTACHED_OUTPUT_DEVICES_TAG, node->name) == 0) {
+            availableOutputDevices.loadDevicesFromName((char *)node->value,
+                                                        declaredDevices);
+            ALOGV("loadGlobalConfig() Attached Output Devices %08x",
+                  availableOutputDevices.types());
+        } else if (strcmp(DEFAULT_OUTPUT_DEVICE_TAG, node->name) == 0) {
+            audio_devices_t device = (audio_devices_t)stringToEnum(
+                    sDeviceNameToEnumTable,
+                    ARRAY_SIZE(sDeviceNameToEnumTable),
+                    (char *)node->value);
+            if (device != AUDIO_DEVICE_NONE) {
+                defaultOutputDevice = new DeviceDescriptor(String8("default-output"), device);
+            } else {
+                ALOGW("loadGlobalConfig() default device not specified");
+            }
+            ALOGV("loadGlobalConfig() mDefaultOutputDevice %08x", defaultOutputDevice->type());
+        } else if (strcmp(ATTACHED_INPUT_DEVICES_TAG, node->name) == 0) {
+            availableInputDevices.loadDevicesFromName((char *)node->value,
+                                                       declaredDevices);
+            ALOGV("loadGlobalConfig() Available InputDevices %08x", availableInputDevices.types());
+        } else if (strcmp(SPEAKER_DRC_ENABLED_TAG, node->name) == 0) {
+            speakerDrcEnabled = stringToBool((char *)node->value);
+            ALOGV("loadGlobalConfig() mSpeakerDrcEnabled = %d", speakerDrcEnabled);
+        } else if (strcmp(AUDIO_HAL_VERSION_TAG, node->name) == 0) {
+            uint32_t major, minor;
+            sscanf((char *)node->value, "%u.%u", &major, &minor);
+            module->mHalVersion = HARDWARE_DEVICE_API_VERSION(major, minor);
+            ALOGV("loadGlobalConfig() mHalVersion = %04x major %u minor %u",
+                  module->mHalVersion, major, minor);
+        }
+        node = node->next;
+    }
+}
+
+//static
+status_t ConfigParsingUtils::loadAudioPolicyConfig(const char *path,
+                                                   HwModuleCollection &hwModules,
+                                                   DeviceVector &availableInputDevices,
+                                                   DeviceVector &availableOutputDevices,
+                                                   sp<DeviceDescriptor> &defaultOutputDevices,
+                                                   bool &isSpeakerDrcEnabled)
+{
+    cnode *root;
+    char *data;
+
+    data = (char *)load_file(path, NULL);
+    if (data == NULL) {
+        return -ENODEV;
+    }
+    root = config_node("", "");
+    config_load(root, data);
+
+    loadHwModules(root, hwModules,
+                  availableInputDevices, availableOutputDevices,
+                  defaultOutputDevices, isSpeakerDrcEnabled);
+    // legacy audio_policy.conf files have one global_configuration section
+    loadGlobalConfig(root, hwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY),
+                     availableInputDevices, availableOutputDevices,
+                     defaultOutputDevices, isSpeakerDrcEnabled);
+    config_free(root);
+    free(root);
+    free(data);
+
+    ALOGI("loadAudioPolicyConfig() loaded %s\n", path);
+
+    return NO_ERROR;
+}
+
+}; // namespace android
diff --git a/services/audiopolicy/managerdefault/Devices.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
similarity index 83%
rename from services/audiopolicy/managerdefault/Devices.cpp
rename to services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
index 42e198c..7df7d75 100644
--- a/services/audiopolicy/managerdefault/Devices.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
@@ -17,18 +17,21 @@
 #define LOG_TAG "APM::Devices"
 //#define LOG_NDEBUG 0
 
-#include "AudioPolicyManager.h"
+#include "DeviceDescriptor.h"
+#include "AudioGain.h"
+#include "HwModule.h"
+#include "ConfigParsingUtils.h"
 
 namespace android {
 
 String8 DeviceDescriptor::emptyNameStr = String8("");
 
 DeviceDescriptor::DeviceDescriptor(const String8& name, audio_devices_t type) :
-                     AudioPort(name, AUDIO_PORT_TYPE_DEVICE,
-                               audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK :
-                                                              AUDIO_PORT_ROLE_SOURCE,
-                             NULL),
-                     mDeviceType(type), mAddress("")
+    AudioPort(name, AUDIO_PORT_TYPE_DEVICE,
+              audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK :
+                                             AUDIO_PORT_ROLE_SOURCE,
+              NULL),
+    mAddress(""), mDeviceType(type)
 {
 
 }
@@ -57,7 +60,7 @@
 {
     mDeviceTypes = AUDIO_DEVICE_NONE;
     for(size_t i = 0; i < size(); i++) {
-        mDeviceTypes |= itemAt(i)->mDeviceType;
+        mDeviceTypes |= itemAt(i)->type();
     }
     ALOGV("DeviceVector::refreshTypes() mDeviceTypes %08x", mDeviceTypes);
 }
@@ -82,7 +85,7 @@
             refreshTypes();
         }
     } else {
-        ALOGW("DeviceVector::add device %08x already in", item->mDeviceType);
+        ALOGW("DeviceVector::add device %08x already in", item->type());
         ret = -1;
     }
     return ret;
@@ -94,7 +97,7 @@
     ssize_t ret = indexOf(item);
 
     if (ret < 0) {
-        ALOGW("DeviceVector::remove device %08x not in", item->mDeviceType);
+        ALOGW("DeviceVector::remove device %08x not in", item->type());
     } else {
         ret = SortedVector::removeAt(ret);
         if (ret >= 0) {
@@ -104,6 +107,17 @@
     return ret;
 }
 
+audio_devices_t DeviceVector::getDevicesFromHwModule(audio_module_handle_t moduleHandle) const
+{
+    audio_devices_t devices = AUDIO_DEVICE_NONE;
+    for (size_t i = 0; i < size(); i++) {
+        if (itemAt(i)->getModuleHandle() == moduleHandle) {
+            devices |= itemAt(i)->type();
+        }
+    }
+    return devices;
+}
+
 void DeviceVector::loadDevicesFromType(audio_devices_t types)
 {
     DeviceVector deviceList;
@@ -151,7 +165,7 @@
 {
     sp<DeviceDescriptor> device;
     for (size_t i = 0; i < size(); i++) {
-        if (itemAt(i)->mDeviceType == type) {
+        if (itemAt(i)->type() == type) {
             if (address == "" || itemAt(i)->mAddress == address) {
                 device = itemAt(i);
                 if (itemAt(i)->mAddress == address) {
@@ -189,7 +203,7 @@
             devices.add(itemAt(i));
             type &= ~curType;
             ALOGV("DeviceVector::getDevicesFromType() for type %x found %p",
-                  itemAt(i)->mDeviceType, itemAt(i).get());
+                  itemAt(i)->type(), itemAt(i).get());
         }
     }
     return devices;
@@ -200,7 +214,7 @@
 {
     DeviceVector devices;
     for (size_t i = 0; i < size(); i++) {
-        if (itemAt(i)->mDeviceType == type) {
+        if (itemAt(i)->type() == type) {
             if (itemAt(i)->mAddress == address) {
                 devices.add(itemAt(i));
             }
@@ -221,6 +235,26 @@
     return device;
 }
 
+
+status_t DeviceVector::dump(int fd, const String8 &direction) const
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+
+    snprintf(buffer, SIZE, "\n Available %s devices:\n", direction.string());
+    write(fd, buffer, strlen(buffer));
+    for (size_t i = 0; i < size(); i++) {
+        itemAt(i)->dump(fd, 2, i);
+    }
+    return NO_ERROR;
+}
+
+audio_policy_dev_state_t DeviceVector::getDeviceConnectionState(const sp<DeviceDescriptor> &devDesc) const
+{
+    ssize_t index = indexOf(devDesc);
+    return index >= 0 ? AUDIO_POLICY_DEVICE_STATE_AVAILABLE : AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
+}
+
 void DeviceDescriptor::toAudioPortConfig(struct audio_port_config *dstConfig,
                                          const struct audio_port_config *srcConfig) const
 {
@@ -241,7 +275,7 @@
     // without the test?
     // This has been demonstrated to NOT be true (at start up)
     // ALOG_ASSERT(mModule != NULL);
-    dstConfig->ext.device.hw_module = mModule != NULL ? mModule->mHandle : NULL;
+    dstConfig->ext.device.hw_module = mModule != 0 ? mModule->mHandle : AUDIO_IO_HANDLE_NONE;
     strncpy(dstConfig->ext.device.address, mAddress.string(), AUDIO_DEVICE_MAX_ADDRESS_LEN);
 }
 
diff --git a/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
new file mode 100644
index 0000000..33d838d
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "APM::EffectDescriptor"
+//#define LOG_NDEBUG 0
+
+#include "EffectDescriptor.h"
+#include <utils/String8.h>
+
+namespace android {
+
+status_t EffectDescriptor::dump(int fd)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    snprintf(buffer, SIZE, " I/O: %d\n", mIo);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Strategy: %d\n", mStrategy);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Session: %d\n", mSession);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Name: %s\n",  mDesc.name);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " %s\n",  mEnabled ? "Enabled" : "Disabled");
+    result.append(buffer);
+    write(fd, result.string(), result.size());
+
+    return NO_ERROR;
+}
+
+EffectDescriptorCollection::EffectDescriptorCollection() :
+    mTotalEffectsCpuLoad(0),
+    mTotalEffectsMemory(0)
+{
+
+}
+
+status_t EffectDescriptorCollection::registerEffect(const effect_descriptor_t *desc,
+                                                    audio_io_handle_t io,
+                                                    uint32_t strategy,
+                                                    int session,
+                                                    int id)
+{
+    if (mTotalEffectsMemory + desc->memoryUsage > getMaxEffectsMemory()) {
+        ALOGW("registerEffect() memory limit exceeded for Fx %s, Memory %d KB",
+                desc->name, desc->memoryUsage);
+        return INVALID_OPERATION;
+    }
+    mTotalEffectsMemory += desc->memoryUsage;
+    ALOGV("registerEffect() effect %s, io %d, strategy %d session %d id %d",
+            desc->name, io, strategy, session, id);
+    ALOGV("registerEffect() memory %d, total memory %d", desc->memoryUsage, mTotalEffectsMemory);
+
+    sp<EffectDescriptor> effectDesc = new EffectDescriptor();
+    memcpy (&effectDesc->mDesc, desc, sizeof(effect_descriptor_t));
+    effectDesc->mIo = io;
+    effectDesc->mStrategy = static_cast<routing_strategy>(strategy);
+    effectDesc->mSession = session;
+    effectDesc->mEnabled = false;
+
+    add(id, effectDesc);
+
+    return NO_ERROR;
+}
+
+status_t EffectDescriptorCollection::unregisterEffect(int id)
+{
+    ssize_t index = indexOfKey(id);
+    if (index < 0) {
+        ALOGW("unregisterEffect() unknown effect ID %d", id);
+        return INVALID_OPERATION;
+    }
+
+    sp<EffectDescriptor> effectDesc = valueAt(index);
+
+    setEffectEnabled(effectDesc, false);
+
+    if (mTotalEffectsMemory < effectDesc->mDesc.memoryUsage) {
+        ALOGW("unregisterEffect() memory %d too big for total %d",
+                effectDesc->mDesc.memoryUsage, mTotalEffectsMemory);
+        effectDesc->mDesc.memoryUsage = mTotalEffectsMemory;
+    }
+    mTotalEffectsMemory -= effectDesc->mDesc.memoryUsage;
+    ALOGV("unregisterEffect() effect %s, ID %d, memory %d total memory %d",
+            effectDesc->mDesc.name, id, effectDesc->mDesc.memoryUsage, mTotalEffectsMemory);
+
+    removeItem(id);
+
+    return NO_ERROR;
+}
+
+status_t EffectDescriptorCollection::setEffectEnabled(int id, bool enabled)
+{
+    ssize_t index = indexOfKey(id);
+    if (index < 0) {
+        ALOGW("unregisterEffect() unknown effect ID %d", id);
+        return INVALID_OPERATION;
+    }
+
+    return setEffectEnabled(valueAt(index), enabled);
+}
+
+
+status_t EffectDescriptorCollection::setEffectEnabled(const sp<EffectDescriptor> &effectDesc,
+                                                      bool enabled)
+{
+    if (enabled == effectDesc->mEnabled) {
+        ALOGV("setEffectEnabled(%s) effect already %s",
+             enabled?"true":"false", enabled?"enabled":"disabled");
+        return INVALID_OPERATION;
+    }
+
+    if (enabled) {
+        if (mTotalEffectsCpuLoad + effectDesc->mDesc.cpuLoad > getMaxEffectsCpuLoad()) {
+            ALOGW("setEffectEnabled(true) CPU Load limit exceeded for Fx %s, CPU %f MIPS",
+                 effectDesc->mDesc.name, (float)effectDesc->mDesc.cpuLoad/10);
+            return INVALID_OPERATION;
+        }
+        mTotalEffectsCpuLoad += effectDesc->mDesc.cpuLoad;
+        ALOGV("setEffectEnabled(true) total CPU %d", mTotalEffectsCpuLoad);
+    } else {
+        if (mTotalEffectsCpuLoad < effectDesc->mDesc.cpuLoad) {
+            ALOGW("setEffectEnabled(false) CPU load %d too high for total %d",
+                    effectDesc->mDesc.cpuLoad, mTotalEffectsCpuLoad);
+            effectDesc->mDesc.cpuLoad = mTotalEffectsCpuLoad;
+        }
+        mTotalEffectsCpuLoad -= effectDesc->mDesc.cpuLoad;
+        ALOGV("setEffectEnabled(false) total CPU %d", mTotalEffectsCpuLoad);
+    }
+    effectDesc->mEnabled = enabled;
+    return NO_ERROR;
+}
+
+bool EffectDescriptorCollection::isNonOffloadableEffectEnabled()
+{
+    for (size_t i = 0; i < size(); i++) {
+        sp<EffectDescriptor> effectDesc = valueAt(i);
+        if (effectDesc->mEnabled && (effectDesc->mStrategy == STRATEGY_MEDIA) &&
+                ((effectDesc->mDesc.flags & EFFECT_FLAG_OFFLOAD_SUPPORTED) == 0)) {
+            ALOGV("isNonOffloadableEffectEnabled() non offloadable effect %s enabled on session %d",
+                  effectDesc->mDesc.name, effectDesc->mSession);
+            return true;
+        }
+    }
+    return false;
+}
+
+uint32_t EffectDescriptorCollection::getMaxEffectsCpuLoad() const
+{
+    return MAX_EFFECTS_CPU_LOAD;
+}
+
+uint32_t EffectDescriptorCollection::getMaxEffectsMemory() const
+{
+    return MAX_EFFECTS_MEMORY;
+}
+
+status_t EffectDescriptorCollection::dump(int fd)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+
+    snprintf(buffer, SIZE, "\nTotal Effects CPU: %f MIPS, Total Effects memory: %d KB\n",
+             (float)mTotalEffectsCpuLoad/10, mTotalEffectsMemory);
+    write(fd, buffer, strlen(buffer));
+
+    snprintf(buffer, SIZE, "Registered effects:\n");
+    write(fd, buffer, strlen(buffer));
+    for (size_t i = 0; i < size(); i++) {
+        snprintf(buffer, SIZE, "- Effect %d dump:\n", keyAt(i));
+        write(fd, buffer, strlen(buffer));
+        valueAt(i)->dump(fd);
+    }
+    return NO_ERROR;
+}
+
+}; //namespace android
diff --git a/services/audiopolicy/managerdefault/HwModule.cpp b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
similarity index 75%
rename from services/audiopolicy/managerdefault/HwModule.cpp
rename to services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
index a04bdc8..0097d69 100644
--- a/services/audiopolicy/managerdefault/HwModule.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
@@ -17,9 +17,13 @@
 #define LOG_TAG "APM::HwModule"
 //#define LOG_NDEBUG 0
 
-#include "AudioPolicyManager.h"
+#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 {
 
@@ -138,7 +142,7 @@
 
     audio_devices_t type = AUDIO_DEVICE_NONE;
     while (node) {
-        if (strcmp(node->name, DEVICE_TYPE) == 0) {
+        if (strcmp(node->name, APM_DEVICE_TYPE) == 0) {
             type = ConfigParsingUtils::parseDeviceNames((char *)node->value);
             break;
         }
@@ -154,7 +158,7 @@
 
     node = root->first_child;
     while (node) {
-        if (strcmp(node->name, DEVICE_ADDRESS) == 0) {
+        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)) {
@@ -276,4 +280,92 @@
     }
 }
 
+sp <HwModule> HwModuleCollection::getModuleFromName(const char *name) const
+{
+    sp <HwModule> module;
+
+    for (size_t i = 0; i < size(); i++)
+    {
+        if (strcmp(itemAt(i)->mName, name) == 0) {
+            return itemAt(i);
+        }
+    }
+    return module;
+}
+
+
+sp <HwModule> HwModuleCollection::getModuleForDevice(audio_devices_t device) const
+{
+    sp <HwModule> module;
+
+    for (size_t i = 0; i < size(); i++) {
+        if (itemAt(i)->mHandle == 0) {
+            continue;
+        }
+        if (audio_is_output_device(device)) {
+            for (size_t j = 0; j < itemAt(i)->mOutputProfiles.size(); j++)
+            {
+                if (itemAt(i)->mOutputProfiles[j]->mSupportedDevices.types() & device) {
+                    return itemAt(i);
+                }
+            }
+        } else {
+            for (size_t j = 0; j < itemAt(i)->mInputProfiles.size(); j++) {
+                if (itemAt(i)->mInputProfiles[j]->mSupportedDevices.types() &
+                        device & ~AUDIO_DEVICE_BIT_IN) {
+                    return itemAt(i);
+                }
+            }
+        }
+    }
+    return module;
+}
+
+sp<DeviceDescriptor>  HwModuleCollection::getDeviceDescriptor(const audio_devices_t device,
+                                                              const char *device_address,
+                                                              const char *device_name) const
+{
+    String8 address = (device_address == NULL) ? String8("") : String8(device_address);
+    // handle legacy remote submix case where the address was not always specified
+    if (device_distinguishes_on_address(device) && (address.length() == 0)) {
+        address = String8("0");
+    }
+
+    for (size_t i = 0; i < size(); i++) {
+        const sp<HwModule> hwModule = itemAt(i);
+        if (hwModule->mHandle == 0) {
+            continue;
+        }
+        DeviceVector deviceList =
+                hwModule->mDeclaredDevices.getDevicesFromTypeAddr(device, address);
+        if (!deviceList.isEmpty()) {
+            return deviceList.itemAt(0);
+        }
+        deviceList = hwModule->mDeclaredDevices.getDevicesFromType(device);
+        if (!deviceList.isEmpty()) {
+            return deviceList.itemAt(0);
+        }
+    }
+
+    sp<DeviceDescriptor> devDesc =
+            new DeviceDescriptor(String8(device_name != NULL ? device_name : ""), device);
+    devDesc->mAddress = address;
+    return devDesc;
+}
+
+status_t HwModuleCollection::dump(int fd) const
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+
+    snprintf(buffer, SIZE, "\nHW Modules dump:\n");
+    write(fd, buffer, strlen(buffer));
+    for (size_t i = 0; i < size(); i++) {
+        snprintf(buffer, SIZE, "- HW Module %zu:\n", i + 1);
+        write(fd, buffer, strlen(buffer));
+        itemAt(i)->dump(fd);
+    }
+    return NO_ERROR;
+}
+
 } //namespace android
diff --git a/services/audiopolicy/managerdefault/IOProfile.cpp b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
similarity index 82%
rename from services/audiopolicy/managerdefault/IOProfile.cpp
rename to services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
index 538ac1a..376dd22 100644
--- a/services/audiopolicy/managerdefault/IOProfile.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
@@ -17,7 +17,9 @@
 #define LOG_TAG "APM::IOProfile"
 //#define LOG_NDEBUG 0
 
-#include "AudioPolicyManager.h"
+#include "IOProfile.h"
+#include "HwModule.h"
+#include "AudioGain.h"
 
 namespace android {
 
@@ -35,19 +37,27 @@
 // Sampling rate, format and channel mask must be specified in order to
 // get a valid a match
 bool IOProfile::isCompatibleProfile(audio_devices_t device,
-                                                        String8 address,
-                                                        uint32_t samplingRate,
-                                                        uint32_t *updatedSamplingRate,
-                                                        audio_format_t format,
-                                                        audio_channel_mask_t channelMask,
-                                                        uint32_t flags) const
+                                    String8 address,
+                                    uint32_t samplingRate,
+                                    uint32_t *updatedSamplingRate,
+                                    audio_format_t format,
+                                    audio_channel_mask_t channelMask,
+                                    uint32_t flags) const
 {
     const bool isPlaybackThread = mType == AUDIO_PORT_TYPE_MIX && mRole == AUDIO_PORT_ROLE_SOURCE;
     const bool isRecordThread = mType == AUDIO_PORT_TYPE_MIX && mRole == AUDIO_PORT_ROLE_SINK;
     ALOG_ASSERT(isPlaybackThread != isRecordThread);
 
-    if (device != AUDIO_DEVICE_NONE && mSupportedDevices.getDevice(device, address) == 0) {
-        return false;
+
+    if (device != AUDIO_DEVICE_NONE) {
+        // just check types if multiple devices are selected
+        if (popcount(device & ~AUDIO_DEVICE_BIT_IN) > 1) {
+            if ((mSupportedDevices.types() & device) != device) {
+                return false;
+            }
+        } else if (mSupportedDevices.getDevice(device, address) == 0) {
+            return false;
+        }
     }
 
     if (samplingRate == 0) {
diff --git a/services/audiopolicy/common/managerdefinitions/src/SoundTriggerSession.cpp b/services/audiopolicy/common/managerdefinitions/src/SoundTriggerSession.cpp
new file mode 100644
index 0000000..8ca3ae0
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/src/SoundTriggerSession.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "APM::SoundTriggerSession"
+//#define LOG_NDEBUG 0
+
+#include "SoundTriggerSession.h"
+
+
+namespace android {
+
+status_t SoundTriggerSessionCollection::acquireSession(audio_session_t session,
+                                                                   audio_io_handle_t ioHandle)
+{
+    add(session, ioHandle);
+
+    return NO_ERROR;
+}
+
+status_t SoundTriggerSessionCollection::releaseSession(audio_session_t session)
+{
+    ssize_t index = indexOfKey(session);
+    if (index < 0) {
+        ALOGW("acquireSoundTriggerSession() session %d not registered", session);
+        return BAD_VALUE;
+    }
+
+    removeItem(session);
+    return NO_ERROR;
+}
+
+}; //namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/StreamDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/StreamDescriptor.cpp
new file mode 100644
index 0000000..b682e2c
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/src/StreamDescriptor.cpp
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "APM::Volumes"
+//#define LOG_NDEBUG 0
+
+//#define VERY_VERBOSE_LOGGING
+#ifdef VERY_VERBOSE_LOGGING
+#define ALOGVV ALOGV
+#else
+#define ALOGVV(a...) do { } while(0)
+#endif
+
+#include "StreamDescriptor.h"
+#include <utils/Log.h>
+#include <utils/String8.h>
+
+namespace android {
+
+// --- StreamDescriptor class implementation
+
+StreamDescriptor::StreamDescriptor()
+    :   mIndexMin(0), mIndexMax(1), mCanBeMuted(true)
+{
+    mIndexCur.add(AUDIO_DEVICE_OUT_DEFAULT, 0);
+}
+
+int StreamDescriptor::getVolumeIndex(audio_devices_t device) const
+{
+    device = Volume::getDeviceForVolume(device);
+    // there is always a valid entry for AUDIO_DEVICE_OUT_DEFAULT
+    if (mIndexCur.indexOfKey(device) < 0) {
+        device = AUDIO_DEVICE_OUT_DEFAULT;
+    }
+    return mIndexCur.valueFor(device);
+}
+
+void StreamDescriptor::clearCurrentVolumeIndex()
+{
+    mIndexCur.clear();
+}
+
+void StreamDescriptor::addCurrentVolumeIndex(audio_devices_t device, int index)
+{
+    mIndexCur.add(device, index);
+}
+
+void StreamDescriptor::setVolumeIndexMin(int volIndexMin)
+{
+    mIndexMin = volIndexMin;
+}
+
+void StreamDescriptor::setVolumeIndexMax(int volIndexMax)
+{
+    mIndexMax = volIndexMax;
+}
+
+void StreamDescriptor::setVolumeCurvePoint(Volume::device_category deviceCategory,
+                                           const VolumeCurvePoint *point)
+{
+    mVolumeCurve[deviceCategory] = point;
+}
+
+void StreamDescriptor::dump(int fd) const
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    snprintf(buffer, SIZE, "%s         %02d         %02d         ",
+             mCanBeMuted ? "true " : "false", mIndexMin, mIndexMax);
+    result.append(buffer);
+    for (size_t i = 0; i < mIndexCur.size(); i++) {
+        snprintf(buffer, SIZE, "%04x : %02d, ",
+                 mIndexCur.keyAt(i),
+                 mIndexCur.valueAt(i));
+        result.append(buffer);
+    }
+    result.append("\n");
+
+    write(fd, result.string(), result.size());
+}
+
+StreamDescriptorCollection::StreamDescriptorCollection()
+{
+    for (size_t stream = 0 ; stream < AUDIO_STREAM_CNT; stream++) {
+        add(static_cast<audio_stream_type_t>(stream), StreamDescriptor());
+    }
+}
+
+bool StreamDescriptorCollection::canBeMuted(audio_stream_type_t stream)
+{
+    return valueAt(stream).canBeMuted();
+}
+
+void StreamDescriptorCollection::clearCurrentVolumeIndex(audio_stream_type_t stream)
+{
+    editValueAt(stream).clearCurrentVolumeIndex();
+}
+
+void StreamDescriptorCollection::addCurrentVolumeIndex(audio_stream_type_t stream,
+                                                       audio_devices_t device, int index)
+{
+    editValueAt(stream).addCurrentVolumeIndex(device, index);
+}
+
+void StreamDescriptorCollection::setVolumeCurvePoint(audio_stream_type_t stream,
+                                                     Volume::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
+{
+    return valueAt(stream).getVolumeCurvePoint(deviceCategory);
+}
+
+void StreamDescriptorCollection::setVolumeIndexMin(audio_stream_type_t stream,int volIndexMin)
+{
+    return editValueAt(stream).setVolumeIndexMin(volIndexMin);
+}
+
+void StreamDescriptorCollection::setVolumeIndexMax(audio_stream_type_t stream,int volIndexMax)
+{
+    return editValueAt(stream).setVolumeIndexMax(volIndexMax);
+}
+
+status_t StreamDescriptorCollection::dump(int fd) const
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+
+    snprintf(buffer, SIZE, "\nStreams dump:\n");
+    write(fd, buffer, strlen(buffer));
+    snprintf(buffer, SIZE,
+             " Stream  Can be muted  Index Min  Index Max  Index Cur [device : index]...\n");
+    write(fd, buffer, strlen(buffer));
+    for (size_t i = 0; i < size(); i++) {
+        snprintf(buffer, SIZE, " %02zu      ", i);
+        write(fd, buffer, strlen(buffer));
+        valueAt(i).dump(fd);
+    }
+
+    return NO_ERROR;
+}
+
+}; // namespace android
diff --git a/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h b/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h
new file mode 100755
index 0000000..eadaa77
--- /dev/null
+++ b/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h
@@ -0,0 +1,171 @@
+/*
+ * 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 <AudioPolicyManagerObserver.h>
+#include <RoutingStrategy.h>
+#include <Volume.h>
+#include <HwModule.h>
+#include <DeviceDescriptor.h>
+#include <system/audio.h>
+#include <system/audio_policy.h>
+#include <utils/Errors.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+/**
+ * This interface is dedicated to the policy manager that a Policy Engine shall implement.
+ */
+class AudioPolicyManagerInterface
+{
+public:
+    /**
+     * Checks if the engine was correctly initialized.
+     *
+     * @return NO_ERROR if initialization has been done correctly, error code otherwise..
+     */
+    virtual status_t initCheck() = 0;
+
+    /**
+     * Sets the Manager observer that allows the engine to retrieve information on collection
+     * of devices, streams, HwModules, ...
+     *
+     * @param[in] observer handle on the manager.
+     */
+    virtual void setObserver(AudioPolicyManagerObserver *observer) = 0;
+
+    /**
+     * Get the input device selected for a given input source.
+     *
+     * @param[in] inputSource to get the selected input device associated to
+     *
+     * @return selected input device for the given input source, may be none if error.
+     */
+    virtual audio_devices_t getDeviceForInputSource(audio_source_t inputSource) const = 0;
+
+    /**
+     * Get the output device associated to a given strategy.
+     *
+     * @param[in] stream type for which the selected ouput device is requested.
+     *
+     * @return selected ouput device for the given strategy, may be none if error.
+     */
+    virtual audio_devices_t getDeviceForStrategy(routing_strategy stategy) const = 0;
+
+    /**
+     * Get the strategy selected for a given stream type.
+     *
+     * @param[in] stream: for which the selected strategy followed by is requested.
+     *
+     * @return strategy to be followed.
+     */
+    virtual routing_strategy getStrategyForStream(audio_stream_type_t stream) = 0;
+
+    /**
+     * Get the strategy selected for a given usage.
+     *
+     * @param[in] usage to get the selected strategy followed by.
+     *
+     * @return strategy to be followed.
+     */
+    virtual routing_strategy getStrategyForUsage(audio_usage_t usage) = 0;
+
+    /**
+     * Set the Telephony Mode.
+     *
+     * @param[in] mode: Android Phone state (normal, ringtone, csv, in communication)
+     *
+     * @return NO_ERROR if Telephony Mode set correctly, error code otherwise.
+     */
+    virtual status_t setPhoneState(audio_mode_t mode) = 0;
+
+    /**
+     * Get the telephony Mode
+     *
+     * @return the current telephony mode
+     */
+    virtual audio_mode_t getPhoneState() const = 0;
+
+    /**
+     * Set Force Use config for a given usage.
+     *
+     * @param[in] usage for which a configuration shall be forced.
+     * @param[in] config wished to be forced for the given usage.
+     *
+     * @return NO_ERROR if the Force Use config was set correctly, error code otherwise (e.g. config not
+     * allowed a given usage...)
+     */
+    virtual status_t setForceUse(audio_policy_force_use_t usage,
+                                 audio_policy_forced_cfg_t config) = 0;
+
+    /**
+     * Get Force Use config for a given usage.
+     *
+     * @param[in] usage for which a configuration shall be forced.
+     *
+     * @return config wished to be forced for the given usage.
+     */
+    virtual audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage) const = 0;
+
+    /**
+     * Set the connection state of device(s).
+     *
+     * @param[in] devDesc for which the state has changed.
+     * @param[in] state of availability of this(these) device(s).
+     *
+     * @return NO_ERROR if devices criterion updated correctly, error code otherwise.
+     */
+    virtual status_t setDeviceConnectionState(const android::sp<android::DeviceDescriptor> devDesc,
+                                              audio_policy_dev_state_t state) = 0;
+
+    /**
+     * Translate a volume index given by the UI to an amplification value for a stream type
+     * and a device category.
+     *
+     * @param[in] deviceCategory for which the conversion is requested.
+     * @param[in] stream type for which the conversion is requested.
+     * @param[in] indexInUi index received from the UI to be translated.
+     *
+     * @return amplification value matching the UI index for this given device and stream.
+     */
+    virtual float volIndexToAmpl(Volume::device_category deviceCategory, audio_stream_type_t stream,
+                                 int indexInUi) = 0;
+
+    /**
+     * Initialize the min / max index of volume applicable for a given stream type. These indexes
+     * will be used upon conversion of UI index to volume amplification.
+     *
+     * @param[in] stream type for which the indexes need to be set
+     * @param[in] indexMin Minimum index allowed for this stream.
+     * @param[in] indexMax Maximum index allowed for this stream.
+     */
+    virtual status_t initStreamVolume(audio_stream_type_t stream, int indexMin, int indexMax) = 0;
+
+    /**
+     * Initialize volume curves for each strategy and device category
+     *
+     * @param[in] isSpeakerDrcEnabled true on devices that use DRC on the DEVICE_CATEGORY_SPEAKER
+                  path to boost soft sounds, used to adjust volume curves accordingly
+     */
+    virtual void initializeVolumeCurves(bool isSpeakerDrcEnabled) = 0;
+
+protected:
+    virtual ~AudioPolicyManagerInterface() {}
+};
+
+}; // namespace android
diff --git a/services/audiopolicy/engine/interface/AudioPolicyManagerObserver.h b/services/audiopolicy/engine/interface/AudioPolicyManagerObserver.h
new file mode 100755
index 0000000..4f5427e
--- /dev/null
+++ b/services/audiopolicy/engine/interface/AudioPolicyManagerObserver.h
@@ -0,0 +1,62 @@
+/*
+ * 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 <AudioGain.h>
+#include <AudioPort.h>
+#include <AudioPatch.h>
+#include <IOProfile.h>
+#include <DeviceDescriptor.h>
+#include <AudioInputDescriptor.h>
+#include <AudioOutputDescriptor.h>
+#include <AudioPolicyMix.h>
+#include <SoundTriggerSession.h>
+#include <StreamDescriptor.h>
+
+namespace android {
+
+/**
+ * This interface is an observer that the manager shall implement to allows e.g. the engine
+ * to access to policy pillars elements (like output / input descritors collections,
+ * HwModule collections, AudioMix, ...
+ */
+class AudioPolicyManagerObserver
+{
+public:
+    virtual const AudioPatchCollection &getAudioPatches() const = 0;
+
+    virtual const SoundTriggerSessionCollection &getSoundTriggerSessionCollection() const = 0;
+
+    virtual const AudioPolicyMixCollection &getAudioPolicyMixCollection() const = 0;
+
+    virtual const AudioOutputCollection &getOutputs() const = 0;
+
+    virtual const AudioInputCollection &getInputs() const = 0;
+
+    virtual const DeviceVector &getAvailableOutputDevices() const = 0;
+
+    virtual const DeviceVector &getAvailableInputDevices() const = 0;
+
+    virtual StreamDescriptorCollection &getStreamDescriptors() = 0;
+
+    virtual const sp<DeviceDescriptor> &getDefaultOutputDevice() const = 0;
+
+protected:
+    virtual ~AudioPolicyManagerObserver() {}
+};
+
+}; // namespace android
diff --git a/services/audiopolicy/enginedefault/Android.mk b/services/audiopolicy/enginedefault/Android.mk
new file mode 100755
index 0000000..b0ae835
--- /dev/null
+++ b/services/audiopolicy/enginedefault/Android.mk
@@ -0,0 +1,48 @@
+LOCAL_PATH := $(call my-dir)
+
+# Component build
+#######################################################################
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+    src/Engine.cpp \
+    src/EngineInstance.cpp \
+    src/Gains.cpp \
+
+
+audio_policy_engine_includes_common := \
+    $(LOCAL_PATH)/include \
+    $(TOPDIR)frameworks/av/services/audiopolicy/engine/interface
+
+LOCAL_CFLAGS += \
+    -Wall \
+    -Werror \
+    -Wextra \
+
+LOCAL_EXPORT_C_INCLUDE_DIRS := \
+    $(audio_policy_engine_includes_common)
+
+LOCAL_C_INCLUDES := \
+    $(audio_policy_engine_includes_common) \
+    $(TARGET_OUT_HEADERS)/hw \
+    $(call include-path-for, frameworks-av) \
+    $(call include-path-for, audio-utils) \
+    $(call include-path-for, bionic) \
+    $(TOPDIR)frameworks/av/services/audiopolicy/common/include
+
+
+LOCAL_MODULE := libaudiopolicyenginedefault
+LOCAL_MODULE_TAGS := optional
+LOCAL_STATIC_LIBRARIES := \
+    libmedia_helper \
+    libaudiopolicycomponents
+
+LOCAL_SHARED_LIBRARIES += \
+    libcutils \
+    libutils \
+    libaudioutils \
+
+include external/stlport/libstlport.mk
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/services/audiopolicy/enginedefault/include/AudioPolicyEngineInstance.h b/services/audiopolicy/enginedefault/include/AudioPolicyEngineInstance.h
new file mode 100755
index 0000000..1e329f0
--- /dev/null
+++ b/services/audiopolicy/enginedefault/include/AudioPolicyEngineInstance.h
@@ -0,0 +1,76 @@
+/*
+ * 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
+
+class AudioPolicyManagerInterface;
+
+namespace android
+{
+namespace audio_policy
+{
+
+class Engine;
+
+class EngineInstance
+{
+protected:
+    EngineInstance();
+
+public:
+    virtual ~EngineInstance();
+
+    /**
+     * Get Audio Policy Engine instance.
+     *
+     * @return pointer to Route Manager Instance object.
+     */
+    static EngineInstance *getInstance();
+
+    /**
+     * Interface query.
+     * The first client of an interface of the policy engine will start the singleton.
+     *
+     * @tparam RequestedInterface: interface that the client is wishing to retrieve.
+     *
+     * @return interface handle.
+     */
+    template <class RequestedInterface>
+    RequestedInterface *queryInterface() const;
+
+protected:
+    /**
+     * Get Audio Policy Engine instance.
+     *
+     * @return Audio Policy Engine singleton.
+     */
+    Engine *getEngine() const;
+
+private:
+    /* Copy facilities are put private to disable copy. */
+    EngineInstance(const EngineInstance &object);
+    EngineInstance &operator=(const EngineInstance &object);
+};
+
+/**
+ * Limit template instantation to supported type interfaces.
+ * Compile time error will claim if invalid interface is requested.
+ */
+template <>
+AudioPolicyManagerInterface *EngineInstance::queryInterface() const;
+
+} // namespace audio_policy
+} // namespace android
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
new file mode 100755
index 0000000..b4d7246
--- /dev/null
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -0,0 +1,707 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "APM::AudioPolicyEngine"
+//#define LOG_NDEBUG 0
+
+//#define VERY_VERBOSE_LOGGING
+#ifdef VERY_VERBOSE_LOGGING
+#define ALOGVV ALOGV
+#else
+#define ALOGVV(a...) do { } while(0)
+#endif
+
+#include "Engine.h"
+#include "Gains.h"
+#include <AudioPolicyManagerObserver.h>
+#include <AudioPort.h>
+#include <IOProfile.h>
+#include <policy.h>
+#include <utils/String8.h>
+#include <utils/Log.h>
+
+namespace android
+{
+namespace audio_policy
+{
+
+Engine::Engine()
+    : mManagerInterface(this),
+      mPhoneState(AUDIO_MODE_NORMAL),
+      mApmObserver(NULL)
+{
+    for (int i = 0; i < AUDIO_POLICY_FORCE_USE_CNT; i++) {
+        mForceUse[i] = AUDIO_POLICY_FORCE_NONE;
+    }
+}
+
+Engine::~Engine()
+{
+}
+
+void Engine::setObserver(AudioPolicyManagerObserver *observer)
+{
+    ALOG_ASSERT(observer != NULL, "Invalid Audio Policy Manager observer");
+    mApmObserver = observer;
+}
+
+status_t Engine::initCheck()
+{
+    return (mApmObserver != NULL) ?  NO_ERROR : NO_INIT;
+}
+
+float Engine::volIndexToAmpl(Volume::device_category category, audio_stream_type_t streamType,
+                             int indexInUi)
+{
+    const StreamDescriptor &streamDesc = mApmObserver->getStreamDescriptors().valueAt(streamType);
+    return Gains::volIndexToAmpl(category, streamDesc, indexInUi);
+}
+
+status_t Engine::initStreamVolume(audio_stream_type_t stream, int indexMin, int indexMax)
+{
+    ALOGV("initStreamVolume() stream %d, min %d, max %d", stream , indexMin, indexMax);
+    if (indexMin < 0 || indexMin >= indexMax) {
+        ALOGW("initStreamVolume() invalid index limits for stream %d, min %d, max %d",
+              stream , indexMin, indexMax);
+        return BAD_VALUE;
+    }
+    mApmObserver->getStreamDescriptors().setVolumeIndexMin(stream, indexMin);
+    mApmObserver->getStreamDescriptors().setVolumeIndexMax(stream, indexMax);
+    return NO_ERROR;
+}
+
+void Engine::initializeVolumeCurves(bool isSpeakerDrcEnabled)
+{
+    StreamDescriptorCollection &streams = mApmObserver->getStreamDescriptors();
+
+    for (int i = 0; i < AUDIO_STREAM_CNT; i++) {
+        for (int j = 0; j < Volume::DEVICE_CATEGORY_CNT; j++) {
+            streams.setVolumeCurvePoint(static_cast<audio_stream_type_t>(i),
+                                         static_cast<Volume::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,
+                Gains::sDefaultSystemVolumeCurveDrc);
+        streams.setVolumeCurvePoint(AUDIO_STREAM_RING, Volume::DEVICE_CATEGORY_SPEAKER,
+                Gains::sSpeakerSonificationVolumeCurveDrc);
+        streams.setVolumeCurvePoint(AUDIO_STREAM_ALARM, Volume::DEVICE_CATEGORY_SPEAKER,
+                Gains::sSpeakerSonificationVolumeCurveDrc);
+        streams.setVolumeCurvePoint(AUDIO_STREAM_NOTIFICATION, Volume::DEVICE_CATEGORY_SPEAKER,
+                Gains::sSpeakerSonificationVolumeCurveDrc);
+        streams.setVolumeCurvePoint(AUDIO_STREAM_MUSIC, Volume::DEVICE_CATEGORY_SPEAKER,
+                Gains::sSpeakerMediaVolumeCurveDrc);
+        streams.setVolumeCurvePoint(AUDIO_STREAM_ACCESSIBILITY, Volume::DEVICE_CATEGORY_SPEAKER,
+                Gains::sSpeakerMediaVolumeCurveDrc);
+    }
+}
+
+
+status_t Engine::setPhoneState(audio_mode_t state)
+{
+    ALOGV("setPhoneState() state %d", state);
+
+    if (state < 0 || state >= AUDIO_MODE_CNT) {
+        ALOGW("setPhoneState() invalid state %d", state);
+        return BAD_VALUE;
+    }
+
+    if (state == mPhoneState ) {
+        ALOGW("setPhoneState() setting same state %d", state);
+        return BAD_VALUE;
+    }
+
+    // store previous phone state for management of sonification strategy below
+    int oldState = mPhoneState;
+    mPhoneState = state;
+    StreamDescriptorCollection &streams = mApmObserver->getStreamDescriptors();
+    // 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),
+                                         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),
+                                         Gains::sVolumeProfiles[AUDIO_STREAM_DTMF][j]);
+        }
+    }
+    return NO_ERROR;
+}
+
+status_t Engine::setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config)
+{
+    switch(usage) {
+    case AUDIO_POLICY_FORCE_FOR_COMMUNICATION:
+        if (config != AUDIO_POLICY_FORCE_SPEAKER && config != AUDIO_POLICY_FORCE_BT_SCO &&
+            config != AUDIO_POLICY_FORCE_NONE) {
+            ALOGW("setForceUse() invalid config %d for FOR_COMMUNICATION", config);
+            return BAD_VALUE;
+        }
+        mForceUse[usage] = config;
+        break;
+    case AUDIO_POLICY_FORCE_FOR_MEDIA:
+        if (config != AUDIO_POLICY_FORCE_HEADPHONES && config != AUDIO_POLICY_FORCE_BT_A2DP &&
+            config != AUDIO_POLICY_FORCE_WIRED_ACCESSORY &&
+            config != AUDIO_POLICY_FORCE_ANALOG_DOCK &&
+            config != AUDIO_POLICY_FORCE_DIGITAL_DOCK && config != AUDIO_POLICY_FORCE_NONE &&
+            config != AUDIO_POLICY_FORCE_NO_BT_A2DP && config != AUDIO_POLICY_FORCE_SPEAKER ) {
+            ALOGW("setForceUse() invalid config %d for FOR_MEDIA", config);
+            return BAD_VALUE;
+        }
+        mForceUse[usage] = config;
+        break;
+    case AUDIO_POLICY_FORCE_FOR_RECORD:
+        if (config != AUDIO_POLICY_FORCE_BT_SCO && config != AUDIO_POLICY_FORCE_WIRED_ACCESSORY &&
+            config != AUDIO_POLICY_FORCE_NONE) {
+            ALOGW("setForceUse() invalid config %d for FOR_RECORD", config);
+            return BAD_VALUE;
+        }
+        mForceUse[usage] = config;
+        break;
+    case AUDIO_POLICY_FORCE_FOR_DOCK:
+        if (config != AUDIO_POLICY_FORCE_NONE && config != AUDIO_POLICY_FORCE_BT_CAR_DOCK &&
+            config != AUDIO_POLICY_FORCE_BT_DESK_DOCK &&
+            config != AUDIO_POLICY_FORCE_WIRED_ACCESSORY &&
+            config != AUDIO_POLICY_FORCE_ANALOG_DOCK &&
+            config != AUDIO_POLICY_FORCE_DIGITAL_DOCK) {
+            ALOGW("setForceUse() invalid config %d for FOR_DOCK", config);
+        }
+        mForceUse[usage] = config;
+        break;
+    case AUDIO_POLICY_FORCE_FOR_SYSTEM:
+        if (config != AUDIO_POLICY_FORCE_NONE &&
+            config != AUDIO_POLICY_FORCE_SYSTEM_ENFORCED) {
+            ALOGW("setForceUse() invalid config %d for FOR_SYSTEM", config);
+        }
+        mForceUse[usage] = config;
+        break;
+    case AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO:
+        if (config != AUDIO_POLICY_FORCE_NONE &&
+            config != AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED) {
+            ALOGW("setForceUse() invalid config %d forHDMI_SYSTEM_AUDIO", config);
+        }
+        mForceUse[usage] = config;
+        break;
+    default:
+        ALOGW("setForceUse() invalid usage %d", usage);
+        break;
+    }
+    return NO_ERROR;
+}
+
+routing_strategy Engine::getStrategyForStream(audio_stream_type_t stream)
+{
+    // stream to strategy mapping
+    switch (stream) {
+    case AUDIO_STREAM_VOICE_CALL:
+    case AUDIO_STREAM_BLUETOOTH_SCO:
+        return STRATEGY_PHONE;
+    case AUDIO_STREAM_RING:
+    case AUDIO_STREAM_ALARM:
+        return STRATEGY_SONIFICATION;
+    case AUDIO_STREAM_NOTIFICATION:
+        return STRATEGY_SONIFICATION_RESPECTFUL;
+    case AUDIO_STREAM_DTMF:
+        return STRATEGY_DTMF;
+    default:
+        ALOGE("unknown stream type %d", stream);
+    case AUDIO_STREAM_SYSTEM:
+        // NOTE: SYSTEM stream uses MEDIA strategy because muting music and switching outputs
+        // while key clicks are played produces a poor result
+    case AUDIO_STREAM_MUSIC:
+        return STRATEGY_MEDIA;
+    case AUDIO_STREAM_ENFORCED_AUDIBLE:
+        return STRATEGY_ENFORCED_AUDIBLE;
+    case AUDIO_STREAM_TTS:
+        return STRATEGY_TRANSMITTED_THROUGH_SPEAKER;
+    case AUDIO_STREAM_ACCESSIBILITY:
+        return STRATEGY_ACCESSIBILITY;
+    case AUDIO_STREAM_REROUTING:
+        return STRATEGY_REROUTING;
+    }
+}
+
+routing_strategy Engine::getStrategyForUsage(audio_usage_t usage)
+{
+    const AudioOutputCollection &outputs = mApmObserver->getOutputs();
+
+    // usage to strategy mapping
+    switch (usage) {
+    case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
+        if (outputs.isStreamActive(AUDIO_STREAM_RING) ||
+                outputs.isStreamActive(AUDIO_STREAM_ALARM)) {
+            return STRATEGY_SONIFICATION;
+        }
+        if (isInCall()) {
+            return STRATEGY_PHONE;
+        }
+        return STRATEGY_ACCESSIBILITY;
+
+    case AUDIO_USAGE_MEDIA:
+    case AUDIO_USAGE_GAME:
+    case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
+    case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
+        return STRATEGY_MEDIA;
+
+    case AUDIO_USAGE_VOICE_COMMUNICATION:
+        return STRATEGY_PHONE;
+
+    case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:
+        return STRATEGY_DTMF;
+
+    case AUDIO_USAGE_ALARM:
+    case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE:
+        return STRATEGY_SONIFICATION;
+
+    case AUDIO_USAGE_NOTIFICATION:
+    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
+    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
+    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
+    case AUDIO_USAGE_NOTIFICATION_EVENT:
+        return STRATEGY_SONIFICATION_RESPECTFUL;
+
+    case AUDIO_USAGE_UNKNOWN:
+    default:
+        return STRATEGY_MEDIA;
+    }
+}
+
+audio_devices_t Engine::getDeviceForStrategy(routing_strategy strategy) const
+{
+    const DeviceVector &availableOutputDevices = mApmObserver->getAvailableOutputDevices();
+    const DeviceVector &availableInputDevices = mApmObserver->getAvailableInputDevices();
+
+    const AudioOutputCollection &outputs = mApmObserver->getOutputs();
+
+    uint32_t device = AUDIO_DEVICE_NONE;
+    uint32_t availableOutputDevicesType = availableOutputDevices.types();
+
+    switch (strategy) {
+
+    case STRATEGY_TRANSMITTED_THROUGH_SPEAKER:
+        device = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
+        if (!device) {
+            ALOGE("getDeviceForStrategy() no device found for "\
+                    "STRATEGY_TRANSMITTED_THROUGH_SPEAKER");
+        }
+        break;
+
+    case STRATEGY_SONIFICATION_RESPECTFUL:
+        if (isInCall()) {
+            device = getDeviceForStrategy(STRATEGY_SONIFICATION);
+        } else if (outputs.isStreamActiveRemotely(AUDIO_STREAM_MUSIC,
+                SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) {
+            // while media is playing on a remote device, use the the sonification behavior.
+            // Note that we test this usecase before testing if media is playing because
+            //   the isStreamActive() method only informs about the activity of a stream, not
+            //   if it's for local playback. Note also that we use the same delay between both tests
+            device = getDeviceForStrategy(STRATEGY_SONIFICATION);
+            //user "safe" speaker if available instead of normal speaker to avoid triggering
+            //other acoustic safety mechanisms for notification
+            if (device == AUDIO_DEVICE_OUT_SPEAKER && (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER_SAFE))
+                device = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
+        } else if (outputs.isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) {
+            // while media is playing (or has recently played), use the same device
+            device = getDeviceForStrategy(STRATEGY_MEDIA);
+        } else {
+            // when media is not playing anymore, fall back on the sonification behavior
+            device = getDeviceForStrategy(STRATEGY_SONIFICATION);
+            //user "safe" speaker if available instead of normal speaker to avoid triggering
+            //other acoustic safety mechanisms for notification
+            if (device == AUDIO_DEVICE_OUT_SPEAKER && (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER_SAFE))
+                device = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
+        }
+        break;
+
+    case STRATEGY_DTMF:
+        if (!isInCall()) {
+            // when off call, DTMF strategy follows the same rules as MEDIA strategy
+            device = getDeviceForStrategy(STRATEGY_MEDIA);
+            break;
+        }
+        // when in call, DTMF and PHONE strategies follow the same rules
+        // FALL THROUGH
+
+    case STRATEGY_PHONE:
+        // Force use of only devices on primary output if:
+        // - in call AND
+        //   - cannot route from voice call RX OR
+        //   - audio HAL version is < 3.0 and TX device is on the primary HW module
+        if (getPhoneState() == AUDIO_MODE_IN_CALL) {
+            audio_devices_t txDevice = getDeviceForInputSource(AUDIO_SOURCE_VOICE_COMMUNICATION);
+            sp<AudioOutputDescriptor> primaryOutput = outputs.getPrimaryOutput();
+            audio_devices_t availPrimaryInputDevices =
+                 availableInputDevices.getDevicesFromHwModule(primaryOutput->getModuleHandle());
+            audio_devices_t availPrimaryOutputDevices =
+                    primaryOutput->supportedDevices() & availableOutputDevices.types();
+
+            if (((availableInputDevices.types() &
+                    AUDIO_DEVICE_IN_TELEPHONY_RX & ~AUDIO_DEVICE_BIT_IN) == 0) ||
+                    (((txDevice & availPrimaryInputDevices & ~AUDIO_DEVICE_BIT_IN) != 0) &&
+                         (primaryOutput->getAudioPort()->mModule->mHalVersion <
+                             AUDIO_DEVICE_API_VERSION_3_0))) {
+                availableOutputDevicesType = availPrimaryOutputDevices;
+            }
+        }
+        // for phone strategy, we first consider the forced use and then the available devices by order
+        // of priority
+        switch (mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION]) {
+        case AUDIO_POLICY_FORCE_BT_SCO:
+            if (!isInCall() || strategy != STRATEGY_DTMF) {
+                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
+                if (device) break;
+            }
+            device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
+            if (device) break;
+            device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO;
+            if (device) break;
+            // if SCO device is requested but no SCO device is available, fall back to default case
+            // FALL THROUGH
+
+        default:    // FORCE_NONE
+            // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP
+            if (!isInCall() &&
+                    (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
+                    (outputs.getA2dpOutput() != 0)) {
+                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
+                if (device) break;
+                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
+                if (device) break;
+            }
+            device = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
+            if (device) break;
+            device = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADSET;
+            if (device) break;
+            device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_DEVICE;
+            if (device) break;
+            if (!isInCall()) {
+                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_ACCESSORY;
+                if (device) break;
+                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
+                if (device) break;
+                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_DIGITAL;
+                if (device) break;
+                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
+                if (device) break;
+            }
+            device = availableOutputDevicesType & AUDIO_DEVICE_OUT_EARPIECE;
+            if (device) break;
+            device = mApmObserver->getDefaultOutputDevice()->type();
+            if (device == AUDIO_DEVICE_NONE) {
+                ALOGE("getDeviceForStrategy() no device found for STRATEGY_PHONE");
+            }
+            break;
+
+        case AUDIO_POLICY_FORCE_SPEAKER:
+            // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to
+            // A2DP speaker when forcing to speaker output
+            if (!isInCall() &&
+                    (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
+                    (outputs.getA2dpOutput() != 0)) {
+                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
+                if (device) break;
+            }
+            if (!isInCall()) {
+                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_ACCESSORY;
+                if (device) break;
+                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_DEVICE;
+                if (device) break;
+                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
+                if (device) break;
+                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_DIGITAL;
+                if (device) break;
+                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
+                if (device) break;
+            }
+            device = availableOutputDevicesType & AUDIO_DEVICE_OUT_LINE;
+            if (device) break;
+            device = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
+            if (device) break;
+            device = mApmObserver->getDefaultOutputDevice()->type();
+            if (device == AUDIO_DEVICE_NONE) {
+                ALOGE("getDeviceForStrategy() no device found for STRATEGY_PHONE, FORCE_SPEAKER");
+            }
+            break;
+        }
+    break;
+
+    case STRATEGY_SONIFICATION:
+
+        // If incall, just select the STRATEGY_PHONE device: The rest of the behavior is handled by
+        // handleIncallSonification().
+        if (isInCall()) {
+            device = getDeviceForStrategy(STRATEGY_PHONE);
+            break;
+        }
+        // FALL THROUGH
+
+    case STRATEGY_ENFORCED_AUDIBLE:
+        // strategy STRATEGY_ENFORCED_AUDIBLE uses same routing policy as STRATEGY_SONIFICATION
+        // except:
+        //   - when in call where it doesn't default to STRATEGY_PHONE behavior
+        //   - in countries where not enforced in which case it follows STRATEGY_MEDIA
+
+        if ((strategy == STRATEGY_SONIFICATION) ||
+                (mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM] == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)) {
+            device = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
+            if (device == AUDIO_DEVICE_NONE) {
+                ALOGE("getDeviceForStrategy() speaker device not found for STRATEGY_SONIFICATION");
+            }
+        }
+        // The second device used for sonification is the same as the device used by media strategy
+        // FALL THROUGH
+
+    // FIXME: STRATEGY_ACCESSIBILITY and STRATEGY_REROUTING follow STRATEGY_MEDIA for now
+    case STRATEGY_ACCESSIBILITY:
+        if (strategy == STRATEGY_ACCESSIBILITY) {
+            // do not route accessibility prompts to a digital output currently configured with a
+            // compressed format as they would likely not be mixed and dropped.
+            for (size_t i = 0; i < outputs.size(); i++) {
+                sp<AudioOutputDescriptor> desc = outputs.valueAt(i);
+                audio_devices_t devices = desc->device() &
+                    (AUDIO_DEVICE_OUT_HDMI | AUDIO_DEVICE_OUT_SPDIF | AUDIO_DEVICE_OUT_HDMI_ARC);
+                if (desc->isActive() && !audio_is_linear_pcm(desc->mFormat) &&
+                        devices != AUDIO_DEVICE_NONE) {
+                    availableOutputDevicesType = availableOutputDevices.types() & ~devices;
+                }
+            }
+        }
+        // FALL THROUGH
+
+    case STRATEGY_REROUTING:
+    case STRATEGY_MEDIA: {
+        uint32_t device2 = AUDIO_DEVICE_NONE;
+        if (strategy != STRATEGY_SONIFICATION) {
+            // no sonification on remote submix (e.g. WFD)
+            if (availableOutputDevices.getDevice(AUDIO_DEVICE_OUT_REMOTE_SUBMIX, String8("0")) != 0) {
+                device2 = availableOutputDevices.types() & AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
+            }
+        }
+        if ((device2 == AUDIO_DEVICE_NONE) &&
+                (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
+                (outputs.getA2dpOutput() != 0)) {
+            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
+            if (device2 == AUDIO_DEVICE_NONE) {
+                device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
+            }
+            if (device2 == AUDIO_DEVICE_NONE) {
+                device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
+            }
+        }
+        if ((device2 == AUDIO_DEVICE_NONE) &&
+            (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] == AUDIO_POLICY_FORCE_SPEAKER)) {
+            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
+        }
+        if (device2 == AUDIO_DEVICE_NONE) {
+            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
+        }
+        if ((device2 == AUDIO_DEVICE_NONE)) {
+            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_LINE;
+        }
+        if (device2 == AUDIO_DEVICE_NONE) {
+            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADSET;
+        }
+        if (device2 == AUDIO_DEVICE_NONE) {
+            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_ACCESSORY;
+        }
+        if (device2 == AUDIO_DEVICE_NONE) {
+            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_DEVICE;
+        }
+        if (device2 == AUDIO_DEVICE_NONE) {
+            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
+        }
+        if ((device2 == AUDIO_DEVICE_NONE) && (strategy != STRATEGY_SONIFICATION)) {
+            // no sonification on aux digital (e.g. HDMI)
+            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_DIGITAL;
+        }
+        if ((device2 == AUDIO_DEVICE_NONE) &&
+                (mForceUse[AUDIO_POLICY_FORCE_FOR_DOCK] == AUDIO_POLICY_FORCE_ANALOG_DOCK)) {
+            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
+        }
+        if (device2 == AUDIO_DEVICE_NONE) {
+            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
+        }
+        int device3 = AUDIO_DEVICE_NONE;
+        if (strategy == STRATEGY_MEDIA) {
+            // ARC, SPDIF and AUX_LINE can co-exist with others.
+            device3 = availableOutputDevicesType & AUDIO_DEVICE_OUT_HDMI_ARC;
+            device3 |= (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPDIF);
+            device3 |= (availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_LINE);
+        }
+
+        device2 |= device3;
+        // device is DEVICE_OUT_SPEAKER if we come from case STRATEGY_SONIFICATION or
+        // STRATEGY_ENFORCED_AUDIBLE, AUDIO_DEVICE_NONE otherwise
+        device |= device2;
+
+        // If hdmi system audio mode is on, remove speaker out of output list.
+        if ((strategy == STRATEGY_MEDIA) &&
+            (mForceUse[AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO] ==
+                AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED)) {
+            device &= ~AUDIO_DEVICE_OUT_SPEAKER;
+        }
+
+        if (device) break;
+        device = mApmObserver->getDefaultOutputDevice()->type();
+        if (device == AUDIO_DEVICE_NONE) {
+            ALOGE("getDeviceForStrategy() no device found for STRATEGY_MEDIA");
+        }
+        } break;
+
+    default:
+        ALOGW("getDeviceForStrategy() unknown strategy: %d", strategy);
+        break;
+    }
+
+    ALOGVV("getDeviceForStrategy() strategy %d, device %x", strategy, device);
+    return device;
+}
+
+
+audio_devices_t Engine::getDeviceForInputSource(audio_source_t inputSource) const
+{
+    const DeviceVector &availableOutputDevices = mApmObserver->getAvailableOutputDevices();
+    const DeviceVector &availableInputDevices = mApmObserver->getAvailableInputDevices();
+    const AudioOutputCollection &outputs = mApmObserver->getOutputs();
+    audio_devices_t availableDeviceTypes = availableInputDevices.types() & ~AUDIO_DEVICE_BIT_IN;
+
+    uint32_t device = AUDIO_DEVICE_NONE;
+
+    switch (inputSource) {
+    case AUDIO_SOURCE_VOICE_UPLINK:
+      if (availableDeviceTypes & AUDIO_DEVICE_IN_VOICE_CALL) {
+          device = AUDIO_DEVICE_IN_VOICE_CALL;
+          break;
+      }
+      break;
+
+    case AUDIO_SOURCE_DEFAULT:
+    case AUDIO_SOURCE_MIC:
+    if (availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_A2DP) {
+        device = AUDIO_DEVICE_IN_BLUETOOTH_A2DP;
+    } else if ((mForceUse[AUDIO_POLICY_FORCE_FOR_RECORD] == AUDIO_POLICY_FORCE_BT_SCO) &&
+        (availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET)) {
+        device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
+    } else if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) {
+        device = AUDIO_DEVICE_IN_WIRED_HEADSET;
+    } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
+        device = AUDIO_DEVICE_IN_USB_DEVICE;
+    } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+        device = AUDIO_DEVICE_IN_BUILTIN_MIC;
+    }
+    break;
+
+    case AUDIO_SOURCE_VOICE_COMMUNICATION:
+        // Allow only use of devices on primary input if in call and HAL does not support routing
+        // to voice call path.
+        if ((getPhoneState() == AUDIO_MODE_IN_CALL) &&
+                (availableOutputDevices.types() & AUDIO_DEVICE_OUT_TELEPHONY_TX) == 0) {
+            sp<AudioOutputDescriptor> primaryOutput = outputs.getPrimaryOutput();
+            availableDeviceTypes =
+                    availableInputDevices.getDevicesFromHwModule(primaryOutput->getModuleHandle())
+                    & ~AUDIO_DEVICE_BIT_IN;
+        }
+
+        switch (mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION]) {
+        case AUDIO_POLICY_FORCE_BT_SCO:
+            // if SCO device is requested but no SCO device is available, fall back to default case
+            if (availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
+                device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
+                break;
+            }
+            // FALL THROUGH
+
+        default:    // FORCE_NONE
+            if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) {
+                device = AUDIO_DEVICE_IN_WIRED_HEADSET;
+            } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
+                device = AUDIO_DEVICE_IN_USB_DEVICE;
+            } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+                device = AUDIO_DEVICE_IN_BUILTIN_MIC;
+            }
+            break;
+
+        case AUDIO_POLICY_FORCE_SPEAKER:
+            if (availableDeviceTypes & AUDIO_DEVICE_IN_BACK_MIC) {
+                device = AUDIO_DEVICE_IN_BACK_MIC;
+            } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+                device = AUDIO_DEVICE_IN_BUILTIN_MIC;
+            }
+            break;
+        }
+        break;
+
+    case AUDIO_SOURCE_VOICE_RECOGNITION:
+    case AUDIO_SOURCE_HOTWORD:
+        if (mForceUse[AUDIO_POLICY_FORCE_FOR_RECORD] == AUDIO_POLICY_FORCE_BT_SCO &&
+                availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
+            device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
+        } else if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) {
+            device = AUDIO_DEVICE_IN_WIRED_HEADSET;
+        } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
+            device = AUDIO_DEVICE_IN_USB_DEVICE;
+        } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+            device = AUDIO_DEVICE_IN_BUILTIN_MIC;
+        }
+        break;
+    case AUDIO_SOURCE_CAMCORDER:
+        if (availableDeviceTypes & AUDIO_DEVICE_IN_BACK_MIC) {
+            device = AUDIO_DEVICE_IN_BACK_MIC;
+        } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+            device = AUDIO_DEVICE_IN_BUILTIN_MIC;
+        }
+        break;
+    case AUDIO_SOURCE_VOICE_DOWNLINK:
+    case AUDIO_SOURCE_VOICE_CALL:
+        if (availableDeviceTypes & AUDIO_DEVICE_IN_VOICE_CALL) {
+            device = AUDIO_DEVICE_IN_VOICE_CALL;
+        }
+        break;
+    case AUDIO_SOURCE_REMOTE_SUBMIX:
+        if (availableDeviceTypes & AUDIO_DEVICE_IN_REMOTE_SUBMIX) {
+            device = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
+        }
+        break;
+     case AUDIO_SOURCE_FM_TUNER:
+        if (availableDeviceTypes & AUDIO_DEVICE_IN_FM_TUNER) {
+            device = AUDIO_DEVICE_IN_FM_TUNER;
+        }
+        break;
+    default:
+        ALOGW("getDeviceForInputSource() invalid input source %d", inputSource);
+        break;
+    }
+    ALOGV("getDeviceForInputSource()input source %d, device %08x", inputSource, device);
+    return device;
+}
+
+template <>
+AudioPolicyManagerInterface *Engine::queryInterface()
+{
+    return &mManagerInterface;
+}
+
+} // namespace audio_policy
+} // namespace android
+
+
diff --git a/services/audiopolicy/enginedefault/src/Engine.h b/services/audiopolicy/enginedefault/src/Engine.h
new file mode 100755
index 0000000..f44556c
--- /dev/null
+++ b/services/audiopolicy/enginedefault/src/Engine.h
@@ -0,0 +1,158 @@
+/*
+ * 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 "AudioPolicyManagerInterface.h"
+#include "Gains.h"
+#include <AudioGain.h>
+#include <policy.h>
+
+namespace android
+{
+
+class AudioPolicyManagerObserver;
+
+namespace audio_policy
+{
+
+class Engine
+{
+public:
+    Engine();
+    virtual ~Engine();
+
+    template <class RequestedInterface>
+    RequestedInterface *queryInterface();
+
+private:
+    /// Interface members
+    class ManagerInterfaceImpl : public AudioPolicyManagerInterface
+    {
+    public:
+        ManagerInterfaceImpl(Engine *policyEngine)
+            : mPolicyEngine(policyEngine) {}
+
+        virtual void setObserver(AudioPolicyManagerObserver *observer)
+        {
+            mPolicyEngine->setObserver(observer);
+        }
+        virtual status_t initCheck()
+        {
+            return mPolicyEngine->initCheck();
+        }
+        virtual audio_devices_t getDeviceForInputSource(audio_source_t inputSource) const
+        {
+            return mPolicyEngine->getDeviceForInputSource(inputSource);
+        }
+        virtual audio_devices_t getDeviceForStrategy(routing_strategy strategy) const
+        {
+            return mPolicyEngine->getDeviceForStrategy(strategy);
+        }
+        virtual routing_strategy getStrategyForStream(audio_stream_type_t stream)
+        {
+            return mPolicyEngine->getStrategyForStream(stream);
+        }
+        virtual routing_strategy getStrategyForUsage(audio_usage_t usage)
+        {
+            return mPolicyEngine->getStrategyForUsage(usage);
+        }
+        virtual status_t setPhoneState(audio_mode_t mode)
+        {
+            return mPolicyEngine->setPhoneState(mode);
+        }
+        virtual audio_mode_t getPhoneState() const
+        {
+            return mPolicyEngine->getPhoneState();
+        }
+        virtual status_t setForceUse(audio_policy_force_use_t usage,
+                                     audio_policy_forced_cfg_t config)
+        {
+            return mPolicyEngine->setForceUse(usage, config);
+        }
+        virtual audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage) const
+        {
+            return mPolicyEngine->getForceUse(usage);
+        }
+        virtual status_t setDeviceConnectionState(const sp<DeviceDescriptor> /*devDesc*/,
+                                                  audio_policy_dev_state_t /*state*/)
+        {
+            return NO_ERROR;
+        }
+        virtual status_t initStreamVolume(audio_stream_type_t stream, int indexMin, int indexMax)
+        {
+            return mPolicyEngine->initStreamVolume(stream, indexMin, indexMax);
+        }
+        virtual void initializeVolumeCurves(bool isSpeakerDrcEnabled)
+        {
+            return mPolicyEngine->initializeVolumeCurves(isSpeakerDrcEnabled);
+        }
+        virtual float volIndexToAmpl(Volume::device_category deviceCategory,
+                                     audio_stream_type_t stream,int indexInUi)
+        {
+            return mPolicyEngine->volIndexToAmpl(deviceCategory, stream, indexInUi);
+        }
+    private:
+        Engine *mPolicyEngine;
+    } mManagerInterface;
+
+private:
+    /* Copy facilities are put private to disable copy. */
+    Engine(const Engine &object);
+    Engine &operator=(const Engine &object);
+
+    void setObserver(AudioPolicyManagerObserver *observer);
+
+    status_t initCheck();
+
+    inline bool isInCall() const
+    {
+        return is_state_in_call(mPhoneState);
+    }
+
+    status_t setPhoneState(audio_mode_t mode);
+    audio_mode_t getPhoneState() const
+    {
+        return mPhoneState;
+    }
+    status_t setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config);
+    audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage) const
+    {
+        return mForceUse[usage];
+    }
+    status_t setDefaultDevice(audio_devices_t device);
+
+    routing_strategy getStrategyForStream(audio_stream_type_t stream);
+    routing_strategy getStrategyForUsage(audio_usage_t usage);
+    audio_devices_t getDeviceForStrategy(routing_strategy strategy) const;
+    audio_devices_t getDeviceForInputSource(audio_source_t inputSource) const;
+
+    float volIndexToAmpl(Volume::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);
+
+    audio_mode_t mPhoneState;  /**< current phone state. */
+
+    /** current forced use configuration. */
+    audio_policy_forced_cfg_t mForceUse[AUDIO_POLICY_FORCE_USE_CNT];
+
+    AudioPolicyManagerObserver *mApmObserver;
+};
+} // namespace audio_policy
+} // namespace android
+
diff --git a/services/audiopolicy/enginedefault/src/EngineInstance.cpp b/services/audiopolicy/enginedefault/src/EngineInstance.cpp
new file mode 100755
index 0000000..17e9832
--- /dev/null
+++ b/services/audiopolicy/enginedefault/src/EngineInstance.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <AudioPolicyManagerInterface.h>
+#include "AudioPolicyEngineInstance.h"
+#include "Engine.h"
+
+namespace android
+{
+namespace audio_policy
+{
+
+EngineInstance::EngineInstance()
+{
+}
+
+EngineInstance *EngineInstance::getInstance()
+{
+    static EngineInstance instance;
+    return &instance;
+}
+
+EngineInstance::~EngineInstance()
+{
+}
+
+Engine *EngineInstance::getEngine() const
+{
+    static Engine engine;
+    return &engine;
+}
+
+template <>
+AudioPolicyManagerInterface *EngineInstance::queryInterface() const
+{
+    return getEngine()->queryInterface<AudioPolicyManagerInterface>();
+}
+
+} // namespace audio_policy
+} // namespace android
+
diff --git a/services/audiopolicy/enginedefault/src/Gains.cpp b/services/audiopolicy/enginedefault/src/Gains.cpp
new file mode 100644
index 0000000..a684fdd
--- /dev/null
+++ b/services/audiopolicy/enginedefault/src/Gains.cpp
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "APM::Gains"
+//#define LOG_NDEBUG 0
+
+//#define VERY_VERBOSE_LOGGING
+#ifdef VERY_VERBOSE_LOGGING
+#define ALOGVV ALOGV
+#else
+#define ALOGVV(a...) do { } while(0)
+#endif
+
+#include "Gains.h"
+#include <Volume.h>
+#include <math.h>
+#include <utils/String8.h>
+
+namespace android {
+
+// Enginedefault
+const VolumeCurvePoint
+Gains::sDefaultVolumeCurve[Volume::VOLCNT] = {
+    {1, -49.5f}, {33, -33.5f}, {66, -17.0f}, {100, 0.0f}
+};
+
+
+const VolumeCurvePoint
+Gains::sDefaultMediaVolumeCurve[Volume::VOLCNT] = {
+    {1, -58.0f}, {20, -40.0f}, {60, -17.0f}, {100, 0.0f}
+};
+
+const VolumeCurvePoint
+Gains::sExtMediaSystemVolumeCurve[Volume::VOLCNT] = {
+    {1, -58.0f}, {20, -40.0f}, {60, -21.0f}, {100, -10.0f}
+};
+
+const VolumeCurvePoint
+Gains::sSpeakerMediaVolumeCurve[Volume::VOLCNT] = {
+    {1, -56.0f}, {20, -34.0f}, {60, -11.0f}, {100, 0.0f}
+};
+
+const VolumeCurvePoint
+Gains::sSpeakerMediaVolumeCurveDrc[Volume::VOLCNT] = {
+    {1, -55.0f}, {20, -43.0f}, {86, -12.0f}, {100, 0.0f}
+};
+
+const VolumeCurvePoint
+Gains::sSpeakerSonificationVolumeCurve[Volume::VOLCNT] = {
+    {1, -29.7f}, {33, -20.1f}, {66, -10.2f}, {100, 0.0f}
+};
+
+const VolumeCurvePoint
+Gains::sSpeakerSonificationVolumeCurveDrc[Volume::VOLCNT] = {
+    {1, -35.7f}, {33, -26.1f}, {66, -13.2f}, {100, 0.0f}
+};
+
+// AUDIO_STREAM_SYSTEM, AUDIO_STREAM_ENFORCED_AUDIBLE and AUDIO_STREAM_DTMF volume tracks
+// AUDIO_STREAM_RING on phones and AUDIO_STREAM_MUSIC on tablets.
+// AUDIO_STREAM_DTMF tracks AUDIO_STREAM_VOICE_CALL while in call (See AudioService.java).
+// The range is constrained between -24dB and -6dB over speaker and -30dB and -18dB over headset.
+
+const VolumeCurvePoint
+Gains::sDefaultSystemVolumeCurve[Volume::VOLCNT] = {
+    {1, -24.0f}, {33, -18.0f}, {66, -12.0f}, {100, -6.0f}
+};
+
+const VolumeCurvePoint
+Gains::sDefaultSystemVolumeCurveDrc[Volume::VOLCNT] = {
+    {1, -34.0f}, {33, -24.0f}, {66, -15.0f}, {100, -6.0f}
+};
+
+const VolumeCurvePoint
+Gains::sHeadsetSystemVolumeCurve[Volume::VOLCNT] = {
+    {1, -30.0f}, {33, -26.0f}, {66, -22.0f}, {100, -18.0f}
+};
+
+const VolumeCurvePoint
+Gains::sDefaultVoiceVolumeCurve[Volume::VOLCNT] = {
+    {0, -42.0f}, {33, -28.0f}, {66, -14.0f}, {100, 0.0f}
+};
+
+const VolumeCurvePoint
+Gains::sSpeakerVoiceVolumeCurve[Volume::VOLCNT] = {
+    {0, -24.0f}, {33, -16.0f}, {66, -8.0f}, {100, 0.0f}
+};
+
+const VolumeCurvePoint
+Gains::sLinearVolumeCurve[Volume::VOLCNT] = {
+    {0, -96.0f}, {33, -68.0f}, {66, -34.0f}, {100, 0.0f}
+};
+
+const VolumeCurvePoint
+Gains::sSilentVolumeCurve[Volume::VOLCNT] = {
+    {0, -96.0f}, {1, -96.0f}, {2, -96.0f}, {100, -96.0f}
+};
+
+const VolumeCurvePoint
+Gains::sFullScaleVolumeCurve[Volume::VOLCNT] = {
+    {0, 0.0f}, {1, 0.0f}, {2, 0.0f}, {100, 0.0f}
+};
+
+const VolumeCurvePoint *Gains::sVolumeProfiles[AUDIO_STREAM_CNT]
+                                                  [Volume::DEVICE_CATEGORY_CNT] = {
+    { // AUDIO_STREAM_VOICE_CALL
+        Gains::sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_HEADSET
+        Gains::sSpeakerVoiceVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+        Gains::sSpeakerVoiceVolumeCurve, // DEVICE_CATEGORY_EARPIECE
+        Gains::sDefaultMediaVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
+    },
+    { // AUDIO_STREAM_SYSTEM
+        Gains::sHeadsetSystemVolumeCurve, // DEVICE_CATEGORY_HEADSET
+        Gains::sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+        Gains::sDefaultSystemVolumeCurve,  // DEVICE_CATEGORY_EARPIECE
+        Gains::sExtMediaSystemVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
+    },
+    { // AUDIO_STREAM_RING
+        Gains::sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET
+        Gains::sSpeakerSonificationVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+        Gains::sDefaultVolumeCurve,  // DEVICE_CATEGORY_EARPIECE
+        Gains::sExtMediaSystemVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
+    },
+    { // AUDIO_STREAM_MUSIC
+        Gains::sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_HEADSET
+        Gains::sSpeakerMediaVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+        Gains::sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_EARPIECE
+        Gains::sDefaultMediaVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
+    },
+    { // AUDIO_STREAM_ALARM
+        Gains::sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET
+        Gains::sSpeakerSonificationVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+        Gains::sDefaultVolumeCurve,  // DEVICE_CATEGORY_EARPIECE
+        Gains::sExtMediaSystemVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
+    },
+    { // AUDIO_STREAM_NOTIFICATION
+        Gains::sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET
+        Gains::sSpeakerSonificationVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+        Gains::sDefaultVolumeCurve,  // DEVICE_CATEGORY_EARPIECE
+        Gains::sExtMediaSystemVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
+    },
+    { // AUDIO_STREAM_BLUETOOTH_SCO
+        Gains::sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_HEADSET
+        Gains::sSpeakerVoiceVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+        Gains::sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_EARPIECE
+        Gains::sDefaultMediaVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
+    },
+    { // AUDIO_STREAM_ENFORCED_AUDIBLE
+        Gains::sHeadsetSystemVolumeCurve, // DEVICE_CATEGORY_HEADSET
+        Gains::sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+        Gains::sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_EARPIECE
+        Gains::sExtMediaSystemVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
+    },
+    {  // AUDIO_STREAM_DTMF
+        Gains::sHeadsetSystemVolumeCurve, // DEVICE_CATEGORY_HEADSET
+        Gains::sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+        Gains::sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_EARPIECE
+        Gains::sExtMediaSystemVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
+    },
+    { // AUDIO_STREAM_TTS
+      // "Transmitted Through Speaker": always silent except on DEVICE_CATEGORY_SPEAKER
+        Gains::sSilentVolumeCurve, // DEVICE_CATEGORY_HEADSET
+        Gains::sLinearVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+        Gains::sSilentVolumeCurve, // DEVICE_CATEGORY_EARPIECE
+        Gains::sSilentVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
+    },
+    { // AUDIO_STREAM_ACCESSIBILITY
+        Gains::sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_HEADSET
+        Gains::sSpeakerMediaVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+        Gains::sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_EARPIECE
+        Gains::sDefaultMediaVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
+    },
+    { // AUDIO_STREAM_REROUTING
+        Gains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_HEADSET
+        Gains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+        Gains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_EARPIECE
+        Gains::sFullScaleVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
+    },
+    { // AUDIO_STREAM_PATCH
+        Gains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_HEADSET
+        Gains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+        Gains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_EARPIECE
+        Gains::sFullScaleVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
+    },
+};
+
+//static
+float Gains::volIndexToAmpl(audio_devices_t device, const StreamDescriptor& streamDesc,
+        int indexInUi)
+{
+    Volume::device_category deviceCategory = Volume::getDeviceCategory(device);
+    const VolumeCurvePoint *curve = streamDesc.getVolumeCurvePoint(deviceCategory);
+
+    // the volume index in the UI is relative to the min and max volume indices for this stream type
+    int nbSteps = 1 + curve[Volume::VOLMAX].mIndex -
+            curve[Volume::VOLMIN].mIndex;
+    int volIdx = (nbSteps * (indexInUi - streamDesc.getVolumeIndexMin())) /
+            (streamDesc.getVolumeIndexMax() - streamDesc.getVolumeIndexMin());
+
+    // 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;
+    } else if (volIdx < curve[Volume::VOLKNEE1].mIndex) {
+        segment = 0;
+    } else if (volIdx < curve[Volume::VOLKNEE2].mIndex) {
+        segment = 1;
+    } else if (volIdx <= curve[Volume::VOLMAX].mIndex) {
+        segment = 2;
+    } else {                                                               // out of bounds
+        return 1.0f;
+    }
+
+    // linear interpolation in the attenuation table in dB
+    float decibels = curve[segment].mDBAttenuation +
+            ((float)(volIdx - curve[segment].mIndex)) *
+                ( (curve[segment+1].mDBAttenuation -
+                        curve[segment].mDBAttenuation) /
+                    ((float)(curve[segment+1].mIndex -
+                            curve[segment].mIndex)) );
+
+    float amplification = exp( decibels * 0.115129f); // exp( dB * ln(10) / 20 )
+
+    ALOGVV("VOLUME vol index=[%d %d %d], dB=[%.1f %.1f %.1f] ampl=%.5f",
+            curve[segment].mIndex, volIdx,
+            curve[segment+1].mIndex,
+            curve[segment].mDBAttenuation,
+            decibels,
+            curve[segment+1].mDBAttenuation,
+            amplification);
+
+    return amplification;
+}
+
+}; // namespace android
diff --git a/services/audiopolicy/enginedefault/src/Gains.h b/services/audiopolicy/enginedefault/src/Gains.h
new file mode 100644
index 0000000..b5601ca
--- /dev/null
+++ b/services/audiopolicy/enginedefault/src/Gains.h
@@ -0,0 +1,59 @@
+/*
+ * 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 <StreamDescriptor.h>
+#include <utils/KeyedVector.h>
+#include <system/audio.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+class StreamDescriptor;
+
+class Gains
+{
+public :
+    static float volIndexToAmpl(audio_devices_t device, const StreamDescriptor& streamDesc,
+                    int indexInUi);
+
+    // default volume curve
+    static const VolumeCurvePoint sDefaultVolumeCurve[Volume::VOLCNT];
+    // default volume curve for media strategy
+    static const VolumeCurvePoint sDefaultMediaVolumeCurve[Volume::VOLCNT];
+    // volume curve for non-media audio on ext media outputs (HDMI, Line, etc)
+    static const VolumeCurvePoint sExtMediaSystemVolumeCurve[Volume::VOLCNT];
+    // volume curve for media strategy on speakers
+    static const VolumeCurvePoint sSpeakerMediaVolumeCurve[Volume::VOLCNT];
+    static const VolumeCurvePoint sSpeakerMediaVolumeCurveDrc[Volume::VOLCNT];
+    // volume curve for sonification strategy on speakers
+    static const VolumeCurvePoint sSpeakerSonificationVolumeCurve[Volume::VOLCNT];
+    static const VolumeCurvePoint sSpeakerSonificationVolumeCurveDrc[Volume::VOLCNT];
+    static const VolumeCurvePoint sDefaultSystemVolumeCurve[Volume::VOLCNT];
+    static const VolumeCurvePoint sDefaultSystemVolumeCurveDrc[Volume::VOLCNT];
+    static const VolumeCurvePoint sHeadsetSystemVolumeCurve[Volume::VOLCNT];
+    static const VolumeCurvePoint sDefaultVoiceVolumeCurve[Volume::VOLCNT];
+    static const VolumeCurvePoint sSpeakerVoiceVolumeCurve[Volume::VOLCNT];
+    static const VolumeCurvePoint sLinearVolumeCurve[Volume::VOLCNT];
+    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];
+};
+
+}; // namespace android
diff --git a/services/audiopolicy/managerdefault/AudioInputDescriptor.cpp b/services/audiopolicy/managerdefault/AudioInputDescriptor.cpp
deleted file mode 100644
index f4054c8..0000000
--- a/services/audiopolicy/managerdefault/AudioInputDescriptor.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "APM::AudioInputDescriptor"
-//#define LOG_NDEBUG 0
-
-#include "AudioPolicyManager.h"
-
-namespace android {
-
-AudioInputDescriptor::AudioInputDescriptor(const sp<IOProfile>& profile)
-    : mId(0), mIoHandle(0),
-      mDevice(AUDIO_DEVICE_NONE), mPolicyMix(NULL), mPatchHandle(0), mRefCount(0),
-      mInputSource(AUDIO_SOURCE_DEFAULT), mProfile(profile), mIsSoundTrigger(false)
-{
-    if (profile != NULL) {
-        mSamplingRate = profile->pickSamplingRate();
-        mFormat = profile->pickFormat();
-        mChannelMask = profile->pickChannelMask();
-        if (profile->mGains.size() > 0) {
-            profile->mGains[0]->getDefaultConfig(&mGain);
-        }
-    }
-}
-
-void AudioInputDescriptor::toAudioPortConfig(
-                                                   struct audio_port_config *dstConfig,
-                                                   const struct audio_port_config *srcConfig) const
-{
-    ALOG_ASSERT(mProfile != 0,
-                "toAudioPortConfig() called on input with null profile %d", mIoHandle);
-    dstConfig->config_mask = AUDIO_PORT_CONFIG_SAMPLE_RATE|AUDIO_PORT_CONFIG_CHANNEL_MASK|
-                            AUDIO_PORT_CONFIG_FORMAT|AUDIO_PORT_CONFIG_GAIN;
-    if (srcConfig != NULL) {
-        dstConfig->config_mask |= srcConfig->config_mask;
-    }
-
-    AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig);
-
-    dstConfig->id = mId;
-    dstConfig->role = AUDIO_PORT_ROLE_SINK;
-    dstConfig->type = AUDIO_PORT_TYPE_MIX;
-    dstConfig->ext.mix.hw_module = mProfile->mModule->mHandle;
-    dstConfig->ext.mix.handle = mIoHandle;
-    dstConfig->ext.mix.usecase.source = mInputSource;
-}
-
-void AudioInputDescriptor::toAudioPort(
-                                                    struct audio_port *port) const
-{
-    ALOG_ASSERT(mProfile != 0, "toAudioPort() called on input with null profile %d", mIoHandle);
-
-    mProfile->toAudioPort(port);
-    port->id = mId;
-    toAudioPortConfig(&port->active_config);
-    port->ext.mix.hw_module = mProfile->mModule->mHandle;
-    port->ext.mix.handle = mIoHandle;
-    port->ext.mix.latency_class = AUDIO_LATENCY_NORMAL;
-}
-
-status_t AudioInputDescriptor::dump(int fd)
-{
-    const size_t SIZE = 256;
-    char buffer[SIZE];
-    String8 result;
-
-    snprintf(buffer, SIZE, " ID: %d\n", mId);
-    result.append(buffer);
-    snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate);
-    result.append(buffer);
-    snprintf(buffer, SIZE, " Format: %d\n", mFormat);
-    result.append(buffer);
-    snprintf(buffer, SIZE, " Channels: %08x\n", mChannelMask);
-    result.append(buffer);
-    snprintf(buffer, SIZE, " Devices %08x\n", mDevice);
-    result.append(buffer);
-    snprintf(buffer, SIZE, " Ref Count %d\n", mRefCount);
-    result.append(buffer);
-    snprintf(buffer, SIZE, " Open Ref Count %d\n", mOpenRefCount);
-    result.append(buffer);
-
-    write(fd, result.string(), result.size());
-
-    return NO_ERROR;
-}
-
-}; //namespace android
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 53ec0f6..797a2b4 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -24,20 +24,11 @@
 #define ALOGVV(a...) do { } while(0)
 #endif
 
-// A device mask for all audio input devices that are considered "virtual" when evaluating
-// active inputs in getActiveInput()
-#define APM_AUDIO_IN_DEVICE_VIRTUAL_ALL  (AUDIO_DEVICE_IN_REMOTE_SUBMIX|AUDIO_DEVICE_IN_FM_TUNER)
-// A device mask for all audio output devices that are considered "remote" when evaluating
-// active output devices in isStreamActiveRemotely()
-#define APM_AUDIO_OUT_DEVICE_REMOTE_ALL  AUDIO_DEVICE_OUT_REMOTE_SUBMIX
-// A device mask for all audio input and output devices where matching inputs/outputs on device
-// type alone is not enough: the address must match too
-#define APM_AUDIO_DEVICE_MATCH_ADDRESS_ALL (AUDIO_DEVICE_IN_REMOTE_SUBMIX | \
-                                            AUDIO_DEVICE_OUT_REMOTE_SUBMIX)
-
 #include <inttypes.h>
 #include <math.h>
 
+#include <AudioPolicyManagerInterface.h>
+#include <AudioPolicyEngineInstance.h>
 #include <cutils/properties.h>
 #include <utils/Log.h>
 #include <hardware/audio.h>
@@ -47,6 +38,8 @@
 #include <soundtrigger/SoundTrigger.h>
 #include "AudioPolicyManager.h"
 #include "audio_policy_conf.h"
+#include <ConfigParsingUtils.h>
+#include <policy.h>
 
 namespace android {
 
@@ -73,7 +66,8 @@
     // connect/disconnect only 1 device at a time
     if (!audio_is_output_device(device) && !audio_is_input_device(device)) return BAD_VALUE;
 
-    sp<DeviceDescriptor> devDesc = getDeviceDescriptor(device, device_address, device_name);
+    sp<DeviceDescriptor> devDesc =
+            mHwModules.getDeviceDescriptor(device, device_address, device_name);
 
     // handle output devices
     if (audio_is_output_device(device)) {
@@ -97,7 +91,7 @@
             // register new device as available
             index = mAvailableOutputDevices.add(devDesc);
             if (index >= 0) {
-                sp<HwModule> module = getModuleForDevice(device);
+                sp<HwModule> module = mHwModules.getModuleForDevice(device);
                 if (module == 0) {
                     ALOGD("setDeviceConnectionState() could not find HW module for device %08x",
                           device);
@@ -113,6 +107,9 @@
                 mAvailableOutputDevices.remove(devDesc);
                 return INVALID_OPERATION;
             }
+            // Propagate device availability to Engine
+            mEngine->setDeviceConnectionState(devDesc, state);
+
             // outputs should never be empty here
             ALOG_ASSERT(outputs.size() != 0, "setDeviceConnectionState():"
                     "checkOutputsForDevice() returned no outputs but status OK");
@@ -143,6 +140,9 @@
             mAvailableOutputDevices.remove(devDesc);
 
             checkOutputsForDevice(devDesc, state, outputs, devDesc->mAddress);
+
+            // Propagate device availability to Engine
+            mEngine->setDeviceConnectionState(devDesc, state);
             } break;
 
         default:
@@ -171,20 +171,20 @@
         }
 
         updateDevicesAndOutputs();
-        if (mPhoneState == AUDIO_MODE_IN_CALL) {
+        if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL) {
             audio_devices_t newDevice = getNewOutputDevice(mPrimaryOutput, false /*fromCache*/);
             updateCallRouting(newDevice);
         }
         for (size_t i = 0; i < mOutputs.size(); i++) {
             audio_io_handle_t output = mOutputs.keyAt(i);
-            if ((mPhoneState != AUDIO_MODE_IN_CALL) || (output != mPrimaryOutput)) {
+            if ((mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) || (output != mPrimaryOutput)) {
                 audio_devices_t newDevice = getNewOutputDevice(mOutputs.keyAt(i),
                                                                true /*fromCache*/);
                 // do not force device change on duplicated output because if device is 0, it will
                 // also force a device 0 for the two outputs it is duplicated to which may override
                 // a valid device selection on those outputs.
                 bool force = !mOutputs.valueAt(i)->isDuplicated()
-                        && (!deviceDistinguishesOnAddress(device)
+                        && (!device_distinguishes_on_address(device)
                                 // always force when disconnecting (a non-duplicated device)
                                 || (state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE));
                 setOutputDevice(output, newDevice, force, 0);
@@ -208,7 +208,7 @@
                 ALOGW("setDeviceConnectionState() device already connected: %d", device);
                 return INVALID_OPERATION;
             }
-            sp<HwModule> module = getModuleForDevice(device);
+            sp<HwModule> module = mHwModules.getModuleForDevice(device);
             if (module == NULL) {
                 ALOGW("setDeviceConnectionState(): could not find HW module for device %08x",
                       device);
@@ -230,6 +230,8 @@
             param.addInt(String8(AUDIO_PARAMETER_DEVICE_CONNECT), device);
             mpClientInterface->setParameters(AUDIO_IO_HANDLE_NONE, param.toString());
 
+            // Propagate device availability to Engine
+            mEngine->setDeviceConnectionState(devDesc, state);
         } break;
 
         // handle input device disconnection
@@ -249,6 +251,8 @@
             checkInputsForDevice(device, state, inputs, devDesc->mAddress);
             mAvailableInputDevices.remove(devDesc);
 
+            // Propagate device availability to Engine
+            mEngine->setDeviceConnectionState(devDesc, state);
         } break;
 
         default:
@@ -258,7 +262,7 @@
 
         closeAllInputs();
 
-        if (mPhoneState == AUDIO_MODE_IN_CALL) {
+        if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL) {
             audio_devices_t newDevice = getNewOutputDevice(mPrimaryOutput, false /*fromCache*/);
             updateCallRouting(newDevice);
         }
@@ -272,9 +276,10 @@
 }
 
 audio_policy_dev_state_t AudioPolicyManager::getDeviceConnectionState(audio_devices_t device,
-                                                  const char *device_address)
+                                                                      const char *device_address)
 {
-    sp<DeviceDescriptor> devDesc = getDeviceDescriptor(device, device_address, "");
+    sp<DeviceDescriptor> devDesc = mHwModules.getDeviceDescriptor(device, device_address, "");
+
     DeviceVector *deviceVector;
 
     if (audio_is_output_device(device)) {
@@ -285,44 +290,7 @@
         ALOGW("getDeviceConnectionState() invalid device type %08x", device);
         return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
     }
-
-    ssize_t index = deviceVector->indexOf(devDesc);
-    if (index >= 0) {
-        return AUDIO_POLICY_DEVICE_STATE_AVAILABLE;
-    } else {
-        return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
-    }
-}
-
-sp<DeviceDescriptor>  AudioPolicyManager::getDeviceDescriptor(const audio_devices_t device,
-                                                              const char *device_address,
-                                                              const char *device_name)
-{
-    String8 address = (device_address == NULL) ? String8("") : String8(device_address);
-    // handle legacy remote submix case where the address was not always specified
-    if (deviceDistinguishesOnAddress(device) && (address.length() == 0)) {
-        address = String8("0");
-    }
-
-    for (size_t i = 0; i < mHwModules.size(); i++) {
-        if (mHwModules[i]->mHandle == 0) {
-            continue;
-        }
-        DeviceVector deviceList =
-                mHwModules[i]->mDeclaredDevices.getDevicesFromTypeAddr(device, address);
-        if (!deviceList.isEmpty()) {
-            return deviceList.itemAt(0);
-        }
-        deviceList = mHwModules[i]->mDeclaredDevices.getDevicesFromType(device);
-        if (!deviceList.isEmpty()) {
-            return deviceList.itemAt(0);
-        }
-    }
-
-    sp<DeviceDescriptor> devDesc =
-            new DeviceDescriptor(String8(device_name != NULL ? device_name : ""), device);
-    devDesc->mAddress = address;
-    return devDesc;
+    return deviceVector->getDeviceConnectionState(devDesc);
 }
 
 void AudioPolicyManager::updateCallRouting(audio_devices_t rxDevice, int delayMs)
@@ -393,8 +361,7 @@
         ALOGW_IF(status != NO_ERROR, "updateCallRouting() error %d creating RX audio patch",
                                                status);
         if (status == NO_ERROR) {
-            mCallRxPatch = new AudioPatch((audio_patch_handle_t)nextUniqueId(),
-                                       &patch, mUidCached);
+            mCallRxPatch = new AudioPatch(&patch, mUidCached);
             mCallRxPatch->mAfPatchHandle = afPatchHandle;
             mCallRxPatch->mUid = mUidCached;
         }
@@ -436,8 +403,7 @@
         ALOGW_IF(status != NO_ERROR, "setPhoneState() error %d creating TX audio patch",
                                                status);
         if (status == NO_ERROR) {
-            mCallTxPatch = new AudioPatch((audio_patch_handle_t)nextUniqueId(),
-                                       &patch, mUidCached);
+            mCallTxPatch = new AudioPatch(&patch, mUidCached);
             mCallTxPatch->mAfPatchHandle = afPatchHandle;
             mCallTxPatch->mUid = mUidCached;
         }
@@ -447,16 +413,14 @@
 void AudioPolicyManager::setPhoneState(audio_mode_t state)
 {
     ALOGV("setPhoneState() state %d", state);
-    if (state < 0 || state >= AUDIO_MODE_CNT) {
-        ALOGW("setPhoneState() invalid state %d", state);
+    // store previous phone state for management of sonification strategy below
+    int oldState = mEngine->getPhoneState();
+
+    if (mEngine->setPhoneState(state) != NO_ERROR) {
+        ALOGW("setPhoneState() invalid or same state %d", state);
         return;
     }
-
-    if (state == mPhoneState ) {
-        ALOGW("setPhoneState() setting same state %d", state);
-        return;
-    }
-
+    /// Opens: can these line be executed after the switch of volume curves???
     // if leaving call state, handle special case of active streams
     // pertaining to sonification strategy see handleIncallSonification()
     if (isInCall()) {
@@ -472,36 +436,12 @@
         mpClientInterface->invalidateStream(AUDIO_STREAM_ACCESSIBILITY);
     }
 
-    // store previous phone state for management of sonification strategy below
-    int oldState = mPhoneState;
-    mPhoneState = state;
-    bool force = false;
-
-    // are we entering or starting a call
-    if (!isStateInCall(oldState) && isStateInCall(state)) {
-        ALOGV("  Entering call in setPhoneState()");
-        // force routing command to audio hardware when starting a call
-        // even if no device change is needed
-        force = true;
-        for (int j = 0; j < ApmGains::DEVICE_CATEGORY_CNT; j++) {
-            mStreams[AUDIO_STREAM_DTMF].mVolumeCurve[j] =
-                    ApmGains::sVolumeProfiles[AUDIO_STREAM_VOICE_CALL][j];
-        }
-    } else if (isStateInCall(oldState) && !isStateInCall(state)) {
-        ALOGV("  Exiting call in setPhoneState()");
-        // force routing command to audio hardware when exiting a call
-        // even if no device change is needed
-        force = true;
-        for (int j = 0; j < ApmGains::DEVICE_CATEGORY_CNT; j++) {
-            mStreams[AUDIO_STREAM_DTMF].mVolumeCurve[j] =
-                    ApmGains::sVolumeProfiles[AUDIO_STREAM_DTMF][j];
-        }
-    } else if (isStateInCall(state) && (state != oldState)) {
-        ALOGV("  Switching between telephony and VoIP in setPhoneState()");
-        // force routing command to audio hardware when switching between telephony and VoIP
-        // even if no device change is needed
-        force = true;
-    }
+    /**
+     * Switching to or from incall state or switching between telephony and VoIP lead to force
+     * routing command.
+     */
+    bool force = ((is_state_in_call(oldState) != is_state_in_call(state))
+                  || (is_state_in_call(state) && (state != oldState)));
 
     // check for device and output changes triggered by new phone state
     checkA2dpSuspend();
@@ -518,12 +458,12 @@
             // mute media and sonification strategies and delay device switch by the largest
             // latency of any output where either strategy is active.
             // This avoid sending the ring tone or music tail into the earpiece or headset.
-            if ((desc->isStrategyActive(STRATEGY_MEDIA,
-                                     SONIFICATION_HEADSET_MUSIC_DELAY,
-                                     sysTime) ||
-                    desc->isStrategyActive(STRATEGY_SONIFICATION,
-                                         SONIFICATION_HEADSET_MUSIC_DELAY,
-                                         sysTime)) &&
+            if ((isStrategyActive(desc, STRATEGY_MEDIA,
+                                  SONIFICATION_HEADSET_MUSIC_DELAY,
+                                  sysTime) ||
+                 isStrategyActive(desc, STRATEGY_SONIFICATION,
+                                  SONIFICATION_HEADSET_MUSIC_DELAY,
+                                  sysTime)) &&
                     (delayMs < (int)desc->mLatency*2)) {
                 delayMs = desc->mLatency*2;
             }
@@ -581,84 +521,35 @@
     }
 }
 
+audio_mode_t AudioPolicyManager::getPhoneState() {
+    return mEngine->getPhoneState();
+}
+
 void AudioPolicyManager::setForceUse(audio_policy_force_use_t usage,
                                          audio_policy_forced_cfg_t config)
 {
-    ALOGV("setForceUse() usage %d, config %d, mPhoneState %d", usage, config, mPhoneState);
+    ALOGV("setForceUse() usage %d, config %d, mPhoneState %d", usage, config, mEngine->getPhoneState());
 
-    bool forceVolumeReeval = false;
-    switch(usage) {
-    case AUDIO_POLICY_FORCE_FOR_COMMUNICATION:
-        if (config != AUDIO_POLICY_FORCE_SPEAKER && config != AUDIO_POLICY_FORCE_BT_SCO &&
-            config != AUDIO_POLICY_FORCE_NONE) {
-            ALOGW("setForceUse() invalid config %d for FOR_COMMUNICATION", config);
-            return;
-        }
-        forceVolumeReeval = true;
-        mForceUse[usage] = config;
-        break;
-    case AUDIO_POLICY_FORCE_FOR_MEDIA:
-        if (config != AUDIO_POLICY_FORCE_HEADPHONES && config != AUDIO_POLICY_FORCE_BT_A2DP &&
-            config != AUDIO_POLICY_FORCE_WIRED_ACCESSORY &&
-            config != AUDIO_POLICY_FORCE_ANALOG_DOCK &&
-            config != AUDIO_POLICY_FORCE_DIGITAL_DOCK && config != AUDIO_POLICY_FORCE_NONE &&
-            config != AUDIO_POLICY_FORCE_NO_BT_A2DP && config != AUDIO_POLICY_FORCE_SPEAKER ) {
-            ALOGW("setForceUse() invalid config %d for FOR_MEDIA", config);
-            return;
-        }
-        mForceUse[usage] = config;
-        break;
-    case AUDIO_POLICY_FORCE_FOR_RECORD:
-        if (config != AUDIO_POLICY_FORCE_BT_SCO && config != AUDIO_POLICY_FORCE_WIRED_ACCESSORY &&
-            config != AUDIO_POLICY_FORCE_NONE) {
-            ALOGW("setForceUse() invalid config %d for FOR_RECORD", config);
-            return;
-        }
-        mForceUse[usage] = config;
-        break;
-    case AUDIO_POLICY_FORCE_FOR_DOCK:
-        if (config != AUDIO_POLICY_FORCE_NONE && config != AUDIO_POLICY_FORCE_BT_CAR_DOCK &&
-            config != AUDIO_POLICY_FORCE_BT_DESK_DOCK &&
-            config != AUDIO_POLICY_FORCE_WIRED_ACCESSORY &&
-            config != AUDIO_POLICY_FORCE_ANALOG_DOCK &&
-            config != AUDIO_POLICY_FORCE_DIGITAL_DOCK) {
-            ALOGW("setForceUse() invalid config %d for FOR_DOCK", config);
-        }
-        forceVolumeReeval = true;
-        mForceUse[usage] = config;
-        break;
-    case AUDIO_POLICY_FORCE_FOR_SYSTEM:
-        if (config != AUDIO_POLICY_FORCE_NONE &&
-            config != AUDIO_POLICY_FORCE_SYSTEM_ENFORCED) {
-            ALOGW("setForceUse() invalid config %d for FOR_SYSTEM", config);
-        }
-        forceVolumeReeval = true;
-        mForceUse[usage] = config;
-        break;
-    case AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO:
-        if (config != AUDIO_POLICY_FORCE_NONE &&
-            config != AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED) {
-            ALOGW("setForceUse() invalid config %d forHDMI_SYSTEM_AUDIO", config);
-        }
-        mForceUse[usage] = config;
-        break;
-    default:
-        ALOGW("setForceUse() invalid usage %d", usage);
-        break;
+    if (mEngine->setForceUse(usage, config) != NO_ERROR) {
+        ALOGW("setForceUse() could not set force cfg %d for usage %d", config, usage);
+        return;
     }
+    bool forceVolumeReeval = (usage == AUDIO_POLICY_FORCE_FOR_COMMUNICATION) ||
+            (usage == AUDIO_POLICY_FORCE_FOR_DOCK) ||
+            (usage == AUDIO_POLICY_FORCE_FOR_SYSTEM);
 
     // check for device and output changes triggered by new force usage
     checkA2dpSuspend();
     checkOutputForAllStrategies();
     updateDevicesAndOutputs();
-    if (mPhoneState == AUDIO_MODE_IN_CALL) {
+    if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL) {
         audio_devices_t newDevice = getNewOutputDevice(mPrimaryOutput, true /*fromCache*/);
         updateCallRouting(newDevice);
     }
     for (size_t i = 0; i < mOutputs.size(); i++) {
         audio_io_handle_t output = mOutputs.keyAt(i);
         audio_devices_t newDevice = getNewOutputDevice(output, true /*fromCache*/);
-        if ((mPhoneState != AUDIO_MODE_IN_CALL) || (output != mPrimaryOutput)) {
+        if ((mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) || (output != mPrimaryOutput)) {
             setOutputDevice(output, newDevice, (newDevice != AUDIO_DEVICE_NONE));
         }
         if (forceVolumeReeval && (newDevice != AUDIO_DEVICE_NONE)) {
@@ -666,18 +557,13 @@
         }
     }
 
-    audio_io_handle_t activeInput = getActiveInput();
+    audio_io_handle_t activeInput = mInputs.getActiveInput();
     if (activeInput != 0) {
         setInputDevice(activeInput, getNewInputDevice(activeInput));
     }
 
 }
 
-audio_policy_forced_cfg_t AudioPolicyManager::getForceUse(audio_policy_force_use_t usage)
-{
-    return mForceUse[usage];
-}
-
 void AudioPolicyManager::setSystemProperty(const char* property, const char* value)
 {
     ALOGV("setSystemProperty() property %s, value %s", property, value);
@@ -711,11 +597,11 @@
 }
 
 audio_io_handle_t AudioPolicyManager::getOutput(audio_stream_type_t stream,
-                                    uint32_t samplingRate,
-                                    audio_format_t format,
-                                    audio_channel_mask_t channelMask,
-                                    audio_output_flags_t flags,
-                                    const audio_offload_info_t *offloadInfo)
+                                                uint32_t samplingRate,
+                                                audio_format_t format,
+                                                audio_channel_mask_t channelMask,
+                                                audio_output_flags_t flags,
+                                                const audio_offload_info_t *offloadInfo)
 {
     routing_strategy strategy = getStrategy(stream);
     audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/);
@@ -753,45 +639,16 @@
         }
         stream_type_to_audio_attributes(*stream, &attributes);
     }
-
-    for (size_t i = 0; i < mPolicyMixes.size(); i++) {
-        sp<AudioOutputDescriptor> desc;
-        if (mPolicyMixes[i]->mMix.mMixType == MIX_TYPE_PLAYERS) {
-            for (size_t j = 0; j < mPolicyMixes[i]->mMix.mCriteria.size(); j++) {
-                if ((RULE_MATCH_ATTRIBUTE_USAGE == mPolicyMixes[i]->mMix.mCriteria[j].mRule &&
-                        mPolicyMixes[i]->mMix.mCriteria[j].mAttr.mUsage == attributes.usage) ||
-                    (RULE_EXCLUDE_ATTRIBUTE_USAGE == mPolicyMixes[i]->mMix.mCriteria[j].mRule &&
-                        mPolicyMixes[i]->mMix.mCriteria[j].mAttr.mUsage != attributes.usage)) {
-                    desc = mPolicyMixes[i]->mOutput;
-                    break;
-                }
-                if (strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 &&
-                        strncmp(attributes.tags + strlen("addr="),
-                                mPolicyMixes[i]->mMix.mRegistrationId.string(),
-                                AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) {
-                    desc = mPolicyMixes[i]->mOutput;
-                    break;
-                }
-            }
-        } else if (mPolicyMixes[i]->mMix.mMixType == MIX_TYPE_RECORDERS) {
-            if (attributes.usage == AUDIO_USAGE_VIRTUAL_SOURCE &&
-                    strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 &&
-                    strncmp(attributes.tags + strlen("addr="),
-                            mPolicyMixes[i]->mMix.mRegistrationId.string(),
-                            AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) {
-                desc = mPolicyMixes[i]->mOutput;
-            }
+    sp<AudioOutputDescriptor> desc;
+    if (mPolicyMixes.getOutputForAttr(attributes, desc) == NO_ERROR) {
+        ALOG_ASSERT(desc != 0, "Invalid desc returned by getOutputForAttr");
+        if (!audio_is_linear_pcm(format)) {
+            return BAD_VALUE;
         }
-        if (desc != 0) {
-            if (!audio_is_linear_pcm(format)) {
-                return BAD_VALUE;
-            }
-            desc->mPolicyMix = &mPolicyMixes[i]->mMix;
-            *stream = streamTypefromAttributesInt(&attributes);
-            *output = desc->mIoHandle;
-            ALOGV("getOutputForAttr() returns output %d", *output);
-            return NO_ERROR;
-        }
+        *stream = streamTypefromAttributesInt(&attributes);
+        *output = desc->mIoHandle;
+        ALOGV("getOutputForAttr() returns output %d", *output);
+        return NO_ERROR;
     }
     if (attributes.usage == AUDIO_USAGE_VIRTUAL_SOURCE) {
         ALOGW("getOutputForAttr() no policy mix found for usage AUDIO_USAGE_VIRTUAL_SOURCE");
@@ -799,7 +656,7 @@
     }
 
     ALOGV("getOutputForAttr() usage=%d, content=%d, tag=%s flags=%08x",
-            attributes.usage, attributes.content_type, attributes.tags, attributes.flags);
+          attributes.usage, attributes.content_type, attributes.tags, attributes.flags);
 
     routing_strategy strategy = (routing_strategy) getStrategyForAttr(&attributes);
     audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/);
@@ -909,7 +766,7 @@
     // in the background.
 
     if (((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0) ||
-            !isNonOffloadableEffectEnabled()) {
+            !mEffects.isNonOffloadableEffectEnabled()) {
         profile = getProfileForDirectOutput(device,
                                            samplingRate,
                                            format,
@@ -1095,7 +952,7 @@
     uint32_t beaconMuteLatency = 0;
     if (stream == AUDIO_STREAM_TTS) {
         ALOGV("\t found BEACON stream");
-        if (isAnyOutputActive(AUDIO_STREAM_TTS /*streamToIgnore*/)) {
+        if (mOutputs.isAnyOutputActive(AUDIO_STREAM_TTS /*streamToIgnore*/)) {
             return INVALID_OPERATION;
         } else {
             beaconMuteLatency = handleEventForBeacon(STARTING_BEACON);
@@ -1274,7 +1131,7 @@
         sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(index);
         if (outputDesc->isActive()) {
             mpClientInterface->closeOutput(output);
-            mOutputs.removeItem(output);
+            removeOutput(output);
             mTestOutputs[testIndex] = 0;
         }
         return;
@@ -1332,19 +1189,13 @@
 
     if (inputSource == AUDIO_SOURCE_REMOTE_SUBMIX &&
             strncmp(attr->tags, "addr=", strlen("addr=")) == 0) {
+        status_t ret = mPolicyMixes.getInputMixForAttr(*attr, policyMix);
+        if (ret != NO_ERROR) {
+            return ret;
+        }
+        *inputType = API_INPUT_MIX_EXT_POLICY_REROUTE;
         device = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
         address = String8(attr->tags + strlen("addr="));
-        ssize_t index = mPolicyMixes.indexOfKey(address);
-        if (index < 0) {
-            ALOGW("getInputForAttr() no policy for address %s", address.string());
-            return BAD_VALUE;
-        }
-        if (mPolicyMixes[index]->mMix.mMixType != MIX_TYPE_PLAYERS) {
-            ALOGW("getInputForAttr() bad policy mix type for address %s", address.string());
-            return BAD_VALUE;
-        }
-        policyMix = &mPolicyMixes[index]->mMix;
-        *inputType = API_INPUT_MIX_EXT_POLICY_REROUTE;
     } else {
         device = getDeviceAndMixForInputSource(inputSource, &policyMix);
         if (device == AUDIO_DEVICE_NONE) {
@@ -1482,10 +1333,10 @@
     }
 
     // virtual input devices are compatible with other input devices
-    if (!isVirtualInputDevice(inputDesc->mDevice)) {
+    if (!is_virtual_input_device(inputDesc->mDevice)) {
 
         // for a non-virtual input device, check if there is another (non-virtual) active input
-        audio_io_handle_t activeInput = getActiveInput();
+        audio_io_handle_t activeInput = mInputs.getActiveInput();
         if (activeInput != 0 && activeInput != input) {
 
             // If the already active input uses AUDIO_SOURCE_HOTWORD then it is closed,
@@ -1503,7 +1354,7 @@
     }
 
     if (inputDesc->mRefCount == 0) {
-        if (activeInputsCount() == 0) {
+        if (mInputs.activeInputsCount() == 0) {
             SoundTrigger::setCaptureState(true);
         }
         setInputDevice(input, getNewInputDevice(input), true /* force */);
@@ -1575,7 +1426,7 @@
 
         resetInputDevice(input);
 
-        if (activeInputsCount() == 0) {
+        if (mInputs.activeInputsCount() == 0) {
             SoundTrigger::setCaptureState(false);
         }
     }
@@ -1642,25 +1493,20 @@
                                             int indexMax)
 {
     ALOGV("initStreamVolume() stream %d, min %d, max %d", stream , indexMin, indexMax);
-    if (indexMin < 0 || indexMin >= indexMax) {
-        ALOGW("initStreamVolume() invalid index limits for stream %d, min %d, max %d", stream , indexMin, indexMax);
-        return;
-    }
-    mStreams[stream].mIndexMin = indexMin;
-    mStreams[stream].mIndexMax = indexMax;
+    mEngine->initStreamVolume(stream, indexMin, indexMax);
     //FIXME: AUDIO_STREAM_ACCESSIBILITY volume follows AUDIO_STREAM_MUSIC for now
     if (stream == AUDIO_STREAM_MUSIC) {
-        mStreams[AUDIO_STREAM_ACCESSIBILITY].mIndexMin = indexMin;
-        mStreams[AUDIO_STREAM_ACCESSIBILITY].mIndexMax = indexMax;
+        mEngine->initStreamVolume(AUDIO_STREAM_ACCESSIBILITY, indexMin, indexMax);
     }
 }
 
 status_t AudioPolicyManager::setStreamVolumeIndex(audio_stream_type_t stream,
-                                                      int index,
-                                                      audio_devices_t device)
+                                                  int index,
+                                                  audio_devices_t device)
 {
 
-    if ((index < mStreams[stream].mIndexMin) || (index > mStreams[stream].mIndexMax)) {
+    if ((index < mStreams[stream].getVolumeIndexMin()) ||
+            (index > mStreams[stream].getVolumeIndexMax())) {
         return BAD_VALUE;
     }
     if (!audio_is_output_device(device)) {
@@ -1668,7 +1514,7 @@
     }
 
     // Force max volume if stream cannot be muted
-    if (!mStreams[stream].mCanBeMuted) index = mStreams[stream].mIndexMax;
+    if (!mStreams.canBeMuted(stream)) index = mStreams[stream].getVolumeIndexMax();
 
     ALOGV("setStreamVolumeIndex() stream %d, device %04x, index %d",
           stream, device, index);
@@ -1676,9 +1522,9 @@
     // if device is AUDIO_DEVICE_OUT_DEFAULT set default value and
     // clear all device specific values
     if (device == AUDIO_DEVICE_OUT_DEFAULT) {
-        mStreams[stream].mIndexCur.clear();
+        mStreams.clearCurrentVolumeIndex(stream);
     }
-    mStreams[stream].mIndexCur.add(device, index);
+    mStreams.addCurrentVolumeIndex(stream, device, index);
 
     // update volume on all outputs whose current device is also selected by the same
     // strategy as the device specified by the caller
@@ -1688,7 +1534,7 @@
     //FIXME: AUDIO_STREAM_ACCESSIBILITY volume follows AUDIO_STREAM_MUSIC for now
     audio_devices_t accessibilityDevice = AUDIO_DEVICE_NONE;
     if (stream == AUDIO_STREAM_MUSIC) {
-        mStreams[AUDIO_STREAM_ACCESSIBILITY].mIndexCur.add(device, index);
+        mStreams.addCurrentVolumeIndex(AUDIO_STREAM_ACCESSIBILITY, device, index);
         accessibilityDevice = getDeviceForStrategy(STRATEGY_ACCESSIBILITY, true /*fromCache*/);
     }
     if ((device != AUDIO_DEVICE_OUT_DEFAULT) &&
@@ -1697,8 +1543,7 @@
     }
     status_t status = NO_ERROR;
     for (size_t i = 0; i < mOutputs.size(); i++) {
-        audio_devices_t curDevice =
-                ApmGains::getDeviceForVolume(mOutputs.valueAt(i)->device());
+        audio_devices_t curDevice = Volume::getDeviceForVolume(mOutputs.valueAt(i)->device());
         if ((device == AUDIO_DEVICE_OUT_DEFAULT) || ((curDevice & strategyDevice) != 0)) {
             status_t volStatus = checkAndSetVolume(stream, index, mOutputs.keyAt(i), curDevice);
             if (volStatus != NO_ERROR) {
@@ -1728,7 +1573,7 @@
     if (device == AUDIO_DEVICE_OUT_DEFAULT) {
         device = getDeviceForStrategy(getStrategy(stream), true /*fromCache*/);
     }
-    device = ApmGains::getDeviceForVolume(device);
+    device = Volume::getDeviceForVolume(device);
 
     *index =  mStreams[stream].getVolumeIndex(device);
     ALOGV("getStreamVolumeIndex() stream %d device %08x index %d", stream, device, *index);
@@ -1805,137 +1650,7 @@
             return INVALID_OPERATION;
         }
     }
-
-    if (mTotalEffectsMemory + desc->memoryUsage > getMaxEffectsMemory()) {
-        ALOGW("registerEffect() memory limit exceeded for Fx %s, Memory %d KB",
-                desc->name, desc->memoryUsage);
-        return INVALID_OPERATION;
-    }
-    mTotalEffectsMemory += desc->memoryUsage;
-    ALOGV("registerEffect() effect %s, io %d, strategy %d session %d id %d",
-            desc->name, io, strategy, session, id);
-    ALOGV("registerEffect() memory %d, total memory %d", desc->memoryUsage, mTotalEffectsMemory);
-
-    sp<EffectDescriptor> effectDesc = new EffectDescriptor();
-    memcpy (&effectDesc->mDesc, desc, sizeof(effect_descriptor_t));
-    effectDesc->mIo = io;
-    effectDesc->mStrategy = (routing_strategy)strategy;
-    effectDesc->mSession = session;
-    effectDesc->mEnabled = false;
-
-    mEffects.add(id, effectDesc);
-
-    return NO_ERROR;
-}
-
-status_t AudioPolicyManager::unregisterEffect(int id)
-{
-    ssize_t index = mEffects.indexOfKey(id);
-    if (index < 0) {
-        ALOGW("unregisterEffect() unknown effect ID %d", id);
-        return INVALID_OPERATION;
-    }
-
-    sp<EffectDescriptor> effectDesc = mEffects.valueAt(index);
-
-    setEffectEnabled(effectDesc, false);
-
-    if (mTotalEffectsMemory < effectDesc->mDesc.memoryUsage) {
-        ALOGW("unregisterEffect() memory %d too big for total %d",
-                effectDesc->mDesc.memoryUsage, mTotalEffectsMemory);
-        effectDesc->mDesc.memoryUsage = mTotalEffectsMemory;
-    }
-    mTotalEffectsMemory -= effectDesc->mDesc.memoryUsage;
-    ALOGV("unregisterEffect() effect %s, ID %d, memory %d total memory %d",
-            effectDesc->mDesc.name, id, effectDesc->mDesc.memoryUsage, mTotalEffectsMemory);
-
-    mEffects.removeItem(id);
-
-    return NO_ERROR;
-}
-
-status_t AudioPolicyManager::setEffectEnabled(int id, bool enabled)
-{
-    ssize_t index = mEffects.indexOfKey(id);
-    if (index < 0) {
-        ALOGW("unregisterEffect() unknown effect ID %d", id);
-        return INVALID_OPERATION;
-    }
-
-    return setEffectEnabled(mEffects.valueAt(index), enabled);
-}
-
-status_t AudioPolicyManager::setEffectEnabled(const sp<EffectDescriptor>& effectDesc, bool enabled)
-{
-    if (enabled == effectDesc->mEnabled) {
-        ALOGV("setEffectEnabled(%s) effect already %s",
-             enabled?"true":"false", enabled?"enabled":"disabled");
-        return INVALID_OPERATION;
-    }
-
-    if (enabled) {
-        if (mTotalEffectsCpuLoad + effectDesc->mDesc.cpuLoad > getMaxEffectsCpuLoad()) {
-            ALOGW("setEffectEnabled(true) CPU Load limit exceeded for Fx %s, CPU %f MIPS",
-                 effectDesc->mDesc.name, (float)effectDesc->mDesc.cpuLoad/10);
-            return INVALID_OPERATION;
-        }
-        mTotalEffectsCpuLoad += effectDesc->mDesc.cpuLoad;
-        ALOGV("setEffectEnabled(true) total CPU %d", mTotalEffectsCpuLoad);
-    } else {
-        if (mTotalEffectsCpuLoad < effectDesc->mDesc.cpuLoad) {
-            ALOGW("setEffectEnabled(false) CPU load %d too high for total %d",
-                    effectDesc->mDesc.cpuLoad, mTotalEffectsCpuLoad);
-            effectDesc->mDesc.cpuLoad = mTotalEffectsCpuLoad;
-        }
-        mTotalEffectsCpuLoad -= effectDesc->mDesc.cpuLoad;
-        ALOGV("setEffectEnabled(false) total CPU %d", mTotalEffectsCpuLoad);
-    }
-    effectDesc->mEnabled = enabled;
-    return NO_ERROR;
-}
-
-bool AudioPolicyManager::isNonOffloadableEffectEnabled()
-{
-    for (size_t i = 0; i < mEffects.size(); i++) {
-        sp<EffectDescriptor> effectDesc = mEffects.valueAt(i);
-        if (effectDesc->mEnabled && (effectDesc->mStrategy == STRATEGY_MEDIA) &&
-                ((effectDesc->mDesc.flags & EFFECT_FLAG_OFFLOAD_SUPPORTED) == 0)) {
-            ALOGV("isNonOffloadableEffectEnabled() non offloadable effect %s enabled on session %d",
-                  effectDesc->mDesc.name, effectDesc->mSession);
-            return true;
-        }
-    }
-    return false;
-}
-
-bool AudioPolicyManager::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const
-{
-    nsecs_t sysTime = systemTime();
-    for (size_t i = 0; i < mOutputs.size(); i++) {
-        const sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(i);
-        if (outputDesc->isStreamActive(stream, inPastMs, sysTime)) {
-            return true;
-        }
-    }
-    return false;
-}
-
-bool AudioPolicyManager::isStreamActiveRemotely(audio_stream_type_t stream,
-                                                    uint32_t inPastMs) const
-{
-    nsecs_t sysTime = systemTime();
-    for (size_t i = 0; i < mOutputs.size(); i++) {
-        const sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(i);
-        if (((outputDesc->device() & APM_AUDIO_OUT_DEVICE_REMOTE_ALL) != 0) &&
-                outputDesc->isStreamActive(stream, inPastMs, sysTime)) {
-            // do not consider re routing (when the output is going to a dynamic policy)
-            // as "remote playback"
-            if (outputDesc->mPolicyMix == NULL) {
-                return true;
-            }
-        }
-    }
-    return false;
+    return mEffects.registerEffect(desc, io, strategy, session, id);
 }
 
 bool AudioPolicyManager::isSourceActive(audio_source_t source) const
@@ -2005,9 +1720,8 @@
 
     for (size_t i = 0; i < mixes.size(); i++) {
         String8 address = mixes[i].mRegistrationId;
-        ssize_t index = mPolicyMixes.indexOfKey(address);
-        if (index >= 0) {
-            ALOGE("registerPolicyMixes(): mix for address %s already registered", address.string());
+
+        if (mPolicyMixes.registerMix(address, mixes[i]) != NO_ERROR) {
             continue;
         }
         audio_config_t outputConfig = mixes[i].mFormat;
@@ -2020,9 +1734,7 @@
                                  AUDIO_DEVICE_OUT_REMOTE_SUBMIX, address);
         module->addInputProfile(address, &inputConfig,
                                  AUDIO_DEVICE_IN_REMOTE_SUBMIX, address);
-        sp<AudioPolicyMix> policyMix = new AudioPolicyMix();
-        policyMix->mMix = mixes[i];
-        mPolicyMixes.add(address, policyMix);
+
         if (mixes[i].mMixType == MIX_TYPE_PLAYERS) {
             setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
                                      AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
@@ -2055,14 +1767,11 @@
 
     for (size_t i = 0; i < mixes.size(); i++) {
         String8 address = mixes[i].mRegistrationId;
-        ssize_t index = mPolicyMixes.indexOfKey(address);
-        if (index < 0) {
-            ALOGE("unregisterPolicyMixes(): mix for address %s not registered", address.string());
+
+        if (mPolicyMixes.unregisterMix(address) != NO_ERROR) {
             continue;
         }
 
-        mPolicyMixes.removeItemsAt(index);
-
         if (getDeviceConnectionState(AUDIO_DEVICE_IN_REMOTE_SUBMIX, address.string()) ==
                                              AUDIO_POLICY_DEVICE_STATE_AVAILABLE)
         {
@@ -2096,87 +1805,32 @@
 
     snprintf(buffer, SIZE, " Primary Output: %d\n", mPrimaryOutput);
     result.append(buffer);
-    snprintf(buffer, SIZE, " Phone state: %d\n", mPhoneState);
+    snprintf(buffer, SIZE, " Phone state: %d\n", mEngine->getPhoneState());
     result.append(buffer);
     snprintf(buffer, SIZE, " Force use for communications %d\n",
-             mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION]);
+             mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION));
     result.append(buffer);
-    snprintf(buffer, SIZE, " Force use for media %d\n", mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA]);
+    snprintf(buffer, SIZE, " Force use for media %d\n", mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA));
     result.append(buffer);
-    snprintf(buffer, SIZE, " Force use for record %d\n", mForceUse[AUDIO_POLICY_FORCE_FOR_RECORD]);
+    snprintf(buffer, SIZE, " Force use for record %d\n", mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD));
     result.append(buffer);
-    snprintf(buffer, SIZE, " Force use for dock %d\n", mForceUse[AUDIO_POLICY_FORCE_FOR_DOCK]);
+    snprintf(buffer, SIZE, " Force use for dock %d\n", mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_DOCK));
     result.append(buffer);
-    snprintf(buffer, SIZE, " Force use for system %d\n", mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM]);
+    snprintf(buffer, SIZE, " Force use for system %d\n", mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM));
     result.append(buffer);
     snprintf(buffer, SIZE, " Force use for hdmi system audio %d\n",
-            mForceUse[AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO]);
-    result.append(buffer);
-
-    snprintf(buffer, SIZE, " Available output devices:\n");
+            mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO));
     result.append(buffer);
     write(fd, result.string(), result.size());
-    for (size_t i = 0; i < mAvailableOutputDevices.size(); i++) {
-        mAvailableOutputDevices[i]->dump(fd, 2, i);
-    }
-    snprintf(buffer, SIZE, "\n Available input devices:\n");
-    write(fd, buffer, strlen(buffer));
-    for (size_t i = 0; i < mAvailableInputDevices.size(); i++) {
-        mAvailableInputDevices[i]->dump(fd, 2, i);
-    }
 
-    snprintf(buffer, SIZE, "\nHW Modules dump:\n");
-    write(fd, buffer, strlen(buffer));
-    for (size_t i = 0; i < mHwModules.size(); i++) {
-        snprintf(buffer, SIZE, "- HW Module %zu:\n", i + 1);
-        write(fd, buffer, strlen(buffer));
-        mHwModules[i]->dump(fd);
-    }
-
-    snprintf(buffer, SIZE, "\nOutputs dump:\n");
-    write(fd, buffer, strlen(buffer));
-    for (size_t i = 0; i < mOutputs.size(); i++) {
-        snprintf(buffer, SIZE, "- Output %d dump:\n", mOutputs.keyAt(i));
-        write(fd, buffer, strlen(buffer));
-        mOutputs.valueAt(i)->dump(fd);
-    }
-
-    snprintf(buffer, SIZE, "\nInputs dump:\n");
-    write(fd, buffer, strlen(buffer));
-    for (size_t i = 0; i < mInputs.size(); i++) {
-        snprintf(buffer, SIZE, "- Input %d dump:\n", mInputs.keyAt(i));
-        write(fd, buffer, strlen(buffer));
-        mInputs.valueAt(i)->dump(fd);
-    }
-
-    snprintf(buffer, SIZE, "\nStreams dump:\n");
-    write(fd, buffer, strlen(buffer));
-    snprintf(buffer, SIZE,
-             " Stream  Can be muted  Index Min  Index Max  Index Cur [device : index]...\n");
-    write(fd, buffer, strlen(buffer));
-    for (size_t i = 0; i < AUDIO_STREAM_CNT; i++) {
-        snprintf(buffer, SIZE, " %02zu      ", i);
-        write(fd, buffer, strlen(buffer));
-        mStreams[i].dump(fd);
-    }
-
-    snprintf(buffer, SIZE, "\nTotal Effects CPU: %f MIPS, Total Effects memory: %d KB\n",
-            (float)mTotalEffectsCpuLoad/10, mTotalEffectsMemory);
-    write(fd, buffer, strlen(buffer));
-
-    snprintf(buffer, SIZE, "Registered effects:\n");
-    write(fd, buffer, strlen(buffer));
-    for (size_t i = 0; i < mEffects.size(); i++) {
-        snprintf(buffer, SIZE, "- Effect %d dump:\n", mEffects.keyAt(i));
-        write(fd, buffer, strlen(buffer));
-        mEffects.valueAt(i)->dump(fd);
-    }
-
-    snprintf(buffer, SIZE, "\nAudio Patches:\n");
-    write(fd, buffer, strlen(buffer));
-    for (size_t i = 0; i < mAudioPatches.size(); i++) {
-        mAudioPatches[i]->dump(fd, 2, i);
-    }
+    mAvailableOutputDevices.dump(fd, String8("output"));
+    mAvailableInputDevices.dump(fd, String8("input"));
+    mHwModules.dump(fd);
+    mOutputs.dump(fd);
+    mInputs.dump(fd);
+    mStreams.dump(fd);
+    mEffects.dump(fd);
+    mAudioPatches.dump(fd);
 
     return NO_ERROR;
 }
@@ -2233,7 +1887,7 @@
     // FIXME: We should check the audio session here but we do not have it in this context.
     // This may prevent offloading in rare situations where effects are left active by apps
     // in the background.
-    if (isNonOffloadableEffectEnabled()) {
+    if (mEffects.isNonOffloadableEffectEnabled()) {
         return false;
     }
 
@@ -2312,93 +1966,6 @@
     return NO_ERROR;
 }
 
-sp<AudioOutputDescriptor> AudioPolicyManager::getOutputFromId(
-                                                                    audio_port_handle_t id) const
-{
-    sp<AudioOutputDescriptor> outputDesc = NULL;
-    for (size_t i = 0; i < mOutputs.size(); i++) {
-        outputDesc = mOutputs.valueAt(i);
-        if (outputDesc->mId == id) {
-            break;
-        }
-    }
-    return outputDesc;
-}
-
-sp<AudioInputDescriptor> AudioPolicyManager::getInputFromId(
-                                                                    audio_port_handle_t id) const
-{
-    sp<AudioInputDescriptor> inputDesc = NULL;
-    for (size_t i = 0; i < mInputs.size(); i++) {
-        inputDesc = mInputs.valueAt(i);
-        if (inputDesc->mId == id) {
-            break;
-        }
-    }
-    return inputDesc;
-}
-
-sp <HwModule> AudioPolicyManager::getModuleForDevice(
-                                                                    audio_devices_t device) const
-{
-    sp <HwModule> module;
-
-    for (size_t i = 0; i < mHwModules.size(); i++) {
-        if (mHwModules[i]->mHandle == 0) {
-            continue;
-        }
-        if (audio_is_output_device(device)) {
-            for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++)
-            {
-                if (mHwModules[i]->mOutputProfiles[j]->mSupportedDevices.types() & device) {
-                    return mHwModules[i];
-                }
-            }
-        } else {
-            for (size_t j = 0; j < mHwModules[i]->mInputProfiles.size(); j++) {
-                if (mHwModules[i]->mInputProfiles[j]->mSupportedDevices.types() &
-                        device & ~AUDIO_DEVICE_BIT_IN) {
-                    return mHwModules[i];
-                }
-            }
-        }
-    }
-    return module;
-}
-
-sp <HwModule> AudioPolicyManager::getModuleFromName(const char *name) const
-{
-    sp <HwModule> module;
-
-    for (size_t i = 0; i < mHwModules.size(); i++)
-    {
-        if (strcmp(mHwModules[i]->mName, name) == 0) {
-            return mHwModules[i];
-        }
-    }
-    return module;
-}
-
-audio_devices_t AudioPolicyManager::availablePrimaryOutputDevices()
-{
-    sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(mPrimaryOutput);
-    audio_devices_t devices = outputDesc->mProfile->mSupportedDevices.types();
-    return devices & mAvailableOutputDevices.types();
-}
-
-audio_devices_t AudioPolicyManager::availablePrimaryInputDevices()
-{
-    audio_module_handle_t primaryHandle =
-                                mOutputs.valueFor(mPrimaryOutput)->mProfile->mModule->mHandle;
-    audio_devices_t devices = AUDIO_DEVICE_NONE;
-    for (size_t i = 0; i < mAvailableInputDevices.size(); i++) {
-        if (mAvailableInputDevices[i]->mModule->mHandle == primaryHandle) {
-            devices |= mAvailableInputDevices[i]->mDeviceType;
-        }
-    }
-    return devices;
-}
-
 status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch,
                                                audio_patch_handle_t *handle,
                                                uid_t uid)
@@ -2454,7 +2021,7 @@
     }
 
     if (patch->sources[0].type == AUDIO_PORT_TYPE_MIX) {
-        sp<AudioOutputDescriptor> outputDesc = getOutputFromId(patch->sources[0].id);
+        sp<AudioOutputDescriptor> outputDesc = mOutputs.getOutputFromId(patch->sources[0].id);
         if (outputDesc == NULL) {
             ALOGV("createAudioPatch() output not found for id %d", patch->sources[0].id);
             return BAD_VALUE;
@@ -2483,15 +2050,14 @@
                 return BAD_VALUE;
             }
 
-            if (!outputDesc->mProfile->isCompatibleProfile(devDesc->mDeviceType,
+            if (!outputDesc->mProfile->isCompatibleProfile(devDesc->type(),
                                                            devDesc->mAddress,
                                                            patch->sources[0].sample_rate,
-                                                         NULL,  // updatedSamplingRate
-                                                         patch->sources[0].format,
-                                                         patch->sources[0].channel_mask,
-                                                         AUDIO_OUTPUT_FLAG_NONE /*FIXME*/)) {
-                ALOGV("createAudioPatch() profile not supported for device %08x",
-                      devDesc->mDeviceType);
+                                                           NULL,  // updatedSamplingRate
+                                                           patch->sources[0].format,
+                                                           patch->sources[0].channel_mask,
+                                                           AUDIO_OUTPUT_FLAG_NONE /*FIXME*/)) {
+                ALOGV("createAudioPatch() profile not supported for device %08x", devDesc->type());
                 return INVALID_OPERATION;
             }
             devices.add(devDesc);
@@ -2523,7 +2089,7 @@
             if (patch->num_sinks > 1) {
                 return INVALID_OPERATION;
             }
-            sp<AudioInputDescriptor> inputDesc = getInputFromId(patch->sinks[0].id);
+            sp<AudioInputDescriptor> inputDesc = mInputs.getInputFromId(patch->sinks[0].id);
             if (inputDesc == NULL) {
                 return BAD_VALUE;
             }
@@ -2538,7 +2104,7 @@
                 return BAD_VALUE;
             }
 
-            if (!inputDesc->mProfile->isCompatibleProfile(devDesc->mDeviceType,
+            if (!inputDesc->mProfile->isCompatibleProfile(devDesc->type(),
                                                           devDesc->mAddress,
                                                           patch->sinks[0].sample_rate,
                                                           NULL, /*updatedSampleRate*/
@@ -2552,8 +2118,8 @@
             }
             // TODO: reconfigure output format and channels here
             ALOGV("createAudioPatch() setting device %08x on output %d",
-                                                  devDesc->mDeviceType, inputDesc->mIoHandle);
-            setInputDevice(inputDesc->mIoHandle, devDesc->mDeviceType, true, handle);
+                                                  devDesc->type(), inputDesc->mIoHandle);
+            setInputDevice(inputDesc->mIoHandle, devDesc->type(), true, handle);
             index = mAudioPatches.indexOfKey(*handle);
             if (index >= 0) {
                 if (patchDesc != 0 && patchDesc != mAudioPatches.valueAt(index)) {
@@ -2603,8 +2169,7 @@
                         return INVALID_OPERATION;
                     }
                     SortedVector<audio_io_handle_t> outputs =
-                                            getOutputsForDevice(sinkDeviceDesc->mDeviceType,
-                                                                mOutputs);
+                                            getOutputsForDevice(sinkDeviceDesc->type(), mOutputs);
                     // if the sink device is reachable via an opened output stream, request to go via
                     // this output stream by adding a second source to the patch description
                     audio_io_handle_t output = selectOutput(outputs,
@@ -2634,8 +2199,7 @@
                                                                   status, afPatchHandle);
             if (status == NO_ERROR) {
                 if (index < 0) {
-                    patchDesc = new AudioPatch((audio_patch_handle_t)nextUniqueId(),
-                                               &newPatch, uid);
+                    patchDesc = new AudioPatch(&newPatch, uid);
                     addAudioPatch(patchDesc->mHandle, patchDesc);
                 } else {
                     patchDesc->mPatch = newPatch;
@@ -2678,7 +2242,7 @@
     struct audio_patch *patch = &patchDesc->mPatch;
     patchDesc->mUid = mUidCached;
     if (patch->sources[0].type == AUDIO_PORT_TYPE_MIX) {
-        sp<AudioOutputDescriptor> outputDesc = getOutputFromId(patch->sources[0].id);
+        sp<AudioOutputDescriptor> outputDesc = mOutputs.getOutputFromId(patch->sources[0].id);
         if (outputDesc == NULL) {
             ALOGV("releaseAudioPatch() output not found for id %d", patch->sources[0].id);
             return BAD_VALUE;
@@ -2691,7 +2255,7 @@
                        NULL);
     } else if (patch->sources[0].type == AUDIO_PORT_TYPE_DEVICE) {
         if (patch->sinks[0].type == AUDIO_PORT_TYPE_MIX) {
-            sp<AudioInputDescriptor> inputDesc = getInputFromId(patch->sinks[0].id);
+            sp<AudioInputDescriptor> inputDesc = mInputs.getInputFromId(patch->sinks[0].id);
             if (inputDesc == NULL) {
                 ALOGV("releaseAudioPatch() input not found for id %d", patch->sinks[0].id);
                 return BAD_VALUE;
@@ -2721,30 +2285,11 @@
                                               struct audio_patch *patches,
                                               unsigned int *generation)
 {
-    if (num_patches == NULL || (*num_patches != 0 && patches == NULL) ||
-            generation == NULL) {
+    if (generation == NULL) {
         return BAD_VALUE;
     }
-    ALOGV("listAudioPatches() num_patches %d patches %p available patches %zu",
-          *num_patches, patches, mAudioPatches.size());
-    if (patches == NULL) {
-        *num_patches = 0;
-    }
-
-    size_t patchesWritten = 0;
-    size_t patchesMax = *num_patches;
-    for (size_t i = 0;
-            i  < mAudioPatches.size() && patchesWritten < patchesMax; i++) {
-        patches[patchesWritten] = mAudioPatches[i]->mPatch;
-        patches[patchesWritten++].id = mAudioPatches[i]->mHandle;
-        ALOGV("listAudioPatches() patch %zu num_sources %d num_sinks %d",
-              i, mAudioPatches[i]->mPatch.num_sources, mAudioPatches[i]->mPatch.num_sinks);
-    }
-    *num_patches = mAudioPatches.size();
-
     *generation = curAudioPortGeneration();
-    ALOGV("listAudioPatches() got %zu patches needed %d", patchesWritten, *num_patches);
-    return NO_ERROR;
+    return mAudioPatches.listAudioPatches(num_patches, patches);
 }
 
 status_t AudioPolicyManager::setAudioPortConfig(const struct audio_port_config *config)
@@ -2763,7 +2308,7 @@
     sp<AudioPortConfig> audioPortConfig;
     if (config->type == AUDIO_PORT_TYPE_MIX) {
         if (config->role == AUDIO_PORT_ROLE_SOURCE) {
-            sp<AudioOutputDescriptor> outputDesc = getOutputFromId(config->id);
+            sp<AudioOutputDescriptor> outputDesc = mOutputs.getOutputFromId(config->id);
             if (outputDesc == NULL) {
                 return BAD_VALUE;
             }
@@ -2772,7 +2317,7 @@
                         outputDesc->mIoHandle);
             audioPortConfig = outputDesc;
         } else if (config->role == AUDIO_PORT_ROLE_SINK) {
-            sp<AudioInputDescriptor> inputDesc = getInputFromId(config->id);
+            sp<AudioInputDescriptor> inputDesc = mInputs.getInputFromId(config->id);
             if (inputDesc == NULL) {
                 return BAD_VALUE;
             }
@@ -2829,79 +2374,24 @@
     *ioHandle = (audio_io_handle_t)mpClientInterface->newAudioUniqueId();
     *device = getDeviceAndMixForInputSource(AUDIO_SOURCE_HOTWORD);
 
-    mSoundTriggerSessions.add(*session, *ioHandle);
-
-    return NO_ERROR;
-}
-
-status_t AudioPolicyManager::releaseSoundTriggerSession(audio_session_t session)
-{
-    ssize_t index = mSoundTriggerSessions.indexOfKey(session);
-    if (index < 0) {
-        ALOGW("acquireSoundTriggerSession() session %d not registered", session);
-        return BAD_VALUE;
-    }
-
-    mSoundTriggerSessions.removeItem(session);
-    return NO_ERROR;
-}
-
-status_t AudioPolicyManager::addAudioPatch(audio_patch_handle_t handle,
-                                           const sp<AudioPatch>& patch)
-{
-    ssize_t index = mAudioPatches.indexOfKey(handle);
-
-    if (index >= 0) {
-        ALOGW("addAudioPatch() patch %d already in", handle);
-        return ALREADY_EXISTS;
-    }
-    mAudioPatches.add(handle, patch);
-    ALOGV("addAudioPatch() handle %d af handle %d num_sources %d num_sinks %d source handle %d"
-            "sink handle %d",
-          handle, patch->mAfPatchHandle, patch->mPatch.num_sources, patch->mPatch.num_sinks,
-          patch->mPatch.sources[0].id, patch->mPatch.sinks[0].id);
-    return NO_ERROR;
-}
-
-status_t AudioPolicyManager::removeAudioPatch(audio_patch_handle_t handle)
-{
-    ssize_t index = mAudioPatches.indexOfKey(handle);
-
-    if (index < 0) {
-        ALOGW("removeAudioPatch() patch %d not in", handle);
-        return ALREADY_EXISTS;
-    }
-    ALOGV("removeAudioPatch() handle %d af handle %d", handle,
-                      mAudioPatches.valueAt(index)->mAfPatchHandle);
-    mAudioPatches.removeItemsAt(index);
-    return NO_ERROR;
+    return mSoundTriggerSessions.acquireSession(*session, *ioHandle);
 }
 
 // ----------------------------------------------------------------------------
 // AudioPolicyManager
 // ----------------------------------------------------------------------------
-
-uint32_t AudioPolicyManager::nextUniqueId()
-{
-    return android_atomic_inc(&mNextUniqueId);
-}
-
 uint32_t AudioPolicyManager::nextAudioPortGeneration()
 {
     return android_atomic_inc(&mAudioPortGeneration);
 }
 
-int32_t volatile AudioPolicyManager::mNextUniqueId = 1;
-
 AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface)
     :
 #ifdef AUDIO_POLICY_TEST
     Thread(false),
 #endif //AUDIO_POLICY_TEST
     mPrimaryOutput((audio_io_handle_t)0),
-    mPhoneState(AUDIO_MODE_NORMAL),
     mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),
-    mTotalEffectsCpuLoad(0), mTotalEffectsMemory(0),
     mA2dpSuspended(false),
     mSpeakerDrcEnabled(false),
     mAudioPortGeneration(1),
@@ -2909,24 +2399,39 @@
     mBeaconPlayingRefCount(0),
     mBeaconMuted(false)
 {
+    audio_policy::EngineInstance *engineInstance = audio_policy::EngineInstance::getInstance();
+    if (!engineInstance) {
+        ALOGE("%s:  Could not get an instance of policy engine", __FUNCTION__);
+        return;
+    }
+    // Retrieve the Policy Manager Interface
+    mEngine = engineInstance->queryInterface<AudioPolicyManagerInterface>();
+    if (mEngine == NULL) {
+        ALOGE("%s: Failed to get Policy Engine Interface", __FUNCTION__);
+        return;
+    }
+    mEngine->setObserver(this);
+    status_t status = mEngine->initCheck();
+    ALOG_ASSERT(status == NO_ERROR, "Policy engine not initialized(err=%d)", status);
+
     mUidCached = getuid();
     mpClientInterface = clientInterface;
 
-    for (int i = 0; i < AUDIO_POLICY_FORCE_USE_CNT; i++) {
-        mForceUse[i] = AUDIO_POLICY_FORCE_NONE;
-    }
-
     mDefaultOutputDevice = new DeviceDescriptor(String8("Speaker"), AUDIO_DEVICE_OUT_SPEAKER);
-    if (loadAudioPolicyConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE) != NO_ERROR) {
-        if (loadAudioPolicyConfig(AUDIO_POLICY_CONFIG_FILE) != NO_ERROR) {
+    if (ConfigParsingUtils::loadAudioPolicyConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE,
+                 mHwModules, mAvailableInputDevices, mAvailableOutputDevices,
+                 mDefaultOutputDevice, mSpeakerDrcEnabled) != NO_ERROR) {
+        if (ConfigParsingUtils::loadAudioPolicyConfig(AUDIO_POLICY_CONFIG_FILE,
+                                  mHwModules, mAvailableInputDevices, mAvailableOutputDevices,
+                                  mDefaultOutputDevice, mSpeakerDrcEnabled) != NO_ERROR) {
             ALOGE("could not load audio policy configuration file, setting defaults");
             defaultAudioPolicyConfig();
         }
     }
     // mAvailableOutputDevices and mAvailableInputDevices now contain all attached devices
 
-    // must be done after reading the policy
-    initializeVolumeCurves();
+    // must be done after reading the policy (since conditionned by Speaker Drc Enabling)
+    mEngine->initializeVolumeCurves(mSpeakerDrcEnabled);
 
     // open all output streams needed to access attached devices
     audio_devices_t outputDeviceTypes = mAvailableOutputDevices.types();
@@ -2954,13 +2459,13 @@
                 continue;
             }
             audio_devices_t profileType = outProfile->mSupportedDevices.types();
-            if ((profileType & mDefaultOutputDevice->mDeviceType) != AUDIO_DEVICE_NONE) {
-                profileType = mDefaultOutputDevice->mDeviceType;
+            if ((profileType & mDefaultOutputDevice->type()) != AUDIO_DEVICE_NONE) {
+                profileType = mDefaultOutputDevice->type();
             } else {
                 // chose first device present in mSupportedDevices also part of
                 // outputDeviceTypes
                 for (size_t k = 0; k  < outProfile->mSupportedDevices.size(); k++) {
-                    profileType = outProfile->mSupportedDevices[k]->mDeviceType;
+                    profileType = outProfile->mSupportedDevices[k]->type();
                     if ((profileType & outputDeviceTypes) != 0) {
                         break;
                     }
@@ -2995,7 +2500,7 @@
                 outputDesc->mFormat = config.format;
 
                 for (size_t k = 0; k  < outProfile->mSupportedDevices.size(); k++) {
-                    audio_devices_t type = outProfile->mSupportedDevices[k]->mDeviceType;
+                    audio_devices_t type = outProfile->mSupportedDevices[k]->type();
                     ssize_t index =
                             mAvailableOutputDevices.indexOf(outProfile->mSupportedDevices[k]);
                     // give a valid ID to an attached device once confirmed it is reachable
@@ -3027,7 +2532,7 @@
             // inputDeviceTypes
             audio_devices_t profileType = AUDIO_DEVICE_NONE;
             for (size_t k = 0; k  < inProfile->mSupportedDevices.size(); k++) {
-                profileType = inProfile->mSupportedDevices[k]->mDeviceType;
+                profileType = inProfile->mSupportedDevices[k]->type();
                 if (profileType & inputDeviceTypes) {
                     break;
                 }
@@ -3063,7 +2568,7 @@
 
             if (status == NO_ERROR) {
                 for (size_t k = 0; k  < inProfile->mSupportedDevices.size(); k++) {
-                    audio_devices_t type = inProfile->mSupportedDevices[k]->mDeviceType;
+                    audio_devices_t type = inProfile->mSupportedDevices[k]->type();
                     ssize_t index =
                             mAvailableInputDevices.indexOf(inProfile->mSupportedDevices[k]);
                     // give a valid ID to an attached device once confirmed it is reachable
@@ -3082,23 +2587,29 @@
     // make sure all attached devices have been allocated a unique ID
     for (size_t i = 0; i  < mAvailableOutputDevices.size();) {
         if (!mAvailableOutputDevices[i]->isAttached()) {
-            ALOGW("Input device %08x unreachable", mAvailableOutputDevices[i]->mDeviceType);
+            ALOGW("Input device %08x unreachable", mAvailableOutputDevices[i]->type());
             mAvailableOutputDevices.remove(mAvailableOutputDevices[i]);
             continue;
         }
+        // The device is now validated and can be appended to the available devices of the engine
+        mEngine->setDeviceConnectionState(mAvailableOutputDevices[i],
+                                          AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
         i++;
     }
     for (size_t i = 0; i  < mAvailableInputDevices.size();) {
         if (!mAvailableInputDevices[i]->isAttached()) {
-            ALOGW("Input device %08x unreachable", mAvailableInputDevices[i]->mDeviceType);
+            ALOGW("Input device %08x unreachable", mAvailableInputDevices[i]->type());
             mAvailableInputDevices.remove(mAvailableInputDevices[i]);
             continue;
         }
+        // The device is now validated and can be appended to the available devices of the engine
+        mEngine->setDeviceConnectionState(mAvailableInputDevices[i],
+                                          AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
         i++;
     }
     // make sure default device is reachable
     if (mAvailableOutputDevices.indexOf(mDefaultOutputDevice) < 0) {
-        ALOGE("Default device %08x is unreachable", mDefaultOutputDevice->mDeviceType);
+        ALOGE("Default device %08x is unreachable", mDefaultOutputDevice->type());
     }
 
     ALOGE_IF((mPrimaryOutput == 0), "Failed to open primary output");
@@ -3254,8 +2765,7 @@
 
                 audio_module_handle_t moduleHandle = outputDesc->mModule->mHandle;
 
-                mOutputs.removeItem(mPrimaryOutput);
-
+                removeOutput(mPrimaryOutput);
                 sp<AudioOutputDescriptor> outputDesc = new AudioOutputDescriptor(NULL);
                 outputDesc->mDevice = AUDIO_DEVICE_OUT_SPEAKER;
                 audio_config_t config = AUDIO_CONFIG_INITIALIZER;
@@ -3314,16 +2824,19 @@
 
 void AudioPolicyManager::addOutput(audio_io_handle_t output, sp<AudioOutputDescriptor> outputDesc)
 {
-    outputDesc->mIoHandle = output;
-    outputDesc->mId = nextUniqueId();
+    outputDesc->setIoHandle(output);
     mOutputs.add(output, outputDesc);
     nextAudioPortGeneration();
 }
 
+void AudioPolicyManager::removeOutput(audio_io_handle_t output)
+{
+    mOutputs.removeItem(output);
+}
+
 void AudioPolicyManager::addInput(audio_io_handle_t input, sp<AudioInputDescriptor> inputDesc)
 {
-    inputDesc->mIoHandle = input;
-    inputDesc->mId = nextUniqueId();
+    inputDesc->setIoHandle(input);
     mInputs.add(input, inputDesc);
     nextAudioPortGeneration();
 }
@@ -3342,11 +2855,11 @@
 }
 
 status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor> devDesc,
-                                                       audio_policy_dev_state_t state,
-                                                       SortedVector<audio_io_handle_t>& outputs,
-                                                       const String8 address)
+                                                   audio_policy_dev_state_t state,
+                                                   SortedVector<audio_io_handle_t>& outputs,
+                                                   const String8 address)
 {
-    audio_devices_t device = devDesc->mDeviceType;
+    audio_devices_t device = devDesc->type();
     sp<AudioOutputDescriptor> desc;
     // erase all current sample rates, formats and channel masks
     devDesc->clearCapabilities();
@@ -3356,7 +2869,7 @@
         for (size_t i = 0; i < mOutputs.size(); i++) {
             desc = mOutputs.valueAt(i);
             if (!desc->isDuplicated() && (desc->mProfile->mSupportedDevices.types() & device)) {
-                if (!deviceDistinguishesOnAddress(device)) {
+                if (!device_distinguishes_on_address(device)) {
                     ALOGV("checkOutputsForDevice(): adding opened output %d", mOutputs.keyAt(i));
                     outputs.add(mOutputs.keyAt(i));
                 } else {
@@ -3376,7 +2889,7 @@
             {
                 sp<IOProfile> profile = mHwModules[i]->mOutputProfiles[j];
                 if (profile->mSupportedDevices.types() & device) {
-                    if (!deviceDistinguishesOnAddress(device) ||
+                    if (!device_distinguishes_on_address(device) ||
                             address == profile->mSupportedDevices[0]->mAddress) {
                         profiles.add(profile);
                         ALOGV("checkOutputsForDevice(): adding profile %zu from module %zu", j, i);
@@ -3512,15 +3025,15 @@
 
                 if (output != AUDIO_IO_HANDLE_NONE) {
                     addOutput(output, desc);
-                    if (deviceDistinguishesOnAddress(device) && address != "0") {
-                        ssize_t index = mPolicyMixes.indexOfKey(address);
-                        if (index >= 0) {
-                            mPolicyMixes[index]->mOutput = desc;
-                            desc->mPolicyMix = &mPolicyMixes[index]->mMix;
-                        } else {
+                    if (device_distinguishes_on_address(device) && address != "0") {
+                        sp<AudioPolicyMix> policyMix;
+                        if (mPolicyMixes.getAudioPolicyMix(address, policyMix) != NO_ERROR) {
                             ALOGE("checkOutputsForDevice() cannot find policy for address %s",
                                   address.string());
                         }
+                        policyMix->setOutput(desc);
+                        desc->mPolicyMix = &(policyMix->getMix());
+
                     } else if ((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) == 0) {
                         // no duplicated output for direct outputs and
                         // outputs used by dynamic policy mixes
@@ -3550,7 +3063,7 @@
                             ALOGW("checkOutputsForDevice() could not open dup output for %d and %d",
                                     mPrimaryOutput, output);
                             mpClientInterface->closeOutput(output);
-                            mOutputs.removeItem(output);
+                            removeOutput(output);
                             nextAudioPortGeneration();
                             output = AUDIO_IO_HANDLE_NONE;
                         }
@@ -3567,7 +3080,7 @@
                 outputs.add(output);
                 devDesc->importAudioPort(profile);
 
-                if (deviceDistinguishesOnAddress(device)) {
+                if (device_distinguishes_on_address(device)) {
                     ALOGV("checkOutputsForDevice(): setOutputDevice(dev=0x%x, addr=%s)",
                             device, address.string());
                     setOutputDevice(output, device, true/*force*/, 0/*delay*/,
@@ -3587,7 +3100,7 @@
             desc = mOutputs.valueAt(i);
             if (!desc->isDuplicated()) {
                 // exact match on device
-                if (deviceDistinguishesOnAddress(device) &&
+                if (device_distinguishes_on_address(device) &&
                         (desc->mProfile->mSupportedDevices.types() == device)) {
                     findIoHandlesByAddress(desc, device, address, outputs);
                 } else if (!(desc->mProfile->mSupportedDevices.types()
@@ -3630,9 +3143,9 @@
 }
 
 status_t AudioPolicyManager::checkInputsForDevice(audio_devices_t device,
-                                                      audio_policy_dev_state_t state,
-                                                      SortedVector<audio_io_handle_t>& inputs,
-                                                      const String8 address)
+                                                  audio_policy_dev_state_t state,
+                                                  SortedVector<audio_io_handle_t>& inputs,
+                                                  const String8 address)
 {
     sp<AudioInputDescriptor> desc;
     if (state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
@@ -3659,7 +3172,7 @@
                 sp<IOProfile> profile = mHwModules[module_idx]->mInputProfiles[profile_index];
 
                 if (profile->mSupportedDevices.types() & (device & ~AUDIO_DEVICE_BIT_IN)) {
-                    if (!deviceDistinguishesOnAddress(device) ||
+                    if (!device_distinguishes_on_address(device) ||
                             address == profile->mSupportedDevices[0]->mAddress) {
                         profiles.add(profile);
                         ALOGV("checkInputsForDevice(): adding profile %zu from module %zu",
@@ -3831,12 +3344,7 @@
         ALOGW("closeOutput() unknown output %d", output);
         return;
     }
-
-    for (size_t i = 0; i < mPolicyMixes.size(); i++) {
-        if (mPolicyMixes[i]->mOutput == outputDesc) {
-            mPolicyMixes[i]->mOutput.clear();
-        }
-    }
+    mPolicyMixes.closeOutput(outputDesc);
 
     // look for duplicated outputs connected to the output being removed.
     for (size_t i = 0; i < mOutputs.size(); i++) {
@@ -3862,7 +3370,7 @@
             ALOGV("closeOutput() closing also duplicated output %d", duplicatedOutput);
 
             mpClientInterface->closeOutput(duplicatedOutput);
-            mOutputs.removeItem(duplicatedOutput);
+            removeOutput(duplicatedOutput);
         }
     }
 
@@ -3881,7 +3389,7 @@
     mpClientInterface->setParameters(output, param.toString());
 
     mpClientInterface->closeOutput(output);
-    mOutputs.removeItem(output);
+    removeOutput(output);
     mPreviousOutputs = mOutputs;
 }
 
@@ -3910,7 +3418,7 @@
 }
 
 SortedVector<audio_io_handle_t> AudioPolicyManager::getOutputsForDevice(audio_devices_t device,
-                        DefaultKeyedVector<audio_io_handle_t, sp<AudioOutputDescriptor> > openOutputs)
+                                                                        AudioOutputCollection openOutputs)
 {
     SortedVector<audio_io_handle_t> outputs;
 
@@ -3927,7 +3435,7 @@
 }
 
 bool AudioPolicyManager::vectorsEqual(SortedVector<audio_io_handle_t>& outputs1,
-                                   SortedVector<audio_io_handle_t>& outputs2)
+                                      SortedVector<audio_io_handle_t>& outputs2)
 {
     if (outputs1.size() != outputs2.size()) {
         return false;
@@ -3971,7 +3479,7 @@
         // mute strategy while moving tracks from one output to another
         for (size_t i = 0; i < srcOutputs.size(); i++) {
             sp<AudioOutputDescriptor> desc = mOutputs.valueFor(srcOutputs[i]);
-            if (desc->isStrategyActive(strategy)) {
+            if (isStrategyActive(desc, strategy)) {
                 setStrategyMute(strategy, true, srcOutputs[i]);
                 setStrategyMute(strategy, false, srcOutputs[i], MUTE_TIME_MS, newDevice);
             }
@@ -4010,10 +3518,10 @@
 
 void AudioPolicyManager::checkOutputForAllStrategies()
 {
-    if (mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM] == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)
+    if (mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)
         checkOutputForStrategy(STRATEGY_ENFORCED_AUDIBLE);
     checkOutputForStrategy(STRATEGY_PHONE);
-    if (mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM] != AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)
+    if (mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) != AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)
         checkOutputForStrategy(STRATEGY_ENFORCED_AUDIBLE);
     checkOutputForStrategy(STRATEGY_SONIFICATION);
     checkOutputForStrategy(STRATEGY_SONIFICATION_RESPECTFUL);
@@ -4023,21 +3531,9 @@
     checkOutputForStrategy(STRATEGY_REROUTING);
 }
 
-audio_io_handle_t AudioPolicyManager::getA2dpOutput()
-{
-    for (size_t i = 0; i < mOutputs.size(); i++) {
-        sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(i);
-        if (!outputDesc->isDuplicated() && outputDesc->device() & AUDIO_DEVICE_OUT_ALL_A2DP) {
-            return mOutputs.keyAt(i);
-        }
-    }
-
-    return 0;
-}
-
 void AudioPolicyManager::checkA2dpSuspend()
 {
-    audio_io_handle_t a2dpOutput = getA2dpOutput();
+    audio_io_handle_t a2dpOutput = mOutputs.getA2dpOutput();
     if (a2dpOutput == 0) {
         mA2dpSuspended = false;
         return;
@@ -4061,20 +3557,20 @@
     //
     if (mA2dpSuspended) {
         if ((!isScoConnected ||
-             ((mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION] != AUDIO_POLICY_FORCE_BT_SCO) &&
-              (mForceUse[AUDIO_POLICY_FORCE_FOR_RECORD] != AUDIO_POLICY_FORCE_BT_SCO))) &&
-             ((mPhoneState != AUDIO_MODE_IN_CALL) &&
-              (mPhoneState != AUDIO_MODE_RINGTONE))) {
+             ((mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION) != AUDIO_POLICY_FORCE_BT_SCO) &&
+              (mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) != AUDIO_POLICY_FORCE_BT_SCO))) &&
+             ((mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) &&
+              (mEngine->getPhoneState() != AUDIO_MODE_RINGTONE))) {
 
             mpClientInterface->restoreOutput(a2dpOutput);
             mA2dpSuspended = false;
         }
     } else {
         if ((isScoConnected &&
-             ((mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION] == AUDIO_POLICY_FORCE_BT_SCO) ||
-              (mForceUse[AUDIO_POLICY_FORCE_FOR_RECORD] == AUDIO_POLICY_FORCE_BT_SCO))) ||
-             ((mPhoneState == AUDIO_MODE_IN_CALL) ||
-              (mPhoneState == AUDIO_MODE_RINGTONE))) {
+             ((mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION) == AUDIO_POLICY_FORCE_BT_SCO) ||
+              (mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) == AUDIO_POLICY_FORCE_BT_SCO))) ||
+             ((mEngine->getPhoneState() == AUDIO_MODE_IN_CALL) ||
+              (mEngine->getPhoneState() == AUDIO_MODE_RINGTONE))) {
 
             mpClientInterface->suspendOutput(a2dpOutput);
             mA2dpSuspended = true;
@@ -4117,27 +3613,27 @@
     //      use device for strategy DTMF
     // 9: the strategy for beacon, a.k.a. "transmitted through speaker" is active on the output:
     //      use device for strategy t-t-s
-    if (outputDesc->isStrategyActive(STRATEGY_ENFORCED_AUDIBLE) &&
-        mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM] == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED) {
+    if (isStrategyActive(outputDesc, STRATEGY_ENFORCED_AUDIBLE) &&
+        mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED) {
         device = getDeviceForStrategy(STRATEGY_ENFORCED_AUDIBLE, fromCache);
     } else if (isInCall() ||
-                    outputDesc->isStrategyActive(STRATEGY_PHONE)) {
+                    isStrategyActive(outputDesc, STRATEGY_PHONE)) {
         device = getDeviceForStrategy(STRATEGY_PHONE, fromCache);
-    } else if (outputDesc->isStrategyActive(STRATEGY_ENFORCED_AUDIBLE)) {
+    } else if (isStrategyActive(outputDesc, STRATEGY_ENFORCED_AUDIBLE)) {
         device = getDeviceForStrategy(STRATEGY_ENFORCED_AUDIBLE, fromCache);
-    } else if (outputDesc->isStrategyActive(STRATEGY_SONIFICATION)) {
+    } else if (isStrategyActive(outputDesc, STRATEGY_SONIFICATION)) {
         device = getDeviceForStrategy(STRATEGY_SONIFICATION, fromCache);
-    } else if (outputDesc->isStrategyActive(STRATEGY_SONIFICATION_RESPECTFUL)) {
+    } else if (isStrategyActive(outputDesc, STRATEGY_SONIFICATION_RESPECTFUL)) {
         device = getDeviceForStrategy(STRATEGY_SONIFICATION_RESPECTFUL, fromCache);
-    } else if (outputDesc->isStrategyActive(STRATEGY_ACCESSIBILITY)) {
+    } else if (isStrategyActive(outputDesc, STRATEGY_ACCESSIBILITY)) {
         device = getDeviceForStrategy(STRATEGY_ACCESSIBILITY, fromCache);
-    } else if (outputDesc->isStrategyActive(STRATEGY_MEDIA)) {
+    } else if (isStrategyActive(outputDesc, STRATEGY_MEDIA)) {
         device = getDeviceForStrategy(STRATEGY_MEDIA, fromCache);
-    } else if (outputDesc->isStrategyActive(STRATEGY_DTMF)) {
+    } else if (isStrategyActive(outputDesc, STRATEGY_DTMF)) {
         device = getDeviceForStrategy(STRATEGY_DTMF, fromCache);
-    } else if (outputDesc->isStrategyActive(STRATEGY_TRANSMITTED_THROUGH_SPEAKER)) {
+    } else if (isStrategyActive(outputDesc, STRATEGY_TRANSMITTED_THROUGH_SPEAKER)) {
         device = getDeviceForStrategy(STRATEGY_TRANSMITTED_THROUGH_SPEAKER, fromCache);
-    } else if (outputDesc->isStrategyActive(STRATEGY_REROUTING)) {
+    } else if (isStrategyActive(outputDesc, STRATEGY_REROUTING)) {
         device = getDeviceForStrategy(STRATEGY_REROUTING, fromCache);
     }
 
@@ -4182,7 +3678,7 @@
     SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(devices, mOutputs);
     for (size_t i = 0; i < outputs.size(); i++) {
         sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(outputs[i]);
-        if (outputDesc->isStrategyActive(strategy)) {
+        if (isStrategyActive(outputDesc, strategy)) {
             devices = outputDesc->device();
             break;
         }
@@ -4198,39 +3694,10 @@
     return devices;
 }
 
-routing_strategy AudioPolicyManager::getStrategy(
-        audio_stream_type_t stream) {
-
+routing_strategy AudioPolicyManager::getStrategy(audio_stream_type_t stream) const
+{
     ALOG_ASSERT(stream != AUDIO_STREAM_PATCH,"getStrategy() called for AUDIO_STREAM_PATCH");
-
-    // stream to strategy mapping
-    switch (stream) {
-    case AUDIO_STREAM_VOICE_CALL:
-    case AUDIO_STREAM_BLUETOOTH_SCO:
-        return STRATEGY_PHONE;
-    case AUDIO_STREAM_RING:
-    case AUDIO_STREAM_ALARM:
-        return STRATEGY_SONIFICATION;
-    case AUDIO_STREAM_NOTIFICATION:
-        return STRATEGY_SONIFICATION_RESPECTFUL;
-    case AUDIO_STREAM_DTMF:
-        return STRATEGY_DTMF;
-    default:
-        ALOGE("unknown stream type %d", stream);
-    case AUDIO_STREAM_SYSTEM:
-        // NOTE: SYSTEM stream uses MEDIA strategy because muting music and switching outputs
-        // while key clicks are played produces a poor result
-    case AUDIO_STREAM_MUSIC:
-        return STRATEGY_MEDIA;
-    case AUDIO_STREAM_ENFORCED_AUDIBLE:
-        return STRATEGY_ENFORCED_AUDIBLE;
-    case AUDIO_STREAM_TTS:
-        return STRATEGY_TRANSMITTED_THROUGH_SPEAKER;
-    case AUDIO_STREAM_ACCESSIBILITY:
-        return STRATEGY_ACCESSIBILITY;
-    case AUDIO_STREAM_REROUTING:
-        return STRATEGY_REROUTING;
-    }
+    return mEngine->getStrategyForStream(stream);
 }
 
 uint32_t AudioPolicyManager::getStrategyForAttr(const audio_attributes_t *attr) {
@@ -4241,45 +3708,8 @@
     if ((attr->flags & AUDIO_FLAG_AUDIBILITY_ENFORCED) == AUDIO_FLAG_AUDIBILITY_ENFORCED) {
         return (uint32_t) STRATEGY_ENFORCED_AUDIBLE;
     }
-
     // usage to strategy mapping
-    switch (attr->usage) {
-    case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
-        if (isStreamActive(AUDIO_STREAM_RING) || isStreamActive(AUDIO_STREAM_ALARM)) {
-            return (uint32_t) STRATEGY_SONIFICATION;
-        }
-        if (isInCall()) {
-            return (uint32_t) STRATEGY_PHONE;
-        }
-        return (uint32_t) STRATEGY_ACCESSIBILITY;
-
-    case AUDIO_USAGE_MEDIA:
-    case AUDIO_USAGE_GAME:
-    case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
-    case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
-        return (uint32_t) STRATEGY_MEDIA;
-
-    case AUDIO_USAGE_VOICE_COMMUNICATION:
-        return (uint32_t) STRATEGY_PHONE;
-
-    case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:
-        return (uint32_t) STRATEGY_DTMF;
-
-    case AUDIO_USAGE_ALARM:
-    case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE:
-        return (uint32_t) STRATEGY_SONIFICATION;
-
-    case AUDIO_USAGE_NOTIFICATION:
-    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
-    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
-    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
-    case AUDIO_USAGE_NOTIFICATION_EVENT:
-        return (uint32_t) STRATEGY_SONIFICATION_RESPECTFUL;
-
-    case AUDIO_USAGE_UNKNOWN:
-    default:
-        return (uint32_t) STRATEGY_MEDIA;
-    }
+    return static_cast<uint32_t>(mEngine->getStrategyForUsage(attr->usage));
 }
 
 void AudioPolicyManager::handleNotificationRoutingForStream(audio_stream_type_t stream) {
@@ -4293,21 +3723,6 @@
     }
 }
 
-bool AudioPolicyManager::isAnyOutputActive(audio_stream_type_t streamToIgnore) {
-    for (size_t s = 0 ; s < AUDIO_STREAM_CNT ; s++) {
-        if (s == (size_t) streamToIgnore) {
-            continue;
-        }
-        for (size_t i = 0; i < mOutputs.size(); i++) {
-            const sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(i);
-            if (outputDesc->mRefCount[s] != 0) {
-                return true;
-            }
-        }
-    }
-    return false;
-}
-
 uint32_t AudioPolicyManager::handleEventForBeacon(int event) {
     switch(event) {
     case STARTING_OUTPUT:
@@ -4362,292 +3777,14 @@
 }
 
 audio_devices_t AudioPolicyManager::getDeviceForStrategy(routing_strategy strategy,
-                                                             bool fromCache)
+                                                         bool fromCache)
 {
-    uint32_t device = AUDIO_DEVICE_NONE;
-
     if (fromCache) {
         ALOGVV("getDeviceForStrategy() from cache strategy %d, device %x",
               strategy, mDeviceForStrategy[strategy]);
         return mDeviceForStrategy[strategy];
     }
-    audio_devices_t availableOutputDeviceTypes = mAvailableOutputDevices.types();
-    switch (strategy) {
-
-    case STRATEGY_TRANSMITTED_THROUGH_SPEAKER:
-        device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPEAKER;
-        if (!device) {
-            ALOGE("getDeviceForStrategy() no device found for "\
-                    "STRATEGY_TRANSMITTED_THROUGH_SPEAKER");
-        }
-        break;
-
-    case STRATEGY_SONIFICATION_RESPECTFUL:
-        if (isInCall()) {
-            device = getDeviceForStrategy(STRATEGY_SONIFICATION, false /*fromCache*/);
-        } else if (isStreamActiveRemotely(AUDIO_STREAM_MUSIC,
-                SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) {
-            // while media is playing on a remote device, use the the sonification behavior.
-            // Note that we test this usecase before testing if media is playing because
-            //   the isStreamActive() method only informs about the activity of a stream, not
-            //   if it's for local playback. Note also that we use the same delay between both tests
-            device = getDeviceForStrategy(STRATEGY_SONIFICATION, false /*fromCache*/);
-            //user "safe" speaker if available instead of normal speaker to avoid triggering
-            //other acoustic safety mechanisms for notification
-            if (device == AUDIO_DEVICE_OUT_SPEAKER && (availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPEAKER_SAFE))
-                device = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
-        } else if (isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) {
-            // while media is playing (or has recently played), use the same device
-            device = getDeviceForStrategy(STRATEGY_MEDIA, false /*fromCache*/);
-        } else {
-            // when media is not playing anymore, fall back on the sonification behavior
-            device = getDeviceForStrategy(STRATEGY_SONIFICATION, false /*fromCache*/);
-            //user "safe" speaker if available instead of normal speaker to avoid triggering
-            //other acoustic safety mechanisms for notification
-            if (device == AUDIO_DEVICE_OUT_SPEAKER && (availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPEAKER_SAFE))
-                device = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
-        }
-
-        break;
-
-    case STRATEGY_DTMF:
-        if (!isInCall()) {
-            // when off call, DTMF strategy follows the same rules as MEDIA strategy
-            device = getDeviceForStrategy(STRATEGY_MEDIA, false /*fromCache*/);
-            break;
-        }
-        // when in call, DTMF and PHONE strategies follow the same rules
-        // FALL THROUGH
-
-    case STRATEGY_PHONE:
-        // Force use of only devices on primary output if:
-        // - in call AND
-        //   - cannot route from voice call RX OR
-        //   - audio HAL version is < 3.0 and TX device is on the primary HW module
-        if (mPhoneState == AUDIO_MODE_IN_CALL) {
-            audio_devices_t txDevice =
-                    getDeviceAndMixForInputSource(AUDIO_SOURCE_VOICE_COMMUNICATION);
-            sp<AudioOutputDescriptor> hwOutputDesc = mOutputs.valueFor(mPrimaryOutput);
-            if (((mAvailableInputDevices.types() &
-                    AUDIO_DEVICE_IN_TELEPHONY_RX & ~AUDIO_DEVICE_BIT_IN) == 0) ||
-                    (((txDevice & availablePrimaryInputDevices() & ~AUDIO_DEVICE_BIT_IN) != 0) &&
-                         (hwOutputDesc->getAudioPort()->mModule->mHalVersion <
-                             AUDIO_DEVICE_API_VERSION_3_0))) {
-                availableOutputDeviceTypes = availablePrimaryOutputDevices();
-            }
-        }
-        // for phone strategy, we first consider the forced use and then the available devices by order
-        // of priority
-        switch (mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION]) {
-        case AUDIO_POLICY_FORCE_BT_SCO:
-            if (!isInCall() || strategy != STRATEGY_DTMF) {
-                device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
-                if (device) break;
-            }
-            device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
-            if (device) break;
-            device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_SCO;
-            if (device) break;
-            // if SCO device is requested but no SCO device is available, fall back to default case
-            // FALL THROUGH
-
-        default:    // FORCE_NONE
-            // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP
-            if (!isInCall() &&
-                    (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
-                    (getA2dpOutput() != 0)) {
-                device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
-                if (device) break;
-                device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
-                if (device) break;
-            }
-            device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
-            if (device) break;
-            device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_WIRED_HEADSET;
-            if (device) break;
-            device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_DEVICE;
-            if (device) break;
-            if (!isInCall()) {
-                device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_ACCESSORY;
-                if (device) break;
-                device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
-                if (device) break;
-                device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_AUX_DIGITAL;
-                if (device) break;
-                device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
-                if (device) break;
-            }
-            device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_EARPIECE;
-            if (device) break;
-            device = mDefaultOutputDevice->mDeviceType;
-            if (device == AUDIO_DEVICE_NONE) {
-                ALOGE("getDeviceForStrategy() no device found for STRATEGY_PHONE");
-            }
-            break;
-
-        case AUDIO_POLICY_FORCE_SPEAKER:
-            // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to
-            // A2DP speaker when forcing to speaker output
-            if (!isInCall() &&
-                    (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
-                    (getA2dpOutput() != 0)) {
-                device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
-                if (device) break;
-            }
-            if (!isInCall()) {
-                device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_ACCESSORY;
-                if (device) break;
-                device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_DEVICE;
-                if (device) break;
-                device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
-                if (device) break;
-                device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_AUX_DIGITAL;
-                if (device) break;
-                device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
-                if (device) break;
-            }
-            device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_LINE;
-            if (device) break;
-            device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPEAKER;
-            if (device) break;
-            device = mDefaultOutputDevice->mDeviceType;
-            if (device == AUDIO_DEVICE_NONE) {
-                ALOGE("getDeviceForStrategy() no device found for STRATEGY_PHONE, FORCE_SPEAKER");
-            }
-            break;
-        }
-    break;
-
-    case STRATEGY_SONIFICATION:
-
-        // If incall, just select the STRATEGY_PHONE device: The rest of the behavior is handled by
-        // handleIncallSonification().
-        if (isInCall()) {
-            device = getDeviceForStrategy(STRATEGY_PHONE, false /*fromCache*/);
-            break;
-        }
-        // FALL THROUGH
-
-    case STRATEGY_ENFORCED_AUDIBLE:
-        // strategy STRATEGY_ENFORCED_AUDIBLE uses same routing policy as STRATEGY_SONIFICATION
-        // except:
-        //   - when in call where it doesn't default to STRATEGY_PHONE behavior
-        //   - in countries where not enforced in which case it follows STRATEGY_MEDIA
-
-        if ((strategy == STRATEGY_SONIFICATION) ||
-                (mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM] == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)) {
-            device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPEAKER;
-            if (device == AUDIO_DEVICE_NONE) {
-                ALOGE("getDeviceForStrategy() speaker device not found for STRATEGY_SONIFICATION");
-            }
-        }
-        // The second device used for sonification is the same as the device used by media strategy
-        // FALL THROUGH
-
-    // FIXME: STRATEGY_ACCESSIBILITY and STRATEGY_REROUTING follow STRATEGY_MEDIA for now
-    case STRATEGY_ACCESSIBILITY:
-        if (strategy == STRATEGY_ACCESSIBILITY) {
-            // do not route accessibility prompts to a digital output currently configured with a
-            // compressed format as they would likely not be mixed and dropped.
-            for (size_t i = 0; i < mOutputs.size(); i++) {
-                sp<AudioOutputDescriptor> desc = mOutputs.valueAt(i);
-                audio_devices_t devices = desc->device() &
-                    (AUDIO_DEVICE_OUT_HDMI | AUDIO_DEVICE_OUT_SPDIF | AUDIO_DEVICE_OUT_HDMI_ARC);
-                if (desc->isActive() && !audio_is_linear_pcm(desc->mFormat) &&
-                        devices != AUDIO_DEVICE_NONE) {
-                    availableOutputDeviceTypes = availableOutputDeviceTypes & ~devices;
-                }
-            }
-        }
-        // FALL THROUGH
-
-    case STRATEGY_REROUTING:
-    case STRATEGY_MEDIA: {
-        uint32_t device2 = AUDIO_DEVICE_NONE;
-        if (strategy != STRATEGY_SONIFICATION) {
-            // no sonification on remote submix (e.g. WFD)
-            if (mAvailableOutputDevices.getDevice(AUDIO_DEVICE_OUT_REMOTE_SUBMIX, String8("0")) != 0) {
-                device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
-            }
-        }
-        if ((device2 == AUDIO_DEVICE_NONE) &&
-                (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
-                (getA2dpOutput() != 0)) {
-            device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
-            if (device2 == AUDIO_DEVICE_NONE) {
-                device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
-            }
-            if (device2 == AUDIO_DEVICE_NONE) {
-                device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
-            }
-        }
-        if ((device2 == AUDIO_DEVICE_NONE) &&
-            (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] == AUDIO_POLICY_FORCE_SPEAKER)) {
-            device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPEAKER;
-        }
-        if (device2 == AUDIO_DEVICE_NONE) {
-            device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
-        }
-        if ((device2 == AUDIO_DEVICE_NONE)) {
-            device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_LINE;
-        }
-        if (device2 == AUDIO_DEVICE_NONE) {
-            device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_WIRED_HEADSET;
-        }
-        if (device2 == AUDIO_DEVICE_NONE) {
-            device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_ACCESSORY;
-        }
-        if (device2 == AUDIO_DEVICE_NONE) {
-            device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_DEVICE;
-        }
-        if (device2 == AUDIO_DEVICE_NONE) {
-            device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
-        }
-        if ((device2 == AUDIO_DEVICE_NONE) && (strategy != STRATEGY_SONIFICATION)) {
-            // no sonification on aux digital (e.g. HDMI)
-            device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_AUX_DIGITAL;
-        }
-        if ((device2 == AUDIO_DEVICE_NONE) &&
-                (mForceUse[AUDIO_POLICY_FORCE_FOR_DOCK] == AUDIO_POLICY_FORCE_ANALOG_DOCK)) {
-            device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
-        }
-        if (device2 == AUDIO_DEVICE_NONE) {
-            device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPEAKER;
-        }
-        int device3 = AUDIO_DEVICE_NONE;
-        if (strategy == STRATEGY_MEDIA) {
-            // ARC, SPDIF and AUX_LINE can co-exist with others.
-            device3 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_HDMI_ARC;
-            device3 |= (availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPDIF);
-            device3 |= (availableOutputDeviceTypes & AUDIO_DEVICE_OUT_AUX_LINE);
-        }
-
-        device2 |= device3;
-        // device is DEVICE_OUT_SPEAKER if we come from case STRATEGY_SONIFICATION or
-        // STRATEGY_ENFORCED_AUDIBLE, AUDIO_DEVICE_NONE otherwise
-        device |= device2;
-
-        // If hdmi system audio mode is on, remove speaker out of output list.
-        if ((strategy == STRATEGY_MEDIA) &&
-            (mForceUse[AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO] ==
-                AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED)) {
-            device &= ~AUDIO_DEVICE_OUT_SPEAKER;
-        }
-
-        if (device) break;
-        device = mDefaultOutputDevice->mDeviceType;
-        if (device == AUDIO_DEVICE_NONE) {
-            ALOGE("getDeviceForStrategy() no device found for STRATEGY_MEDIA");
-        }
-        } break;
-
-    default:
-        ALOGW("getDeviceForStrategy() unknown strategy: %d", strategy);
-        break;
-    }
-
-    ALOGVV("getDeviceForStrategy() strategy %d, device %x", strategy, device);
-    return device;
+    return mEngine->getDeviceForStrategy(strategy);
 }
 
 void AudioPolicyManager::updateDevicesAndOutputs()
@@ -4698,7 +3835,7 @@
                 ALOGVV("checkDeviceMuteStrategies() %s strategy %d (curDevice %04x) on output %d",
                       mute ? "muting" : "unmuting", i, curDevice, curOutput);
                 setStrategyMute((routing_strategy)i, mute, curOutput, mute ? 0 : delayMs);
-                if (desc->isStrategyActive((routing_strategy)i)) {
+                if (isStrategyActive(desc, (routing_strategy)i)) {
                     if (mute) {
                         // FIXME: should not need to double latency if volume could be applied
                         // immediately by the audioflinger mixer. We must account for the delay
@@ -4721,7 +3858,7 @@
             muteWaitMs = outputDesc->latency() * 2;
         }
         for (size_t i = 0; i < NUM_STRATEGIES; i++) {
-            if (outputDesc->isStrategyActive((routing_strategy)i)) {
+            if (isStrategyActive(outputDesc, (routing_strategy)i)) {
                 setStrategyMute((routing_strategy)i, true, outputDesc->mIoHandle);
                 // do tempMute unmute after twice the mute wait time
                 setStrategyMute((routing_strategy)i, false, outputDesc->mIoHandle,
@@ -4827,8 +3964,7 @@
                                        status, afPatchHandle, patch.num_sources, patch.num_sinks);
             if (status == NO_ERROR) {
                 if (index < 0) {
-                    patchDesc = new AudioPatch((audio_patch_handle_t)nextUniqueId(),
-                                               &patch, mUidCached);
+                    patchDesc = new AudioPatch(&patch, mUidCached);
                     addAudioPatch(patchDesc->mHandle, patchDesc);
                 } else {
                     patchDesc->mPatch = patch;
@@ -4847,7 +3983,7 @@
         // inform all input as well
         for (size_t i = 0; i < mInputs.size(); i++) {
             const sp<AudioInputDescriptor>  inputDescriptor = mInputs.valueAt(i);
-            if (!isVirtualInputDevice(inputDescriptor->mDevice)) {
+            if (!is_virtual_input_device(inputDescriptor->mDevice)) {
                 AudioParameter inputCmd = AudioParameter();
                 ALOGV("%s: inform input %d of device:%d", __func__,
                       inputDescriptor->mIoHandle, device);
@@ -4934,8 +4070,7 @@
                                                                           status, afPatchHandle);
             if (status == NO_ERROR) {
                 if (index < 0) {
-                    patchDesc = new AudioPatch((audio_patch_handle_t)nextUniqueId(),
-                                               &patch, mUidCached);
+                    patchDesc = new AudioPatch(&patch, mUidCached);
                     addAudioPatch(patchDesc->mHandle, patchDesc);
                 } else {
                     patchDesc->mPatch = patch;
@@ -4978,11 +4113,11 @@
 }
 
 sp<IOProfile> AudioPolicyManager::getInputProfile(audio_devices_t device,
-                                                   String8 address,
-                                                   uint32_t& samplingRate,
-                                                   audio_format_t format,
-                                                   audio_channel_mask_t channelMask,
-                                                   audio_input_flags_t flags)
+                                                  String8 address,
+                                                  uint32_t& samplingRate,
+                                                  audio_format_t format,
+                                                  audio_channel_mask_t channelMask,
+                                                  audio_input_flags_t flags)
 {
     // Choose an input profile based on the requested capture parameters: select the first available
     // profile supporting all requested parameters.
@@ -5009,224 +4144,35 @@
 
 
 audio_devices_t AudioPolicyManager::getDeviceAndMixForInputSource(audio_source_t inputSource,
-                                                            AudioMix **policyMix)
+                                                                  AudioMix **policyMix)
 {
-    audio_devices_t availableDeviceTypes = mAvailableInputDevices.types() &
-                                            ~AUDIO_DEVICE_BIT_IN;
+    audio_devices_t availableDeviceTypes = mAvailableInputDevices.types() & ~AUDIO_DEVICE_BIT_IN;
+    audio_devices_t selectedDeviceFromMix =
+           mPolicyMixes.getDeviceAndMixForInputSource(inputSource, availableDeviceTypes, policyMix);
 
-    for (size_t i = 0; i < mPolicyMixes.size(); i++) {
-        if (mPolicyMixes[i]->mMix.mMixType != MIX_TYPE_RECORDERS) {
-            continue;
-        }
-        for (size_t j = 0; j < mPolicyMixes[i]->mMix.mCriteria.size(); j++) {
-            if ((RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET == mPolicyMixes[i]->mMix.mCriteria[j].mRule &&
-                    mPolicyMixes[i]->mMix.mCriteria[j].mAttr.mSource == inputSource) ||
-               (RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET == mPolicyMixes[i]->mMix.mCriteria[j].mRule &&
-                    mPolicyMixes[i]->mMix.mCriteria[j].mAttr.mSource != inputSource)) {
-                if (availableDeviceTypes & AUDIO_DEVICE_IN_REMOTE_SUBMIX) {
-                    if (policyMix != NULL) {
-                        *policyMix = &mPolicyMixes[i]->mMix;
-                    }
-                    return AUDIO_DEVICE_IN_REMOTE_SUBMIX;
-                }
-                break;
-            }
-        }
+    if (selectedDeviceFromMix != AUDIO_DEVICE_NONE) {
+        return selectedDeviceFromMix;
     }
-
     return getDeviceForInputSource(inputSource);
 }
 
 audio_devices_t AudioPolicyManager::getDeviceForInputSource(audio_source_t inputSource)
 {
-    uint32_t device = AUDIO_DEVICE_NONE;
-    audio_devices_t availableDeviceTypes = mAvailableInputDevices.types() &
-                                            ~AUDIO_DEVICE_BIT_IN;
-
-    switch (inputSource) {
-    case AUDIO_SOURCE_VOICE_UPLINK:
-      if (availableDeviceTypes & AUDIO_DEVICE_IN_VOICE_CALL) {
-          device = AUDIO_DEVICE_IN_VOICE_CALL;
-          break;
-      }
-      break;
-
-    case AUDIO_SOURCE_DEFAULT:
-    case AUDIO_SOURCE_MIC:
-    if (availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_A2DP) {
-        device = AUDIO_DEVICE_IN_BLUETOOTH_A2DP;
-    } else if ((mForceUse[AUDIO_POLICY_FORCE_FOR_RECORD] == AUDIO_POLICY_FORCE_BT_SCO) &&
-        (availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET)) {
-        device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
-    } else if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) {
-        device = AUDIO_DEVICE_IN_WIRED_HEADSET;
-    } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
-        device = AUDIO_DEVICE_IN_USB_DEVICE;
-    } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
-        device = AUDIO_DEVICE_IN_BUILTIN_MIC;
-    }
-    break;
-
-    case AUDIO_SOURCE_VOICE_COMMUNICATION:
-        // Allow only use of devices on primary input if in call and HAL does not support routing
-        // to voice call path.
-        if ((mPhoneState == AUDIO_MODE_IN_CALL) &&
-                (mAvailableOutputDevices.types() & AUDIO_DEVICE_OUT_TELEPHONY_TX) == 0) {
-            availableDeviceTypes = availablePrimaryInputDevices() & ~AUDIO_DEVICE_BIT_IN;
-        }
-
-        switch (mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION]) {
-        case AUDIO_POLICY_FORCE_BT_SCO:
-            // if SCO device is requested but no SCO device is available, fall back to default case
-            if (availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
-                device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
-                break;
-            }
-            // FALL THROUGH
-
-        default:    // FORCE_NONE
-            if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) {
-                device = AUDIO_DEVICE_IN_WIRED_HEADSET;
-            } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
-                device = AUDIO_DEVICE_IN_USB_DEVICE;
-            } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
-                device = AUDIO_DEVICE_IN_BUILTIN_MIC;
-            }
-            break;
-
-        case AUDIO_POLICY_FORCE_SPEAKER:
-            if (availableDeviceTypes & AUDIO_DEVICE_IN_BACK_MIC) {
-                device = AUDIO_DEVICE_IN_BACK_MIC;
-            } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
-                device = AUDIO_DEVICE_IN_BUILTIN_MIC;
-            }
-            break;
-        }
-        break;
-
-    case AUDIO_SOURCE_VOICE_RECOGNITION:
-    case AUDIO_SOURCE_HOTWORD:
-        if (mForceUse[AUDIO_POLICY_FORCE_FOR_RECORD] == AUDIO_POLICY_FORCE_BT_SCO &&
-                availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
-            device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
-        } else if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) {
-            device = AUDIO_DEVICE_IN_WIRED_HEADSET;
-        } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
-            device = AUDIO_DEVICE_IN_USB_DEVICE;
-        } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
-            device = AUDIO_DEVICE_IN_BUILTIN_MIC;
-        }
-        break;
-    case AUDIO_SOURCE_CAMCORDER:
-        if (availableDeviceTypes & AUDIO_DEVICE_IN_BACK_MIC) {
-            device = AUDIO_DEVICE_IN_BACK_MIC;
-        } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
-            device = AUDIO_DEVICE_IN_BUILTIN_MIC;
-        }
-        break;
-    case AUDIO_SOURCE_VOICE_DOWNLINK:
-    case AUDIO_SOURCE_VOICE_CALL:
-        if (availableDeviceTypes & AUDIO_DEVICE_IN_VOICE_CALL) {
-            device = AUDIO_DEVICE_IN_VOICE_CALL;
-        }
-        break;
-    case AUDIO_SOURCE_REMOTE_SUBMIX:
-        if (availableDeviceTypes & AUDIO_DEVICE_IN_REMOTE_SUBMIX) {
-            device = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
-        }
-        break;
-     case AUDIO_SOURCE_FM_TUNER:
-        if (availableDeviceTypes & AUDIO_DEVICE_IN_FM_TUNER) {
-            device = AUDIO_DEVICE_IN_FM_TUNER;
-        }
-        break;
-    default:
-        ALOGW("getDeviceForInputSource() invalid input source %d", inputSource);
-        break;
-    }
-    ALOGV("getDeviceForInputSource()input source %d, device %08x", inputSource, device);
-    return device;
-}
-
-bool AudioPolicyManager::isVirtualInputDevice(audio_devices_t device)
-{
-    if ((device & AUDIO_DEVICE_BIT_IN) != 0) {
-        device &= ~AUDIO_DEVICE_BIT_IN;
-        if ((popcount(device) == 1) && ((device & ~APM_AUDIO_IN_DEVICE_VIRTUAL_ALL) == 0))
-            return true;
-    }
-    return false;
-}
-
-bool AudioPolicyManager::deviceDistinguishesOnAddress(audio_devices_t device) {
-    return ((device & APM_AUDIO_DEVICE_MATCH_ADDRESS_ALL & ~AUDIO_DEVICE_BIT_IN) != 0);
-}
-
-audio_io_handle_t AudioPolicyManager::getActiveInput(bool ignoreVirtualInputs)
-{
-    for (size_t i = 0; i < mInputs.size(); i++) {
-        const sp<AudioInputDescriptor>  input_descriptor = mInputs.valueAt(i);
-        if ((input_descriptor->mRefCount > 0)
-                && (!ignoreVirtualInputs || !isVirtualInputDevice(input_descriptor->mDevice))) {
-            return mInputs.keyAt(i);
-        }
-    }
-    return 0;
-}
-
-uint32_t AudioPolicyManager::activeInputsCount() const
-{
-    uint32_t count = 0;
-    for (size_t i = 0; i < mInputs.size(); i++) {
-        const sp<AudioInputDescriptor>  desc = mInputs.valueAt(i);
-        if (desc->mRefCount > 0) {
-            count++;
-        }
-    }
-    return count;
-}
-
-
-void AudioPolicyManager::initializeVolumeCurves()
-{
-    for (int i = 0; i < AUDIO_STREAM_CNT; i++) {
-        for (int j = 0; j < ApmGains::DEVICE_CATEGORY_CNT; j++) {
-            mStreams[i].mVolumeCurve[j] =
-                    ApmGains::sVolumeProfiles[i][j];
-        }
-    }
-
-    // Check availability of DRC on speaker path: if available, override some of the speaker curves
-    if (mSpeakerDrcEnabled) {
-        mStreams[AUDIO_STREAM_SYSTEM].mVolumeCurve[ApmGains::DEVICE_CATEGORY_SPEAKER] =
-                ApmGains::sDefaultSystemVolumeCurveDrc;
-        mStreams[AUDIO_STREAM_RING].mVolumeCurve[ApmGains::DEVICE_CATEGORY_SPEAKER] =
-                ApmGains::sSpeakerSonificationVolumeCurveDrc;
-        mStreams[AUDIO_STREAM_ALARM].mVolumeCurve[ApmGains::DEVICE_CATEGORY_SPEAKER] =
-                ApmGains::sSpeakerSonificationVolumeCurveDrc;
-        mStreams[AUDIO_STREAM_NOTIFICATION].mVolumeCurve[ApmGains::DEVICE_CATEGORY_SPEAKER] =
-                ApmGains::sSpeakerSonificationVolumeCurveDrc;
-        mStreams[AUDIO_STREAM_MUSIC].mVolumeCurve[ApmGains::DEVICE_CATEGORY_SPEAKER] =
-                ApmGains::sSpeakerMediaVolumeCurveDrc;
-        mStreams[AUDIO_STREAM_ACCESSIBILITY].mVolumeCurve[ApmGains::DEVICE_CATEGORY_SPEAKER] =
-                ApmGains::sSpeakerMediaVolumeCurveDrc;
-    }
+    return mEngine->getDeviceForInputSource(inputSource);
 }
 
 float AudioPolicyManager::computeVolume(audio_stream_type_t stream,
-                                            int index,
-                                            audio_io_handle_t output,
-                                            audio_devices_t device)
+                                        int index,
+                                        audio_io_handle_t output,
+                                        audio_devices_t device)
 {
     float volume = 1.0;
     sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
-    StreamDescriptor &streamDesc = mStreams[stream];
 
     if (device == AUDIO_DEVICE_NONE) {
         device = outputDesc->device();
     }
-
-    volume = ApmGains::volIndexToAmpl(device, streamDesc, index);
+    volume = mEngine->volIndexToAmpl(Volume::getDeviceCategory(device), stream, index);
 
     // if a headset is connected, apply the following rules to ring tones and notifications
     // to avoid sound level bursts in user's ears:
@@ -5242,8 +4188,8 @@
                 || (stream_strategy == STRATEGY_SONIFICATION_RESPECTFUL)
                 || (stream == AUDIO_STREAM_SYSTEM)
                 || ((stream_strategy == STRATEGY_ENFORCED_AUDIBLE) &&
-                    (mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM] == AUDIO_POLICY_FORCE_NONE))) &&
-        streamDesc.mCanBeMuted) {
+                    (mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_NONE))) &&
+            mStreams.canBeMuted(stream)) {
         volume *= SONIFICATION_HEADSET_VOLUME_FACTOR;
         // when the phone is ringing we must consider that music could have been paused just before
         // by the music application and behave as if music was active if the last music track was
@@ -5268,11 +4214,11 @@
 }
 
 status_t AudioPolicyManager::checkAndSetVolume(audio_stream_type_t stream,
-                                                   int index,
-                                                   audio_io_handle_t output,
-                                                   audio_devices_t device,
-                                                   int delayMs,
-                                                   bool force)
+                                               int index,
+                                               audio_io_handle_t output,
+                                               audio_devices_t device,
+                                               int delayMs,
+                                               bool force)
 {
 
     // do not change actual stream volume if the stream is muted
@@ -5281,14 +4227,13 @@
               stream, mOutputs.valueFor(output)->mMuteCount[stream]);
         return NO_ERROR;
     }
-
+    audio_policy_forced_cfg_t forceUseForComm =
+            mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION);
     // do not change in call volume if bluetooth is connected and vice versa
-    if ((stream == AUDIO_STREAM_VOICE_CALL &&
-            mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION] == AUDIO_POLICY_FORCE_BT_SCO) ||
-        (stream == AUDIO_STREAM_BLUETOOTH_SCO &&
-                mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION] != AUDIO_POLICY_FORCE_BT_SCO)) {
+    if ((stream == AUDIO_STREAM_VOICE_CALL && forceUseForComm == AUDIO_POLICY_FORCE_BT_SCO) ||
+        (stream == AUDIO_STREAM_BLUETOOTH_SCO && forceUseForComm != AUDIO_POLICY_FORCE_BT_SCO)) {
         ALOGV("checkAndSetVolume() cannot set stream %d volume with force use = %d for comm",
-             stream, mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION]);
+             stream, forceUseForComm);
         return INVALID_OPERATION;
     }
 
@@ -5325,7 +4270,7 @@
         float voiceVolume;
         // Force voice volume to max for bluetooth SCO as volume is managed by the headset
         if (stream == AUDIO_STREAM_VOICE_CALL) {
-            voiceVolume = (float)index/(float)mStreams[stream].mIndexMax;
+            voiceVolume = (float)index/(float)mStreams[stream].getVolumeIndexMax();
         } else {
             voiceVolume = 1.0;
         }
@@ -5340,9 +4285,9 @@
 }
 
 void AudioPolicyManager::applyStreamVolumes(audio_io_handle_t output,
-                                                audio_devices_t device,
-                                                int delayMs,
-                                                bool force)
+                                            audio_devices_t device,
+                                            int delayMs,
+                                            bool force)
 {
     ALOGVV("applyStreamVolumes() for output %d and device %x", output, device);
 
@@ -5360,10 +4305,10 @@
 }
 
 void AudioPolicyManager::setStrategyMute(routing_strategy strategy,
-                                             bool on,
-                                             audio_io_handle_t output,
-                                             int delayMs,
-                                             audio_devices_t device)
+                                         bool on,
+                                         audio_io_handle_t output,
+                                         int delayMs,
+                                         audio_devices_t device)
 {
     ALOGVV("setStrategyMute() strategy %d, mute %d, output %d", strategy, on, output);
     for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) {
@@ -5377,12 +4322,12 @@
 }
 
 void AudioPolicyManager::setStreamMute(audio_stream_type_t stream,
-                                           bool on,
-                                           audio_io_handle_t output,
-                                           int delayMs,
-                                           audio_devices_t device)
+                                       bool on,
+                                       audio_io_handle_t output,
+                                       int delayMs,
+                                       audio_devices_t device)
 {
-    StreamDescriptor &streamDesc = mStreams[stream];
+    const StreamDescriptor &streamDesc = mStreams[stream];
     sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
     if (device == AUDIO_DEVICE_NONE) {
         device = outputDesc->device();
@@ -5393,9 +4338,9 @@
 
     if (on) {
         if (outputDesc->mMuteCount[stream] == 0) {
-            if (streamDesc.mCanBeMuted &&
+            if (streamDesc.canBeMuted() &&
                     ((stream != AUDIO_STREAM_ENFORCED_AUDIBLE) ||
-                     (mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM] == AUDIO_POLICY_FORCE_NONE))) {
+                     (mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_NONE))) {
                 checkAndSetVolume(stream, 0, output, device, delayMs);
             }
         }
@@ -5461,192 +4406,6 @@
     }
 }
 
-bool AudioPolicyManager::isInCall()
-{
-    return isStateInCall(mPhoneState);
-}
-
-bool AudioPolicyManager::isStateInCall(int state) {
-    return ((state == AUDIO_MODE_IN_CALL) ||
-            (state == AUDIO_MODE_IN_COMMUNICATION));
-}
-
-uint32_t AudioPolicyManager::getMaxEffectsCpuLoad()
-{
-    return MAX_EFFECTS_CPU_LOAD;
-}
-
-uint32_t AudioPolicyManager::getMaxEffectsMemory()
-{
-    return MAX_EFFECTS_MEMORY;
-}
-
-
-// --- EffectDescriptor class implementation
-
-status_t AudioPolicyManager::EffectDescriptor::dump(int fd)
-{
-    const size_t SIZE = 256;
-    char buffer[SIZE];
-    String8 result;
-
-    snprintf(buffer, SIZE, " I/O: %d\n", mIo);
-    result.append(buffer);
-    snprintf(buffer, SIZE, " Strategy: %d\n", mStrategy);
-    result.append(buffer);
-    snprintf(buffer, SIZE, " Session: %d\n", mSession);
-    result.append(buffer);
-    snprintf(buffer, SIZE, " Name: %s\n",  mDesc.name);
-    result.append(buffer);
-    snprintf(buffer, SIZE, " %s\n",  mEnabled ? "Enabled" : "Disabled");
-    result.append(buffer);
-    write(fd, result.string(), result.size());
-
-    return NO_ERROR;
-}
-
-
-// --- audio_policy.conf file parsing
-// TODO candidate to be moved to ConfigParsingUtils
-void AudioPolicyManager::loadHwModule(cnode *root)
-{
-    status_t status = NAME_NOT_FOUND;
-    cnode *node;
-    sp<HwModule> module = new HwModule(root->name);
-
-    node = config_find(root, DEVICES_TAG);
-    if (node != NULL) {
-        node = node->first_child;
-        while (node) {
-            ALOGV("loadHwModule() loading device %s", node->name);
-            status_t tmpStatus = module->loadDevice(node);
-            if (status == NAME_NOT_FOUND || status == NO_ERROR) {
-                status = tmpStatus;
-            }
-            node = node->next;
-        }
-    }
-    node = config_find(root, OUTPUTS_TAG);
-    if (node != NULL) {
-        node = node->first_child;
-        while (node) {
-            ALOGV("loadHwModule() loading output %s", node->name);
-            status_t tmpStatus = module->loadOutput(node);
-            if (status == NAME_NOT_FOUND || status == NO_ERROR) {
-                status = tmpStatus;
-            }
-            node = node->next;
-        }
-    }
-    node = config_find(root, INPUTS_TAG);
-    if (node != NULL) {
-        node = node->first_child;
-        while (node) {
-            ALOGV("loadHwModule() loading input %s", node->name);
-            status_t tmpStatus = module->loadInput(node);
-            if (status == NAME_NOT_FOUND || status == NO_ERROR) {
-                status = tmpStatus;
-            }
-            node = node->next;
-        }
-    }
-    loadGlobalConfig(root, module);
-
-    if (status == NO_ERROR) {
-        mHwModules.add(module);
-    }
-}
-
-// TODO candidate to be moved to ConfigParsingUtils
-void AudioPolicyManager::loadHwModules(cnode *root)
-{
-    cnode *node = config_find(root, AUDIO_HW_MODULE_TAG);
-    if (node == NULL) {
-        return;
-    }
-
-    node = node->first_child;
-    while (node) {
-        ALOGV("loadHwModules() loading module %s", node->name);
-        loadHwModule(node);
-        node = node->next;
-    }
-}
-
-// TODO candidate to be moved to ConfigParsingUtils
-void AudioPolicyManager::loadGlobalConfig(cnode *root, const sp<HwModule>& module)
-{
-    cnode *node = config_find(root, GLOBAL_CONFIG_TAG);
-
-    if (node == NULL) {
-        return;
-    }
-    DeviceVector declaredDevices;
-    if (module != NULL) {
-        declaredDevices = module->mDeclaredDevices;
-    }
-
-    node = node->first_child;
-    while (node) {
-        if (strcmp(ATTACHED_OUTPUT_DEVICES_TAG, node->name) == 0) {
-            mAvailableOutputDevices.loadDevicesFromName((char *)node->value,
-                                                        declaredDevices);
-            ALOGV("loadGlobalConfig() Attached Output Devices %08x",
-                  mAvailableOutputDevices.types());
-        } else if (strcmp(DEFAULT_OUTPUT_DEVICE_TAG, node->name) == 0) {
-            audio_devices_t device = (audio_devices_t)ConfigParsingUtils::stringToEnum(
-                    sDeviceNameToEnumTable,
-                    ARRAY_SIZE(sDeviceNameToEnumTable),
-                    (char *)node->value);
-            if (device != AUDIO_DEVICE_NONE) {
-                mDefaultOutputDevice = new DeviceDescriptor(String8("default-output"), device);
-            } else {
-                ALOGW("loadGlobalConfig() default device not specified");
-            }
-            ALOGV("loadGlobalConfig() mDefaultOutputDevice %08x", mDefaultOutputDevice->mDeviceType);
-        } else if (strcmp(ATTACHED_INPUT_DEVICES_TAG, node->name) == 0) {
-            mAvailableInputDevices.loadDevicesFromName((char *)node->value,
-                                                       declaredDevices);
-            ALOGV("loadGlobalConfig() Available InputDevices %08x", mAvailableInputDevices.types());
-        } else if (strcmp(SPEAKER_DRC_ENABLED_TAG, node->name) == 0) {
-            mSpeakerDrcEnabled = ConfigParsingUtils::stringToBool((char *)node->value);
-            ALOGV("loadGlobalConfig() mSpeakerDrcEnabled = %d", mSpeakerDrcEnabled);
-        } else if (strcmp(AUDIO_HAL_VERSION_TAG, node->name) == 0) {
-            uint32_t major, minor;
-            sscanf((char *)node->value, "%u.%u", &major, &minor);
-            module->mHalVersion = HARDWARE_DEVICE_API_VERSION(major, minor);
-            ALOGV("loadGlobalConfig() mHalVersion = %04x major %u minor %u",
-                  module->mHalVersion, major, minor);
-        }
-        node = node->next;
-    }
-}
-
-// TODO candidate to be moved to ConfigParsingUtils
-status_t AudioPolicyManager::loadAudioPolicyConfig(const char *path)
-{
-    cnode *root;
-    char *data;
-
-    data = (char *)load_file(path, NULL);
-    if (data == NULL) {
-        return -ENODEV;
-    }
-    root = config_node("", "");
-    config_load(root, data);
-
-    loadHwModules(root);
-    // legacy audio_policy.conf files have one global_configuration section
-    loadGlobalConfig(root, getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY));
-    config_free(root);
-    free(root);
-    free(data);
-
-    ALOGI("loadAudioPolicyConfig() loaded %s\n", path);
-
-    return NO_ERROR;
-}
-
 void AudioPolicyManager::defaultAudioPolicyConfig(void)
 {
     sp<HwModule> module;
@@ -5732,7 +4491,8 @@
     }
 }
 
-bool AudioPolicyManager::isValidAttributes(const audio_attributes_t *paa) {
+bool AudioPolicyManager::isValidAttributes(const audio_attributes_t *paa)
+{
     // has flags that map to a strategy?
     if ((paa->flags & (AUDIO_FLAG_AUDIBILITY_ENFORCED | AUDIO_FLAG_SCO | AUDIO_FLAG_BEACON)) != 0) {
         return true;
@@ -5763,4 +4523,39 @@
     return true;
 }
 
+bool AudioPolicyManager::isStrategyActive(const sp<AudioOutputDescriptor> outputDesc,
+                                          routing_strategy strategy, uint32_t inPastMs,
+                                          nsecs_t sysTime) const
+{
+    if ((sysTime == 0) && (inPastMs != 0)) {
+        sysTime = systemTime();
+    }
+    for (int i = 0; i < (int)AUDIO_STREAM_CNT; i++) {
+        if (i == AUDIO_STREAM_PATCH) {
+            continue;
+        }
+        if (((getStrategy((audio_stream_type_t)i) == strategy) ||
+                (NUM_STRATEGIES == strategy)) &&
+                outputDesc->isStreamActive((audio_stream_type_t)i, inPastMs, sysTime)) {
+            return true;
+        }
+    }
+    return false;
+}
+
+audio_policy_forced_cfg_t AudioPolicyManager::getForceUse(audio_policy_force_use_t usage)
+{
+    return mEngine->getForceUse(usage);
+}
+
+bool AudioPolicyManager::isInCall()
+{
+    return isStateInCall(mEngine->getPhoneState());
+}
+
+bool AudioPolicyManager::isStateInCall(int state)
+{
+    return is_state_in_call(state);
+}
+
 }; // namespace android
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 61ea6f2..02b678a 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#pragma once
 
 #include <stdint.h>
 #include <sys/types.h>
@@ -26,14 +27,21 @@
 #include <media/AudioPolicy.h>
 #include "AudioPolicyInterface.h"
 
-#include "Gains.h"
-#include "Ports.h"
-#include "ConfigParsingUtils.h"
-#include "Devices.h"
-#include "IOProfile.h"
-#include "HwModule.h"
-#include "AudioInputDescriptor.h"
-#include "AudioOutputDescriptor.h"
+#include <AudioPolicyManagerInterface.h>
+#include <AudioPolicyManagerObserver.h>
+#include <AudioGain.h>
+#include <AudioPort.h>
+#include <AudioPatch.h>
+#include <ConfigParsingUtils.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>
 
 namespace android {
 
@@ -46,9 +54,7 @@
 // Time in milliseconds during which we consider that music is still active after a music
 // track was stopped - see computeVolume()
 #define SONIFICATION_HEADSET_MUSIC_DELAY  5000
-// Time in milliseconds after media stopped playing during which we consider that the
-// sonification should be as unobtrusive as during the time media was playing.
-#define SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY 5000
+
 // Time in milliseconds during witch some streams are muted while the audio path
 // is switched
 #define MUTE_TIME_MS 2000
@@ -61,14 +67,12 @@
 // Can be overridden by the audio.offload.min.duration.secs property
 #define OFFLOAD_DEFAULT_MIN_DURATION_SECS 60
 
-#define MAX_MIXER_SAMPLING_RATE 48000
-#define MAX_MIXER_CHANNEL_COUNT 8
-
 // ----------------------------------------------------------------------------
 // AudioPolicyManager implements audio policy manager behavior common to all platforms.
 // ----------------------------------------------------------------------------
 
-class AudioPolicyManager: public AudioPolicyInterface
+class AudioPolicyManager : public AudioPolicyInterface, public AudioPolicyManagerObserver
+
 #ifdef AUDIO_POLICY_TEST
     , public Thread
 #endif //AUDIO_POLICY_TEST
@@ -89,6 +93,7 @@
         virtual void setForceUse(audio_policy_force_use_t usage,
                                  audio_policy_forced_cfg_t config);
         virtual audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage);
+
         virtual void setSystemProperty(const char* property, const char* value);
         virtual status_t initCheck();
         virtual audio_io_handle_t getOutput(audio_stream_type_t stream,
@@ -158,16 +163,28 @@
                                         uint32_t strategy,
                                         int session,
                                         int id);
-        virtual status_t unregisterEffect(int id);
-        virtual status_t setEffectEnabled(int id, bool enabled);
+        virtual status_t unregisterEffect(int id)
+        {
+            return mEffects.unregisterEffect(id);
+        }
+        virtual status_t setEffectEnabled(int id, bool enabled)
+        {
+            return mEffects.setEffectEnabled(id, enabled);
+        }
 
-        virtual bool isStreamActive(audio_stream_type_t stream, uint32_t inPastMs = 0) const;
+        virtual bool isStreamActive(audio_stream_type_t stream, uint32_t inPastMs = 0) const
+        {
+            return mOutputs.isStreamActive(stream, inPastMs);
+        }
         // return whether a stream is playing remotely, override to change the definition of
         //   local/remote playback, used for instance by notification manager to not make
         //   media players lose audio focus when not playing locally
         //   For the base implementation, "remotely" means playing during screen mirroring which
         //   uses an output for playback with a non-empty, non "0" address.
-        virtual bool isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs = 0) const;
+        virtual bool isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs = 0) const
+        {
+            return mOutputs.isStreamActiveRemotely(stream, inPastMs);
+        }
         virtual bool isSourceActive(audio_source_t source) const;
 
         virtual status_t dump(int fd);
@@ -195,39 +212,61 @@
                                                audio_io_handle_t *ioHandle,
                                                audio_devices_t *device);
 
-        virtual status_t releaseSoundTriggerSession(audio_session_t session);
+        virtual status_t releaseSoundTriggerSession(audio_session_t session)
+        {
+            return mSoundTriggerSessions.releaseSession(session);
+        }
 
         virtual status_t registerPolicyMixes(Vector<AudioMix> mixes);
         virtual status_t unregisterPolicyMixes(Vector<AudioMix> mixes);
 
         // Audio policy configuration file parsing (audio_policy.conf)
         // TODO candidates to be moved to ConfigParsingUtils
-                void loadHwModule(cnode *root);
-                void loadHwModules(cnode *root);
-                void loadGlobalConfig(cnode *root, const sp<HwModule>& module);
-                status_t loadAudioPolicyConfig(const char *path);
                 void defaultAudioPolicyConfig(void);
 
-                // return the strategy corresponding to a given stream type
-                static routing_strategy getStrategy(audio_stream_type_t stream);
+        // return the strategy corresponding to a given stream type
+        routing_strategy getStrategy(audio_stream_type_t stream) const;
 
-                static uint32_t nextUniqueId();
-protected:
-
-        class EffectDescriptor : public RefBase
+        // From AudioPolicyManagerObserver
+        virtual const AudioPatchCollection &getAudioPatches() const
         {
-        public:
-
-            status_t dump(int fd);
-
-            int mIo;                // io the effect is attached to
-            routing_strategy mStrategy; // routing strategy the effect is associated to
-            int mSession;               // audio session the effect is on
-            effect_descriptor_t mDesc;  // effect descriptor
-            bool mEnabled;              // enabled state: CPU load being used or not
-        };
-
+            return mAudioPatches;
+        }
+        virtual const SoundTriggerSessionCollection &getSoundTriggerSessionCollection() const
+        {
+            return mSoundTriggerSessions;
+        }
+        virtual const AudioPolicyMixCollection &getAudioPolicyMixCollection() const
+        {
+            return mPolicyMixes;
+        }
+        virtual const AudioOutputCollection &getOutputs() const
+        {
+            return mOutputs;
+        }
+        virtual const AudioInputCollection &getInputs() const
+        {
+            return mInputs;
+        }
+        virtual const DeviceVector &getAvailableOutputDevices() const
+        {
+            return mAvailableOutputDevices;
+        }
+        virtual const DeviceVector &getAvailableInputDevices() const
+        {
+            return mAvailableInputDevices;
+        }
+        virtual StreamDescriptorCollection &getStreamDescriptors()
+        {
+            return mStreams;
+        }
+        virtual const sp<DeviceDescriptor> &getDefaultOutputDevice() const
+        {
+            return mDefaultOutputDevice;
+        }
+protected:
         void addOutput(audio_io_handle_t output, sp<AudioOutputDescriptor> outputDesc);
+        void removeOutput(audio_io_handle_t output);
         void addInput(audio_io_handle_t input, sp<AudioInputDescriptor> inputDesc);
 
         // return appropriate device for streams handled by the specified strategy according to current
@@ -244,6 +283,9 @@
         virtual audio_devices_t getDeviceForStrategy(routing_strategy strategy,
                                                      bool fromCache);
 
+        bool isStrategyActive(const sp<AudioOutputDescriptor> outputDesc, routing_strategy strategy,
+                              uint32_t inPastMs = 0, nsecs_t sysTime = 0) const;
+
         // change the route of the specified output. Returns the number of ms we have slept to
         // allow new routing to take effect in certain cases.
         virtual uint32_t setOutputDevice(audio_io_handle_t output,
@@ -265,16 +307,6 @@
         // select input device corresponding to requested audio source
         virtual audio_devices_t getDeviceForInputSource(audio_source_t inputSource);
 
-        // return io handle of active input or 0 if no input is active
-        //    Only considers inputs from physical devices (e.g. main mic, headset mic) when
-        //    ignoreVirtualInputs is true.
-        audio_io_handle_t getActiveInput(bool ignoreVirtualInputs = true);
-
-        uint32_t activeInputsCount() const;
-
-        // initialize volume curves for each strategy and device category
-        void initializeVolumeCurves();
-
         // compute the actual volume for a given stream according to the requested index and a particular
         // device
         virtual float computeVolume(audio_stream_type_t stream, int index,
@@ -307,9 +339,10 @@
         // a special tone in the device used for communication
         void handleIncallSonification(audio_stream_type_t stream, bool starting, bool stateChange);
 
+        audio_mode_t getPhoneState();
+
         // true if device is in a telephony or VoIP call
         virtual bool isInCall();
-
         // true if given state represents a device in a telephony or VoIP call
         virtual bool isStateInCall(int state);
 
@@ -347,9 +380,6 @@
         // manages A2DP output suspend/restore according to phone state and BT SCO usage
         void checkA2dpSuspend();
 
-        // returns the A2DP output handle if it is open or 0 otherwise
-        audio_io_handle_t getA2dpOutput();
-
         // selects the most appropriate device on output for current state
         // must be called every time a condition that affects the device choice for a given output is
         // changed: connected device, phone state, force use, output start, output stop..
@@ -366,18 +396,23 @@
         // selects the most appropriate device on input for current state
         audio_devices_t getNewInputDevice(audio_io_handle_t input);
 
-        virtual uint32_t getMaxEffectsCpuLoad();
-        virtual uint32_t getMaxEffectsMemory();
+        virtual uint32_t getMaxEffectsCpuLoad()
+        {
+            return mEffects.getMaxEffectsCpuLoad();
+        }
+
+        virtual uint32_t getMaxEffectsMemory()
+        {
+            return mEffects.getMaxEffectsMemory();
+        }
 #ifdef AUDIO_POLICY_TEST
         virtual     bool        threadLoop();
                     void        exit();
         int testOutputIndex(audio_io_handle_t output);
 #endif //AUDIO_POLICY_TEST
 
-        status_t setEffectEnabled(const sp<EffectDescriptor>& effectDesc, bool enabled);
-
         SortedVector<audio_io_handle_t> getOutputsForDevice(audio_devices_t device,
-                        DefaultKeyedVector<audio_io_handle_t, sp<AudioOutputDescriptor> > openOutputs);
+                                                            AudioOutputCollection openOutputs);
         bool vectorsEqual(SortedVector<audio_io_handle_t>& outputs1,
                                            SortedVector<audio_io_handle_t>& outputs2);
 
@@ -407,60 +442,57 @@
 
         audio_io_handle_t selectOutputForEffects(const SortedVector<audio_io_handle_t>& outputs);
 
-        bool isNonOffloadableEffectEnabled();
+        virtual status_t addAudioPatch(audio_patch_handle_t handle, const sp<AudioPatch>& patch)
+        {
+            return mAudioPatches.addAudioPatch(handle, patch);
+        }
+        virtual status_t removeAudioPatch(audio_patch_handle_t handle)
+        {
+            return mAudioPatches.removeAudioPatch(handle);
+        }
 
-        virtual status_t addAudioPatch(audio_patch_handle_t handle,
-                               const sp<AudioPatch>& patch);
-        virtual status_t removeAudioPatch(audio_patch_handle_t handle);
-
-        sp<AudioOutputDescriptor> getOutputFromId(audio_port_handle_t id) const;
-        sp<AudioInputDescriptor> getInputFromId(audio_port_handle_t id) const;
-        sp<HwModule> getModuleForDevice(audio_devices_t device) const;
-        sp<HwModule> getModuleFromName(const char *name) const;
-        audio_devices_t availablePrimaryOutputDevices();
-        audio_devices_t availablePrimaryInputDevices();
+        audio_devices_t availablePrimaryOutputDevices() const
+        {
+            return mOutputs.getSupportedDevices(mPrimaryOutput) & mAvailableOutputDevices.types();
+        }
+        audio_devices_t availablePrimaryInputDevices() const
+        {
+            return mAvailableInputDevices.getDevicesFromHwModule(
+                        mOutputs.valueFor(mPrimaryOutput)->getModuleHandle());
+        }
 
         void updateCallRouting(audio_devices_t rxDevice, int delayMs = 0);
 
-
         uid_t mUidCached;
         AudioPolicyClientInterface *mpClientInterface;  // audio policy client interface
         audio_io_handle_t mPrimaryOutput;              // primary output handle
         // list of descriptors for outputs currently opened
-        DefaultKeyedVector<audio_io_handle_t, sp<AudioOutputDescriptor> > mOutputs;
+        AudioOutputCollection mOutputs;
         // copy of mOutputs before setDeviceConnectionState() opens new outputs
         // reset to mOutputs when updateDevicesAndOutputs() is called.
-        DefaultKeyedVector<audio_io_handle_t, sp<AudioOutputDescriptor> > mPreviousOutputs;
-        DefaultKeyedVector<audio_io_handle_t, sp<AudioInputDescriptor> > mInputs;     // list of input descriptors
+        AudioOutputCollection mPreviousOutputs;
+        AudioInputCollection mInputs;     // list of input descriptors
         DeviceVector  mAvailableOutputDevices; // all available output devices
         DeviceVector  mAvailableInputDevices;  // all available input devices
-        int mPhoneState;                                                    // current phone state
-        audio_policy_forced_cfg_t mForceUse[AUDIO_POLICY_FORCE_USE_CNT];   // current forced use configuration
 
-        StreamDescriptor mStreams[AUDIO_STREAM_CNT];           // stream descriptors for volume control
-        bool    mLimitRingtoneVolume;                                       // limit ringtone volume to music volume if headset connected
+        StreamDescriptorCollection mStreams; // stream descriptors for volume control
+        bool    mLimitRingtoneVolume;        // limit ringtone volume to music volume if headset connected
         audio_devices_t mDeviceForStrategy[NUM_STRATEGIES];
-        float   mLastVoiceVolume;                                           // last voice volume value sent to audio HAL
+        float   mLastVoiceVolume;            // last voice volume value sent to audio HAL
 
-        // Maximum CPU load allocated to audio effects in 0.1 MIPS (ARMv5TE, 0 WS memory) units
-        static const uint32_t MAX_EFFECTS_CPU_LOAD = 1000;
-        // Maximum memory allocated to audio effects in KB
-        static const uint32_t MAX_EFFECTS_MEMORY = 512;
-        uint32_t mTotalEffectsCpuLoad; // current CPU load used by effects
-        uint32_t mTotalEffectsMemory;  // current memory used by effects
-        KeyedVector<int, sp<EffectDescriptor> > mEffects;  // list of registered audio effects
+        EffectDescriptorCollection mEffects;  // list of registered audio effects
         bool    mA2dpSuspended;  // true if A2DP output is suspended
         sp<DeviceDescriptor> mDefaultOutputDevice; // output device selected by default at boot time
         bool mSpeakerDrcEnabled;// true on devices that use DRC on the DEVICE_CATEGORY_SPEAKER path
                                 // to boost soft sounds, used to adjust volume curves accordingly
 
-        Vector < sp<HwModule> > mHwModules;
-        static volatile int32_t mNextUniqueId;
+        HwModuleCollection mHwModules;
+
         volatile int32_t mAudioPortGeneration;
 
-        DefaultKeyedVector<audio_patch_handle_t, sp<AudioPatch> > mAudioPatches;
+        AudioPatchCollection mAudioPatches;
 
-        DefaultKeyedVector<audio_session_t, audio_io_handle_t> mSoundTriggerSessions;
+        SoundTriggerSessionCollection mSoundTriggerSessions;
 
         sp<AudioPatch> mCallTxPatch;
         sp<AudioPatch> mCallRxPatch;
@@ -477,16 +509,7 @@
         uint32_t mBeaconPlayingRefCount;// ref count for the playing beacon streams
         bool mBeaconMuted;              // has STREAM_TTS been muted
 
-        // custom mix entry in mPolicyMixes
-        class AudioPolicyMix : public RefBase {
-        public:
-            AudioPolicyMix() {}
-
-            AudioMix    mMix;                   // Audio policy mix descriptor
-            sp<AudioOutputDescriptor> mOutput;  // Corresponding output stream
-        };
-        DefaultKeyedVector<String8, sp<AudioPolicyMix> > mPolicyMixes; // list of registered mixes
-
+        AudioPolicyMixCollection mPolicyMixes; // list of registered mixes
 
 #ifdef AUDIO_POLICY_TEST
         Mutex   mLock;
@@ -503,14 +526,14 @@
         uint32_t        mTestLatencyMs;
 #endif //AUDIO_POLICY_TEST
 
-        static bool isVirtualInputDevice(audio_devices_t device);
-
         uint32_t nextAudioPortGeneration();
+
+        // Audio Policy Engine Interface.
+        AudioPolicyManagerInterface *mEngine;
 private:
         // updates device caching and output for streams that can influence the
         //    routing of notifications
         void handleNotificationRoutingForStream(audio_stream_type_t stream);
-        static bool deviceDistinguishesOnAddress(audio_devices_t device);
         // find the outputs on a given output descriptor that have the given address.
         // to be called on an AudioOutputDescriptor whose supported devices (as defined
         //   in mProfile->mSupportedDevices) matches the device whose address is to be matched.
@@ -533,8 +556,6 @@
                 const audio_offload_info_t *offloadInfo);
         // internal function to derive a stream type value from audio attributes
         audio_stream_type_t streamTypefromAttributesInt(const audio_attributes_t *attr);
-        // return true if any output is playing anything besides the stream to ignore
-        bool isAnyOutputActive(audio_stream_type_t streamToIgnore);
         // event is one of STARTING_OUTPUT, STARTING_BEACON, STOPPING_OUTPUT, STOPPING_BEACON
         // returns 0 if no mute/unmute event happened, the largest latency of the device where
         //   the mute/unmute happened
@@ -552,9 +573,6 @@
                                                           audio_policy_dev_state_t state,
                                                           const char *device_address,
                                                           const char *device_name);
-        sp<DeviceDescriptor>  getDeviceDescriptor(const audio_devices_t device,
-                                                  const char *device_address,
-                                                  const char *device_name);
 };
 
 };
diff --git a/services/audiopolicy/managerdefault/ConfigParsingUtils.cpp b/services/audiopolicy/managerdefault/ConfigParsingUtils.cpp
deleted file mode 100644
index 1afd487..0000000
--- a/services/audiopolicy/managerdefault/ConfigParsingUtils.cpp
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "APM::ConfigParsingUtils"
-//#define LOG_NDEBUG 0
-
-#include "AudioPolicyManager.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 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, "|");
-    }
-    //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)
-{
-    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 |= stringToEnum(sInputFlagNameToEnumTable,
-                               ARRAY_SIZE(sInputFlagNameToEnumTable),
-                               flagName);
-        }
-        flagName = strtok(NULL, "|");
-    }
-    return flag;
-}
-
-//static
-audio_devices_t ConfigParsingUtils::parseDeviceNames(char *name)
-{
-    uint32_t device = 0;
-
-    char *devName = strtok(name, "|");
-    while (devName != NULL) {
-        if (strlen(devName) != 0) {
-            device |= stringToEnum(sDeviceNameToEnumTable,
-                                 ARRAY_SIZE(sDeviceNameToEnumTable),
-                                 devName);
-         }
-        devName = strtok(NULL, "|");
-     }
-    return device;
-}
-
-}; // namespace android
diff --git a/services/audiopolicy/managerdefault/Gains.cpp b/services/audiopolicy/managerdefault/Gains.cpp
deleted file mode 100644
index 4aca26d..0000000
--- a/services/audiopolicy/managerdefault/Gains.cpp
+++ /dev/null
@@ -1,446 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "APM::Gains"
-//#define LOG_NDEBUG 0
-
-//#define VERY_VERBOSE_LOGGING
-#ifdef VERY_VERBOSE_LOGGING
-#define ALOGVV ALOGV
-#else
-#define ALOGVV(a...) do { } while(0)
-#endif
-
-#include "AudioPolicyManager.h"
-
-#include <math.h>
-
-namespace android {
-
-const VolumeCurvePoint
-ApmGains::sDefaultVolumeCurve[ApmGains::VOLCNT] = {
-    {1, -49.5f}, {33, -33.5f}, {66, -17.0f}, {100, 0.0f}
-};
-
-
-const VolumeCurvePoint
-ApmGains::sDefaultMediaVolumeCurve[ApmGains::VOLCNT] = {
-    {1, -58.0f}, {20, -40.0f}, {60, -17.0f}, {100, 0.0f}
-};
-
-const VolumeCurvePoint
-ApmGains::sExtMediaSystemVolumeCurve[ApmGains::VOLCNT] = {
-    {1, -58.0f}, {20, -40.0f}, {60, -21.0f}, {100, -10.0f}
-};
-
-const VolumeCurvePoint
-ApmGains::sSpeakerMediaVolumeCurve[ApmGains::VOLCNT] = {
-    {1, -56.0f}, {20, -34.0f}, {60, -11.0f}, {100, 0.0f}
-};
-
-const VolumeCurvePoint
-ApmGains::sSpeakerMediaVolumeCurveDrc[ApmGains::VOLCNT] = {
-    {1, -55.0f}, {20, -43.0f}, {86, -12.0f}, {100, 0.0f}
-};
-
-const VolumeCurvePoint
-ApmGains::sSpeakerSonificationVolumeCurve[ApmGains::VOLCNT] = {
-    {1, -29.7f}, {33, -20.1f}, {66, -10.2f}, {100, 0.0f}
-};
-
-const VolumeCurvePoint
-ApmGains::sSpeakerSonificationVolumeCurveDrc[ApmGains::VOLCNT] = {
-    {1, -35.7f}, {33, -26.1f}, {66, -13.2f}, {100, 0.0f}
-};
-
-// AUDIO_STREAM_SYSTEM, AUDIO_STREAM_ENFORCED_AUDIBLE and AUDIO_STREAM_DTMF volume tracks
-// AUDIO_STREAM_RING on phones and AUDIO_STREAM_MUSIC on tablets.
-// AUDIO_STREAM_DTMF tracks AUDIO_STREAM_VOICE_CALL while in call (See AudioService.java).
-// The range is constrained between -24dB and -6dB over speaker and -30dB and -18dB over headset.
-
-const VolumeCurvePoint
-ApmGains::sDefaultSystemVolumeCurve[ApmGains::VOLCNT] = {
-    {1, -24.0f}, {33, -18.0f}, {66, -12.0f}, {100, -6.0f}
-};
-
-const VolumeCurvePoint
-ApmGains::sDefaultSystemVolumeCurveDrc[ApmGains::VOLCNT] = {
-    {1, -34.0f}, {33, -24.0f}, {66, -15.0f}, {100, -6.0f}
-};
-
-const VolumeCurvePoint
-ApmGains::sHeadsetSystemVolumeCurve[ApmGains::VOLCNT] = {
-    {1, -30.0f}, {33, -26.0f}, {66, -22.0f}, {100, -18.0f}
-};
-
-const VolumeCurvePoint
-ApmGains::sDefaultVoiceVolumeCurve[ApmGains::VOLCNT] = {
-    {0, -42.0f}, {33, -28.0f}, {66, -14.0f}, {100, 0.0f}
-};
-
-const VolumeCurvePoint
-ApmGains::sSpeakerVoiceVolumeCurve[ApmGains::VOLCNT] = {
-    {0, -24.0f}, {33, -16.0f}, {66, -8.0f}, {100, 0.0f}
-};
-
-const VolumeCurvePoint
-ApmGains::sLinearVolumeCurve[ApmGains::VOLCNT] = {
-    {0, -96.0f}, {33, -68.0f}, {66, -34.0f}, {100, 0.0f}
-};
-
-const VolumeCurvePoint
-ApmGains::sSilentVolumeCurve[ApmGains::VOLCNT] = {
-    {0, -96.0f}, {1, -96.0f}, {2, -96.0f}, {100, -96.0f}
-};
-
-const VolumeCurvePoint
-ApmGains::sFullScaleVolumeCurve[ApmGains::VOLCNT] = {
-    {0, 0.0f}, {1, 0.0f}, {2, 0.0f}, {100, 0.0f}
-};
-
-const VolumeCurvePoint *ApmGains::sVolumeProfiles[AUDIO_STREAM_CNT]
-                                                  [ApmGains::DEVICE_CATEGORY_CNT] = {
-    { // AUDIO_STREAM_VOICE_CALL
-        ApmGains::sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_HEADSET
-        ApmGains::sSpeakerVoiceVolumeCurve, // DEVICE_CATEGORY_SPEAKER
-        ApmGains::sSpeakerVoiceVolumeCurve, // DEVICE_CATEGORY_EARPIECE
-        ApmGains::sDefaultMediaVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
-    },
-    { // AUDIO_STREAM_SYSTEM
-        ApmGains::sHeadsetSystemVolumeCurve, // DEVICE_CATEGORY_HEADSET
-        ApmGains::sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_SPEAKER
-        ApmGains::sDefaultSystemVolumeCurve,  // DEVICE_CATEGORY_EARPIECE
-        ApmGains::sExtMediaSystemVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
-    },
-    { // AUDIO_STREAM_RING
-        ApmGains::sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET
-        ApmGains::sSpeakerSonificationVolumeCurve, // DEVICE_CATEGORY_SPEAKER
-        ApmGains::sDefaultVolumeCurve,  // DEVICE_CATEGORY_EARPIECE
-        ApmGains::sExtMediaSystemVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
-    },
-    { // AUDIO_STREAM_MUSIC
-        ApmGains::sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_HEADSET
-        ApmGains::sSpeakerMediaVolumeCurve, // DEVICE_CATEGORY_SPEAKER
-        ApmGains::sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_EARPIECE
-        ApmGains::sDefaultMediaVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
-    },
-    { // AUDIO_STREAM_ALARM
-        ApmGains::sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET
-        ApmGains::sSpeakerSonificationVolumeCurve, // DEVICE_CATEGORY_SPEAKER
-        ApmGains::sDefaultVolumeCurve,  // DEVICE_CATEGORY_EARPIECE
-        ApmGains::sExtMediaSystemVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
-    },
-    { // AUDIO_STREAM_NOTIFICATION
-        ApmGains::sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET
-        ApmGains::sSpeakerSonificationVolumeCurve, // DEVICE_CATEGORY_SPEAKER
-        ApmGains::sDefaultVolumeCurve,  // DEVICE_CATEGORY_EARPIECE
-        ApmGains::sExtMediaSystemVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
-    },
-    { // AUDIO_STREAM_BLUETOOTH_SCO
-        ApmGains::sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_HEADSET
-        ApmGains::sSpeakerVoiceVolumeCurve, // DEVICE_CATEGORY_SPEAKER
-        ApmGains::sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_EARPIECE
-        ApmGains::sDefaultMediaVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
-    },
-    { // AUDIO_STREAM_ENFORCED_AUDIBLE
-        ApmGains::sHeadsetSystemVolumeCurve, // DEVICE_CATEGORY_HEADSET
-        ApmGains::sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_SPEAKER
-        ApmGains::sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_EARPIECE
-        ApmGains::sExtMediaSystemVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
-    },
-    {  // AUDIO_STREAM_DTMF
-        ApmGains::sHeadsetSystemVolumeCurve, // DEVICE_CATEGORY_HEADSET
-        ApmGains::sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_SPEAKER
-        ApmGains::sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_EARPIECE
-        ApmGains::sExtMediaSystemVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
-    },
-    { // AUDIO_STREAM_TTS
-      // "Transmitted Through Speaker": always silent except on DEVICE_CATEGORY_SPEAKER
-        ApmGains::sSilentVolumeCurve, // DEVICE_CATEGORY_HEADSET
-        ApmGains::sLinearVolumeCurve, // DEVICE_CATEGORY_SPEAKER
-        ApmGains::sSilentVolumeCurve, // DEVICE_CATEGORY_EARPIECE
-        ApmGains::sSilentVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
-    },
-    { // AUDIO_STREAM_ACCESSIBILITY
-        ApmGains::sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_HEADSET
-        ApmGains::sSpeakerMediaVolumeCurve, // DEVICE_CATEGORY_SPEAKER
-        ApmGains::sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_EARPIECE
-        ApmGains::sDefaultMediaVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
-    },
-    { // AUDIO_STREAM_REROUTING
-        ApmGains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_HEADSET
-        ApmGains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_SPEAKER
-        ApmGains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_EARPIECE
-        ApmGains::sFullScaleVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
-    },
-    { // AUDIO_STREAM_PATCH
-        ApmGains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_HEADSET
-        ApmGains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_SPEAKER
-        ApmGains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_EARPIECE
-        ApmGains::sFullScaleVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
-    },
-};
-
-//static
-audio_devices_t ApmGains::getDeviceForVolume(audio_devices_t device)
-{
-    if (device == AUDIO_DEVICE_NONE) {
-        // this happens when forcing a route update and no track is active on an output.
-        // In this case the returned category is not important.
-        device =  AUDIO_DEVICE_OUT_SPEAKER;
-    } else if (popcount(device) > 1) {
-        // Multiple device selection is either:
-        //  - speaker + one other device: give priority to speaker in this case.
-        //  - one A2DP device + another device: happens with duplicated output. In this case
-        // retain the device on the A2DP output as the other must not correspond to an active
-        // selection if not the speaker.
-        //  - HDMI-CEC system audio mode only output: give priority to available item in order.
-        if (device & AUDIO_DEVICE_OUT_SPEAKER) {
-            device = AUDIO_DEVICE_OUT_SPEAKER;
-        } else if (device & AUDIO_DEVICE_OUT_HDMI_ARC) {
-            device = AUDIO_DEVICE_OUT_HDMI_ARC;
-        } else if (device & AUDIO_DEVICE_OUT_AUX_LINE) {
-            device = AUDIO_DEVICE_OUT_AUX_LINE;
-        } else if (device & AUDIO_DEVICE_OUT_SPDIF) {
-            device = AUDIO_DEVICE_OUT_SPDIF;
-        } else {
-            device = (audio_devices_t)(device & AUDIO_DEVICE_OUT_ALL_A2DP);
-        }
-    }
-
-    /*SPEAKER_SAFE is an alias of SPEAKER for purposes of volume control*/
-    if (device == AUDIO_DEVICE_OUT_SPEAKER_SAFE)
-        device = AUDIO_DEVICE_OUT_SPEAKER;
-
-    ALOGW_IF(popcount(device) != 1,
-            "getDeviceForVolume() invalid device combination: %08x",
-            device);
-
-    return device;
-}
-
-//static
-ApmGains::device_category ApmGains::getDeviceCategory(audio_devices_t device)
-{
-    switch(getDeviceForVolume(device)) {
-        case AUDIO_DEVICE_OUT_EARPIECE:
-            return ApmGains::DEVICE_CATEGORY_EARPIECE;
-        case AUDIO_DEVICE_OUT_WIRED_HEADSET:
-        case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
-        case AUDIO_DEVICE_OUT_BLUETOOTH_SCO:
-        case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET:
-        case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
-        case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
-            return ApmGains::DEVICE_CATEGORY_HEADSET;
-        case AUDIO_DEVICE_OUT_LINE:
-        case AUDIO_DEVICE_OUT_AUX_DIGITAL:
-        /*USB?  Remote submix?*/
-            return ApmGains::DEVICE_CATEGORY_EXT_MEDIA;
-        case AUDIO_DEVICE_OUT_SPEAKER:
-        case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT:
-        case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:
-        case AUDIO_DEVICE_OUT_USB_ACCESSORY:
-        case AUDIO_DEVICE_OUT_USB_DEVICE:
-        case AUDIO_DEVICE_OUT_REMOTE_SUBMIX:
-        default:
-            return ApmGains::DEVICE_CATEGORY_SPEAKER;
-    }
-}
-
-//static
-float ApmGains::volIndexToAmpl(audio_devices_t device, const StreamDescriptor& streamDesc,
-        int indexInUi)
-{
-    ApmGains::device_category deviceCategory = ApmGains::getDeviceCategory(device);
-    const VolumeCurvePoint *curve = streamDesc.mVolumeCurve[deviceCategory];
-
-    // the volume index in the UI is relative to the min and max volume indices for this stream type
-    int nbSteps = 1 + curve[ApmGains::VOLMAX].mIndex -
-            curve[ApmGains::VOLMIN].mIndex;
-    int volIdx = (nbSteps * (indexInUi - streamDesc.mIndexMin)) /
-            (streamDesc.mIndexMax - streamDesc.mIndexMin);
-
-    // find what part of the curve this index volume belongs to, or if it's out of bounds
-    int segment = 0;
-    if (volIdx < curve[ApmGains::VOLMIN].mIndex) {         // out of bounds
-        return 0.0f;
-    } else if (volIdx < curve[ApmGains::VOLKNEE1].mIndex) {
-        segment = 0;
-    } else if (volIdx < curve[ApmGains::VOLKNEE2].mIndex) {
-        segment = 1;
-    } else if (volIdx <= curve[ApmGains::VOLMAX].mIndex) {
-        segment = 2;
-    } else {                                                               // out of bounds
-        return 1.0f;
-    }
-
-    // linear interpolation in the attenuation table in dB
-    float decibels = curve[segment].mDBAttenuation +
-            ((float)(volIdx - curve[segment].mIndex)) *
-                ( (curve[segment+1].mDBAttenuation -
-                        curve[segment].mDBAttenuation) /
-                    ((float)(curve[segment+1].mIndex -
-                            curve[segment].mIndex)) );
-
-    float amplification = exp( decibels * 0.115129f); // exp( dB * ln(10) / 20 )
-
-    ALOGVV("VOLUME vol index=[%d %d %d], dB=[%.1f %.1f %.1f] ampl=%.5f",
-            curve[segment].mIndex, volIdx,
-            curve[segment+1].mIndex,
-            curve[segment].mDBAttenuation,
-            decibels,
-            curve[segment+1].mDBAttenuation,
-            amplification);
-
-    return amplification;
-}
-
-
-
-AudioGain::AudioGain(int index, bool useInChannelMask)
-{
-    mIndex = index;
-    mUseInChannelMask = useInChannelMask;
-    memset(&mGain, 0, sizeof(struct audio_gain));
-}
-
-void AudioGain::getDefaultConfig(struct audio_gain_config *config)
-{
-    config->index = mIndex;
-    config->mode = mGain.mode;
-    config->channel_mask = mGain.channel_mask;
-    if ((mGain.mode & AUDIO_GAIN_MODE_JOINT) == AUDIO_GAIN_MODE_JOINT) {
-        config->values[0] = mGain.default_value;
-    } else {
-        uint32_t numValues;
-        if (mUseInChannelMask) {
-            numValues = audio_channel_count_from_in_mask(mGain.channel_mask);
-        } else {
-            numValues = audio_channel_count_from_out_mask(mGain.channel_mask);
-        }
-        for (size_t i = 0; i < numValues; i++) {
-            config->values[i] = mGain.default_value;
-        }
-    }
-    if ((mGain.mode & AUDIO_GAIN_MODE_RAMP) == AUDIO_GAIN_MODE_RAMP) {
-        config->ramp_duration_ms = mGain.min_ramp_ms;
-    }
-}
-
-status_t AudioGain::checkConfig(const struct audio_gain_config *config)
-{
-    if ((config->mode & ~mGain.mode) != 0) {
-        return BAD_VALUE;
-    }
-    if ((config->mode & AUDIO_GAIN_MODE_JOINT) == AUDIO_GAIN_MODE_JOINT) {
-        if ((config->values[0] < mGain.min_value) ||
-                    (config->values[0] > mGain.max_value)) {
-            return BAD_VALUE;
-        }
-    } else {
-        if ((config->channel_mask & ~mGain.channel_mask) != 0) {
-            return BAD_VALUE;
-        }
-        uint32_t numValues;
-        if (mUseInChannelMask) {
-            numValues = audio_channel_count_from_in_mask(config->channel_mask);
-        } else {
-            numValues = audio_channel_count_from_out_mask(config->channel_mask);
-        }
-        for (size_t i = 0; i < numValues; i++) {
-            if ((config->values[i] < mGain.min_value) ||
-                    (config->values[i] > mGain.max_value)) {
-                return BAD_VALUE;
-            }
-        }
-    }
-    if ((config->mode & AUDIO_GAIN_MODE_RAMP) == AUDIO_GAIN_MODE_RAMP) {
-        if ((config->ramp_duration_ms < mGain.min_ramp_ms) ||
-                    (config->ramp_duration_ms > mGain.max_ramp_ms)) {
-            return BAD_VALUE;
-        }
-    }
-    return NO_ERROR;
-}
-
-void AudioGain::dump(int fd, int spaces, int index) const
-{
-    const size_t SIZE = 256;
-    char buffer[SIZE];
-    String8 result;
-
-    snprintf(buffer, SIZE, "%*sGain %d:\n", spaces, "", index+1);
-    result.append(buffer);
-    snprintf(buffer, SIZE, "%*s- mode: %08x\n", spaces, "", mGain.mode);
-    result.append(buffer);
-    snprintf(buffer, SIZE, "%*s- channel_mask: %08x\n", spaces, "", mGain.channel_mask);
-    result.append(buffer);
-    snprintf(buffer, SIZE, "%*s- min_value: %d mB\n", spaces, "", mGain.min_value);
-    result.append(buffer);
-    snprintf(buffer, SIZE, "%*s- max_value: %d mB\n", spaces, "", mGain.max_value);
-    result.append(buffer);
-    snprintf(buffer, SIZE, "%*s- default_value: %d mB\n", spaces, "", mGain.default_value);
-    result.append(buffer);
-    snprintf(buffer, SIZE, "%*s- step_value: %d mB\n", spaces, "", mGain.step_value);
-    result.append(buffer);
-    snprintf(buffer, SIZE, "%*s- min_ramp_ms: %d ms\n", spaces, "", mGain.min_ramp_ms);
-    result.append(buffer);
-    snprintf(buffer, SIZE, "%*s- max_ramp_ms: %d ms\n", spaces, "", mGain.max_ramp_ms);
-    result.append(buffer);
-
-    write(fd, result.string(), result.size());
-}
-
-
-// --- StreamDescriptor class implementation
-
-StreamDescriptor::StreamDescriptor()
-    :   mIndexMin(0), mIndexMax(1), mCanBeMuted(true)
-{
-    mIndexCur.add(AUDIO_DEVICE_OUT_DEFAULT, 0);
-}
-
-int StreamDescriptor::getVolumeIndex(audio_devices_t device)
-{
-    device = ApmGains::getDeviceForVolume(device);
-    // there is always a valid entry for AUDIO_DEVICE_OUT_DEFAULT
-    if (mIndexCur.indexOfKey(device) < 0) {
-        device = AUDIO_DEVICE_OUT_DEFAULT;
-    }
-    return mIndexCur.valueFor(device);
-}
-
-void StreamDescriptor::dump(int fd)
-{
-    const size_t SIZE = 256;
-    char buffer[SIZE];
-    String8 result;
-
-    snprintf(buffer, SIZE, "%s         %02d         %02d         ",
-             mCanBeMuted ? "true " : "false", mIndexMin, mIndexMax);
-    result.append(buffer);
-    for (size_t i = 0; i < mIndexCur.size(); i++) {
-        snprintf(buffer, SIZE, "%04x : %02d, ",
-                 mIndexCur.keyAt(i),
-                 mIndexCur.valueAt(i));
-        result.append(buffer);
-    }
-    result.append("\n");
-
-    write(fd, result.string(), result.size());
-}
-
-}; // namespace android
diff --git a/services/audiopolicy/managerdefault/Gains.h b/services/audiopolicy/managerdefault/Gains.h
deleted file mode 100644
index b4ab129..0000000
--- a/services/audiopolicy/managerdefault/Gains.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-namespace android {
-
-class VolumeCurvePoint
-{
-public:
-    int mIndex;
-    float mDBAttenuation;
-};
-
-class StreamDescriptor;
-
-class ApmGains
-{
-public :
-    // 4 points to define the volume attenuation curve, each characterized by the volume
-    // index (from 0 to 100) at which they apply, and the attenuation in dB at that index.
-    // we use 100 steps to avoid rounding errors when computing the volume in volIndexToAmpl()
-    enum { VOLMIN = 0, VOLKNEE1 = 1, VOLKNEE2 = 2, VOLMAX = 3, VOLCNT = 4};
-
-    // 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
-    };
-
-    // returns the category the device belongs to with regard to volume curve management
-    static ApmGains::device_category getDeviceCategory(audio_devices_t device);
-
-    // extract one device relevant for volume control from multiple device selection
-    static audio_devices_t getDeviceForVolume(audio_devices_t device);
-
-    static float volIndexToAmpl(audio_devices_t device, const StreamDescriptor& streamDesc,
-                    int indexInUi);
-
-    // default volume curve
-    static const VolumeCurvePoint sDefaultVolumeCurve[ApmGains::VOLCNT];
-    // default volume curve for media strategy
-    static const VolumeCurvePoint sDefaultMediaVolumeCurve[ApmGains::VOLCNT];
-    // volume curve for non-media audio on ext media outputs (HDMI, Line, etc)
-    static const VolumeCurvePoint sExtMediaSystemVolumeCurve[ApmGains::VOLCNT];
-    // volume curve for media strategy on speakers
-    static const VolumeCurvePoint sSpeakerMediaVolumeCurve[ApmGains::VOLCNT];
-    static const VolumeCurvePoint sSpeakerMediaVolumeCurveDrc[ApmGains::VOLCNT];
-    // volume curve for sonification strategy on speakers
-    static const VolumeCurvePoint sSpeakerSonificationVolumeCurve[ApmGains::VOLCNT];
-    static const VolumeCurvePoint sSpeakerSonificationVolumeCurveDrc[ApmGains::VOLCNT];
-    static const VolumeCurvePoint sDefaultSystemVolumeCurve[ApmGains::VOLCNT];
-    static const VolumeCurvePoint sDefaultSystemVolumeCurveDrc[ApmGains::VOLCNT];
-    static const VolumeCurvePoint sHeadsetSystemVolumeCurve[ApmGains::VOLCNT];
-    static const VolumeCurvePoint sDefaultVoiceVolumeCurve[ApmGains::VOLCNT];
-    static const VolumeCurvePoint sSpeakerVoiceVolumeCurve[ApmGains::VOLCNT];
-    static const VolumeCurvePoint sLinearVolumeCurve[ApmGains::VOLCNT];
-    static const VolumeCurvePoint sSilentVolumeCurve[ApmGains::VOLCNT];
-    static const VolumeCurvePoint sFullScaleVolumeCurve[ApmGains::VOLCNT];
-    // default volume curves per stream and device category. See initializeVolumeCurves()
-    static const VolumeCurvePoint *sVolumeProfiles[AUDIO_STREAM_CNT][ApmGains::DEVICE_CATEGORY_CNT];
-};
-
-
-class AudioGain: public RefBase
-{
-public:
-    AudioGain(int index, bool useInChannelMask);
-    virtual ~AudioGain() {}
-
-    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);
-    int               mIndex;
-    struct audio_gain mGain;
-    bool              mUseInChannelMask;
-};
-
-
-// stream descriptor used for volume control
-class StreamDescriptor
-{
-public:
-    StreamDescriptor();
-
-    int getVolumeIndex(audio_devices_t device);
-    void dump(int fd);
-
-    int mIndexMin;      // min volume index
-    int mIndexMax;      // max volume index
-    KeyedVector<audio_devices_t, int> mIndexCur;   // current volume index per device
-    bool mCanBeMuted;   // true is the stream can be muted
-
-    const VolumeCurvePoint *mVolumeCurve[ApmGains::DEVICE_CATEGORY_CNT];
-};
-
-}; // namespace android
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index c2df489..e9c96c6 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -35,7 +35,6 @@
 #include <binder/ProcessInfoService.h>
 #include <cutils/atomic.h>
 #include <cutils/properties.h>
-#include <cutils/multiuser.h>
 #include <gui/Surface.h>
 #include <hardware/hardware.h>
 #include <media/AudioSystem.h>
@@ -123,9 +122,8 @@
 // should be ok for now.
 static CameraService *gCameraService;
 
-CameraService::CameraService()
-    : mEventLog(DEFAULT_EVICTION_LOG_LENGTH), mSoundRef(0), mModule(0), mFlashlight(0)
-{
+CameraService::CameraService() : mEventLog(DEFAULT_EVICTION_LOG_LENGTH),
+        mLastUserId(DEFAULT_LAST_USER_ID), mSoundRef(0), mModule(0), mFlashlight(0) {
     ALOGI("CameraService started (pid=%d)", getpid());
     gCameraService = this;
 
@@ -757,7 +755,8 @@
     return INVALID_OPERATION;
 }
 
-status_t CameraService::validateConnect(const String8& cameraId, /*inout*/int& clientUid) const {
+status_t CameraService::validateConnectLocked(const String8& cameraId, /*inout*/int& clientUid)
+        const {
 
     int callingPid = getCallingPid();
 
@@ -797,6 +796,13 @@
         return -EACCES;
     }
 
+    // Only allow clients who are being used by the current foreground device user.
+    if (mLastUserId != clientUserId && mLastUserId != DEFAULT_LAST_USER_ID) {
+        ALOGE("CameraService::connect X (PID %d) rejected (cannot connect from non-foreground "
+                "device user)", callingPid);
+        return PERMISSION_DENIED;
+    }
+
     return checkIfDeviceIsUsable(cameraId);
 }
 
@@ -1163,6 +1169,21 @@
     return OK;
 }
 
+void CameraService::notifySystemEvent(int eventId, int arg0) {
+    switch(eventId) {
+        case ICameraService::USER_SWITCHED: {
+            doUserSwitch(/*newUserId*/arg0);
+            break;
+        }
+        case ICameraService::NO_EVENT:
+        default: {
+            ALOGW("%s: Received invalid system event from system_server: %d", __FUNCTION__,
+                    eventId);
+            break;
+        }
+    }
+}
+
 status_t CameraService::addListener(
                                 const sp<ICameraServiceListener>& listener) {
     ALOGV("%s: Add listener %p", __FUNCTION__, listener.get());
@@ -1351,6 +1372,8 @@
         // other clients from connecting in mServiceLockWrapper if held
         mServiceLock.unlock();
 
+        // Do not clear caller identity, remote caller should be client proccess
+
         for (auto& i : evicted) {
             if (i.get() != nullptr) {
                 i->disconnect();
@@ -1392,6 +1415,60 @@
     return clientDescriptorPtr->getValue();
 }
 
+void CameraService::doUserSwitch(int newUserId) {
+    // Acquire mServiceLock and prevent other clients from connecting
+    std::unique_ptr<AutoConditionLock> lock =
+            AutoConditionLock::waitAndAcquire(mServiceLockWrapper);
+
+    if (newUserId <= 0) {
+        ALOGW("%s: Bad user ID %d given during user switch, resetting to default.", __FUNCTION__,
+                newUserId);
+        newUserId = DEFAULT_LAST_USER_ID;
+    }
+
+    mLastUserId = newUserId;
+
+    // Current user has switched, evict all current clients.
+    std::vector<sp<BasicClient>> evicted;
+    for (auto& i : mActiveClientManager.getAll()) {
+        auto clientSp = i->getValue();
+
+        if (clientSp.get() == nullptr) {
+            ALOGE("%s: Dead client still in mActiveClientManager.", __FUNCTION__);
+            continue;
+        }
+
+        evicted.push_back(clientSp);
+
+        String8 curTime = getFormattedCurrentTime();
+
+        ALOGE("Evicting conflicting client for camera ID %s due to user change",
+                i->getKey().string());
+        // Log the clients evicted
+        mEventLog.add(String8::format("%s : EVICT device %s client for package %s (PID %"
+                PRId32 ", priority %" PRId32 ")\n   - Evicted due to user switch.",
+                curTime.string(), i->getKey().string(),
+                String8{clientSp->getPackageName()}.string(), i->getOwnerId(),
+                i->getPriority()));
+
+    }
+
+    // Do not hold mServiceLock while disconnecting clients, but retain the condition
+    // blocking other clients from connecting in mServiceLockWrapper if held.
+    mServiceLock.unlock();
+
+    // Clear caller identity temporarily so client disconnect PID checks work correctly
+    int64_t token = IPCThreadState::self()->clearCallingIdentity();
+
+    for (auto& i : evicted) {
+        i->disconnect();
+    }
+
+    IPCThreadState::self()->restoreCallingIdentity(token);
+
+    // Reacquire mServiceLock
+    mServiceLock.lock();
+}
 
 void CameraService::logDisconnected(const String8& cameraId, int clientPid,
         const String8& clientPackage) {
@@ -1411,16 +1488,18 @@
             curTime.string(), cameraId.string(), clientPackage.string(), clientPid));
 }
 
-status_t CameraService::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
+status_t CameraService::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+        uint32_t flags) {
+
+    const int pid = getCallingPid();
+    const int selfPid = getpid();
+
     // Permission checks
     switch (code) {
         case BnCameraService::CONNECT:
         case BnCameraService::CONNECT_DEVICE:
-        case BnCameraService::CONNECT_LEGACY:
-            const int pid = getCallingPid();
-            const int self_pid = getpid();
-            if (pid != self_pid) {
+        case BnCameraService::CONNECT_LEGACY: {
+            if (pid != selfPid) {
                 // we're called from a different process, do the real check
                 if (!checkCallingPermission(
                         String16("android.permission.CAMERA"))) {
@@ -1431,6 +1510,21 @@
                 }
             }
             break;
+        }
+        case BnCameraService::NOTIFY_SYSTEM_EVENT: {
+            if (pid != selfPid) {
+                // Ensure we're being called by system_server, or similar process with
+                // permissions to notify the camera service about system events
+                if (!checkCallingPermission(
+                        String16("android.permission.CAMERA_SEND_SYSTEM_EVENTS"))) {
+                    const int uid = getCallingUid();
+                    ALOGE("Permission Denial: cannot send updates to camera service about system"
+                            " events from pid=%d, uid=%d", pid, uid);
+                    return PERMISSION_DENIED;
+                }
+            }
+            break;
+        }
     }
 
     return BnCameraService::onTransact(code, data, reply, flags);
@@ -1544,7 +1638,11 @@
 }
 
 void CameraService::BasicClient::disconnect() {
-    if (mDisconnected) return;
+    if (mDisconnected) {
+        ALOGE("%s: Disconnect called on already disconnected client for device %d", __FUNCTION__,
+                mCameraId);
+        return;
+    }
     mDisconnected = true;;
 
     mCameraService->removeByClient(this);
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 53f1c72..ca1c504 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -17,6 +17,7 @@
 #ifndef ANDROID_SERVERS_CAMERA_CAMERASERVICE_H
 #define ANDROID_SERVERS_CAMERA_CAMERASERVICE_H
 
+#include <cutils/multiuser.h>
 #include <utils/Vector.h>
 #include <utils/KeyedVector.h>
 #include <binder/AppOpsManager.h>
@@ -92,6 +93,11 @@
     // Default number of messages to store in eviction log
     static const size_t DEFAULT_EVICTION_LOG_LENGTH = 50;
 
+    enum {
+        // Default last user id
+        DEFAULT_LAST_USER_ID = 0,
+    };
+
     // Implementation of BinderService<T>
     static char const* getServiceName() { return "media.camera"; }
 
@@ -145,6 +151,8 @@
     virtual status_t    setTorchMode(const String16& cameraId, bool enabled,
             const sp<IBinder>& clientBinder);
 
+    virtual void notifySystemEvent(int eventId, int arg0);
+
     // OK = supports api of that version, -EOPNOTSUPP = does not support
     virtual status_t    supportsCameraApi(
             int cameraId, int apiVersion);
@@ -447,7 +455,7 @@
     virtual void onFirstRef();
 
     // Check if we can connect, before we acquire the service lock.
-    status_t validateConnect(const String8& cameraId, /*inout*/int& clientUid) const;
+    status_t validateConnectLocked(const String8& cameraId, /*inout*/int& clientUid) const;
 
     // Handle active client evictions, and update service state.
     // Only call with with mServiceLock held.
@@ -485,6 +493,9 @@
     // Circular buffer for storing event logging for dumps
     RingBuffer<String8> mEventLog;
 
+    // UID of last user.
+    int mLastUserId;
+
     /**
      * Get the camera state for a given camera id.
      *
@@ -530,6 +541,11 @@
     sp<CameraService::BasicClient> removeClientLocked(const String8& cameraId);
 
     /**
+     * Handle a notification that the current device user has changed.
+     */
+    void doUserSwitch(int newUserId);
+
+    /**
      * Add a event log message that a client has been disconnected.
      */
     void logDisconnected(const String8& cameraId, int clientPid, const String8& clientPackage);
@@ -702,22 +718,24 @@
             "Camera API version %d", clientPid, clientName8.string(), cameraId.string(),
             halVersion, static_cast<int>(effectiveApiLevel));
 
-    // Enforce client permissions and do basic sanity checks
-    if((ret = validateConnect(cameraId, /*inout*/clientUid)) != NO_ERROR) {
-        return ret;
-    }
-
     sp<CLIENT> client = nullptr;
     {
         // Acquire mServiceLock and prevent other clients from connecting
         std::unique_ptr<AutoConditionLock> lock =
                 AutoConditionLock::waitAndAcquire(mServiceLockWrapper, DEFAULT_CONNECT_TIMEOUT_NS);
+
         if (lock == nullptr) {
             ALOGE("CameraService::connect X (PID %d) rejected (too many other clients connecting)."
                     , clientPid);
             return -EBUSY;
         }
 
+        // Enforce client permissions and do basic sanity checks
+        if((ret = validateConnectLocked(cameraId, /*inout*/clientUid)) != NO_ERROR) {
+            return ret;
+        }
+        mLastUserId = multiuser_get_user_id(clientUid);
+
         // Check the shim parameters after acquiring lock, if they have already been updated and
         // we were doing a shim update, return immediately
         if (shimUpdateOnly) {
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp
index 87e0132..6b0f8b5 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.cpp
+++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp
@@ -65,15 +65,29 @@
     const Size MAX_PREVIEW_SIZE = { MAX_PREVIEW_WIDTH, MAX_PREVIEW_HEIGHT };
     // Treat the H.264 max size as the max supported video size.
     MediaProfiles *videoEncoderProfiles = MediaProfiles::getInstance();
-    int32_t maxVideoWidth = videoEncoderProfiles->getVideoEncoderParamByName(
-                            "enc.vid.width.max", VIDEO_ENCODER_H264);
-    int32_t maxVideoHeight = videoEncoderProfiles->getVideoEncoderParamByName(
-                            "enc.vid.height.max", VIDEO_ENCODER_H264);
-    const Size MAX_VIDEO_SIZE = {maxVideoWidth, maxVideoHeight};
+    Vector<video_encoder> encoders = videoEncoderProfiles->getVideoEncoders();
+    int32_t maxVideoWidth = 0;
+    int32_t maxVideoHeight = 0;
+    for (size_t i = 0; i < encoders.size(); i++) {
+        int width = videoEncoderProfiles->getVideoEncoderParamByName(
+                "enc.vid.width.max", encoders[i]);
+        int height = videoEncoderProfiles->getVideoEncoderParamByName(
+                "enc.vid.height.max", encoders[i]);
+        // Treat width/height separately here to handle the case where different
+        // profile might report max size of different aspect ratio
+        if (width > maxVideoWidth) {
+            maxVideoWidth = width;
+        }
+        if (height > maxVideoHeight) {
+            maxVideoHeight = height;
+        }
+    }
+    // This is just an upper bound and may not be an actually valid video size
+    const Size VIDEO_SIZE_UPPER_BOUND = {maxVideoWidth, maxVideoHeight};
 
     res = getFilteredSizes(MAX_PREVIEW_SIZE, &availablePreviewSizes);
     if (res != OK) return res;
-    res = getFilteredSizes(MAX_VIDEO_SIZE, &availableVideoSizes);
+    res = getFilteredSizes(VIDEO_SIZE_UPPER_BOUND, &availableVideoSizes);
     if (res != OK) return res;
 
     // Select initial preview and video size that's under the initial bound and