Merge "agm: Add aif state check while getting merged metadata"
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 404049c..a8cb5fc 100644
--- a/ipc/HwBinders/agm_ipc_client/src/agm_client_wrapper.cpp
+++ b/ipc/HwBinders/agm_ipc_client/src/agm_client_wrapper.cpp
@@ -281,6 +281,15 @@
     return -EINVAL;
 }
 
+int agm_session_suspend(uint64_t handle){
+    ALOGV("%s called with handle = %llx \n", __func__, (unsigned long long) handle);
+    if (!agm_server_died) {
+        android::sp<IAGM> agm_client = get_agm_server();
+        return agm_client->ipc_agm_session_suspend(handle);
+    }
+    return -EINVAL;
+}
+
 int agm_session_open(uint32_t session_id, enum agm_session_mode sess_mode ,
                      uint64_t *handle) {
     ALOGD("%s called with handle = %x , *handle = %x\n", __func__, handle, *handle);
@@ -817,7 +826,7 @@
     return -EINVAL;
 }
 
-int agm_session_write_with_metadata(uint64_t handle, struct agm_buff *buf, uint32_t *consumed_size)
+int agm_session_write_with_metadata(uint64_t handle, struct agm_buff *buf, size_t *consumed_size)
 {
     ALOGV("%s called with handle = %x \n", __func__, handle);
     int32_t ret = -EINVAL;
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 b1eb594..4b656f0 100644
--- a/ipc/HwBinders/agm_ipc_service/inc/agm_server_wrapper.h
+++ b/ipc/HwBinders/agm_ipc_service/inc/agm_server_wrapper.h
@@ -207,6 +207,7 @@
     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_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,
                                     ipc_agm_session_read_cb _hidl_cb) override;
     Return<void> ipc_agm_session_write(uint64_t hndl,
@@ -245,7 +246,7 @@
                        const hidl_vec<AgmBufferConfig>& in_buffer_config,
                        const hidl_vec<AgmBufferConfig>& out_buffer_config) override;
     Return<void> ipc_agm_session_write_with_metadata(uint64_t hndl, const hidl_vec<AgmBuff>& buff,
-                                               uint32_t consumed_size,
+                                               uint64_t consumed_size,
                                                ipc_agm_session_write_with_metadata_cb) override;
     Return<void> ipc_agm_session_read_with_metadata(uint64_t hndl, const hidl_vec<AgmBuff>& buff,
                                                uint32_t captured_size,
@@ -254,7 +255,7 @@
     int is_agm_initialized() { return agm_initialized;}
 
 private:
-    sp<client_death_notifier> Client_death_notifier = NULL;
+    sp<client_death_notifier> mDeathNotifier = NULL;
     bool agm_initialized;
 };
 
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 a7aed12..0ad500e 100644
--- a/ipc/HwBinders/agm_ipc_service/src/agm_server_wrapper.cpp
+++ b/ipc/HwBinders/agm_ipc_service/src/agm_server_wrapper.cpp
@@ -36,11 +36,13 @@
 #include <hwbinder/IPCThreadState.h>
 
 #define MAX_CACHE_SIZE 64
