audio flinger: improve device to device audio patches

Allow creation of audio patches between input and output
devices managed by the same audio HW module.

Change-Id: I4b83268a4d5c41f3d5905d7581202cf5193efd32
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index efbdcff..834947f 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -200,26 +200,17 @@
                     status = BAD_VALUE;
                     goto exit;
                 }
-                // limit to connections between devices and input streams for HAL before 3.0
-                if (patch->sinks[i].ext.mix.hw_module == srcModule &&
-                        (audioHwDevice->version() < AUDIO_DEVICE_API_VERSION_3_0) &&
-                        (patch->sinks[i].type != AUDIO_PORT_TYPE_MIX)) {
-                    ALOGW("createAudioPatch() invalid sink type %d for device source",
-                          patch->sinks[i].type);
-                    status = BAD_VALUE;
-                    goto exit;
-                }
             }
 
-            if (patch->sinks[0].ext.device.hw_module != srcModule) {
-                // limit to device to device connection if not on same hw module
-                if (patch->sinks[0].type != AUDIO_PORT_TYPE_DEVICE) {
-                    ALOGW("createAudioPatch() invalid sink type for cross hw module");
-                    status = INVALID_OPERATION;
-                    goto exit;
-                }
-                // special case num sources == 2 -=> reuse an exiting output mix to connect to the
-                // sink
+            // manage patches requiring a software bridge
+            // - Device to device AND
+            //    - source HW module != destination HW module OR
+            //    - audio HAL version < 3.0
+            //    - special patch request with 2 sources (reuse one existing output mix)
+            if ((patch->sinks[0].type == AUDIO_PORT_TYPE_DEVICE) &&
+                    ((patch->sinks[0].ext.device.hw_module != srcModule) ||
+                    (audioHwDevice->version() < AUDIO_DEVICE_API_VERSION_3_0) ||
+                    (patch->num_sources == 2))) {
                 if (patch->num_sources == 2) {
                     if (patch->sources[1].type != AUDIO_PORT_TYPE_MIX ||
                             patch->sinks[0].ext.device.hw_module !=
@@ -304,6 +295,11 @@
                                                                &halHandle);
                     }
                 } else {
+                    if (patch->sinks[0].type != AUDIO_PORT_TYPE_MIX) {
+                        status = INVALID_OPERATION;
+                        goto exit;
+                    }
+
                     sp<ThreadBase> thread = audioflinger->checkRecordThread_l(
                                                                     patch->sinks[0].ext.mix.handle);
                     if (thread == 0) {
@@ -472,6 +468,7 @@
     // this track is given the same buffer as the PatchRecord buffer
     patch->mPatchTrack = new PlaybackThread::PatchTrack(
                                            patch->mPlaybackThread.get(),
+                                           audioPatch->sources[1].ext.mix.usecase.stream,
                                            sampleRate,
                                            outChannelMask,
                                            format,
@@ -578,8 +575,8 @@
                 break;
             }
 
-            if (patch->sinks[0].type == AUDIO_PORT_TYPE_DEVICE &&
-                    patch->sinks[0].ext.device.hw_module != srcModule) {
+            if (removedPatch->mRecordPatchHandle != AUDIO_PATCH_HANDLE_NONE ||
+                    removedPatch->mPlaybackPatchHandle != AUDIO_PATCH_HANDLE_NONE) {
                 clearPatchConnections(removedPatch);
                 break;
             }
@@ -693,5 +690,4 @@
     return NO_ERROR;
 }
 
-
 } // namespace android