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