auto import from //branches/cupcake/...@137197
diff --git a/libs/audioflinger/A2dpAudioInterface.cpp b/libs/audioflinger/A2dpAudioInterface.cpp
index eb00f8c..2974e32 100644
--- a/libs/audioflinger/A2dpAudioInterface.cpp
+++ b/libs/audioflinger/A2dpAudioInterface.cpp
@@ -48,7 +48,6 @@
         int format, int channelCount, uint32_t sampleRate, status_t *status)
 {
     LOGD("A2dpAudioInterface::openOutputStream %d, %d, %d\n", format, channelCount, sampleRate);
-    Mutex::Autolock lock(mLock);
     status_t err = 0;
 
     // only one output stream allowed
@@ -134,7 +133,8 @@
     mFd(-1), mStandby(true), mStartCount(0), mRetryCount(0), mData(NULL)
 {
     // use any address by default
-    strncpy(mA2dpAddress, "00:00:00:00:00:00", sizeof(mA2dpAddress));
+    strcpy(mA2dpAddress, "00:00:00:00:00:00");
+    init();
 }
 
 status_t A2dpAudioInterface::A2dpAudioStreamOut::set(
@@ -163,18 +163,12 @@
 
 ssize_t A2dpAudioInterface::A2dpAudioStreamOut::write(const void* buffer, size_t bytes)
 {    
-    status_t status = NO_INIT;
-    size_t remaining = bytes;
+    Mutex::Autolock lock(mLock);
 
-    if (!mData) {
-        status = a2dp_init(44100, 2, &mData);
-        if (status < 0) {
-            LOGE("a2dp_init failed err: %d\n", status);
-            mData = NULL;
-            goto Error;
-        }
-        a2dp_set_sink(mData, mA2dpAddress);
-    }
+    size_t remaining = bytes;
+    status_t status = init();
+    if (status < 0)
+        goto Error;
     
     while (remaining > 0) {
         status = a2dp_write(mData, buffer, remaining);
@@ -197,10 +191,27 @@
     return status;
 }
 
+status_t A2dpAudioInterface::A2dpAudioStreamOut::init()
+{
+    if (!mData) {
+        status_t status = a2dp_init(44100, 2, &mData);
+        if (status < 0) {
+            LOGE("a2dp_init failed err: %d\n", status);
+            mData = NULL;
+            return status;
+        }
+        a2dp_set_sink(mData, mA2dpAddress);
+    }
+
+    return 0;
+}
+
 status_t A2dpAudioInterface::A2dpAudioStreamOut::standby()
 {
     int result = 0;
 
+    Mutex::Autolock lock(mLock);
+
     if (!mStandby) {
         result = a2dp_stop(mData);
         if (result == 0)
@@ -212,15 +223,15 @@
 
 status_t A2dpAudioInterface::A2dpAudioStreamOut::setAddress(const char* address)
 {
-    if (strlen(address) < sizeof(mA2dpAddress))
+    Mutex::Autolock lock(mLock);
+
+    if (strlen(address) != strlen("00:00:00:00:00:00"))
         return -EINVAL;
 
-    if (strcmp(address, mA2dpAddress)) {
-        strcpy(mA2dpAddress, address);
-        if (mData)
-            a2dp_set_sink(mData, mA2dpAddress);
-    }
-    
+    strcpy(mA2dpAddress, address);
+    if (mData)
+        a2dp_set_sink(mData, mA2dpAddress);
+
     return NO_ERROR;
 }
 
diff --git a/libs/audioflinger/A2dpAudioInterface.h b/libs/audioflinger/A2dpAudioInterface.h
index a56e8a0..99614dc 100644
--- a/libs/audioflinger/A2dpAudioInterface.h
+++ b/libs/audioflinger/A2dpAudioInterface.h
@@ -82,11 +82,12 @@
         virtual status_t    setVolume(float volume) { return INVALID_OPERATION; }
         virtual ssize_t     write(const void* buffer, size_t bytes);
                 status_t    standby();
-                status_t    close();
         virtual status_t    dump(int fd, const Vector<String16>& args);
 
     private:
         friend class A2dpAudioInterface;
+                status_t    init();
+                status_t    close();
         status_t            setAddress(const char* address);
 
     private:
@@ -96,9 +97,9 @@
                 int         mRetryCount;
                 char        mA2dpAddress[20];
                 void*       mData;
+                Mutex       mLock;
     };
 
-    Mutex                   mLock;
     A2dpAudioStreamOut*     mOutput;
 };
 
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index 92c40e9..440778d 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -71,6 +71,9 @@
 static const int kStartSleepTime = 30000;
 static const int kStopSleepTime = 30000;
 
+static const int kDumpLockRetries = 50;
+static const int kDumpLockSleep = 20000;
+
 // Maximum number of pending buffers allocated by OutputTrack::write()
 static const uint8_t kMaxOutputTrackBuffers = 5;
 
@@ -115,8 +118,7 @@
 
 AudioFlinger::AudioFlinger()
     : BnAudioFlinger(),
-        mAudioHardware(0), mA2dpAudioInterface(0),
-        mA2dpEnabled(false), mA2dpEnabledReq(false),
+        mAudioHardware(0), mA2dpAudioInterface(0), mA2dpEnabled(false), mNotifyA2dpChange(false),
         mForcedSpeakerCount(0), mForcedRoute(0), mRouteRestoreTime(0), mMusicMuteSaved(false)
 {
     mHardwareStatus = AUDIO_HW_IDLE;
@@ -190,13 +192,44 @@
 
 
 #ifdef WITH_A2DP
-void AudioFlinger::setA2dpEnabled(bool enable)
+// setA2dpEnabled_l() must be called with AudioFlinger::mLock held
+void AudioFlinger::setA2dpEnabled_l(bool enable)
 {
+    SortedVector < sp<MixerThread::Track> > tracks;
+    SortedVector < wp<MixerThread::Track> > activeTracks;
+    
     LOGV_IF(enable, "set output to A2DP\n");
     LOGV_IF(!enable, "set output to hardware audio\n");
 
-    mA2dpEnabledReq = enable;
-    mA2dpMixerThread->wakeUp();
+    // Transfer tracks playing on MUSIC stream from one mixer to the other
+    if (enable) {
+        mHardwareMixerThread->getTracks_l(tracks, activeTracks);
+        mA2dpMixerThread->putTracks_l(tracks, activeTracks);
+    } else {
+        mA2dpMixerThread->getTracks_l(tracks, activeTracks);
+        mHardwareMixerThread->putTracks_l(tracks, activeTracks);
+    }
+    mA2dpEnabled = enable;
+    mNotifyA2dpChange = true;
+    mWaitWorkCV.broadcast();
+}
+
+// checkA2dpEnabledChange_l() must be called with AudioFlinger::mLock held
+void AudioFlinger::checkA2dpEnabledChange_l()
+{
+    if (mNotifyA2dpChange) {
+        // Notify AudioSystem of the A2DP activation/deactivation
+        size_t size = mNotificationClients.size();
+        for (size_t i = 0; i < size; i++) {
+            sp<IBinder> binder = mNotificationClients.itemAt(i).promote();
+            if (binder != NULL) {
+                LOGV("Notifying output change to client %p", binder.get());
+                sp<IAudioFlingerClient> client = interface_cast<IAudioFlingerClient> (binder);
+                client->a2dpEnabledChanged(mA2dpEnabled);
+            }
+        }
+        mNotifyA2dpChange = false;
+    }
 }
 #endif // WITH_A2DP
 
@@ -236,8 +269,12 @@
     const size_t SIZE = 256;
     char buffer[SIZE];
     String8 result;
-
-    snprintf(buffer, SIZE, "Hardware status: %d\n", mHardwareStatus);
+    int hardwareStatus = mHardwareStatus;
+    
+    if (hardwareStatus == AUDIO_HW_IDLE && mHardwareMixerThread->mStandby) {
+        hardwareStatus = AUDIO_HW_STANDBY;
+    }
+    snprintf(buffer, SIZE, "Hardware status: %d\n", hardwareStatus);
     result.append(buffer);
     write(fd, result.string(), result.size());
     return NO_ERROR;
@@ -262,7 +299,14 @@
     if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
         dumpPermissionDenial(fd, args);
     } else {
-        AutoMutex lock(&mLock);
+        bool locked = false;
+        for (int i = 0; i < kDumpLockRetries; ++i) {
+            if (mLock.tryLock() == NO_ERROR) {
+                locked = true;
+                break;
+            }
+            usleep(kDumpLockSleep);
+        }
 
         dumpClients(fd, args);
         dumpInternals(fd, args);
@@ -277,6 +321,7 @@
         if (mAudioHardware) {
             mAudioHardware->dumpState(fd, args);
         }
+        if (locked) mLock.unlock();
     }
     return NO_ERROR;
 }
@@ -320,18 +365,19 @@
         }
 #ifdef WITH_A2DP
         if (isA2dpEnabled() && AudioSystem::routedToA2dpOutput(streamType)) {
-            track = mA2dpMixerThread->createTrack(client, streamType, sampleRate, format,
+            track = mA2dpMixerThread->createTrack_l(client, streamType, sampleRate, format,
                     channelCount, frameCount, sharedBuffer, &lStatus);            
         } else 
 #endif
         {
-            track = mHardwareMixerThread->createTrack(client, streamType, sampleRate, format,
+            track = mHardwareMixerThread->createTrack_l(client, streamType, sampleRate, format,
                     channelCount, frameCount, sharedBuffer, &lStatus);            
         }
-        if (track != NULL) {
-            trackHandle = new TrackHandle(track);
-            lStatus = NO_ERROR;            
-        }
+    }
+    if (lStatus == NO_ERROR) {
+        trackHandle = new TrackHandle(track);
+    } else {
+        track.clear();
     }
 
 Exit:
@@ -409,7 +455,7 @@
 #ifdef WITH_A2DP
     mA2dpMixerThread->setMasterVolume(value);
 #endif
-    
+
     return NO_ERROR;
 }
 
@@ -436,7 +482,7 @@
         if (routes & AudioSystem::ROUTE_BLUETOOTH_A2DP) {
             enableA2dp = true;
         }
-        setA2dpEnabled(enableA2dp);
+        setA2dpEnabled_l(enableA2dp);
         LOGV("setOutput done\n");
     }
 #endif
