Merge 7d13d4867bfe79bc8c9836c26cab372b5572bcf8 on remote branch

Change-Id: Icbeff68b78402a23759b306b123e55f717fe032a
diff --git a/configs/parrot/parrot.mk b/configs/parrot/parrot.mk
index 747799f..6e989a5 100644
--- a/configs/parrot/parrot.mk
+++ b/configs/parrot/parrot.mk
@@ -84,6 +84,7 @@
 AUDIO_FEATURE_ENABLED_USB_BURST_MODE := true
 AUDIO_FEATURE_ENABLED_SVA_MULTI_STAGE := true
 AUDIO_FEATURE_ENABLED_BATTERY_LISTENER := true
+AUDIO_FEATURE_ENABLED_DYNAMIC_SR := false 
 BUILD_AUDIO_TECHPACK_SOURCE := true
 AUDIO_FEATURE_ENABLED_MCS := true
 ##AUDIO_FEATURE_FLAGS
@@ -179,6 +180,7 @@
 PRODUCT_PACKAGES += fai__2.0.0_0.1__3.0.0_0.0__eai_1.36_enpu2.pmd
 PRODUCT_PACKAGES += fai__2.7.2_0.0__3.0.0_0.0__eai_1.36_enpu2.pmd
 PRODUCT_PACKAGES += fai__2.7.20_0.0__3.0.0_0.0__eai_1.36_enpu2.pmd
+PRODUCT_PACKAGES += fai__4.8.4_0.0__3.0.0_0.0__eai_1.43_enpu2.pmd
 PRODUCT_PACKAGES += fai__3.0.0_0.0__eai_1.36_enpu2.pmd
 PRODUCT_PACKAGES += libfmpal
 PRODUCT_PACKAGES += event.eai
diff --git a/hal/Android.mk b/hal/Android.mk
index bcc5f21..5514ae6 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -33,6 +33,10 @@
 LOCAL_CFLAGS += -DEC_REF_CAPTURE_ENABLED
 endif
 
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_DYNAMIC_SR)),true)
+LOCAL_CFLAGS += -DDYNAMIC_SR_ENABLED
+endif
+
 LOCAL_CFLAGS += -Wno-macro-redefined
 LOCAL_CFLAGS += -DSOUND_TRIGGER_PLATFORM_NAME=$(TARGET_BOARD_PLATFORM)
 LOCAL_CFLAGS += -D_GNU_SOURCE
diff --git a/hal/AudioStream.cpp b/hal/AudioStream.cpp
index 94ba25b..ab8d53d 100644
--- a/hal/AudioStream.cpp
+++ b/hal/AudioStream.cpp
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -89,20 +89,20 @@
     bool orientationInverted = adevice->inverted;
 
     if (orientationLandscape && !orientationInverted) {
-        strlcpy(palInDevice->custom_config.custom_key,
-            "unprocessed-hdr-mic-landscape",
+        strlcat(palInDevice->custom_config.custom_key,
+            "unprocessed-hdr-mic-landscape;",
             sizeof(palInDevice->custom_config.custom_key));
     } else if (!orientationLandscape && !orientationInverted) {
-        strlcpy(palInDevice->custom_config.custom_key,
-            "unprocessed-hdr-mic-portrait",
+        strlcat(palInDevice->custom_config.custom_key,
+            "unprocessed-hdr-mic-portrait;",
             sizeof(palInDevice->custom_config.custom_key));
     } else if (orientationLandscape && orientationInverted) {
-        strlcpy(palInDevice->custom_config.custom_key,
-            "unprocessed-hdr-mic-inverted-landscape",
+        strlcat(palInDevice->custom_config.custom_key,
+            "unprocessed-hdr-mic-inverted-landscape;",
             sizeof(palInDevice->custom_config.custom_key));
     } else if (!orientationLandscape && orientationInverted) {
-        strlcpy(palInDevice->custom_config.custom_key,
-            "unprocessed-hdr-mic-inverted-portrait",
+        strlcat(palInDevice->custom_config.custom_key,
+            "unprocessed-hdr-mic-inverted-portrait;",
             sizeof(palInDevice->custom_config.custom_key));
     }
     AHAL_INFO("Setting custom key as %s",
@@ -2218,7 +2218,7 @@
 
             if ((AudioExtn::audio_devices_cmp(mAndroidOutDevices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) &&
                                    (mPalOutDeviceIds[i] == PAL_DEVICE_OUT_SPEAKER)) {
-                strlcpy(mPalOutDevice[i].custom_config.custom_key, "speaker-safe",
+                strlcat(mPalOutDevice[i].custom_config.custom_key, "speaker-safe;",
                         sizeof(mPalOutDevice[i].custom_config.custom_key));
                 AHAL_INFO("Setting custom key as %s", mPalOutDevice[i].custom_config.custom_key);
             }
@@ -2230,17 +2230,80 @@
 
                 AHAL_DBG("hifi-filter custom key sent to PAL (only applicable to certain streams)\n");
 
-                strlcpy(mPalOutDevice[i].custom_config.custom_key,
-                       "hifi-filter_custom_key",
+                strlcat(mPalOutDevice[i].custom_config.custom_key,
+                       "hifi-filter_custom_key;",
                        sizeof(mPalOutDevice[i].custom_config.custom_key));
             }
+
+#ifdef DYNAMIC_SR_ENABLED
+            if (((usecase_ == USECASE_AUDIO_PLAYBACK_VOIP) ||
+                  (usecase_ == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER) ||
+                  (isOffloadUsecase())) &&
+                 ((mPalOutDevice[i].id == PAL_DEVICE_OUT_SPEAKER) ||
+                  (mPalOutDevice[i].id == PAL_DEVICE_OUT_HANDSET) ||
+                  (mPalOutDevice[i].id == PAL_DEVICE_OUT_WIRED_HEADPHONE) ||
+                  (mPalOutDevice[i].id == PAL_DEVICE_OUT_WIRED_HEADSET) ||
+                  (mPalOutDevice[i].id == PAL_DEVICE_OUT_USB_DEVICE) ||
+                  (mPalOutDevice[i].id == PAL_DEVICE_OUT_USB_HEADSET))) {
+                if (config_.sample_rate == 8000) {
+                    strlcat(mPalOutDevice[i].custom_config.custom_key, "8K;",
+                    sizeof(mPalOutDevice[i].custom_config.custom_key));
+                } else if (config_.sample_rate == 11025) {
+                     strlcat(mPalOutDevice[i].custom_config.custom_key, "11K;",
+                     sizeof(mPalOutDevice[i].custom_config.custom_key));
+                } else if (config_.sample_rate == 16000) {
+                     strlcat(mPalOutDevice[i].custom_config.custom_key, "16K;",
+                     sizeof(mPalOutDevice[i].custom_config.custom_key));
+                } else if (config_.sample_rate == 22050) {
+                     strlcat(mPalOutDevice[i].custom_config.custom_key, "22K;",
+                     sizeof(mPalOutDevice[i].custom_config.custom_key));
+                } else if (config_.sample_rate == 24000) {
+                     strlcat(mPalOutDevice[i].custom_config.custom_key, "24K;",
+                     sizeof(mPalOutDevice[i].custom_config.custom_key));
+                } else if (config_.sample_rate == 32000) {
+                    strlcat(mPalOutDevice[i].custom_config.custom_key, "32K;",
+                    sizeof(mPalOutDevice[i].custom_config.custom_key));
+                } else if (config_.sample_rate == 44100) {
+                    strlcat(mPalOutDevice[i].custom_config.custom_key, "44.1K;",
+                    sizeof(mPalOutDevice[i].custom_config.custom_key));
+                } else if (config_.sample_rate == 48000) {
+                    strlcat(mPalOutDevice[i].custom_config.custom_key, "48K;",
+                    sizeof(mPalOutDevice[i].custom_config.custom_key));
+                } else if (config_.sample_rate == 64000) {
+                    strlcat(mPalOutDevice[i].custom_config.custom_key, "64K;",
+                    sizeof(mPalOutDevice[i].custom_config.custom_key));
+                } else if (config_.sample_rate == 88200) {
+                    strlcat(mPalOutDevice[i].custom_config.custom_key, "88.2K;",
+                    sizeof(mPalOutDevice[i].custom_config.custom_key));
+                } else if (config_.sample_rate == 96000) {
+                    strlcat(mPalOutDevice[i].custom_config.custom_key, "96K;",
+                    sizeof(mPalOutDevice[i].custom_config.custom_key));
+                } else if (config_.sample_rate == 176400) {
+                    strlcat(mPalOutDevice[i].custom_config.custom_key, "176.4K;",
+                    sizeof(mPalOutDevice[i].custom_config.custom_key));
+                } else if (config_.sample_rate == 192000) {
+                    strlcat(mPalOutDevice[i].custom_config.custom_key, "192K;",
+                    sizeof(mPalOutDevice[i].custom_config.custom_key));
+                } else if (config_.sample_rate == 352800) {
+                    strlcat(mPalOutDevice[i].custom_config.custom_key, "352.8K;",
+                    sizeof(mPalOutDevice[i].custom_config.custom_key));
+                } else if (config_.sample_rate == 384000) {
+                    strlcat(mPalOutDevice[i].custom_config.custom_key, "384K;",
+                    sizeof(mPalOutDevice[i].custom_config.custom_key));
+                } else {
+                    AHAL_DBG("No custom config to set for usecase %d for sr %d",
+                             usecase_, config_.sample_rate);
+                }
+                AHAL_DBG("setting SR for usecase %d as %d", usecase_, config_.sample_rate);
+            }
+#endif
         }
 
         mAndroidOutDevices = new_devices;
 
         std::shared_ptr<AudioDevice> adevice = AudioDevice::GetInstance();
         if (adevice->hac_voip && (mPalOutDevice->id == PAL_DEVICE_OUT_HANDSET)) {
-            strlcpy(mPalOutDevice->custom_config.custom_key, "HAC",
+            strlcat(mPalOutDevice->custom_config.custom_key, "HAC;",
                    sizeof(mPalOutDevice->custom_config.custom_key));
         }
 
@@ -2700,8 +2763,8 @@
 
         AHAL_DBG("hifi-filter custom key sent to PAL (only applicable to certain streams)\n");
 
-        strlcpy(mPalOutDevice->custom_config.custom_key,
-                "hifi-filter_custom_key",
+        strlcat(mPalOutDevice->custom_config.custom_key,
+                "hifi-filter_custom_key;",
                 sizeof(mPalOutDevice->custom_config.custom_key));
     }
 
@@ -2726,7 +2789,7 @@
     }
 
     if (adevice->hac_voip && (mPalOutDevice->id == PAL_DEVICE_OUT_HANDSET)) {
-        strlcpy(mPalOutDevice->custom_config.custom_key, "HAC",
+        strlcat(mPalOutDevice->custom_config.custom_key, "HAC;",
                 sizeof(mPalOutDevice->custom_config.custom_key));
     }
 
@@ -2749,6 +2812,16 @@
         ret = -EINVAL;
         goto error_open;
     }
+
+    /* set cached volume if any, dont return failure back up */
+    if (volume_) {
+        AHAL_DBG("set cached volume (%f)", volume_->volume_pair[0].vol);
+        ret = pal_stream_set_volume(pal_stream_handle_, volume_);
+        if (ret) {
+            AHAL_ERR("Pal Stream volume Error (%x)", ret);
+        }
+    }
+
     if (usecase_ == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
         ch_info.channels = audio_channel_count_from_out_mask(config_.channel_mask & AUDIO_CHANNEL_HAPTIC_ALL);
         ch_info.ch_map[0] = PAL_CHMAP_CHANNEL_FL;
@@ -3081,13 +3154,6 @@
 
     if (!stream_started_) {
         AutoPerfLock perfLock;
-        /* set cached volume if any, dont return failure back up */
-        if (volume_) {
-            ret = pal_stream_set_volume(pal_stream_handle_, volume_);
-            if (ret) {
-                AHAL_ERR("Pal Stream volume Error (%x)", ret);
-            }
-        }
 
         ATRACE_BEGIN("hal: pal_stream_start");
         ret = pal_stream_start(pal_stream_handle_);
@@ -3498,11 +3564,73 @@
 
         if ((AudioExtn::audio_devices_cmp(mAndroidOutDevices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) &&
                                    (mPalOutDeviceIds[i] == PAL_DEVICE_OUT_SPEAKER)) {
-            strlcpy(mPalOutDevice[i].custom_config.custom_key, "speaker-safe",
+            strlcat(mPalOutDevice[i].custom_config.custom_key, "speaker-safe;",
                      sizeof(mPalOutDevice[i].custom_config.custom_key));
             AHAL_INFO("Setting custom key as %s", mPalOutDevice[i].custom_config.custom_key);
         }
 
+#ifdef DYNAMIC_SR_ENABLED
+        if (((usecase_ == USECASE_AUDIO_PLAYBACK_VOIP) ||
+              (usecase_ == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER) ||
+              (isOffloadUsecase())) &&
+             ((mPalOutDevice[i].id == PAL_DEVICE_OUT_SPEAKER) ||
+              (mPalOutDevice[i].id == PAL_DEVICE_OUT_HANDSET) ||
+              (mPalOutDevice[i].id == PAL_DEVICE_OUT_WIRED_HEADPHONE) ||
+              (mPalOutDevice[i].id == PAL_DEVICE_OUT_WIRED_HEADSET) ||
+              (mPalOutDevice[i].id == PAL_DEVICE_OUT_USB_DEVICE) ||
+              (mPalOutDevice[i].id == PAL_DEVICE_OUT_USB_HEADSET))) {
+            if (config_.sample_rate == 8000) {
+                strlcat(mPalOutDevice[i].custom_config.custom_key, "8K;",
+                sizeof(mPalOutDevice[i].custom_config.custom_key));
+            } else if (config_.sample_rate == 11025) {
+                 strlcat(mPalOutDevice[i].custom_config.custom_key, "11K;",
+                 sizeof(mPalOutDevice[i].custom_config.custom_key));
+            } else if (config_.sample_rate == 16000) {
+                 strlcat(mPalOutDevice[i].custom_config.custom_key, "16K;",
+                 sizeof(mPalOutDevice[i].custom_config.custom_key));
+            } else if (config_.sample_rate == 22050) {
+                 strlcat(mPalOutDevice[i].custom_config.custom_key, "22K;",
+                 sizeof(mPalOutDevice[i].custom_config.custom_key));
+            } else if (config_.sample_rate == 24000) {
+                 strlcat(mPalOutDevice[i].custom_config.custom_key, "24K;",
+                 sizeof(mPalOutDevice[i].custom_config.custom_key));
+            } else if (config_.sample_rate == 32000) {
+                strlcat(mPalOutDevice[i].custom_config.custom_key, "32K;",
+                sizeof(mPalOutDevice[i].custom_config.custom_key));
+            } else if (config_.sample_rate == 44100) {
+                strlcat(mPalOutDevice[i].custom_config.custom_key, "44.1K;",
+                sizeof(mPalOutDevice[i].custom_config.custom_key));
+            } else if (config_.sample_rate == 48000) {
+                strlcat(mPalOutDevice[i].custom_config.custom_key, "48K;",
+                sizeof(mPalOutDevice[i].custom_config.custom_key));
+            } else if (config_.sample_rate == 64000) {
+                strlcat(mPalOutDevice[i].custom_config.custom_key, "64K;",
+                sizeof(mPalOutDevice[i].custom_config.custom_key));
+            } else if (config_.sample_rate == 88200) {
+                strlcat(mPalOutDevice[i].custom_config.custom_key, "88.2K;",
+                sizeof(mPalOutDevice[i].custom_config.custom_key));
+            } else if (config_.sample_rate == 96000) {
+                strlcat(mPalOutDevice[i].custom_config.custom_key, "96K;",
+                sizeof(mPalOutDevice[i].custom_config.custom_key));
+            } else if (config_.sample_rate == 176400) {
+                strlcat(mPalOutDevice[i].custom_config.custom_key, "176.4K;",
+                sizeof(mPalOutDevice[i].custom_config.custom_key));
+            } else if (config_.sample_rate == 192000) {
+                strlcat(mPalOutDevice[i].custom_config.custom_key, "192K;",
+                sizeof(mPalOutDevice[i].custom_config.custom_key));
+            } else if (config_.sample_rate == 352800) {
+                strlcat(mPalOutDevice[i].custom_config.custom_key, "352.8K;",
+                sizeof(mPalOutDevice[i].custom_config.custom_key));
+            } else if (config_.sample_rate == 384000) {
+                strlcat(mPalOutDevice[i].custom_config.custom_key, "384K;",
+                sizeof(mPalOutDevice[i].custom_config.custom_key));
+            } else {
+                AHAL_DBG("No custom config to set for usecase %d for sr %d",
+                         usecase_, config_.sample_rate);
+            }
+            AHAL_DBG("setting SR for usecase %d as %d", usecase_, config_.sample_rate);
+        }
+#endif
     }
 
     if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
@@ -3983,10 +4111,36 @@
                 setup_hdr_usecase(&mPalInDevice[i]);
 
             if (source_ == AUDIO_SOURCE_CAMCORDER && adevice->cameraOrientation == CAMERA_DEFAULT) {
-                strlcpy(mPalInDevice[i].custom_config.custom_key, "camcorder_landscape",
+                strlcat(mPalInDevice[i].custom_config.custom_key, "camcorder_landscape;",
                         sizeof(mPalInDevice[i].custom_config.custom_key));
                 AHAL_INFO("Setting custom key as %s", mPalInDevice[i].custom_config.custom_key);
             }
+
+#ifdef DYNAMIC_SR_ENABLED
+            if (((usecase_ == USECASE_AUDIO_RECORD_VOIP) ||
+                 (usecase_ == USECASE_AUDIO_RECORD)) &&
+                ((mPalInDevice[i].id == PAL_DEVICE_IN_HANDSET_MIC) ||
+                 (mPalInDevice[i].id == PAL_DEVICE_IN_SPEAKER_MIC) ||
+                 (mPalInDevice[i].id == PAL_DEVICE_IN_WIRED_HEADSET))) {
+                if (config_.sample_rate == 8000) {
+                    strlcat(mPalInDevice[i].custom_config.custom_key, "8K;",
+                    sizeof(mPalInDevice[i].custom_config.custom_key));
+                } else if (config_.sample_rate == 16000) {
+                     strlcat(mPalInDevice[i].custom_config.custom_key, "16K;",
+                     sizeof(mPalInDevice[i].custom_config.custom_key));
+                } else if (config_.sample_rate == 32000) {
+                    strlcat(mPalInDevice[i].custom_config.custom_key, "32K;",
+                    sizeof(mPalInDevice[i].custom_config.custom_key));
+                } else if (config_.sample_rate == 48000) {
+                    strlcat(mPalInDevice[i].custom_config.custom_key, "48K;",
+                    sizeof(mPalInDevice[i].custom_config.custom_key));
+                } else {
+                    AHAL_DBG("No custom config to set for usecase %d for sr %d",
+                             usecase_, config_.sample_rate);
+                }
+                AHAL_DBG("setting SR for usecase %d as %d", usecase_, config_.sample_rate);
+            }
+#endif
         }
 
         mAndroidInDevices = new_devices;
@@ -4760,7 +4914,6 @@
     }
 
     for (int i = 0; i < mAndroidInDevices.size(); i++) {
-        memset(mPalInDevice[i].custom_config.custom_key, 0, sizeof(mPalInDevice[i].custom_config.custom_key));
         mPalInDevice[i].id = mPalInDeviceIds[i];
         mPalInDevice[i].config.sample_rate = config->sample_rate;
         mPalInDevice[i].config.bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
@@ -4772,8 +4925,6 @@
             mPalInDevice[i].address.card_id = adevice->usb_card_id_;
             mPalInDevice[i].address.device_num = adevice->usb_dev_num_;
         }
-        strlcpy(mPalInDevice[i].custom_config.custom_key, "",
-                sizeof(mPalInDevice[i].custom_config.custom_key));
 
         /* HDR use case check */
         if ((source_ == AUDIO_SOURCE_UNPROCESSED) &&
@@ -4787,15 +4938,49 @@
                 }
             }
         }
-
-        if (source_ == AUDIO_SOURCE_CAMCORDER && adevice->cameraOrientation == CAMERA_DEFAULT) {
-            strlcpy(mPalInDevice[i].custom_config.custom_key, "camcorder_landscape",
-                    sizeof(mPalInDevice[i].custom_config.custom_key));
-            AHAL_INFO("Setting custom key as %s", mPalInDevice[i].custom_config.custom_key);
-        }
     }
 
     usecase_ = GetInputUseCase(flags, source);
+    for (int i = 0; i < mAndroidInDevices.size(); i++) {
+        memset(mPalInDevice[i].custom_config.custom_key, 0,
+               sizeof(mPalInDevice[i].custom_config.custom_key));
+
+        strlcpy(mPalInDevice[i].custom_config.custom_key, "",
+                sizeof(mPalInDevice[i].custom_config.custom_key));
+
+        if (source_ == AUDIO_SOURCE_CAMCORDER && adevice->cameraOrientation == CAMERA_DEFAULT) {
+            strlcat(mPalInDevice[i].custom_config.custom_key, "camcorder_landscape;",
+                    sizeof(mPalInDevice[i].custom_config.custom_key));
+            AHAL_INFO("Setting custom key as %s", mPalInDevice[i].custom_config.custom_key);
+        }
+
+#ifdef DYNAMIC_SR_ENABLED
+        if (((usecase_ == USECASE_AUDIO_RECORD_VOIP) ||
+             (usecase_ == USECASE_AUDIO_RECORD)) &&
+            ((mPalInDevice[i].id == PAL_DEVICE_IN_HANDSET_MIC) ||
+             (mPalInDevice[i].id == PAL_DEVICE_IN_SPEAKER_MIC) ||
+             (mPalInDevice[i].id == PAL_DEVICE_IN_WIRED_HEADSET))) {
+            if (config_.sample_rate == 8000) {
+                strlcat(mPalInDevice[i].custom_config.custom_key, "8K;",
+                sizeof(mPalInDevice[i].custom_config.custom_key));
+            } else if (config_.sample_rate == 16000) {
+                 strlcat(mPalInDevice[i].custom_config.custom_key, "16K;",
+                 sizeof(mPalInDevice[i].custom_config.custom_key));
+            } else if (config_.sample_rate == 32000) {
+                strlcat(mPalInDevice[i].custom_config.custom_key, "32K;",
+                sizeof(mPalInDevice[i].custom_config.custom_key));
+            } else if (config_.sample_rate == 48000) {
+                strlcat(mPalInDevice[i].custom_config.custom_key, "48K;",
+                sizeof(mPalInDevice[i].custom_config.custom_key));
+            } else {
+                AHAL_DBG("No custom config to set for usecase %d for sr %d",
+                         usecase_, config_.sample_rate);
+            }
+            AHAL_DBG("setting SR for usecase %d as %d", usecase_, config_.sample_rate);
+        }
+#endif
+    }
+
     if (flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) {
         stream_.get()->start = astream_in_mmap_noirq_start;
         stream_.get()->stop = astream_in_mmap_noirq_stop;
diff --git a/hal/AudioStream.h b/hal/AudioStream.h
index 424631a..51f9e47 100644
--- a/hal/AudioStream.h
+++ b/hal/AudioStream.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-2024, 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
@@ -527,6 +527,23 @@
     pal_device_id_t* mPalOutDeviceIds;
     std::set<audio_devices_t> mAndroidOutDevices;
     bool mInitialized;
+    bool isOffloadUsecase() {
+        int usecase = GetUseCase();
+        switch (usecase) {
+            case USECASE_AUDIO_PLAYBACK_OFFLOAD:
+            case USECASE_AUDIO_PLAYBACK_OFFLOAD2:
+            case USECASE_AUDIO_PLAYBACK_OFFLOAD3:
+            case USECASE_AUDIO_PLAYBACK_OFFLOAD4:
+            case USECASE_AUDIO_PLAYBACK_OFFLOAD5:
+            case USECASE_AUDIO_PLAYBACK_OFFLOAD6:
+            case USECASE_AUDIO_PLAYBACK_OFFLOAD7:
+            case USECASE_AUDIO_PLAYBACK_OFFLOAD8:
+            case USECASE_AUDIO_PLAYBACK_OFFLOAD9:
+                return true;
+            default:
+                return false;
+        }
+    }
 
 public:
     StreamOutPrimary(audio_io_handle_t handle,
diff --git a/hal/AudioVoice.cpp b/hal/AudioVoice.cpp
index 15a8169..fdd9f9d 100644
--- a/hal/AudioVoice.cpp
+++ b/hal/AudioVoice.cpp
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022, 2024, Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -679,9 +679,9 @@
     /*set custom key for hac mode*/
     if (session && session->hac && palDevices[1].id == 
         PAL_DEVICE_OUT_HANDSET) {
-        strlcpy(palDevices[0].custom_config.custom_key, "HAC",
+        strlcat(palDevices[0].custom_config.custom_key, "HAC;",
                     sizeof(palDevices[0].custom_config.custom_key));
-        strlcpy(palDevices[1].custom_config.custom_key, "HAC",
+        strlcat(palDevices[1].custom_config.custom_key, "HAC;",
                     sizeof(palDevices[1].custom_config.custom_key));
         AHAL_INFO("Setting custom key as %s", palDevices[0].custom_config.custom_key);
     }
@@ -945,9 +945,9 @@
     /*set or remove custom key for hac mode*/
     if (session && session->hac && palDevices[1].id == 
         PAL_DEVICE_OUT_HANDSET) {
-        strlcpy(palDevices[0].custom_config.custom_key, "HAC",
+        strlcat(palDevices[0].custom_config.custom_key, "HAC;",
                     sizeof(palDevices[0].custom_config.custom_key));
-        strlcpy(palDevices[1].custom_config.custom_key, "HAC",
+        strlcat(palDevices[1].custom_config.custom_key, "HAC;",
                     sizeof(palDevices[1].custom_config.custom_key));
             AHAL_INFO("Setting custom key as %s", palDevices[0].custom_config.custom_key);
     } else {