exynos: audiohal_comv1: Import a2dp offload from T BSP

* Supported by exynos9830.

Change-Id: I1caaa39d10ed27bf240d3665414c82ed11c281c9
Signed-off-by: Francescodario Cuzzocrea <bosconovic@gmail.com>
diff --git a/include/libaudio/audiohal_comv1/audio_devices.h b/include/libaudio/audiohal_comv1/audio_devices.h
index 01233b8..2bc104c 100644
--- a/include/libaudio/audiohal_comv1/audio_devices.h
+++ b/include/libaudio/audiohal_comv1/audio_devices.h
@@ -40,6 +40,12 @@
     DEVICE_SPEAKER_AND_USB_HEADSET,
     DEVICE_SPEAKER_AND_BT_SCO_HEADSET,
 
+    // BT A2DP Offload playback devices
+#ifdef SUPPORT_BTA2DP_OFFLOAD
+    DEVICE_BT_A2DP_HEADPHONE,
+    DEVICE_SPEAKER_AND_BT_A2DP_HEADPHONE,
+#endif
+
     // Special Playback Devices
     DEVICE_AUX_DIGITAL,
     DEVICE_FM_EXTERNAL,
@@ -85,6 +91,7 @@
     /* Playback Path modifier */
     MODIFIER_BT_SCO_RX_NB = 0,
     MODIFIER_BT_SCO_RX_WB,
+    MODIFIER_BT_A2DP_PLAYBACK,
 
     /* Capture Path modifier */
     MODIFIER_BT_SCO_TX_NB,
diff --git a/include/libaudio/audiohal_comv1/audio_proxy_interface.h b/include/libaudio/audiohal_comv1/audio_proxy_interface.h
index 1a42421..7fe2777 100644
--- a/include/libaudio/audiohal_comv1/audio_proxy_interface.h
+++ b/include/libaudio/audiohal_comv1/audio_proxy_interface.h
@@ -151,6 +151,10 @@
 void  proxy_clear_apcall_txse(void);
 void  proxy_set_call_path_param(uint32_t set, uint32_t param, int32_t value);
 
+#ifdef SUPPORT_BTA2DP_OFFLOAD
+bool proxy_is_bt_a2dp_ready(void);
+#endif
+
 // Audio Device Proxy Dump Function
 int   proxy_fw_dump(int fd);
 
diff --git a/include/libaudio/audiohal_comv1/audio_tables.h b/include/libaudio/audiohal_comv1/audio_tables.h
index 023f406..ca3d3b1 100644
--- a/include/libaudio/audiohal_comv1/audio_tables.h
+++ b/include/libaudio/audiohal_comv1/audio_tables.h
@@ -183,6 +183,12 @@
     [DEVICE_SPEAKER_AND_USB_HEADSET]        = "speaker-usb-headset",
     [DEVICE_SPEAKER_AND_BT_SCO_HEADSET]         = "speaker-bt-sco-headset",
 
+    // BT A2DP Offload playback devices
+#ifdef SUPPORT_BTA2DP_OFFLOAD
+    [DEVICE_BT_A2DP_HEADPHONE]              = "bt-a2dp-headphone",
+    [DEVICE_SPEAKER_AND_BT_A2DP_HEADPHONE]  = "speaker-bt-a2dp-headphone",
+#endif
+
     // Special Playback Devices
     [DEVICE_AUX_DIGITAL]                    = "aux-digital",
     [DEVICE_FM_EXTERNAL]                    = "external",
@@ -223,6 +229,7 @@
     /* RX modifier */
     [MODIFIER_BT_SCO_RX_NB]     = "set-bt-sco-rx-rate-nb",
     [MODIFIER_BT_SCO_RX_WB]     = "set-bt-sco-rx-rate-wb",
+    [MODIFIER_BT_A2DP_PLAYBACK] = "set-bt-a2dp-playback",
 
     /* TX modifier */
     [MODIFIER_BT_SCO_TX_NB]     = "set-bt-sco-tx-rate-nb",
diff --git a/libaudio/audiohal_comv1/common_audiohal/Android.mk b/libaudio/audiohal_comv1/common_audiohal/Android.mk
index d2246f3..0c41846 100644
--- a/libaudio/audiohal_comv1/common_audiohal/Android.mk
+++ b/libaudio/audiohal_comv1/common_audiohal/Android.mk
@@ -55,6 +55,10 @@
 LOCAL_CFLAGS += -Wno-unused-parameter -Wno-unused-variable -Wno-unused-function
 
 # Audio Feature based Configuration
+ifeq ($(BOARD_USE_BTA2DP_OFFLOAD),true)
+LOCAL_CFLAGS += -DSUPPORT_BTA2DP_OFFLOAD
+endif
+
 ifeq ($(BOARD_USE_SOUNDTRIGGER_HAL),true)
 LOCAL_CFLAGS += -DSUPPORT_STHAL_INTERFACE
 endif
diff --git a/libaudio/audiohal_comv1/common_audiohal/audio_hw.c b/libaudio/audiohal_comv1/common_audiohal/audio_hw.c
index ffdc418..22f5e56 100644
--- a/libaudio/audiohal_comv1/common_audiohal/audio_hw.c
+++ b/libaudio/audiohal_comv1/common_audiohal/audio_hw.c
@@ -723,6 +723,11 @@
                 case AUDIO_DEVICE_OUT_BLUETOOTH_SCO:
                 case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET:
                 case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT:     return DEVICE_BT_SCO_HEADSET;