+using AgmCallbackData = ::vendor::qti::hardware::AGMIPC::V1_0::implementation::clbk_data;
+using AgmServerCallback = ::vendor::qti::hardware::AGMIPC::V1_0::implementation::SrvrClbk;
 
 void client_death_notifier::serviceDied(uint64_t cookie,
                    const android::wp<::android::hidl::base::V1_0::IBase>& who __unused)
 {
-    ALOGI("Client died ,cookie (pid): %llu",(unsigned long long) cookie);
+    ALOGI("Client died (pid): %llu",(unsigned long long) cookie);
     struct listnode *node = NULL;
     struct listnode *tempnode = NULL;
     agm_client_session_handle *hndl = NULL;
@@ -48,28 +50,26 @@
     struct listnode *sess_node = NULL;
     struct listnode *sess_tempnode = NULL;
 
-    ::vendor::qti::hardware::AGMIPC::V1_0::implementation::clbk_data *clbk_data_hndl = NULL;
+    AgmCallbackData* clbk_data_hndl = NULL;
     if (clbk_data_list_init) {
-    pthread_mutex_lock(&clbk_data_list_lock);
-    list_for_each_safe(node, tempnode, &clbk_data_list) {
-        clbk_data_hndl = node_to_item(node,
-             ::vendor::qti::hardware::AGMIPC::V1_0::implementation::clbk_data, list);
-        if (clbk_data_hndl->srv_clt_data->pid == cookie) {
-            ALOGV("%s : Matched pid with cookie = \" %d \" ", __func__,
-                                               clbk_data_hndl->srv_clt_data->pid);
-            ::vendor::qti::hardware::AGMIPC::V1_0::implementation::SrvrClbk *tmp_sr_clbk_data =
-                                                                   clbk_data_hndl->srv_clt_data;
-            /*Unregister this callback from session_obj*/
-            agm_session_register_cb(tmp_sr_clbk_data->session_id,
-                                    NULL,
-                                    (enum event_type)tmp_sr_clbk_data->event,
-                                    tmp_sr_clbk_data),
-            list_remove(node);
-            free(clbk_data_hndl);
+        pthread_mutex_lock(&clbk_data_list_lock);
+        list_for_each_safe(node, tempnode, &clbk_data_list) {
+            clbk_data_hndl = node_to_item(node, AgmCallbackData, list);
+            if (clbk_data_hndl->srv_clt_data->pid == cookie) {
+                ALOGV("%s pid matched %d ", __func__, clbk_data_hndl->srv_clt_data->pid);
+                AgmServerCallback* tmp_sr_clbk_data = clbk_data_hndl->srv_clt_data;
+                /*Unregister this callback from session_obj*/
+                agm_session_register_cb(tmp_sr_clbk_data->session_id,
+                                        NULL,
+                                        (enum event_type)tmp_sr_clbk_data->event,
+                                        tmp_sr_clbk_data),
+                list_remove(node);
+                free(clbk_data_hndl);
+            }
         }
+        pthread_mutex_unlock(&clbk_data_list_lock);
     }
-    pthread_mutex_unlock(&clbk_data_list_lock);
-    }
+
     pthread_mutex_lock(&client_list_lock);
     if (client_list_init) {
         list_for_each_safe(node, tempnode, &client_list) {
@@ -798,6 +798,12 @@
     return agm_session_resume(hndl);
 }
 
+Return<int32_t> AGM::ipc_agm_session_suspend(uint64_t hndl) {
+    ALOGV("%s called with handle = %llx \n", __func__, (unsigned long long) hndl);
+
+    return agm_session_suspend(hndl);
+}
+
 Return<void> AGM::ipc_agm_session_read(uint64_t hndl, uint32_t count,
                                              ipc_agm_session_read_cb _hidl_cb) {
     ALOGV("%s called with handle = %llx \n", __func__, (unsigned long long) hndl);
@@ -903,15 +909,11 @@
     SrvrClbk  *sr_clbk_data = NULL, *tmp_sr_clbk_data = NULL;
     clbk_data *clbk_data_obj = NULL;
 
-    if ( this->Client_death_notifier == NULL ) {
-        this->Client_death_notifier = new client_death_notifier();
-        ALOGV("Client_death_notifier = %p", this->Client_death_notifier.get());
-    }
     int pid = ::android::hardware::IPCThreadState::self()->getCallingPid();
-    ALOGV("%s : client about to link to death with pid = %d\n", __func__, pid);
 
     if (cb != NULL) {
-        cb->linkToDeath(this->Client_death_notifier, pid);
+        bool newClient = true;
+
         ALOGV("%s : client linked to death with pid = %d\n", __func__, pid);
         sr_clbk_data = new SrvrClbk (session_id, cb, evt_type, ipc_client_data, pid);
         ALOGV("%s new SrvrClbk= %p, clntdata= %llx, sess id= %d, evt_type= %d \n",
@@ -924,7 +926,31 @@
             (const pthread_mutexattr_t *) NULL);
             list_init(&clbk_data_list);
             clbk_data_list_init = true;
+        } else {
+            struct listnode* node = NULL;
+            clbk_data* callbackData = NULL;
+            pthread_mutex_lock(&clbk_data_list_lock);
+
+            list_for_each(node, &clbk_data_list) {
+                callbackData = node_to_item(node, clbk_data, list);
+                if (callbackData->srv_clt_data->pid == pid) {
+                    ALOGV("client with pid %d already exists", pid);
+                    newClient = false;
+                    break;
+                }
+            }
+
+            pthread_mutex_unlock(&clbk_data_list_lock);
         }
+
+        if (newClient) {
+            if (mDeathNotifier == NULL) {
+                mDeathNotifier = new client_death_notifier();
+            }
+            ALOGI("linkToDeath for pid %d", pid);
+            cb->linkToDeath(mDeathNotifier, pid);
+        }
+
         clbk_data_obj = (clbk_data *)calloc(1, sizeof(clbk_data));
         if (clbk_data_obj == NULL) {
             ALOGE("%s: Cannot allocate memory for cb data object\n", __func__);
@@ -1130,13 +1156,13 @@
 }
 
 Return<void> AGM::ipc_agm_session_write_with_metadata(uint64_t hndl, const hidl_vec<AgmBuff>& buff_hidl,
-                                               uint32_t consumed_sz,
+                                               uint64_t consumed_sz,
                                                ipc_agm_session_write_with_metadata_cb _hidl_cb)
 {
     int32_t ret = -EINVAL;
     struct agm_buff buf;
     uint32_t bufSize;
-    uint32_t consumed_size = consumed_sz;
+    size_t consumed_size = consumed_sz;
     const native_handle *allochandle = nullptr;
     buf.addr = nullptr;
     buf.metadata = nullptr;
diff --git a/ipc/HwBinders/interfaces/AGMIPC/1.0/IAGM.hal b/ipc/HwBinders/interfaces/AGMIPC/1.0/IAGM.hal
index a1a8cd4..dd2016f 100644
--- a/ipc/HwBinders/interfaces/AGMIPC/1.0/IAGM.hal
+++ b/ipc/HwBinders/interfaces/AGMIPC/1.0/IAGM.hal
@@ -85,6 +85,7 @@
     ipc_agm_session_pause(uint64_t hndl) generates (int32_t ret);
     ipc_agm_session_flush(uint64_t hndl) 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)
                     generates (int32_t ret, vec<uint8_t> buff, uint32_t count_ret);
     ipc_agm_session_write(uint64_t hndl, vec<uint8_t> buff, uint32_t count)
@@ -111,7 +112,7 @@
     ipc_agm_set_gapless_session_metadata(uint64_t hndl, AgmGaplessSilenceType type,
                     uint32_t silence)
                     generates (int32_t ret);
-    ipc_agm_session_write_with_metadata(uint64_t hndl, vec<AgmBuff> buff, uint32_t consumed_size)
+    ipc_agm_session_write_with_metadata(uint64_t hndl, vec<AgmBuff> buff, uint64_t consumed_size)
                     generates (int32_t ret, uint32_t consumed_size);
     ipc_agm_session_read_with_metadata(uint64_t hndl, vec<AgmBuff> buff, uint32_t captured_size)
                     generates (int32_t ret, vec<AgmBuff> buff, uint32_t captured_size);
diff --git a/service/inc/private/agm/device.h b/service/inc/private/agm/device.h
index 372e195..daf3d1e 100644
--- a/service/inc/private/agm/device.h
+++ b/service/inc/private/agm/device.h
@@ -31,6 +31,7 @@
 #define __AGM_DEVICE_H__
 
 #include <pthread.h>
+#include <agm/agm_list.h>
 #include <agm/agm_priv.h>
 #ifdef DEVICE_USES_ALSALIB
 #include <alsa/asoundlib.h>
@@ -129,6 +130,7 @@
      */
     char name[MAX_DEV_NAME_LEN];
 
+    struct listnode list_node;
     pthread_mutex_t lock;
     /* pcm device info associated with the device object */
     uint32_t card_id;
diff --git a/service/inc/private/agm/graph.h b/service/inc/private/agm/graph.h
index d760672..9cea7d7 100644
--- a/service/inc/private/agm/graph.h
+++ b/service/inc/private/agm/graph.h
@@ -209,6 +209,14 @@
 int graph_resume(struct graph_obj *gph_obj);
 
 /**
+ *\brief suspend an existing graph.
+ *\param [in] graph_obj: associated graph obj
+ *
+ * return AR_EOK on success or error code otherwise.
+ */
+int graph_suspend(struct graph_obj *gph_obj);
+
+/**
  *\brief add a new audio path (graph/subgraph) to an exisitng graph.
  * Assumption here is only the device leg would always be updated,
  * as a part of the passed GKV.
diff --git a/service/inc/private/agm/session_obj.h b/service/inc/private/agm/session_obj.h
index d9a2405..33408b2 100644
--- a/service/inc/private/agm/session_obj.h
+++ b/service/inc/private/agm/session_obj.h
@@ -123,6 +123,7 @@
 int session_obj_pause(struct session_obj *sess_obj);
 int session_obj_flush(struct session_obj *sess_obj);
 int session_obj_resume(struct session_obj *sess_obj);
+int session_obj_suspend(struct session_obj *sess_obj);
 int session_obj_read(struct session_obj *sess_obj, void *buff, size_t *count);
 int session_obj_write(struct session_obj *sess_obj, void *buff, size_t *count);
 int session_obj_sess_aif_connect(struct session_obj *sess_obj,
@@ -174,7 +175,7 @@
                                      uint32_t silence);
 int session_obj_write_with_metadata(struct session_obj *sess_obj,
                                     struct agm_buff *buff,
-                                    uint32_t *consumed_size);
+                                    size_t *consumed_size);
 int session_obj_read_with_metadata(struct session_obj *sess_obj,
                                    struct agm_buff *buff,
                                    uint32_t *captured_size);
diff --git a/service/inc/public/agm/agm_api.h b/service/inc/public/agm/agm_api.h
index 7731fc6..f784b5e 100644
--- a/service/inc/public/agm/agm_api.h
+++ b/service/inc/public/agm/agm_api.h
@@ -839,6 +839,17 @@
 int agm_session_resume(uint64_t hndl);
 
 /**
+  * \brief suspend the session. session must be in started state
+  *        before suspending.
+  *
+  * \param[in] handle - Valid session handle obtained
+  *       from agm_session_open
+  *
+  * \return 0 on success, error code otherwise
+  */
+int agm_session_suspend(uint64_t hndl);
+
+/**
   * \brief Read data buffers.from session
   *
   * \param[in] handle: session handle returned from
@@ -1008,7 +1019,7 @@
  * \return 0 on success, error code otherwise
  */
 int agm_session_write_with_metadata(uint64_t hndl, struct agm_buff *buff,
-                                    uint32_t *consumed_size);
+                                    size_t *consumed_size);
 
 /**
  * \brief Read data buffers with metadata to session
diff --git a/service/src/agm.c b/service/src/agm.c
index d7a356a..2f15f76 100644
--- a/service/src/agm.c
+++ b/service/src/agm.c
@@ -602,6 +602,16 @@
     return session_obj_resume(handle);
 }
 
+int agm_session_suspend(uint64_t hndl)
+{
+    struct session_obj *handle = (struct session_obj *) hndl;
+    if (!handle) {
+        AGM_LOGE("Invalid handle\n");
+        return -EINVAL;
+    }
+    return session_obj_suspend(handle);
+}
+
 int agm_session_write(uint64_t hndl, void *buff, size_t *count)
 {
     struct session_obj *handle = (struct session_obj *) hndl;
@@ -763,7 +773,7 @@
 }
 
 int agm_session_write_with_metadata(uint64_t handle, struct agm_buff *buff,
-                                    uint32_t *consumed_size)
+                                    size_t *consumed_size)
 {
     if (!handle) {
         AGM_LOGE("%s Invalid handle\n", __func__);
diff --git a/service/src/device.c b/service/src/device.c
index ffcc710..c150808 100644
--- a/service/src/device.c
+++ b/service/src/device.c
@@ -65,7 +65,7 @@
 #define DEVICE_DISABLE 0
 
 /* Global list to store supported devices */
-struct device_obj **device_list;
+static struct listnode device_list;
 static uint32_t num_audio_intfs;
 
 #ifdef DEVICE_USES_ALSALIB
@@ -148,7 +148,8 @@
 
 int device_get_snd_card_id()
 {
-    struct device_obj *dev_obj = device_list[0];
+    struct device_obj *dev_obj = node_to_item(list_head(&device_list),
+                                              struct device_obj, list_node);
 
     if (dev_obj == NULL) {
         AGM_LOGE("%s: Invalid device object\n", __func__);
@@ -465,16 +466,19 @@
     struct device_obj *dev_obj;
     uint32_t copied = 0;
     uint32_t requested = *audio_intfs;
+    struct listnode *dev_node, *temp;
 
     if (*audio_intfs == 0){
         *audio_intfs = num_audio_intfs;
     } else {
-        for(copied = 0; (copied < num_audio_intfs) && (copied < requested);
-                                                               copied++) {
-            dev_obj = device_list[copied];
+        list_for_each_safe(dev_node, temp, &device_list) {
+            dev_obj = node_to_item(dev_node, struct device_obj, list_node);
             strlcpy(aif_list[copied].aif_name, dev_obj->name,
-                                          AIF_NAME_MAX_LEN );
+                                          AIF_NAME_MAX_LEN);
             aif_list[copied].dir = dev_obj->hw_ep_info.dir;
+            copied++;
+            if (copied == requested)
+                break;
         }
         *audio_intfs = copied;
     }
@@ -483,14 +487,24 @@
 
 int device_get_obj(uint32_t device_idx, struct device_obj **dev_obj)
 {
+    int i = 0;
+    struct listnode *dev_node, *temp;
+    struct device_obj *obj;
+
     if (device_idx > num_audio_intfs) {
         AGM_LOGE("Invalid device_id %u, max_supported device id: %d\n",
                 device_idx, num_audio_intfs);
         return -EINVAL;
     }
 
-    *dev_obj = device_list[device_idx];
-    return 0;
+    list_for_each_safe(dev_node, temp, &device_list) {
+        if (i++ == device_idx) {
+            obj = node_to_item(dev_node, struct device_obj, list_node);
+            *dev_obj = obj;
+            return 0;
+        }
+    }
+    return -EINVAL;
 }
 
 int device_set_media_config(struct device_obj *dev_obj,
@@ -686,6 +700,8 @@
     unsigned int count = 0, i = 0;
     FILE *fp;
     int ret = 0;
+    struct listnode *dev_node, *temp;
+    struct device_obj *dev_obj = NULL;
 
     fp = fopen(PCM_DEVICE_FILE, "r");
     if (!fp) {
@@ -694,20 +710,10 @@
         return -ENODEV;
     }
 
-    while (fgets(buffer, MAX_BUF_SIZE - 1, fp) != NULL)
-        num_audio_intfs++;
-
-    device_list = calloc (num_audio_intfs, sizeof(struct device_obj*));
-    if (!device_list) {
-        ret = -ENOMEM;
-        goto close_file;
-    }
-
-    rewind(fp);
-
+    list_init(&device_list);
     while (fgets(buffer, MAX_BUF_SIZE - 1, fp) != NULL)
     {
-        struct device_obj *dev_obj = calloc(1, sizeof(struct device_obj));
+        dev_obj = calloc(1, sizeof(struct device_obj));
 
         if (!dev_obj) {
             AGM_LOGE("failed to allocate device_obj mem\n");
@@ -737,7 +743,7 @@
         }
 
         pthread_mutex_init(&dev_obj->lock, (const pthread_mutexattr_t *) NULL);
-        device_list[count] = dev_obj;
+        list_add_tail(&device_list, &dev_obj->list_node);
         count++;
         dev_obj = NULL;
     }
@@ -754,12 +760,14 @@
     goto close_file;
 
 free_device:
-    for (i = 0; i < num_audio_intfs; i++) {
-        if (device_list[i])
-            free(device_list[i]);
+    list_for_each_safe(dev_node, temp, &device_list) {
+        dev_obj = node_to_item(dev_node, struct device_obj, list_node);
+        list_remove(dev_node);
+        free(dev_obj);
+        dev_obj = NULL;
     }
-    if (device_list)
-       free(device_list);
+
+    list_remove(&device_list);
 close_file:
     fclose(fp);
     return ret;
@@ -787,10 +795,13 @@
 {
     unsigned int list_count = 0;
     struct device_obj *dev_obj = NULL;
+    struct listnode *dev_node, *temp;
 
     AGM_LOGE("device deinit called\n");
-    for (list_count = 0; list_count < num_audio_intfs; list_count++) {
-        dev_obj = device_list[list_count];
+    list_for_each_safe(dev_node, temp, &device_list) {
+        dev_obj = node_to_item(dev_node, struct device_obj, list_node);
+        list_remove(dev_node);
+
         metadata_free(&dev_obj->metadata);
 
         if (dev_obj->params)
@@ -799,6 +810,8 @@
         free(dev_obj);
         dev_obj = NULL;
     }
+
+    list_remove(&device_list);
     if (sysfs_fd >= 0)
         close(sysfs_fd);
     sysfs_fd = -1;
@@ -810,7 +823,4 @@
     if (mixer)
         mixer_close(mixer);
 #endif
-
-    free(device_list);
-    device_list = NULL;
 }
diff --git a/service/src/graph.c b/service/src/graph.c
index 13e4374..46882a2 100644
--- a/service/src/graph.c
+++ b/service/src/graph.c
@@ -541,6 +541,9 @@
         ret = -ENOMEM;
         goto done;
     }
+
+    metadata_print(meta_data_kv);
+
     list_init(&graph_obj->tagged_mod_list);
     pthread_mutex_init(&graph_obj->lock, (const pthread_mutexattr_t *)NULL);
     if (sess_obj->stream_config.sess_mode == AGM_SESSION_NO_CONFIG)
@@ -658,7 +661,6 @@
 no_config:
     graph_obj->sess_obj = sess_obj;
 
-    metadata_print(meta_data_kv);
     ret = gsl_open((struct gsl_key_vector *)&meta_data_kv->gkv,
                    (struct gsl_key_vector *)&meta_data_kv->ckv,
                    &graph_obj->graph_handle);
@@ -1017,6 +1019,31 @@
     return graph_pause_resume(graph_obj, false);
 }
 
+int graph_suspend(struct graph_obj *graph_obj)
+{
+    int ret = 0;
+
+    if (graph_obj == NULL) {
+        AGM_LOGE("invalid graph object\n");
+        return -EINVAL;
+    }
+
+    pthread_mutex_lock(&graph_obj->lock);
+    AGM_LOGD("entry graph_handle %p\n", graph_obj->graph_handle);
+
+    ret = gsl_ioctl(graph_obj->graph_handle, GSL_CMD_SUSPEND, NULL, 0);
+    if (ret !=0) {
+        ret = ar_err_get_lnx_err_code(ret);
+        AGM_LOGE("graph_suspend failed %d\n", ret);
+        goto done;
+    }
+
+done:
+    pthread_mutex_unlock(&graph_obj->lock);
+    AGM_LOGD("exit\n");
+    return ret;
+}
+
 int graph_set_config(struct graph_obj *graph_obj, void *payload,
                      size_t payload_size)
 {
@@ -1793,6 +1820,11 @@
     int ret = -EINVAL;
     struct agm_buffer_config buffer_config = {0};
 
+    if (graph_obj == NULL) {
+        AGM_LOGE("invalid graph object");
+        return -EINVAL;
+    }
+
     sess_obj = graph_obj->sess_obj;
     if (sess_obj == NULL) {
         AGM_LOGE("invalid sess object");
diff --git a/service/src/graph_module.c b/service/src/graph_module.c
index f899da1..4c7e954 100644
--- a/service/src/graph_module.c
+++ b/service/src/graph_module.c
@@ -926,7 +926,7 @@
                         (channels * bits);
 
         if (samples_per_msec &&
-            (((frame_size/samples_per_msec) * samples_per_msec) != frame_size)) {
+            (((frame_size * 1000) % sess_obj->in_media_config.rate) != 0)) {
             AGM_LOGD("pcm encoder: frame_size %d\n", frame_size);
             ret = configure_pcm_encoder_frame_size(mod, graph_obj, frame_size);
         }
diff --git a/service/src/session_obj.c b/service/src/session_obj.c
index f8fcf46..59a9aa0 100644
--- a/service/src/session_obj.c
+++ b/service/src/session_obj.c
@@ -1837,7 +1837,9 @@
     goto done;
 
 unwind:
+    aif_obj->state = AIF_CLOSE;
     session_disconnect_aif(sess_obj, aif_obj, opened_count);
+    opened_count--;
 
 done:
     pthread_mutex_unlock(&sess_obj->lock);
@@ -2055,6 +2057,22 @@
     return ret;
 }
 
+int session_obj_suspend(struct session_obj *sess_obj)
+{
+    int ret = 0;
+
+    pthread_mutex_lock(&sess_obj->lock);
+
+    ret = graph_suspend(sess_obj->graph);
+    if (ret) {
+        AGM_LOGE("Error:%d suspending graph\n", ret);
+    }
+
+done:
+    pthread_mutex_unlock(&sess_obj->lock);
+    return ret;
+}
+
 int session_obj_read(struct session_obj *sess_obj, void *buff, size_t *count)
 {
     int ret = 0;
@@ -2346,7 +2364,7 @@
 
 int session_obj_write_with_metadata(struct session_obj *sess_obj,
                                     struct agm_buff *buffer,
-                                    uint32_t *consumed_size)
+                                    size_t *consumed_size)
 {
     int ret = 0;