@@ -704,46 +750,6 @@
     }
 }
 
-void AudioFlinger::handleOutputSwitch()
-{
-    if (mA2dpEnabled != mA2dpEnabledReq)
-    {
-        Mutex::Autolock _l(mLock);
-
-        if (mA2dpEnabled != mA2dpEnabledReq)
-        {
-            mA2dpEnabled = mA2dpEnabledReq;
-            SortedVector < sp<MixerThread::Track> > tracks;
-            SortedVector < wp<MixerThread::Track> > activeTracks;
-            
-            // We hold mA2dpMixerThread mLock already 
-            Mutex::Autolock _l(mHardwareMixerThread->mLock);
-            
-            // Transfer tracks playing on MUSIC stream from one mixer to the other
-            if (mA2dpEnabled) {
-                mHardwareMixerThread->getTracks(tracks, activeTracks);
-                mA2dpMixerThread->putTracks(tracks, activeTracks);
-            } else {
-                mA2dpMixerThread->getTracks(tracks, activeTracks);
-                mHardwareMixerThread->putTracks(tracks, activeTracks);
-            }            
-            
-            // Notify AudioSystem of the A2DP activation/deactivation
-            size_t size = mNotificationClients.size();
-            for (size_t i = 0; i < size; i++) {
-                sp<IBinder> binder = mNotificationClients.itemAt(i).promote();
-                if (binder != NULL) {
-                    LOGV("Notifying output change to client %p", binder.get());
-                    sp<IAudioFlingerClient> client = interface_cast<IAudioFlingerClient> (binder);
-                    client->a2dpEnabledChanged(mA2dpEnabled);
-                }
-            }
-
-            mHardwareMixerThread->wakeUp();
-        }
-    }
-}
-
 void AudioFlinger::removeClient(pid_t pid)
 {
     LOGV("removeClient() pid %d, tid %d, calling tid %d", pid, gettid(), IPCThreadState::self()->getCallingPid());
@@ -751,17 +757,9 @@
     mClients.removeItem(pid);
 }
 
