audio: Dedicated usecase for voip call (uplink and downlink)

Add dedicated usecases for voip call.

coauthored-by: Vikram Panduranga <vpandura@codeaurora.org>

Bug: 62393776
Test: hangout call
Change-Id: Iff8911aa8d4f072923e2f2649098a44a4bc4485c
Signed-off-by: David Lin <dtwlin@google.com>
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index eb0f9f6..2fc424c 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -34,14 +34,17 @@
 
 #define MAX_LENGTH_MIXER_CONTROL_IN_INT 128
 
-static int set_mixer_ctrl(struct audio_device *adev,
-                          int pcm_device_id, int app_type,
-                          int acdb_dev_id, int sample_rate, int stream_type)
+static int set_stream_app_type_mixer_ctrl(struct audio_device *adev,
+                                          int pcm_device_id, int app_type,
+                                          int acdb_dev_id, int sample_rate,
+                                          int stream_type,
+                                          snd_device_t snd_device)
 {
 
     char mixer_ctl_name[MAX_LENGTH_MIXER_CONTROL_IN_INT];
     struct mixer_ctl *ctl;
     int app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT], len = 0, rc = 0;
+    int snd_device_be_idx = -1;
 
     if (stream_type == PCM_PLAYBACK) {
         snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
@@ -61,8 +64,14 @@
     app_type_cfg[len++] = app_type;
     app_type_cfg[len++] = acdb_dev_id;
     app_type_cfg[len++] = sample_rate;
-    ALOGV("%s: stream type %d app_type %d, acdb_dev_id %d sample rate %d",
-          __func__, stream_type, app_type, acdb_dev_id, sample_rate);
+
+    snd_device_be_idx = platform_get_snd_device_backend_index(snd_device);
+    if (snd_device_be_idx > 0)
+        app_type_cfg[len++] = snd_device_be_idx;
+    ALOGV("%s: stream type %d app_type %d, acdb_dev_id %d "
+          "sample rate %d, snd_device_be_idx %d",
+          __func__, stream_type, app_type, acdb_dev_id, sample_rate,
+          snd_device_be_idx);
     mixer_ctl_set_array(ctl, app_type_cfg, len);
 
 exit:
@@ -92,6 +101,20 @@
     return;
 }
 
+static const char *flags_to_mode(int dir, uint32_t flags)
+{
+    if (dir == 0) {
+        if (flags & AUDIO_OUTPUT_FLAG_VOIP_RX) {
+            return "voip";
+        }
+    } else if (dir == 1) {
+        if (flags & AUDIO_INPUT_FLAG_VOIP_TX) {
+            return "voip";
+        }
+    }
+    return "default";
+}
+
 static int audio_extn_utils_send_app_type_cfg_hfp(struct audio_device *adev,
                                        struct audio_usecase *usecase)
 {
@@ -134,16 +157,20 @@
             goto exit_send_app_type_cfg;
 
         sample_rate= CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
-        rc = set_mixer_ctrl(adev, pcm_device_id, app_type,
-               acdb_dev_id, sample_rate, PCM_PLAYBACK);
+        rc = set_stream_app_type_mixer_ctrl(adev, pcm_device_id, app_type,
+                                            acdb_dev_id, sample_rate,
+                                            PCM_PLAYBACK,
+                                            SND_DEVICE_NONE); // use legacy behavior
         if (rc < 0)
             goto exit_send_app_type_cfg;
         /* config HFP session:1 capture path */
         rc = platform_get_default_app_type_v2(adev->platform, PCM_CAPTURE, &app_type);
 
         if (rc == 0) {
-            rc = set_mixer_ctrl(adev, pcm_device_id, app_type,
-                   acdb_dev_id, sample_rate, PCM_CAPTURE);
+            rc = set_stream_app_type_mixer_ctrl(adev, pcm_device_id, app_type,
+                                                acdb_dev_id, sample_rate,
+                                                PCM_CAPTURE,
+                                                SND_DEVICE_NONE);
             if (rc < 0)
                 goto exit_send_app_type_cfg;
         }
@@ -158,8 +185,9 @@
         }
         rc = platform_get_default_app_type_v2(adev->platform, PCM_CAPTURE, &app_type);
         if (rc == 0) {
-            rc = set_mixer_ctrl(adev, pcm_device_id, app_type,
-                   acdb_dev_id, sample_rate, PCM_CAPTURE);
+            rc = set_stream_app_type_mixer_ctrl(adev, pcm_device_id, app_type,
+                                                acdb_dev_id, sample_rate, PCM_CAPTURE,
+                                                SND_DEVICE_NONE);
             if (rc < 0)
                 goto exit_send_app_type_cfg;
         }
@@ -167,8 +195,9 @@
         /* config HFP session:2 playback path */
         rc = platform_get_default_app_type_v2(adev->platform, PCM_PLAYBACK, &app_type);
         if (rc == 0) {
-            rc = set_mixer_ctrl(adev, pcm_device_id, app_type,
-                   acdb_dev_id, sample_rate, PCM_PLAYBACK);
+            rc = set_stream_app_type_mixer_ctrl(adev, pcm_device_id, app_type,
+                                acdb_dev_id, sample_rate,
+                                PCM_PLAYBACK, SND_DEVICE_NONE);
             if (rc < 0)
                 goto exit_send_app_type_cfg;
         }
@@ -179,93 +208,185 @@
     return rc;
 }
 
-int audio_extn_utils_send_app_type_cfg(struct audio_device *adev,
-                                       struct audio_usecase *usecase)
+
+static int derive_capture_app_type_cfg(struct audio_device *adev,
+                                       struct audio_usecase *usecase,
+                                       int *app_type,
+                                       int *sample_rate)
 {
-    int len = 0;
-    if (usecase->type == PCM_HFP_CALL) {
-        return audio_extn_utils_send_app_type_cfg_hfp(adev, usecase);
+    struct stream_in *in = usecase->stream.in;
+    struct stream_app_type_cfg *app_type_cfg = &in->app_type_cfg;
+
+    *sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
+    if (in->device & AUDIO_DEVICE_IN_USB_DEVICE) {
+        platform_check_and_update_copp_sample_rate(adev->platform,
+                                                   usecase->in_snd_device,
+                                                   in->sample_rate,
+                                                   sample_rate);
     }
 
-    if (usecase->type != PCM_PLAYBACK || !platform_supports_app_type_cfg())
-        return -1;
-
-    size_t app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {0};
-    int pcm_device_id = platform_get_pcm_device_id(usecase->id, PCM_PLAYBACK);
-
-    char mixer_ctl_name[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {0};
-    snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
-             "Audio Stream %d App Type Cfg", pcm_device_id);
-    struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
-    if (!ctl) {
-        ALOGE("%s: Could not get ctl for mixer cmd - %s", __func__,
-              mixer_ctl_name);
-        return -EINVAL;
-    }
-
-    snd_device_t snd_device = usecase->out_snd_device; // add speaker prot changes if needed
-    int acdb_dev_id = platform_get_snd_device_acdb_id(snd_device);
-    if (acdb_dev_id <= 0) {
-        ALOGE("%s: Couldn't get the acdb dev id", __func__);
-        return -1;
-    }
-
-    if (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
-        usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
-    } else if (snd_device == SND_DEVICE_OUT_USB_HEADSET ||
-               snd_device == SND_DEVICE_OUT_USB_HEADPHONES) {
-        platform_check_and_update_copp_sample_rate(adev->platform, snd_device,
-                                                   usecase->stream.out->sample_rate,
-                                                   &usecase->stream.out->app_type_cfg.sample_rate);
-    }
-
-    int32_t sample_rate = usecase->stream.out->app_type_cfg.sample_rate;
-    int app_type;
-    if (!audio_is_linear_pcm(usecase->stream.out->format)) {
-        platform_get_default_app_type_v2(adev->platform,
-                                         PCM_PLAYBACK,
-                                         &app_type);
-    } else if (usecase->stream.out->format == AUDIO_FORMAT_PCM_16_BIT) {
+    app_type_cfg->mode = flags_to_mode(1 /*capture*/, in->flags);
+    ALOGV("%s mode %s", __func__, app_type_cfg->mode);
+    if (in->format == AUDIO_FORMAT_PCM_16_BIT) {
         platform_get_app_type_v2(adev->platform,
+                                 PCM_CAPTURE,
+                                 app_type_cfg->mode,
                                  16,
-                                 sample_rate,
-                                 PCM_PLAYBACK,
-                                 &app_type);
-    } else if (usecase->stream.out->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
-               usecase->stream.out->format == AUDIO_FORMAT_PCM_8_24_BIT) {
+                                 app_type_cfg->sample_rate,
+                                 app_type);
+    } else if (in->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
+               in->format == AUDIO_FORMAT_PCM_8_24_BIT) {
         platform_get_app_type_v2(adev->platform,
+                                 PCM_CAPTURE,
+                                 app_type_cfg->mode,
                                  24,
-                                 sample_rate,
-                                 PCM_PLAYBACK,
-                                 &app_type);
-    } else if (usecase->stream.out->format == AUDIO_FORMAT_PCM_32_BIT) {
+                                 app_type_cfg->sample_rate,
+                                 app_type);
+    } else if (in->format == AUDIO_FORMAT_PCM_32_BIT) {
         platform_get_app_type_v2(adev->platform,
+                                 PCM_CAPTURE,
+                                 app_type_cfg->mode,
                                  32,
-                                 sample_rate,
-                                 PCM_PLAYBACK,
-                                 &app_type);
+                                 app_type_cfg->sample_rate,
+                                 app_type);
     } else {
         ALOGE("%s bad format\n", __func__);
         return -1;
     }
 
-    //XXX this would be set somewhere else
-    usecase->stream.out->app_type_cfg.app_type = app_type;
-    app_type_cfg[len++] = app_type;
-    app_type_cfg[len++] = acdb_dev_id;
-    app_type_cfg[len++] = sample_rate;
-
-    // add be_idx once available
-    // if (snd_device_be_idx > 0)
-    //    app_type_cfg[len++] = snd_device_be_idx;
-
-    ALOGI("%s PLAYBACK app_type %d, acdb_dev_id %d, sample_rate %d",
-          __func__, app_type, acdb_dev_id, sample_rate);
-
-    mixer_ctl_set_array(ctl, app_type_cfg, len);
+    app_type_cfg->app_type = *app_type;
+    app_type_cfg->sample_rate = *sample_rate;
     return 0;
 }
 
+static int derive_playback_app_type_cfg(struct audio_device *adev,
+                                        struct audio_usecase *usecase,
+                                        int *app_type,
+                                        int *sample_rate)
+{
+    struct stream_out *out = usecase->stream.out;
+    struct stream_app_type_cfg *app_type_cfg = &out->app_type_cfg;
+
+    *sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
+
+    // add speaker prot changes if needed
+    // and use that to check for device
+    if (out->devices & AUDIO_DEVICE_OUT_USB_DEVICE) {
+        platform_check_and_update_copp_sample_rate(adev->platform,
+                                                   usecase->out_snd_device,
+                                                   out->sample_rate,
+                                                   sample_rate);
+    }
+
+    app_type_cfg->mode = flags_to_mode(0 /*playback*/, out->flags);
+    if (!audio_is_linear_pcm(out->format)) {
+        platform_get_default_app_type_v2(adev->platform,
+                                         PCM_PLAYBACK,
+                                         app_type);
+    } else if (out->format == AUDIO_FORMAT_PCM_16_BIT) {
+        platform_get_app_type_v2(adev->platform,
+                                 PCM_PLAYBACK,
+                                 app_type_cfg->mode,
+                                 16,
+                                 *sample_rate,
+                                 app_type);
+    } else if (out->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
+               out->format == AUDIO_FORMAT_PCM_8_24_BIT) {
+        platform_get_app_type_v2(adev->platform,
+                                 PCM_PLAYBACK,
+                                 app_type_cfg->mode,
+                                 24,
+                                 *sample_rate,
+                                 app_type);
+    } else if (out->format == AUDIO_FORMAT_PCM_32_BIT) {
+        platform_get_app_type_v2(adev->platform,
+                                 PCM_PLAYBACK,
+                                 app_type_cfg->mode,
+                                 32,
+                                 *sample_rate,
+                                 app_type);
+    } else {
+        ALOGE("%s bad format\n", __func__);
+        return -1;
+    }
+
+    app_type_cfg->app_type = *app_type;
+    app_type_cfg->sample_rate = *sample_rate;
+    return 0;
+}
+
+static int derive_acdb_dev_id(struct audio_device *adev __unused,
+                              struct audio_usecase *usecase)
+{
+    struct stream_out *out;
+    struct stream_in *in;
+
+    if (usecase->type == PCM_PLAYBACK) {
+        return platform_get_snd_device_acdb_id(usecase->out_snd_device);
+    } else if(usecase->type == PCM_CAPTURE) {
+        return platform_get_snd_device_acdb_id(usecase->in_snd_device);
+    }
+    return -1;
+}
+
+int audio_extn_utils_send_app_type_cfg(struct audio_device *adev,
+                                       struct audio_usecase *usecase)
+{
+    int len = 0;
+    int sample_rate;
+    int app_type;
+    int acdb_dev_id;
+    size_t app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {0};
+    char mixer_ctl_name[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {0};
+    int pcm_device_id;
+    struct mixer_ctl *ctl;
+    int ret;
+
+    if (usecase->type == PCM_HFP_CALL) {
+        return audio_extn_utils_send_app_type_cfg_hfp(adev, usecase);
+    }
+
+    if (!platform_supports_app_type_cfg())
+        return -1;
+
+    if (usecase->type == PCM_PLAYBACK) {
+        ret = derive_playback_app_type_cfg(adev,
+                                           usecase,
+                                           &app_type,
+                                           &sample_rate);
+    } else if (usecase->type == PCM_CAPTURE) {
+        ret = derive_capture_app_type_cfg(adev,
+                                          usecase,
+                                          &app_type,
+                                          &sample_rate);
+    } else {
+        ALOGE("%s: Invalid uc type : 0x%x", __func__, usecase->type);
+        return -1;
+    }
+
+    if (ret < 0) {
+        ALOGE("%s: Failed to derive app_type for uc type : 0x%x", __func__,
+              usecase->type);
+        return -1;
+    }
+
+    acdb_dev_id = derive_acdb_dev_id(adev, usecase);
+    if (acdb_dev_id <= 0) {
+        ALOGE("%s: Couldn't get the acdb dev id", __func__);
+        return -1;
+    }
+
+    pcm_device_id = platform_get_pcm_device_id(usecase->id, usecase->type);
+    set_stream_app_type_mixer_ctrl(adev, pcm_device_id, app_type, acdb_dev_id,
+                                   sample_rate,
+                                   usecase->type,
+                                   usecase->type == PCM_PLAYBACK ? usecase->out_snd_device :
+                                                                   usecase->in_snd_device);
+    return 0;
+}
+
+// this assumes correct app_type and sample_rate fields
+// have been set for the stream using audio_extn_utils_send_app_type_cfg
 void audio_extn_utils_send_audio_calibration(struct audio_device *adev,
                                              struct audio_usecase *usecase)
 {
@@ -274,24 +395,25 @@
 
     if (type == PCM_PLAYBACK && usecase->stream.out != NULL) {
         struct stream_out *out = usecase->stream.out;
-        ALOGV("%s send cal for app_type %d, rate %d", __func__, out->app_type_cfg.app_type,
-              usecase->stream.out->app_type_cfg.sample_rate);
+        ALOGV("%s send cal for app_type %d, rate %d", __func__,
+              out->app_type_cfg.app_type,
+              out->app_type_cfg.sample_rate);
         platform_send_audio_calibration_v2(adev->platform, usecase,
-                                        out->app_type_cfg.app_type,
-                                        usecase->stream.out->app_type_cfg.sample_rate);
+                                           out->app_type_cfg.app_type,
+                                           out->app_type_cfg.sample_rate);
     } else if (type == PCM_CAPTURE && usecase->stream.in != NULL) {
-        // TBD
-        // platform_send_audio_calibration_v2(adev->platform, usecase,
-        // usecase->stream.in->app_type_cfg.app_type,
-        // usecase->stream.in->app_type_cfg.sample_rate);
-        // uncomment these once send_app_type_cfg and the config entries for
-        // non-16 bit capture are figured out.
-        platform_get_default_app_type_v2(adev->platform, type, &app_type);
-        platform_send_audio_calibration_v2(adev->platform, usecase, app_type, 48000);
+        struct stream_in *in = usecase->stream.in;
+        ALOGV("%s send cal for capture app_type %d, rate %d", __func__,
+              in->app_type_cfg.app_type,
+              in->app_type_cfg.sample_rate);
+        platform_send_audio_calibration_v2(adev->platform, usecase,
+                                           in->app_type_cfg.app_type,
+                                           in->app_type_cfg.sample_rate);
     } else {
         /* when app type is default. the sample rate is not used to send cal */
         platform_get_default_app_type_v2(adev->platform, type, &app_type);
-        platform_send_audio_calibration_v2(adev->platform, usecase, app_type, 48000);
+        platform_send_audio_calibration_v2(adev->platform, usecase, app_type,
+                                           48000);
     }
 }
 
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index cca56ec..44a0216 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -67,6 +67,7 @@
 /* ToDo: Check and update a proper value in msec */
 #define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
 #define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
+#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
 
 #define PROXY_OPEN_RETRY_COUNT           100
 #define PROXY_OPEN_WAIT_TIME             20
@@ -204,6 +205,14 @@
     .avail_min = MMAP_PERIOD_SIZE, //1 ms
 };
 
+struct pcm_config pcm_config_voip = {
+    .channels = 1,
+    .period_count = 2,
+    .format = PCM_FORMAT_S16_LE,
+    .stop_threshold = INT_MAX,
+    .avail_min = 0,
+};
+
 #define AFE_PROXY_CHANNEL_COUNT 2
 #define AFE_PROXY_SAMPLING_RATE 48000
 
@@ -270,6 +279,8 @@
     [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
     [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
 
+    [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
+    [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
 };
 
 
@@ -1440,7 +1451,6 @@
 error_config:
     adev->active_input = NULL;
     ALOGW("%s: exit: status(%d)", __func__, ret);
-
     return ret;
 }
 
@@ -1896,17 +1906,18 @@
     return 0;
 }
 
-static size_t get_input_buffer_size(uint32_t sample_rate,
-                                    audio_format_t format,
-                                    int channel_count,
-                                    bool is_low_latency)
+static size_t get_stream_buffer_size(size_t duration_ms,
+                                     uint32_t sample_rate,
+                                     audio_format_t format,
+                                     int channel_count,
+                                     bool is_low_latency)
 {
     size_t size = 0;
 
     if (check_input_parameters(sample_rate, format, channel_count) != 0)
         return 0;
 
-    size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
+    size = (sample_rate * duration_ms) / 1000;
     if (is_low_latency)
         size = configured_low_latency_capture_period_size;
 
@@ -2366,6 +2377,23 @@
         volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
         mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
         return 0;
+    } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
+        int gain_cfg[4];
+        const char *mixer_ctl_name = "App Type Gain";
+        struct audio_device *adev = out->dev;
+        struct mixer_ctl *ctl;
+        ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+        if (!ctl) {
+            ALOGE("%s: Could not get volume ctl mixer %s", __func__,
+                  mixer_ctl_name);
+            return -EINVAL;
+        }
+        gain_cfg[0] = 0;
+        gain_cfg[1] = out->app_type_cfg.app_type;
+        gain_cfg[2] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
+        gain_cfg[3] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
+        mixer_ctl_set_array(ctl, gain_cfg, sizeof(gain_cfg)/sizeof(gain_cfg[0]));
+        return 0;
     }
 
     return -ENOSYS;
@@ -2900,7 +2928,6 @@
 static size_t in_get_buffer_size(const struct audio_stream *stream)
 {
     struct stream_in *in = (struct stream_in *)stream;
-
     return in->config.period_size * in->af_period_multiplier *
         audio_stream_in_frame_size((const struct audio_stream_in *)stream);
 }
@@ -3572,6 +3599,27 @@
         out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
         out->config = pcm_config_afe_proxy_playback;
         adev->voice_tx_output = out;
+    } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
+               (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT |
+                               AUDIO_OUTPUT_FLAG_VOIP_RX))) {
+        uint32_t buffer_size, frame_size;
+        out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
+        out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
+        out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
+        out->config = pcm_config_voip;
+        out->config.format = pcm_format_from_audio_format(config->format);
+        out->config.rate = config->sample_rate;
+        out->config.channels =
+                audio_channel_count_from_out_mask(config->channel_mask);
+        buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
+                                             config->sample_rate,
+                                             config->format,
+                                             out->config.channels,
+                                             false /*is_low_latency*/);
+        frame_size = audio_bytes_per_sample(config->format) * out->config.channels;
+        out->config.period_size = buffer_size / frame_size;
+        out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
+        out->af_period_multiplier = 1;
     } else {
         if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
             out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
@@ -3983,8 +4031,10 @@
 {
     int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
 
-    return get_input_buffer_size(config->sample_rate, config->format, channel_count,
-            false /* is_low_latency: since we don't know, be conservative */);
+    return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
+                                 config->sample_rate, config->format,
+                                 channel_count,
+                                 false /* is_low_latency: since we don't know, be conservative */);
 }
 
 static bool adev_input_allow_hifi_record(struct audio_device *adev,
@@ -4161,10 +4211,11 @@
         in->usecase = USECASE_AUDIO_RECORD_HIFI;
         in->config = pcm_config_audio_capture;
         frame_size = audio_stream_in_frame_size(&in->stream);
-        buffer_size = get_input_buffer_size(config->sample_rate,
-                                            config->format,
-                                            channel_count,
-                                            false /*is_low_latency*/);
+        buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
+                                             config->sample_rate,
+                                             config->format,
+                                             channel_count,
+                                             false /*is_low_latency*/);
         in->config.period_size = buffer_size / frame_size;
         in->config.rate = config->sample_rate;
         in->af_period_multiplier = 1;
@@ -4181,10 +4232,11 @@
             if (!in->realtime) {
                 in->config = pcm_config_audio_capture;
                 frame_size = audio_stream_in_frame_size(&in->stream);
-                buffer_size = get_input_buffer_size(config->sample_rate,
-                                                    config->format,
-                                                    channel_count,
-                                                    is_low_latency);
+                buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
+                                                     config->sample_rate,
+                                                     config->format,
+                                                     channel_count,
+                                                     is_low_latency);
                 in->config.period_size = buffer_size / frame_size;
                 in->config.rate = config->sample_rate;
                 in->af_period_multiplier = 1;
@@ -4204,13 +4256,33 @@
             in->stream.get_mmap_position = in_get_mmap_position;
             in->af_period_multiplier = 1;
             ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
+        } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
+                   in->dev->mode == AUDIO_MODE_IN_COMMUNICATION &&
+                   (config->sample_rate == 8000 ||
+                    config->sample_rate == 16000 ||
+                    config->sample_rate == 32000 ||
+                    config->sample_rate == 48000) &&
+                   channel_count == 1) {
+            in->usecase = USECASE_AUDIO_RECORD_VOIP;
+            in->config = pcm_config_audio_capture;
+            frame_size = audio_stream_in_frame_size(&in->stream);
+            buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
+                                                 config->sample_rate,
+                                                 config->format,
+                                                 channel_count, false /*is_low_latency*/);
+            in->config.period_size = buffer_size / frame_size;
+            in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
+            in->config.rate = config->sample_rate;
+            in->af_period_multiplier = 1;
+            in->flags |= AUDIO_INPUT_FLAG_VOIP_TX;
         } else {
             in->config = pcm_config_audio_capture;
             frame_size = audio_stream_in_frame_size(&in->stream);
-            buffer_size = get_input_buffer_size(config->sample_rate,
-                                                config->format,
-                                                channel_count,
-                                                is_low_latency);
+            buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
+                                                 config->sample_rate,
+                                                 config->format,
+                                                 channel_count,
+                                                 is_low_latency);
             in->config.period_size = buffer_size / frame_size;
             in->config.rate = config->sample_rate;
             in->af_period_multiplier = 1;
@@ -4220,6 +4292,7 @@
     }
 
     in->config.channels = channel_count;
+    in->sample_rate  = in->config.rate;
 
     /* This stream could be for sound trigger lab,
        get sound trigger pcm if present */
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index b1e5e45..28bf19b 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -132,6 +132,10 @@
     USECASE_AUDIO_RECORD_AFE_PROXY,
     USECASE_AUDIO_DSM_FEEDBACK,
 
+    /* VOIP usecase*/
+    USECASE_AUDIO_PLAYBACK_VOIP,
+    USECASE_AUDIO_RECORD_VOIP,
+
     AUDIO_USECASE_MAX
 };
 
@@ -170,7 +174,8 @@
 
 struct stream_app_type_cfg {
     int sample_rate;
-    uint32_t bit_width;
+    uint32_t bit_width; // unused
+    const char *mode;
     int app_type;
 };
 
@@ -198,7 +203,6 @@
     bool muted;
     uint64_t written; /* total frames written, not cleared when entering standby */
     audio_io_handle_t handle;
-    struct stream_app_type_cfg app_type_cfg;
 
     int non_blocking;
     int playback_started;
@@ -219,6 +223,8 @@
 
     error_log_t *error_log;
     power_log_t *power_log;
+
+    struct stream_app_type_cfg app_type_cfg;
 };
 
 struct stream_in {
@@ -232,6 +238,7 @@
     int pcm_device_id;
     audio_devices_t device;
     audio_channel_mask_t channel_mask;
+    unsigned int sample_rate;
     audio_usecase_t usecase;
     bool enable_aec;
     bool enable_ns;
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index aa3419d..6d92d93 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -2322,12 +2322,16 @@
 
 bool platform_supports_app_type_cfg() { return false; }
 
-void platform_add_app_type(int bw __unused, const char *uc_type __unused,
-                           int app_type __unused, int max_sr __unused) {}
+void platform_add_app_type(const char *uc_type __unused,
+                           const char *mode __unused,
+                           int bw __unused, int app_type __unused,
+                           int max_sr __unused) {}
 
 int platform_get_app_type_v2(void *platform __unused,
                              enum usecase_type_t type __unused,
+                             const char *mode __unused,
                              int bw __unused, int sr __unused,
                              int *app_type __unused) {
     return -ENOSYS;
 }
+
diff --git a/hal/msm8916/platform.h b/hal/msm8916/platform.h
index 07dc1af..69bfd62 100644
--- a/hal/msm8916/platform.h
+++ b/hal/msm8916/platform.h
@@ -194,6 +194,12 @@
 #define AUDIO_CAPTURE_PERIOD_DURATION_MSEC 20
 #define AUDIO_CAPTURE_PERIOD_COUNT 2
 
+#define VOIP_CAPTURE_PERIOD_DURATION_MSEC 20
+#define VOIP_CAPTURE_PERIOD_COUNT 2
+
+#define VOIP_PLAYBACK_PERIOD_DURATION_MSEC 20
+#define VOIP_PLAYBACK_PERIOD_COUNT 2
+
 #define LOW_LATENCY_CAPTURE_SAMPLE_RATE 48000
 #define LOW_LATENCY_CAPTURE_PERIOD_SIZE 240
 #define LOW_LATENCY_CAPTURE_USE_CASE 1
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index cfae645..cd7305d 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -1153,11 +1153,19 @@
 
 bool platform_supports_app_type_cfg() { return false; }
 
-void platform_add_app_type(int bw, const char *uc_type,
-                           int app_type, int max_sr) {}
+void platform_add_app_type(const char *uc_type __unused,
+                           const char *mode __unused,
+                           int bw __unused, int app_type __unused,
+                           int max_sr __unused) {}
 
+int platform_get_app_type_v2(void *platform __unused,
+                             enum usecase_type_t type __unused,
+                             const char *mode __unused,
+                             int bw __unused, int sr __unused,
+                             int *app_type __unused) {
+    return -ENOSYS;
+}
 
-int platform_get_app_type_v2(void *platform, enum usecase_type_t type,
-                             int bw, int sr, int *app_type) {
+int platform_get_snd_device_backend_index(snd_device_t snd_device) {
     return -ENOSYS;
 }
diff --git a/hal/msm8960/platform.h b/hal/msm8960/platform.h
index 0835378..1276b73 100644
--- a/hal/msm8960/platform.h
+++ b/hal/msm8960/platform.h
@@ -119,6 +119,12 @@
 #define AUDIO_CAPTURE_PERIOD_DURATION_MSEC 20
 #define AUDIO_CAPTURE_PERIOD_COUNT 2
 
+#define VOIP_CAPTURE_PERIOD_DURATION_MSEC 20
+#define VOIP_CAPTURE_PERIOD_COUNT 2
+
+#define VOIP_PLAYBACK_PERIOD_DURATION_MSEC 20
+#define VOIP_PLAYBACK_PERIOD_COUNT 2
+
 #define LOW_LATENCY_CAPTURE_SAMPLE_RATE 48000
 #define LOW_LATENCY_CAPTURE_PERIOD_SIZE 240
 #define LOW_LATENCY_CAPTURE_USE_CASE 0
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 02512ea..72f9937 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -196,6 +196,10 @@
                                         AFE_PROXY_RECORD_PCM_DEVICE},
     [USECASE_AUDIO_DSM_FEEDBACK] = {QUAT_MI2S_PCM_DEVICE, QUAT_MI2S_PCM_DEVICE},
 
+    [USECASE_AUDIO_PLAYBACK_VOIP] = {AUDIO_PLAYBACK_VOIP_PCM_DEVICE,
+                                     AUDIO_PLAYBACK_VOIP_PCM_DEVICE},
+    [USECASE_AUDIO_RECORD_VOIP] = {AUDIO_RECORD_VOIP_PCM_DEVICE,
+                                   AUDIO_RECORD_VOIP_PCM_DEVICE},
 };
 
 /* Array to store sound devices */
