hal: retry a2dp path start up when failed

Check if a2dp path start failed and do retry from
out_write to recover the path is possible, which
can avoid blocking write if path set up failed.

Bug: 148926518
Change-Id: I479386e1760b214c1be31d34449a068e41ff5ced
diff --git a/hal/audio_extn/a2dp.c b/hal/audio_extn/a2dp.c
index 8422846..4bd9125 100644
--- a/hal/audio_extn/a2dp.c
+++ b/hal/audio_extn/a2dp.c
@@ -2524,6 +2524,7 @@
         if (ret != 0 ) {
            ALOGE("BT controller start failed");
            a2dp.a2dp_source_started = false;
+           ret = -ETIMEDOUT;
         } else {
            if (configure_a2dp_encoder_format() == true) {
                 a2dp.a2dp_source_started = true;
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 87d1ff6..2ec01de 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -1419,10 +1419,13 @@
                    __func__, device_name);
         }
 
-        if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
-            (audio_extn_a2dp_start_playback() < 0)) {
-            ALOGE(" fail to configure A2dp Source control path ");
-            goto err;
+        if (SND_DEVICE_OUT_BT_A2DP == snd_device) {
+            if (audio_extn_a2dp_start_playback() < 0) {
+                ALOGE(" fail to configure A2dp Source control path ");
+                goto err;
+            } else {
+                adev->a2dp_started = true;
+            }
         }
 
         if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
@@ -1529,9 +1532,10 @@
             audio_route_reset_and_update_path(adev->audio_route, device_name);
         }
 
-        if (snd_device == SND_DEVICE_OUT_BT_A2DP)
+        if (snd_device == SND_DEVICE_OUT_BT_A2DP) {
             audio_extn_a2dp_stop_playback();
-        else if (snd_device == SND_DEVICE_IN_BT_A2DP)
+            adev->a2dp_started = false;
+        } else if (snd_device == SND_DEVICE_IN_BT_A2DP)
             audio_extn_a2dp_stop_capture();
         else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
                 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
@@ -3909,7 +3913,26 @@
             assign_devices(&out->device_list, &dev);
         }
     } else {
-         select_devices(adev, out->usecase);
+        select_devices(adev, out->usecase);
+        if (is_a2dp_out_device_type(&out->device_list) &&
+             !adev->a2dp_started) {
+            if (is_speaker_active || is_speaker_safe_active) {
+                struct listnode dev;
+                list_init(&dev);
+                assign_devices(&dev, &out->device_list);
+                if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
+                    reassign_device_list(&out->device_list,
+                                    AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
+                else
+                    reassign_device_list(&out->device_list,
+                                    AUDIO_DEVICE_OUT_SPEAKER, "");
+                select_devices(adev, out->usecase);
+                assign_devices(&out->device_list, &dev);
+            } else {
+                ret = -EINVAL;
+                goto error_open;
+            }
+        }
     }
 
     if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
@@ -10471,6 +10494,7 @@
     adev->enable_hfp = false;
     adev->use_old_pspd_mix_ctrl = false;
     adev->adm_routing_changed = false;
+    adev->a2dp_started = false;
 
     audio_extn_perf_lock_init();
 
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 055a96b..6931d8d 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -739,6 +739,7 @@
     struct listnode audio_patch_record_list;
     Hashmap *patch_map;
     Hashmap *io_streams_map;
+    bool a2dp_started;
     bool ha_proxy_enable;
 };