Merge "hal: add support for configuring render window"
diff --git a/hal/audio_extn/audio_defs.h b/hal/audio_extn/audio_defs.h
index 0e1848e..a0b1949 100644
--- a/hal/audio_extn/audio_defs.h
+++ b/hal/audio_extn/audio_defs.h
@@ -306,4 +306,12 @@
     AUDIO_EXTN_PARAM_LICENSE_PARAMS,
 } audio_extn_param_id;
 
+typedef union {
+    struct audio_out_render_window_param render_window_params;
+} audio_extn_loopback_param_payload;
+
+typedef enum {
+    AUDIO_EXTN_PARAM_LOOPBACK_RENDER_WINDOW /* PARAM to set render window */
+} audio_extn_loopback_param_id;
+
 #endif /* AUDIO_DEFS_H */
diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c
index c6c0924..3eee428 100755
--- a/hal/audio_extn/audio_extn.c
+++ b/hal/audio_extn/audio_extn.c
@@ -1478,6 +1478,33 @@
     return ret;
 }
 
+#ifdef AUDIO_HW_LOOPBACK_ENABLED
+int audio_extn_hw_loopback_set_param_data(audio_patch_handle_t handle,
+                                          audio_extn_loopback_param_id param_id,
+                                          audio_extn_loopback_param_payload *payload) {
+    int ret = -EINVAL;
+
+    if (!payload) {
+        ALOGE("%s:: Invalid Param",__func__);
+        return ret;
+    }
+
+    ALOGD("%d: %s: param id is %d\n", __LINE__, __func__, param_id);
+
+    switch(param_id) {
+        case AUDIO_EXTN_PARAM_LOOPBACK_RENDER_WINDOW:
+            ret = audio_extn_hw_loopback_set_render_window(handle, payload);
+            break;
+        default:
+            ALOGE("%s: unsupported param id %d", __func__, param_id);
+            break;
+    }
+
+    return ret;
+}
+#endif
+
+
 /* API to get playback stream specific config parameters */
 int audio_extn_out_get_param_data(struct stream_out *out,
                              audio_extn_param_id param_id,
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 6ec07b3..e158b0a 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -999,6 +999,14 @@
                                     const struct audio_port_config *config);
 int audio_extn_hw_loopback_get_audio_port(struct audio_hw_device *dev,
                                     struct audio_port *port_in);
+
+int audio_extn_hw_loopback_set_param_data(audio_patch_handle_t handle,
+                                          audio_extn_loopback_param_id param_id,
+                                          audio_extn_loopback_param_payload *payload);
+
+int audio_extn_hw_loopback_set_render_window(audio_patch_handle_t handle,
+                                             struct audio_out_render_window_param *render_window);
+
 int audio_extn_hw_loopback_init(struct audio_device *adev);
 void audio_extn_hw_loopback_deinit(struct audio_device *adev);
 #else
@@ -1026,6 +1034,18 @@
 {
     return -ENOSYS;
 }
+static int __unused audio_extn_hw_loopback_set_param_data(audio_patch_handle_t handle __unused,
+                                               audio_extn_loopback_param_id param_id __unused,
+                                               audio_extn_loopback_param_payload *payload __unused)
+{
+    return -ENOSYS;
+}
+
+static int __unused audio_extn_hw_loopback_set_render_window(audio_patch_handle_t handle __unused,
+                                     struct audio_out_render_window_param *render_window __unused)
+{
+    return -ENOSYS;
+}
 static int __unused audio_extn_hw_loopback_init(struct audio_device *adev __unused)
 {
     return -ENOSYS;
diff --git a/hal/audio_extn/hw_loopback.c b/hal/audio_extn/hw_loopback.c
index 990a283..7516717 100644
--- a/hal/audio_extn/hw_loopback.c
+++ b/hal/audio_extn/hw_loopback.c
@@ -357,6 +357,78 @@
     return 0;
 }
 
