auto import from //branches/cupcake/...@125939
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index 53b18ad..d4692ad 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -100,11 +100,11 @@
 AudioFlinger::AudioFlinger()
     : BnAudioFlinger(), Thread(false),
         mMasterVolume(0), mMasterMute(true), mHardwareAudioMixer(0), mA2dpAudioMixer(0),
-        mAudioMixer(0), mAudioHardware(0), mA2dpAudioInterface(0),
-        mHardwareOutput(0), mA2dpOutput(0), mOutput(0), mAudioRecordThread(0),
-        mSampleRate(0), mFrameCount(0), mChannelCount(0), mFormat(0),
-        mMixBuffer(0), mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0),
-        mStandby(false), mInWrite(false)
+        mAudioMixer(0), mAudioHardware(0), mA2dpAudioInterface(0), mHardwareOutput(0),
+        mA2dpOutput(0), mOutput(0), mRequestedOutput(0), mAudioRecordThread(0),
+        mSampleRate(0), mFrameCount(0), mChannelCount(0), mFormat(0), mMixBuffer(0),
+        mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mStandby(false),
+        mInWrite(false)
 {
     mHardwareStatus = AUDIO_HW_IDLE;
     mAudioHardware = AudioHardwareInterface::create();
@@ -116,9 +116,9 @@
         mHardwareOutput = mAudioHardware->openOutputStream(AudioSystem::PCM_16_BIT, 0, 0, &status);
         mHardwareStatus = AUDIO_HW_IDLE;
         if (mHardwareOutput) {
-            mSampleRate = mHardwareOutput->sampleRate();
-            mHardwareAudioMixer = new AudioMixer(getOutputFrameCount(mHardwareOutput), mSampleRate);
-            setOutput(mHardwareOutput);
+            mHardwareAudioMixer = new AudioMixer(getOutputFrameCount(mHardwareOutput), mHardwareOutput->sampleRate());
+            mRequestedOutput = mHardwareOutput;
+            doSetOutput(mHardwareOutput);
 
             // FIXME - this should come from settings
             setMasterVolume(1.0f);
@@ -159,7 +159,6 @@
     }
 
     char value[PROPERTY_VALUE_MAX];
-    // FIXME: What property should this be???
     property_get("ro.audio.silent", value, "0");
     if (atoi(value)) {
         LOGD("Silence is golden");
@@ -173,9 +172,8 @@
         mAudioRecordThread->exit();
         mAudioRecordThread.clear();        
     }
-    delete mOutput;
-    delete mA2dpOutput;
     delete mAudioHardware;
+    // deleting mA2dpAudioInterface also deletes mA2dpOutput;
     delete mA2dpAudioInterface;
     delete [] mMixBuffer;
     delete mHardwareAudioMixer;
@@ -184,26 +182,22 @@
  
 void AudioFlinger::setOutput(AudioStreamOut* output)
 {
-    // lock on mOutputLock to prevent threadLoop() from starving us
-    Mutex::Autolock _l2(mOutputLock);
-    
-    // to synchronize with threadLoop()
-    Mutex::Autolock _l(mLock);
+    mRequestedOutput = output;
+}
 
-    if (mOutput != output) {
-        mSampleRate = output->sampleRate();
-        mChannelCount = output->channelCount();
-    
-        // FIXME - Current mixer implementation only supports stereo output
-        if (mChannelCount == 1) {
-            LOGE("Invalid audio hardware channel count");
-        }
-        mFormat = output->format();
-        mFrameCount = getOutputFrameCount(output);
-                
-        mAudioMixer = (output == mA2dpOutput ? mA2dpAudioMixer : mHardwareAudioMixer);
-        mOutput = output;
+void AudioFlinger::doSetOutput(AudioStreamOut* output)
+{
+    mSampleRate = output->sampleRate();
+    mChannelCount = output->channelCount();
+
+    // FIXME - Current mixer implementation only supports stereo output
+    if (mChannelCount == 1) {
+        LOGE("Invalid audio hardware channel count");
     }
+    mFormat = output->format();
+    mFrameCount = getOutputFrameCount(output);
+    mAudioMixer = (output == mA2dpOutput ? mA2dpAudioMixer : mHardwareAudioMixer);
+    mOutput = output;
 }
 
 size_t AudioFlinger::getOutputFrameCount(AudioStreamOut* output) 
@@ -330,21 +324,11 @@
     Vector< sp<Track> > tracksToRemove;
     size_t enabledTracks = 0;
     nsecs_t standbyTime = systemTime();
-    AudioMixer* mixer = 0;
-    size_t frameCount = 0;
-    int channelCount = 0;
-    uint32_t sampleRate = 0;
-    AudioStreamOut* output = 0;
 
     do {
         enabledTracks = 0;
         { // scope for the mLock
         
-            // locking briefly on the secondary mOutputLock is necessary to avoid
-            // having this thread starve the thread that called setOutput()
-            mOutputLock.lock();
-            mOutputLock.unlock();
-
             Mutex::Autolock _l(mLock);
             const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
 
@@ -354,7 +338,7 @@
                 LOGV("Audio hardware entering standby\n");
                 mHardwareStatus = AUDIO_HW_STANDBY;
                 if (!mStandby) {
-                    mAudioHardware->standby();
+                    mOutput->standby();
                     mStandby = true;
                 }
                 mHardwareStatus = AUDIO_HW_IDLE;
@@ -366,15 +350,16 @@
                 continue;
             }
 
-            // get active mixer and output parameter while the lock is held and keep them
-            // consistent till the next loop.
-            
-            mixer = audioMixer();
-            frameCount = mFrameCount;
-            channelCount = mChannelCount;
-            sampleRate = mSampleRate;
-            output = mOutput;
-            
+            // check for change in output
+            if (mRequestedOutput != mOutput) {
+
+                // put current output into standby mode
+                if (mOutput) mOutput->standby();
+
+                // change output
+                doSetOutput(mRequestedOutput);
+            }
+
             // find out which tracks need to be processed
             size_t count = activeTracks.size();
             for (size_t i=0 ; i<count ; i++) {
@@ -386,7 +371,7 @@
 
                 // The first time a track is added we wait
                 // for all its buffers to be filled before processing it
-                mixer->setActiveTrack(track->name());
+                mAudioMixer->setActiveTrack(track->name());
                 if (cblk->framesReady() && (track->isReady() || track->isStopped()) &&
                         !track->isPaused())
                 {
@@ -412,8 +397,8 @@
                     }
 
                     // XXX: these things DON'T need to be done each time
-                    mixer->setBufferProvider(track);
-                    mixer->enable(AudioMixer::MIXING);
+                    mAudioMixer->setBufferProvider(track);
+                    mAudioMixer->enable(AudioMixer::MIXING);
 
                     int param;
                     if ( track->mFillingUpStatus == Track::FS_FILLED) {
@@ -428,15 +413,15 @@
                     } else {
                         param = AudioMixer::RAMP_VOLUME;
                     }
-                    mixer->setParameter(param, AudioMixer::VOLUME0, left);
-                    mixer->setParameter(param, AudioMixer::VOLUME1, right);
-                    mixer->setParameter(
+                    mAudioMixer->setParameter(param, AudioMixer::VOLUME0, left);
+                    mAudioMixer->setParameter(param, AudioMixer::VOLUME1, right);
+                    mAudioMixer->setParameter(
                         AudioMixer::TRACK,
                         AudioMixer::FORMAT, track->format());
-                    mixer->setParameter(
+                    mAudioMixer->setParameter(
                         AudioMixer::TRACK,
                         AudioMixer::CHANNEL_COUNT, track->channelCount());
-                    mixer->setParameter(
+                    mAudioMixer->setParameter(
                         AudioMixer::RESAMPLE,
                         AudioMixer::SAMPLE_RATE,
                         int(cblk->sampleRate));
@@ -463,7 +448,7 @@
                         }
                     }
                     // LOGV("disable(%d)", track->name());
-                    mixer->disable(AudioMixer::MIXING);
+                    mAudioMixer->disable(AudioMixer::MIXING);
                 }
             }
 
@@ -475,27 +460,27 @@
                     mActiveTracks.remove(track);
                     if (track->isTerminated()) {
                         mTracks.remove(track);
-                        mixer->deleteTrackName(track->mName);
+                        mAudioMixer->deleteTrackName(track->mName);
                     }
                 }
             }  
        }
         if (LIKELY(enabledTracks)) {
             // mix buffers...
-            mixer->process(curBuf);
+            mAudioMixer->process(curBuf);
 
             // output audio to hardware
             mLastWriteTime = systemTime();
             mInWrite = true;
-            size_t mixBufferSize = frameCount*channelCount*sizeof(int16_t);
-            output->write(curBuf, mixBufferSize);
+            size_t mixBufferSize = mFrameCount*mChannelCount*sizeof(int16_t);
+            mOutput->write(curBuf, mixBufferSize);
             mNumWrites++;
             mInWrite = false;
             mStandby = false;
             nsecs_t temp = systemTime();
             standbyTime = temp + kStandbyTimeInNsecs;
             nsecs_t delta = temp - mLastWriteTime;
-            nsecs_t maxPeriod = seconds(frameCount) / sampleRate * 2;
+            nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 2;
             if (delta > maxPeriod) {
                 LOGW("write blocked for %llu msecs", ns2ms(delta));
                 mNumDelayedWrites++;
@@ -653,6 +638,8 @@
 
 status_t AudioFlinger::setRouting(int mode, uint32_t routes, uint32_t mask)
 {
+    status_t err = NO_ERROR;
+
     // check calling permissions
     if (!settingsAllowed()) {
         return PERMISSION_DENIED;
@@ -677,16 +664,20 @@
     }
 #endif
 
-    AutoMutex lock(mHardwareLock);
-    mHardwareStatus = AUDIO_HW_GET_ROUTING;
-    uint32_t r;
-    uint32_t err = mAudioHardware->getRouting(mode, &r);
-    if (err == NO_ERROR) {
-        r = (r & ~mask) | (routes & mask);
-        mHardwareStatus = AUDIO_HW_SET_ROUTING;
-        err = mAudioHardware->setRouting(mode, r);
+    // do nothing if only A2DP routing is affected
+    mask &= ~AudioSystem::ROUTE_BLUETOOTH_A2DP;
+    if (mask) {
+        AutoMutex lock(mHardwareLock);
+        mHardwareStatus = AUDIO_HW_GET_ROUTING;
+        uint32_t r;
+        err = mAudioHardware->getRouting(mode, &r);
+        if (err == NO_ERROR) {
+            r = (r & ~mask) | (routes & mask);
+            mHardwareStatus = AUDIO_HW_SET_ROUTING;
+            err = mAudioHardware->setRouting(mode, r);
+        }
+        mHardwareStatus = AUDIO_HW_IDLE;
     }
-    mHardwareStatus = AUDIO_HW_IDLE;
     return err;
 }