auto import from //branches/cupcake/...@125939
diff --git a/libs/audioflinger/A2dpAudioInterface.cpp b/libs/audioflinger/A2dpAudioInterface.cpp
index d54795c..b2a8e96 100644
--- a/libs/audioflinger/A2dpAudioInterface.cpp
+++ b/libs/audioflinger/A2dpAudioInterface.cpp
@@ -79,11 +79,6 @@
     return NULL;
 }
 
-status_t A2dpAudioInterface::standby()
-{
-    return 0;
-}
-
 status_t A2dpAudioInterface::setMicMute(bool state)
 {
     return 0;
@@ -123,8 +118,8 @@
 // ----------------------------------------------------------------------------
 
 A2dpAudioInterface::A2dpAudioStreamOut::A2dpAudioStreamOut() :
-    mFd(-1), mStartCount(0), mRetryCount(0), mData(NULL),
-    mInitialized(false), mBufferRemaining(0)
+    mFd(-1), mStandby(false), mStartCount(0), mRetryCount(0), mData(NULL),
+    mInitialized(false)
 {
 }
 
@@ -155,26 +150,50 @@
 
 ssize_t A2dpAudioInterface::A2dpAudioStreamOut::write(const void* buffer, size_t bytes)
 {    
+    status_t status = NO_INIT;
+    size_t remaining = bytes;
+
     if (!mInitialized) {
-        int ret = a2dp_init("00:00:00:00:00:00", 44100, 2, &mData);
-        if (ret)
-            return ret;
+        status = a2dp_init("00:00:00:00:00:00", 44100, 2, &mData);
+        if (status < 0) {
+            LOGE("a2dp_init failed err: %d\n", status);
+            goto Error;
+        }
         mInitialized = true;
     }
     
-    size_t remaining = bytes;
     while (remaining > 0) {
-        int written = a2dp_write(mData, buffer, remaining);        
-        remaining -= written;
-        buffer = ((char *)buffer) + written;
+        status = a2dp_write(mData, buffer, remaining);
+        if (status <= 0) {
+            LOGE("a2dp_write failed err: %d\n", status);
+            goto Error;
+        }
+        remaining -= status;
+        buffer = ((char *)buffer) + status;
     }
+
+    mStandby = false;
     
     return bytes;
+
+Error:   
+    // Simulate audio output timing in case of error
+    usleep(bytes * 1000000 / frameSize() / sampleRate());
+
+    return status;
 }
 
 status_t A2dpAudioInterface::A2dpAudioStreamOut::standby()
 {
-    return 0;
+    int result = 0;
+
+    if (!mStandby) {
+        result = a2dp_stop(mData);
+        if (result == 0)
+            mStandby = true;
+    }
+
+    return result;
 }
 
 status_t A2dpAudioInterface::A2dpAudioStreamOut::dump(int fd, const Vector<String16>& args)
diff --git a/libs/audioflinger/A2dpAudioInterface.h b/libs/audioflinger/A2dpAudioInterface.h
index 03bf933..b8119a1 100644
--- a/libs/audioflinger/A2dpAudioInterface.h
+++ b/libs/audioflinger/A2dpAudioInterface.h
@@ -35,7 +35,6 @@
                         A2dpAudioInterface();
     virtual             ~A2dpAudioInterface();
     virtual status_t    initCheck();
-    virtual status_t    standby();
 
     virtual status_t    setVoiceVolume(float volume);
     virtual status_t    setMasterVolume(float volume);
@@ -74,11 +73,11 @@
                                 int channelCount,
                                 uint32_t sampleRate);
         virtual uint32_t    sampleRate() const { return 44100; }
-        // must be 32-bit aligned - driver only seems to like 4800
-        virtual size_t      bufferSize() const { return 5120; }
+        // SBC codec wants a multiple of 512
+        virtual size_t      bufferSize() const { return 512 * 30; }
         virtual int         channelCount() const { return 2; }
         virtual int         format() const { return AudioSystem::PCM_16_BIT; }
