Merge 978eb819b860bc121477d9ea2cee8af40eaaa1d1 on remote branch

Change-Id: Ic89ce1821afdf6d827772ced0b671c21b13f604f
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/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/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/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/resource_manager/inc/ResourceManager.h b/resource_manager/inc/ResourceManager.h
index a16e844..f5fcfda 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
@@ -621,6 +622,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 +916,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);
diff --git a/resource_manager/src/ResourceManager.cpp b/resource_manager/src/ResourceManager.cpp
index 0e4444c..374d1ff 100644
--- a/resource_manager/src/ResourceManager.cpp
+++ b/resource_manager/src/ResourceManager.cpp
@@ -483,6 +483,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;
@@ -7817,6 +7818,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 +7957,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 +7989,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")))
@@ -9205,7 +9229,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 +9281,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 +9493,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");
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);