audio: hal: Add Hal extension for transcode loopback usecase

Adding HAL extension for transcode hw loopback
Userspace qahwi APIs introduced to exercise this extension

Change-Id: Iffae3f6936c2519f0c5349c2430eb598b97c3364
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 3d3a5d7..6375ec5 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -263,6 +263,8 @@
     [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
     [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
     [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = "silence-playback",
+    /* Transcode loopback cases */
+    [USECASE_AUDIO_TRANSCODE_LOOPBACK] = "audio-transcode-loopback",
 };
 
 static const audio_usecase_t offload_usecases[] = {
@@ -989,12 +991,22 @@
                                                struct audio_usecase *new_uc,
                                                snd_device_t new_snd_device)
 {
-    audio_devices_t a1 = uc->stream.out->devices;
-    audio_devices_t a2 = new_uc->stream.out->devices;
+    audio_devices_t a1, a2;
 
     snd_device_t d1 = uc->out_snd_device;
     snd_device_t d2 = new_snd_device;
 
+    switch (uc->type) {
+        case TRANSCODE_LOOPBACK :
+            a1 = uc->stream.inout->out_config.devices;
+            a2 = new_uc->stream.inout->out_config.devices;
+            break;
+        default :
+            a1 = uc->stream.out->devices;
+            a2 = new_uc->stream.out->devices;
+            break;
+    }
+
     // Treat as a special case when a1 and a2 are not disjoint
     if ((a1 != a2) && (a1 & a2)) {
         snd_device_t d3[2];
@@ -1554,6 +1566,14 @@
                                                         usecase->stream.out);
         in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
         usecase->devices = usecase->stream.out->devices;
+    } else if (usecase->type == TRANSCODE_LOOPBACK ) {
+        if (usecase->stream.inout == NULL) {
+            ALOGE("%s: stream.inout is NULL", __func__);
+            return -EINVAL;
+        }
+        out_snd_device = usecase->stream.inout->out_config.devices;
+        in_snd_device = usecase->stream.inout->in_config.devices;
+        usecase->devices = (out_snd_device | in_snd_device);
     } else {
         /*
          * If the voice call is active, use the sound devices of voice call usecase
@@ -5353,6 +5373,41 @@
     return;
 }
 
+int adev_create_audio_patch(struct audio_hw_device *dev,
+                            unsigned int num_sources,
+                            const struct audio_port_config *sources,
+                            unsigned int num_sinks,
+                            const struct audio_port_config *sinks,
+                            audio_patch_handle_t *handle)
+{
+
+
+     return audio_extn_hw_loopback_create_audio_patch(dev,
+                                         num_sources,
+                                         sources,
+                                         num_sinks,
+                                         sinks,
+                                         handle);
+
+}
+
+int adev_release_audio_patch(struct audio_hw_device *dev,
+                           audio_patch_handle_t handle)
+{
+    return audio_extn_hw_loopback_release_audio_patch(dev, handle);
+}
+
+int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
+{
+    return audio_extn_hw_loopback_get_audio_port(dev, config);
+}
+
+int adev_set_audio_port_config(struct audio_hw_device *dev,
+                        const struct audio_port_config *config)
+{
+    return audio_extn_hw_loopback_set_audio_port_config(dev, config);
+}
+
 static int adev_dump(const audio_hw_device_t *device __unused,
                      int fd __unused)
 {
@@ -5386,6 +5441,7 @@
         qahwi_deinit(device);
         audio_extn_adsp_hdlr_deinit();
         audio_extn_snd_mon_deinit();
+        audio_extn_loopback_deinit(adev);
         free(device);
         adev = NULL;
     }
@@ -5498,6 +5554,10 @@
     adev->device.close_output_stream = adev_close_output_stream;
     adev->device.open_input_stream = adev_open_input_stream;
     adev->device.close_input_stream = adev_close_input_stream;
+    adev->device.create_audio_patch = adev_create_audio_patch;
+    adev->device.release_audio_patch = adev_release_audio_patch;
+    adev->device.get_audio_port = adev_get_audio_port;
+    adev->device.set_audio_port_config = adev_set_audio_port_config;
     adev->device.dump = adev_dump;
 
     /* Set the default route before the PCM stream is opened */
@@ -5564,6 +5624,7 @@
     audio_extn_init(adev);
     audio_extn_listen_init(adev, adev->snd_card);
     audio_extn_gef_init(adev);
+    audio_extn_loopback_init(adev);
 
     if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
         adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);