merge in jb-release history after reset to jb-dev
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index b78c6d1..aab9984 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1106,6 +1106,20 @@
     mClients.removeItem(pid);
 }
 
+// getEffectThread_l() must be called with AudioFlinger::mLock held
+sp<AudioFlinger::PlaybackThread> AudioFlinger::getEffectThread_l(int sessionId, int EffectId)
+{
+    sp<PlaybackThread> thread;
+
+    for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+        if (mPlaybackThreads.valueAt(i)->getEffect(sessionId, EffectId) != 0) {
+            ALOG_ASSERT(thread == 0);
+            thread = mPlaybackThreads.valueAt(i);
+        }
+    }
+
+    return thread;
+}
 
 // ----------------------------------------------------------------------------
 
@@ -4677,6 +4691,44 @@
     sp<ThreadBase> thread = mThread.promote();
     if (thread != 0) {
         PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+        sp<AudioFlinger> af = mClient->audioFlinger();
+
+        Mutex::Autolock _l(af->mLock);
+
+        sp<PlaybackThread> srcThread = af->getEffectThread_l(AUDIO_SESSION_OUTPUT_MIX, EffectId);
+
+        if (EffectId != 0 && srcThread != 0 && playbackThread != srcThread.get()) {
+            Mutex::Autolock _dl(playbackThread->mLock);
+            Mutex::Autolock _sl(srcThread->mLock);
+            sp<EffectChain> chain = srcThread->getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
+            if (chain == 0) {
+                return INVALID_OPERATION;
+            }
+
+            sp<EffectModule> effect = chain->getEffectFromId_l(EffectId);
+            if (effect == 0) {
+                return INVALID_OPERATION;
+            }
+            srcThread->removeEffect_l(effect);
+            playbackThread->addEffect_l(effect);
+            // removeEffect_l() has stopped the effect if it was active so it must be restarted
+            if (effect->state() == EffectModule::ACTIVE ||
+                    effect->state() == EffectModule::STOPPING) {
+                effect->start();
+            }
+
+            sp<EffectChain> dstChain = effect->chain().promote();
+            if (dstChain == 0) {
+                srcThread->addEffect_l(effect);
+                return INVALID_OPERATION;
+            }
+            AudioSystem::unregisterEffect(effect->id());
+            AudioSystem::registerEffect(&effect->desc(),
+                                        srcThread->id(),
+                                        dstChain->strategy(),
+                                        AUDIO_SESSION_OUTPUT_MIX,
+                                        effect->id());
+        }
         status = playbackThread->attachAuxEffect(this, EffectId);
     }
     return status;
@@ -7645,6 +7697,12 @@
     return handle;
 }
 
+sp<AudioFlinger::EffectModule> AudioFlinger::ThreadBase::getEffect(int sessionId, int effectId)
+{
+    Mutex::Autolock _l(mLock);
+    return getEffect_l(sessionId, effectId);
+}
+
 sp<AudioFlinger::EffectModule> AudioFlinger::ThreadBase::getEffect_l(int sessionId, int effectId)
 {
     sp<EffectChain> chain = getEffectChain_l(sessionId);
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 384306c..cfd718f 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -253,6 +253,7 @@
                                         int listenerSession,
                                         sync_event_callback_t callBack,
                                         void *cookie);
+
 private:
                audio_mode_t getMode() const { return mMode; }
 
@@ -543,6 +544,7 @@
                     // set audio mode to all effect chains
                     void setMode(audio_mode_t mode);
                     // get effect module with corresponding ID on specified audio session
+                    sp<AudioFlinger::EffectModule> getEffect(int sessionId, int effectId);
                     sp<AudioFlinger::EffectModule> getEffect_l(int sessionId, int effectId);
                     // add and effect module. Also creates the effect chain is none exists for
                     // the effects audio session
@@ -1287,6 +1289,8 @@
               PlaybackThread *primaryPlaybackThread_l() const;
               uint32_t primaryOutputDevice_l() const;
 
+              sp<PlaybackThread> getEffectThread_l(int sessionId, int EffectId);
+
     // server side of the client's IAudioTrack
     class TrackHandle : public android::BnAudioTrack {
     public: