Merge "policy_hal: add support for fm device loopback"
diff --git a/hal/audio_extn/fm.c b/hal/audio_extn/fm.c
index ed3776c..a13a789 100644
--- a/hal/audio_extn/fm.c
+++ b/hal/audio_extn/fm.c
@@ -35,6 +35,7 @@
 #define AUDIO_PARAMETER_KEY_HANDLE_FM "handle_fm"
 #define AUDIO_PARAMETER_KEY_FM_VOLUME "fm_volume"
 #define AUDIO_PARAMETER_KEY_REC_PLAY_CONC "rec_play_conc_on"
+#define FM_LOOPBACK_DRAIN_TIME_MS 2
 
 static struct pcm_config pcm_config_fm = {
     .channels = 2,
@@ -65,7 +66,7 @@
   .scard_state = SND_CARD_STATE_ONLINE,
 };
 
-static int32_t fm_set_volume(struct audio_device *adev, float value)
+static int32_t fm_set_volume(struct audio_device *adev, float value, bool persist)
 {
     int32_t vol, ret = 0;
     struct mixer_ctl *ctl;
@@ -82,7 +83,8 @@
         value = 1.0;
     }
     vol  = lrint((value * 0x2000) + 0.5);
-    fmmod.fm_volume = value;
+    if (persist)
+        fmmod.fm_volume = value;
 
     if (!fmmod.is_fm_running) {
         ALOGV("%s: FM not active, ignoring set_fm_volume call", __func__);
@@ -202,7 +204,7 @@
     pcm_start(fmmod.fm_pcm_tx);
 
     fmmod.is_fm_running = true;
-    fm_set_volume(adev, fmmod.fm_volume);
+    fm_set_volume(adev, fmmod.fm_volume, false);
 
     ALOGD("%s: exit: status(%d)", __func__, ret);
     return 0;
@@ -263,8 +265,11 @@
                 adev->primary_output->devices = val & ~AUDIO_DEVICE_OUT_FM;
                 fm_start(adev);
             } else if (!(val & AUDIO_DEVICE_OUT_FM)
-                     && fmmod.is_fm_running == true)
+                     && fmmod.is_fm_running == true) {
+                fm_set_volume(adev, 0, false);
+                usleep(FM_LOOPBACK_DRAIN_TIME_MS*1000);
                 fm_stop(adev);
+            }
        }
     }
 
@@ -278,7 +283,7 @@
             goto exit;
         }
         ALOGD("%s: set_fm_volume usecase", __func__);
-        fm_set_volume(adev, vol);
+        fm_set_volume(adev, vol, true);
     }
 
 #ifdef RECORD_PLAY_CONCURRENCY
@@ -293,7 +298,7 @@
             ALOGD("Record play concurrency OFF Forcing FM device reroute");
 
         select_devices(adev, USECASE_AUDIO_PLAYBACK_FM);
-        fm_set_volume(adev,fmmod.fm_volume);
+        fm_set_volume(adev, fmmod.fm_volume, false);
     }
 #endif
 exit:
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 308a6a8..6af23f1 100755
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -915,6 +915,8 @@
 
     if (out_snd_device == usecase->out_snd_device &&
         in_snd_device == usecase->in_snd_device) {
+        audio_extn_dolby_set_endpoint(adev);
+        audio_extn_dolby_ds2_set_endpoint(adev);
         return 0;
     }
 
@@ -2958,6 +2960,12 @@
         } else {
             ALOGV("%s:: inserting OFFLOAD_USECASE", __func__);
             out->usecase = get_offload_usecase(adev);
+
+            out->stream.set_callback = out_set_callback;
+            out->stream.pause = out_pause;
+            out->stream.resume = out_resume;
+            out->stream.drain = out_drain;
+            out->stream.flush = out_flush;
         }
         if (config->offload_info.channel_mask)
             out->channel_mask = config->offload_info.channel_mask;
@@ -2968,11 +2976,6 @@
         format = out->format = config->offload_info.format;
         out->sample_rate = config->offload_info.sample_rate;
 
-        out->stream.set_callback = out_set_callback;
-        out->stream.pause = out_pause;
-        out->stream.resume = out_resume;
-        out->stream.drain = out_drain;
-        out->stream.flush = out_flush;
         out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
 
         if (audio_extn_is_dolby_format(config->offload_info.format))