hal: use stream specific app type for MBDRC

- when multi app type is supported use stream specific app type
- enforce custome volume MBDRC level to start from > 0 level
- add speaker safe as valid mbdrc supported device

Bug: 64774822
Test: phone call, duo call and video playback over speaker and headset

Change-Id: I4cb484bbd1ff8a46432c82738d67164799928ff2
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index c27042e..2847666 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -443,6 +443,12 @@
     return 0;
 }
 
+// always call with adev lock held
+void send_gain_dep_calibration_l() {
+    if (last_known_cal_step >= 0)
+        platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
+}
+
 __attribute__ ((visibility ("default")))
 bool audio_hw_send_gain_dep_calibration(int level) {
     bool ret_val = false;
@@ -452,15 +458,9 @@
 
     if (adev != NULL && adev->platform != NULL) {
         pthread_mutex_lock(&adev->lock);
-        ret_val = platform_send_gain_dep_cal(adev->platform, level);
+        last_known_cal_step = level;
+        send_gain_dep_calibration_l();
         pthread_mutex_unlock(&adev->lock);
-
-        // if cal set fails, cache level info
-        // if cal set succeds, reset known last cal set
-        if (!ret_val)
-            last_known_cal_step = level;
-        else if (last_known_cal_step != -1)
-            last_known_cal_step = -1;
     } else {
         ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
     }
@@ -2613,17 +2613,19 @@
         out->standby = false;
         pthread_mutex_lock(&adev->lock);
         ret = start_output_stream(out);
-        pthread_mutex_unlock(&adev->lock);
+
         /* ToDo: If use case is compress offload should return 0 */
         if (ret != 0) {
             out->standby = true;
+            pthread_mutex_unlock(&adev->lock);
             goto exit;
         }
 
-        if (last_known_cal_step != -1) {
-            ALOGD("%s: retry previous failed cal level set", __func__);
-            audio_hw_send_gain_dep_calibration(last_known_cal_step);
-        }
+        // after standby always force set last known cal step
+        // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
+        ALOGD("%s: retry previous failed cal level set", __func__);
+        send_gain_dep_calibration_l();
+        pthread_mutex_unlock(&adev->lock);
     }
 
     if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index b324b66..3b1d4d5 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -748,7 +748,6 @@
     if (!voice_is_in_call(adev)) {
         ALOGV("%s: Not Voice call usecase, apply new cal for level %d",
                __func__, level);
-        app_type = DEFAULT_APP_TYPE_RX_PATH;
 
         // find the current active sound device
         list_for_each(node, &adev->usecase_list) {
@@ -760,18 +759,23 @@
             if (valid_uc_type) {
                 audio_devices_t dev = usecase->stream.out->devices;
                 valid_dev = (dev == AUDIO_DEVICE_OUT_SPEAKER ||
+                             dev == AUDIO_DEVICE_OUT_SPEAKER_SAFE ||
                              dev == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
                              dev == AUDIO_DEVICE_OUT_WIRED_HEADPHONE);
             }
             if (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];
-                 }
+                ALOGV("%s: out device is %d", __func__,  usecase->out_snd_device);
+                if (platform_supports_app_type_cfg())
+                    app_type = usecase->stream.out->app_type_cfg.app_type;
+                else
+                    app_type = DEFAULT_APP_TYPE_RX_PATH;
 
-                 if (!my_data->acdb_send_gain_dep_cal(acdb_dev_id, app_type,
+                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];
+
+                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;
diff --git a/hal/platform_info.c b/hal/platform_info.c
index 283936e..41b59c8 100644
--- a/hal/platform_info.c
+++ b/hal/platform_info.c
@@ -216,6 +216,9 @@
     tbl_entry.amp = exp(tbl_entry.db * 0.115129f);
     tbl_entry.level = atoi(attr[3]);
 
+    //custome level should be > 0. Level 0 is fixed for default
+    CHECK(tbl_entry.level > 0);
+
     ALOGV("%s: amp [%f]  db [%f] level [%d]", __func__,
            tbl_entry.amp, tbl_entry.db, tbl_entry.level);
     platform_add_gain_level_mapping(&tbl_entry);
diff --git a/post_proc/volume_listener.c b/post_proc/volume_listener.c
index 63aeccc..0fb62cb 100644
--- a/post_proc/volume_listener.c
+++ b/post_proc/volume_listener.c
@@ -241,7 +241,8 @@
 
 static inline bool valid_dev_in_context(struct vol_listener_context_s *context)
 {
-    if (context->dev_id == AUDIO_DEVICE_OUT_SPEAKER)
+    if (context->dev_id == AUDIO_DEVICE_OUT_SPEAKER ||
+        context->dev_id == AUDIO_DEVICE_OUT_SPEAKER_SAFE)
         return true;
 
     if (context->stream_type == VC_CALL && headset_cal_enabled &&
@@ -320,20 +321,22 @@
                     // decision made .. send new level now
                     if (!send_gain_dep_cal(gain_dep_cal_level)) {
                         ALOGE("%s: Failed to set gain dep cal level", __func__);
-                    } else {
-                        // Success in setting the gain dep cal level, store new level and Volume
-                        if (dumping_enabled) {
-                            ALOGW("%s: (old/new) Volume (%f/%f) (old/new) level (%d/%d)",
-                                  __func__, current_vol, new_vol, current_gain_dep_cal_level,
-                                  gain_dep_cal_level);
-                        } else {
-                            ALOGV("%s: Change in Cal::(old/new) Volume (%f/%f) (old/new) level (%d/%d)",
-                                  __func__, current_vol, new_vol, current_gain_dep_cal_level,
-                                  gain_dep_cal_level);
-                        }
-                        current_gain_dep_cal_level = gain_dep_cal_level;
-                        current_vol = new_vol;
                     }
+
+                    if (dumping_enabled) {
+                        ALOGW("%s: (old/new) Volume (%f/%f) (old/new) level (%d/%d)",
+                              __func__, current_vol, new_vol, current_gain_dep_cal_level,
+                              gain_dep_cal_level);
+                    } else {
+                        ALOGV("%s: Change in Cal::(old/new) Volume (%f/%f) (old/new) level (%d/%d)",
+                              __func__, current_vol, new_vol, current_gain_dep_cal_level,
+                              gain_dep_cal_level);
+                    }
+
+                    // Gain level change info send to lower layer that has logic to re-apply on
+                    // failure, so change current gain level to reflect new level
+                    current_gain_dep_cal_level = gain_dep_cal_level;
+                    current_vol = new_vol;
                 } else {
                     if (dumping_enabled) {
                         ALOGW("%s: volume changed but gain dep cal level is still the same",
@@ -517,7 +520,8 @@
 
         // check if old or new device is speaker
         if (valid_dev_in_context(context) ||
-            new_device == AUDIO_DEVICE_OUT_SPEAKER) {
+            new_device == AUDIO_DEVICE_OUT_SPEAKER ||
+            new_device == AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
             recompute_gain_dep_cal_Level = true;
         }