Merge "AGM: lock device object before metadata merge"
diff --git a/service/src/session_obj.c b/service/src/session_obj.c
index dfb98bc..3b681f4 100644
--- a/service/src/session_obj.c
+++ b/service/src/session_obj.c
@@ -152,8 +152,10 @@
                 AGM_LOGD("ignore closed AIF node");
                 continue;
             }
+            pthread_mutex_lock(&aif_node->dev_obj->lock);
             merged = metadata_merge(4, temp, &sess_obj->sess_meta,
                            &aif_node->sess_aif_meta, &aif_node->dev_obj->metadata);
+            pthread_mutex_unlock(&aif_node->dev_obj->lock);
             if (temp) {
                 metadata_free(temp);
                 free(temp);
@@ -459,7 +461,9 @@
         goto done;
     }
 
+    pthread_mutex_lock(&dev_obj->lock);
     merged_metadata = metadata_merge(2, capture_metadata, &dev_obj->metadata);
+    pthread_mutex_unlock(&dev_obj->lock);
     if (!merged_metadata) {
         ret = -ENOMEM;
         AGM_LOGE("Error:%d, merging metadata with capture \
@@ -501,8 +505,10 @@
     struct agm_meta_data_gsl temp = {0};
     struct graph_obj *graph = sess_obj->graph;
 
+    pthread_mutex_lock(&aif_obj->dev_obj->lock);
     merged_metadata = metadata_merge(3, &sess_obj->sess_meta,
                       &aif_obj->sess_aif_meta, &aif_obj->dev_obj->metadata);
+    pthread_mutex_unlock(&aif_obj->dev_obj->lock);
     if (!merged_metadata) {
         AGM_LOGE("No memory to create merged_metadata session_id: %d, \
                       audio interface id:%d \n",
@@ -515,8 +521,10 @@
     if (opened_count == 1) {
         //this is SSSD condition, hence stop just the stream/stream-device,
         //merged only sess-aif, aif
+        pthread_mutex_lock(&aif_obj->dev_obj->lock);
         merged_meta_sess_aif = metadata_merge(2, &aif_obj->sess_aif_meta,
                                             &aif_obj->dev_obj->metadata);
+        pthread_mutex_unlock(&aif_obj->dev_obj->lock);
         if (!merged_meta_sess_aif) {
             AGM_LOGE("No memory to create merged_metadata session_id: %d, \
                           audio interface id:%d \n",
@@ -669,8 +677,10 @@
     struct graph_obj *graph = sess_obj->graph;
 
     //step 2.a  merge metadata
+    pthread_mutex_lock(&aif_obj->dev_obj->lock);
     merged_metadata = metadata_merge(3, &sess_obj->sess_meta,
                          &aif_obj->sess_aif_meta, &aif_obj->dev_obj->metadata);
+    pthread_mutex_unlock(&aif_obj->dev_obj->lock);
     if (!merged_metadata) {
         AGM_LOGE("Error merging metadata session_id:%d aif_id:%d\n",
             sess_obj->sess_id, aif_obj->aif_id);
@@ -991,7 +1001,6 @@
         }
 
         if (dir == TX) {
-
             // For loopback, check if the playback session is in STARTED state,
             //otherwise return failure
             if (sess_obj->loopback_state == true) {
@@ -1039,24 +1048,63 @@
         }
 
         pthread_mutex_lock(&hwep_lock);
+
+        //For Slimbus 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);
+            if (!aif_obj) {
+                AGM_LOGE("Error:%d could not find aif node\n", ret);
+                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->state == AIF_OPENED || aif_obj->state == AIF_STOPPED) {
+                    ret = device_prepare(aif_obj->dev_obj);
+                    if (ret) {
+                        AGM_LOGE("Error:%d preparing device\n", ret);
+                        goto device_stop;
+                    }
+                    aif_obj->state = AIF_PREPARED;
+                }
+
+                if (aif_obj->state == AIF_OPENED || aif_obj->state == AIF_PREPARED ||
+                                                     aif_obj->state == AIF_STOPPED ) {
+                    ret = device_start(aif_obj->dev_obj);
+                    if (ret) {
+                        AGM_LOGE("Error:%d starting device id:%d\n",
+                                       ret, aif_obj->aif_id);
+                        goto device_stop;
+                    }
+                    aif_obj->state = AIF_STARTED;
+                }
+            }
+        }
+
         ret = graph_start(sess_obj->graph);
         if (ret) {
             AGM_LOGE("Error:%d starting graph\n", ret);
-            pthread_mutex_unlock(&hwep_lock);
-            goto done;
+            goto device_stop;
         }
 
         list_for_each(node, &sess_obj->aif_pool) {
             aif_obj = node_to_item(node, struct aif, node);
             if (!aif_obj) {
                 AGM_LOGE("Error:%d could not find aif node\n", ret);
+                pthread_mutex_unlock(&hwep_lock);
                 goto unwind;
             }
 
+            //Continue/SKIP for SLIMBUS EP as they are started early.
+            if (aif_obj->dev_obj->hw_ep_info.intf == SLIMBUS)
+                continue;
+
             if (aif_obj->state == AIF_OPENED || aif_obj->state == AIF_STOPPED) {
                 ret = device_prepare(aif_obj->dev_obj);
                 if (ret) {
                     AGM_LOGE("Error:%d preparing device\n", ret);
+                    pthread_mutex_unlock(&hwep_lock);
                     goto unwind;
                 }
                 aif_obj->state = AIF_PREPARED;
@@ -1068,14 +1116,13 @@
                 if (ret) {
                     AGM_LOGE("Error:%d starting device id:%d\n",
                                    ret, aif_obj->aif_id);
+                    pthread_mutex_unlock(&hwep_lock);
                     goto unwind;
                 }
                 aif_obj->state = AIF_STARTED;
             }
         }
         pthread_mutex_unlock(&hwep_lock);
-
-
     } else {
         ret = graph_start(sess_obj->graph);
         if (ret) {
@@ -1088,10 +1135,9 @@
     goto done;
 
 unwind:
-
     pthread_mutex_lock(&hwep_lock);
     graph_stop(sess_obj->graph, NULL);
-
+device_stop:
     if (sess_mode != AGM_SESSION_NON_TUNNEL  && sess_mode != AGM_SESSION_NO_CONFIG) {
         list_for_each(node, &sess_obj->aif_pool) {
             aif_obj = node_to_item(node, struct aif, node);
@@ -1426,8 +1472,10 @@
             goto done;
         }
 
+        pthread_mutex_lock(&aif_obj->dev_obj->lock);
         merged_metadata = metadata_merge(3, &sess_obj->sess_meta,
                           &aif_obj->sess_aif_meta, &aif_obj->dev_obj->metadata);
+        pthread_mutex_unlock(&aif_obj->dev_obj->lock);
         if (!merged_metadata) {
             AGM_LOGE("Error merging metadata session_id:%d aif_id:%d\n",
                 sess_obj->sess_id, aif_obj->aif_id);
@@ -1502,8 +1550,10 @@
         goto error;
     }
 
+    pthread_mutex_lock(&aif_obj->dev_obj->lock);
     merged_metadata = metadata_merge(3, &sess_obj->sess_meta,
                         &aif_obj->sess_aif_meta, &aif_obj->dev_obj->metadata);
+    pthread_mutex_unlock(&aif_obj->dev_obj->lock);
 
     if (!merged_metadata) {
         AGM_LOGE("Error merging metadata session_id:%d aif_id:%d\n",
@@ -1579,8 +1629,10 @@
         metadata_update_cal(&aif_obj->sess_aif_meta, &ckv);
         metadata_update_cal(&aif_obj->dev_obj->metadata, &ckv);
 
+        pthread_mutex_lock(&aif_obj->dev_obj->lock);
         merged_metadata = metadata_merge(3, &sess_obj->sess_meta,
                           &aif_obj->sess_aif_meta, &aif_obj->dev_obj->metadata);
+        pthread_mutex_unlock(&aif_obj->dev_obj->lock);
         if (!merged_metadata) {
             AGM_LOGE("Error merging metadata session_id:%d aif_id:%d\n",
                 sess_obj->sess_id, aif_obj->aif_id);
@@ -1689,8 +1741,10 @@
                 goto done;
             }
 
+            pthread_mutex_lock(&aif_obj->dev_obj->lock);
             merged_metadata = metadata_merge(3, &sess_obj->sess_meta,
                                 &aif_obj->sess_aif_meta, &aif_obj->dev_obj->metadata);
+            pthread_mutex_unlock(&aif_obj->dev_obj->lock);
             if (!merged_metadata) {
                 AGM_LOGE("Error merging metadata session_id:%d aif_id:%d\n",
                     sess_obj->sess_id, aif_obj->aif_id);