Merge "ipc: HwBinders: add check to avoid OOB in ipc_pal_stream_set_device"
diff --git a/Android.mk b/Android.mk
index 232daab..2253871 100644
--- a/Android.mk
+++ b/Android.mk
@@ -33,8 +33,14 @@
 endif
 LOCAL_CPPFLAGS      += -fexceptions -frtti
 
+# Define A2DP_SINK_SUPPORTED for targets other than anorak, and
+# for anorak target that uses Android U
 ifneq ($(TARGET_BOARD_PLATFORM), anorak)
 LOCAL_CFLAGS        += -DA2DP_SINK_SUPPORTED
+else
+ifneq ($(filter 14 U, $(PLATFORM_VERSION)),)
+LOCAL_CFLAGS        += -DA2DP_SINK_SUPPORTED
+endif
 endif
 
 LOCAL_C_INCLUDES := \
diff --git a/Pal.cpp b/Pal.cpp
index 46b3b86..f918fe9 100644
--- a/Pal.cpp
+++ b/Pal.cpp
@@ -256,14 +256,13 @@
         return status;
     }
 
-    rm->lockActiveStream();
+    rm->lockValidStreamMutex();
     if (!rm->isActiveStream(stream_handle)) {
         status = -EINVAL;
-        rm->unlockActiveStream();
+        rm->unlockValidStreamMutex();
         return status;
     }
-
-    rm->unlockActiveStream();
+    rm->unlockValidStreamMutex();
 
     s = reinterpret_cast<Stream *>(stream_handle);
     s->setCachedState(STREAM_IDLE);
@@ -314,30 +313,31 @@
         goto exit;
     }
 
-    s = reinterpret_cast<Stream *>(stream_handle);
-    s->getStreamAttributes(&sAttr);
-    if (sAttr.type == PAL_STREAM_VOICE_UI)
-        rm->handleDeferredSwitch();
-
-    rm->lockActiveStream();
+    rm->lockValidStreamMutex();
     if (!rm->isActiveStream(stream_handle)) {
-        rm->unlockActiveStream();
+        rm->unlockValidStreamMutex();
         status = -EINVAL;
         goto exit;
     }
 
+    s = reinterpret_cast<Stream *>(stream_handle);
     status = rm->increaseStreamUserCounter(s);
     if (0 != status) {
-        rm->unlockActiveStream();
+        rm->unlockValidStreamMutex();
         PAL_ERR(LOG_TAG, "failed to increase stream user count");
         goto exit;
     }
-    rm->unlockActiveStream();
+    rm->unlockValidStreamMutex();
+
+    s->getStreamAttributes(&sAttr);
+    if (sAttr.type == PAL_STREAM_VOICE_UI)
+        rm->handleDeferredSwitch();
+
     status = s->start();
 
-    rm->lockActiveStream();
+    rm->lockValidStreamMutex();
     rm->decreaseStreamUserCounter(s);
-    rm->unlockActiveStream();
+    rm->unlockValidStreamMutex();
 
     if (0 != status) {
         PAL_ERR(LOG_TAG, "stream start failed. status %d", status);
@@ -368,9 +368,9 @@
         goto exit;
     }
 
-    rm->lockActiveStream();
+    rm->lockValidStreamMutex();
     if (!rm->isActiveStream(stream_handle)) {
-        rm->unlockActiveStream();
+        rm->unlockValidStreamMutex();
         status = -EINVAL;
         goto exit;
     }
@@ -378,17 +378,17 @@
     s = reinterpret_cast<Stream *>(stream_handle);
     status = rm->increaseStreamUserCounter(s);
     if (0 != status) {
-        rm->unlockActiveStream();
+        rm->unlockValidStreamMutex();
         PAL_ERR(LOG_TAG, "failed to increase stream user count");
         goto exit;
     }
-    rm->unlockActiveStream();
+    rm->unlockValidStreamMutex();
     s->setCachedState(STREAM_STOPPED);
     status = s->stop();
 
-    rm->lockActiveStream();
+    rm->lockValidStreamMutex();
     rm->decreaseStreamUserCounter(s);
-    rm->unlockActiveStream();
+    rm->unlockValidStreamMutex();
 
     if (0 != status) {
         PAL_ERR(LOG_TAG, "stream stop failed. status : %d", status);
@@ -412,22 +412,33 @@
         status = -EINVAL;
         return status;
     }
-    rm->lockActiveStream();
+    rm->lockValidStreamMutex();
     if (!stream_handle || !rm->isActiveStream(stream_handle) || !buf) {
-        rm->unlockActiveStream();
+        rm->unlockValidStreamMutex();
         status = -EINVAL;
         PAL_ERR(LOG_TAG, "Invalid input parameters status %d", status);
         return status;
     }
-    rm->unlockActiveStream();
 
     PAL_VERBOSE(LOG_TAG, "Enter. Stream handle :%pK", stream_handle);
     s =  reinterpret_cast<Stream *>(stream_handle);
+    status = rm->increaseStreamUserCounter(s);
+    if (0 != status) {
+        rm->unlockValidStreamMutex();
+        PAL_ERR(LOG_TAG, "failed to increase stream user count");
+        return status;
+    }
+    rm->unlockValidStreamMutex();
+
     status = s->write(buf);
     if (status < 0) {
         PAL_ERR(LOG_TAG, "stream write failed status %d", status);
-        return status;
     }
+
+    rm->lockValidStreamMutex();
+    rm->decreaseStreamUserCounter(s);
+    rm->unlockValidStreamMutex();
+
     PAL_VERBOSE(LOG_TAG, "Exit. status %d", status);
     return status;
 }
@@ -444,22 +455,32 @@
         status = -EINVAL;
         return status;
     }
-    rm->lockActiveStream();
+    rm->lockValidStreamMutex();
     if (!stream_handle || !rm->isActiveStream(stream_handle) || !buf) {
-        rm->unlockActiveStream();
+        rm->unlockValidStreamMutex();
         status = -EINVAL;
         PAL_ERR(LOG_TAG, "Invalid input parameters status %d", status);
         return status;
     }
-    rm->unlockActiveStream();
 
     PAL_VERBOSE(LOG_TAG, "Enter. Stream handle :%pK", stream_handle);
     s =  reinterpret_cast<Stream *>(stream_handle);
+    status = rm->increaseStreamUserCounter(s);
+    if (0 != status) {
+        rm->unlockValidStreamMutex();
+        PAL_ERR(LOG_TAG, "failed to increase stream user count");
+        return status;
+    }
+    rm->unlockValidStreamMutex();
+
     status = s->read(buf);
     if (status < 0) {
         PAL_ERR(LOG_TAG, "stream read failed status %d", status);
-        return status;
     }
+
+    rm->lockValidStreamMutex();
+    rm->decreaseStreamUserCounter(s);
+    rm->unlockValidStreamMutex();
     PAL_VERBOSE(LOG_TAG, "Exit. status %d", status);
     return status;
 }
@@ -478,22 +499,32 @@
         return status;
     }
 
-    rm->lockActiveStream();
+    rm->lockValidStreamMutex();
     if (!stream_handle || !rm->isActiveStream(stream_handle)) {
-        rm->unlockActiveStream();
+        rm->unlockValidStreamMutex();
         status = -EINVAL;
         PAL_ERR(LOG_TAG,  "Invalid input parameters status %d", status);
         return status;
     }
-    rm->unlockActiveStream();
 
     PAL_DBG(LOG_TAG, "Enter. Stream handle :%pK", stream_handle);
     s =  reinterpret_cast<Stream *>(stream_handle);
+    status = rm->increaseStreamUserCounter(s);
+    if (0 != status) {
+        rm->unlockValidStreamMutex();
+        PAL_ERR(LOG_TAG, "failed to increase stream user count");
+        return status;
+    }
+    rm->unlockValidStreamMutex();
+
     status = s->getParameters(param_id, (void **)param_payload);
     if (0 != status) {
         PAL_ERR(LOG_TAG, "get parameters failed status %d param_id %u", status, param_id);
-        return status;
     }
+
+    rm->lockValidStreamMutex();
+    rm->decreaseStreamUserCounter(s);
+    rm->unlockValidStreamMutex();
     PAL_DBG(LOG_TAG, "Exit. status %d", status);
     return status;
 }
@@ -512,23 +543,34 @@
         return status;
     }
 
-    rm->lockActiveStream();
+    rm->lockValidStreamMutex();
     if (!stream_handle || !rm->isActiveStream(stream_handle)) {
-        rm->unlockActiveStream();
+        rm->unlockValidStreamMutex();
         status = -EINVAL;
         PAL_ERR(LOG_TAG,  "Invalid stream handle, status %d", status);
         return status;
     }
-    rm->unlockActiveStream();
 
     PAL_DBG(LOG_TAG, "Enter. Stream handle :%pK param_id %d", stream_handle,
             param_id);
     s =  reinterpret_cast<Stream *>(stream_handle);
+    status = rm->increaseStreamUserCounter(s);
+    if (0 != status) {
+        rm->unlockValidStreamMutex();
+        PAL_ERR(LOG_TAG, "failed to increase stream user count");
+        return status;
+    }
+    rm->unlockValidStreamMutex();
+
     if (PAL_PARAM_ID_UIEFFECT == param_id) {
         status = s->setEffectParameters((void *)param_payload);
     } else {
         status = s->setParameters(param_id, (void *)param_payload);
     }
+    rm->lockValidStreamMutex();
+    rm->decreaseStreamUserCounter(s);
+    rm->unlockValidStreamMutex();
+
     if (0 != status) {
         PAL_ERR(LOG_TAG, "set parameters failed status %d param_id %u", status, param_id);
         return status;
@@ -538,6 +580,7 @@
         PAL_DBG(LOG_TAG, "Buffering stopped, handle deferred LPI<->NLPI switch");
         rm->handleDeferredSwitch();
     }
+
     PAL_DBG(LOG_TAG, "Exit. status %d", status);
     return status;
 }
@@ -562,9 +605,9 @@
     }
     PAL_DBG(LOG_TAG, "Enter. Stream handle :%pK", stream_handle);
 
-    rm->lockActiveStream();
+    rm->lockValidStreamMutex();
     if (!rm->isActiveStream(stream_handle)) {
-        rm->unlockActiveStream();
+        rm->unlockValidStreamMutex();
         status = -EINVAL;
         return status;
     }
@@ -572,19 +615,19 @@
     s =  reinterpret_cast<Stream *>(stream_handle);
     status = rm->increaseStreamUserCounter(s);
     if (0 != status) {
-        rm->unlockActiveStream();
+        rm->unlockValidStreamMutex();
         PAL_ERR(LOG_TAG, "failed to increase stream user count");
         return status;
     }
-    rm->unlockActiveStream();
+    rm->unlockValidStreamMutex();
 
     s->lockStreamMutex();
     status = s->setVolume(volume);
     s->unlockStreamMutex();
 
-    rm->lockActiveStream();
+    rm->lockValidStreamMutex();
     rm->decreaseStreamUserCounter(s);
