Merge "hal: Update STHAL about Voicecall usecase." into audio-hal.lnx.4.0
diff --git a/configs/sdm660/audio_policy_configuration.xml b/configs/sdm660/audio_policy_configuration.xml
index f0528c6..5cb77df 100644
--- a/configs/sdm660/audio_policy_configuration.xml
+++ b/configs/sdm660/audio_policy_configuration.xml
@@ -117,15 +117,6 @@
                     <profile name="" format="AUDIO_FORMAT_AAC_HE_V2"
                              samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000"
                              channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
-                    <profile name="" format="AUDIO_FORMAT_AC3"
-                             samplingRates="32000,44100,48000"
-                             channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_2POINT1,AUDIO_CHANNEL_OUT_QUAD,AUDIO_CHANNEL_OUT_PENTA,AUDIO_CHANNEL_OUT_5POINT1"/>
-                    <profile name="" format="AUDIO_FORMAT_E_AC3"
-                             samplingRates="32000,44100,48000"
-                             channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_2POINT1,AUDIO_CHANNEL_OUT_QUAD,AUDIO_CHANNEL_OUT_PENTA,AUDIO_CHANNEL_OUT_5POINT1,AUDIO_CHANNEL_OUT_6POINT1,AUDIO_CHANNEL_OUT_7POINT1"/>
-                    <profile name="" format="AUDIO_FORMAT_E_AC3_JOC"
-                             samplingRates="32000,44100,48000"
-                             channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_2POINT1,AUDIO_CHANNEL_OUT_QUAD,AUDIO_CHANNEL_OUT_PENTA,AUDIO_CHANNEL_OUT_5POINT1,AUDIO_CHANNEL_OUT_6POINT1,AUDIO_CHANNEL_OUT_7POINT1"/>
                     <profile name="" format="AUDIO_FORMAT_DTS"
                              samplingRates="32000,44100,48000"
                              channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_2POINT1,AUDIO_CHANNEL_OUT_QUAD,AUDIO_CHANNEL_OUT_PENTA,AUDIO_CHANNEL_OUT_5POINT1"/>
diff --git a/hal/acdb.c b/hal/acdb.c
index ad67d61..4ae03e9 100644
--- a/hal/acdb.c
+++ b/hal/acdb.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
  * Not a Contribution.
  *
  * Copyright (C) 2013 The Android Open Source Project
@@ -32,11 +32,7 @@
 {
 
     int result = -1;
-    char *cvd_version = NULL;
-
-    const char *snd_card_name = NULL;
     struct mixer *mixer = NULL;
-    struct acdb_platform_data *my_data = NULL;
 
     if(snd_card_num < 0) {
         ALOGE("invalid sound card number");
@@ -47,7 +43,25 @@
     if (!mixer) {
         ALOGE("%s: Unable to open the mixer card: %d", __func__,
                snd_card_num);
-        goto cleanup;
+        return result;
+    }
+    result = acdb_init_v2(mixer);
+    mixer_close(mixer);
+    return result;
+}
+
+int acdb_init_v2(struct mixer *mixer)
+{
+
+    int result = -1;
+    char *cvd_version = NULL;
+
+    const char *snd_card_name = NULL;
+    struct acdb_platform_data *my_data = NULL;
+
+    if (!mixer) {
+       ALOGE("Invalid mixer handle");
+       return result;
     }
 
     my_data = calloc(1, sizeof(struct acdb_platform_data));
@@ -155,9 +169,6 @@
         free(my_data);
     }
 
-    if (mixer)
-        mixer_close(mixer);
-
     if (cvd_version)
         free(cvd_version);
 
diff --git a/hal/acdb.h b/hal/acdb.h
index d1f863b..140370a 100644
--- a/hal/acdb.h
+++ b/hal/acdb.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
  * Not a Contribution.
  *
  * Copyright (C) 2013 The Android Open Source Project
@@ -33,6 +33,7 @@
 #define PLATFORM_INFO_XML_PATH "/vendor/etc/audio_platform_info.xml"
 #endif
 
+struct mixer;
 /* Audio calibration related functions */
 typedef void (*acdb_deallocate_t)();
 typedef int  (*acdb_init_t)();
@@ -68,6 +69,7 @@
 };
 
 int acdb_init(int);
+int acdb_init_v2(struct mixer *);
 
 int acdb_set_metainfo_key(void *platform, char *name, int key);
 #endif //ACDB_H
diff --git a/hal/audio_extn/audio_defs.h b/hal/audio_extn/audio_defs.h
index 3921f49..1b34c53 100755
--- a/hal/audio_extn/audio_defs.h
+++ b/hal/audio_extn/audio_defs.h
@@ -117,6 +117,10 @@
 /* MAX SECTORS for sourcetracking feature */
 #define MAX_SECTORS 8
 
+/* Max length for license string */
+#define AUDIO_PRODUCT_STR_MAX_LENGTH (64)
+#define AUDIO_LICENSE_STR_MAX_LENGTH (64)
+
 struct source_tracking_param {
     uint8_t   vad[MAX_SECTORS];
     uint16_t  doa_speech;
@@ -255,6 +259,13 @@
     uint32_t mixer_coeffs[AUDIO_CHANNEL_COUNT_MAX][AUDIO_CHANNEL_COUNT_MAX];
 } mix_matrix_params_t;
 
+
+typedef struct audio_license_params {
+    char product[AUDIO_PRODUCT_STR_MAX_LENGTH + 1];
+    int  key;
+    char license[AUDIO_LICENSE_STR_MAX_LENGTH + 1];
+} audio_license_params_t;
+
 typedef union {
     struct source_tracking_param st_params;
     struct sound_focus_param sf_params;
@@ -268,6 +279,7 @@
     struct audio_out_channel_map_param channel_map_param;
     struct audio_device_cfg_param device_cfg;
     struct mix_matrix_params mm_params;
+    struct audio_license_params license_params;
 } audio_extn_param_payload;
 
 typedef enum {
@@ -288,7 +300,9 @@
     /* Pan/scale params to be set on ASM */
     AUDIO_EXTN_PARAM_OUT_MIX_MATRIX_PARAMS,
     /* Downmix params to be set on ADM */
-    AUDIO_EXTN_PARAM_CH_MIX_MATRIX_PARAMS
+    AUDIO_EXTN_PARAM_CH_MIX_MATRIX_PARAMS,
+    /* License information */
+    AUDIO_EXTN_PARAM_LICENSE_PARAMS,
 } audio_extn_param_id;
 
 #endif /* AUDIO_DEFS_H */
diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c
index 292e516..c6c0924 100755
--- a/hal/audio_extn/audio_extn.c
+++ b/hal/audio_extn/audio_extn.c
@@ -300,6 +300,74 @@
         ALOGV("%s: Setting custom stereo state success", __func__);
     }
 }
+
+void audio_extn_send_dual_mono_mixing_coefficients(struct stream_out *out)
+{
+    struct audio_device *adev = out->dev;
+    struct mixer_ctl *ctl;
+    char mixer_ctl_name[128];
+    int cust_ch_mixer_cfg[128], len = 0;
+    int ip_channel_cnt = audio_channel_count_from_out_mask(out->channel_mask);
+    int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
+    int op_channel_cnt= 2;
+    int i, j, err;
+
+    ALOGV("%s", __func__);
+    if (!out->started) {
+        out->set_dual_mono = true;
+        goto exit;
+    }
+
+    ALOGD("%s: i/p channel count %d, o/p channel count %d, pcm id %d", __func__,
+           ip_channel_cnt, op_channel_cnt, pcm_device_id);
+
+    snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+             "Audio Stream %d Channel Mix Cfg", pcm_device_id);
+    ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+    if (!ctl) {
+        ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
+        __func__, mixer_ctl_name);
+        goto exit;
+    }
+
+    /* Output channel count corresponds to backend configuration channels.
+     * Input channel count corresponds to ASM session channels.
+     * Set params is called with channels that need to be selected from
+     * input to generate output.
+     * ex: "8,2" to downmix from 8 to 2 i.e. to downmix from 8 to 2,
+     *
+     * This mixer control takes values in the following sequence:
+     * - input channel count(m)
+     * - output channel count(n)
+     * - weight coeff for [out ch#1, in ch#1]
+     * ....
+     * - weight coeff for [out ch#1, in ch#m]
+     *
+     * - weight coeff for [out ch#2, in ch#1]
+     * ....
+     * - weight coeff for [out ch#2, in ch#m]
+     *
+     * - weight coeff for [out ch#n, in ch#1]
+     * ....
+     * - weight coeff for [out ch#n, in ch#m]
+     *
+     * To get dualmono ouptu weightage coeff is calculated as Unity gain
+     * divided by number of input channels.
+     */
+    cust_ch_mixer_cfg[len++] = ip_channel_cnt;
+    cust_ch_mixer_cfg[len++] = op_channel_cnt;
+    for (i = 0; i < op_channel_cnt; i++) {
+         for (j = 0; j < ip_channel_cnt; j++) {
+              cust_ch_mixer_cfg[len++] = Q14_GAIN_UNITY/ip_channel_cnt;
+         }
+    }
+
+    err = mixer_ctl_set_array(ctl, cust_ch_mixer_cfg, len);
+    if (err)
+        ALOGE("%s: ERROR. Mixer ctl set failed", __func__);
+exit:
+    return;
+}
 #endif /* CUSTOM_STEREO_ENABLED */
 
 #ifndef DTS_EAGLE
@@ -1261,7 +1329,15 @@
     if (ssr_supported) {
         return audio_extn_ssr_set_usecase(in, config, update_params);
     } else if (audio_extn_ffv_check_usecase(in)) {
-        return audio_extn_ffv_set_usecase(in);
+        char ffv_lic[LICENSE_STR_MAX_LEN + 1] = {0};
+        int ffv_key = 0;
+        if(platform_get_license_by_product(adev->platform, PRODUCT_FFV, &ffv_key, ffv_lic))
+        {
+            ALOGD("%s: Valid licence not availble for %s ", __func__, PRODUCT_FFV);
+            return -EINVAL;
+        }
+        ALOGD("%s: KEY: %d LICENSE: %s ", __func__, ffv_key, ffv_lic);
+        return audio_extn_ffv_set_usecase(in, ffv_key, ffv_lic);
     } else {
         return audio_extn_set_multichannel_mask(adev, in, config,
                                                 update_params);
@@ -1488,70 +1564,4 @@
     return 0;
 }
 
