Fix issue 1795088       Improve audio routing code

Initial commit for review.
Integrated comments after patch set 1 review.
Fixed lockup in AudioFlinger::ThreadBase::exit()
Fixed lockup when playing tone with AudioPlocyService startTone()
diff --git a/media/libmedia/IAudioFlingerClient.cpp b/media/libmedia/IAudioFlingerClient.cpp
index 75699b4..eaae977 100644
--- a/media/libmedia/IAudioFlingerClient.cpp
+++ b/media/libmedia/IAudioFlingerClient.cpp
@@ -23,11 +23,12 @@
 #include <binder/Parcel.h>
 
 #include <media/IAudioFlingerClient.h>
+#include <media/AudioSystem.h>
 
 namespace android {
 
 enum {
-    AUDIO_OUTPUT_CHANGED = IBinder::FIRST_CALL_TRANSACTION
+    IO_CONFIG_CHANGED = IBinder::FIRST_CALL_TRANSACTION
 };
 
 class BpAudioFlingerClient : public BpInterface<IAudioFlingerClient>
@@ -38,12 +39,25 @@
     {
     }
 
-    void a2dpEnabledChanged(bool enabled)
+    void ioConfigChanged(int event, void *param1, void *param2)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlingerClient::getInterfaceDescriptor());
-        data.writeInt32((int)enabled);
-        remote()->transact(AUDIO_OUTPUT_CHANGED, data, &reply, IBinder::FLAG_ONEWAY);
+        data.writeInt32(event);
+        data.write(&param1, sizeof(void *));
+        if (event == AudioSystem::STREAM_CONFIG_CHANGED) {
+            uint32_t stream = *(uint32_t *)param2;
+            LOGV("ioConfigChanged stream %d", stream);
+            data.writeInt32(stream);
+        } else if (event != AudioSystem::OUTPUT_CLOSED && event != AudioSystem::INPUT_CLOSED) {
+            AudioSystem::OutputDescriptor *desc = (AudioSystem::OutputDescriptor *)param2;
+            data.writeInt32(desc->samplingRate);
+            data.writeInt32(desc->format);
+            data.writeInt32(desc->channels);
+            data.writeInt32(desc->frameCount);
+            data.writeInt32(desc->latency);
+        }
+        remote()->transact(IO_CONFIG_CHANGED, data, &reply, IBinder::FLAG_ONEWAY);
     }
 };
 
@@ -55,10 +69,27 @@
     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
 {
     switch(code) {
-        case AUDIO_OUTPUT_CHANGED: {
+    case IO_CONFIG_CHANGED: {
             CHECK_INTERFACE(IAudioFlingerClient, data, reply);
-            bool enabled = (bool)data.readInt32();
-            a2dpEnabledChanged(enabled);
+            int event = data.readInt32();
+            void *param1;
+            void *param2 = 0;
+            AudioSystem::OutputDescriptor desc;
+            uint32_t stream;
+            data.read(&param1, sizeof(void *));
+            if (event == AudioSystem::STREAM_CONFIG_CHANGED) {
+                stream = data.readInt32();
+                param2 = &stream;
+                LOGV("STREAM_CONFIG_CHANGED stream %d", stream);
+            } else if (event != AudioSystem::OUTPUT_CLOSED && event != AudioSystem::INPUT_CLOSED) {
+                desc.samplingRate = data.readInt32();
+                desc.format = data.readInt32();
+                desc.channels = data.readInt32();
+                desc.frameCount = data.readInt32();
+                desc.latency = data.readInt32();
+                param2 = &desc;
+            }
+            ioConfigChanged(event, param1, param2);
             return NO_ERROR;
         } break;
         default: