Merge "Configs: msm8937: Add a2dp on compress-offload2"
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 2abb760..071c594 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -948,7 +948,8 @@
 
     new_backend_idx = platform_get_backend_index(snd_device);
     spkr_hph_single_be_native_concurrency = platform_get_spkr_hph_single_be_native_concurrency_flag();
-    if ( spkr_hph_single_be_native_concurrency && (new_backend_idx == DEFAULT_CODEC_BACKEND)) {
+    if ((spkr_hph_single_be_native_concurrency && (new_backend_idx == DEFAULT_CODEC_BACKEND)) ||
+            uc_info->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
         list_for_each(node, &adev->usecase_list) {
             usecase = node_to_item(node, struct audio_usecase, list);
             if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
@@ -961,8 +962,8 @@
                     usecase->stream.out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
                     platform_check_and_set_codec_backend_cfg(adev, usecase,
                                                             usecase->out_snd_device);
-                    enable_audio_route(adev, usecase);
                     enable_snd_device(adev, usecase->out_snd_device);
+                    enable_audio_route(adev, usecase);
                 }
             }
         }
@@ -4070,7 +4071,7 @@
 
         if (out->realtime)
             platform_set_stream_channel_map(adev->platform, out->channel_mask,
-                   out->pcm_device_id, &out->channel_map_param.channel_map[0]);
+                   out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
 
         out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
                                        flags, pcm_open_retry_count,
@@ -4096,7 +4097,7 @@
 
         if (!out->realtime)
             platform_set_stream_channel_map(adev->platform, out->channel_mask,
-                   out->pcm_device_id, &out->channel_map_param.channel_map[0]);
+                   out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
 
         // apply volume for voip playback after path is set up
         if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
@@ -4117,7 +4118,7 @@
          */
         if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
             platform_set_stream_channel_map(adev->platform, out->channel_mask,
-                       out->pcm_device_id, &out->channel_map_param.channel_map[0]);
+                       out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
         audio_enable_asm_bit_width_enforce_mode(adev->mixer,
                                                 adev->dsp_bit_width_enforce_mode,
                                                 true);
@@ -4849,15 +4850,6 @@
     return;
 }
 
-static int get_alive_usb_card(struct str_parms* parms) {
-    int card;
-    if ((str_parms_get_int(parms, "card", &card) >= 0) &&
-        !audio_extn_usb_alive(card)) {
-        return card;
-    }
-    return -ENODEV;
-}
-
 int route_output_stream(struct stream_out *out,
                         struct listnode *devices)
 {
@@ -4905,7 +4897,7 @@
         reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
     }
     /*
-     * When USB headset is disconnected the music platback paused
+     * When USB headset is disconnected the music playback paused
      * and the policy manager send routing=0. But if the USB is connected
      * back before the standby time, AFE is not closed and opened
      * when USB is connected back. So routing to speker will guarantee
@@ -4942,14 +4934,13 @@
 
     // Workaround: If routing to an non existing usb device, fail gracefully
     // The routing request will otherwise block during 10 second
-    int card;
     if (is_usb_out_device_type(&new_devices)) {
         struct str_parms *parms =
             str_parms_create_str(get_usb_device_address(&new_devices));
         if (!parms)
             goto error;
-        if ((card = get_alive_usb_card(parms)) >= 0) {
-            ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
+        if (!audio_extn_usb_connected(NULL)) {
+            ALOGW("%s: ignoring rerouting to non existing USB card", __func__);
             pthread_mutex_unlock(&adev->lock);
             pthread_mutex_unlock(&out->lock);
             str_parms_destroy(parms);
@@ -5928,6 +5919,12 @@
         }
     }
 
+    if (is_usb_out_device_type(&out->device_list) &&
+            !audio_extn_usb_connected(NULL)) {
+        ret = -EIO;
+        goto exit;
+    }
+
     if (out->standby) {
         out->standby = false;
         const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
@@ -6977,12 +6974,11 @@
           is_audio_in_device_type(devices)) {
         // Workaround: If routing to an non existing usb device, fail gracefully
         // The routing request will otherwise block during 10 second
-        int card;
         struct str_parms *usb_addr =
                 str_parms_create_str(get_usb_device_address(devices));
         if (is_usb_in_device_type(devices) && usb_addr &&
-             (card = get_alive_usb_card(usb_addr)) >= 0) {
-            ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
+             !audio_extn_usb_connected(NULL)) {
+            ALOGW("%s: ignoring rerouting to non existing USB", __func__);
             ret = -ENOSYS;
         } else {
             /* If recording is in progress, change the tx device to new device */
@@ -7654,20 +7650,25 @@
     if (position == NULL) {
         return -EINVAL;
     }
+    lock_input_stream(in);
     if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
+        pthread_mutex_unlock(&in->lock);
         return -ENOSYS;
     }
     if (in->pcm == NULL) {
+        pthread_mutex_unlock(&in->lock);
         return -ENOSYS;
     }
     struct timespec ts = { 0, 0 };
     int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
     if (ret < 0) {
         ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
+        pthread_mutex_unlock(&in->lock);
         return ret;
     }
     position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
             + in->mmap_time_offset_nanos;
+    pthread_mutex_unlock(&in->lock);
     return 0;
 }
 
@@ -10443,8 +10444,6 @@
 {
     struct audio_usecase *uc_info;
     struct audio_usecase *usecase;
-    float left_p;
-    float right_p;
     struct listnode devices;
     struct listnode *node;
 
@@ -10493,33 +10492,31 @@
                     break;
                 }
             }
-            left_p = out->volume_l;
-            right_p = out->volume_r;
-            out->a2dp_muted = true;
-            if (is_offload_usecase(out->usecase)) {
-                if (out->offload_state == OFFLOAD_STATE_PLAYING)
-                    compress_pause(out->compr);
-                out_set_compr_volume(&out->stream, (float)0, (float)0);
-            } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
-                out_set_voip_volume(&out->stream, (float)0, (float)0);
-            } else {
-                out_set_pcm_volume(&out->stream, (float)0, (float)0);
-                /* wait for stale pcm drained before switching to speaker */
-                uint32_t latency =
-                    (out->config.period_count * out->config.period_size * 1000) /
-                    (out->config.rate);
-                usleep(latency * 1000);
+            if (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP) {
+                out->a2dp_muted = true;
+                if (is_offload_usecase(out->usecase)) {
+                    if (out->offload_state == OFFLOAD_STATE_PLAYING)
+                        compress_pause(out->compr);
+                    out_set_compr_volume(&out->stream, (float)0, (float)0);
+                } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
+                    out_set_voip_volume(&out->stream, (float)0, (float)0);
+                } else {
+                    out_set_pcm_volume(&out->stream, (float)0, (float)0);
+                    /* wait for stale pcm drained before switching to speaker */
+                    uint32_t latency =
+                        (out->config.period_count * out->config.period_size * 1000) /
+                        (out->config.rate);
+                    usleep(latency * 1000);
+                }
             }
             select_devices(adev, out->usecase);
-            ALOGD("%s: switched to device:%s and mute stream",
-                   __func__, platform_get_snd_device_name(uc_info->out_snd_device));
+            ALOGD("%s: switched to device:%s and stream muted:%d", __func__,
+                platform_get_snd_device_name(uc_info->out_snd_device), out->a2dp_muted);
             if (is_offload_usecase(out->usecase)) {
                 if (out->offload_state == OFFLOAD_STATE_PLAYING)
                     compress_resume(out->compr);
             }
             assign_devices(&out->device_list, &devices);
-            out->volume_l = left_p;
-            out->volume_r = right_p;
         }
         pthread_mutex_unlock(&out->latch_lock);
     }
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index d9957ef..2f8a6f2 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2021, The Linux Foundation. All rights reserved.
  * Not a Contribution.
  *
  * Copyright (C) 2013 The Android Open Source Project
@@ -7263,14 +7263,14 @@
 }
 
 int platform_set_stream_channel_map(void *platform, audio_channel_mask_t channel_mask,
-                                               int snd_id, uint8_t *input_channel_map)
+                                    int snd_id, int be_idx, uint8_t *input_channel_map)
 {
     int ret = 0, i = 0;
     int channels = audio_channel_count_from_out_mask(channel_mask);
 
     char channel_map[AUDIO_CHANNEL_COUNT_MAX];
     memset(channel_map, 0, sizeof(channel_map));
-    if (*input_channel_map) {
+    if ((input_channel_map != NULL) && *input_channel_map) {
         for (i = 0; i < channels; i++) {
              ALOGV("%s:: Channel Map channel_map[%d] - %d", __func__, i, *input_channel_map);
              channel_map[i] = *input_channel_map;
@@ -7357,7 +7357,7 @@
                 return -1;
         }
     }
-    ret = platform_set_channel_map(platform, channels, channel_map, snd_id, -1);
+    ret = platform_set_channel_map(platform, channels, channel_map, snd_id, be_idx);
     return ret;
 }
 
@@ -7704,7 +7704,9 @@
                 platform_set_channel_map(platform, adev_device_cfg_ptr->dev_cfg_params.channels,
                                    (char *)adev_device_cfg_ptr->dev_cfg_params.channel_map, -1, -1);
             } else {
-                platform_set_channel_map(platform, channels, info->channel_map, -1, -1);
+                platform_set_stream_channel_map(platform,
+                        audio_channel_out_mask_from_count(channels),
+                        -1, -1, NULL);
             }
 
             if (adev_device_cfg_ptr->use_client_dev_cfg) {
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index 90105cd..94c0a62 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2019, 2021 The Linux Foundation. All rights reserved.
  * Not a contribution.
  *
  * Copyright (C) 2013 The Android Open Source Project
@@ -1202,14 +1202,16 @@
 }
 
 int platform_set_channel_map(void *platform __unused, int ch_count __unused,
-                             char *ch_map __unused, int snd_id __unused)
+                             char *ch_map __unused, int snd_id __unused,
+                             int be_idx __unused)
 {
     return -ENOSYS;
 }
 
 int platform_set_stream_channel_map(void *platform __unused,
                                     audio_channel_mask_t channel_mask __unused,
-                                    int snd_id __unused
+                                    int snd_id __unused,
+                                    int be_idx __unused,
                                     uint8_t *input_channel_map __unused)
 {
     return -ENOSYS;
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 572ae99..4ebe8cd 100755
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -10802,14 +10802,14 @@
 }
 
 int platform_set_stream_channel_map(void *platform, audio_channel_mask_t channel_mask,
-                                               int snd_id, uint8_t *input_channel_map)
+                                    int snd_id, int be_idx, uint8_t *input_channel_map)
 {
     int ret = 0, i = 0;
     int channels = audio_channel_count_from_out_mask(channel_mask);
 
     char channel_map[AUDIO_CHANNEL_COUNT_MAX];
     memset(channel_map, 0, sizeof(channel_map));
-    if (*input_channel_map) {
+    if ((input_channel_map != NULL) && *input_channel_map) {
         for (i = 0; i < channels; i++) {
              ALOGV("%s:: Channel Map channel_map[%d] - %d", __func__, i, *input_channel_map);
              channel_map[i] = *input_channel_map;
@@ -10935,7 +10935,7 @@
                 return -1;
         }
     }
-    ret = platform_set_channel_map(platform, channels, channel_map, snd_id, -1);
+    ret = platform_set_channel_map(platform, channels, channel_map, snd_id, be_idx);
     return ret;
 }
 
@@ -11486,7 +11486,9 @@
                 platform_set_channel_map(platform, adev_device_cfg_ptr->dev_cfg_params.channels,
                                      (char *)adev_device_cfg_ptr->dev_cfg_params.channel_map, -1, be_idx);
             } else {
-                platform_set_channel_map(platform, channels, info->channel_map, -1, be_idx);
+                platform_set_stream_channel_map(platform,
+                        audio_channel_out_mask_from_count(channels),
+                        -1, be_idx, NULL);
             }
 
             if (adev_device_cfg_ptr->use_client_dev_cfg) {
diff --git a/hal/platform_api.h b/hal/platform_api.h
index d4eb4f5..ca72708 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2021, The Linux Foundation. All rights reserved.
  * Not a contribution.
  *
  * Copyright (C) 2013 The Android Open Source Project
@@ -283,7 +283,7 @@
 int platform_set_channel_map(void *platform, int ch_count, char *ch_map,
                              int snd_id, int be_idx);
 int platform_set_stream_channel_map(void *platform, audio_channel_mask_t channel_mask,
-                                   int snd_id, uint8_t *input_channel_map);
+                                   int snd_id, int be_idx, uint8_t *input_channel_map);
 int platform_set_stream_pan_scale_params(void *platform,
                                          int snd_id,
                                          struct mix_matrix_params mm_params);