-    rm->unlockActiveStream();
+    rm->unlockValidStreamMutex();
 
     if (0 != status) {
         PAL_ERR(LOG_TAG, "setVolume failed with status %d", status);
@@ -615,9 +658,9 @@
 
     PAL_DBG(LOG_TAG, "Enter. Stream handle :%pK", stream_handle);
 
-    rm->lockActiveStream();
+    rm->lockValidStreamMutex();
     if (!rm->isActiveStream(stream_handle)) {
-        rm->unlockActiveStream();
+        rm->unlockValidStreamMutex();
         status = -EINVAL;
         goto exit;
     }
@@ -625,16 +668,16 @@
     s =  reinterpret_cast<Stream *>(stream_handle);
     status = rm->increaseStreamUserCounter(s);
     if (0 != status) {
-        rm->unlockActiveStream();
+        rm->unlockValidStreamMutex();
         PAL_ERR(LOG_TAG, "failed to increase stream user count");
         goto exit;
     }
-    rm->unlockActiveStream();
+    rm->unlockValidStreamMutex();
     status = s->mute(state);
 
-    rm->lockActiveStream();
+    rm->lockValidStreamMutex();
     rm->decreaseStreamUserCounter(s);
-    rm->unlockActiveStream();
+    rm->unlockValidStreamMutex();
 
     if (0 != status) {
         PAL_ERR(LOG_TAG, "mute failed with status %d", status);
@@ -643,7 +686,6 @@
 
 exit:
     PAL_DBG(LOG_TAG, "Exit. status %d", status);
-
     return status;
 }
 
@@ -660,22 +702,31 @@
         return status;
     }
 
-    rm->lockActiveStream();
+    rm->lockValidStreamMutex();
     if (!stream_handle || !rm->isActiveStream(stream_handle)) {
-        rm->unlockActiveStream();
+        rm->unlockValidStreamMutex();
         status = -EINVAL;
         PAL_ERR(LOG_TAG, "Invalid stream handle status %d", status);
         return status;
     }
-    rm->unlockActiveStream();
 
     PAL_DBG(LOG_TAG, "Enter. Stream handle :%pK", stream_handle);
     s =  reinterpret_cast<Stream *>(stream_handle);
+    status = rm->increaseStreamUserCounter(s);
+    if (0 != status) {
+        rm->unlockValidStreamMutex();
+        PAL_ERR(LOG_TAG, "failed to increase stream user count");
+        return status;
+    }
+    rm->unlockValidStreamMutex();
+
     status = s->pause();
     if (0 != status) {
         PAL_ERR(LOG_TAG, "pal_stream_pause failed with status %d", status);
-        return status;
     }
+    rm->lockValidStreamMutex();
+    rm->decreaseStreamUserCounter(s);
+    rm->unlockValidStreamMutex();
     PAL_DBG(LOG_TAG, "Exit. status %d", status);
     return status;
 }
@@ -693,24 +744,31 @@
         return status;
     }
 
-    rm->lockActiveStream();
+    rm->lockValidStreamMutex();
     if (!stream_handle || !rm->isActiveStream(stream_handle)) {
-        rm->unlockActiveStream();
+        rm->unlockValidStreamMutex();
         status = -EINVAL;
         PAL_ERR(LOG_TAG, "Invalid stream handle status %d", status);
         return status;
     }
-    rm->unlockActiveStream();
 
     PAL_DBG(LOG_TAG, "Enter. Stream handle :%pK", stream_handle);
     s =  reinterpret_cast<Stream *>(stream_handle);
+    status = rm->increaseStreamUserCounter(s);
+    if (0 != status) {
+        rm->unlockValidStreamMutex();
+        PAL_ERR(LOG_TAG, "failed to increase stream user count");
+        return status;
+    }
+    rm->unlockValidStreamMutex();
 
     status = s->resume();
     if (0 != status) {
         PAL_ERR(LOG_TAG, "resume failed with status %d", status);
-        return status;
     }
-
+    rm->lockValidStreamMutex();
+    rm->decreaseStreamUserCounter(s);
+    rm->unlockValidStreamMutex();
     PAL_DBG(LOG_TAG, "Exit. status %d", status);
     return status;
 }
@@ -736,9 +794,9 @@
         goto exit;
     }
 
-    rm->lockActiveStream();
+    rm->lockValidStreamMutex();
     if (!rm->isActiveStream(stream_handle)) {
-        rm->unlockActiveStream();
+        rm->unlockValidStreamMutex();
         status = -EINVAL;
         goto exit;
     }
@@ -746,17 +804,17 @@
     s =  reinterpret_cast<Stream *>(stream_handle);
     status = rm->increaseStreamUserCounter(s);
     if (0 != status) {
-        rm->unlockActiveStream();
+        rm->unlockValidStreamMutex();
         PAL_ERR(LOG_TAG, "failed to increase stream user count");
         goto exit;
     }
-    rm->unlockActiveStream();
+    rm->unlockValidStreamMutex();
 
     status = s->drain(type);
 
-    rm->lockActiveStream();
+    rm->lockValidStreamMutex();
     rm->decreaseStreamUserCounter(s);
-    rm->unlockActiveStream();
+    rm->unlockValidStreamMutex();
 
     if (0 != status) {
         PAL_ERR(LOG_TAG, "drain failed with status %d", status);
@@ -780,24 +838,32 @@
         return status;
     }
 
-    rm->lockActiveStream();
+    rm->lockValidStreamMutex();
     if (!stream_handle || !rm->isActiveStream(stream_handle)) {
-        rm->unlockActiveStream();
+        rm->unlockValidStreamMutex();
         status = -EINVAL;
         PAL_ERR(LOG_TAG, "Invalid stream handle status %d", status);
         return status;
     }
-    rm->unlockActiveStream();
 
     PAL_DBG(LOG_TAG, "Enter. Stream handle :%pK", stream_handle);
     s =  reinterpret_cast<Stream *>(stream_handle);
+    status = rm->increaseStreamUserCounter(s);
+    if (0 != status) {
+        rm->unlockValidStreamMutex();
+        PAL_ERR(LOG_TAG, "failed to increase stream user count");
+        return status;
+    }
+    rm->unlockValidStreamMutex();
 
     status = s->flush();
     if (0 != status) {
         PAL_ERR(LOG_TAG, "flush failed with status %d", status);
-        return status;
     }
 
+    rm->lockValidStreamMutex();
+    rm->decreaseStreamUserCounter(s);
+    rm->unlockValidStreamMutex();
     PAL_DBG(LOG_TAG, "Exit. status %d", status);
     return status;
 }
@@ -815,23 +881,32 @@
         return status;
     }
 
-    rm->lockActiveStream();
+    rm->lockValidStreamMutex();
     if (!stream_handle || !rm->isActiveStream(stream_handle)) {
-        rm->unlockActiveStream();
+        rm->unlockValidStreamMutex();
         status = -EINVAL;
         PAL_ERR(LOG_TAG, "Invalid stream handle status %d", status);
         return status;
     }
-    rm->unlockActiveStream();
 
     PAL_DBG(LOG_TAG, "Enter. Stream handle :%pK", stream_handle);
     s =  reinterpret_cast<Stream *>(stream_handle);
+    status = rm->increaseStreamUserCounter(s);
+    if (0 != status) {
+        rm->unlockValidStreamMutex();
+        PAL_ERR(LOG_TAG, "failed to increase stream user count");
+        return status;
+    }
+    rm->unlockValidStreamMutex();
 
     status = s->suspend();
     if (0 != status) {
         PAL_ERR(LOG_TAG, "suspend failed with status %d", status);
     }
 
+    rm->lockValidStreamMutex();
+    rm->decreaseStreamUserCounter(s);
+    rm->unlockValidStreamMutex();
     PAL_DBG(LOG_TAG, "Exit. status %d", status);
     return status;
 }
@@ -851,23 +926,31 @@
         return status;
     }
 
-    rm->lockActiveStream();
+    rm->lockValidStreamMutex();
     if (!stream_handle || !rm->isActiveStream(stream_handle)) {
-        rm->unlockActiveStream();
+        rm->unlockValidStreamMutex();
         status = -EINVAL;
         PAL_ERR(LOG_TAG, "Invalid stream handle status %d", status);
         return status;
     }
-    rm->unlockActiveStream();
 
     PAL_DBG(LOG_TAG, "Enter. Stream handle :%pK", stream_handle);
     s =  reinterpret_cast<Stream *>(stream_handle);
+    status = rm->increaseStreamUserCounter(s);
+    if (0 != status) {
+        rm->unlockValidStreamMutex();
+        PAL_ERR(LOG_TAG, "failed to increase stream user count");
+        return status;
+    }
+    rm->unlockValidStreamMutex();
 
     status = s->setBufInfo(in_buffer_cfg, out_buffer_cfg);
     if (0 != status) {
         PAL_ERR(LOG_TAG, "pal_stream_set_buffer_size failed with status %d", status);
-        return status;
     }
+    rm->lockValidStreamMutex();
+    rm->decreaseStreamUserCounter(s);
+    rm->unlockValidStreamMutex();
     PAL_DBG(LOG_TAG, "Exit. status %d", status);
     return status;
 }
@@ -878,11 +961,6 @@
     Stream *s = NULL;
     int status = -EINVAL;
     std::shared_ptr<ResourceManager> rm = NULL;
-
-    if (!stream_handle) {
-        PAL_ERR(LOG_TAG, "Invalid input parameters status %d\n", status);
-        return status;
-    }
     PAL_DBG(LOG_TAG, "Enter. Stream handle :%pK\n", stream_handle);
 
     rm = ResourceManager::getInstance();
@@ -891,14 +969,26 @@
         return status;
     }
 
-    rm->lockActiveStream();
-    if (rm->isActiveStream(stream_handle)) {
-        s =  reinterpret_cast<Stream *>(stream_handle);
-        status = s->getTimestamp(stime);
-    } else {
-        PAL_ERR(LOG_TAG, "stream handle in stale state.\n");
+    rm->lockValidStreamMutex();
+    if (!stream_handle || !rm->isActiveStream(stream_handle)) {
+        rm->unlockValidStreamMutex();
+        status = -EINVAL;
+        PAL_ERR(LOG_TAG, "Invalid stream handle status %d", status);
+        return status;
     }
-    rm->unlockActiveStream();
+    s =  reinterpret_cast<Stream *>(stream_handle);
+    status = rm->increaseStreamUserCounter(s);
+    if (0 != status) {
+        rm->unlockValidStreamMutex();
+        PAL_ERR(LOG_TAG, "failed to increase stream user count");
+        return status;
+    }
+    rm->unlockValidStreamMutex();
+    status = s->getTimestamp(stime);
+
+    rm->lockValidStreamMutex();
+    rm->decreaseStreamUserCounter(s);
+    rm->unlockValidStreamMutex();
 
     if (0 != status) {
         PAL_ERR(LOG_TAG, "pal_get_timestamp failed with status %d\n", status);
@@ -927,23 +1017,32 @@
         return status;
     }
 
-    rm->lockActiveStream();
+    rm->lockValidStreamMutex();
     if (!stream_handle || !rm->isActiveStream(stream_handle)) {
-        rm->unlockActiveStream();
+        rm->unlockValidStreamMutex();
         status = -EINVAL;
         PAL_ERR(LOG_TAG, "Invalid stream handle status %d", status);
         return status;
     }
-    rm->unlockActiveStream();
 
     PAL_DBG(LOG_TAG, "Enter. Stream handle :%pK", stream_handle);
-
     s =  reinterpret_cast<Stream *>(stream_handle);
+    status = rm->increaseStreamUserCounter(s);
+    if (0 != status) {
+        rm->unlockValidStreamMutex();
+        PAL_ERR(LOG_TAG, "failed to increase stream user count");
+        return status;
+    }
+    rm->unlockValidStreamMutex();
+
     status = s->addRemoveEffect(effect, enable);
     if (0 != status) {
         PAL_ERR(LOG_TAG, "pal_add_effect failed with status %d", status);
-        return status;
     }
+
+    rm->lockValidStreamMutex();
+    rm->decreaseStreamUserCounter(s);
+    rm->unlockValidStreamMutex();
     PAL_DBG(LOG_TAG, "Exit. status %d", status);
     return status;
 
@@ -982,9 +1081,9 @@
         return status;
     }
 