-void audio_extn_send_dual_mono_mixing_coefficients(struct stream_out *out)
-{
-    struct audio_device *adev = out->dev;
-    struct mixer_ctl *ctl;
-    char mixer_ctl_name[128];
-    int cust_ch_mixer_cfg[128], len = 0;
-    int ip_channel_cnt = audio_channel_count_from_out_mask(out->channel_mask);
-    int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
-    int op_channel_cnt= 2;
-    int i, j, err;
 
-    ALOGV("%s", __func__);
-    if (!out->started) {
-        out->set_dual_mono = true;
-        goto exit;
-    }
-
-    ALOGD("%s: i/p channel count %d, o/p channel count %d, pcm id %d", __func__,
-           ip_channel_cnt, op_channel_cnt, pcm_device_id);
-
-    snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
-             "Audio Stream %d Channel Mix Cfg", pcm_device_id);
-    ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
-    if (!ctl) {
-        ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
-        __func__, mixer_ctl_name);
-        goto exit;
-    }
-
-    /* Output channel count corresponds to backend configuration channels.
-     * Input channel count corresponds to ASM session channels.
-     * Set params is called with channels that need to be selected from
-     * input to generate output.
-     * ex: "8,2" to downmix from 8 to 2 i.e. to downmix from 8 to 2,
-     *
-     * This mixer control takes values in the following sequence:
-     * - input channel count(m)
-     * - output channel count(n)
-     * - weight coeff for [out ch#1, in ch#1]
-     * ....
-     * - weight coeff for [out ch#1, in ch#m]
-     *
-     * - weight coeff for [out ch#2, in ch#1]
-     * ....
-     * - weight coeff for [out ch#2, in ch#m]
-     *
-     * - weight coeff for [out ch#n, in ch#1]
-     * ....
-     * - weight coeff for [out ch#n, in ch#m]
-     *
-     * To get dualmono ouptu weightage coeff is calculated as Unity gain
-     * divided by number of input channels.
-     */
-    cust_ch_mixer_cfg[len++] = ip_channel_cnt;
-    cust_ch_mixer_cfg[len++] = op_channel_cnt;
-    for (i = 0; i < op_channel_cnt; i++) {
-         for (j = 0; j < ip_channel_cnt; j++) {
-              cust_ch_mixer_cfg[len++] = Q14_GAIN_UNITY/ip_channel_cnt;
-         }
-    }
-
-    err = mixer_ctl_set_array(ctl, cust_ch_mixer_cfg, len);
-    if (err)
-        ALOGE("%s: ERROR. Mixer ctl set failed", __func__);
-exit:
-    return;
-}
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 46c09a9..0092e87 100755
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -638,6 +638,8 @@
                                   struct audio_device *adev,
                                   struct audio_usecase *usecase);
 int audio_extn_utils_get_snd_card_num();
+int audio_extn_utils_open_snd_mixer(struct mixer **mixer_handle);
+void audio_extn_utils_close_snd_mixer(struct mixer *mixer);
 bool audio_extn_is_dsp_bit_width_enforce_mode_supported(audio_output_flags_t flags);
 bool audio_extn_utils_is_dolby_format(audio_format_t format);
 int audio_extn_utils_get_bit_width_from_string(const char *);
@@ -1000,8 +1002,8 @@
 #define audio_extn_ffv_init(adev) (0)
 #define audio_extn_ffv_deinit() (0)
 #define audio_extn_ffv_check_usecase(in) (0)
-#define audio_extn_ffv_set_usecase(in) (0)
-#define audio_extn_ffv_stream_init(in) (0)
+#define audio_extn_ffv_set_usecase(in, key, lic) (0)
+#define audio_extn_ffv_stream_init(in, key, lic) (0)
 #define audio_extn_ffv_stream_deinit() (0)
 #define audio_extn_ffv_update_enabled() (0)
 #define audio_extn_ffv_get_enabled() (0)
@@ -1018,8 +1020,8 @@
 int32_t audio_extn_ffv_init(struct audio_device *adev);
 int32_t audio_extn_ffv_deinit();
 bool audio_extn_ffv_check_usecase(struct stream_in *in);
-int audio_extn_ffv_set_usecase(struct stream_in *in);
-int32_t audio_extn_ffv_stream_init(struct stream_in *in);
+int audio_extn_ffv_set_usecase( struct stream_in *in, int key, char* lic);
+int32_t audio_extn_ffv_stream_init(struct stream_in *in, int key, char* lic);
 int32_t audio_extn_ffv_stream_deinit();
 void audio_extn_ffv_update_enabled();
 bool audio_extn_ffv_get_enabled();
@@ -1043,4 +1045,5 @@
 #else
 void audio_extn_send_dual_mono_mixing_coefficients(struct stream_out *out);
 #endif
+int audio_extn_utils_get_license_params(const struct audio_device *adev,  struct audio_license_params *lic_params);
 #endif /* AUDIO_EXTN_H */
diff --git a/hal/audio_extn/ffv.c b/hal/audio_extn/ffv.c
old mode 100644
new mode 100755
index 596f49b..54ce30c
--- a/hal/audio_extn/ffv.c
+++ b/hal/audio_extn/ffv.c
@@ -114,7 +114,8 @@
 static FfvStatusType (*ffv_init_fn)(void** handle, int num_tx_in_ch,
     int num_out_ch, int num_ec_ref_ch, int frame_len, int sample_rate,
     const char *config_file_name, char *svaModelBuffer,
-    uint32_t svaModelSize, int* totMemSize);
+    uint32_t svaModelSize, int* totMemSize,
+    int product_id, const char* prduct_license);
 static void (*ffv_deinit_fn)(void* handle);
 static void (*ffv_process_fn)(void *handle, const int16_t *in_pcm,
     int16_t *out_pcm, const int16_t *ec_ref_pcm);
@@ -379,12 +380,12 @@
     return ret;
 }
 
