Merge "pal: Update volume configuration payload for pcm"
diff --git a/Pal.cpp b/Pal.cpp
index f918fe9..46f8682 100644
--- a/Pal.cpp
+++ b/Pal.cpp
@@ -1143,22 +1143,23 @@
                 break;
         }
 
-      /*
-       * When USB headset is disconnected the music playback pauses
-       * and the policy manager sends routing=0. But if the USB is connected
-       * back before the standby time, it can not switch device to usb hs any more
-       * because current pal device is usb hs which equals new device when resuming playback.
-       * So routing to default device first during handling routing = 0 msg will guarantee
-       * the device switch to usb can be executed once USB is connected again.
-       */
-        bool curPalDevice_usb = curPalDevices.find(PAL_DEVICE_OUT_USB_DEVICE) != curPalDevices.end() ||
-                                curPalDevices.find(PAL_DEVICE_OUT_USB_HEADSET) != curPalDevices.end();
-        bool activeDevices_usb = activeDevices.find(PAL_DEVICE_OUT_USB_DEVICE) != activeDevices.end() ||
-                                 activeDevices.find(PAL_DEVICE_OUT_USB_HEADSET) != activeDevices.end();
-        bool usb_active = rm->isDeviceAvailable(PAL_DEVICE_OUT_USB_DEVICE) ||
-                          rm->isDeviceAvailable(PAL_DEVICE_OUT_USB_HEADSET);
+        /*
+        * When headset is disconnected the music playback pauses
+        * and the policy manager sends routing=0. But if the headset is connected
+        * back before the standby time, it can not switch device to headset any more
+        * because current pal device is headset which equals new device when resuming playback.
+        * So routing to default device first during handling routing = 0 msg will guarantee
+        * the device switch to headset can be executed once headset is connected again.
+        */
         if (devices[0].id == PAL_DEVICE_NONE &&
-            curPalDevice_usb && activeDevices_usb && !usb_active)
+            (rm->isDisconnectedDeviceStillActive(curPalDevices,activeDevices,
+            PAL_DEVICE_OUT_USB_DEVICE) ||
+            rm->isDisconnectedDeviceStillActive(curPalDevices,activeDevices,
+            PAL_DEVICE_OUT_USB_HEADSET) ||
+            rm->isDisconnectedDeviceStillActive(curPalDevices,activeDevices,
+            PAL_DEVICE_OUT_WIRED_HEADPHONE) ||
+            rm->isDisconnectedDeviceStillActive(curPalDevices,activeDevices,
+            PAL_DEVICE_OUT_WIRED_HEADSET)))
         {
             devices[0].id = PAL_DEVICE_OUT_SPEAKER;
         }
diff --git a/device/inc/Device.h b/device/inc/Device.h
index c14a16a..6a9fc51 100644
--- a/device/inc/Device.h
+++ b/device/inc/Device.h
@@ -127,6 +127,7 @@
     virtual int getCodecConfig(struct pal_media_config *config);
     static std::shared_ptr<Device> getObject(pal_device_id_t dev_id);
     int updateCustomPayload(void *payload, size_t size);
+    int freeCustomPayload(uint8_t **payload, size_t *payloadSize);
     void* getCustomPayload();
     size_t getCustomPayloadSize();
     virtual int32_t setDeviceParameter(uint32_t param_id, void *param);
diff --git a/device/src/Device.cpp b/device/src/Device.cpp
index 076a8a5..f09bfb2 100644
--- a/device/src/Device.cpp
+++ b/device/src/Device.cpp
@@ -377,6 +377,16 @@
     return status;
 }
 