+#ifdef SNDRV_COMPRESS_RENDER_WINDOW
+static loopback_patch_t *get_active_loopback_patch(audio_patch_handle_t handle)
+{
+    int n = 0;
+    int patch_index = -1;
+    loopback_patch_t *active_loopback_patch = NULL;
+
+    for (n=0; n < MAX_NUM_PATCHES; n++) {
+        if (audio_loopback_mod->patch_db.num_patches > 0) {
+            if (audio_loopback_mod->patch_db.loopback_patch[n].patch_handle_id == handle) {
+                patch_index = n;
+                break;
+            }
+        } else {
+            ALOGE("%s, No active audio loopback patch", __func__);
+            return active_loopback_patch;
+        }
+    }
+
+    if ((patch_index > -1) && (patch_index < MAX_NUM_PATCHES))
+        active_loopback_patch = &(audio_loopback_mod->patch_db.loopback_patch[
+                                patch_index]);
+    else
+        ALOGE("%s, Requested Patch handle does not exist", __func__);
+
+    return active_loopback_patch;
+}
+
+int audio_extn_hw_loopback_set_render_window(audio_patch_handle_t handle,
+                      struct audio_out_render_window_param *render_window)
+{
+    struct snd_compr_metadata metadata = {0};
+    int ret = 0;
+    loopback_patch_t *active_loopback_patch = get_active_loopback_patch(handle);
+
+    if (active_loopback_patch == NULL) {
+        ALOGE("%s: Invalid patch handle", __func__);
+        ret = -EINVAL;
+        goto exit;
+    }
+
+    if (render_window == NULL) {
+        ALOGE("%s: Invalid render_window", __func__);
+        ret = -EINVAL;
+        goto exit;
+    }
+
+    metadata.key = SNDRV_COMPRESS_RENDER_WINDOW;
+    /*render window start value */
+    metadata.value[0] = 0xFFFFFFFF & render_window->render_ws; /* lsb */
+    metadata.value[1] = \
+            (0xFFFFFFFF00000000 & render_window->render_ws) >> 32; /* msb*/
+    /*render window end value */
+    metadata.value[2] = 0xFFFFFFFF & render_window->render_we; /* lsb */
+    metadata.value[3] = \
+            (0xFFFFFFFF00000000 & render_window->render_we) >> 32; /* msb*/
+
+    ret = compress_set_metadata(active_loopback_patch->sink_stream, &metadata);
+
+exit:
+    return ret;
+}
+#else
+int audio_extn_hw_loopback_set_render_window(struct audio_hw_device *dev,
+                      audio_patch_handle_t handle __unused,
+                      struct audio_out_render_window_param *render_window __unused)
+{
+    ALOGD("%s:: configuring render window not supported", __func__);
+    return 0;
+}
+#endif
+
 #if defined SNDRV_COMPRESS_LATENCY_MODE
 static void transcode_loopback_util_set_latency_mode(
                              loopback_patch_t *active_loopback_patch,
diff --git a/hal/audio_hw_extn_api.c b/hal/audio_hw_extn_api.c
index f5e0659..310b537 100644
--- a/hal/audio_hw_extn_api.c
+++ b/hal/audio_hw_extn_api.c
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2016-2017, 2018, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -423,6 +423,19 @@
     return ret;
 }
 
+int qahwi_loopback_set_param_data(audio_patch_handle_t handle,
+                                  audio_extn_loopback_param_id param_id,
+                                  void *payload) {
+    int ret = 0;
+
+    ret = audio_extn_hw_loopback_set_param_data(
+                                             handle,
+                                             param_id,
+                                             (audio_extn_loopback_param_payload *)payload);
+
+    return ret;
+}
+
 void qahwi_init(hw_device_t *device)
 {
     struct audio_device *adev = (struct audio_device *) device;
diff --git a/qahw/inc/qahw.h b/qahw/inc/qahw.h
index e91fd00..dd5b403 100644
--- a/qahw/inc/qahw.h
+++ b/qahw/inc/qahw.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
  * Not a Contribution.
  *
  * Copyright (C) 2011 The Android Open Source Project *
@@ -463,6 +463,13 @@
 /* Release an audio patch */
 int qahw_release_audio_patch_l(qahw_module_handle_t *hw_module,
                         audio_patch_handle_t handle);
+
+/* API to set loopback stream specific config parameters. */
+int qahw_loopback_set_param_data_l(qahw_module_handle_t *hw_module,
+                                   audio_patch_handle_t handle,
+                                   qahw_loopback_param_id param_id,
+                                   qahw_loopback_param_payload *payload);
+
 /* Fills the list of supported attributes for a given audio port.
  * As input, "port" contains the information (type, role, address etc...)
  * needed by the HAL to identify the port.
diff --git a/qahw/inc/qahw_defs.h b/qahw/inc/qahw_defs.h
index 4e7faff..755553b 100644
--- a/qahw/inc/qahw_defs.h
+++ b/qahw/inc/qahw_defs.h
@@ -417,6 +417,14 @@
     QAHW_PARAM_LICENSE_PARAMS,
 } qahw_param_id;
 
+typedef union {
+    struct qahw_out_render_window_param render_window_params;
+} qahw_loopback_param_payload;
+
+typedef enum {
+    QAHW_PARAM_LOOPBACK_RENDER_WINDOW /* PARAM to set render window */
+} qahw_loopback_param_id;
+
 __END_DECLS
 
 #endif  // QTI_AUDIO_HAL_DEFS_H
diff --git a/qahw/src/qahw.c b/qahw/src/qahw.c
index 0c00158..126f794 100644
--- a/qahw/src/qahw.c
+++ b/qahw/src/qahw.c
@@ -69,6 +69,10 @@
                                       qahw_param_id param_id,
                                       qahw_param_payload *payload);
 
+typedef int (*qahwi_loopback_set_param_data_t)(audio_patch_handle_t patch_handle,
+                                               qahw_param_id param_id,
+                                               qahw_param_payload *payload);
+
 typedef struct {
     audio_hw_device_t *audio_device;
     char module_name[MAX_MODULE_NAME_LENGTH];
@@ -80,6 +84,7 @@
     const hw_module_t* module;
     qahwi_get_param_data_t qahwi_get_param_data;
     qahwi_set_param_data_t qahwi_set_param_data;
+    qahwi_loopback_set_param_data_t qahwi_loopback_set_param_data;
 } qahw_module_t;
 
 typedef struct {
@@ -1438,6 +1443,34 @@
      return ret;
 }
 