-int audio_extn_ffv_set_usecase(struct stream_in *in)
+int audio_extn_ffv_set_usecase(struct stream_in *in, int ffv_key, char* ffv_lic)
 {
     int ret = -EINVAL;
 
     if (audio_extn_ffv_check_usecase(in)) {
-        if (!audio_extn_ffv_stream_init(in)) {
+        if (!audio_extn_ffv_stream_init(in, ffv_key, ffv_lic)) {
             ALOGD("%s: Created FFV session succesfully", __func__);
             ret = 0;
         } else {
@@ -428,7 +429,7 @@
     return 0;
 }
 
-int32_t audio_extn_ffv_stream_init(struct stream_in *in)
+int32_t audio_extn_ffv_stream_init(struct stream_in *in, int key, char* lic)
 {
     uint32_t ret = -EINVAL;
     int num_tx_in_ch, num_out_ch, num_ec_ref_ch;
@@ -487,7 +488,7 @@
     ALOGD("%s: config file path %s", __func__, config_file_path);
     status_type = ffv_init_fn(&ffvmod.handle, num_tx_in_ch, num_out_ch, num_ec_ref_ch,
                       frame_len, sample_rate, config_file_path, sm_buffer, 0,
-                      &total_mem_size);
+                      &total_mem_size, key, lic);
     if (status_type) {
         ALOGE("%s: ERROR. ffv_init returned %d", __func__, status_type);
         ret = -EINVAL;
diff --git a/hal/audio_extn/spkr_protection.c b/hal/audio_extn/spkr_protection.c
index abbdc8e..e7c3661 100644
--- a/hal/audio_extn/spkr_protection.c
+++ b/hal/audio_extn/spkr_protection.c
@@ -1007,6 +1007,7 @@
     int ret;
     bool spv3_enable = false;
     unsigned int afe_api_version = 0;
+    struct mixer_ctl *ctl;
 
     memset(&protCfg, 0, sizeof(protCfg));
     /* If the value of this persist.vendor.audio.spkr.cal.duration is 0
@@ -1114,9 +1115,18 @@
            }
            if (goahead) {
                if (spk_1_tzn >= 0) {
+                   const char *mixer_ctl_name = "SpkrLeft WSA T0 Init";
                    snprintf(wsa_path, MAX_PATH, TZ_WSA, spk_1_tzn);
                    ALOGV("%s: wsa_path: %s\n", __func__, wsa_path);
                    thermal_fd = -1;
+
+                   ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+                   if (ctl) {
+                       ALOGD("%s: Got ctl for mixer cmd %s",
+                                             __func__, mixer_ctl_name);
+                       mixer_ctl_set_value(ctl, 0, 1);
+                   }
+
                    thermal_fd = open(wsa_path, O_RDONLY);
                    if (thermal_fd > 0) {
                        if ((ret = read(thermal_fd, buf, sizeof(buf))) >= 0)
@@ -1127,6 +1137,9 @@
                    } else {
                        ALOGE("%s: fd for %s is NULL\n", __func__, wsa_path);
                    }
+                   if (ctl) {
+                       mixer_ctl_set_value(ctl, 0, 0);
+                   }
                    if (t0_spk_1 < TZ_TEMP_MIN_THRESHOLD ||
                        t0_spk_1 > TZ_TEMP_MAX_THRESHOLD) {
                        pthread_mutex_unlock(&adev->lock);
@@ -1138,8 +1151,15 @@
                    t0_spk_1 = (t0_spk_1 * (1 << 6));
                }
                if (spk_2_tzn >= 0) {
+                   const char *mixer_ctl_name = "SpkrRight WSA T0 Init";
                    snprintf(wsa_path, MAX_PATH, TZ_WSA, spk_2_tzn);
                    ALOGV("%s: wsa_path: %s\n", __func__, wsa_path);
+                   ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+                   if (ctl) {
+                       ALOGD("%s: Got ctl for mixer cmd %s",
+                                             __func__, mixer_ctl_name);
+                       mixer_ctl_set_value(ctl, 0, 1);
+                   }
                    thermal_fd = open(wsa_path, O_RDONLY);
                    if (thermal_fd > 0) {
                        if ((ret = read(thermal_fd, buf, sizeof(buf))) >= 0)
@@ -1150,6 +1170,9 @@
                    } else {
                        ALOGE("%s: fd for %s is NULL\n", __func__, wsa_path);
                    }
+                   if (ctl) {
+                       mixer_ctl_set_value(ctl, 0, 0);
+                   }
                    if (t0_spk_2 < TZ_TEMP_MIN_THRESHOLD ||
                        t0_spk_2 > TZ_TEMP_MAX_THRESHOLD) {
                        pthread_mutex_unlock(&adev->lock);
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
old mode 100644
new mode 100755
index d4c6351..8a585df
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -2111,6 +2111,17 @@
 
 int audio_extn_utils_get_snd_card_num()
 {
+    int snd_card_num = 0;
+    struct mixer *mixer = NULL;
+
+    snd_card_num = audio_extn_utils_open_snd_mixer(&mixer);
+    if (mixer)
+        mixer_close(mixer);
+    return snd_card_num;
+}
+
+int audio_extn_utils_open_snd_mixer(struct mixer **mixer_handle)
+{
 
     void *hw_info = NULL;
     struct mixer *mixer = NULL;
@@ -2118,6 +2129,11 @@
     int snd_card_num = 0, min_snd_card_num = 0;
     char* snd_card_name = NULL;
 
+    if (!mixer_handle) {
+        ALOGE("invalid mixer handle");
+        return -1;
+    }
+    *mixer_handle = NULL;
     /*
     * Try with all the sound cards ( 0 to 8 ) and if none of them were detected
     * sleep for 1 sec and try detections with sound card 0 again.
@@ -2171,9 +2187,6 @@
     if (snd_card_name)
         free(snd_card_name);
 
-    if (mixer)
-        mixer_close(mixer);
-
     if (hw_info)
         hw_info_deinit(hw_info);
 
@@ -2182,9 +2195,18 @@
         return -1;
     }
 
+    if (mixer)
+        *mixer_handle = mixer;
+
     return snd_card_num;
 }
 
+void audio_extn_utils_close_snd_mixer(struct mixer *mixer)
+{
+    if (mixer)
+        mixer_close(mixer);
+}
+
 #ifdef SNDRV_COMPRESS_ENABLE_ADJUST_SESSION_CLOCK
 int audio_extn_utils_compress_enable_drift_correction(
         struct stream_out *out,
@@ -2486,3 +2508,15 @@
 
     return -EINVAL;
 }
+
+int audio_extn_utils_get_license_params
+(
+const struct audio_device *adev,
+struct audio_license_params *license_params
+)
+{
+    if(!license_params)
+        return -EINVAL;
+    return platform_get_license_by_product(adev->platform, (const char*)license_params->product, &license_params->key, license_params->license);
+}
+
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 3eef21f..ad3a260 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -2020,6 +2020,10 @@
     struct stream_out stream_out;
     audio_usecase_t hfp_ucid;
     int status = 0;
+    audio_devices_t audio_device;
+    audio_channel_mask_t channel_mask;
+    int sample_rate;
+    int acdb_id;
 
     ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
 
@@ -2260,14 +2264,11 @@
             usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
         }
 
-        /* Notify device change info to effect clients registered */
-        pthread_mutex_unlock(&adev->lock);
-        audio_extn_gef_notify_device_config(
-                usecase->stream.out->devices,
-                usecase->stream.out->channel_mask,
-                usecase->stream.out->app_type_cfg.sample_rate,
-                platform_get_snd_device_acdb_id(usecase->out_snd_device));
-        pthread_mutex_lock(&adev->lock);
+        /* Cache stream information to be notified to gef clients */
+        audio_device = usecase->stream.out->devices;
+        channel_mask = usecase->stream.out->channel_mask;
+        sample_rate = usecase->stream.out->app_type_cfg.sample_rate;
+        acdb_id = platform_get_snd_device_acdb_id(usecase->out_snd_device);
     }
     enable_audio_route(adev, usecase);
 
@@ -2324,6 +2325,16 @@
          }
     }
 
+    /* Notify device change info to effect clients registered
+     * NOTE: device lock has to be unlock temporarily here.
+     * To the worst case, we notify stale info to clients.
+     */
+    if (usecase->type == PCM_PLAYBACK) {
+        pthread_mutex_unlock(&adev->lock);
+        audio_extn_gef_notify_device_config(audio_device, channel_mask, sample_rate, acdb_id);
+        pthread_mutex_lock(&adev->lock);
+    }
+
     ALOGD("%s: done",__func__);
 
     return status;
@@ -6669,9 +6680,9 @@
                                                   DEFAULT_VOIP_BUF_DURATION_MS,
                                                   DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
     } else {
-        if (!valid_ch) config->channel_mask = 1;
-        if (!valid_rate) config->sample_rate = 48000;
-        return -EINVAL;
+        ALOGW("%s No valid input in voip, use defaults"
+               "sample rate %u, channel mask 0x%X",
+               __func__, config->sample_rate, in->channel_mask);
     }
     in->config.rate = config->sample_rate;
     in->sample_rate = config->sample_rate;
diff --git a/hal/audio_hw_extn_api.c b/hal/audio_hw_extn_api.c
old mode 100644
new mode 100755
index 4e49a83..550a06b
--- a/hal/audio_hw_extn_api.c
+++ b/hal/audio_hw_extn_api.c
@@ -140,6 +140,10 @@
               ret = audio_extn_get_sourcetrack_data(dev,
                      (struct source_tracking_param*)payload);
               break;
+        case AUDIO_EXTN_PARAM_LICENSE_PARAMS:
+              ret = audio_extn_utils_get_license_params(dev,
+                     (struct audio_license_params *)(payload));
+              break;
        default:
              ALOGE("%s::INVALID PARAM ID:%d\n",__func__,param_id);
              ret = -EINVAL;
diff --git a/hal/msm8916/hw_info.c b/hal/msm8916/hw_info.c
index b88572f..40e39a2 100644
--- a/hal/msm8916/hw_info.c
+++ b/hal/msm8916/hw_info.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -118,6 +118,9 @@
         strlcpy(hw_info->name, "msm8952", sizeof(hw_info->name));
     } else if (!strcmp(snd_card_name, "msm8952-snd-card-mtp")) {
         strlcpy(hw_info->name, "msm8952", sizeof(hw_info->name));
+    } else if (!strcmp(snd_card_name, "sdm439-sku1-snd-card")) {
+        hw_info->is_stereo_spkr = false;
+        strlcpy(hw_info->name, "msm8952", sizeof(hw_info->name));
     } else if (!strcmp(snd_card_name, "sdm439-snd-card-mtp")) {
         strlcpy(hw_info->name, "msm8952", sizeof(hw_info->name));
     } else if (!strcmp(snd_card_name, "msm8952-tomtom-snd-card")) {
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
old mode 100644
new mode 100755
index e74353e..d364a0f
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -1239,6 +1239,13 @@
         msm_device_to_be_id = msm_device_to_be_id_internal_codec;
         msm_be_id_array_len  =
             sizeof(msm_device_to_be_id_internal_codec) / sizeof(msm_device_to_be_id_internal_codec[0]);
+    } else if (!strncmp(snd_card_name, "sdm439-sku1-snd-card",
+                 sizeof("sdm439-sku1-snd-card"))) {
+        strlcpy(mixer_xml_path, MIXER_XML_PATH_SDM439_PM8953,
+                sizeof(MIXER_XML_PATH_SDM439_PM8953));
+        msm_device_to_be_id = msm_device_to_be_id_internal_codec;
+        msm_be_id_array_len  =
+            sizeof(msm_device_to_be_id_internal_codec) / sizeof(msm_device_to_be_id_internal_codec[0]);
     }  else if (!strncmp(snd_card_name, "msm8952-tomtom-snd-card",
                  sizeof("msm8952-tomtom-snd-card"))) {
         strlcpy(mixer_xml_path, MIXER_XML_PATH_WCD9330,
@@ -2060,6 +2067,10 @@
                     sizeof("msm8953-snd-card-mtp")) ||
                 (!strncmp(snd_card_name, "msm8953-sku4-snd-card",
                     sizeof("msm8953-sku4-snd-card"))) ||
+                (!strncmp(snd_card_name, "sdm439-sku1-snd-card",
+                    sizeof("sdm439-sku1-snd-card"))) ||
+                (!strncmp(snd_card_name, "sdm439-snd-card-mtp",
+                    sizeof("sdm439-snd-card-mtp"))) ||
                 (!strncmp(snd_card_name, "msm8952-skum-snd-card",
                     sizeof("msm8952-skum-snd-card"))))) {
                 *is_wsa_combo_supported = true;
@@ -2204,7 +2215,7 @@
     const char *id_string = NULL;
     int cfg_value = -1;
 
-    snd_card_num = audio_extn_utils_get_snd_card_num();
+    snd_card_num = audio_extn_utils_open_snd_mixer(&adev->mixer);
     if(snd_card_num < 0) {
         ALOGE("%s: Unable to find correct sound card", __func__);
         return NULL;
@@ -2213,13 +2224,6 @@
     adev->snd_card = snd_card_num;
     ALOGD("%s: Opened sound card:%d", __func__, snd_card_num);
 
-    adev->mixer = mixer_open(snd_card_num);
-    if (!adev->mixer) {
-        ALOGE("%s: Unable to open the mixer card: %d", __func__,
-               snd_card_num);
-        return NULL;
-    }
-
     snd_card_name = mixer_get_name(adev->mixer);
     ALOGD("%s: snd_card_name: %s", __func__, snd_card_name);
 
@@ -2249,7 +2253,7 @@
         ALOGE("%s: Failed to init audio route controls, aborting.",
                __func__);
         free(my_data);
-        mixer_close(adev->mixer);
+        audio_extn_utils_close_snd_mixer(adev->mixer);
         return NULL;
     }
     update_codec_type(snd_card_name);
@@ -2471,7 +2475,7 @@
             goto acdb_init_fail;
         }
 
-        int result = acdb_init(adev->snd_card);
+        int result = acdb_init_v2(adev->mixer);
         if (!result) {
             my_data->is_acdb_initialized = true;
             ALOGD("ACDB initialized");
@@ -2722,6 +2726,17 @@
     return my_data;
 }
 
+void platform_release_acdb_metainfo_key(void *platform)
+{
+    struct platform_data *my_data = (struct platform_data *)platform;
+    struct listnode *node, *tempnode;
+
+    list_for_each_safe(node, tempnode, &my_data->acdb_meta_key_list) {
+        list_remove(node);
+        free(node_to_item(node, struct meta_key_list, list));
+    }
+}
+
 void platform_deinit(void *platform)
 {
     struct platform_data *my_data = (struct platform_data *)platform;
@@ -2766,10 +2781,32 @@
     }
 
     if (my_data->adev->mixer) {
-        mixer_close(my_data->adev->mixer);
+        audio_extn_utils_close_snd_mixer(my_data->adev->mixer);
         my_data->adev->mixer = NULL;
     }
 
+    int32_t idx;
+
+    for (idx = 0; idx < MAX_CODEC_BACKENDS; idx++) {
+         if (my_data->current_backend_cfg[idx].bitwidth_mixer_ctl) {
+             free(my_data->current_backend_cfg[idx].bitwidth_mixer_ctl);
+             my_data->current_backend_cfg[idx].bitwidth_mixer_ctl = NULL;
+         }
+
+         if (my_data->current_backend_cfg[idx].samplerate_mixer_ctl) {
+             free(my_data->current_backend_cfg[idx].samplerate_mixer_ctl);
+             my_data->current_backend_cfg[idx].samplerate_mixer_ctl = NULL;
+         }
+
+         if (my_data->current_backend_cfg[idx].channels_mixer_ctl) {
+             free(my_data->current_backend_cfg[idx].channels_mixer_ctl);
+             my_data->current_backend_cfg[idx].channels_mixer_ctl = NULL;
+         }
+    }
+
+    /* free acdb_meta_key_list */
+    platform_release_acdb_metainfo_key(platform);
+
     free(platform);
     /* deinit usb */
     audio_extn_usb_deinit();
@@ -3091,6 +3128,59 @@
     return 0;
 }
 
+int platform_get_license_by_product
+(
+    void *platform,
+    const char* product_name,
+    int* product_id,
+    char* product_license
+)
+{
+    int ret = 0;
+    int id = 0;
+    acdb_audio_cal_cfg_t cal;
+    uint32_t param_len = LICENSE_STR_MAX_LEN;
+    struct platform_data *my_data = (struct platform_data *)platform;
+
+    if ((NULL == platform) || (NULL == product_name) || (NULL == product_id)) {
+        ALOGE("[%s] Invalid input parameters",__func__);
+        ret = -EINVAL;
+        goto on_error;
+    }
+
+    id =  platform_get_meta_info_key_from_list(platform, (char*)product_name);
+    if(0 == id)
+    {
+        ALOGE("%s:Id not found for %s", __func__, product_name);
+        ret = -EINVAL;
+        goto on_error;
+    }
+
+    ALOGD("%s: Found Id[%d] for %s", __func__, id, product_name);
+    if(NULL == my_data->acdb_get_audio_cal){
+        ALOGE("[%s] acdb_get_audio_cal is NULL.",__func__);
+        ret = -ENOSYS;
+        goto on_error;
+    }
+
+    memset(&cal, 0, sizeof(cal));
+    cal.persist = 1;
+    cal.cal_type = AUDIO_CORE_METAINFO_CAL_TYPE;
+    cal.acdb_dev_id = (uint32_t) id;
+    ret = my_data->acdb_get_audio_cal((void*)&cal, (void*)product_license, &param_len);
+
+    if (0 == ret) {
+        ALOGD("%s: Got Length[%d] License[%s]", __func__, param_len, product_license );
+        *product_id = id;
+        return 0;
+    }
+    ALOGD("%s: License not found for %s", __func__, product_name);
+
+on_error:
+    *product_id = 0;
+    return ret;
+}
+
 int platform_get_meta_info_key_from_list(void *platform, char *mod_name)
 {
     struct listnode *node;
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
old mode 100644
new mode 100755
index 43aeaed..f4132c2
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -1374,3 +1374,8 @@
 {
     return -ENOSYS;
 }
+
+int platform_get_license_by_product(void *platform, const char* product_name, int *product_id, char* product_license)
+{
+    return -ENOSYS;
+}
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
old mode 100644
new mode 100755
index 9a5d647..8ce00f3
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -1947,24 +1947,17 @@
     const char *id_string = NULL;
     int cfg_value = -1;
 
-    adev->snd_card = audio_extn_utils_get_snd_card_num();
+    adev->snd_card = audio_extn_utils_open_snd_mixer(&adev->mixer);
     if (adev->snd_card < 0) {
         ALOGE("%s: Unable to find correct sound card", __func__);
         return NULL;
     }
     ALOGD("%s: Opened sound card:%d", __func__, adev->snd_card);
 
-    adev->mixer = mixer_open(adev->snd_card);
-    if (!adev->mixer) {
-        ALOGE("%s: Unable to open the mixer card: %d", __func__,
-               adev->snd_card);
-        return NULL;
-    }
-
     snd_card_name = strdup(mixer_get_name(adev->mixer));
     if (!snd_card_name) {
         ALOGE("failed to allocate memory for snd_card_name\n");
-        mixer_close(adev->mixer);
+        audio_extn_utils_close_snd_mixer(adev->mixer);
         return NULL;
     }
 
@@ -1973,7 +1966,7 @@
         ALOGE("failed to allocate platform data");
         if (snd_card_name)
             free(snd_card_name);
-        mixer_close(adev->mixer);
+        audio_extn_utils_close_snd_mixer(adev->mixer);
         return NULL;
     }
 