-        virtual uint32_t    latency() const { return 0; }
+        virtual uint32_t    latency() const { return ((1000*channelCount()*bufferSize())/frameSize())/sampleRate() + 200; }
         virtual status_t    setVolume(float volume) { return INVALID_OPERATION; }
         virtual ssize_t     write(const void* buffer, size_t bytes);
                 status_t    standby();
@@ -86,14 +85,11 @@
 
     private:
                 int         mFd;
+                bool        mStandby;
                 int         mStartCount;
                 int         mRetryCount;
                 void*       mData;
                 bool        mInitialized;
-
-#define kBufferSize 50000
-                char                    mBuffer[kBufferSize];
-                int                     mBufferRemaining;
     };
 
     Mutex                   mLock;
diff --git a/libs/audioflinger/AudioDumpInterface.cpp b/libs/audioflinger/AudioDumpInterface.cpp
index 8eee9cc..b4940cb 100644
--- a/libs/audioflinger/AudioDumpInterface.cpp
+++ b/libs/audioflinger/AudioDumpInterface.cpp
@@ -49,14 +49,6 @@
 }
 
 
-status_t AudioDumpInterface::standby()
-{
-    if(mStreamOut)  mStreamOut->Close();
-    gFirst = true;
-    return mFinalInterface->standby();
-}
-
-
 AudioStreamOut* AudioDumpInterface::openOutputStream(
         int format, int channelCount, uint32_t sampleRate, status_t *status)
 {
@@ -106,6 +98,14 @@
     return ret;
 }
 
