Merge "AGM: lock device object before metadata merge"
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 337d5bc..a0b41b6 100644
--- a/ipc/HwBinders/agm_ipc_service/src/agm_server_wrapper.cpp
+++ b/ipc/HwBinders/agm_ipc_service/src/agm_server_wrapper.cpp
@@ -36,6 +36,8 @@
 #include <hwbinder/IPCThreadState.h>
 
 #define MAX_CACHE_SIZE 64
+#define NUM_GKV(x)                     (*((uint32_t *) x))
+
 using AgmCallbackData = ::vendor::qti::hardware::AGMIPC::V1_0::implementation::clbk_data;
 using AgmServerCallback = ::vendor::qti::hardware::AGMIPC::V1_0::implementation::SrvrClbk;
 
@@ -48,8 +50,10 @@
 typedef struct {
    struct listnode list;
    uint32_t session_id;
+   pthread_mutex_t handle_lock;
    uint64_t handle;
    std::vector<std::pair<int, int>> shared_mem_fd_list;
+   std::vector<int> aif_id_list;
 } agm_client_session_handle;
 
 typedef struct {
@@ -65,7 +69,7 @@
     ALOGI("Client died (pid): %llu",(unsigned long long) cookie);
     struct listnode *node = NULL;
     struct listnode *tempnode = NULL;
-    agm_client_session_handle *hndl = NULL;
+    agm_client_session_handle *session_handle = NULL;
     client_info *handle = NULL;
     struct listnode *sess_node = NULL;
     struct listnode *sess_tempnode = NULL;
@@ -96,13 +100,34 @@
             ALOGV("%s: MATCHED pid = %llu\n", __func__, (unsigned long long) cookie);
             list_for_each_safe(sess_node, sess_tempnode,
                                       &handle->agm_client_hndl_list) {
-                hndl = node_to_item(sess_node, agm_client_session_handle, list);
-                if (hndl->handle) {
-                    agm_session_close(hndl->handle);
-                    list_remove(sess_node);
-                    hndl->shared_mem_fd_list.clear();
-                    free(hndl);
+                session_handle = node_to_item(sess_node, agm_client_session_handle, list);
+                pthread_mutex_lock(&session_handle->handle_lock);
+                if (session_handle->handle) {
+                    pthread_mutex_unlock(&client_list_lock);
+                    agm_session_close(session_handle->handle);
+                    pthread_mutex_lock(&client_list_lock);
                 }
+                session_handle->shared_mem_fd_list.clear();
+                for (const auto & aif_id : session_handle->aif_id_list) {
+                    agm_session_aif_set_params(session_handle->session_id,
+                                      aif_id, NULL, 0);
+                    /* AGM session close disconnects the backend,
+                       if handle is not present, disconnect explicitly */
+                    if (!session_handle->handle)
+                        agm_session_aif_connect(session_handle->session_id, aif_id, false);
+                    agm_session_aif_set_metadata(session_handle->session_id, aif_id, 0, NULL);
+                }
+                session_handle->handle = 0;
+                pthread_mutex_unlock(&session_handle->handle_lock);
+
+                agm_session_set_metadata(session_handle->session_id, 0, NULL);
+                agm_session_set_params(session_handle->session_id, NULL, 0);
+
+                session_handle->aif_id_list.clear();
+                pthread_mutex_destroy(&session_handle->handle_lock);
+                list_remove(sess_node);
+                free(session_handle);
+                session_handle = NULL;
             }
             list_remove(node);
             free(handle);
@@ -116,7 +141,7 @@
 {
     struct listnode *node = NULL;
     struct listnode *tempnode = NULL;
-    agm_client_session_handle *hndle = NULL;
+    agm_client_session_handle *session_handle = NULL;
     client_info *handle = NULL;
     struct listnode *sess_node = NULL;
     struct listnode *sess_tempnode = NULL;
@@ -127,71 +152,137 @@
         handle = node_to_item(node, client_info, list);
         list_for_each_safe(sess_node, sess_tempnode,
                                      &handle->agm_client_hndl_list) {
-            hndle = node_to_item(sess_node,
+            session_handle = node_to_item(sess_node,
                                      agm_client_session_handle,
                                      list);
-            if (hndle->handle == sess_handle) {
-                if (hndle->shared_mem_fd_list.size() > MAX_CACHE_SIZE) {
-                    ALOGE("%s cache limit exceeded handle %p [input %d - dup %d] ",
+            if (session_handle->handle == sess_handle) {
+                if (session_handle->shared_mem_fd_list.size() > MAX_CACHE_SIZE) {
+                    ALOGE("%s cache limit exceeded handle %llx [input %d - dup %d] ",
                             __func__ , sess_handle, input_fd, dup_fd );
                 }
-                hndle->shared_mem_fd_list.push_back(std::make_pair(input_fd, dup_fd));
-                ALOGV("sess_handle %x, session_id:%d input_fd %d, dup fd %d", hndle->handle,
-                       hndle->session_id, input_fd, dup_fd);
+                session_handle->shared_mem_fd_list.push_back(std::make_pair(input_fd, dup_fd));
+                ALOGV("sess_handle %x, session_id:%d input_fd %d, dup fd %d", session_handle->handle,
+                       session_handle->session_id, input_fd, dup_fd);
             }
          }
     }
     pthread_mutex_unlock(&client_list_lock);
 }
 
-static void add_handle_to_list(uint32_t session_id, uint64_t handle)
+static client_info* get_client_handle_l(int pid)
 {
     struct listnode *node = NULL;
     client_info *client_handle = NULL;
-    client_info *client_handle_temp = NULL;
-    agm_client_session_handle *hndl = NULL;
-    int pid = ::android::hardware::IPCThreadState::self()->getCallingPid();
-    int flag = 0;
 
-    pthread_mutex_lock(&client_list_lock);
     list_for_each(node, &client_list) {
-        client_handle_temp = node_to_item(node, client_info, list);
-        if (client_handle_temp->pid == pid) {
-            hndl = (agm_client_session_handle *)
-                               calloc(1, sizeof(agm_client_session_handle));
-            if (hndl == NULL) {
-                ALOGE("%s: Cannot allocate memory for agm handle\n", __func__);
+        client_handle = node_to_item(node, client_info, list);
+        if (client_handle->pid == pid)
+            goto exit;
+    }
+
+    client_handle = (client_info *)calloc(1, sizeof(client_info));
+    if (client_handle == NULL) {
+        ALOGE("%s: Cannot allocate memory for client handle\n", __func__);
+        goto exit;
+    }
+    client_handle->pid = pid;
+    list_add_tail(&client_list, &client_handle->list);
+    list_init(&client_handle->agm_client_hndl_list);
+exit:
+    return client_handle;
+}
+
+static agm_client_session_handle* get_session_handle_l(uint32_t session_id)
+{
+    struct listnode *node = NULL;
+    agm_client_session_handle *session_handle = NULL;
+    client_info *client_handle = NULL;
+    int pid = ::android::hardware::IPCThreadState::self()->getCallingPid();
+
+    client_handle = get_client_handle_l(pid);
+    if (!client_handle) {
+        ALOGE("Client handle in NULL, unable to add session %d", session_id);
+        goto exit;
+    }
+
+    list_for_each(node, &client_handle->agm_client_hndl_list) {
+        session_handle = node_to_item(node,
+                                     agm_client_session_handle,
+                                     list);
+            if (session_handle->session_id == session_id) {
                 goto exit;
             }
-            hndl->handle = handle;
-            hndl->session_id = session_id;
-            ALOGV("%s: Adding session id %d and handle %x to client handle list \n", __func__, session_id, handle);
-            list_add_tail(&client_handle_temp->agm_client_hndl_list, &hndl->list);
-            flag = 1;
-            break;
+    }
+    session_handle = (agm_client_session_handle *)calloc(1, sizeof(agm_client_session_handle));
+    if (session_handle == NULL) {
+        ALOGE("%s: Cannot allocate memory to store agm session handle\n", __func__);
+        goto exit;
+    }
+    pthread_mutex_init(&session_handle->handle_lock, (const pthread_mutexattr_t *) NULL);
+    session_handle->session_id = session_id;
+    list_add_tail(&client_handle->agm_client_hndl_list, &session_handle->list);
+    ALOGV("%s: Adding session id %d to client session list", __func__, session_id);
+exit:
+    return session_handle;
+}
+
+static void add_session_to_list_l(uint32_t session_id)
+{
+    agm_client_session_handle *session_handle = NULL;
+
+
+    session_handle = get_session_handle_l(session_id);
+    if (!session_handle) {
+        ALOGE("session handle in NULL, unable to add session %d", session_id);
+        return;
+    }
+}
+
+static void add_session_aif_to_list_l(uint32_t session_id, uint64_t aif_id)
+{
+    agm_client_session_handle *session_handle = NULL;
+
+    session_handle = get_session_handle_l(session_id);
+    if (!session_handle) {
+        ALOGE("session handle in NULL, unable to add session %d", session_id);
+        return;
+    }
+    for (const auto & avail_aif_id : session_handle->aif_id_list) {
+        if (avail_aif_id == aif_id) {
+            ALOGD("Aif id %d already added to session list of %d", aif_id, session_id);
+            return;
         }
     }
-    if (flag == 0) {
-        client_handle = (client_info *)calloc(1, sizeof(client_info));
-        if (client_handle == NULL) {
-            ALOGE("%s: Cannot allocate memory for client handle\n", __func__);
-            goto exit;
-        }
-        client_handle->pid = pid;
-        list_add_tail(&client_list, &client_handle->list);
-        list_init(&client_handle->agm_client_hndl_list);
-        hndl = (agm_client_session_handle *)calloc(1, sizeof(agm_client_session_handle));
-        if (hndl == NULL) {
-            ALOGE("%s: Cannot allocate memory to store agm session handle\n", __func__);
-            goto exit;
-        }
-        hndl->handle = handle;
-        hndl->session_id = session_id;
-        ALOGV("%s: Adding session id %d and handle %x to client handle list \n", __func__, session_id, handle);
-        list_add_tail(&client_handle->agm_client_hndl_list, &hndl->list);
+    session_handle->aif_id_list.push_back(aif_id);
+}
+
+static void remove_session_aif_from_list_l(uint32_t session_id, uint64_t aif_id)
+{
+    agm_client_session_handle *session_handle = NULL;
+
+    session_handle = get_session_handle_l(session_id);
+    if (!session_handle) {
+        ALOGE("session handle in NULL, unable to get session %d", session_id);
+        return;
     }
-exit :
-        pthread_mutex_unlock(&client_list_lock);
+
+    auto iter = std::find(session_handle->aif_id_list.begin(), session_handle->aif_id_list.end(), aif_id);
+    if (iter != session_handle->aif_id_list.end()) {
+        session_handle->aif_id_list.erase(iter);
+    }
+}
+
+static void add_session_handle_to_list_l(uint32_t session_id, uint64_t handle)
+{
+    agm_client_session_handle *session_handle = NULL;
+
+    session_handle = get_session_handle_l(session_id);
+    if (!session_handle) {
+        ALOGE("session handle in NULL, unable to add session %d", session_id);
+        return;
+    }
+    session_handle->handle = handle;
+    ALOGV("%s: Adding session id %d and handle %x to client handle list \n", __func__, session_id, handle);
 }
 
 namespace vendor {
@@ -402,6 +493,10 @@
         return -ENOMEM;
     }
     memcpy(metadata_l, metadata.data(), size);
+    pthread_mutex_lock(&client_list_lock);
+    if (NUM_GKV(metadata_l))
+        add_session_to_list_l(session_id);
+    pthread_mutex_unlock(&client_list_lock);
     ret = agm_session_set_metadata(session_id, size, metadata_l);
     free(metadata_l);
     return ret;
@@ -421,6 +516,11 @@
         return -ENOMEM;
     }
     memcpy(metadata_l, metadata.data(), size);
+    pthread_mutex_lock(&client_list_lock);
+    if (NUM_GKV(metadata_l))
+        add_session_aif_to_list_l(session_id, aif_id);
+    pthread_mutex_unlock(&client_list_lock);
+
     ret = agm_session_aif_set_metadata(session_id, aif_id, size, metadata_l);
     free(metadata_l);
     return ret;
@@ -431,6 +531,13 @@
                                                  bool state) {
     ALOGV("%s : session_id = %d, aif_id =%d, state = %s\n", __func__,
                           session_id, aif_id, state ? "true" : "false");
+    pthread_mutex_lock(&client_list_lock);
+    if (state)
+        add_session_aif_to_list_l(session_id, aif_id);
+    else
+        remove_session_aif_from_list_l(session_id, aif_id);
+    pthread_mutex_unlock(&client_list_lock);
+
     return agm_session_aif_connect(session_id, aif_id, state);
 }
 
@@ -657,17 +764,32 @@
 Return<void> AGM::ipc_agm_session_open(uint32_t session_id,
                                        AgmSessionMode sess_mode,
                                        ipc_agm_session_open_cb _hidl_cb) {
-    uint64_t handle;
+    uint64_t handle = 0;
+    agm_client_session_handle *session_handle = NULL;
+    hidl_vec<uint64_t> handle_ret;
+    int32_t ret = -EINVAL;
     enum agm_session_mode session_mode = (enum agm_session_mode) sess_mode;
+
     ALOGV("%s: session_id=%d session_mode=%d\n", __func__, session_id,
               session_mode);
-    int32_t ret = agm_session_open(session_id, session_mode, &handle);
-    hidl_vec<uint64_t> handle_ret;
     handle_ret.resize(sizeof(uint64_t));
+    pthread_mutex_lock(&client_list_lock);
+    session_handle = get_session_handle_l(session_id);
+    pthread_mutex_unlock(&client_list_lock);
+    if (!session_handle) {
+        *handle_ret.data() = handle;
+        goto exit;
+    }
+
+    pthread_mutex_lock(&session_handle->handle_lock);
+    ret = agm_session_open(session_id, session_mode, &handle);
     *handle_ret.data() = handle;
-    _hidl_cb(ret, handle_ret);
     if (!ret)
-        add_handle_to_list(session_id, handle);
+        add_session_handle_to_list_l(session_id, handle);
+
+    pthread_mutex_unlock(&session_handle->handle_lock);
+exit:
+    _hidl_cb(ret, handle_ret);
     ALOGV("%s : handle received is : %llx",__func__, (unsigned long long) handle);
     return Void();
 }
@@ -724,7 +846,7 @@
     ALOGV("%s called with handle = %llx \n", __func__, (unsigned long long) hndl);
     struct listnode *node = NULL;
     struct listnode *tempnode = NULL;
-    agm_client_session_handle *hndle = NULL;
+    agm_client_session_handle *session_handle = NULL;
     client_info *handle = NULL;
     struct listnode *sess_node = NULL;
     struct listnode *sess_tempnode = NULL;
@@ -738,15 +860,24 @@
 
         list_for_each_safe(sess_node, sess_tempnode,
                                   &handle->agm_client_hndl_list) {
-            hndle = node_to_item(sess_node,
+            session_handle = node_to_item(sess_node,
                                  agm_client_session_handle,
                                  list);
-           if (hndle->handle == hndl) {
+           pthread_mutex_lock(&session_handle->handle_lock);
+           if (session_handle->handle == hndl) {
+               session_handle->handle = 0;
+               pthread_mutex_unlock(&session_handle->handle_lock);
+               session_handle->shared_mem_fd_list.clear();
+               session_handle->aif_id_list.clear();
+               pthread_mutex_destroy(&session_handle->handle_lock);
                list_remove(sess_node);
-               free(hndle);
-           }
-       }
+               free(session_handle);
+               goto done;
+            }
+           pthread_mutex_unlock(&session_handle->handle_lock);
+        }
     }
+done:
     pthread_mutex_unlock(&client_list_lock);
     return agm_session_close(hndl);
 }
@@ -914,8 +1045,10 @@
     if (mDeathNotifier == NULL)
         mDeathNotifier = new client_death_notifier();
 
-    cb->linkToDeath(mDeathNotifier, pid);
-    client_handle->clbk_binder = cb;
+    if (!client_handle->clbk_binder) {
+        cb->linkToDeath(mDeathNotifier, pid);
+        client_handle->clbk_binder = cb;
+    }
     pthread_mutex_unlock(&client_list_lock);
     return 0;
 }
diff --git a/plugins/tinyalsa/Makefile.am b/plugins/tinyalsa/Makefile.am
index 4f569b0..c82e5f2 100644
--- a/plugins/tinyalsa/Makefile.am
+++ b/plugins/tinyalsa/Makefile.am
@@ -6,11 +6,10 @@
 
 AM_CFLAGS := -Wno-unused-parameter
 if !BUILDSYSTEM_OPENWRT
-AM_CFLAGS += -I $(top_srcdir)/include -I $(PKG_CONFIG_SYSROOT_DIR)/usr/include/agm/
-AM_CFLAGS += $(GLIB_CFLAGS) -Dstrlcpy=g_strlcpy -Dstrlcat=g_strlcat
+AM_CFLAGS += -I $(top_srcdir)/include @AGM_CFLAGS@
+AM_CFLAGS += @GLIB_CFLAGS@ -Dstrlcpy=g_strlcpy -Dstrlcat=g_strlcat
 AM_CFLAGS += -D__unused=__attribute__\(\(__unused__\)\) -DLINUX_ENABLED
-AM_CFLAGS += -I $(PKG_CONFIG_SYSROOT_DIR)/usr/include/sndparser/
-AM_CFLAGS += -I $(PKG_CONFIG_SYSROOT_DIR)/usr/include/
+AM_CFLAGS += @SNDPARSER_CFLAGS@
 AM_CFLAGS += -Wno-unused-parameter
 AM_CFLAGS += -DDYNAMIC_LOG_ENABLED
 
diff --git a/plugins/tinyalsa/configure.ac b/plugins/tinyalsa/configure.ac
index 17dd6e5..079242d 100644
--- a/plugins/tinyalsa/configure.ac
+++ b/plugins/tinyalsa/configure.ac
@@ -40,6 +40,13 @@
 
 AM_CONDITIONAL(USE_GLIB, test "x${with_glib}" = "xyes")
 
+# Checks for libraries
+PKG_CHECK_MODULES([AGM], [agm])
+AC_SUBST([AGM_CFLAGS])
+
+PKG_CHECK_MODULES([SNDPARSER], [sndparser])
+AC_SUBST([SNDPARSER_CFLAGS])
+
 AC_ARG_WITH([openwrt],
     AS_HELP_STRING([use openwrt (default is no)]),
     [with_openwrt=$withval],
diff --git a/plugins/tinyalsa/test/Makefile.am b/plugins/tinyalsa/test/Makefile.am
index 6055d92..0b22057 100644
--- a/plugins/tinyalsa/test/Makefile.am
+++ b/plugins/tinyalsa/test/Makefile.am
@@ -6,8 +6,8 @@
 if !BUILDSYSTEM_OPENWRT
 AM_CFLAGS += -I $(PKG_CONFIG_SYSROOT_DIR)/usr/include/
 endif
-AM_CFLAGS += $(GLIB_CFLAGS) -Dstrlcpy=g_strlcpy -Dstrlcat=g_strlcat -include glib.h
-AM_CFLAGS += -I $(PKG_CONFIG_SYSROOT_DIR)/usr/include/acdbdata
+AM_CFLAGS += @GLIB_CFLAGS@ -Dstrlcpy=g_strlcpy -Dstrlcat=g_strlcat -include glib.h
+AM_CFLAGS += @MMHEADERS_CFLAGS@
 
 AM_CFLAGS += -DBACKEND_CONF_FILE=\"/etc/backend_conf.xml\"
 
@@ -53,3 +53,8 @@
 
 agmvoiceui_la_CFLAGS := $(AM_CFLAGS)
 agmvoiceui_LDADD    := -lpthread -ltinyalsa libagmmixer.la
+# install xml files under /etc
+root_etcdir      = "/etc"
+root_etc_SCRIPTS = backend_conf.xml
+install-data-hook:
+	chmod  go-x $(DESTDIR)$(root_etcdir)/backend_conf.xml
diff --git a/plugins/tinyalsa/test/agmtest.pc.in b/plugins/tinyalsa/test/agmtest.pc.in
index c489de4..f7c36f8 100644
--- a/plugins/tinyalsa/test/agmtest.pc.in
+++ b/plugins/tinyalsa/test/agmtest.pc.in
@@ -7,4 +7,4 @@
 Description: agm test tool
 Version: @VERSION@
 Libs: -L${libdir}
-Cflags: -I${includedir}
+Cflags: -I${includedir}/agmtest
diff --git a/plugins/tinyalsa/test/configure.ac b/plugins/tinyalsa/test/configure.ac
index 8b1e241..058e8ad 100644
--- a/plugins/tinyalsa/test/configure.ac
+++ b/plugins/tinyalsa/test/configure.ac
@@ -39,6 +39,10 @@
 
 AM_CONDITIONAL(USE_GLIB, test "x${with_glib}" = "xyes")
 
+# Checks for libraries
+PKG_CHECK_MODULES([MMHEADERS], [mm-audio-headers])
+AC_SUBST([MMHEADERS_CFLAGS])
+
 AC_ARG_WITH([openwrt],
     AS_HELP_STRING([use openwrt (default is no)]),
     [with_openwrt=$withval],
diff --git a/service/Makefile.am b/service/Makefile.am
index fffecd1..1e7458a 100644
--- a/service/Makefile.am
+++ b/service/Makefile.am
@@ -31,10 +31,10 @@
             ${top_srcdir}/inc/private/agm/session_obj.h \
             ${top_srcdir}/inc/private/agm/device.h
 
-AM_CFLAGS = -I $(PKG_CONFIG_SYSROOT_DIR)/usr/include/spf
+AM_CFLAGS = @SPF_CFLAGS@
 AM_CFLAGS += -I ${top_srcdir}/inc/public
 AM_CFLAGS += -I ${top_srcdir}/inc/private
-AM_CFLAGS += -I $(PKG_CONFIG_SYSROOT_DIR)/usr/include/acdbdata
+AM_CFLAGS += @MMHEADERS_CFLAGS@
 AM_CFLAGS += -DDYNAMIC_LOG_ENABLED
 
 library_include_HEADERS = $(h_sources)
@@ -64,5 +64,5 @@
 libagm_la_LIBADD += -lglib-2.0
 endif
 libagm_la_CFLAGS += -D__unused=__attribute__\(\(__unused__\)\)
-libagm_la_CFLAGS += $(GLIB_CFLAGS) -Dstrlcpy=g_strlcpy -Dstrlcat=g_strlcat -include glib.h
+libagm_la_CFLAGS += @GLIB_CFLAGS@ -Dstrlcpy=g_strlcpy -Dstrlcat=g_strlcat -include glib.h
 libagm_la_LDFLAGS = -module -shared -avoid-version
diff --git a/service/agm.pc.in b/service/agm.pc.in
index fa42c75..eeded6d 100644
--- a/service/agm.pc.in
+++ b/service/agm.pc.in
@@ -6,3 +6,5 @@
 Name: agm
 Description: agm library
 Version: @VERSION@
+Libs: -L${libdir}
+Cflags: -I${includedir}/agm
diff --git a/service/configure.ac b/service/configure.ac
index 4434dc6..921f025 100644
--- a/service/configure.ac
+++ b/service/configure.ac
@@ -39,6 +39,13 @@
 
 AM_CONDITIONAL(USE_GLIB, test "x${with_glib}" = "xyes")
 
+# Checks for libraries
+PKG_CHECK_MODULES([SPF], [spf])
+AC_SUBST([SPF_CFLAGS])
+
+PKG_CHECK_MODULES([MMHEADERS], [mm-audio-headers])
+AC_SUBST([MMHEADERS_CFLAGS])
+
 AC_ARG_WITH([openwrt],
     AS_HELP_STRING([use openwrt (default is no)]),
     [with_openwrt=$withval],
diff --git a/service/src/metadata.c b/service/src/metadata.c
index 79c1000..87c0677 100644
--- a/service/src/metadata.c
+++ b/service/src/metadata.c
@@ -268,8 +268,7 @@
     int ret = 0;
 
     if (!metadata) {
-        AGM_LOGE("Invalid metadata passed\n");
-        ret = -EINVAL;
+        AGM_LOGI("NULL metadata passed, ignoring\n");
         return ret;
     }
     dest->gkv.num_kvs = NUM_GKV(metadata);
diff --git a/service/src/session_obj.c b/service/src/session_obj.c
index f375b67..3b681f4 100644
--- a/service/src/session_obj.c
+++ b/service/src/session_obj.c
@@ -1340,6 +1340,9 @@
        sess_obj->params_size = 0;
    }
 
+   if ((size == 0) ||(payload == NULL))
+       goto done;
+
    sess_obj->params = calloc(1, size);
    if (!sess_obj->params) {
        AGM_LOGE("No memory for sess params on sess_id:%d\n",
@@ -1389,6 +1392,9 @@
        aif_obj->params_size = 0;
    }
 
+   if ((size == 0) || (payload == NULL))
+       goto done;
+
    aif_obj->params = calloc(1, size);
    if (!aif_obj->params) {
        AGM_LOGE("No memory for sess_aif params on sess_id:%d, aif_id:%d\n",
diff --git a/snd_parser/Makefile.am b/snd_parser/Makefile.am
index f9d9bb2..da05f67 100644
--- a/snd_parser/Makefile.am
+++ b/snd_parser/Makefile.am
@@ -19,7 +19,13 @@
 
 lib_LTLIBRARIES      = libsndcardparser.la
 libsndcardparser_la_SOURCES   = src/snd-card-parser.c
-libsndcardparser_la_LIBADD = $(GLIB_LIBS) -lexpat -lpthread
+libsndcardparser_la_LIBADD = @GLIB_LIBS@ -lexpat -lpthread
 libsndcardparser_la_CFLAGS := $(AM_CFLAGS)
-libsndcardparser_la_CFLAGS += $(GLIB_CFLAGS) -Dstrlcpy=g_strlcpy -Dstrlcat=g_strlcat -include glib.h
+libsndcardparser_la_CFLAGS += @GLIB_CFLAGS@ -Dstrlcpy=g_strlcpy -Dstrlcat=g_strlcat -include glib.h
 libsndcardparser_la_LDFLAGS   = -avoid-version -shared
+libsndcardparser_la_list   = $(top_srcdir)/configs/$(MACHINE_ENABLED)/card-defs.xml
+#install xml files under /etc
+root_etcdir = "/etc"
+root_etc_SCRIPTS = $(libsndcardparser_la_list)
+install-data-hook:
+	chmod  go+r $(DESTDIR)$(root_etcdir)/card-defs.xml
diff --git a/snd_parser/configs/neo/card-defs.xml b/snd_parser/configs/neo/card-defs.xml
new file mode 100644
index 0000000..d59e669
--- /dev/null
+++ b/snd_parser/configs/neo/card-defs.xml
@@ -0,0 +1,104 @@
+<!--  Copyright (c) 2019-2021, 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  -->
+<!--  met:                                                                    -->
+<!--      * Redistributions of source code must retain the above copyright    -->
+<!--        notice, this list of conditions and the following disclaimer.     -->
+<!--      * Redistributions in binary form must reproduce the above           -->
+<!--        copyright notice, this list of conditions and the following       -->
+<!--        disclaimer in the documentation and/or other materials provided   -->
+<!--        with the distribution.                                            -->
+<!--      * Neither the name of The Linux Foundation nor the names of its     -->
+<!--        contributors may be used to endorse or promote products derived   -->
+<!--        from this software without specific prior written permission.     -->
+<!--                                                                          -->
+<!--  THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED            -->
+<!--  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF    -->
+<!--  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT  -->
+<!--  ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS  -->
+<!--  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR  -->
+<!--  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF    -->
+<!--  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR         -->
+<!--  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,   -->
+<!--  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE    -->
+<!--  OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN  -->
+<!--  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                           -->
+<defs>
+<card>
+    <id>0</id>
+    <name>auroravirtualsndcard</name>
+
+    <pcm-device>
+        <id>100</id>
+        <name>PCM100</name>
+        <pcm_plugin>
+            <so-name>libagm_pcm_passthrough_plugin.so</so-name>
+        </pcm_plugin>
+        <props>
+            <playback>1</playback>
+            <capture>0</capture>
+        </props>
+    </pcm-device>
+
+    <pcm-device>
+        <id>101</id>
+        <name>PCM101</name>
+        <pcm_plugin>
+            <so-name>libagm_pcm_passthrough_plugin.so</so-name>
+        </pcm_plugin>
+        <props>
+            <playback>0</playback>
+            <capture>1</capture>
+        </props>
+    </pcm-device>
+
+    <pcm-device>
+        <id>103</id>
+        <name>PCM103</name>
+        <pcm_plugin>
+            <so-name>libagm_pcm_passthrough_plugin.so</so-name>
+        </pcm_plugin>
+        <props>
+            <playback>1</playback>
+            <capture>0</capture>
+            <hostless>1</hostless>
+        </props>
+    </pcm-device>
+
+    <pcm-device>
+        <id>104</id>
+        <name>PCM104</name>
+        <pcm_plugin>
+            <so-name>libagm_pcm_passthrough_plugin.so</so-name>
+        </pcm_plugin>
+        <props>
+            <playback>0</playback>
+            <capture>1</capture>
+            <hostless>1</hostless>
+        </props>
+    </pcm-device>
+
+    <compress-device>
+        <id>105</id>
+        <name>COMPRESS105</name>
+        <compress_plugin>
+            <so-name>libagm_compress_passthrough_plugin.so</so-name>
+        </compress_plugin>
+        <props>
+            <playback>1</playback>
+            <capture>0</capture>
+            <hostless>0</hostless>
+        </props>
+    </compress-device>
+
+    <mixer>
+        <id>1</id>
+        <name>agm_mixer</name>
+        <mixer_plugin>
+            <so-name>libagm_mixer_passthrough_plugin.so</so-name>
+        </mixer_plugin>
+    </mixer>
+
+</card>
+</defs>
diff --git a/snd_parser/configs/qcs40x/card-defs.xml b/snd_parser/configs/qcs40x/card-defs.xml
new file mode 100644
index 0000000..7002713
--- /dev/null
+++ b/snd_parser/configs/qcs40x/card-defs.xml
@@ -0,0 +1,104 @@
+<!--  Copyright (c) 2019, 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  -->
+<!--  met:                                                                    -->
+<!--      * Redistributions of source code must retain the above copyright    -->
+<!--        notice, this list of conditions and the following disclaimer.     -->
+<!--      * Redistributions in binary form must reproduce the above           -->
+<!--        copyright notice, this list of conditions and the following       -->
+<!--        disclaimer in the documentation and/or other materials provided   -->
+<!--        with the distribution.                                            -->
+<!--      * Neither the name of The Linux Foundation nor the names of its     -->
+<!--        contributors may be used to endorse or promote products derived   -->
+<!--        from this software without specific prior written permission.     -->
+<!--                                                                          -->
+<!--  THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED            -->
+<!--  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF    -->
+<!--  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT  -->
+<!--  ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS  -->
+<!--  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR  -->
+<!--  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF    -->
+<!--  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR         -->
+<!--  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,   -->
+<!--  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE    -->
+<!--  OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN  -->
+<!--  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                           -->
+<defs>
+<card>
+    <id>100</id>
+    <name>qcs405wsasndcard</name>
+
+    <pcm-device>
+        <id>100</id>
+        <name>PCM100</name>
+        <pcm_plugin>
+            <so-name>libagm_pcm_plugin.so</so-name>
+        </pcm_plugin>
+        <props>
+            <playback>1</playback>
+            <capture>0</capture>
+        </props>
+    </pcm-device>
+
+    <pcm-device>
+        <id>101</id>
+        <name>PCM101</name>
+        <pcm_plugin>
+            <so-name>libagm_pcm_plugin.so</so-name>
+        </pcm_plugin>
+        <props>
+            <playback>0</playback>
+            <capture>1</capture>
+        </props>
+    </pcm-device>
+
+    <pcm-device>
+        <id>103</id>
+        <name>PCM103</name>
+        <pcm_plugin>
+            <so-name>libagm_pcm_plugin.so</so-name>
+        </pcm_plugin>
+        <props>
+            <playback>1</playback>
+            <capture>0</capture>
+            <hostless>1</hostless>
+        </props>
+    </pcm-device>
+
+    <pcm-device>
+        <id>104</id>
+        <name>PCM104</name>
+        <pcm_plugin>
+            <so-name>libagm_pcm_plugin.so</so-name>
+        </pcm_plugin>
+        <props>
+            <playback>0</playback>
+            <capture>1</capture>
+            <hostless>1</hostless>
+        </props>
+    </pcm-device>
+
+    <compress-device>
+        <id>105</id>
+        <name>COMPRESS105</name>
+        <compress_plugin>
+            <so-name>libagm_compress_plugin.so</so-name>
+        </compress_plugin>
+        <props>
+            <playback>1</playback>
+            <capture>0</capture>
+            <hostless>0</hostless>
+        </props>
+    </compress-device>
+
+    <mixer>
+        <id>1</id>
+        <name>agm_mixer</name>
+        <mixer_plugin>
+            <so-name>libagm_mixer_plugin.so</so-name>
+        </mixer_plugin>
+    </mixer>
+
+</card>
+</defs>
diff --git a/snd_parser/configs/sxr2130/card-defs.xml b/snd_parser/configs/sxr2130/card-defs.xml
new file mode 100644
index 0000000..f4ab036
--- /dev/null
+++ b/snd_parser/configs/sxr2130/card-defs.xml
@@ -0,0 +1,104 @@
+<!--  Copyright (c) 2019-2021, 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  -->
+<!--  met:                                                                    -->
+<!--      * Redistributions of source code must retain the above copyright    -->
+<!--        notice, this list of conditions and the following disclaimer.     -->
+<!--      * Redistributions in binary form must reproduce the above           -->
+<!--        copyright notice, this list of conditions and the following       -->
+<!--        disclaimer in the documentation and/or other materials provided   -->
+<!--        with the distribution.                                            -->
+<!--      * Neither the name of The Linux Foundation nor the names of its     -->
+<!--        contributors may be used to endorse or promote products derived   -->
+<!--        from this software without specific prior written permission.     -->
+<!--                                                                          -->
+<!--  THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED            -->
+<!--  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF    -->
+<!--  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT  -->
+<!--  ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS  -->
+<!--  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR  -->
+<!--  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF    -->
+<!--  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR         -->
+<!--  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,   -->
+<!--  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE    -->
+<!--  OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN  -->
+<!--  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                           -->
+<defs>
+<card>
+    <id>0</id>
+    <name>konamtpsndcard</name>
+
+    <pcm-device>
+        <id>100</id>
+        <name>PCM100</name>
+        <pcm_plugin>
+            <so-name>libagm_pcm_plugin.so</so-name>
+        </pcm_plugin>
+        <props>
+            <playback>1</playback>
+            <capture>0</capture>
+        </props>
+    </pcm-device>
+
+    <pcm-device>
+        <id>101</id>
+        <name>PCM101</name>
+        <pcm_plugin>
+            <so-name>libagm_pcm_plugin.so</so-name>
+        </pcm_plugin>
+        <props>
+            <playback>0</playback>
+            <capture>1</capture>
+        </props>
+    </pcm-device>
+
+    <pcm-device>
+        <id>103</id>
+        <name>PCM103</name>
+        <pcm_plugin>
+            <so-name>libagm_pcm_plugin.so</so-name>
+        </pcm_plugin>
+        <props>
+            <playback>1</playback>
+            <capture>0</capture>
+            <hostless>1</hostless>
+        </props>
+    </pcm-device>
+
+    <pcm-device>
+        <id>104</id>
+        <name>PCM104</name>
+        <pcm_plugin>
+            <so-name>libagm_pcm_plugin.so</so-name>
+        </pcm_plugin>
+        <props>
+            <playback>0</playback>
+            <capture>1</capture>
+            <hostless>1</hostless>
+        </props>
+    </pcm-device>
+
+    <compress-device>
+        <id>105</id>
+        <name>COMPRESS105</name>
+        <compress_plugin>
+            <so-name>libagm_compress_plugin.so</so-name>
+        </compress_plugin>
+        <props>
+            <playback>1</playback>
+            <capture>0</capture>
+            <hostless>0</hostless>
+        </props>
+    </compress-device>
+
+    <mixer>
+        <id>1</id>
+        <name>agm_mixer</name>
+        <mixer_plugin>
+            <so-name>libagm_mixer_plugin.so</so-name>
+        </mixer_plugin>
+    </mixer>
+
+</card>
+</defs>
diff --git a/snd_parser/configure.ac b/snd_parser/configure.ac
index 8c4196d..5314aea 100644
--- a/snd_parser/configure.ac
+++ b/snd_parser/configure.ac
@@ -17,6 +17,17 @@
 # defines some macros variable to be included by source
 AC_CONFIG_MACRO_DIR([m4])
 
+#basemachine
+AC_MSG_CHECKING([which base machine to use])
+AC_ARG_WITH([basemachine],
+            [AS_HELP_STRING([--with-basemachine],
+            [Specify the base machine])],
+            [machine_selected="$withval"],
+            [machine_selected=none])
+
+AC_MSG_RESULT([$machine_selected])
+AC_SUBST([MACHINE_ENABLED],[$machine_selected])
+
 # Checks for programs.
 AC_PROG_CC
 AM_PROG_CC_C_O
diff --git a/snd_parser/sndparser.pc.in b/snd_parser/sndparser.pc.in
index 7e0d6fa..7f9277d 100644
--- a/snd_parser/sndparser.pc.in
+++ b/snd_parser/sndparser.pc.in
@@ -7,4 +7,4 @@
 Description: sndparser library
 Version: @VERSION@
 Libs: -L${libdir}
-Cflags: -I${includedir}
+Cflags: -I${includedir}/sndparser