Merge "agm: change retry time interval for ats_init"
diff --git a/ipc/HwBinders/agm_ipc_service/src/agm_server_wrapper.cpp b/ipc/HwBinders/agm_ipc_service/src/agm_server_wrapper.cpp
index f05167e..0875084 100644
--- a/ipc/HwBinders/agm_ipc_service/src/agm_server_wrapper.cpp
+++ b/ipc/HwBinders/agm_ipc_service/src/agm_server_wrapper.cpp
@@ -278,9 +278,9 @@
                                hndle->shared_mem_fd_list.size());
                          if (hndle->shared_mem_fd_list[i].second == rw_done_payload->buff.alloc_info.alloc_handle) {
                              input_fd = hndle->shared_mem_fd_list[i].first;
-                          /*   it = (hndle->shared_mem_fd_list.begin() + i);
+                             it = (hndle->shared_mem_fd_list.begin() + i);
                              if (it != hndle->shared_mem_fd_list.end())
-                                 hndle->shared_mem_fd_list.erase(it);*/
+                                 hndle->shared_mem_fd_list.erase(it);
                              ALOGV("input fd %d  payload fd %d\n", input_fd,
                                    rw_done_payload->buff.alloc_info.alloc_handle);
                              break;
@@ -336,7 +336,7 @@
         // allocated during read_with_metadata()
         if (rw_done_payload->buff.metadata)
             free(rw_done_payload->buff.metadata);
-        //close(rw_done_payload->buff.alloc_info.alloc_handle);
+        close(rw_done_payload->buff.alloc_info.alloc_handle);
     } else {
         evt_param_l.resize(sizeof(struct agm_event_cb_params) +
                                 evt_param->event_payload_size);
diff --git a/plugins/tinyalsa/test/agmmixer.c b/plugins/tinyalsa/test/agmmixer.c
index 9b8db08..7f53996 100644
--- a/plugins/tinyalsa/test/agmmixer.c
+++ b/plugins/tinyalsa/test/agmmixer.c
@@ -46,6 +46,11 @@
 #define PARAM_ID_DETECTION_ENGINE_GENERIC_EVENT_CFG 0x0800104E
 #define PARAM_ID_MFC_OUTPUT_MEDIA_FORMAT            0x08001024
 
+enum {
+    DEVICE = 1,
+    GROUP,
+};
+
 enum pcm_channel_map
 {
    PCM_CHANNEL_L = 1,
@@ -154,6 +159,47 @@
     config->bits = atoi(attr[7]);
 }
 
+void start_group_tag(void *userdata, const XML_Char *tag_name, const XML_Char **attr)
+{
+    struct group_config *config = (struct group_config *)userdata;
+
+    if (strncmp(tag_name, "group_device", strlen("group_device")) != 0)
+        return;
+
+    if (strcmp(attr[0], "name") != 0) {
+        printf("name not found\n");
+        return;
+    }
+
+    if (strcmp(attr[2], "rate") != 0) {
+        printf("rate not found\n");
+        return;
+    }
+
+    if (strcmp(attr[4], "ch") != 0) {
+        printf("channels not found\n");
+        return;
+    }
+
+    if (strcmp(attr[6], "bits") != 0) {
+        printf("bits not found");
+        return;
+    }
+
+    if (strcmp(attr[8], "slot_mask") != 0) {
+        printf("slot_mask not found");
+        return;
+    }
+
+    if (strncmp(config->name, attr[1], sizeof(config->name)))
+        return;
+
+    config->rate = atoi(attr[3]);
+    config->ch = atoi(attr[5]);
+    config->bits = atoi(attr[7]);
+    config->slot_mask = atoi(attr[9]);
+}
+
 int convert_char_to_hex(char *char_num)
 {
     uint64_t hex_num = 0;
@@ -174,13 +220,15 @@
     return (int32_t) hex_num;
 }
 
-int get_device_media_config(char* filename, char *intf_name, struct device_config *config)
+static int get_backend_info(char* filename, char *intf_name, void *config, int type)
 {
     FILE *file = NULL;
     XML_Parser parser;
     int ret = 0;
     int bytes_read;
     void *buf = NULL;
+    struct device_config *dev_cfg;
+    struct group_config *grp_cfg;
 
     file = fopen(filename, "r");
     if (!file) {
@@ -195,11 +243,17 @@
         printf("Failed to create XML ret %d", ret);
         goto closeFile;
     }
-    memset(config, 0, sizeof(*config));
-    strlcpy(config->name, intf_name, sizeof(config->name));
+    if (type == DEVICE) {
+        dev_cfg = (struct device_config *)config;
+        strlcpy(dev_cfg->name, intf_name, sizeof(dev_cfg->name));
+        XML_SetElementHandler(parser, start_tag, NULL);
+    } else {
+        grp_cfg = (struct group_config *)config;
+        strlcpy(grp_cfg->name, intf_name, sizeof(grp_cfg->name));
+        XML_SetElementHandler(parser, start_group_tag, NULL);
+    }
 
     XML_SetUserData(parser, config);
-    XML_SetElementHandler(parser, start_tag, NULL);
 
     while (1) {
         buf = XML_GetBuffer(parser, 1024);
@@ -221,11 +275,11 @@
             printf("XML ParseBuffer failed for %s file ret %d", filename, ret);
             goto freeParser;
         }
-        if (bytes_read == 0 || config->rate != 0)
+        if (bytes_read == 0 || ((struct device_config *)config)->rate != 0)
             break;
     }
 
-    if (config->rate == 0) {
+    if (((struct device_config *)config)->rate == 0) {
         ret = -EINVAL;
         printf("Entry not found\n");
     }
@@ -237,6 +291,112 @@
     return ret;
 }
 
+int get_device_media_config(char* filename, char *intf_name, struct device_config *config)
+{
+    return get_backend_info(filename, intf_name, (void *)config, DEVICE);
+}
+
+int get_group_device_info(char* filename, char *intf_name, struct group_config *config)
+{
+    char *be_name = strdup(intf_name);
+    if (be_name == NULL) {
+        printf("%s(): Insufficient memory to create be_name \n", __func__);
+        return -ENOMEM;
+    }
+    int be_len = strlen(intf_name) - 7;
+
+    be_name[be_len] = '\0';
+    return get_backend_info(filename, be_name, (void *)config, GROUP);
+}
+
+int set_agm_group_device_config(struct mixer *mixer, unsigned int device, struct group_config *config, char *intf_name)
+{
+    char *stream = "PCM";
+    char *grp_ctl = "grp config";
+    char *control = "setParamTag";
+    char *mixer_str = NULL;
+    struct mixer_ctl *ctl;
+    long grp_config[5];
+    int ctl_len = 0, be_len, val_len;
+    int ret = 0;
+    struct agm_tag_config* tag_config = NULL;
+    char *be_name = strdup(intf_name);
+    if (be_name == NULL) {
+        printf("%s(): Insufficient memory to create be_name \n", __func__);
+        ret = -ENOMEM;
+        goto done;
+    }
+
+    be_len = strlen(intf_name) - 7;
+    be_name[be_len] = '\0';
+
+    ctl_len = strlen(be_name) + 1 + strlen(grp_ctl) + 1;
+    mixer_str = calloc(1, ctl_len);
+    if (!mixer_str) {
+        printf("mixer_str calloc failed\n");
+        ret = -ENOMEM;
+        goto done;
+    }
+    snprintf(mixer_str, ctl_len, "%s %s", be_name, grp_ctl);
+    ctl = mixer_get_ctl_by_name(mixer, mixer_str);
+    if (!ctl) {
+        printf("Invalid mixer control: %s\n", mixer_str);
+        ret = ENOENT;
+        goto done;
+    }
+
+    grp_config[0] = config->rate;
+    grp_config[1] = config->ch;
+    grp_config[2] = bits_to_alsa_format(config->bits);
+    grp_config[3] = AGM_DATA_FORMAT_FIXED_POINT;
+    grp_config[4] = config->slot_mask;
+
+    ret = mixer_ctl_set_array(ctl, &grp_config, sizeof(grp_config)/sizeof(grp_config[0]));
+    if (ret) {
+        printf("Failed to set grp config mixer ctl\n");
+        goto done;
+    }
+
+    /* Configure MUX MODULE TKV */
+    ret = set_agm_stream_metadata_type(mixer, device, intf_name, STREAM_PCM);
+    if (ret) {
+        ret = 0;
+        goto done;
+    }
+    ctl_len = strlen(stream) + 4 + strlen(control) + 1;
+    mixer_str = realloc(mixer_str, ctl_len);
+    if (!mixer_str) {
+        printf("mixer_str realloc failed\n");
+        goto done;
+    }
+
+    val_len = sizeof(struct agm_tag_config) + sizeof(struct agm_key_value);
+
+    tag_config = (struct agm_tag_config*)calloc(1, val_len);
+    if (!tag_config)
+        goto done;
+
+    snprintf(mixer_str, ctl_len, "%s%d %s", stream, device, control);
+    ctl = mixer_get_ctl_by_name(mixer, mixer_str);
+    if (!ctl) {
+        printf("Invalid mixer control: %s\n", mixer_str);
+        goto done;
+    }
+    tag_config->tag = TAG_DEVICE_MUX;
+    tag_config->num_tkvs = 1;
+    tag_config->kv[0].key = TAG_KEY_SLOT_MASK;
+    tag_config->kv[0].value = config->slot_mask;
+
+    mixer_ctl_set_array(ctl, tag_config, val_len);
+done:
+    if (be_name)
+        free(be_name);
+
+    if (mixer_str)
+        free(mixer_str);
+    return ret;
+}
+
 int set_agm_device_media_config(struct mixer *mixer, unsigned int channels,
                                 unsigned int rate, unsigned int bits, char *intf_name)
 {
diff --git a/plugins/tinyalsa/test/agmmixer.h b/plugins/tinyalsa/test/agmmixer.h
index 984373b..b3e4792 100644
--- a/plugins/tinyalsa/test/agmmixer.h
+++ b/plugins/tinyalsa/test/agmmixer.h
@@ -52,9 +52,18 @@
     unsigned int bits;
 };
 
+struct group_config {
+    char name[80];
+    unsigned int rate;
+    unsigned int ch;
+    unsigned int bits;
+    unsigned int slot_mask;
+};
+
 int convert_char_to_hex(char *char_num);
 int set_agm_device_media_config(struct mixer *mixer, unsigned int channels,
                                 unsigned int rate, unsigned int bits, char *intf_name);
+int set_agm_group_device_config(struct mixer *mixer, unsigned int device, struct group_config *config, char *intf_name);
 int connect_play_pcm_to_cap_pcm(struct mixer *mixer, unsigned int p_device, unsigned int c_device);
 int set_agm_audio_intf_metadata(struct mixer *mixer, char *intf_name, unsigned int dkv, enum usecase_type, int rate, int bitwidth, uint32_t val);
 int set_agm_stream_metadata_type(struct mixer *mixer, int device, char *val, enum stream_type stype);
@@ -72,6 +81,7 @@
 int agm_mixer_get_event_param(struct mixer *mixer, int device, enum stream_type stype,uint32_t miid);
 int agm_mixer_get_buf_tstamp(struct mixer *mixer, int device, enum stream_type stype, uint64_t *tstamp);
 int get_device_media_config(char* filename, char *intf_name, struct device_config *config);
+int get_group_device_info(char* filename, char *intf_name, struct group_config *config);
 int configure_mfc(struct mixer *mixer, int device, char *intf_name, int tag, enum stream_type stype, unsigned int rate,
                        unsigned int channels, unsigned int bits);
 #endif
diff --git a/plugins/tinyalsa/test/agmplay.c b/plugins/tinyalsa/test/agmplay.c
index 0172f3d..ca54d53 100644
--- a/plugins/tinyalsa/test/agmplay.c
+++ b/plugins/tinyalsa/test/agmplay.c
@@ -84,7 +84,7 @@
     struct chunk_fmt chunk_fmt;
     unsigned int card = 100, device = 100;
     unsigned int device_kv = 0;
-    bool haptics;
+    bool haptics = false;
     char *intf_name = NULL;
     struct device_config config;
     char *filename;
@@ -187,6 +187,7 @@
     int size;
     int num_read;
     char *name = dev_config->name;
+    struct group_config grp_config;
 
     memset(&config, 0, sizeof(config));
     config.channels = fmt.num_channels;
@@ -217,6 +218,7 @@
         printf("Failed to set device media config\n");
         goto err_close_mixer;
     }