+int qahw_loopback_set_param_data_l(qahw_module_handle_t *hw_module,
+                                   audio_patch_handle_t handle,
+                                   qahw_loopback_param_id param_id,
+                                   qahw_loopback_param_payload *payload)
+
+{
+    int ret = -EINVAL;
+    qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
+
+    if (!payload) {
+        ALOGE("%s:: invalid param", __func__);
+        goto exit;
+    }
+
+    if (qahw_module->qahwi_loopback_set_param_data) {
+        ret = qahw_module->qahwi_loopback_set_param_data(handle,
+                                                         param_id,
+                                                         (void *)payload);
+    } else {
+        ret = -ENOSYS;
+        ALOGE("%s not supported\n", __func__);
+    }
+
+exit:
+    return ret;
+
+}
+
 /* Fills the list of supported attributes for a given audio port.
  * As input, "port" contains the information (type, role, address etc...)
  * needed by the HAL to identify the port.
@@ -1889,6 +1922,12 @@
     if (!qahw_module->qahwi_set_param_data)
          ALOGD("%s::qahwi_set_param_data api is not defined\n",__func__);
 
+    qahw_module->qahwi_loopback_set_param_data = (qahwi_loopback_set_param_data_t)
+                                                  dlsym(module->dso,
+                                                  "qahwi_loopback_set_param_data");
+    if (!qahw_module->qahwi_loopback_set_param_data)
+         ALOGD("%s::qahwi_loopback_set_param_data api is not defined\n", __func__);
+
     if (!qahw_list_count)
         list_init(&qahw_module_list);
     qahw_list_count++;
diff --git a/qahw_api/inc/qahw_api.h b/qahw_api/inc/qahw_api.h
index 0aa3c79..823c6bb 100644
--- a/qahw_api/inc/qahw_api.h
+++ b/qahw_api/inc/qahw_api.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
  * Not a Contribution.
  *
  * Copyright (C) 2011 The Android Open Source Project *
@@ -459,6 +459,13 @@
 /* Release an audio patch */
 int qahw_release_audio_patch(qahw_module_handle_t *hw_module,
                         audio_patch_handle_t handle);
+
+/* API to set loopback stream specific config parameters */
+int qahw_loopback_set_param_data(qahw_module_handle_t *hw_module,
+                                 audio_patch_handle_t handle,
+                                 qahw_loopback_param_id param_id,
+                                 qahw_loopback_param_payload *payload);
+
 /* Fills the list of supported attributes for a given audio port.
  * As input, "port" contains the information (type, role, address etc...)
  * needed by the HAL to identify the port.
diff --git a/qahw_api/inc/qahw_defs.h b/qahw_api/inc/qahw_defs.h
index c6d42ca..7c01c57 100644
--- a/qahw_api/inc/qahw_defs.h
+++ b/qahw_api/inc/qahw_defs.h
@@ -399,6 +399,15 @@
     QAHW_PARAM_LICENSE_PARAMS,
 } qahw_param_id;
 
+
+typedef union {
+    struct qahw_out_render_window_param render_window_params;
+} qahw_loopback_param_payload;
+
+typedef enum {
+    QAHW_PARAM_LOOPBACK_RENDER_WINDOW /* PARAM to set render window */
+} qahw_loopback_param_id;
+
 __END_DECLS
 
 #endif  // QTI_AUDIO_HAL_DEFS_H
diff --git a/qahw_api/src/qahw_api.cpp b/qahw_api/src/qahw_api.cpp
index cbd9041..f1c75f4 100644
--- a/qahw_api/src/qahw_api.cpp
+++ b/qahw_api/src/qahw_api.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -915,6 +915,15 @@
     }
 }
 
+int qahw_loopback_set_param_data(qahw_module_handle_t *hw_module __unused,
+                                 audio_patch_handle_t handle __unused,
+                                 qahw_loopback_param_id param_id __unused,
+                                 qahw_loopback_param_payload *payload __unused)
+{
+    ALOGD("%d:%s", __LINE__, __func__);
+    return -ENOSYS;
+}
+
 int qahw_get_audio_port(qahw_module_handle_t *hw_module,
                       struct audio_port *port)
 {
@@ -1699,6 +1708,15 @@
     return qahw_release_audio_patch_l(hw_module, handle);
 }
 
+int qahw_loopback_set_param_data(qahw_module_handle_t *hw_module,
+                                 audio_patch_handle_t handle,
+                                 qahw_loopback_param_id param_id,
+                                 qahw_loopback_param_payload *payload)
+{
+    ALOGV("%d:%s\n", __LINE__, __func__);
+    return qahw_loopback_set_param_data_l(hw_module, handle, param_id, payload);
+}
+
 int qahw_get_audio_port(qahw_module_handle_t *hw_module,
                       struct audio_port *port)
 {