Fix issue 2153835: AudioFlinger: setParameters() can remain stuck if output thread is terminated.

Wait for the parameter set completed condition with a time out in ThreadBase::setParameters().
Also lock AudioFlinger mutex before accessing thread list in AudioFlinger::setParameters() and keep a strong reference
on the thread being used in case it is exited while processing the request.
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index 2ed5d3b..8e967fb 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -603,18 +603,19 @@
         return result;
     }
 
-    // Check if parameters are for an output
-    PlaybackThread *playbackThread = checkPlaybackThread_l(ioHandle);
-    if (playbackThread != NULL) {
-        return playbackThread->setParameters(keyValuePairs);
+    // hold a strong ref on thread in case closeOutput() or closeInput() is called
+    // and the thread is exited once the lock is released
+    sp<ThreadBase> thread;
+    {
+        Mutex::Autolock _l(mLock);
+        thread = checkPlaybackThread_l(ioHandle);
+        if (thread == NULL) {
+            thread = checkRecordThread_l(ioHandle);
+        }
     }
-
-    // Check if parameters are for an input
-    RecordThread *recordThread = checkRecordThread_l(ioHandle);
-    if (recordThread != NULL) {
-        return recordThread->setParameters(keyValuePairs);
+    if (thread != NULL) {
+        return thread->setParameters(keyValuePairs);
     }
-
     return BAD_VALUE;
 }
 
@@ -626,6 +627,9 @@
     if (ioHandle == 0) {
         return mAudioHardware->getParameters(keys);
     }
+
+    Mutex::Autolock _l(mLock);
+
     PlaybackThread *playbackThread = checkPlaybackThread_l(ioHandle);
     if (playbackThread != NULL) {
         return playbackThread->getParameters(keys);
@@ -736,7 +740,7 @@
 
 void AudioFlinger::ThreadBase::exit()
 {
-    // keep a strong ref on ourself so that we want get
+    // keep a strong ref on ourself so that we wont get
     // destroyed in the middle of requestExitAndWait()
     sp <ThreadBase> strongMe = this;
 
@@ -778,9 +782,14 @@
 
     mNewParameters.add(keyValuePairs);
     mWaitWorkCV.signal();
-    mParamCond.wait(mLock);
-    status = mParamStatus;
-    mWaitWorkCV.signal();
+    // wait condition with timeout in case the thread loop has exited
+    // before the request could be processed
+    if (mParamCond.waitRelative(mLock, seconds(2)) == NO_ERROR) {
+        status = mParamStatus;
+        mWaitWorkCV.signal();
+    } else {
+        status = TIMED_OUT;
+    }
     return status;
 }