@@ -573,6 +577,8 @@
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_AFE_PROXY)},
     {TO_NAME_INDEX(USECASE_AUDIO_RECORD_AFE_PROXY)},
     {TO_NAME_INDEX(USECASE_AUDIO_DSM_FEEDBACK)},
+    {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_VOIP)},
+    {TO_NAME_INDEX(USECASE_AUDIO_RECORD_VOIP)},
 };
 
 static const struct name_to_index usecase_type_index[USECASE_TYPE_MAX] = {
@@ -587,6 +593,7 @@
     int bit_width;
     int app_type;
     int max_rate;
+    char *mode;
     struct listnode node; // membership in app_type_entry_list;
 };
 
@@ -722,6 +729,8 @@
     int mode = CAL_MODE_RTAC;
     struct listnode *node;
     struct audio_usecase *usecase;
+    bool valid_uc_type = false;
+    bool valid_dev = false;
 
     if (my_data->acdb_send_gain_dep_cal == NULL) {
         ALOGE("%s: dlsym error for acdb_send_gain_dep_cal", __func__);
@@ -736,19 +745,20 @@
         // find the current active sound device
         list_for_each(node, &adev->usecase_list) {
             usecase = node_to_item(node, struct audio_usecase, list);
-
-            if (usecase != NULL &&
-                usecase->type == PCM_PLAYBACK &&
-                (usecase->stream.out->devices == AUDIO_DEVICE_OUT_SPEAKER)) {
-
-                ALOGV("%s: out device is %d", __func__,  usecase->out_snd_device);
-                if (audio_extn_spkr_prot_is_enabled()) {
+            valid_uc_type =  usecase->type == PCM_PLAYBACK;
+            audio_devices_t dev = usecase->stream.out->devices;
+            valid_dev = (dev == AUDIO_DEVICE_OUT_SPEAKER ||
+                         dev == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
+                         dev == AUDIO_DEVICE_OUT_WIRED_HEADPHONE);
+             if (usecase != NULL && valid_uc_type && valid_dev) {
+                 ALOGV("%s: out device is %d", __func__,  usecase->out_snd_device);
+                 if (audio_extn_spkr_prot_is_enabled()) {
                     acdb_dev_id = audio_extn_spkr_prot_get_acdb_id(usecase->out_snd_device);
-                } else {
-                    acdb_dev_id = acdb_device_table[usecase->out_snd_device];
-                }
+                 } else {
+                     acdb_dev_id = acdb_device_table[usecase->out_snd_device];
+                 }
 
-                if (!my_data->acdb_send_gain_dep_cal(acdb_dev_id, app_type,
+                 if (!my_data->acdb_send_gain_dep_cal(acdb_dev_id, app_type,
                                                      acdb_dev_type, mode, level)) {
                     // set ret_val true if at least one calibration is set successfully
                     ret_val = true;
@@ -1540,6 +1550,7 @@
         node = list_head(&app_type_entry_list);
         list_remove(node);
         ap = node_to_item(node, struct app_type_entry, node);
+        if (ap->mode) free(ap->mode);
         free(ap);
     }
 
@@ -3050,7 +3061,9 @@
         ALOGE("%s: invalid usecase type", __func__);
         ret = -EINVAL;
     }
-    ALOGV("%s: pcm_device_table[%d][%d] = %d", __func__, usecase, type, pcm_id);
+    ALOGV("%s: pcm_device_table[%d %s][%d] = %d", __func__, usecase,
+          use_case_table[usecase],
+          type, pcm_id);
     pcm_device_table[usecase][type] = pcm_id;
 done:
     return ret;
@@ -3748,7 +3761,8 @@
         goto done;
     }
 
-    posix_memalign((void **)&be_dai_name_table, 32, size);
+    be_dai_name_table =
+            (const struct be_dai_name_struct *)calloc(1, size);
     if (be_dai_name_table == NULL) {
         ALOGE("%s: Failed to allocate memory for %s\n",
                __func__, mixer_ctl_name);
@@ -3821,7 +3835,7 @@
 
     ALOGV("%s: enter with device %d\n", __func__, device);
 
-    if ((device <= SND_DEVICE_MIN) || (device >= SND_DEVICE_MAX)) {
+    if ((device < SND_DEVICE_MIN) || (device >= SND_DEVICE_MAX)) {
         ALOGE("%s: Invalid snd_device = %d",
               __func__, device);
         be_dai_id = -EINVAL;
@@ -3885,7 +3899,9 @@
 }
 
 // called from info parser
-void platform_add_app_type(int bw, const char *uc_type,
+void platform_add_app_type(const char *uc_type,
+                           const char *mode,
+                           int bw,
                            int app_type, int max_rate) {
     struct app_type_entry *ap =
             (struct app_type_entry *)calloc(1, sizeof(struct app_type_entry));
@@ -3908,11 +3924,12 @@
         return;
     }
 
-    ALOGI("%s bw %d uc %s app_type %d max_rate %d",
-          __func__, bw, uc_type, app_type, max_rate);
+    ALOGI("%s uc %s mode %s bw %d app_type %d max_rate %d",
+          __func__, uc_type, mode, bw, app_type, max_rate);
     ap->bit_width = bw;
     ap->app_type = app_type;
     ap->max_rate = max_rate;
+    ap->mode = strdup(mode);
     list_add_tail(&app_type_entry_list, &ap->node);
 }
 
@@ -3928,23 +3945,35 @@
     return 0;
 }
 
-int platform_get_app_type_v2(void *platform, usecase_type_t uc_type,
+int platform_get_app_type_v2(void *platform,
+                             usecase_type_t uc_type,
+                             const char *mode,
                              int bw, int sr __unused,
                              int *app_type)
 {
     struct listnode *node;
     struct app_type_entry *entry;
     *app_type = -1;
+
+    ALOGV("%s find match for uc %d mode %s bw %d rate %d",
+          __func__, uc_type, mode, bw, sr);
     list_for_each(node, &app_type_entry_list) {
         entry = node_to_item(node, struct app_type_entry, node);
+        ALOGV("%s uc %d mode %s bw %d app_type %d max_rate %d",
+              __func__, entry->uc_type, entry->mode, entry->bit_width,
+              entry->app_type, entry->max_rate);
         if (entry->bit_width == bw &&
-            entry->uc_type == uc_type) {
+            entry->uc_type == uc_type &&
+            sr <= entry->max_rate &&
+            entry->mode && !strcmp(mode, entry->mode)) {
+            ALOGV("%s found match %d", __func__, entry->app_type);
             *app_type = entry->app_type;
             break;
         }
     }
 
     if (*app_type == -1) {
+        ALOGV("%s no match found, return default", __func__);
         return platform_get_default_app_type_v2(platform, uc_type, app_type);
     }
     return 0;
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index 9df8a1d..4692560 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -182,7 +182,7 @@
 };
 #define DEFAULT_OUTPUT_SAMPLING_RATE    48000
 #define OUTPUT_SAMPLING_RATE_44100      44100
-#define DEFAULT_INPUT_SAMPLING_RATE 48000
+#define DEFAULT_INPUT_SAMPLING_RATE     48000
 
 enum {
     DEFAULT_CODEC_BACKEND,
@@ -245,6 +245,12 @@
 #define AUDIO_CAPTURE_PERIOD_DURATION_MSEC 20
 #define AUDIO_CAPTURE_PERIOD_COUNT 2
 
+#define VOIP_CAPTURE_PERIOD_DURATION_MSEC 20
+#define VOIP_CAPTURE_PERIOD_COUNT 2
+
+#define VOIP_PLAYBACK_PERIOD_DURATION_MSEC 20
+#define VOIP_PLAYBACK_PERIOD_COUNT 2
+
 #define LOW_LATENCY_CAPTURE_SAMPLE_RATE 48000
 #define LOW_LATENCY_CAPTURE_PERIOD_SIZE 240
 #define LOW_LATENCY_CAPTURE_USE_CASE 1
@@ -266,6 +272,10 @@
 #define LOWLATENCY_PCM_DEVICE 15
 #define VOICE_VSID  0x10C01000
 
+//needs verification
+#define AUDIO_PLAYBACK_VOIP_PCM_DEVICE 5
+#define AUDIO_RECORD_VOIP_PCM_DEVICE 6
+
 #ifdef PLATFORM_MSM8x26
 #define VOICE_CALL_PCM_DEVICE 2
 #define VOICE2_CALL_PCM_DEVICE 14
diff --git a/hal/platform_api.h b/hal/platform_api.h
index c51c492..98e4223 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -51,7 +51,7 @@
 int platform_get_snd_device_acdb_id(snd_device_t snd_device);
 int platform_send_audio_calibration(void *platform, snd_device_t snd_device);
 int platform_send_audio_calibration_v2(void *platform, struct audio_usecase *usecase,
-                                           int app_type, int sample_rate);
+                                       int app_type, int sample_rate);
 int platform_get_default_app_type_v2(void *platform, enum usecase_type_t type, int *app_type);
 int platform_switch_voice_call_device_pre(void *platform);
 int platform_switch_voice_call_enable_device_config(void *platform,
@@ -134,7 +134,12 @@
      unsigned int stream_sr,int *sample_rate);
 int platform_get_snd_device_backend_index(snd_device_t snd_device);
 bool platform_supports_app_type_cfg();
-int platform_get_app_type_v2(void *platform, enum usecase_type_t type,
+int platform_get_app_type_v2(void *platform,
+                             enum usecase_type_t type,
+                             const char *mode,
                              int bw, int sr, int *app_type);
-void platform_add_app_type(int bw, const char *uc_type, int app_type, int max_sr);
+void platform_add_app_type(const char *uc_type,
+                           const char *mode,
+                           int bw, int app_type, int max_sr);
+int platform_get_snd_device_backend_index(snd_device_t snd_device);
 #endif // AUDIO_PLATFORM_API_H
diff --git a/hal/platform_info.c b/hal/platform_info.c
index cd2b5d4..283936e 100644
--- a/hal/platform_info.c
+++ b/hal/platform_info.c
@@ -320,22 +320,28 @@
         goto done;
     }
 
-    if (strcmp(attr[2], "bit_width")) {
+    if (strcmp(attr[2], "mode")) {
+        ALOGE("%s: mode not found", __func__);
+        goto done;
+    }
+
+    if (strcmp(attr[4], "bit_width")) {
         ALOGE("%s: bit_width not found", __func__);
         goto done;
     }
 
-    if (strcmp(attr[4], "id")) {
+    if (strcmp(attr[6], "id")) {
         ALOGE("%s: id not found", __func__);
         goto done;
     }
 
-    if (strcmp(attr[6], "max_rate")) {
+    if (strcmp(attr[8], "max_rate")) {
         ALOGE("%s: max rate not found", __func__);
         goto done;
     }
 
-    platform_add_app_type(atoi(attr[3]), attr[1], atoi(attr[5]), atoi(attr[7]));
+    platform_add_app_type(attr[1], attr[3], atoi(attr[5]), atoi(attr[7]),
+                          atoi(attr[9]));
 done:
     return;
 }
diff --git a/post_proc/volume_listener.c b/post_proc/volume_listener.c
index 5494fd0..54226b7 100644
--- a/post_proc/volume_listener.c
+++ b/post_proc/volume_listener.c
@@ -43,6 +43,7 @@
                                                             i == RING?"RING": \
                                                             i == ALARM?"ALARM": \
                                                             i == VOICE_CALL?"Voice_call": \
+                                                            i == VC_CALL ?"VC_call":       \
                                                             i == NOTIFICATION?"Notification":\
                                                             "--INVALID--"); \
 
@@ -72,6 +73,7 @@
     RING,
     ALARM,
     VOICE_CALL,
+    VC_CALL,
     NOTIFICATION,
     MAX_STREAM_TYPES,
 };
@@ -206,6 +208,8 @@
 static const char *primary_audio_hal_path[] =
     {"/vendor/lib/hw/", "/system/lib/hw/"};
 
+static bool headset_cal_enabled;
+
 /*
  *  Local functions
  */
@@ -225,6 +229,7 @@
                 context->stream_type == RING ? "RING" :
                 context->stream_type == ALARM ? "ALARM" :
                 context->stream_type == VOICE_CALL ? "VOICE_CALL" :
+                context->stream_type == VC_CALL ? "VC_CALL" :
                 context->stream_type == NOTIFICATION ? "NOTIFICATION" : "--INVALID--",
                 context->dev_id, context->state, context->session_id, context->left_vol,context->right_vol);
     }
@@ -232,6 +237,20 @@
     ALOGW("DUMP_END :: ===========");
 }
 
+static inline bool valid_dev_in_context(struct vol_listener_context_s *context)
+{
+    if (context->dev_id == AUDIO_DEVICE_OUT_SPEAKER)
+        return true;
+
+    if (context->stream_type == VC_CALL && headset_cal_enabled &&
+        (context->dev_id == AUDIO_DEVICE_OUT_EARPIECE ||
+         context->dev_id == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
+         context->dev_id == AUDIO_DEVICE_OUT_WIRED_HEADPHONE))
+        return true;
+
+    return false;
+}
+
 static void check_and_set_gain_dep_cal()
 {
     // iterate through list and make decision to set new gain dep cal level for speaker device
@@ -257,7 +276,7 @@
     list_for_each(node, &vol_effect_list) {
         context = node_to_item(node, struct vol_listener_context_s, effect_list_node);
         if ((context->state == VOL_LISTENER_STATE_ACTIVE) &&
-            (context->dev_id & AUDIO_DEVICE_OUT_SPEAKER)) {
+            valid_dev_in_context(context)) {
             sum_energy_used = true;
             temp_vol = fmax(context->left_vol, context->right_vol);
             sum_energy += temp_vol * temp_vol;
@@ -437,8 +456,8 @@
 
         // After changing the state and if device is speaker
         // recalculate gain dep cal level
-        if (context->dev_id == AUDIO_DEVICE_OUT_SPEAKER) {
-                check_and_set_gain_dep_cal();
+        if (valid_dev_in_context(context)) {
+            check_and_set_gain_dep_cal();
         }
 
         break;
@@ -464,7 +483,7 @@
 
         // After changing the state and if device is speaker
         // recalculate gain dep cal level
-        if (context->dev_id == AUDIO_DEVICE_OUT_SPEAKER) {
+        if (valid_dev_in_context(context)) {
             check_and_set_gain_dep_cal();
         }
 
@@ -495,8 +514,8 @@
                __func__, context->dev_id, new_device);
 
         // check if old or new device is speaker
-        if ((context->dev_id ==  AUDIO_DEVICE_OUT_SPEAKER) ||
-            (new_device == AUDIO_DEVICE_OUT_SPEAKER)) {
+        if (valid_dev_in_context(context) ||
+            new_device == AUDIO_DEVICE_OUT_SPEAKER) {
             recompute_gain_dep_cal_Level = true;
         }
 
@@ -521,7 +540,7 @@
             goto exit;
         }
 
-        if (context->dev_id == AUDIO_DEVICE_OUT_SPEAKER) {
+        if (valid_dev_in_context(context)) {
             recompute_gain_dep_cal_Level = true;
         }
 
@@ -649,13 +668,8 @@
         }
     }
 
-    // check system property to see if dumping is required
-    char check_dump_val[PROPERTY_VALUE_MAX];
-    property_get("audio.volume.listener.dump", check_dump_val, "0");
-    if (atoi(check_dump_val)) {
-        dumping_enabled = true;
-    }
-
+    dumping_enabled = property_get_bool("audio.volume.listener.dump", false);
+    headset_cal_enabled = property_get_bool("audio.volume.headset.gain.depcal", false);
     init_status = 0;
     list_init(&vol_effect_list);
     initialized = true;
@@ -763,7 +777,7 @@
             ALOGV("--- Found something to remove ---");
             list_remove(node);
             PRINT_STREAM_TYPE(context->stream_type);
-            if (context->dev_id == AUDIO_DEVICE_OUT_SPEAKER) {
+            if (valid_dev_in_context(context)) {
                 recompute_flag = true;
             }
             free(context);