-    rm->lockActiveStream();
+    rm->lockValidStreamMutex();
     if (!rm->isActiveStream(stream_handle)) {
-        rm->unlockActiveStream();
+        rm->unlockValidStreamMutex();
         status = -EINVAL;
         return status;
     }
@@ -994,11 +1093,11 @@
     s = reinterpret_cast<Stream *>(stream_handle);
     status = rm->increaseStreamUserCounter(s);
     if (0 != status) {
-        rm->unlockActiveStream();
+        rm->unlockValidStreamMutex();
         PAL_ERR(LOG_TAG, "failed to increase stream user count");
         return status;
     }
-    rm->unlockActiveStream();
+    rm->unlockValidStreamMutex();
 
     s->getStreamAttributes(&sattr);
 
@@ -1121,9 +1220,9 @@
     }
 
 exit:
-    rm->lockActiveStream();
+    rm->lockValidStreamMutex();
     rm->decreaseStreamUserCounter(s);
-    rm->unlockActiveStream();
+    rm->unlockValidStreamMutex();
     if (pDevices)
         free(pDevices);
     PAL_INFO(LOG_TAG, "Exit. status %d", status);
@@ -1144,20 +1243,30 @@
         return status;
     }
 
-    rm->lockActiveStream();
+    rm->lockValidStreamMutex();
     if (!stream_handle || !rm->isActiveStream(stream_handle)) {
-        rm->unlockActiveStream();
+        rm->unlockValidStreamMutex();
         status = -EINVAL;
         PAL_ERR(LOG_TAG, "Invalid stream handle status %d", status);
         return status;
     }
-    rm->unlockActiveStream();
 
     PAL_DBG(LOG_TAG, "Enter. Stream handle :%pK", stream_handle);
 
     s =  reinterpret_cast<Stream *>(stream_handle);
+    status = rm->increaseStreamUserCounter(s);
+    if (0 != status) {
+        rm->unlockValidStreamMutex();
+        PAL_ERR(LOG_TAG, "failed to increase stream user count");
+        return status;
+    }
+    rm->unlockValidStreamMutex();
+
     status = s->getTagsWithModuleInfo(size, payload);
 
+    rm->lockValidStreamMutex();
+    rm->decreaseStreamUserCounter(s);
+    rm->unlockValidStreamMutex();
     PAL_DBG(LOG_TAG, "Exit. Stream handle: %pK, status %d", stream_handle, status);
     return status;
 }
@@ -1222,22 +1331,32 @@
         return status;
     }
 
-    rm->lockActiveStream();
+    rm->lockValidStreamMutex();
     if (!stream_handle || !rm->isActiveStream(stream_handle)) {
-        rm->unlockActiveStream();
+        rm->unlockValidStreamMutex();
         status = -EINVAL;
         PAL_ERR(LOG_TAG, "Invalid stream handle status %d", status);
         return status;
     }
-    rm->unlockActiveStream();
 
     PAL_DBG(LOG_TAG, "Enter. Stream handle :%pK", stream_handle);
     s =  reinterpret_cast<Stream *>(stream_handle);
+    status = rm->increaseStreamUserCounter(s);
+    if (0 != status) {
+        rm->unlockValidStreamMutex();
+        PAL_ERR(LOG_TAG, "failed to increase stream user count");
+        return status;
+    }
+    rm->unlockValidStreamMutex();
+
     status = s->GetMmapPosition(position);
     if (0 != status) {
         PAL_ERR(LOG_TAG, "pal_stream_get_mmap_position failed with status %d", status);
-        return status;
     }
+
+    rm->lockValidStreamMutex();
+    rm->decreaseStreamUserCounter(s);
+    rm->unlockValidStreamMutex();
     PAL_DBG(LOG_TAG, "Exit. status %d", status);
     return status;
 }
@@ -1257,22 +1376,32 @@
         return status;
     }
 
-    rm->lockActiveStream();
+    rm->lockValidStreamMutex();
     if (!stream_handle || !rm->isActiveStream(stream_handle)) {
-        rm->unlockActiveStream();
+        rm->unlockValidStreamMutex();
         status = -EINVAL;
         PAL_ERR(LOG_TAG, "Invalid stream handle status %d", status);
         return status;
     }
-    rm->unlockActiveStream();
 
     PAL_DBG(LOG_TAG, "Enter. Stream handle :%pK", stream_handle);
     s =  reinterpret_cast<Stream *>(stream_handle);
+    status = rm->increaseStreamUserCounter(s);
+    if (0 != status) {
+        rm->unlockValidStreamMutex();
+        PAL_ERR(LOG_TAG, "failed to increase stream user count");
+        return status;
+    }
+    rm->unlockValidStreamMutex();
+
     status = s->createMmapBuffer(min_size_frames, info);
     if (0 != status) {
         PAL_ERR(LOG_TAG, "pal_stream_create_mmap_buffer failed with status %d", status);
-        return status;
     }
+
+    rm->lockValidStreamMutex();
+    rm->decreaseStreamUserCounter(s);
+    rm->unlockValidStreamMutex();
     PAL_DBG(LOG_TAG, "Exit. status %d", status);
     return status;
 }
diff --git a/configs/anorak/usecaseKvManager.xml b/configs/anorak/usecaseKvManager.xml
index f57d31d..d9d6ace 100644
--- a/configs/anorak/usecaseKvManager.xml
+++ b/configs/anorak/usecaseKvManager.xml
@@ -28,7 +28,7 @@
 
 
 * Changes from Qualcomm Innovation Center are provided under the following license:
-* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
 * SPDX-License-Identifier: BSD-3-Clause-Clear
 *  -->
 
@@ -80,6 +80,15 @@
                 <graph_kv key="0xAB000000" value="0x2"/>
             </keys_and_values>
         </stream>
+        <!-- Spatial audio stream -->
+        <stream type="PAL_STREAM_SPATIAL_AUDIO">
+            <keys_and_values Direction="RX" Instance="1">
+                <!-- STREAMRX - SPATIAL_AUDIO_PLAYBACK  -->
+                <graph_kv key="0xA1000000" value="0xA1000018"/>
+                <!-- INSTANCE - INSTANCE_1 -->
+                <graph_kv key="0xAB000000" value="0x1"/>
+            </keys_and_values>
+        </stream>
         <stream type="PAL_STREAM_VOICE_RECOGNITION">
             <keys_and_values Direction="TX" Instance="1">
                 <!-- STREAMTX - PCM_RECORD -->
@@ -756,13 +765,13 @@
     <devicepps>
         <!-- OUT Speaker DevicePPs -->
         <devicepp id="PAL_DEVICE_OUT_SPEAKER">
-            <keys_and_values StreamType="PAL_STREAM_DEEP_BUFFER,PAL_STREAM_PCM_OFFLOAD,PAL_STREAM_COMPRESSED,PAL_STREAM_LOW_LATENCY,PAL_STREAM_GENERIC">
+            <keys_and_values StreamType="PAL_STREAM_DEEP_BUFFER,PAL_STREAM_PCM_OFFLOAD,PAL_STREAM_COMPRESSED,PAL_STREAM_LOW_LATENCY,PAL_STREAM_GENERIC,PAL_STREAM_SPATIAL_AUDIO">
                 <!-- DEVICERX - SPEAKER -->
                 <graph_kv key="0xA2000000" value="0xA2000001"/>
                 <!-- DEVICEPP_RX - DEVICEPP_RX_AUDIO_MBDRC -->
                 <graph_kv key="0xAC000000" value="0xAC000002"/>
             </keys_and_values>
-            <keys_and_values StreamType="PAL_STREAM_DEEP_BUFFER,PAL_STREAM_PCM_OFFLOAD,PAL_STREAM_COMPRESSED,PAL_STREAM_GENERIC,PAL_STREAM_LOW_LATENCY" CustomConfig="mspp">
+            <keys_and_values StreamType="PAL_STREAM_DEEP_BUFFER,PAL_STREAM_PCM_OFFLOAD,PAL_STREAM_COMPRESSED,PAL_STREAM_GENERIC,PAL_STREAM_LOW_LATENCY,PAL_STREAM_SPATIAL_AUDIO" CustomConfig="mspp">
                 <!-- DEVICERX - SPEAKER -->
                 <graph_kv key="0xA2000000" value="0xA2000001"/>
                 <!-- DEVICEPP_RX - DEVICEPP_RX_AUDIO_MSPP -->
@@ -858,7 +867,7 @@
         </devicepp>
         <!-- OUT Headset and Headphone Digital DevicePPs -->
         <devicepp id="PAL_DEVICE_OUT_WIRED_HEADSET,PAL_DEVICE_OUT_WIRED_HEADPHONE">
-            <keys_and_values StreamType="PAL_STREAM_DEEP_BUFFER,PAL_STREAM_PCM_OFFLOAD,PAL_STREAM_COMPRESSED,PAL_STREAM_LOW_LATENCY,PAL_STREAM_GENERIC">
+            <keys_and_values StreamType="PAL_STREAM_DEEP_BUFFER,PAL_STREAM_PCM_OFFLOAD,PAL_STREAM_COMPRESSED,PAL_STREAM_LOW_LATENCY,PAL_STREAM_GENERIC,PAL_STREAM_SPATIAL_AUDIO">
                 <!-- DEVICERX - HEADPHONES -->
                 <graph_kv key="0xA2000000" value="0xA2000002"/>
                 <!-- DEVICEPP_RX - DEVICEPP_RX_AUDIO_MBDRC -->
@@ -891,7 +900,7 @@
         </devicepp>
         <!-- OUT Bluetooth A2DP DevicePPs -->
         <devicepp id="PAL_DEVICE_OUT_BLUETOOTH_A2DP">
-            <keys_and_values StreamType="PAL_STREAM_COMPRESSED,PAL_STREAM_DEEP_BUFFER,PAL_STREAM_LOW_LATENCY,PAL_STREAM_PCM_OFFLOAD,PAL_STREAM_GENERIC">
+            <keys_and_values StreamType="PAL_STREAM_COMPRESSED,PAL_STREAM_DEEP_BUFFER,PAL_STREAM_LOW_LATENCY,PAL_STREAM_PCM_OFFLOAD,PAL_STREAM_GENERIC,PAL_STREAM_SPATIAL_AUDIO">
                 <!-- DEVICEPP_RX - DEVICEPP_RX_AUDIO_MBDRC -->
                 <graph_kv key="0xAC000000" value="0xAC000002"/>
             </keys_and_values>
@@ -902,7 +911,7 @@
         </devicepp>
         <!-- OUT Bluetooth BLE DevicePPs -->
         <devicepp id="PAL_DEVICE_OUT_BLUETOOTH_BLE">
-            <keys_and_values StreamType="PAL_STREAM_COMPRESSED,PAL_STREAM_DEEP_BUFFER,PAL_STREAM_LOW_LATENCY,PAL_STREAM_PCM_OFFLOAD">
+            <keys_and_values StreamType="PAL_STREAM_COMPRESSED,PAL_STREAM_DEEP_BUFFER,PAL_STREAM_LOW_LATENCY,PAL_STREAM_PCM_OFFLOAD,PAL_STREAM_SPATIAL_AUDIO">
                 <!-- DEVICEPP_RX - DEVICEPP_RX_AUDIO_MBDRC -->
                 <graph_kv key="0xAC000000" value="0xAC000002"/>
             </keys_and_values>
@@ -924,7 +933,7 @@
         </devicepp>
         <!-- OUT BT SCO DevicePPs -->
         <devicepp id="PAL_DEVICE_OUT_BLUETOOTH_SCO">