+#ifdef SUPPORT_BTA2DP_OFFLOAD
+                case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
+                case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
+                case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:   return DEVICE_BT_A2DP_HEADPHONE;
+#endif
                 case AUDIO_DEVICE_OUT_AUX_DIGITAL:              return DEVICE_AUX_DIGITAL;
                 case AUDIO_DEVICE_OUT_USB_DEVICE:
                 case AUDIO_DEVICE_OUT_USB_HEADSET:              return DEVICE_USB_HEADSET;
@@ -739,6 +744,10 @@
 
             if ((devices & AUDIO_DEVICE_OUT_ALL_SCO) && (devices & AUDIO_DEVICE_OUT_SPEAKER))
                 return DEVICE_SPEAKER_AND_BT_SCO_HEADSET;
+#ifdef SUPPORT_BTA2DP_OFFLOAD
+            if ((devices & AUDIO_DEVICE_OUT_ALL_A2DP) && (devices & AUDIO_DEVICE_OUT_SPEAKER))
+                return DEVICE_SPEAKER_AND_BT_A2DP_HEADPHONE;
+#endif
             if ((devices & AUDIO_DEVICE_OUT_ALL_USB) && (devices & AUDIO_DEVICE_OUT_SPEAKER))
                 return DEVICE_SPEAKER_AND_USB_HEADSET;
         }
@@ -812,7 +821,12 @@
             else
                 type = MODIFIER_BT_SCO_RX_NB;
             break;
-
+#ifdef SUPPORT_BTA2DP_OFFLOAD
+        case DEVICE_BT_A2DP_HEADPHONE:
+        case DEVICE_SPEAKER_AND_BT_A2DP_HEADPHONE:
+            type = MODIFIER_BT_A2DP_PLAYBACK;
+            break;
+#endif
         case DEVICE_BT_SCO_HEADSET_MIC:
         case DEVICE_BT_NREC_HEADSET_MIC:
             if (adev->voice && adev->voice->bluetooth_samplerate == WB_SAMPLING_RATE)
@@ -1793,7 +1807,9 @@
         audio_devices_t requested_devices = atoi(value);
         audio_devices_t current_devices = out->common.requested_devices;
         bool need_routing = false;
-
+#ifdef SUPPORT_BTA2DP_OFFLOAD
+        bool bypass_a2dp = false;
+#endif
         /*
          * AudioFlinger informs Audio path is this device.
          * AudioHAL has to decide to do actual routing or not.
@@ -1804,6 +1820,20 @@
                   device_table[get_device_id(adev, current_devices)],
                   device_table[get_device_id(adev, requested_devices)]);
 
+#ifdef SUPPORT_BTA2DP_OFFLOAD
+            /* To avoid a2dp to sco overlapping / BT device improper state
+             * check with BT lib about a2dp streaming support before routing
+             */
+            if ((requested_devices & AUDIO_DEVICE_OUT_ALL_A2DP) && !proxy_is_bt_a2dp_ready()) {
+                if (requested_devices & AUDIO_DEVICE_OUT_SPEAKER) {
+                    //combo usecase just by pass a2dp
+                    ALOGW("%s-%s: A2DP profile is not ready, routing to speaker only",
+                        stream_table[out->common.stream_type], __func__);
+                    bypass_a2dp = true;
+                }
+            }
+#endif
+
             /* Assign requested device to Output Stream */
             out->common.requested_devices = requested_devices;
 
@@ -1865,6 +1895,13 @@
                     pthread_mutex_lock(&out->common.lock);
                     pthread_mutex_lock(&adev->lock);
                 } else {
+#ifdef SUPPORT_BTA2DP_OFFLOAD
+                    if (bypass_a2dp) {
+                        out->common.requested_devices = AUDIO_DEVICE_OUT_SPEAKER;
+                        adev_set_route((void *)out, AUSAGE_PLAYBACK, ROUTE, out->force);
+                        out->common.requested_devices = requested_devices;
+                    } else
+#endif
                     /* Do actual routing */
                     adev_set_route((void *)out, AUSAGE_PLAYBACK, ROUTE, out->force);
                 }
@@ -2170,6 +2207,14 @@
                    stream_table[out->common.stream_type], __func__);
         } else if (!adev->is_playback_path_routed) {
             ALOGI("%s-%s: try to route for playback", stream_table[out->common.stream_type], __func__);
+#ifdef SUPPORT_BTA2DP_OFFLOAD
+            if (a2dp_combo) {
+                audio_devices_t dev = out->common.requested_devices;
+                out->common.requested_devices = AUDIO_DEVICE_OUT_SPEAKER;
+                adev_set_route((void *)out, AUSAGE_PLAYBACK, ROUTE, NON_FORCE_ROUTE);
+                out->common.requested_devices = dev;
+            } else
+#endif
             adev_set_route((void *)out, AUSAGE_PLAYBACK, ROUTE, NON_FORCE_ROUTE);
         }
         pthread_mutex_unlock(&adev->lock);