+status_t AudioStreamOutDump::standby()
+{
+    Close();
+    gFirst = true;
+    return mFinalStream->standby();
+}
+
+
 void AudioStreamOutDump::Close(void)
 {
     if(mOutFile) {
diff --git a/libs/audioflinger/AudioDumpInterface.h b/libs/audioflinger/AudioDumpInterface.h
index a65e56a..82b5250 100644
--- a/libs/audioflinger/AudioDumpInterface.h
+++ b/libs/audioflinger/AudioDumpInterface.h
@@ -40,6 +40,7 @@
     virtual uint32_t    latency() const { return mFinalStream->latency(); }
     virtual status_t    setVolume(float volume)
                             { return mFinalStream->setVolume(volume); }
+    virtual status_t    standby();
     virtual status_t    dump(int fd, const Vector<String16>& args) { return mFinalStream->dump(fd, args); }
     void                Close(void);
 
@@ -54,7 +55,6 @@
 
 public:
                         AudioDumpInterface(AudioHardwareInterface* hw);
-    virtual status_t    standby();
     virtual AudioStreamOut* openOutputStream(
                                 int format=0,
                                 int channelCount=0,
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;
 }
 
diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h
index d9f7b49..7c84e62 100644
--- a/libs/audioflinger/AudioFlinger.h
+++ b/libs/audioflinger/AudioFlinger.h
@@ -150,6 +150,7 @@
     virtual                 ~AudioFlinger();
     
     void                    setOutput(AudioStreamOut* output);
+    void                    doSetOutput(AudioStreamOut* output);
     size_t                  getOutputFrameCount(AudioStreamOut* output);
 
     // Internal dump utilites.
@@ -450,7 +451,6 @@
 
     mutable     Mutex                                       mHardwareLock;
     mutable     Mutex                                       mLock;
-    mutable     Mutex                                       mOutputLock;
     mutable     Condition                                   mWaitWorkCV;
                 DefaultKeyedVector< pid_t, wp<Client> >     mClients;
                 SortedVector< wp<Track> >                   mActiveTracks;
@@ -468,6 +468,7 @@
                 AudioStreamOut*                     mHardwareOutput;
                 AudioStreamOut*                     mA2dpOutput;
                 AudioStreamOut*                     mOutput;
+                AudioStreamOut*                     mRequestedOutput;
                 sp<AudioRecordThread>               mAudioRecordThread;
                 uint32_t                            mSampleRate;
                 size_t                              mFrameCount;
diff --git a/libs/audioflinger/AudioHardwareGeneric.cpp b/libs/audioflinger/AudioHardwareGeneric.cpp
index e6a163b..e455186 100644
--- a/libs/audioflinger/AudioHardwareGeneric.cpp
+++ b/libs/audioflinger/AudioHardwareGeneric.cpp
@@ -61,12 +61,6 @@
     return NO_INIT;
 }
 
-status_t AudioHardwareGeneric::standby()
-{
-    // Implement: audio hardware to standby mode
-    return NO_ERROR;
-}
-
 AudioStreamOut* AudioHardwareGeneric::openOutputStream(
         int format, int channelCount, uint32_t sampleRate, status_t *status)
 {
@@ -215,6 +209,12 @@
     return ssize_t(::write(mFd, buffer, bytes));
 }
 
+status_t AudioStreamOutGeneric::standby()
+{
+    // Implement: audio hardware to standby mode
+    return NO_ERROR;
+}
+
 status_t AudioStreamOutGeneric::dump(int fd, const Vector<String16>& args)
 {
     const size_t SIZE = 256;
diff --git a/libs/audioflinger/AudioHardwareGeneric.h b/libs/audioflinger/AudioHardwareGeneric.h
index a2342cd..bc006b8 100644
--- a/libs/audioflinger/AudioHardwareGeneric.h
+++ b/libs/audioflinger/AudioHardwareGeneric.h
@@ -50,6 +50,7 @@
     virtual uint32_t    latency() const { return 0; }
     virtual status_t    setVolume(float volume) { return INVALID_OPERATION; }
     virtual ssize_t     write(const void* buffer, size_t bytes);
+    virtual status_t    standby();
     virtual status_t    dump(int fd, const Vector<String16>& args);
 
 private:
@@ -92,7 +93,6 @@
                         AudioHardwareGeneric();
     virtual             ~AudioHardwareGeneric();
     virtual status_t    initCheck();
-    virtual status_t    standby();
     virtual status_t    setVoiceVolume(float volume);
     virtual status_t    setMasterVolume(float volume);
 
diff --git a/libs/audioflinger/AudioHardwareStub.cpp b/libs/audioflinger/AudioHardwareStub.cpp
index d309902..e9f3d69 100644
--- a/libs/audioflinger/AudioHardwareStub.cpp
+++ b/libs/audioflinger/AudioHardwareStub.cpp
@@ -41,11 +41,6 @@
     return NO_ERROR;
 }
 
-status_t AudioHardwareStub::standby()
-{
-    return NO_ERROR;
-}
-
 AudioStreamOut* AudioHardwareStub::openOutputStream(
         int format, int channelCount, uint32_t sampleRate, status_t *status)
 {
@@ -125,6 +120,11 @@
     return bytes;
 }
 
+status_t AudioStreamOutStub::standby()
+{
+    return NO_ERROR;
+}
+
 status_t AudioStreamOutStub::dump(int fd, const Vector<String16>& args)
 {
     const size_t SIZE = 256;
diff --git a/libs/audioflinger/AudioHardwareStub.h b/libs/audioflinger/AudioHardwareStub.h
index 5316d60..7ec5b95 100644
--- a/libs/audioflinger/AudioHardwareStub.h
+++ b/libs/audioflinger/AudioHardwareStub.h
@@ -37,6 +37,7 @@
     virtual uint32_t    latency() const { return 0; }
     virtual status_t    setVolume(float volume) { return NO_ERROR; }
     virtual ssize_t     write(const void* buffer, size_t bytes);
+    virtual status_t    standby();
     virtual status_t    dump(int fd, const Vector<String16>& args);
 };
 
@@ -59,7 +60,6 @@
                         AudioHardwareStub();
     virtual             ~AudioHardwareStub();
     virtual status_t    initCheck();
-    virtual status_t    standby();
     virtual status_t    setVoiceVolume(float volume);
     virtual status_t    setMasterVolume(float volume);