-            <keys_and_values StreamType="PAL_STREAM_DEEP_BUFFER,PAL_STREAM_PCM_OFFLOAD,PAL_STREAM_COMPRESSED,PAL_STREAM_LOW_LATENCY,PAL_STREAM_GENERIC">
+            <keys_and_values StreamType="PAL_STREAM_DEEP_BUFFER,PAL_STREAM_PCM_OFFLOAD,PAL_STREAM_COMPRESSED,PAL_STREAM_LOW_LATENCY,PAL_STREAM_GENERIC,PAL_STREAM_SPATIAL_AUDIO">
                 <!-- DEVICERX - BT_RX -->
                 <graph_kv key="0xA2000000" value="0xA2000003"/>
                 <!-- DEVICEPP_RX - DEVICEPP_RX_AUDIO_MBDRC -->
@@ -960,7 +969,7 @@
         </devicepp>
         <!-- OUT USB device and USB Headset DevicePPs -->
         <devicepp id="PAL_DEVICE_OUT_USB_DEVICE,PAL_DEVICE_OUT_USB_HEADSET">
-            <keys_and_values StreamType="PAL_STREAM_DEEP_BUFFER,PAL_STREAM_PCM_OFFLOAD,PAL_STREAM_COMPRESSED,PAL_STREAM_LOW_LATENCY,PAL_STREAM_GENERIC">
+            <keys_and_values StreamType="PAL_STREAM_DEEP_BUFFER,PAL_STREAM_PCM_OFFLOAD,PAL_STREAM_COMPRESSED,PAL_STREAM_LOW_LATENCY,PAL_STREAM_GENERIC,PAL_STREAM_SPATIAL_AUDIO">
                 <!-- DEVICERX - USB_RX -->
                 <graph_kv key="0xA2000000" value="0xA2000005"/>
                 <!-- DEVICEPP_RX - DEVICEPP_RX_AUDIO_MBDRC -->
diff --git a/configs/crow/resourcemanager_crow_idp_wcd9395_aatc.xml b/configs/crow/resourcemanager_crow_idp_wcd9395_aatc.xml
index 459d534..4db17c2 100644
--- a/configs/crow/resourcemanager_crow_idp_wcd9395_aatc.xml
+++ b/configs/crow/resourcemanager_crow_idp_wcd9395_aatc.xml
@@ -561,10 +561,10 @@
             <id>PAL_DEVICE_IN_VI_FEEDBACK</id>
             <back_end_name>CODEC_DMA-LPAIF_WSA-TX-0</back_end_name>
             <max_channels>2</max_channels>
-            <channels>2</channels>
+            <channels>1</channels>
             <samplerate>48000</samplerate>
             <bit_width>32</bit_width>
-            <snd_device_name>vi-feedback</snd_device_name>
+            <snd_device_name>vi-feedback-mono-2</snd_device_name>
             <usecase>
                 <name>PAL_STREAM_VOICE_CALL</name>
                 <channels>1</channels>
@@ -575,10 +575,10 @@
             <id>PAL_DEVICE_IN_CPS_FEEDBACK</id>
             <back_end_name>CODEC_DMA-LPAIF_WSA-TX-2</back_end_name>
             <max_channels>2</max_channels>
-            <channels>2</channels>
+            <channels>1</channels>
             <samplerate>24000</samplerate>
             <bit_width>32</bit_width>
-            <snd_device_name>cps-feedback</snd_device_name>
+            <snd_device_name>cps-feedback-mono-2</snd_device_name>
             <usecase>
                 <name>PAL_STREAM_VOICE_CALL</name>
                 <channels>1</channels>
diff --git a/configs/kalama/resourcemanager_kalama_cdp.xml b/configs/kalama/resourcemanager_kalama_cdp.xml
index 5ba1983..7f4744b 100644
--- a/configs/kalama/resourcemanager_kalama_cdp.xml
+++ b/configs/kalama/resourcemanager_kalama_cdp.xml
@@ -28,7 +28,7 @@
 
 * Changes from Qualcomm Innovation Center are provided under the following license:
 *
-* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted (subject to the limitations in the
@@ -77,6 +77,7 @@
         <param key="device_mux_config" value ="false" />
         <param key="upd_duty_cycle_enable" value="false" />
         <param key="upd_virtual_port" value ="false" />
+        <param key="spkr_xmax_tmax_logging_enable" value ="false" />
     </config_params>
     <config_gapless key="gapless_supported" value="1"/>
     <bt_codecs>
diff --git a/configs/kalama/resourcemanager_kalama_cdp_apq.xml b/configs/kalama/resourcemanager_kalama_cdp_apq.xml
index 924b3ee..8239fee 100644
--- a/configs/kalama/resourcemanager_kalama_cdp_apq.xml
+++ b/configs/kalama/resourcemanager_kalama_cdp_apq.xml
@@ -28,7 +28,7 @@
 
 * Changes from Qualcomm Innovation Center are provided under the following license:
 *
-* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted (subject to the limitations in the
@@ -77,6 +77,7 @@
         <param key="device_mux_config" value ="false" />
         <param key="upd_duty_cycle_enable" value="false" />
         <param key="upd_virtual_port" value ="false" />
+        <param key="spkr_xmax_tmax_logging_enable" value ="false" />
     </config_params>
     <config_gapless key="gapless_supported" value="1"/>
     <bt_codecs>
diff --git a/configs/kalama/resourcemanager_kalama_grd.xml b/configs/kalama/resourcemanager_kalama_grd.xml
index becf30f..6420508 100644
--- a/configs/kalama/resourcemanager_kalama_grd.xml
+++ b/configs/kalama/resourcemanager_kalama_grd.xml
@@ -28,7 +28,7 @@
 
 * Changes from Qualcomm Innovation Center are provided under the following license:
 *
-* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted (subject to the limitations in the
@@ -77,6 +77,7 @@
         <param key="device_mux_config" value ="false" />
         <param key="upd_duty_cycle_enable" value="false" />
         <param key="upd_virtual_port" value ="false" />
+        <param key="spkr_xmax_tmax_logging_enable" value ="false" />
     </config_params>
     <config_volume>
         <use_volume_set_param>0</use_volume_set_param>
diff --git a/configs/kalama/resourcemanager_kalama_mtp.xml b/configs/kalama/resourcemanager_kalama_mtp.xml
index bda23c9..169c83c 100644
--- a/configs/kalama/resourcemanager_kalama_mtp.xml
+++ b/configs/kalama/resourcemanager_kalama_mtp.xml
@@ -28,7 +28,7 @@
 
 * Changes from Qualcomm Innovation Center are provided under the following license:
 *
-* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted (subject to the limitations in the
@@ -77,6 +77,7 @@
         <param key="signal_handler" value ="true" />
         <param key="device_mux_config" value ="false" />
         <param key="upd_virtual_port" value ="false" />
+        <param key="spkr_xmax_tmax_logging_enable" value ="false" />
     </config_params>
     <config_volume>
         <use_volume_set_param>0</use_volume_set_param>
diff --git a/configs/kalama/resourcemanager_kalama_mtp_apq.xml b/configs/kalama/resourcemanager_kalama_mtp_apq.xml
index fee3ff1..55e9c08 100644
--- a/configs/kalama/resourcemanager_kalama_mtp_apq.xml
+++ b/configs/kalama/resourcemanager_kalama_mtp_apq.xml
@@ -28,7 +28,7 @@
 
 * Changes from Qualcomm Innovation Center are provided under the following license:
 *
-* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted (subject to the limitations in the
@@ -77,6 +77,7 @@
         <param key="signal_handler" value ="true" />
         <param key="device_mux_config" value ="false" />
         <param key="upd_virtual_port" value ="false" />
+        <param key="spkr_xmax_tmax_logging_enable" value ="false" />
     </config_params>
     <config_volume>
         <use_volume_set_param>0</use_volume_set_param>
diff --git a/configs/kalama/resourcemanager_kalama_qrd.xml b/configs/kalama/resourcemanager_kalama_qrd.xml
index 3818244..f41696a 100644
--- a/configs/kalama/resourcemanager_kalama_qrd.xml
+++ b/configs/kalama/resourcemanager_kalama_qrd.xml
@@ -28,7 +28,7 @@
 
 * Changes from Qualcomm Innovation Center are provided under the following license:
 *
-* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted (subject to the limitations in the
@@ -77,6 +77,7 @@
         <param key="device_mux_config" value ="false" />
         <param key="upd_duty_cycle_enable" value="false" />
         <param key="upd_virtual_port" value ="false" />
+        <param key="spkr_xmax_tmax_logging_enable" value ="false" />
     </config_params>
     <config_volume>
         <use_volume_set_param>0</use_volume_set_param>
diff --git a/device/inc/SpeakerProtection.h b/device/inc/SpeakerProtection.h
index bf40718..94ac1aa 100644
--- a/device/inc/SpeakerProtection.h
+++ b/device/inc/SpeakerProtection.h
@@ -28,7 +28,7 @@
  *
  * Changes from Qualcomm Innovation Center are provided under the following license:
  *
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted (subject to the limitations in the
@@ -131,6 +131,7 @@
     spkr_prot_proc_state spkrProcessingState;
     int *spkerTempList;
     static bool isSpkrInUse;
+    static bool startXmaxLogging;
     static bool calThrdCreated;
     static bool isDynamicCalTriggered;
     static struct timespec spkrLastTimeUsed;
@@ -158,11 +159,13 @@
 
 public:
     static std::thread mCalThread;
+    static std::thread XmaxTmaxLogThread;
     static std::condition_variable cv;
     static std::mutex cvMutex;
     std::mutex deviceMutex;
     static std::mutex calibrationMutex;
     void spkrCalibrationThread();
+    void startSpkrXmaxTmaxLogging();
     int getSpeakerTemperature(int spkr_pos);
     void spkrCalibrateWait();
     int spkrStartCalibration();
@@ -194,6 +197,7 @@
     int getCpsDevNumber(std::string mixer);
     int32_t getCalibrationData(void **param);
     int32_t getFTMParameter(void **param);
+    int32_t getSpkrXmaxTmaxData();
     void disconnectFeandBe(std::vector<int> pcmDevIds, std::string backEndName);
 };
 
diff --git a/device/inc/USBAudio.h b/device/inc/USBAudio.h
index 4928838..c6d80cd 100644
--- a/device/inc/USBAudio.h
+++ b/device/inc/USBAudio.h
@@ -146,9 +146,9 @@
     int getMaxBitWidth(bool is_playback);
     int getMaxChannels(bool is_playback);
     unsigned int getFormatByBitWidth(int bitwidth);
-    unsigned int readSupportedFormat(bool is_playback, uint32_t *format);
-    unsigned int readSupportedSampleRate(bool is_playback, uint32_t *sample_rate);
-    unsigned int readSupportedChannelMask(bool is_playback, uint32_t *channel);
+    void readSupportedFormat(bool is_playback, uint32_t *format);
+    void readSupportedSampleRate(bool is_playback, uint32_t *sample_rate);
+    void readSupportedChannelMask(bool is_playback, uint32_t *channel);
     int readSupportedConfig(dynamic_media_config_t *config, bool is_playback, int usb_card);
     int readBestConfig(struct pal_media_config *config,
                                     struct pal_stream_attributes *sattr,
diff --git a/device/src/Bluetooth.cpp b/device/src/Bluetooth.cpp
index a448e47..709143e 100644
--- a/device/src/Bluetooth.cpp
+++ b/device/src/Bluetooth.cpp
@@ -1734,11 +1734,17 @@
         // session will be restarted after suspend completion
         PAL_INFO(LOG_TAG, "a2dp start requested during suspend state");
         return -ENOSYS;
+    } else if (a2dpState == A2DP_STATE_DISCONNECTED) {
+        PAL_INFO(LOG_TAG, "a2dp start requested when a2dp source stream is failed to open");
+        return -ENOSYS;
     }
 
     if (a2dpState != A2DP_STATE_STARTED && !totalActiveSessionRequests) {
         codecFormat = CODEC_TYPE_INVALID;
-        isAbrEnabled = false;
+
+        if (!isConfigured)
+            isAbrEnabled = false;
+
         PAL_DBG(LOG_TAG, "calling BT module stream start");
         /* This call indicates BT IPC lib to start playback */
         if (audio_source_start_api) {
@@ -2285,6 +2291,9 @@
             ((a2dpState != A2DP_STATE_STARTED) && (param_bt_a2dp.a2dp_suspended == true))) {
             param_bt_a2dp.is_force_switch = true;
             PAL_DBG(LOG_TAG, "a2dp reconfig or a2dp suspended/a2dpState is not started");
+        } else if (totalActiveSessionRequests == 0) {
+            param_bt_a2dp.is_force_switch = true;
+            PAL_DBG(LOG_TAG, "Force BT device switch for no total active BT sessions");
         } else {
             param_bt_a2dp.is_force_switch = false;
         }
diff --git a/device/src/Device.cpp b/device/src/Device.cpp
index 5a75d7c..076a8a5 100644
--- a/device/src/Device.cpp
+++ b/device/src/Device.cpp
@@ -493,6 +493,8 @@
            disableDevice(audioRoute, mSndDeviceName);
            mCurrentPriority = MIN_USECASE_PRIORITY;
            deviceStartStopCount = 0;
+           if(rm->num_proxy_channels != 0)
+               rm->num_proxy_channels = 0;
        }
     }
     PAL_INFO(LOG_TAG, "Exit. deviceCount %d for device id %d (%s), exit status %d", deviceCount,
diff --git a/device/src/SpeakerProtection.cpp b/device/src/SpeakerProtection.cpp
index a686e4e..30b3c92 100644
--- a/device/src/SpeakerProtection.cpp
+++ b/device/src/SpeakerProtection.cpp
@@ -63,10 +63,7 @@
 
 #define LOG_TAG "PAL: SpeakerProtection"
 
-
 #include "SpeakerProtection.h"
-#include "PalAudioRoute.h"
-#include "ResourceManager.h"
 #include "SessionAlsaUtils.h"
 #include "kvh2xml.h"
 #include <errno.h>
@@ -80,6 +77,8 @@
 #define PAL_SP_II_TEMP_PATH "/data/vendor/audio/audio_sp2.cal"
 #endif
 
+#define PAL_SP_XMAX_TMAX_DATA_PATH "/data/vendor/audio/spkr_xmax_tmax.txt"
+#define PAL_SP_XMAX_TMAX_LOG_PATH "/data/vendor/audio/log_spkr_xmax_tmax.cal"
 #define FEEDBACK_MONO_1 "-mono-1"
 
 #define MIN_SPKR_IDLE_SEC (60 * 30)
@@ -124,6 +123,7 @@
 #define CALIBRATION_STATUS_FAILURE 5
 
 std::thread SpeakerProtection::mCalThread;
+std::thread SpeakerProtection::XmaxTmaxLogThread;
 std::condition_variable SpeakerProtection::cv;
 std::mutex SpeakerProtection::cvMutex;
 std::mutex SpeakerProtection::calibrationMutex;
@@ -131,6 +131,7 @@
 bool SpeakerProtection::isSpkrInUse;
 bool SpeakerProtection::calThrdCreated;
 bool SpeakerProtection::isDynamicCalTriggered = false;
+bool SpeakerProtection::startXmaxLogging = false;
 struct timespec SpeakerProtection::spkrLastTimeUsed;
 struct mixer *SpeakerProtection::virtMixer;
 struct mixer *SpeakerProtection::hwMixer;
@@ -1400,6 +1401,189 @@
     customPayloadSize = 0;
 }
 
+int32_t SpeakerProtection::getSpkrXmaxTmaxData()
+{
+    const char* getParamControl = "getParam";
+    char* pcmDeviceName = NULL;
+    uint8_t* payload = NULL;
+    int ret = 0;
+    uint32_t miid = 0, num_ch = 0, stringLen =0;
+    int32_t pcmID = -EINVAL;
+    size_t payloadSize = 0, bytesWritten = -1;
+    struct mixer_ctl* ctl;
+    FILE* fp;
+    std::ostringstream cntrlName;
+    std::string backendName;
+    param_id_sp_tmax_xmax_logging_t sp_xmax_tmax;
+    param_id_sp_tmax_xmax_logging_t* sp_xmax_tmax_value;
+    PayloadBuilder* builder = new PayloadBuilder();
+
+    /* Frontend ID information for RX Session presents at SessionAlsaPCM/Compress
+     * In Kalama, there is no getter func for pcmDevIds (private attribute)
+     * Assuming there will be only one session. So hardcoded here*/
+
+    pcmID = 125;
+    pcmDeviceName = rm->getDeviceNameFromID(pcmID);
+
+    if (pcmDeviceName == NULL) {
+        /*To check for PAL_STREAM_COMPRESSED*/
+        pcmID = 105;
+        pcmDeviceName = rm->getDeviceNameFromID(pcmID);
+    }
+
+    if (pcmDeviceName) {
+        cntrlName << pcmDeviceName << " " << getParamControl;
+    }
+    else {
+        PAL_ERR(LOG_TAG, "Error: %d Unable to get Device name\n", -EINVAL);
+        ret = -EINVAL;
+        goto exit;
+    }
+
+    ctl = mixer_get_ctl_by_name(virtMixer, cntrlName.str().data());
+
+    if (!ctl) {
+        ret = -ENOENT;
+        PAL_ERR(LOG_TAG, "Error: %d Invalid mixer control: %s\n", ret, cntrlName.str().data());
+        goto exit;
+    }
+
+    rm->getBackendName(PAL_DEVICE_OUT_SPEAKER, backendName);
+
+    if (!strlen(backendName.c_str())) {
+        ret = -ENOENT;
+        PAL_ERR(LOG_TAG, "Error: %d Failed to obtain RX backend name", ret);
+        goto exit;
+    }
+
+    ret = SessionAlsaUtils::getModuleInstanceId(virtMixer, pcmID,
+        backendName.c_str(), MODULE_SP, &miid);
+
+    if (0 != ret) {
+        PAL_ERR(LOG_TAG, "Error: %d Failed to get tag info %x", ret, MODULE_SP);
+        goto exit;
+    }
+
+    sp_xmax_tmax.num_ch = vi_device.channels;
+    builder->payloadSPConfig(&payload, &payloadSize, miid,
+        PARAM_ID_SP_TMAX_XMAX_LOGGING, (void *) &sp_xmax_tmax);
+
+    if (!payloadSize) {
+        PAL_ERR(LOG_TAG, "Payload memory allocation failed");
+        ret = -EINVAL;
+        goto exit;
+    }
+
+    ret = mixer_ctl_set_array(ctl, payload, payloadSize);
+    if (0 != ret) {
+        PAL_ERR(LOG_TAG, "Set failed with return value = %d", ret);
+        goto exit;
+    }
+
+    memset(payload, 0, payloadSize);
+
+    ret = mixer_ctl_get_array(ctl, payload, payloadSize);
+    if (0 != ret) {
+        PAL_ERR(LOG_TAG, "Get failed with return value = %d", ret);
+        goto exit;
+    }
+    else {
+        sp_xmax_tmax_value = (param_id_sp_tmax_xmax_logging_t*)(payload +
+            sizeof(struct apm_module_param_data_t));
+        fp = fopen(PAL_SP_XMAX_TMAX_DATA_PATH, "a");
+
+        if (!fp) {
+            PAL_ERR(LOG_TAG, "Unable to open file for write");
+            ret = -EBADF;
+            goto exit;
+        }
+        else {
+            num_ch = sp_xmax_tmax_value->num_ch;
+            auto currentTime = std::chrono::system_clock::now();
+            std::time_t currentTimeT = std::chrono::system_clock::to_time_t(currentTime);
+            const char* currentTimeStr = std::ctime(&currentTimeT);
+            stringLen = std::strlen(currentTimeStr);
+
+            PAL_DBG(LOG_TAG, "Current Timestamp : %s and size of string : %d", currentTimeStr, stringLen);
+            bytesWritten = fprintf(fp, "%s ", currentTimeStr);
+
+            if (bytesWritten < 0) {
+                PAL_ERR(LOG_TAG, "Error in writing to file");
+                fclose(fp);
+                ret = -EBADF;
+                goto exit;
+            }
+
+            for (int i = 0; i < num_ch; i++) {
+                PAL_DBG(LOG_TAG, "Channel: %d, Max Excursion Value =%d",i, sp_xmax_tmax_value->tmax_xmax_params[i].max_excursion);
+                bytesWritten = fprintf(fp, "Ch: %d <Xmax> : %3.4f", i, (float)sp_xmax_tmax_value->tmax_xmax_params[i].max_excursion / (1 << 27));
+
+                if (bytesWritten < 0) {
+                    PAL_ERR(LOG_TAG, "Error in writing to file");
+                    fclose(fp);
+                    ret = -EBADF;
+                    goto exit;
+                }
+
+                PAL_DBG(LOG_TAG, "Channel: %d, Max Temperature Value =%d",i, sp_xmax_tmax_value->tmax_xmax_params[i].max_temperature);
+                bytesWritten = fprintf(fp, " <Tmax> : %3.4f ", (float)sp_xmax_tmax_value->tmax_xmax_params[i].max_temperature / (1 << 22));
+
+                if (bytesWritten < 0) {
+                    PAL_ERR(LOG_TAG, "Error in writing to file");
+                    fclose(fp);
+                    ret = -EBADF;
+                    goto exit;
+                }
+            }
+            bytesWritten = fprintf(fp, "\n");
+            if (bytesWritten < 0) {
+                PAL_ERR(LOG_TAG, "Error in writing to file");
+                fclose(fp);
+                ret = -EBADF;
+                goto exit;
+            }
+            fclose(fp);
+        }
+    }
+exit:
+    if (builder) {
+        delete builder;
+        builder = NULL;
+    }
+    return ret;
+
+}
+
+void SpeakerProtection::startSpkrXmaxTmaxLogging()
+{
+    FILE* log_fp = NULL;
+    int32_t ret = 0;
+
+    PAL_DBG(LOG_TAG, "Enter");
+
+    /* This condition is added to know if the Speaker_RX graph started or not.
+     * Assuming this file will be pushed to target after playback started
+     * That's how, we will be sure Speaker_RX graph has been started */
+
+    while (!log_fp) {
+        log_fp = fopen(PAL_SP_XMAX_TMAX_LOG_PATH, "rb");
+    }
+    fclose(log_fp);
+
+    if (remove(PAL_SP_XMAX_TMAX_LOG_PATH) == 0) {
+        PAL_DBG(LOG_TAG, "log_spkr_xmax_tmax file deleted successfully");
+    }
+
+    startXmaxLogging = true;
+    while (startXmaxLogging && (ret == 0)) {
+        ret = getSpkrXmaxTmaxData();
+        if (ret != 0) {
+            PAL_ERR(LOG_TAG, "Failed to get Param for spkr_xmax_tmax");
+        }
+        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
+    }
+}
+
 /*
  * CPS related custom payload
  */
@@ -2471,6 +2655,11 @@
                 }
             }
         }
+
+        if (ResourceManager::isSpkrXmaxTmaxLoggingEnabled) {
+            XmaxTmaxLogThread = std::thread(&SpeakerProtection::startSpkrXmaxTmaxLogging,
+                this);
+        }
         // Free up the local variables
         goto exit;
     }
@@ -2486,6 +2675,8 @@
         }
         spkrProtSetSpkrStatus(flag);
         // Speaker not in use anymore. Stop the processing mode