@@ -1983,7 +1976,7 @@
     my_data->hw_info = hw_info_init(snd_card_name);
     if (!my_data->hw_info) {
         ALOGE("failed to init hw_info");
-        mixer_close(adev->mixer);
+        audio_extn_utils_close_snd_mixer(adev->mixer);
         if (my_data)
             free(my_data);
 
@@ -2055,7 +2048,7 @@
             free(snd_card_name);
         if (snd_card_name_t)
             free(snd_card_name_t);
-        mixer_close(adev->mixer);
+        audio_extn_utils_close_snd_mixer(adev->mixer);
         return NULL;
     }
 
@@ -2267,7 +2260,7 @@
             goto acdb_init_fail;
         }
 
-        int result = acdb_init(adev->snd_card);
+        int result = acdb_init_v2(adev->mixer);
         if (!result) {
             my_data->is_acdb_initialized = true;
             ALOGD("ACDB initialized");
@@ -2531,6 +2524,17 @@
     return my_data;
 }
 
+void platform_release_acdb_metainfo_key(void *platform)
+{
+    struct platform_data *my_data = (struct platform_data *)platform;
+    struct listnode *node, *tempnode;
+
+    list_for_each_safe(node, tempnode, &my_data->acdb_meta_key_list) {
+        list_remove(node);
+        free(node_to_item(node, struct meta_key_list, list));
+    }
+}
+
 void platform_deinit(void *platform)
 {
     struct platform_data *my_data = (struct platform_data *)platform;
@@ -2574,10 +2578,32 @@
     }
 
     if (my_data->adev->mixer) {
-        mixer_close(my_data->adev->mixer);
+        audio_extn_utils_close_snd_mixer(my_data->adev->mixer);
         my_data->adev->mixer = NULL;
     }
 
+    int32_t idx;
+
+    for (idx = 0; idx < MAX_CODEC_BACKENDS; idx++) {
+         if (my_data->current_backend_cfg[idx].bitwidth_mixer_ctl) {
+             free(my_data->current_backend_cfg[idx].bitwidth_mixer_ctl);
+             my_data->current_backend_cfg[idx].bitwidth_mixer_ctl = NULL;
+         }
+
+         if (my_data->current_backend_cfg[idx].samplerate_mixer_ctl) {
+             free(my_data->current_backend_cfg[idx].samplerate_mixer_ctl);
+             my_data->current_backend_cfg[idx].samplerate_mixer_ctl = NULL;
+         }
+
+         if (my_data->current_backend_cfg[idx].channels_mixer_ctl) {
+             free(my_data->current_backend_cfg[idx].channels_mixer_ctl);
+             my_data->current_backend_cfg[idx].channels_mixer_ctl = NULL;
+         }
+    }
+
+    /* free acdb_meta_key_list */
+    platform_release_acdb_metainfo_key(platform);
+
     free(platform);
     /* deinit usb */
     audio_extn_usb_deinit();
@@ -7927,3 +7953,8 @@
 
     return id_string;
 }
+
+int platform_get_license_by_product(void *platform, const char* product_name, int *product_id, char* product_license)
+{
+    return -ENOSYS;
+}
diff --git a/hal/platform_api.h b/hal/platform_api.h
old mode 100644
new mode 100755
index 0fec452..2bacf6d
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -31,6 +31,9 @@
 #define SAMPLE_RATE_11025 11025
 #define sample_rate_multiple(sr, base) ((sr % base)== 0?true:false)
 #define MAX_VOLUME_CAL_STEPS 15
+#define LICENSE_STR_MAX_LEN  (64)
+#define PRODUCT_FFV      "ffv"
+#define PRODUCT_ALLPLAY  "allplay"
 
 typedef enum {
     PLATFORM,
@@ -108,6 +111,7 @@
                                       effect_type_t effect_type);
 int platform_get_snd_device_bit_width(snd_device_t snd_device);
 int platform_set_acdb_metainfo_key(void *platform, char *name, int key);
+void platform_release_acdb_metainfo_key(void *platform);
 int platform_get_meta_info_key_from_list(void *platform, char *mod_name);
 int platform_set_native_support(int na_mode);
 int platform_get_native_support();
@@ -261,4 +265,5 @@
                                int *fd, uint32_t *size);
 int platform_get_ec_ref_loopback_snd_device(int channel_count);
 const char * platform_get_snd_card_name_for_acdb_loader(const char *snd_card_name);