-void AudioFlinger::wakeUp()
-{
-    mHardwareMixerThread->wakeUp();
-#ifdef WITH_A2DP
-    mA2dpMixerThread->wakeUp();
-#endif // WITH_A2DP
-}
-
 bool AudioFlinger::isA2dpEnabled() const
 {
-    return mA2dpEnabledReq;
+    return mA2dpEnabled;
 }
 
 void AudioFlinger::handleForcedSpeakerRoute(int command)
@@ -803,7 +801,7 @@
                 LOGV("mForcedSpeakerCount decremented to %d", mForcedSpeakerCount);            
             } else {
                 LOGE("mForcedSpeakerCount is already zero");            
-            }            
+            }
         }
         break;
     case CHECK_ROUTE_RESTORE_TIME:
@@ -946,20 +944,20 @@
 
     do {
         enabledTracks = 0;
-        { // scope for the mLock
+        { // scope for the AudioFlinger::mLock
         
-            Mutex::Autolock _l(mLock);
+            Mutex::Autolock _l(mAudioFlinger->mLock);
 
 #ifdef WITH_A2DP
-            if (mOutputType == AudioSystem::AUDIO_OUTPUT_A2DP) {
-                mAudioFlinger->handleOutputSwitch();
-            }
             if (mOutputTrack != NULL && !mAudioFlinger->isA2dpEnabled()) {
                 if (outputTrackActive) {
+                    mAudioFlinger->mLock.unlock();
                     mOutputTrack->stop();
+                    mAudioFlinger->mLock.lock();
                     outputTrackActive = false;
                 }
             }
+            mAudioFlinger->checkA2dpEnabledChange_l();
 #endif
 
             const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
@@ -968,7 +966,6 @@
             if UNLIKELY(!activeTracks.size() && systemTime() > standbyTime) {
                 // wait until we have something to do...
                 LOGV("Audio hardware entering standby, output %d\n", mOutputType);
-//                mAudioFlinger->mHardwareStatus = AUDIO_HW_STANDBY;
                 if (!mStandby) {
                     mOutput->standby();
                     mStandby = true;
@@ -976,17 +973,18 @@
                 
 #ifdef WITH_A2DP
                 if (outputTrackActive) {
+                    mAudioFlinger->mLock.unlock();
                     mOutputTrack->stop();
+                    mAudioFlinger->mLock.lock();
                     outputTrackActive = false;
                 }
 #endif
                 if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) {
                     mAudioFlinger->handleForcedSpeakerRoute(FORCE_ROUTE_RESTORE);
                 }                
-//                mHardwareStatus = AUDIO_HW_IDLE;
                 // we're about to wait, flush the binder command buffer
                 IPCThreadState::self()->flushCommands();
-                mWaitWorkCV.wait(mLock);
+                mAudioFlinger->mWaitWorkCV.wait(mAudioFlinger->mLock);
                 LOGV("Audio hardware exiting standby, output %d\n", mOutputType);
                 
                 if (mMasterMute == false) {
@@ -1104,13 +1102,13 @@
             if (UNLIKELY(count)) {
                 for (size_t i=0 ; i<count ; i++) {
                     const sp<Track>& track = tracksToRemove[i];
-                    removeActiveTrack(track);
+                    removeActiveTrack_l(track);
                     if (track->isTerminated()) {
                         mTracks.remove(track);
-                        deleteTrackName(track->mName);
+                        deleteTrackName_l(track->mName);
                     }
                 }
-            }  
+            }
        }
         
         if (LIKELY(enabledTracks)) {
@@ -1197,8 +1195,8 @@
     run(buffer, ANDROID_PRIORITY_URGENT_AUDIO);
 }
 
-
-sp<AudioFlinger::MixerThread::Track>  AudioFlinger::MixerThread::createTrack(
+// MixerThread::createTrack_l() must be called with AudioFlinger::mLock held
+sp<AudioFlinger::MixerThread::Track>  AudioFlinger::MixerThread::createTrack_l(
         const sp<AudioFlinger::Client>& client,
         int streamType,
         uint32_t sampleRate,
@@ -1218,26 +1216,22 @@
         goto Exit;
     }
 
-    {
-        Mutex::Autolock _l(mLock);
 
-        if (mSampleRate == 0) {
-            LOGE("Audio driver not initialized.");
-            lStatus = NO_INIT;
-            goto Exit;
-        }
-
-        track = new Track(this, client, streamType, sampleRate, format,
-                channelCount, frameCount, sharedBuffer);
-        if (track->getCblk() == NULL) {
-            track.clear();
-            lStatus = NO_MEMORY;
-            goto Exit;
-        }
-        mTracks.add(track);
-        lStatus = NO_ERROR;
+    if (mSampleRate == 0) {
+        LOGE("Audio driver not initialized.");
+        lStatus = NO_INIT;
+        goto Exit;
     }
 
+    track = new Track(this, client, streamType, sampleRate, format,
+            channelCount, frameCount, sharedBuffer);
+    if (track->getCblk() == NULL) {
+        lStatus = NO_MEMORY;
+        goto Exit;
+    }
+    mTracks.add(track);
+    lStatus = NO_ERROR;
+
 Exit:
     if(status) {
         *status = lStatus;
@@ -1245,12 +1239,13 @@
     return track;
 }
 
-void AudioFlinger::MixerThread::getTracks(
+// getTracks_l() must be called with AudioFlinger::mLock held
+void AudioFlinger::MixerThread::getTracks_l(
         SortedVector < sp<Track> >& tracks,
         SortedVector < wp<Track> >& activeTracks)
 {
     size_t size = mTracks.size();
-    LOGV ("MixerThread::getTracks() for output %d, mTracks.size %d, mActiveTracks.size %d", mOutputType,  mTracks.size(), mActiveTracks.size());
+    LOGV ("MixerThread::getTracks_l() for output %d, mTracks.size %d, mActiveTracks.size %d", mOutputType,  mTracks.size(), mActiveTracks.size());
     for (size_t i = 0; i < size; i++) {
         sp<Track> t = mTracks[i];
         if (AudioSystem::routedToA2dpOutput(t->mStreamType)) {
@@ -1267,28 +1262,29 @@
 
     size = activeTracks.size();
     for (size_t i = 0; i < size; i++) {
-        removeActiveTrack(activeTracks[i]);
+        removeActiveTrack_l(activeTracks[i]);
     }
     
     size = tracks.size();
     for (size_t i = 0; i < size; i++) {
         sp<Track> t = tracks[i];
         mTracks.remove(t);
-        deleteTrackName(t->name());
+        deleteTrackName_l(t->name());
     }
 }
 
-void AudioFlinger::MixerThread::putTracks(
+// putTracks_l() must be called with AudioFlinger::mLock held
+void AudioFlinger::MixerThread::putTracks_l(
         SortedVector < sp<Track> >& tracks,
         SortedVector < wp<Track> >& activeTracks)
 {
 
-    LOGV ("MixerThread::putTracks() for output %d, tracks.size %d, activeTracks.size %d", mOutputType,  tracks.size(), activeTracks.size());
+    LOGV ("MixerThread::putTracks_l() for output %d, tracks.size %d, activeTracks.size %d", mOutputType,  tracks.size(), activeTracks.size());
 
     size_t size = tracks.size();
     for (size_t i = 0; i < size ; i++) {
         sp<Track> t = tracks[i];
-        int name = getTrackName();
+        int name = getTrackName_l();
 
         if (name < 0) return;
         
@@ -1298,7 +1294,7 @@
 
         int j = activeTracks.indexOf(t);
         if (j >= 0) {
-            addActiveTrack(t);
+            addActiveTrack_l(t);
         }            
     }
 }
@@ -1390,10 +1386,10 @@
     return false;
 }
 
-status_t AudioFlinger::MixerThread::addTrack(const sp<Track>& track)
+// addTrack_l() must be called with AudioFlinger::mLock held
+status_t AudioFlinger::MixerThread::addTrack_l(const sp<Track>& track)
 {
     status_t status = ALREADY_EXISTS;
-    Mutex::Autolock _l(mLock);
 
     // here the track could be either new, or restarted
     // in both cases "unstop" the track
@@ -1412,55 +1408,41 @@
         // effectively get the latency it requested.
         track->mFillingUpStatus = Track::FS_FILLING;
         track->mResetDone = false;
-        addActiveTrack(track);
+        addActiveTrack_l(track);
         status = NO_ERROR;
     }
     
     LOGV("mWaitWorkCV.broadcast");
-    mWaitWorkCV.broadcast();
+    mAudioFlinger->mWaitWorkCV.broadcast();
 
     return status;
 }
 
-void AudioFlinger::MixerThread::removeTrack(wp<Track> track, int name)
+// removeTrack_l() must be called with AudioFlinger::mLock held
+void AudioFlinger::MixerThread::removeTrack_l(wp<Track> track, int name)
 {
-    Mutex::Autolock _l(mLock);
     sp<Track> t = track.promote();
     if (t!=NULL && (t->mState <= TrackBase::STOPPED)) {
-        remove_track_l(track, name);
-    }
-}
-
-void AudioFlinger::MixerThread::remove_track_l(wp<Track> track, int name)
-{
-    sp<Track> t = track.promote();
-    if (t!=NULL) {
         t->reset();
+        deleteTrackName_l(name);
+        removeActiveTrack_l(track);
+        mAudioFlinger->mWaitWorkCV.broadcast();
     }
-    deleteTrackName(name);
-    removeActiveTrack(track);
-    mWaitWorkCV.broadcast();
 }
 
-void AudioFlinger::MixerThread::destroyTrack(const sp<Track>& track)
+// destroyTrack_l() must be called with AudioFlinger::mLock held
+void AudioFlinger::MixerThread::destroyTrack_l(const sp<Track>& track)
 {
-    // NOTE: We're acquiring a strong reference on the track before
-    // acquiring the lock, this is to make sure removing it from
-    // mTracks won't cause the destructor to be called while the lock is
-    // held (note that technically, 'track' could be a reference to an item
-    // in mTracks, which is why we need to do this).
-    sp<Track> keep(track);
-    Mutex::Autolock _l(mLock);
     track->mState = TrackBase::TERMINATED;
     if (mActiveTracks.indexOf(track) < 0) {
         LOGV("remove track (%d) and delete from mixer", track->name());
         mTracks.remove(track);
-        deleteTrackName(keep->name());
+        deleteTrackName_l(track->name());
     }
 }
 
-
-void AudioFlinger::MixerThread::addActiveTrack(const wp<Track>& t)
+// addActiveTrack_l() must be called with AudioFlinger::mLock held
+void AudioFlinger::MixerThread::addActiveTrack_l(const wp<Track>& t)
 {
     mActiveTracks.add(t);
 
@@ -1476,7 +1458,8 @@
     }
 }
 
-void AudioFlinger::MixerThread::removeActiveTrack(const wp<Track>& t)
+// removeActiveTrack_l() must be called with AudioFlinger::mLock held
+void AudioFlinger::MixerThread::removeActiveTrack_l(const wp<Track>& t)
 {
     mActiveTracks.remove(t);
 
@@ -1492,12 +1475,14 @@
     }
 }
 
-int AudioFlinger::MixerThread::getTrackName()
+// getTrackName_l() must be called with AudioFlinger::mLock held
+int AudioFlinger::MixerThread::getTrackName_l()
 {
     return mAudioMixer->getTrackName();
 }
 
-void AudioFlinger::MixerThread::deleteTrackName(int name)
+// deleteTrackName_l() must be called with AudioFlinger::mLock held
+void AudioFlinger::MixerThread::deleteTrackName_l(int name)
 {
     mAudioMixer->deleteTrackName(name);
 }
@@ -1509,6 +1494,7 @@
 
 // ----------------------------------------------------------------------------
 
+// TrackBase constructor must be called with AudioFlinger::mLock held
 AudioFlinger::MixerThread::TrackBase::TrackBase(
             const sp<MixerThread>& mixerThread,
             const sp<Client>& client,
@@ -1529,7 +1515,7 @@
         mFormat(format),
         mFlags(flags & ~SYSTEM_FLAGS_MASK)
 {
-    mName = mixerThread->getTrackName();
+    mName = mixerThread->getTrackName_l();
     LOGV("TrackBase contructor name %d, calling thread %d", mName, IPCThreadState::self()->getCallingPid());
     if (mName < 0) {
         LOGE("no more track names availlable");
@@ -1661,6 +1647,7 @@
 
 // ----------------------------------------------------------------------------
 
+// Track constructor must be called with AudioFlinger::mLock held
 AudioFlinger::MixerThread::Track::Track(
             const sp<MixerThread>& mixerThread,
             const sp<Client>& client,
@@ -1681,13 +1668,26 @@
 AudioFlinger::MixerThread::Track::~Track()
 {
     wp<Track> weak(this); // never create a strong ref from the dtor
+    Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
     mState = TERMINATED;
-    mMixerThread->removeTrack(weak, mName);
+    mMixerThread->removeTrack_l(weak, mName);
 }
 
 void AudioFlinger::MixerThread::Track::destroy()
 {
-    mMixerThread->destroyTrack(this);
+    // NOTE: destroyTrack_l() can remove a strong reference to this Track 
+    // by removing it from mTracks vector, so there is a risk that this Tracks's
+    // desctructor is called. As the destructor needs to lock AudioFlinger::mLock,
+    // we must acquire a strong reference on this Track before locking AudioFlinger::mLock
+    // here so that the destructor is called only when exiting this function.
+    // On the other hand, as long as Track::destroy() is only called by 
+    // TrackHandle destructor, the TrackHandle still holds a strong ref on 
+    // this Track with its member mTrack.
+    sp<Track> keep(this);
+    { // scope for AudioFlinger::mLock
+        Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
+        mMixerThread->destroyTrack_l(this);
+    }
 }
 
 void AudioFlinger::MixerThread::Track::dump(char* buffer, size_t size)
@@ -1765,14 +1765,15 @@
 status_t AudioFlinger::MixerThread::Track::start()
 {
     LOGV("start(%d), calling thread %d for output %d", mName, IPCThreadState::self()->getCallingPid(), mMixerThread->mOutputType);
-    mMixerThread->addTrack(this);
+    Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
+    mMixerThread->addTrack_l(this);
     return NO_ERROR;
 }
 
 void AudioFlinger::MixerThread::Track::stop()
 {
     LOGV("stop(%d), calling thread %d for output %d", mName, IPCThreadState::self()->getCallingPid(), mMixerThread->mOutputType);
-    Mutex::Autolock _l(mMixerThread->mLock);
+    Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
     if (mState > STOPPED) {
         mState = STOPPED;
         // If the track is not active (PAUSED and buffers full), flush buffers
@@ -1786,7 +1787,7 @@
 void AudioFlinger::MixerThread::Track::pause()
 {
     LOGV("pause(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
-    Mutex::Autolock _l(mMixerThread->mLock);
+    Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
     if (mState == ACTIVE || mState == RESUMING) {
         mState = PAUSING;
         LOGV("ACTIVE/RESUMING => PAUSING (%d)", mName);
@@ -1796,7 +1797,7 @@
 void AudioFlinger::MixerThread::Track::flush()
 {
     LOGV("flush(%d)", mName);
-    Mutex::Autolock _l(mMixerThread->mLock);
+    Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
     if (mState != STOPPED && mState != PAUSED && mState != PAUSING) {
         return;
     }
@@ -1840,6 +1841,7 @@
 
 // ----------------------------------------------------------------------------
 
+// RecordTrack constructor must be called with AudioFlinger::mLock held
 AudioFlinger::MixerThread::RecordTrack::RecordTrack(
             const sp<MixerThread>& mixerThread,
             const sp<Client>& client,
@@ -1857,7 +1859,8 @@
 
 AudioFlinger::MixerThread::RecordTrack::~RecordTrack()
 {
-    mMixerThread->deleteTrackName(mName);
+    Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
+    mMixerThread->deleteTrackName_l(mName);
 }
 
 status_t AudioFlinger::MixerThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
@@ -2183,7 +2186,6 @@
         uint32_t flags,
         status_t *status)
 {
-    sp<AudioRecordThread> thread;
     sp<MixerThread::RecordTrack> recordTrack;
     sp<RecordHandle> recordHandle;
     sp<Client> client;
@@ -2227,7 +2229,7 @@
     }
 
     // add client to list
-    {
+    { // scope for mLock
         Mutex::Autolock _l(mLock);
         wclient = mClients.valueFor(pid);
         if (wclient != NULL) {
@@ -2236,15 +2238,15 @@
             client = new Client(this, pid);
             mClients.add(pid, client);
         }
+
+        // frameCount must be a multiple of input buffer size
+        inFrameCount = inputBufferSize/channelCount/sizeof(short);
+        frameCount = ((frameCount - 1)/inFrameCount + 1) * inFrameCount;
+    
+        // create new record track. The record track uses one track in mHardwareMixerThread by convention.
+        recordTrack = new MixerThread::RecordTrack(mHardwareMixerThread, client, streamType, sampleRate,
+                                                   format, channelCount, frameCount, flags);
     }
-
-    // frameCount must be a multiple of input buffer size
-    inFrameCount = inputBufferSize/channelCount/sizeof(short);
-    frameCount = ((frameCount - 1)/inFrameCount + 1) * inFrameCount;
-
-    // create new record track and pass to record thread
-    recordTrack = new MixerThread::RecordTrack(mHardwareMixerThread, client, streamType, sampleRate,
-                                               format, channelCount, frameCount, flags);
     if (recordTrack->getCblk() == NULL) {
         recordTrack.clear();
         lStatus = NO_MEMORY;
@@ -2369,7 +2371,8 @@
         } else if (mRecordTrack != 0) {
 
             buffer.frameCount = inFrameCount;
-            if (LIKELY(mRecordTrack->getNextBuffer(&buffer) == NO_ERROR)) {
+            if (LIKELY(mRecordTrack->getNextBuffer(&buffer) == NO_ERROR &&
+                       (int)buffer.frameCount == inFrameCount)) {
                 LOGV("AudioRecordThread read: %d frames", buffer.frameCount);
                 ssize_t bytesRead = input->read(buffer.raw, inBufferSize);
                 if (bytesRead < 0) {
diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h
index 77f064b..c505336 100644
--- a/libs/audioflinger/AudioFlinger.h
+++ b/libs/audioflinger/AudioFlinger.h
@@ -112,7 +112,7 @@
     
     virtual     size_t      getInputBufferSize(uint32_t sampleRate, int format, int channelCount);
     
-    virtual     void        wakeUp();
+    virtual     void        wakeUp()    { mWaitWorkCV.broadcast(); }
     
     // IBinder::DeathRecipient
     virtual     void        binderDied(const wp<IBinder>& who);
@@ -161,7 +161,8 @@
     void                    doSetOutput(int outputType);
 
 #ifdef WITH_A2DP
-    void                    setA2dpEnabled(bool enable);
+    void                    setA2dpEnabled_l(bool enable);
+    void                    checkA2dpEnabledChange_l();
 #endif
     static bool             streamForcedToSpeaker(int streamType);
     
@@ -459,7 +460,7 @@
                     bool        isMusicActive() const;
         
                     
-        sp<Track> createTrack(
+                    sp<Track>   createTrack_l(
                                     const sp<AudioFlinger::Client>& client,
                                     int streamType,
                                     uint32_t sampleRate,
@@ -468,12 +469,10 @@
                                     int frameCount,
                                     const sp<IMemory>& sharedBuffer,
                                     status_t *status);
-
-                    void        wakeUp() { mWaitWorkCV.broadcast(); }
                     
-                    void        getTracks(SortedVector < sp<Track> >& tracks,
+                    void        getTracks_l(SortedVector < sp<Track> >& tracks,
                                           SortedVector < wp<Track> >& activeTracks);
-                    void        putTracks(SortedVector < sp<Track> >& tracks,
+                    void        putTracks_l(SortedVector < sp<Track> >& tracks,
                                           SortedVector < wp<Track> >& activeTracks);
                     void        setOuputTrack(OutputTrack *track) { mOutputTrack = track; }
                     
@@ -498,22 +497,19 @@
         MixerThread(const Client&);
         MixerThread& operator = (const MixerThread&);
   
-        status_t    addTrack(const sp<Track>& track);
-        void        removeTrack(wp<Track> track, int name);
-        void        remove_track_l(wp<Track> track, int name);
-        void        destroyTrack(const sp<Track>& track);
-        int         getTrackName();
-        void        deleteTrackName(int name);
-        void        addActiveTrack(const wp<Track>& t);
-        void        removeActiveTrack(const wp<Track>& t);
+        status_t    addTrack_l(const sp<Track>& track);
+        void        removeTrack_l(wp<Track> track, int name);
+        void        destroyTrack_l(const sp<Track>& track);
+        int         getTrackName_l();
+        void        deleteTrackName_l(int name);
+        void        addActiveTrack_l(const wp<Track>& t);
+        void        removeActiveTrack_l(const wp<Track>& t);
         size_t      getOutputFrameCount();
 
         status_t    dumpInternals(int fd, const Vector<String16>& args);
         status_t    dumpTracks(int fd, const Vector<String16>& args);
         
         sp<AudioFlinger>                mAudioFlinger;       
-        mutable     Mutex               mLock;
-        mutable     Condition           mWaitWorkCV;
         SortedVector< wp<Track> >       mActiveTracks;
         SortedVector< sp<Track> >       mTracks;
         stream_type_t                   mStreamTypes[AudioSystem::NUM_STREAM_TYPES];
@@ -607,11 +603,11 @@
 
                 status_t    startRecord(MixerThread::RecordTrack* recordTrack);
                 void        stopRecord(MixerThread::RecordTrack* recordTrack);
-                
-                void        handleOutputSwitch();
 
-    mutable     Mutex                                       mHardwareLock;
-    mutable     Mutex                                       mLock;
+    mutable     Mutex                               mHardwareLock;
+    mutable     Mutex                               mLock;
+    mutable     Condition                           mWaitWorkCV;
+
                 DefaultKeyedVector< pid_t, wp<Client> >     mClients;
 
                 sp<MixerThread>                     mA2dpMixerThread;
@@ -620,7 +616,7 @@
                 AudioHardwareInterface*             mA2dpAudioInterface;
                 sp<AudioRecordThread>               mAudioRecordThread;
                 bool                                mA2dpEnabled;
-                bool                                mA2dpEnabledReq;
+                bool                                mNotifyA2dpChange;
     mutable     int                                 mHardwareStatus;
                 SortedVector< wp<IBinder> >         mNotificationClients;
                 int                                 mForcedSpeakerCount;