Merge fc852cd9fdcdc2fbac6da7eba4cadbc9615fd653 on remote branch

Change-Id: Ib5cb67b5dbf4463b425f8aa3d20455a42080d47a
diff --git a/ipc/HwBinders/agm_ipc_client/src/agm_client_wrapper.cpp b/ipc/HwBinders/agm_ipc_client/src/agm_client_wrapper.cpp
index 9b2d1d0..49860a0 100644
--- a/ipc/HwBinders/agm_ipc_client/src/agm_client_wrapper.cpp
+++ b/ipc/HwBinders/agm_ipc_client/src/agm_client_wrapper.cpp
@@ -314,6 +314,16 @@
     return -EINVAL;
 }
 
+int agm_sessionid_flush(uint32_t session_id)
+{
+    ALOGV("%s called with session id = %d", __func__, session_id);
+    if (!agm_server_died) {
+        android::sp<IAGM> agm_client = get_agm_server();
+        return agm_client->ipc_agm_sessionid_flush(session_id);
+    }
+    return -EINVAL;
+}
+
 int agm_session_resume(uint64_t handle){
     ALOGV("%s called with handle = %llx \n", __func__, (unsigned long long) handle);
     if (!agm_server_died) {
diff --git a/ipc/HwBinders/agm_ipc_service/inc/agm_server_wrapper.h b/ipc/HwBinders/agm_ipc_service/inc/agm_server_wrapper.h
index 9ad0a2d..4c31633 100644
--- a/ipc/HwBinders/agm_ipc_service/inc/agm_server_wrapper.h
+++ b/ipc/HwBinders/agm_ipc_service/inc/agm_server_wrapper.h
@@ -200,6 +200,7 @@
     Return<int32_t> ipc_agm_session_stop(uint64_t hndl) override;
     Return<int32_t> ipc_agm_session_pause(uint64_t hndl) override;
     Return<int32_t> ipc_agm_session_flush(uint64_t hndl) override;
+    Return<int32_t> ipc_agm_sessionid_flush(uint32_t session_id) override;
     Return<int32_t> ipc_agm_session_resume(uint64_t hndl) override;
     Return<int32_t> ipc_agm_session_suspend(uint64_t hndl) override;
     Return<void> ipc_agm_session_read(uint64_t hndl, uint32_t count,
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 b8dd8c7..ccf047e 100644
--- a/ipc/HwBinders/agm_ipc_service/src/agm_server_wrapper.cpp
+++ b/ipc/HwBinders/agm_ipc_service/src/agm_server_wrapper.cpp
@@ -541,6 +541,10 @@
     ALOGV("%s called with aif_id = %d, size = %d\n", __func__, aif_id, size);
     uint8_t * metadata_l = NULL;
     int32_t ret = 0;
+
+    if (metadata.size() < size) {
+        return -EINVAL;
+    }
     metadata_l = (uint8_t *) calloc(1,size);
     if (metadata_l == NULL) {
         ALOGE("%s: Cannot allocate memory for metadata_l\n", __func__);
@@ -558,6 +562,11 @@
     ALOGV("%s : session_id = %d, size = %d\n", __func__, session_id, size);
     uint8_t * metadata_l = NULL;
     int32_t ret = 0;
+
+    if (metadata.size() < size) {
+        return -EINVAL;
+    }
+
     metadata_l = (uint8_t *) calloc(1,size);
     if (metadata_l == NULL) {
         ALOGE("%s: Cannot allocate memory for metadata_l\n", __func__);
@@ -581,6 +590,11 @@
                                                       session_id, aif_id, size);
     uint8_t * metadata_l = NULL;
     int32_t ret = 0;
+
+    if (metadata.size() < size) {
+        return -EINVAL;
+    }
+
     metadata_l = (uint8_t *) calloc(1,size);
     if (metadata_l == NULL) {
         ALOGE("%s: Cannot allocate memory for metadata_l\n", __func__);
@@ -652,6 +666,11 @@
     int32_t ret = 0;
     hidl_vec<uint8_t> payload_hidl;
 
+     if (buff.size() < size) {
+        _hidl_cb(-EINVAL, size);
+        return Void();
+    }
+
     payload_local = (uint8_t *) calloc (1, size);
     if (payload_local == NULL) {
         ALOGE("%s: Cannot allocate memory for payload_local\n", __func__);
@@ -707,6 +726,11 @@
     int32_t ret = 0;
 
     ALOGV("%s : aif_id =%d, size = %d\n", __func__, aif_id, size);
+
+    if (payload.size() < size) {
+        return -EINVAL;
+    }
+
     payload_local = (void*) calloc (1,size);
     if (payload_local == NULL) {
         ALOGE("%s: calloc failed for payload_local\n", __func__);
@@ -727,6 +751,11 @@
     size_t size_local = (size_t) size;
     void * payload_local = NULL;
     int32_t ret = 0;
+
+    if (payload.size() < size) {
+        return -EINVAL;
+    }
+
     payload_local = (void*) calloc (1,size);
     if (payload_local == NULL) {
         ALOGE("%s: Cannot allocate memory for payload_local\n", __func__);
@@ -778,6 +807,11 @@
     size_t size_local = (size_t) size;
     void * payload_local = NULL;
     int32_t ret = 0;
+
+    if (payload.size() < size) {
+        return -EINVAL;
+    }
+
     payload_local = (void*) calloc (1,size);
     if (payload_local == NULL) {
         ALOGE("%s: Cannot allocate memory for payload_local\n", __func__);
@@ -826,6 +860,10 @@
     size_t size_local = (size_t) size;
     void * payload_local = NULL;
     int32_t ret = 0;
+
+    if (payload.size() < size) {
+        return -EINVAL;
+    }
     payload_local = (void*) calloc(1,size);
     if (payload_local == NULL) {
         ALOGE("%s: Cannot allocate memory for payload_local\n", __func__);
@@ -1032,6 +1070,12 @@
     return agm_session_flush(hndl);
 }
 
+Return<int32_t> AGM::ipc_agm_sessionid_flush(uint32_t session_id) {
+    ALOGV("%s called with session id = %d", __func__, session_id);
+
+    return agm_sessionid_flush(session_id);
+}
+
 Return<int32_t> AGM::ipc_agm_session_resume(uint64_t hndl) {
     ALOGV("%s called with handle = %llx \n", __func__, (unsigned long long) hndl);
 
@@ -1070,6 +1114,12 @@
                                         ipc_agm_session_write_cb _hidl_cb) {
     ALOGV("%s called with handle = %llx \n", __func__, (unsigned long long) hndl);
     void* buffer = NULL;
+
+    if (buff.size() < count) {
+        _hidl_cb(-EINVAL, count);
+        return Void();
+    }
+
     buffer = (void*) calloc(1,count);
     if (buffer == NULL) {
         ALOGE("%s: Cannot allocate memory for buffer\n", __func__);
@@ -1419,6 +1469,10 @@
     buf.addr = nullptr;
     buf.metadata = nullptr;
 
+    if (buff_hidl.data()->metadata.size() < buff_hidl.data()->metadata_size) {
+        _hidl_cb(-EINVAL, buff_hidl.data()->metadata_size);
+        return Void();
+    }
     bufSize = buff_hidl.data()->size;
     buf.addr = (uint8_t *)calloc(1, bufSize);
     if (!buf.addr) {
diff --git a/ipc/HwBinders/interfaces/AGMIPC/1.0/IAGM.hal b/ipc/HwBinders/interfaces/AGMIPC/1.0/IAGM.hal
index 0e797a4..280cc5d 100644
--- a/ipc/HwBinders/interfaces/AGMIPC/1.0/IAGM.hal
+++ b/ipc/HwBinders/interfaces/AGMIPC/1.0/IAGM.hal
@@ -125,6 +125,7 @@
     ipc_agm_session_stop(uint64_t hndl) generates (int32_t ret);
     ipc_agm_session_pause(uint64_t hndl) generates (int32_t ret);
     ipc_agm_session_flush(uint64_t hndl) generates (int32_t ret);
+    ipc_agm_sessionid_flush(uint32_t session_id) generates (int32_t ret);
     ipc_agm_session_resume(uint64_t hndl) generates (int32_t ret);
     ipc_agm_session_suspend(uint64_t hndl) generates (int32_t ret);
     ipc_agm_session_read(uint64_t hndl, uint32_t count)
diff --git a/ipc/HwBinders/interfaces/AGMIPC/current.txt b/ipc/HwBinders/interfaces/AGMIPC/current.txt
index ae21480..8eae287 100644
--- a/ipc/HwBinders/interfaces/AGMIPC/current.txt
+++ b/ipc/HwBinders/interfaces/AGMIPC/current.txt
@@ -1,4 +1,4 @@
 # Hash for vendor.qti.hardware.AGMIPC@1.0 package
 1846dac975898187405fcd011ea43c98415334e187a74a2e4fcaea123e0064b7 vendor.qti.hardware.AGMIPC@1.0::types
-c75ed15965f38d53fe69c0a641fb7c9ae043560cb5dcd4e73ea31499251a8dc5 vendor.qti.hardware.AGMIPC@1.0::IAGM
+a1545123ef5e6f4536cd2f2902c74a202b39bac323bcbc0ed703ab1437056d4c vendor.qti.hardware.AGMIPC@1.0::IAGM
 e8d1ca223a57cfacc7373f6418555330bb545c43a1e9d2c3a1fdd984fcec4a14 vendor.qti.hardware.AGMIPC@1.0::IAGMCallback
diff --git a/plugins/tinyalsa/src/agm_mixer_plugin.c b/plugins/tinyalsa/src/agm_mixer_plugin.c
index 819ed25..cb85c9d 100644
--- a/plugins/tinyalsa/src/agm_mixer_plugin.c
+++ b/plugins/tinyalsa/src/agm_mixer_plugin.c
@@ -144,17 +144,19 @@
     "loopback",
     "echoReference",
     "bufTimestamp",
-    /* Add new ones here, be sue to update enum as well */
+    /* Add new ones here, be sure to update enum as well */
 };
 
 enum {
     PCM_RX_CTL_NAME_SIDETONE = 0,
     PCM_RX_CTL_NAME_DATAPATH_PARAMS,
+    PCM_RX_CTL_NAME_FLUSH,
 };
 /* strings should be at the index as per the enum */
 static char *amp_pcm_rx_ctl_names[] = {
     "sidetone",
     "datapathParams",
+    "flush",
 };
 
 struct amp_get_param_info {
@@ -1678,6 +1680,26 @@
     return ret;
 }
 
+/* Dummy implementation for flush_get */
+static int amp_pcm_flush_get(struct mixer_plugin *plugin __unused,
+                struct snd_control *ctl __unused, struct snd_ctl_elem_value *ev __unused)
+{
+    return 0;
+}
+
+static int amp_pcm_flush_put(struct mixer_plugin *plugin,
+                struct snd_control *ctl, struct snd_ctl_elem_value *ev)
+{
+    uint32_t pcm_idx = ctl->private_value;
+    bool flush = !!(ev->value.integer.value[0]);
+    int ret = 0;
+
+    if (flush)
+        ret = agm_sessionid_flush(pcm_idx);
+
+    return ret;
+}
+
 /* 512 max bytes for non-tlv controls, reserving 16 for future use */
 static struct snd_value_bytes pcm_calibration_bytes =
     SND_VALUE_BYTES(512 - 16);
@@ -1714,6 +1736,9 @@
 static struct snd_value_int group_media_fmt_int =
     SND_VALUE_INTEGER(5, 0, 384000, 1);
 
+static struct snd_value_int flush_param_int =
+    SND_VALUE_INTEGER(1, 0, 1, 1);
+
 static struct snd_value_tlv_bytes be_setparam_bytes =
     SND_VALUE_TLV_BYTES(64 * 1024, amp_be_set_param_get, amp_be_set_param_put);
 
@@ -1957,6 +1982,18 @@
             pcm_getacdbtunnel_bytes, pval, pdata);
 }
 
+static void amp_create_pcm_flush_ctl(struct amp_priv *amp_priv,
+    char *name, int ctl_idx, int pval, void *pdata)
+{
+    struct snd_control *ctl = AMP_PRIV_GET_CTL_PTR(amp_priv, ctl_idx);
+    char *ctl_name = AMP_PRIV_GET_CTL_NAME_PTR(amp_priv, ctl_idx);
+
+    snprintf(ctl_name, AIF_NAME_MAX_LEN + 16, "%s %s",
+            name, amp_pcm_rx_ctl_names[PCM_RX_CTL_NAME_FLUSH]);
+
+    INIT_SND_CONTROL_INTEGER(ctl, ctl_name, amp_pcm_flush_get,
+            amp_pcm_flush_put, flush_param_int, pval, pdata);
+}
 
 /* BE related mixer control creations here */
 static void amp_create_metadata_ctl(struct amp_priv *amp_priv,
@@ -2140,6 +2177,8 @@
                         &be_tx_adi->dev_enum, idx, rx_adi);
         amp_create_pcm_write_with_metadata_ctl(amp_priv, name, (*ctl_idx)++,
                         idx, rx_adi);
+        amp_create_pcm_flush_ctl(amp_priv, name, (*ctl_idx)++,
+                        idx, rx_adi);
     }
 
     return 0;
diff --git a/plugins/tinyalsa/src/agm_pcm_plugin.c b/plugins/tinyalsa/src/agm_pcm_plugin.c
index 176a218..92561fc 100644
--- a/plugins/tinyalsa/src/agm_pcm_plugin.c
+++ b/plugins/tinyalsa/src/agm_pcm_plugin.c
@@ -59,7 +59,8 @@
 #define AGM_PULL_PUSH_IDX_RETRY_COUNT 2
 #define AGM_PULL_PUSH_FRAME_CNT_RETRY_COUNT 5
 
-#define SNDCARD_PATH "/sys/kernel/snd_card/card_state"
+/* multiplier of timeout for wating for mmap buffers */
+#define MMAP_TOUT_MULTI 4
 
 struct agm_shared_pos_buffer {
     volatile uint32_t frame_counter;
@@ -100,7 +101,7 @@
     /* idx: 0: out port, 1: in port */
     struct agm_mmap_buffer_port mmap_buffer_port[2];
     bool mmap_status;
-    int fd;
+    uint32_t mmap_buf_tout;
 };
 
 struct pcm_plugin_hw_constraints agm_pcm_constrs = {
@@ -310,28 +311,6 @@
     return -EAGAIN;
 }
 
-static int agm_pcm_plugin_get_card_status(struct agm_pcm_priv *priv)
-{
-    char buf[10];
-    int card_status = -1;
-
-    if (priv->fd < 0) {
-         if ((priv->fd = open(SNDCARD_PATH, O_RDWR)) < 0) {
-             AGM_LOGE(LOG_TAG, "Open failed snd sysfs node");
-             errno = ENETRESET;
-             return -ENETRESET;
-        }
-        AGM_LOGD(LOG_TAG, "Snd sysfs node open successful");
-    }
-
-    memset(buf, 0, sizeof(buf));
-    read(priv->fd, buf, 1);
-    lseek(priv->fd, 0L, SEEK_SET);
-    sscanf(buf, "%d", &card_status);
-
-    return card_status;
-}
-
 static int agm_pcm_plugin_update_hw_ptr(struct agm_pcm_priv *priv)
 {
     int retries = 10;
@@ -344,15 +323,8 @@
     int ret = 0;
     uint32_t period_size = priv->period_size; /** in frames */
     uint32_t crossed_boundary = 0;
-    int card_status = -1;
     uint32_t old_frame_counter = priv->pos_buf->frame_counter;
 
-    card_status = agm_pcm_plugin_get_card_status(priv);
-    if (card_status != 1) {    // 1 assume to be snd card status online
-        AGM_LOGE("%s: Snd card is Offline\n", __func__);
-        errno = ENETRESET;
-        return -ENETRESET;
-    }
     do {
         ret = agm_pcm_plugin_get_shared_pos(priv->pos_buf,
                 &read_index, &wall_clk_msw, &wall_clk_lsw);
@@ -727,10 +699,6 @@
             close(priv->buf_info->data_buf_fd);
         free(priv->buf_info);
     }
-    if (priv->fd >= 0) {
-        close(priv->fd);
-        priv->fd = -1;
-    }
     free(plugin->priv);
     free(plugin);
 
@@ -767,6 +735,7 @@
     uint32_t period_size = priv->period_size;
     snd_pcm_sframes_t avail;
     int ret = 0;
+    uint32_t period_to_msec = period_size / (priv->media_config->rate / 1000);
 
     avail = agm_pcm_get_avail(plugin);
 
@@ -777,8 +746,6 @@
         ret = agm_pcm_plugin_update_hw_ptr(priv);
         if (ret == 0)
             avail = agm_pcm_get_avail(plugin);
-        else if (ret == -ENETRESET)
-            return ret;
     }
 
     if (avail >= period_size) {
@@ -789,8 +756,16 @@
             pfd->revents = POLLOUT;
             ret = POLLOUT;
         }
+        priv->mmap_buf_tout = 0;
     } else {
         ret = 0; /* TIMEOUT */
+        priv->mmap_buf_tout += timeout;
+        if (priv->mmap_buf_tout > (period_to_msec * MMAP_TOUT_MULTI)) {
+            AGM_LOGE("timeout in waiting for mmap buffer");
+            priv->mmap_buf_tout = 0;
+            errno = ETIMEDOUT;
+            return -ETIMEDOUT;
+        }
     }
 
     return ret;
@@ -967,13 +942,6 @@
         goto err_buf_free;
     }
 
-    priv->fd = -1;
-    if ((priv->fd = open(SNDCARD_PATH, O_RDWR)) < 0) {
-        AGM_LOGE(LOG_TAG, "Open failed snd sysfs node");
-        ret = -EINVAL;
-        goto err_session_free;
-    }
-
     card_node = snd_card_def_get_card(card);
     if (!card_node) {
         ret = -EINVAL;
@@ -1021,10 +989,6 @@
 err_card_put:
     snd_card_def_put_card(card_node);
 err_session_free:
-    if (priv->fd >= 0) {
-        close(priv->fd);
-        priv->fd = -1;
-    }
     free(session_config);
 err_buf_free:
     free(buffer_config);
diff --git a/service/inc/private/agm/device.h b/service/inc/private/agm/device.h
index 7fda4a3..9bd6a08 100644
--- a/service/inc/private/agm/device.h
+++ b/service/inc/private/agm/device.h
@@ -89,6 +89,7 @@
 #define  PCM_RT_PROXY               0x7
 #define  AUDIOSS_DMA                0x8
 #define  PCM_DUMMY                  0x9
+#define  BTFM_PROXY                 0xa
 
 #define  AUDIO_OUTPUT               0x1 /**< playback usecases*/
 #define  AUDIO_INPUT                0x2 /**< capture/voice activation usecases*/
diff --git a/service/inc/private/agm/session_obj.h b/service/inc/private/agm/session_obj.h
index 4679117..b6969d0 100644
--- a/service/inc/private/agm/session_obj.h
+++ b/service/inc/private/agm/session_obj.h
@@ -111,6 +111,7 @@
 int session_obj_deinit();
 int session_obj_valid_check(uint64_t hndl);
 int session_obj_get(int session_id, struct session_obj **sess_obj);
+struct session_obj *session_obj_retrieve_from_pool(uint32_t session_id);
 int session_obj_open(uint32_t session_id,
                      enum agm_session_mode sess_mode,
                      struct session_obj **sess_obj);
diff --git a/service/inc/public/agm/agm_api.h b/service/inc/public/agm/agm_api.h
index 8680fa1..3ff08f7 100644
--- a/service/inc/public/agm/agm_api.h
+++ b/service/inc/public/agm/agm_api.h
@@ -960,6 +960,16 @@
 int agm_session_flush(uint64_t hndl);
 
 /**
+  * \brief flush the session. session must be in pause state
+  *        before flushing.
+  *
+  * \param[in] session_id - Valid audio session id
+  *
+  * \return 0 on success, error code otherwise
+  */
+int agm_sessionid_flush(uint32_t session_id);
+
+/**
   * \brief Resume the session. session must be in paused state
   *        before resuming.
   *
diff --git a/service/src/agm.c b/service/src/agm.c
index f56e7a4..f718369 100644
--- a/service/src/agm.c
+++ b/service/src/agm.c
@@ -795,6 +795,20 @@
     return session_obj_flush(handle);
 }
 
+int agm_sessionid_flush(uint32_t session_id)
+{
+    struct session_obj *handle = NULL;
+    int ret = 0;
+
+    handle = session_obj_retrieve_from_pool(session_id);
+    if (!handle) {
+        AGM_LOGE("Incorrect session_id:%d, doesn't match sess_obj from pool",
+                                        session_id);
+        return -EINVAL;
+    }
+    return session_obj_flush(handle);
+}
+
 int agm_session_resume(uint64_t hndl)
 {
     struct session_obj *handle = (struct session_obj *) hndl;
diff --git a/service/src/device_hw_ep.c b/service/src/device_hw_ep.c
index 155f0a0..bee6bce 100644
--- a/service/src/device_hw_ep.c
+++ b/service/src/device_hw_ep.c
@@ -178,6 +178,8 @@
         hw_ep_info->intf = AUDIOSS_DMA;
     else if (!strcmp(intf, "PCM_DUMMY"))
         hw_ep_info->intf = PCM_DUMMY;
+    else if (!strcmp(intf, "BTFM_PROXY"))
+        hw_ep_info->intf = BTFM_PROXY;
     else {
         AGM_LOGE("No matching intf found\n");
         return -EINVAL;
@@ -232,7 +234,7 @@
 
 }
 
-static int populate_pcm_rt_proxy_ep_info(hw_ep_info_t *hw_ep_info, char *value)
+static int populate_btfm_rt_proxy_ep_info(hw_ep_info_t *hw_ep_info, char *value)
 {
     char arg[DEV_ARG_SIZE] = {0};
     struct hw_ep_pcm_rt_proxy_config *pcm_rt_proxy_config;
@@ -410,7 +412,8 @@
     case USB_AUDIO:
         return populate_slim_dp_usb_ep_info(&dev_obj->hw_ep_info, value);
     case PCM_RT_PROXY:
-        return populate_pcm_rt_proxy_ep_info(&dev_obj->hw_ep_info, value);
+    case BTFM_PROXY:
+        return populate_btfm_rt_proxy_ep_info(&dev_obj->hw_ep_info, value);
     case AUDIOSS_DMA:
         return populate_audioss_dma_ep_info(&dev_obj->hw_ep_info, value);
     case PCM_DUMMY:
diff --git a/service/src/graph_module.c b/service/src/graph_module.c
index f77aa0f..1a0cb70 100644
--- a/service/src/graph_module.c
+++ b/service/src/graph_module.c
@@ -744,10 +744,11 @@
     int ret = 0;
     struct device_obj *dev_obj = mod->dev_obj;
 
-    if(dev_obj->hw_ep_info.intf == PCM_RT_PROXY || dev_obj->hw_ep_info.intf == PCM_DUMMY) {
+    if ((dev_obj->hw_ep_info.intf == PCM_RT_PROXY) ||
+        (dev_obj->hw_ep_info.intf == PCM_DUMMY) ||
+        (dev_obj->hw_ep_info.intf == BTFM_PROXY)) {
         AGM_LOGD("no ep media config for %d\n",  dev_obj->hw_ep_info.intf);
-    }
-    else {
+    } else {
         ret = configure_hw_ep_media_config(mod, graph_obj);
         if (ret) {
             AGM_LOGE("hw_ep_media_config failed %d", ret);
@@ -772,19 +773,15 @@
          break;
     case DISPLAY_PORT:
     case USB_AUDIO:
-        AGM_LOGD("no ep configuration for %d\n",  dev_obj->hw_ep_info.intf);
-        break;
     case PCM_RT_PROXY:
-        AGM_LOGD("no ep configuration for %d\n",  dev_obj->hw_ep_info.intf);
-        break;
     case AUDIOSS_DMA:
-        AGM_LOGD("no ep configuration for %d\n",  dev_obj->hw_ep_info.intf);
-        break;
     case PCM_DUMMY:
+    case BTFM_PROXY:
         AGM_LOGD("no ep configuration for %d\n",  dev_obj->hw_ep_info.intf);
         break;
     default:
          AGM_LOGE("hw intf %d not enabled yet", dev_obj->hw_ep_info.intf);
+         ret = -EINVAL;
          break;
     }
     return ret;
diff --git a/service/src/metadata.c b/service/src/metadata.c
index c94f856..047f5e0 100644
--- a/service/src/metadata.c
+++ b/service/src/metadata.c
@@ -270,17 +270,17 @@
     return merged;
 }
 
-int metadata_copy(struct agm_meta_data_gsl *dest, uint32_t size __unused,
+int metadata_copy(struct agm_meta_data_gsl *dest, uint32_t size,
                                               uint8_t *metadata)
 {
 
     int ret = 0;
+    int min_req_len = 0;
 
     if (!metadata) {
         AGM_LOGI("NULL metadata passed, ignoring\n");
-        return ret;
+        goto done;
     }
-
     if ((NUM_GKV(metadata) > MAX_KVPAIR) || (NUM_CKV(metadata) > MAX_KVPAIR)) {
         AGM_LOGE("Num GKVs %d Num CKVs %d more than expected: %d", NUM_GKV(metadata),
                                                       NUM_CKV(metadata), MAX_KVPAIR);
@@ -288,39 +288,84 @@
         return ret;
     }
 
+    min_req_len += sizeof(uint32_t);
+    if (size < min_req_len) {
+        AGM_LOGE("size should be atleast %d size for GKV\n", sizeof(uint32_t));
+        ret = -EINVAL;
+        goto done;
+
+    }
+
     dest->gkv.num_kvs = NUM_GKV(metadata);
     dest->gkv.kv =  calloc(dest->gkv.num_kvs, sizeof(struct agm_key_value));
     if (!dest->gkv.kv) {
         AGM_LOGE("Memory allocation failed to copy GKV\n");
         ret = -ENOMEM;
-        return ret;
+        goto free_metadata;
+    }
+
+    min_req_len += (dest->gkv.num_kvs * sizeof(struct agm_key_value));
+    if (size < min_req_len) {
+        AGM_LOGE("Invalid GKV passed\n");
+        ret = -EINVAL;
+        goto free_metadata;
     }
     memcpy(dest->gkv.kv, PTR_TO_GKV(metadata), dest->gkv.num_kvs *
                                     sizeof(struct agm_key_value));
 
+    min_req_len += sizeof(uint32_t);
+    if (size < min_req_len) {
+        goto done;
+    }
     dest->ckv.num_kvs = NUM_CKV(metadata);
     dest->ckv.kv =  calloc(dest->ckv.num_kvs, sizeof(struct agm_key_value));
     if (!dest->ckv.kv) {
         AGM_LOGE("Memory allocation failed to copy CKV\n");
-        metadata_free(dest);
         ret = -ENOMEM;
-        return ret;
+        goto free_metadata;
+    }
+    min_req_len += (dest->ckv.num_kvs * sizeof(struct agm_key_value));
+    if (size < min_req_len) {
+        AGM_LOGE("Invalid CKV passed\n");
+        ret = -EINVAL;
+        goto free_metadata;
     }
     memcpy(dest->ckv.kv, PTR_TO_CKV(metadata), dest->ckv.num_kvs *
                                     sizeof(struct agm_key_value));
 
+    min_req_len += sizeof(uint32_t);
+    if (size < min_req_len) {
+        goto done;
+    }
     dest->sg_props.prop_id = PROP_ID(metadata);
+
+    min_req_len += sizeof(uint32_t);
+    if (size < min_req_len) {
+        AGM_LOGE("Invalid properties passed\n");
+        ret = -EINVAL;
+        goto free_metadata;
+    }
     dest->sg_props.num_values = NUM_PROPS(metadata);
     dest->sg_props.values =  calloc(dest->sg_props.num_values, sizeof(uint32_t));
     if (!dest->sg_props.values) {
         AGM_LOGE("Memory allocation failed to copy properties\n");
-        metadata_free(dest);
         ret = -ENOMEM;
-        return ret;
+        goto free_metadata;
+    }
+    min_req_len += (dest->sg_props.num_values * sizeof(uint32_t));
+    if (size < min_req_len) {
+        AGM_LOGE("Invalid properties passed\n");
+        ret = -EINVAL;
+        goto free_metadata;
     }
     memcpy(dest->sg_props.values, PTR_TO_PROPS(metadata),
            dest->sg_props.num_values * sizeof(uint32_t));
+    goto done;
 
+free_metadata:
+    metadata_free(dest);
+
+done:
     return ret;
 
 }
diff --git a/service/src/session_obj.c b/service/src/session_obj.c
index f3295b0..7809de4 100644
--- a/service/src/session_obj.c
+++ b/service/src/session_obj.c
@@ -1081,7 +1081,7 @@
 
         pthread_mutex_lock(&hwep_lock);
 
-        //For Slimbus EP - First configure the slave ports via device_prepare/start
+        //For Slimbus/CP EP - First configure the slave ports via device_prepare/start
         //and then start the master side via graph_start.
         list_for_each(node, &sess_obj->aif_pool) {
             aif_obj = node_to_item(node, struct aif, node);
@@ -1090,8 +1090,9 @@
                 goto device_stop;
             }
 
-            if (aif_obj->dev_obj->hw_ep_info.intf == SLIMBUS) {
-                AGM_LOGD("configuring device early - for SLIMBUS EPs\n");
+            if ((aif_obj->dev_obj->hw_ep_info.intf == SLIMBUS) ||
+                (aif_obj->dev_obj->hw_ep_info.intf == BTFM_PROXY)) {
+                AGM_LOGD("configuring device early - for SLIMBUS/Connectivity Proxy EPs\n");
                 if (aif_obj->state == AIF_OPENED || aif_obj->state == AIF_STOPPED) {
                     ret = device_prepare(aif_obj->dev_obj);
                     if (ret) {
@@ -1128,9 +1129,11 @@
                 goto unwind;
             }
 
-            //Continue/SKIP for SLIMBUS EP as they are started early.
-            if (aif_obj->dev_obj->hw_ep_info.intf == SLIMBUS)
+            //Continue/SKIP for SLIMBUS/Connectivity Proxy EP as they are started early.
+            if ((aif_obj->dev_obj->hw_ep_info.intf == SLIMBUS) ||
+                (aif_obj->dev_obj->hw_ep_info.intf == BTFM_PROXY)) {
                 continue;
+            }
 
             if (aif_obj->state == AIF_OPENED || aif_obj->state == AIF_STOPPED) {
                 ret = device_prepare(aif_obj->dev_obj);
diff --git a/snd_parser/src/snd-card-parser.c b/snd_parser/src/snd-card-parser.c
index 525028d..37824e6 100644
--- a/snd_parser/src/snd-card-parser.c
+++ b/snd_parser/src/snd-card-parser.c
@@ -491,6 +491,7 @@
         }
     }
 
+    card_def = NULL;
     /* read XML */
     file = fopen(CARD_DEF_FILE, "r");
     if (!file) {