+int platform_get_license_by_product(void *platform, const char* product_name, int *product_id, char* product_license);
 #endif // AUDIO_PLATFORM_API_H
diff --git a/qahw/inc/qahw_defs.h b/qahw/inc/qahw_defs.h
old mode 100644
new mode 100755
index c13a1a4..e67c91e
--- a/qahw/inc/qahw_defs.h
+++ b/qahw/inc/qahw_defs.h
@@ -354,6 +354,14 @@
     float mixer_coeffs[AUDIO_CHANNEL_COUNT_MAX][AUDIO_CHANNEL_COUNT_MAX];
 } qahw_mix_matrix_params_t;
 
+#define QAHW_LICENCE_STR_MAX_LENGTH (64)
+#define QAHW_PRODUCT_STR_MAX_LENGTH (64)
+typedef struct qahw_license_params {
+    char product[QAHW_PRODUCT_STR_MAX_LENGTH + 1];
+    int key;
+    char license[QAHW_LICENCE_STR_MAX_LENGTH + 1];
+} qahw_license_params_t;
+
 typedef union {
     struct qahw_source_tracking_param st_params;
     struct qahw_sound_focus_param sf_params;
@@ -367,6 +375,7 @@
     struct qahw_out_channel_map_param channel_map_params;
     struct qahw_device_cfg_param device_cfg_params;
     struct qahw_mix_matrix_params mix_matrix_params;
+    struct qahw_license_params license_params;
 } qahw_param_payload;
 
 typedef enum {
@@ -385,6 +394,7 @@
     QAHW_PARAM_DEVICE_CONFIG,      /* PARAM to set device config */
     QAHW_PARAM_OUT_MIX_MATRIX_PARAMS,
     QAHW_PARAM_CH_MIX_MATRIX_PARAMS,
+    QAHW_PARAM_LICENSE_PARAMS,
 } qahw_param_id;
 
 __END_DECLS
diff --git a/qahw_api/inc/qahw_defs.h b/qahw_api/inc/qahw_defs.h
old mode 100644
new mode 100755
index a33caf6..c708ce0
--- a/qahw_api/inc/qahw_defs.h
+++ b/qahw_api/inc/qahw_defs.h
@@ -354,6 +354,15 @@
     float mixer_coeffs[AUDIO_CHANNEL_COUNT_MAX][AUDIO_CHANNEL_COUNT_MAX];
 } qahw_mix_matrix_params_t;
 
+
+#define QAHW_LICENCE_STR_MAX_LENGTH (64)
+#define QAHW_PRODUCT_STR_MAX_LENGTH (64)
+typedef struct qahw_license_params {
+    char product[QAHW_PRODUCT_STR_MAX_LENGTH + 1];
+    int key;
+    char license[QAHW_LICENCE_STR_MAX_LENGTH + 1];
+} qahw_license_params_t;
+
 typedef union {
     struct qahw_source_tracking_param st_params;
     struct qahw_sound_focus_param sf_params;
@@ -367,6 +376,7 @@
     struct qahw_out_channel_map_param channel_map_params;
     struct qahw_device_cfg_param device_cfg_params;
     struct qahw_mix_matrix_params mix_matrix_params;
+    struct qahw_license_params license_params;
 } qahw_param_payload;
 
 typedef enum {
@@ -385,6 +395,7 @@
     QAHW_PARAM_DEVICE_CONFIG,      /* PARAM to set device config */
     QAHW_PARAM_OUT_MIX_MATRIX_PARAMS,
     QAHW_PARAM_CH_MIX_MATRIX_PARAMS,
+    QAHW_PARAM_LICENSE_PARAMS,
 } qahw_param_id;
 
 __END_DECLS
diff --git a/qahw_api/src/qahw_api.cpp b/qahw_api/src/qahw_api.cpp
index 8967e79..cbd9041 100644
--- a/qahw_api/src/qahw_api.cpp
+++ b/qahw_api/src/qahw_api.cpp
@@ -1113,6 +1113,7 @@
 
 int qahw_unload_module(qahw_module_handle_t *hw_module)
 {
+    int rc = -EINVAL;
     ALOGV("%d:%s",__LINE__, __func__);
     if (g_binder_enabled) {
         if (!g_qas_died && ((g_qas_load_count > 0) && (--g_qas_load_count == 0))) {
@@ -1120,7 +1121,13 @@
             if (qas_status(qas) == -1)
                 return -ENODEV;
             pthread_mutex_destroy(&list_lock);
-            return qas->qahw_unload_module(hw_module);
+            rc = qas->qahw_unload_module(hw_module);
+            if (g_death_notifier != NULL) {
+                IInterface::asBinder(qas)->unlinkToDeath(g_death_notifier);
+                g_death_notifier.clear();
+            }
+            g_qas = NULL;
+            return rc;
         } else {
             return -ENODEV;
         }
diff --git a/qahw_api/test/qap_wrapper_extn.c b/qahw_api/test/qap_wrapper_extn.c
index a084277..9cd9fd6 100644
--- a/qahw_api/test/qap_wrapper_extn.c
+++ b/qahw_api/test/qap_wrapper_extn.c
@@ -814,6 +814,22 @@
 
             break;
         }
+        case QAP_MODULE_CALLBACK_EVENT_INPUT_CFG_CHANGE:
+        {
+            if (size < sizeof(qap_input_config_t)) {
+                ALOGE("%s %d event id %d, wrong payload size %d\n",
+                      __func__, __LINE__, event_id, size);
+                break;
+            }
+            qap_input_config_t *p_stream_format = (qap_input_config_t*)data;
+
+            ALOGV(" %s %d Input format updated; sample_rate %lu, channels %lu, bitwidth %lu",
+                  __func__, __LINE__,
+                  p_stream_format->sample_rate,
+                  p_stream_format->channels,
+                  p_stream_format->bit_width);
+            break;
+        }
         default:
         break;
     }