+
     if (haptics) {
         playback_path = HAPTICS;
         playback_value = HAPTICS_PLAYBACK;
@@ -258,6 +260,16 @@
         goto err_close_mixer;
     }
 
+    if (strstr(name, "VIRT-")) {
+        if (get_group_device_info(BACKEND_CONF_FILE, name, &grp_config))
+            goto err_close_mixer;
+
+        if (set_agm_group_device_config(mixer, device, &grp_config, name)) {
+            printf("Failed to set grp device config\n");
+            goto err_close_mixer;
+        }
+    }
+
     size = pcm_frames_to_bytes(pcm, pcm_get_buffer_size(pcm));
     buffer = malloc(size);
     if (!buffer) {
diff --git a/plugins/tinyalsa/test/backend_conf.xml b/plugins/tinyalsa/test/backend_conf.xml
old mode 100755
new mode 100644
index 7467cec..1e342d3
--- a/plugins/tinyalsa/test/backend_conf.xml
+++ b/plugins/tinyalsa/test/backend_conf.xml
@@ -26,6 +26,8 @@
 <!-- OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN    -->
 <!-- IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                             -->
 <config>
+    <group_device name="TDM-LPAIF-RX-TERTIARY" rate="96000" ch="3" bits="16" slot_mask="7"/>
+    <device name="TDM-LPAIF-RX-TERTIARY-VIRT-0" rate="96000" ch="2" bits="16" />
     <device name="CODEC_DMA-LPAIF_WSA-RX-0" rate="48000" ch="1" bits="16" />
     <device name="CODEC_DMA-LPAIF_WSA-RX-1" rate="48000" ch="1" bits="16" />
     <device name="CODEC_DMA-LPAIF_RXTX-RX-0" rate="48000" ch="1" bits="16" />