+int Device::freeCustomPayload(uint8_t **payload, size_t *payloadSize)
+{
+    if (*payload) {
+        free(*payload);
+        *payload = NULL;
+        *payloadSize = 0;
+    }
+    return 0;
+}
+
 int Device::updateCustomPayload(void *payload, size_t size)
 {
     if (!customPayloadSize) {
diff --git a/device/src/USBAudio.cpp b/device/src/USBAudio.cpp
index a27fd25..cb6f8ac 100644
--- a/device/src/USBAudio.cpp
+++ b/device/src/USBAudio.cpp
@@ -192,7 +192,7 @@
     builder->payloadUsbAudioConfig(&payload, &payloadSize, miid, &cfg);
     if (payloadSize) {
         status = updateCustomPayload(payload, payloadSize);
-        delete[] payload;
+        freeCustomPayload(&payload, &payloadSize);
         if (0 != status) {
             PAL_ERR(LOG_TAG,"updateCustomPayload Failed\n");
             goto exit;
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 4f42240..b0bf840 100644
--- a/ipc/HwBinders/pal_ipc_client/src/pal_client_wrapper.cpp
+++ b/ipc/HwBinders/pal_ipc_client/src/pal_client_wrapper.cpp
@@ -351,12 +351,11 @@
         if (pal_client == nullptr)
             return ret;
 
-        hidl_vec<PalStreamAttributes> attr_hidl;
+        hidl_vec<PalStreamAttributes> attr_hidl(1);
         hidl_vec<PalDevice> devs_hidl;
         hidl_vec<ModifierKV> modskv_hidl;
         uint16_t in_channels = 0;
         uint16_t out_channels = 0;
-        uint32_t dev_size = 0;
         int cnt = 0;
         uint8_t *temp = NULL;
         struct pal_stream_info info = attr->info.opt_stream_info;
@@ -367,8 +366,6 @@
             info.version, info.size, info.duration_us, info.has_video, info.is_streaming,
             info.loopback_type);
 
-        attr_hidl.resize(sizeof(::vendor::qti::hardware::pal::V1_0::PalStreamAttributes) + in_channels +
-                         out_channels);
         attr_hidl.data()->type = (PalStreamType)attr->type;
         attr_hidl.data()->info.version = info.version;
         attr_hidl.data()->info.size = info.size;
@@ -382,7 +379,8 @@
 
         if (in_channels) {
             attr_hidl.data()->in_media_config.ch_info.channels = attr->in_media_config.ch_info.channels;
-            attr_hidl.data()->in_media_config.ch_info.ch_map = attr->in_media_config.ch_info.ch_map;
+            memcpy(&attr_hidl.data()->in_media_config.ch_info.ch_map, &attr->in_media_config.ch_info.ch_map,
+                sizeof(uint8_t[64]));
         }
         attr_hidl.data()->in_media_config.aud_fmt_id = (PalAudioFmt)attr->in_media_config.aud_fmt_id;
 
@@ -394,26 +392,28 @@
         attr_hidl.data()->out_media_config.bit_width = attr->out_media_config.bit_width;
         if (out_channels) {
             attr_hidl.data()->out_media_config.ch_info.channels = attr->out_media_config.ch_info.channels;
-            attr_hidl.data()->out_media_config.ch_info.ch_map = attr->out_media_config.ch_info.ch_map;
+            memcpy(&attr_hidl.data()->out_media_config.ch_info.ch_map, &attr->out_media_config.ch_info.ch_map,
+                sizeof(uint8_t[64]));
         }
         attr_hidl.data()->out_media_config.aud_fmt_id = (PalAudioFmt)attr->out_media_config.aud_fmt_id;
         if (devices) {
-            dev_size = no_of_devices * sizeof(struct pal_device);
-            devs_hidl.resize(dev_size);
-            PalDevice *dev_hidl = devs_hidl.data();
+            devs_hidl.resize(no_of_devices);
             for ( cnt = 0; cnt < no_of_devices; cnt++) {
-                 dev_hidl->id =(PalDeviceId)devices[cnt].id;
-                 dev_hidl->config.sample_rate = devices[cnt].config.sample_rate;
-                 dev_hidl->config.bit_width = devices[cnt].config.bit_width;
-                 dev_hidl->config.ch_info.channels = devices[cnt].config.ch_info.channels;
-                 dev_hidl->config.ch_info.ch_map = devices[cnt].config.ch_info.ch_map;
-                 dev_hidl->config.aud_fmt_id = (PalAudioFmt)devices[cnt].config.aud_fmt_id;
-                 dev_hidl =  (PalDevice *)(devs_hidl.data() + sizeof(PalDevice));
+                 devs_hidl[cnt].id =(PalDeviceId)devices[cnt].id;
+                 devs_hidl[cnt].config.sample_rate = devices[cnt].config.sample_rate;
+                 devs_hidl[cnt].config.bit_width = devices[cnt].config.bit_width;
+                 devs_hidl[cnt].config.ch_info.channels = devices[cnt].config.ch_info.channels;
+                 memcpy(&devs_hidl[cnt].config.ch_info.ch_map, &devices[cnt].config.ch_info.ch_map,
+                 sizeof(uint8_t [64]));
+                 devs_hidl[cnt].config.aud_fmt_id = (PalAudioFmt)devices[cnt].config.aud_fmt_id;
             }
         }
         if (modifiers) {
-            modskv_hidl.resize(sizeof(struct modifier_kv) * no_of_modifiers);
-            memcpy(modskv_hidl.data(), modifiers, sizeof(struct modifier_kv) * no_of_modifiers);
+            modskv_hidl.resize(no_of_modifiers);
+            for ( cnt = 0; cnt < no_of_modifiers; cnt++) {
+                modskv_hidl[cnt].key = modifiers[cnt].key;
+                modskv_hidl[cnt].value = modifiers[cnt].value;
+            } 
         }
         pal_client->ipc_pal_stream_open(attr_hidl, no_of_devices, devs_hidl, no_of_modifiers,
                                         modskv_hidl, ClbkBinder, cookie,
@@ -777,7 +777,6 @@
 {
     hidl_vec<PalDevice> devs_hidl;
     int32_t cnt = 0;
-    uint32_t dev_size = 0;
     int32_t ret = -EINVAL;
 
     if (!pal_server_died) {
@@ -788,18 +787,16 @@
 
 
         if (devices) {
-           dev_size = no_of_devices * sizeof(struct pal_device);
-           ALOGD("dev_size %d", dev_size);
-           devs_hidl.resize(dev_size);
-           PalDevice *dev_hidl = devs_hidl.data();
+           ALOGD("no_of_devices %d", no_of_devices);
+           devs_hidl.resize(no_of_devices);
            for (cnt = 0; cnt < no_of_devices; cnt++) {
-                dev_hidl->id =(PalDeviceId)devices[cnt].id;
-                dev_hidl->config.sample_rate = devices[cnt].config.sample_rate;
-                dev_hidl->config.bit_width = devices[cnt].config.bit_width;
-                dev_hidl->config.ch_info.channels = devices[cnt].config.ch_info.channels;
-                dev_hidl->config.ch_info.ch_map = devices[cnt].config.ch_info.ch_map;
-                dev_hidl->config.aud_fmt_id = (PalAudioFmt)devices[cnt].config.aud_fmt_id;
-                dev_hidl =  (PalDevice *)(devs_hidl.data() + sizeof(PalDevice));
+                devs_hidl[cnt].id =(PalDeviceId)devices[cnt].id;
+                devs_hidl[cnt].config.sample_rate = devices[cnt].config.sample_rate;
+                devs_hidl[cnt].config.bit_width = devices[cnt].config.bit_width;
+                devs_hidl[cnt].config.ch_info.channels = devices[cnt].config.ch_info.channels;
+                memcpy(&devs_hidl[cnt].config.ch_info.ch_map, &devices[cnt].config.ch_info.ch_map,
+                sizeof(uint8_t [64]));
+                devs_hidl[cnt].config.aud_fmt_id = (PalAudioFmt)devices[cnt].config.aud_fmt_id;
            }
            ret = pal_client->ipc_pal_stream_set_device((PalStreamHandle)stream_handle,
                                                        no_of_devices, devs_hidl);
@@ -819,7 +816,7 @@
 int32_t pal_stream_set_volume(pal_stream_handle_t *stream_handle,
                               struct pal_volume_data *volume)
 {
-    hidl_vec<PalVolumeData> vol;
+    hidl_vec<PalVolumeData> vol(1);
     int32_t ret = -EINVAL;
     if (volume == NULL) {
        ALOGE("Invalid volume");
@@ -832,8 +829,6 @@
             return ret;
 
         uint32_t noOfVolPair = volume->no_of_volpair;
-        uint32_t volSize = sizeof(PalVolumeData);
-        vol.resize(volSize);
         vol.data()->volPair.resize(sizeof(PalChannelVolKv) * noOfVolPair);
         vol.data()->noOfVolPairs = noOfVolPair;
         memcpy(vol.data()->volPair.data(), volume->volume_pair,
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 3381842..ba2ee12 100644
--- a/ipc/HwBinders/pal_ipc_server/src/pal_server_wrapper.cpp
+++ b/ipc/HwBinders/pal_ipc_server/src/pal_server_wrapper.cpp
@@ -510,24 +510,22 @@
     }
 
     if (devs_hidl.size()) {
-        PalDevice *dev_hidl = NULL;
         devices = (struct pal_device *)calloc (1,
                                       sizeof(struct pal_device) * noOfDevices);
         if (!devices) {
             ALOGE("Not enough memory for devices");
             goto exit;
         }
-        dev_hidl = (PalDevice *)devs_hidl.data();
+
         for ( cnt = 0; cnt < noOfDevices; cnt++) {
-             devices[cnt].id = (pal_device_id_t)dev_hidl->id;
-             devices[cnt].config.sample_rate = dev_hidl->config.sample_rate;
-             devices[cnt].config.bit_width = dev_hidl->config.bit_width;
-             devices[cnt].config.ch_info.channels = dev_hidl->config.ch_info.channels;
-             memcpy(&devices[cnt].config.ch_info.ch_map, &dev_hidl->config.ch_info.ch_map,
+             devices[cnt].id = (pal_device_id_t)devs_hidl[cnt].id;
+             devices[cnt].config.sample_rate = devs_hidl[cnt].config.sample_rate;
+             devices[cnt].config.bit_width = devs_hidl[cnt].config.bit_width;
+             devices[cnt].config.ch_info.channels = devs_hidl[cnt].config.ch_info.channels;
+             memcpy(&devices[cnt].config.ch_info.ch_map, &devs_hidl[cnt].config.ch_info.ch_map,
                     sizeof(uint8_t [64]));
              devices[cnt].config.aud_fmt_id =
-                                  (pal_audio_fmt_t)dev_hidl->config.aud_fmt_id;
-             dev_hidl =  (PalDevice *)(dev_hidl + sizeof(PalDevice));
+                                  (pal_audio_fmt_t)devs_hidl[cnt].config.aud_fmt_id;
         }
     }
 
@@ -881,25 +879,28 @@
     struct pal_device *devices = NULL;
     int cnt = 0;
     int32_t ret = -ENOMEM;
+
+    if (noOfDevices > devs_hidl.size()) {
+        ALOGE("Invalid noOfDevices");
+        return -EINVAL;
+    }
     if (devs_hidl.size()) {
-        PalDevice *dev_hidl = NULL;
         devices = (struct pal_device *)calloc (1,
                                     sizeof(struct pal_device) * noOfDevices);
         if (!devices) {
             ALOGE("Not enough memory for devices");
             goto exit;
         }
-        dev_hidl = (PalDevice *)devs_hidl.data();
+
         for (cnt = 0; cnt < noOfDevices; cnt++) {
-            devices[cnt].id = (pal_device_id_t)dev_hidl->id;
-            devices[cnt].config.sample_rate = dev_hidl->config.sample_rate;
-            devices[cnt].config.bit_width = dev_hidl->config.bit_width;
-            devices[cnt].config.ch_info.channels = dev_hidl->config.ch_info.channels;
-            memcpy(&devices[cnt].config.ch_info.ch_map, &dev_hidl->config.ch_info.ch_map,
+            devices[cnt].id = (pal_device_id_t)devs_hidl[cnt].id;
+            devices[cnt].config.sample_rate = devs_hidl[cnt].config.sample_rate;
+            devices[cnt].config.bit_width = devs_hidl[cnt].config.bit_width;
+            devices[cnt].config.ch_info.channels = devs_hidl[cnt].config.ch_info.channels;
+            memcpy(&devices[cnt].config.ch_info.ch_map, &devs_hidl[cnt].config.ch_info.ch_map,
                    sizeof(uint8_t [64]));
             devices[cnt].config.aud_fmt_id =
-                                (pal_audio_fmt_t)dev_hidl->config.aud_fmt_id;
-            dev_hidl = (PalDevice *)(dev_hidl + sizeof(PalDevice));
+                                (pal_audio_fmt_t)devs_hidl[cnt].config.aud_fmt_id;
         }
     }
 
@@ -923,6 +924,14 @@
     struct pal_volume_data *volume = nullptr;
     uint32_t noOfVolPairs = vol.data()->noOfVolPairs;
     int32_t ret = -ENOMEM;
+    if (1 != vol.size()) {
+        ALOGE("Invalid vol pairs");
+        return -EINVAL;
+    }
+    if (noOfVolPairs > vol.data()->volPair.size()) {
+        ALOGE("Invalid vol vector size");
+        return -EINVAL;
+    }
     volume = (struct pal_volume_data *) calloc(1,
                                         sizeof(struct pal_volume_data) +
                                         noOfVolPairs * sizeof(pal_channel_vol_kv));
diff --git a/resource_manager/inc/ResourceManager.h b/resource_manager/inc/ResourceManager.h
index ed87d2f..5e01198 100644
--- a/resource_manager/inc/ResourceManager.h
+++ b/resource_manager/inc/ResourceManager.h
@@ -45,6 +45,7 @@
 #include "PalCommon.h"
 #include <array>
 #include <map>
+#include <set>
 #include <expat.h>
 #include <stdio.h>
 #include <queue>
@@ -931,6 +932,7 @@
     bool isDeviceAvailable(pal_device_id_t id);
     bool isDeviceAvailable(std::vector<std::shared_ptr<Device>> devices, pal_device_id_t id);
     bool isDeviceAvailable(struct pal_device *devices, uint32_t devCount, pal_device_id_t id);
+    bool isDisconnectedDeviceStillActive(std::set<pal_device_id_t> &curPalDevices, std::set<pal_device_id_t> &activeDevices, pal_device_id_t id);
     bool isDeviceReady(pal_device_id_t id);
     static bool isBtScoDevice(pal_device_id_t id);
     static bool isBtDevice(pal_device_id_t id);
diff --git a/resource_manager/src/ResourceManager.cpp b/resource_manager/src/ResourceManager.cpp
index ec1a876..a0151a0 100644
--- a/resource_manager/src/ResourceManager.cpp
+++ b/resource_manager/src/ResourceManager.cpp
@@ -9383,7 +9383,8 @@
 
                 dev->setDeviceParameter(param_id, param_payload);
                 dev->getDeviceParameter(param_id, (void **)&current_param_bt_a2dp);
-                if (current_param_bt_a2dp->reconfig == true) {
+                if ((current_param_bt_a2dp->reconfig == true) &&
+                    (current_param_bt_a2dp->a2dp_suspended == false)) {
                     param_bt_a2dp.a2dp_suspended = true;
                     mResourceManagerMutex.unlock();
                     status = dev->setDeviceParameter(PAL_PARAM_ID_BT_A2DP_SUSPENDED,
@@ -10540,6 +10541,15 @@
     return isAvailable;
 }
 
+bool ResourceManager::isDisconnectedDeviceStillActive(
+    std::set<pal_device_id_t> &curPalDevices, std::set<pal_device_id_t> &activeDevices,
+    pal_device_id_t id)
+{
+    return (!isDeviceAvailable(id)) &&
+        (curPalDevices.find(id) != curPalDevices.end()) &&
+        (activeDevices.find(id) != activeDevices.end());
+}
+
 bool ResourceManager::isDeviceReady(pal_device_id_t id)
 {
     struct pal_device dAttr;
diff --git a/session/inc/PayloadBuilder.h b/session/inc/PayloadBuilder.h
index 183e8df..0228668 100644
--- a/session/inc/PayloadBuilder.h
+++ b/session/inc/PayloadBuilder.h
@@ -200,6 +200,9 @@
     void payloadVolumeConfig(uint8_t** payload, size_t* size,
                            uint32_t miid,
                            struct pal_volume_data * data);
+    void payloadMultichVolumemConfig(uint8_t** payload, size_t* size,
+                           uint32_t miid,
+                           struct pal_volume_data * data);
     int payloadCustomParam(uint8_t **alsaPayload, size_t *size,
                             uint32_t *customayload, uint32_t customPayloadSize,
                             uint32_t moduleInstanceId, uint32_t dspParamId);
diff --git a/session/src/PayloadBuilder.cpp b/session/src/PayloadBuilder.cpp
index 9a8945a..4a07e3f 100644
--- a/session/src/PayloadBuilder.cpp
+++ b/session/src/PayloadBuilder.cpp
@@ -441,8 +441,14 @@
     uint8_t* payloadInfo = NULL;
     size_t payloadSize = 0, padBytes = 0;
 
-    PAL_VERBOSE(LOG_TAG,"volume sent:%f \n",(voldata->volume_pair[0].vol));
-    voldB = (voldata->volume_pair[0].vol);
+    if (voldata->no_of_volpair == 1) {
+        voldB = (voldata->volume_pair[0].vol);
+    } else {
+        voldB = (voldata->volume_pair[0].vol + voldata->volume_pair[1].vol)/2;
+        PAL_DBG(LOG_TAG,"volume sent left:%f , right: %f \n",(voldata->volume_pair[0].vol),
+                  (voldata->volume_pair[1].vol));
+    }
+    PAL_VERBOSE(LOG_TAG,"volume sent:%f \n",voldB);
     vol = (long)(voldB * (PLAYBACK_VOLUME_MAX*1.0));
     payloadSize = sizeof(struct apm_module_param_data_t) +
                   sizeof(struct volume_ctrl_master_gain_t);
@@ -467,6 +473,51 @@
     PAL_DBG(LOG_TAG, "payload %pK size %zu", *payload, *size);
 }
 
+void PayloadBuilder::payloadMultichVolumemConfig(uint8_t** payload, size_t* size,
+        uint32_t miid, struct pal_volume_data* voldata)
+{
+     const uint32_t PLAYBACK_MULTI_VOLUME_GAIN = 1 << 28;
+     struct apm_module_param_data_t* header = nullptr;
+     volume_ctrl_multichannel_gain_t *volConf = nullptr;
+     int numChannels;
+     uint8_t* payloadInfo = NULL;
+     size_t payloadSize = 0, padBytes = 0;
+
+     numChannels = voldata->no_of_volpair;
+     payloadSize = sizeof(struct apm_module_param_data_t) +
+                   sizeof(struct volume_ctrl_multichannel_gain_t) +
+                   numChannels * sizeof(volume_ctrl_channels_gain_config_t);
+     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;
+     header->module_instance_id = miid;
+     header->param_id = PARAM_ID_VOL_CTRL_MULTICHANNEL_GAIN;
+     header->error_code = 0x0;
+     header->param_size = payloadSize -  sizeof(struct apm_module_param_data_t);
+     volConf = (volume_ctrl_multichannel_gain_t *) (payloadInfo + sizeof(struct apm_module_param_data_t));
+     volConf->num_config = numChannels;
+     PAL_DBG(LOG_TAG, "num_config %d", numChannels);
+     /*
+      * Only L/R channel setting is supported. No need to convert channel_mask to channel_map.
+      * If other channel types support, the conversion is needed.
+      */
+     for (uint32_t i = 0; i < numChannels; i++) {
+          volConf->gain_data[i].channel_mask_lsb = (1 << voldata->volume_pair[i].channel_mask);
+          volConf->gain_data[i].channel_mask_msb = 0;
+          volConf->gain_data[i].gain = (uint32_t)((voldata->volume_pair[i].vol) * (PLAYBACK_MULTI_VOLUME_GAIN * 1.0));
+     }
+     PAL_DBG(LOG_TAG, "header params IID:%x param_id:%x error_code:%d param_size:%d",
+                   header->module_instance_id, header->param_id,
+                   header->error_code, header->param_size);
+     *size = payloadSize + padBytes;
+     *payload = payloadInfo;
+     PAL_DBG(LOG_TAG, "payload %pK size %zu", *payload, *size);
+}
+
 void PayloadBuilder::payloadVolumeCtrlRamp(uint8_t** payload, size_t* size,
         uint32_t miid, uint32_t ramp_period_ms)
 {
@@ -1996,7 +2047,8 @@
         mediaFmtPayload->alignment       = PCM_MSB_ALIGNED;
     } else {
         PAL_ERR(LOG_TAG, "invalid bit width %d", data->bit_width);
-        delete[] payloadInfo;
+        free(payloadInfo);
+        payloadInfo = NULL;
         *size = 0;
         *payload = NULL;
         return;
@@ -3181,6 +3233,7 @@
     }
 
     long voldB = 0;
+    float vol = 0;
     struct pal_volume_data *voldata = NULL;
     voldata = (struct pal_volume_data *)calloc(1, (sizeof(uint32_t) +
                       (sizeof(struct pal_channel_vol_kv) * (0xFFFF))));
@@ -3195,9 +3248,17 @@
         goto error_1;
     }
 
-    PAL_VERBOSE(LOG_TAG,"volume sent:%f \n",(voldata->volume_pair[0].vol));
+    if (voldata->no_of_volpair == 1) {
+        vol = (voldata->volume_pair[0].vol);
+    } else {
+        vol = (voldata->volume_pair[0].vol + voldata->volume_pair[1].vol)/2;
+        PAL_VERBOSE(LOG_TAG,"volume sent left:%f , right: %f \n",(voldata->volume_pair[0].vol),
+                  (voldata->volume_pair[1].vol));
+    }
+
     /*scaling the volume by PLAYBACK_VOLUME_MAX factor*/
-    voldB = (long)((voldata->volume_pair[0].vol) * (PLAYBACK_VOLUME_MAX*1.0));
+    voldB = (long)(vol * (PLAYBACK_VOLUME_MAX*1.0));
+    PAL_VERBOSE(LOG_TAG,"volume sent:%f \n",voldB);
 
     switch (static_cast<uint32_t>(tag)) {
     case TAG_STREAM_VOLUME:
diff --git a/session/src/SessionAlsaCompress.cpp b/session/src/SessionAlsaCompress.cpp
index 5778888..e6b9e9e 100644
--- a/session/src/SessionAlsaCompress.cpp
+++ b/session/src/SessionAlsaCompress.cpp
@@ -2182,12 +2182,17 @@
                 goto exit;
             }
 
-            builder->payloadVolumeConfig(&alsaParamData, &alsaPayloadSize, miid, vdata);
+            if (vdata->no_of_volpair == 2 && sAttr.out_media_config.ch_info.channels == 2) {
+                builder->payloadMultichVolumemConfig(&alsaParamData, &alsaPayloadSize, miid, vdata);
+            } else {
+                builder->payloadVolumeConfig(&alsaParamData, &alsaPayloadSize, miid, vdata);
+            }
+
             if (alsaPayloadSize) {
                 status = SessionAlsaUtils::setMixerParameter(mixer, device,
                                                alsaParamData, alsaPayloadSize);
                 PAL_INFO(LOG_TAG, "mixer set volume config status=%d\n", status);
-                delete [] alsaParamData;
+                freeCustomPayload(&alsaParamData, &alsaPayloadSize);
                 alsaPayloadSize = 0;
             }
         }
diff --git a/session/src/SessionAlsaPcm.cpp b/session/src/SessionAlsaPcm.cpp
index b527e7b..efd5284 100644
--- a/session/src/SessionAlsaPcm.cpp
+++ b/session/src/SessionAlsaPcm.cpp
@@ -2560,7 +2560,7 @@
                 status = SessionAlsaUtils::setMixerParameter(mixer, device,
                                                paramData, paramSize);
                 PAL_INFO(LOG_TAG, "mixer set volume config status=%d\n", status);
-                delete [] paramData;
+                freeCustomPayload(&paramData, &paramSize);
                 paramSize = 0;
             }
             return 0;