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
btif_a2dp_on_idle(void)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
btif_a2dp_on_started(const RawAddress & peer_addr,tBTA_AV_START * p_av_start,bool pending_start)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
btif_a2dp_on_stopped(tBTA_AV_SUSPEND * p_av_suspend)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
btif_a2dp_on_suspended(tBTA_AV_SUSPEND * p_av_suspend)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
btif_a2dp_on_offload_started(const RawAddress & peer_addr,tBTA_AV_STATUS status)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
btif_debug_a2dp_dump(int fd)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