+        startXmaxLogging = false;
+
         PAL_DBG(LOG_TAG, "Closing VI path");
         if (txPcm) {
             rm = ResourceManager::getInstance();
@@ -2652,7 +2843,7 @@
     }
     stream = static_cast<Stream *>(activeStreams[0]);
     stream->getAssociatedSession(&session);
-    for (int ch = numberOfChannels; ch != 0; ch >> ch/CHANNELS_2) {
+    for (int ch = numberOfChannels; ch != 0; ch == ch >> CHANNELS_2) {
         if (ch == CHANNELS_4)
             tagid = MODULE_SP2;
         else {
@@ -2808,7 +2999,7 @@
         goto exit;
     }
 
-    for (int ch = numberOfChannels; ch != 0; ch >> ch/CHANNELS_2) {
+    for (int ch = numberOfChannels; ch != 0; ch == ch >> CHANNELS_2) {
 
         if (ch == CHANNELS_4)
             tagid = MODULE_VI2;
diff --git a/device/src/USBAudio.cpp b/device/src/USBAudio.cpp
index 5c40793..a27fd25 100644
--- a/device/src/USBAudio.cpp
+++ b/device/src/USBAudio.cpp
@@ -508,13 +508,13 @@
         check = true;
 
     while (str_start != NULL) {
-        str_start = strstr(str_start, "Altset");
+        str_start = strstr(str_start, "Altset ");
         if ((str_start == NULL) || (check  && (str_start >= str_end))) {
             PAL_VERBOSE(LOG_TAG,"done parsing %s\n", str_start);
             break;
         }
         PAL_VERBOSE(LOG_TAG,"remaining string %s\n", str_start);
-        str_start += sizeof("Altset");
+        str_start += sizeof("Altset ");
         std::shared_ptr<USBDeviceConfig> usb_device_info(new USBDeviceConfig());
         if (!usb_device_info) {
             PAL_ERR(LOG_TAG, "error unable to create usb device config object");
@@ -524,7 +524,7 @@
         usb_device_info->setType(type);
         /* Bit bit_width parsing */
         bit_width_start = strstr(str_start, "Format: ");
-        if (bit_width_start == NULL) {
+        if (bit_width_start == NULL || (check && (bit_width_start >= str_end))) {
             PAL_INFO(LOG_TAG, "Could not find bit_width string");
             continue;
         }
@@ -558,7 +558,7 @@
 
         /* channels parsing */
         channel_start = strstr(str_start, CHANNEL_NUMBER_STR);
-        if (channel_start == NULL) {
+        if (channel_start == NULL || (check && (channel_start >= str_end))) {
             PAL_INFO(LOG_TAG, "could not find Channels string");
             continue;
         }
@@ -567,7 +567,7 @@
 
         /* Sample rates parsing */
         rates_str_start = strstr(str_start, "Rates: ");
-        if (rates_str_start == NULL) {
+        if (rates_str_start == NULL || (check && (rates_str_start >= str_end))) {
             PAL_INFO(LOG_TAG, "cant find rates string");
             continue;
         }
@@ -686,7 +686,7 @@
     return default_format;
 }
 
-unsigned int USBCardConfig::readSupportedFormat(bool is_playback, uint32_t *format) {
+void USBCardConfig::readSupportedFormat(bool is_playback, uint32_t *format) {
     int i = 0;
     unsigned int bw;
     unsigned int bitWidth[MAX_SUPPORTED_FORMATS + 1];
@@ -729,11 +729,9 @@
     /* convert bw to format */
     for (int j = 0; j < i; j++)
         format[j] = getFormatByBitWidth(bitWidth[j]);
-
-    return 0;
 }
 
-unsigned int USBCardConfig::readSupportedSampleRate(bool is_playback, uint32_t *sample_rate) {
+void USBCardConfig::readSupportedSampleRate(bool is_playback, uint32_t *sample_rate) {
     usb_usecase_type_t type = is_playback ? USB_PLAYBACK : USB_CAPTURE;
 
     typename std::vector<std::shared_ptr<USBDeviceConfig>>::iterator iter;
@@ -760,50 +758,34 @@
 
     for (int j = 0; j < i; j++)
         PAL_DBG(LOG_TAG, "%s %d", is_playback ? "P" : "C", sample_rate[j]);
-
-    return 0;
 }
 
-unsigned int USBCardConfig::readSupportedChannelMask(bool is_playback, uint32_t *channel) {
+void USBCardConfig::readSupportedChannelMask(bool is_playback, uint32_t *channel) {
 
     int channels = getMaxChannels(is_playback);
     int channel_count;
-    uint32_t num_masks = 0;
 
     if (channels > MAX_HIFI_CHANNEL_COUNT)
         channels = MAX_HIFI_CHANNEL_COUNT;
-
+     /* need to calculate the mask from channel count either because this is
+      * the query case or the specified mask isn't valid for this device,
+      * or is more than the FW can handle
+      */
     if (is_playback) {
-        channel[num_masks++] = channels <= 2
+        channel[0] = channels <= 2
                      /* position mask for mono and stereo*/
                      ? audio_channel_out_mask_from_count(channels)
                      /* otherwise indexed */
                      : audio_channel_mask_for_index_assignment_from_count(channels);
-        // TODO: needs to figure out the accurate match of channel mask
     } else {
-        // For capture we report all supported channel masks from 1 channel up.
-        channel_count = MIN_CHANNEL_COUNT;
-        // audio_channel_in_mask_from_count() does the right conversion to either positional or
-        // indexed mask
-        for ( ; channel_count <= channels && num_masks < MAX_SUPPORTED_CHANNEL_MASKS; channel_count++) {
-            audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
-            if (channel_count <= 2) {
-                mask = audio_channel_in_mask_from_count(channel_count);
-                channel[num_masks++] = mask;
-            }
-            const audio_channel_mask_t index_mask =
-                    audio_channel_mask_for_index_assignment_from_count(channel_count);
-            if (mask != index_mask && num_masks < MAX_SUPPORTED_CHANNEL_MASKS) { // ensure index mask added.
-                channel[num_masks++] = index_mask;
-            }
-        }
+        channel[0] = channels <= 2
+             /* position mask for mono & stereo */
+             ? audio_channel_in_mask_from_count(channels)
+             /* otherwise indexed */
+             : audio_channel_mask_for_index_assignment_from_count(channels);
     }
-
-    for (size_t i = 0; i < num_masks; ++i) {
-        PAL_DBG(LOG_TAG, "%s supported ch %d channel[%zu] %08x num_masks %d",
-              is_playback ? "P" : "C", channels, i, channel[i], num_masks);
-    }
-    return num_masks;
+    PAL_DBG(LOG_TAG, "%s supported ch %d, channel mask: %08x ",
+            is_playback ? "P" : "C", channels, channel[0]);
 }
 
 bool USBCardConfig::readDefaultJackStatus(bool is_playback) {
diff --git a/ipc/HwBinders/pal_ipc_client/src/pal_client_wrapper.cpp b/ipc/HwBinders/pal_ipc_client/src/pal_client_wrapper.cpp
index 894da97..4f42240 100644
--- a/ipc/HwBinders/pal_ipc_client/src/pal_client_wrapper.cpp
+++ b/ipc/HwBinders/pal_ipc_client/src/pal_client_wrapper.cpp
@@ -713,8 +713,7 @@
         if (pal_client == nullptr)
             return ret;
 
-        hidl_vec<PalParamPayload> paramPayload;
-        paramPayload.resize(sizeof(PalParamPayload));
+        hidl_vec<PalParamPayload> paramPayload(1);
         paramPayload.data()->payload.resize(param_payload->payload_size);
         paramPayload.data()->size = param_payload->payload_size;
         memcpy(paramPayload.data()->payload.data(), param_payload->payload,
diff --git a/ipc/HwBinders/pal_ipc_server/src/pal_server_wrapper.cpp b/ipc/HwBinders/pal_ipc_server/src/pal_server_wrapper.cpp
index 1dbceda..99174e7 100644
--- a/ipc/HwBinders/pal_ipc_server/src/pal_server_wrapper.cpp
+++ b/ipc/HwBinders/pal_ipc_server/src/pal_server_wrapper.cpp
@@ -825,6 +825,14 @@
 {
     int32_t ret = 0;
     pal_param_payload *param_payload;
+    if (1 != paramPayload.size()) {
+        ALOGE("Invalid vector size");
+        return -EINVAL;
+    }
+    if (paramPayload.data()->size > paramPayload.data()->payload.size()) {
+        ALOGE("Invalid payload size");
+        return -EINVAL;
+    }
     param_payload = (pal_param_payload *)calloc (1,
                                     sizeof(pal_param_payload) + paramPayload.data()->size);
     if (!param_payload) {
diff --git a/resource_manager/inc/ResourceManager.h b/resource_manager/inc/ResourceManager.h
index a16e844..ed87d2f 100644
--- a/resource_manager/inc/ResourceManager.h
+++ b/resource_manager/inc/ResourceManager.h
@@ -82,6 +82,7 @@
 #define AUDIO_PARAMETER_KEY_DEVICE_MUX "device_mux_config"
 #define AUDIO_PARAMETER_KEY_UPD_DUTY_CYCLE "upd_duty_cycle_enable"
 #define AUDIO_PARAMETER_KEY_UPD_VIRTUAL_PORT "upd_virtual_port"
+#define AUDIO_PARAMETER_KEY_SPKR_XMAX_TMAX_LOG "spkr_xmax_tmax_logging_enable"
 #define MAX_PCM_NAME_SIZE 50
 #define MAX_STREAM_INSTANCES (sizeof(uint64_t) << 3)
 #define MIN_USECASE_PRIORITY 0xFFFFFFFF
@@ -507,6 +508,7 @@
     static std::mutex mResourceManagerMutex;
     static std::mutex mGraphMutex;
     static std::mutex mActiveStreamMutex;
+    static std::mutex mValidStreamMutex;
     static std::mutex mSleepMonitorMutex;
     static std::mutex mListFrontEndsMutex;
     static int snd_virt_card;
@@ -621,6 +623,8 @@
     /* Variable to store which speaker side is being used for call audio.
      * Valid for Stereo case only
      */
+    /*Variable to check XmaxTmaxLogging Enabled or not*/
+    static bool isSpkrXmaxTmaxLoggingEnabled;
     static bool isMainSpeakerRight;
     /* Variable to store Quick calibration time for Speaker protection */
     static int spQuickCalTime;
@@ -913,6 +917,7 @@
     static int setDualMonoEnableParam(struct str_parms *parms,char *value, int len);
     static int setSignalHandlerEnableParam(struct str_parms *parms,char *value, int len);
     static int setMuxconfigEnableParam(struct str_parms *parms,char *value, int len);
+    static int setSpkrXmaxTmaxLoggingParam(struct str_parms* parms, char* value, int len);
     static bool isLpiLoggingEnabled();
     static void processConfigParams(const XML_Char **attr);
     static bool isValidDevId(int deviceId);
@@ -944,6 +949,8 @@
     void unlockGraph() { mGraphMutex.unlock(); };
     void lockActiveStream() { mActiveStreamMutex.lock(); };
     void unlockActiveStream() { mActiveStreamMutex.unlock(); };
+    void lockValidStreamMutex() { mValidStreamMutex.lock(); };
+    void unlockValidStreamMutex() { mValidStreamMutex.unlock(); };
     void lockResourceManagerMutex() {mResourceManagerMutex.lock();};
     void unlockResourceManagerMutex() {mResourceManagerMutex.unlock();};
     void getSharedBEActiveStreamDevs(std::vector <std::tuple<Stream *, uint32_t>> &activeStreamDevs,
diff --git a/resource_manager/src/ResourceManager.cpp b/resource_manager/src/ResourceManager.cpp
index d037720..ec1a876 100644
--- a/resource_manager/src/ResourceManager.cpp
+++ b/resource_manager/src/ResourceManager.cpp
@@ -428,6 +428,7 @@
 std::mutex ResourceManager::mChargerBoostMutex;
 std::mutex ResourceManager::mGraphMutex;
 std::mutex ResourceManager::mActiveStreamMutex;
+std::mutex ResourceManager::mValidStreamMutex;
 std::mutex ResourceManager::mSleepMonitorMutex;
 std::mutex ResourceManager::mListFrontEndsMutex;
 std::vector <int> ResourceManager::listAllFrontEndIds = {0};
@@ -483,6 +484,7 @@
 int ResourceManager::wake_unlock_fd = -1;
 uint32_t ResourceManager::wake_lock_cnt = 0;
 static int max_session_num;
+bool ResourceManager::isSpkrXmaxTmaxLoggingEnabled = false;
 bool ResourceManager::isSpeakerProtectionEnabled = false;
 bool ResourceManager::isHandsetProtectionEnabled = false;
 bool ResourceManager::isChargeConcurrencyEnabled = false;
@@ -1295,7 +1297,9 @@
                 PAL_INFO(LOG_TAG, "%d state already handled", state);
             } else if (state == CARD_STATUS_OFFLINE) {
                 for (auto str: rm->mActiveStreams) {
+                    lockValidStreamMutex();
                     ret = increaseStreamUserCounter(str);
+                    unlockValidStreamMutex();
                     if (0 != ret) {
                         PAL_ERR(LOG_TAG, "Error incrementing the stream counter for the stream handle: %pK", str);
                         continue;
@@ -1311,7 +1315,9 @@
                         if (ret)
                             PAL_DBG(LOG_TAG, "Failed to unvote for stream type %d", type);
                     }
+                    lockValidStreamMutex();
                     ret = decreaseStreamUserCounter(str);
+                    unlockValidStreamMutex();
                     if (0 != ret) {
                         PAL_ERR(LOG_TAG, "Error decrementing the stream counter for the stream handle: %pK", str);
                     }
@@ -1337,7 +1343,9 @@
 
                 SoundTriggerCaptureProfile = GetCaptureProfileByPriority(nullptr);
                 for (auto str: rm->mActiveStreams) {
+                    lockValidStreamMutex();
                     ret = increaseStreamUserCounter(str);
+                    unlockValidStreamMutex();
                     if (0 != ret) {
                         PAL_ERR(LOG_TAG, "Error incrementing the stream counter for the stream handle: %pK", str);
                         continue;
@@ -1347,7 +1355,9 @@
                         PAL_ERR(LOG_TAG, "Ssr up handling failed for %pK ret %d",
                                           str, ret);
                     }
+                    lockValidStreamMutex();
                     ret = decreaseStreamUserCounter(str);
+                    unlockValidStreamMutex();
                     if (0 != ret) {
                         PAL_ERR(LOG_TAG, "Error decrementing the stream counter for the stream handle: %pK", str);
                     }
@@ -2685,8 +2695,8 @@
             {
                 PAL_INFO(LOG_TAG, "wfd TX is not in progress");
                 if (rm->num_proxy_channels) {
+                    PAL_INFO(LOG_TAG, "proxy device channel number: %d", rm->num_proxy_channels);
                     deviceattr->config.ch_info.channels = rm->num_proxy_channels;
-                    rm->num_proxy_channels = 0;
                 }
             }
             PAL_INFO(LOG_TAG, "PAL_DEVICE_OUT_PROXY sample rate %d bitwidth %d ch:%d",
@@ -3075,6 +3085,7 @@
     }
     PAL_DBG(LOG_TAG, "stream type %d", type);
     mActiveStreamMutex.lock();
+    mValidStreamMutex.lock();
     switch (type) {
         case PAL_STREAM_LOW_LATENCY:
         case PAL_STREAM_VOIP_RX:
@@ -3215,7 +3226,7 @@
 
     mAllActiveStreams.push_back(s);
 #endif
-
+    mValidStreamMutex.unlock();
     mActiveStreamMutex.unlock();
     PAL_DBG(LOG_TAG, "Exit. ret %d", ret);
     return ret;
@@ -3254,6 +3265,7 @@
 #endif
     PAL_INFO(LOG_TAG, "stream type %d", type);
     mActiveStreamMutex.lock();
+    mValidStreamMutex.lock();
     switch (type) {
         case PAL_STREAM_LOW_LATENCY:
         case PAL_STREAM_VOIP_RX:
@@ -3384,6 +3396,7 @@
     }
 
     deregisterstream(s, mActiveStreams);
+    mValidStreamMutex.unlock();
     mActiveStreamMutex.unlock();
 exit:
     PAL_DBG(LOG_TAG, "Exit. ret %d", ret);
@@ -3417,30 +3430,30 @@
 
 int ResourceManager::initStreamUserCounter(Stream *s)
 {
-    lockActiveStream();
+    lockValidStreamMutex();
     mActiveStreamUserCounter.insert(std::make_pair(s, std::make_pair(0, true)));
     s->initStreamSmph();
-    unlockActiveStream();
+    unlockValidStreamMutex();
     return 0;
 }
 
 int ResourceManager::deactivateStreamUserCounter(Stream *s)
 {
     std::map<Stream*, std::pair<uint32_t, bool>>::iterator it;
-    lockActiveStream();
+    lockValidStreamMutex();
     printStreamUserCounter(s);
     it = mActiveStreamUserCounter.find(s);
     if (it != mActiveStreamUserCounter.end() && it->second.second == true) {
         PAL_DBG(LOG_TAG, "stream %p is to be deactivated.", s);
         it->second.second = false;
-        unlockActiveStream();
+        unlockValidStreamMutex();
         s->waitStreamSmph();
         PAL_DBG(LOG_TAG, "stream %p is inactive.", s);
         s->deinitStreamSmph();
         return 0;
     } else {
         PAL_ERR(LOG_TAG, "stream %p is not found or inactive", s);
-        unlockActiveStream();
+        unlockValidStreamMutex();
         return -EINVAL;
     }
 }
@@ -3448,16 +3461,16 @@
 int ResourceManager::eraseStreamUserCounter(Stream *s)
 {
     std::map<Stream*, std::pair<uint32_t, bool>>::iterator it;
-    lockActiveStream();
+    lockValidStreamMutex();
     it = mActiveStreamUserCounter.find(s);
     if (it != mActiveStreamUserCounter.end()) {
         mActiveStreamUserCounter.erase(it);
         PAL_DBG(LOG_TAG, "stream counter for %p is erased.", s);
-        unlockActiveStream();
+        unlockValidStreamMutex();
         return 0;
     } else {
         PAL_ERR(LOG_TAG, "stream counter for %p is not found.", s);
-        unlockActiveStream();
+        unlockValidStreamMutex();
         return -EINVAL;
     }
 }
@@ -5001,7 +5014,7 @@
                 in_type != PAL_STREAM_CONTEXT_PROXY  &&
                 in_type != PAL_STREAM_VOICE_UI)) {
         *tx_conc = true;
-        if (!audio_capture_conc_enable) {
+        if (!audio_capture_conc_enable && in_type != PAL_STREAM_PROXY) {
             PAL_DBG(LOG_TAG, "pause on audio capture concurrency");
             *conc_en = false;
         }
@@ -7817,6 +7830,7 @@
     ret = setMuxconfigEnableParam(parms, value, len);
     ret = setUpdDutyCycleEnableParam(parms, value, len);
     ret = setUpdVirtualPortParam(parms, value, len);
+    ret = setSpkrXmaxTmaxLoggingParam(parms, value, len);
 
     /* Not checking return value as this is optional */
     setLpiLoggingParams(parms, value, len);
@@ -7955,6 +7969,29 @@
     return ret;
 }
 
+int ResourceManager::setSpkrXmaxTmaxLoggingParam(struct str_parms* parms,
+    char* value, int len)
+{
+    int ret = -EINVAL;
+
+    if (!value || !parms) {
+        return ret;
+    }
+
+    ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SPKR_XMAX_TMAX_LOG,
+        value, len);
+    PAL_VERBOSE(LOG_TAG, " value %s", value);
+
+    if (ret >= 0) {
+        if (value && !strncmp(value, "true", sizeof("true")))
+            ResourceManager::isSpkrXmaxTmaxLoggingEnabled = true;
+
+        str_parms_del(parms, AUDIO_PARAMETER_KEY_SPKR_XMAX_TMAX_LOG);
+    }
+
+    return ret;
+}
+
 int ResourceManager::setUpdVirtualPortParam(struct str_parms *parms, char *value, int len)
 {
     int ret = -EINVAL;
@@ -7964,8 +8001,7 @@
 
     ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_UPD_VIRTUAL_PORT,
                             value, len);
-
-    PAL_VERBOSE(LOG_TAG," value %s", value);
+    PAL_VERBOSE(LOG_TAG, " value %s", value);
 
     if (ret >= 0) {
         if (value && !strncmp(value, "true", sizeof("true")))
@@ -8843,20 +8879,20 @@
         {
             bool match = false;
             std::list<Stream*>::iterator sIter;
-            lockActiveStream();
+            lockValidStreamMutex();
             for(sIter = mActiveStreams.begin(); sIter != mActiveStreams.end(); sIter++) {
                 match = (*sIter)->checkStreamMatch(pal_device_id, pal_stream_type);
                 if (match) {
                     if (increaseStreamUserCounter(*sIter) < 0)
                         continue;
-                    unlockActiveStream();
+                    unlockValidStreamMutex();
                     status = (*sIter)->getEffectParameters(param_payload);
-                    lockActiveStream();
+                    lockValidStreamMutex();
                     decreaseStreamUserCounter(*sIter);
                     break;
                 }
             }
-            unlockActiveStream();
+            unlockValidStreamMutex();
             break;
         }
         default:
@@ -9205,7 +9241,8 @@
                          (sAttr.type == PAL_STREAM_PCM_OFFLOAD) ||
                          (sAttr.type == PAL_STREAM_SPATIAL_AUDIO) ||
                          (sAttr.type == PAL_STREAM_DEEP_BUFFER) ||
-                         (sAttr.type == PAL_STREAM_COMPRESSED))) {
+                         (sAttr.type == PAL_STREAM_COMPRESSED) ||
+                         (sAttr.type == PAL_STREAM_GENERIC))) {
                         str->getAssociatedDevices(associatedDevices);
                         for (int i = 0; i < associatedDevices.size(); i++) {
                             if (!isDeviceActive_l(associatedDevices[i], str) ||
@@ -9256,6 +9293,22 @@
 
                 SortAndUnique(rxDevices);
                 SortAndUnique(txDevices);
+
+                /*
+                 * If there a switch in SCO configurations and at the time of BT_SCO=on,
+                 * there are streams active with old SCO configs as well as on another
+                 * device. In this case, we need to disconnect streams over SCO first and
+                 * move them to new SCO configs, before we move streams on other devices
+                 * to SCO. This is ensured by moving SCO to the beginning of the disconnect
+                 * device list.
+                 */
+                {
+                    dAttr.id = PAL_DEVICE_OUT_BLUETOOTH_SCO;
+                    dev = Device::getInstance(&dAttr, rm);
+                    auto it = std::find(rxDevices.begin(),rxDevices.end(),dev);
+                    if ((it != rxDevices.end()) && (it != rxDevices.begin()))
+                        std::iter_swap(it, rxDevices.begin());
+                }
                 mActiveStreamMutex.unlock();
 
                 for (auto& device : rxDevices) {
@@ -9452,7 +9505,8 @@
                             (streamType == PAL_STREAM_PCM_OFFLOAD) ||
                             (streamType == PAL_STREAM_DEEP_BUFFER) ||
                             (streamType == PAL_STREAM_SPATIAL_AUDIO) ||
-                            (streamType == PAL_STREAM_COMPRESSED)) {
+                            (streamType == PAL_STREAM_COMPRESSED) ||
+                            (streamType == PAL_STREAM_GENERIC)) {
                             (*sIter)->suspendedDevIds.clear();
                             (*sIter)->suspendedDevIds.push_back(a2dp_dattr.id);
                             PAL_DBG(LOG_TAG, "a2dp resumed, mark sco streams as to route them later");
@@ -9771,7 +9825,7 @@
         case PAL_PARAM_ID_UIEFFECT:
         {
             bool match = false;
-            lockActiveStream();
+            lockValidStreamMutex();
             std::list<Stream*>::iterator sIter;
             for(sIter = mActiveStreams.begin(); sIter != mActiveStreams.end();
                     sIter++) {
@@ -9781,9 +9835,9 @@
                     if (match) {
                         if (increaseStreamUserCounter(*sIter) < 0)
                             continue;
-                        unlockActiveStream();
+                        unlockValidStreamMutex();
                         status = (*sIter)->setEffectParameters(param_payload);
-                        lockActiveStream();
+                        lockValidStreamMutex();
                         decreaseStreamUserCounter(*sIter);
                         if (status) {
                             PAL_ERR(LOG_TAG, "failed to set param for pal_device_id=%x stream_type=%x",
@@ -9794,7 +9848,7 @@
                     PAL_ERR(LOG_TAG, "There is no active stream.");
                 }
             }
-            unlockActiveStream();
+            unlockValidStreamMutex();
         }
         break;
         default:
diff --git a/session/src/PayloadBuilder.cpp b/session/src/PayloadBuilder.cpp
index f995e99..9a8945a 100644
--- a/session/src/PayloadBuilder.cpp
+++ b/session/src/PayloadBuilder.cpp
@@ -27,7 +27,7 @@
  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * Changes from Qualcomm Innovation Center are provided under the following license:
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted (subject to the limitations in the
@@ -3945,6 +3945,23 @@
                 }
             }
         break;
+        case PARAM_ID_SP_TMAX_XMAX_LOGGING:
+        {
+            param_id_sp_tmax_xmax_logging_t *data;
+            data = (param_id_sp_tmax_xmax_logging_t*)param;
+
+            payloadSize = sizeof(struct apm_module_param_data_t) +
+                sizeof(param_id_sp_tmax_xmax_logging_t) + (sizeof(sp_tmax_xmax_params_t) * data->num_ch);
+
+            padBytes = PAL_PADDING_8BYTE_ALIGN(payloadSize);
+            payloadInfo = (uint8_t*)calloc(1, payloadSize + padBytes);
+            if (!payloadInfo) {
+                PAL_ERR(LOG_TAG, "payloadInfo malloc failed %s", strerror(errno));
+                return;
+            }
+            header = (struct apm_module_param_data_t*)payloadInfo;
+        }
+        break;
         default:
             {
                 PAL_ERR(LOG_TAG, "unknown param id 0x%x", param_id);
diff --git a/session/src/SessionAlsaCompress.cpp b/session/src/SessionAlsaCompress.cpp
index 25648a9..5778888 100644
--- a/session/src/SessionAlsaCompress.cpp
+++ b/session/src/SessionAlsaCompress.cpp
@@ -1707,6 +1707,9 @@
 
     switch (sAttr.direction) {
         case PAL_AUDIO_OUTPUT:
+            if (compress && playback_started) {
+                status = compress_stop(compress);
+            }
             // Deregister for callback for Soft Pause
             if (isPauseRegistrationDone) {
                 payload_size = sizeof(struct agm_event_reg_cfg);
@@ -1735,10 +1738,6 @@
                     status = 0;
                 }
             }
-
-            if (compress && playback_started) {
-                status = compress_stop(compress);
-            }
             break;
         case PAL_AUDIO_INPUT:
             if (compress) {
diff --git a/session/src/SessionAlsaPcm.cpp b/session/src/SessionAlsaPcm.cpp
index f3516e9..2adcfcc 100644
--- a/session/src/SessionAlsaPcm.cpp
+++ b/session/src/SessionAlsaPcm.cpp
@@ -2741,6 +2741,8 @@
             }
 
 skip_ultrasound_gain:
+            if (tagConfig)
+                free(tagConfig);
             if (status)
                 PAL_ERR(LOG_TAG, "Failed to set Ultrasound Gain %d", status);
             return 0;
diff --git a/stream/src/Stream.cpp b/stream/src/Stream.cpp
index 1f8f2c0..2637c53 100644
--- a/stream/src/Stream.cpp
+++ b/stream/src/Stream.cpp
@@ -904,8 +904,8 @@
                     rm->unlockGraph();
                     goto exit;
                 }
-                rm->unlockGraph();
                 iter = mDevices.erase(iter);
+                rm->unlockGraph();
             }
         } else {
             PAL_ERR(LOG_TAG, "BT SCO output device is not ready");
@@ -972,8 +972,8 @@
                     rm->unlockGraph();
                     goto exit;
                 }
-                rm->unlockGraph();
                 iter = mDevices.erase(iter);
+                rm->unlockGraph();
             }
         } else {
             // For non-combo device, mute the stream and route to speaker or handset
@@ -984,8 +984,8 @@
             suspendedDevIds.clear();
             suspendedDevIds.push_back(dattr.id);
 
+            rm->lockGraph();
             for (int i = 0; i < mDevices.size(); i++) {
-                rm->lockGraph();
                 status = session->disconnectSessionDevice(this, mStreamAttr->type, mDevices[i]);
                 if (0 != status) {
                     PAL_ERR(LOG_TAG, "disconnectSessionDevice failed:%d", status);
@@ -1009,9 +1009,9 @@
                     rm->unlockGraph();
                     goto exit;
                 }
-                rm->unlockGraph();
             }
             mDevices.clear();
+            rm->unlockGraph();
             clearOutPalDevices(this);
 
             /* Check whether there's active stream associated with handset or speaker
@@ -1141,14 +1141,15 @@
                     goto exit;
                 }
             }
-            rm->unlockGraph();
 
             status = mDevices[i]->close();
             if (0 != status) {
                 PAL_ERR(LOG_TAG, "device close failed with status %d", status);
+                rm->unlockGraph();
                 goto exit;
             }
             mDevices.erase(mDevices.begin() + i);
+            rm->unlockGraph();
             break;
         }
     }
diff --git a/stream/src/StreamCommon.cpp b/stream/src/StreamCommon.cpp
index 3c8c7e1..d9cf880 100644
--- a/stream/src/StreamCommon.cpp
+++ b/stream/src/StreamCommon.cpp
@@ -274,7 +274,6 @@
 
     rm->lockGraph();
     status = session->close(this);
-    rm->unlockGraph();
     if (0 != status) {
         PAL_ERR(LOG_TAG, "Error:session close failed with status %d", status);
     }
@@ -287,6 +286,7 @@
     }
     PAL_VERBOSE(LOG_TAG, "closed the devices successfully");
     currentState = STREAM_IDLE;
+    rm->unlockGraph();
     rm->checkAndSetDutyCycleParam();
 
     mStreamMutex.unlock();
diff --git a/stream/src/StreamCompress.cpp b/stream/src/StreamCompress.cpp
index 9fe128e..72a7ce1 100644
--- a/stream/src/StreamCompress.cpp
+++ b/stream/src/StreamCompress.cpp
@@ -238,7 +238,6 @@
     }
     rm->lockGraph();
     status = session->close(this);
-    rm->unlockGraph();
     if (0 != status) {
         PAL_ERR(LOG_TAG,"session close failed with status %d", status);
     }
@@ -254,6 +253,7 @@
     }
     PAL_VERBOSE(LOG_TAG,"closed the devices successfully");
     currentState = STREAM_IDLE;
+    rm->unlockGraph();
     rm->checkAndSetDutyCycleParam();
     mStreamMutex.unlock();
 
diff --git a/stream/src/StreamPCM.cpp b/stream/src/StreamPCM.cpp
index 5f2c5a3..4bb80b2 100644
--- a/stream/src/StreamPCM.cpp
+++ b/stream/src/StreamPCM.cpp
@@ -312,7 +312,6 @@
 
     rm->lockGraph();
     status = session->close(this);
-    rm->unlockGraph();
     if (0 != status) {
         PAL_ERR(LOG_TAG, "session close failed with status %d", status);
     }
@@ -325,6 +324,7 @@
     }
     PAL_VERBOSE(LOG_TAG, "closed the devices successfully");
     currentState = STREAM_IDLE;
+    rm->unlockGraph();
     rm->checkAndSetDutyCycleParam();
     mStreamMutex.unlock();
 
diff --git a/stream/src/StreamSoundTrigger.cpp b/stream/src/StreamSoundTrigger.cpp
index 2014c1d..fc32972 100644
--- a/stream/src/StreamSoundTrigger.cpp
+++ b/stream/src/StreamSoundTrigger.cpp
@@ -389,6 +389,21 @@
     }
 
     std::lock_guard<std::mutex> lck(mStreamMutex);
+    if (cur_state_ == st_buffering_) {
+        if (!this->force_nlpi_vote) {
+            rm->voteSleepMonitor(this, true, true);
+            this->force_nlpi_vote = true;
+
+            offset = vui_intf_->GetReadOffset();
+            if (offset) {
+                reader_->advanceReadOffset(offset);
+                vui_intf_->SetReadOffset(0);
+            }
+        }
+    } else {
+        PAL_ERR(LOG_TAG, "Invalid Stream Current State %d", GetCurrentStateId());
+        return size;
+    }
     if (vui_ptfm_info_->GetEnableDebugDumps() && !lab_fd_) {
         ST_DBG_FILE_OPEN_WR(lab_fd_, ST_DEBUG_DUMP_LOCATION,
             "lab_reading", "bin", lab_cnt);
@@ -396,16 +411,6 @@
             lab_cnt);
         lab_cnt++;
     }
-    if (cur_state_ == st_buffering_ && !this->force_nlpi_vote) {
-        rm->voteSleepMonitor(this, true, true);
-        this->force_nlpi_vote = true;
-
-        offset = vui_intf_->GetReadOffset();
-        if (offset) {
-            reader_->advanceReadOffset(offset);
-            vui_intf_->SetReadOffset(0);
-        }
-    }
 
     std::shared_ptr<StEventConfig> ev_cfg(
         new StReadBufferEventConfig((void *)buf));
@@ -1139,6 +1144,11 @@
         engine = HandleEngineLoad((uint8_t *)iter.second.first,
                                   iter.second.second,
                                   iter.first, model_type_);
+        if (!engine) {
+            PAL_ERR(LOG_TAG, "Failed to create engine");
+            status = -EINVAL;
+            goto error_exit;
+        }
         std::shared_ptr<EngineCfg> engine_cfg(new EngineCfg(
             engine_id, engine, (void *)iter.second.first, iter.second.second));
 
@@ -1173,6 +1183,7 @@
     }
     engines_.clear();
     gsl_engine_.reset();
+    rm->resetStreamInstanceID(this, mInstanceID);
     if (sm_config_) {
         free(sm_config_);
         sm_config_ = nullptr;