1 /****************************************************************************** 2 * 3 * Copyright 2016 The Android Open Source Project 4 * Copyright 2009-2012 Broadcom Corporation 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at: 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 * 18 ******************************************************************************/ 19 20 #define LOG_TAG "bt_btif_a2dp" 21 22 #include <stdbool.h> 23 24 #include "audio_a2dp_hw/include/audio_a2dp_hw.h" 25 #include "bt_common.h" 26 #include "bta_av_api.h" 27 #include "btif_a2dp.h" 28 #include "btif_a2dp_audio_interface.h" 29 #include "btif_a2dp_control.h" 30 #include "btif_a2dp_sink.h" 31 #include "btif_a2dp_source.h" 32 #include "btif_av.h" 33 #include "btif_av_co.h" 34 #include "btif_hf.h" 35 #include "btif_util.h" 36 #include "osi/include/log.h" 37 38 void btif_a2dp_on_idle(void) { 39 LOG_INFO(LOG_TAG, "%s: ## ON A2DP IDLE ## peer_sep = %d", __func__, 40 btif_av_get_peer_sep()); 41 if (btif_av_get_peer_sep() == AVDT_TSEP_SNK) { 42 btif_a2dp_source_on_idle(); 43 } else if (btif_av_get_peer_sep() == AVDT_TSEP_SRC) { 44 btif_a2dp_sink_on_idle(); 45 } 46 } 47 48 bool btif_a2dp_on_started(const RawAddress& peer_addr, 49 tBTA_AV_START* p_av_start, bool pending_start) { 50 bool ack = false; 51 52 LOG_INFO(LOG_TAG, 53 "%s: ## ON A2DP STARTED ## peer %s pending_start:%s p_av_start:%p", 54 __func__, peer_addr.ToString().c_str(), 55 logbool(pending_start).c_str(), p_av_start); 56 57 if (p_av_start == NULL) { 58 /* ack back a local start request */ 59 60 if (!btif_av_is_a2dp_offload_enabled()) { 61 btif_a2dp_command_ack(A2DP_CTRL_ACK_SUCCESS); 62 return true; 63 } else if (bluetooth::headset::IsCallIdle()) { 64 btif_av_stream_start_offload(); 65 } else { 66 LOG_ERROR(LOG_TAG, "%s: peer %s call in progress, do not start offload", 67 __func__, peer_addr.ToString().c_str()); 68 btif_a2dp_audio_on_started(A2DP_CTRL_ACK_INCALL_FAILURE); 69 } 70 return true; 71 } 72 73 LOG_INFO(LOG_TAG, 74 "%s: peer %s pending_start:%s status:%d suspending:%s initiator:%s", 75 __func__, peer_addr.ToString().c_str(), 76 logbool(pending_start).c_str(), p_av_start->status, 77 logbool(p_av_start->suspending).c_str(), 78 logbool(p_av_start->initiator).c_str()); 79 80 if (p_av_start->status == BTA_AV_SUCCESS) { 81 if (!p_av_start->suspending) { 82 if (p_av_start->initiator) { 83 if (pending_start) { 84 if (btif_av_is_a2dp_offload_enabled()) { 85 btif_av_stream_start_offload(); 86 } else { 87 btif_a2dp_command_ack(A2DP_CTRL_ACK_SUCCESS); 88 } 89 ack = true; 90 } 91 } 92 93 /* media task is autostarted upon a2dp audiopath connection */ 94 } 95 } else if (pending_start) { 96 LOG_ERROR(LOG_TAG, "%s: peer %s A2DP start request failed: status = %d", 97 __func__, peer_addr.ToString().c_str(), p_av_start->status); 98 btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE); 99 ack = true; 100 } 101 return ack; 102 } 103 104 void btif_a2dp_on_stopped(tBTA_AV_SUSPEND* p_av_suspend) { 105 LOG_INFO(LOG_TAG, "%s: ## ON A2DP STOPPED ## p_av_suspend=%p", __func__, 106 p_av_suspend); 107 108 if (btif_av_get_peer_sep() == AVDT_TSEP_SRC) { 109 btif_a2dp_sink_on_stopped(p_av_suspend); 110 return; 111 } 112 if (!btif_av_is_a2dp_offload_enabled()) { 113 btif_a2dp_source_on_stopped(p_av_suspend); 114 } else if (p_av_suspend != NULL) { 115 btif_a2dp_audio_on_stopped(p_av_suspend->status); 116 } 117 } 118 119 void btif_a2dp_on_suspended(tBTA_AV_SUSPEND* p_av_suspend) { 120 LOG_INFO(LOG_TAG, "%s: ## ON A2DP SUSPENDED ## p_av_suspend=%p", __func__, 121 p_av_suspend); 122 if (!btif_av_is_a2dp_offload_enabled()) { 123 if (btif_av_get_peer_sep() == AVDT_TSEP_SRC) { 124 btif_a2dp_sink_on_suspended(p_av_suspend); 125 } else { 126 btif_a2dp_source_on_suspended(p_av_suspend); 127 } 128 } else { 129 btif_a2dp_audio_on_suspended(p_av_suspend->status); 130 } 131 } 132 133 void btif_a2dp_on_offload_started(const RawAddress& peer_addr, 134 tBTA_AV_STATUS status) { 135 tA2DP_CTRL_ACK ack; 136 LOG_INFO(LOG_TAG, "%s: peer %s status %d", __func__, 137 peer_addr.ToString().c_str(), status); 138 139 switch (status) { 140 case BTA_AV_SUCCESS: 141 ack = A2DP_CTRL_ACK_SUCCESS; 142 break; 143 case BTA_AV_FAIL_RESOURCES: 144 LOG_ERROR(LOG_TAG, "%s: peer %s FAILED UNSUPPORTED", __func__, 145 peer_addr.ToString().c_str()); 146 ack = A2DP_CTRL_ACK_UNSUPPORTED; 147 break; 148 default: 149 LOG_ERROR(LOG_TAG, "%s: peer %s FAILED: status = %d", __func__, 150 peer_addr.ToString().c_str(), status); 151 ack = A2DP_CTRL_ACK_FAILURE; 152 break; 153 } 154 if (btif_av_is_a2dp_offload_enabled()) { 155 btif_a2dp_audio_on_started(status); 156 if (ack != BTA_AV_SUCCESS && btif_av_stream_started_ready()) { 157 // Offload request will return with failure from btif_av sm if 158 // suspend is triggered for remote start. Disconnect only if SoC 159 // returned failure for offload VSC 160 LOG_ERROR(LOG_TAG, "%s: peer %s offload start failed", __func__, 161 peer_addr.ToString().c_str()); 162 btif_av_src_disconnect_sink(peer_addr); 163 } 164 } else { 165 btif_a2dp_command_ack(ack); 166 } 167 } 168 169 void btif_debug_a2dp_dump(int fd) { 170 btif_a2dp_source_debug_dump(fd); 171 btif_a2dp_sink_debug_dump(fd); 172 btif_a2dp_codec_debug_dump(fd); 173 } 174