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 "bluetooth-a2dp"
21 
22 #include "btif_a2dp.h"
23 
24 #include <bluetooth/log.h>
25 #include <com_android_bluetooth_flags.h>
26 
27 #include <cstddef>
28 #include <cstdint>
29 
30 #include "audio_hal_interface/a2dp_encoding.h"
31 #include "avdt_api.h"
32 #include "bta_av_api.h"
33 #include "btif_a2dp_sink.h"
34 #include "btif_a2dp_source.h"
35 #include "btif_av.h"
36 #include "btif_av_co.h"
37 #include "btif_hf.h"
38 #include "types/raw_address.h"
39 
40 using namespace bluetooth;
41 using bluetooth::audio::a2dp::Status;
42 
btif_a2dp_on_idle(const RawAddress &,const A2dpType local_a2dp_type)43 void btif_a2dp_on_idle(const RawAddress& /*peer_addr*/, const A2dpType local_a2dp_type) {
44   log::verbose("Peer stream endpoint type:{}",
45                peer_stream_endpoint_text(btif_av_get_peer_sep(local_a2dp_type)));
46   if (btif_av_get_peer_sep(local_a2dp_type) == AVDT_TSEP_SNK) {
47     btif_a2dp_source_on_idle();
48   } else if (btif_av_get_peer_sep(local_a2dp_type) == AVDT_TSEP_SRC) {
49     btif_a2dp_sink_on_idle();
50   }
51 }
52 
btif_a2dp_on_started(const RawAddress & peer_addr,tBTA_AV_START * p_av_start,const A2dpType local_a2dp_type)53 bool btif_a2dp_on_started(const RawAddress& peer_addr, tBTA_AV_START* p_av_start,
54                           const A2dpType local_a2dp_type) {
55   log::info("## ON A2DP STARTED ## peer {} p_av_start:{}", peer_addr, std::format_ptr(p_av_start));
56 
57   if (p_av_start == NULL) {
58     auto status = Status::SUCCESS;
59     if (!bluetooth::headset::IsCallIdle()) {
60       log::error("peer {} call in progress, do not start A2DP stream", peer_addr);
61       status = Status::FAILURE;
62     }
63     /* just ack back a local start request, do not start the media encoder since
64      * this is not for BTA_AV_START_EVT. */
65     bluetooth::audio::a2dp::ack_stream_started(status);
66     return true;
67   }
68 
69   log::info("peer {} status:{} suspending:{} initiator:{}", peer_addr, p_av_start->status,
70             p_av_start->suspending, p_av_start->initiator);
71 
72   if (p_av_start->status == BTA_AV_SUCCESS) {
73     if (p_av_start->suspending) {
74       log::warn("peer {} A2DP is suspending and ignores the started event", peer_addr);
75       return false;
76     }
77     if (btif_av_is_a2dp_offload_running()) {
78       btif_av_stream_start_offload();
79     } else {
80       if (btif_av_get_peer_sep(local_a2dp_type) == AVDT_TSEP_SNK) {
81         /* Start the media encoder to do the SW audio stream */
82         btif_a2dp_source_start_audio_req();
83       }
84       if (p_av_start->initiator) {
85         bluetooth::audio::a2dp::ack_stream_started(Status::SUCCESS);
86         return true;
87       }
88     }
89   } else if (p_av_start->initiator) {
90     log::error("peer {} A2DP start request failed: status = {}", peer_addr, p_av_start->status);
91     bluetooth::audio::a2dp::ack_stream_started(Status::FAILURE);
92     return true;
93   }
94   return false;
95 }
96 
btif_a2dp_on_stopped(tBTA_AV_SUSPEND * p_av_suspend,const A2dpType local_a2dp_type)97 void btif_a2dp_on_stopped(tBTA_AV_SUSPEND* p_av_suspend, const A2dpType local_a2dp_type) {
98   log::info("## ON A2DP STOPPED ## p_av_suspend={}", std::format_ptr(p_av_suspend));
99 
100   const uint8_t peer_type_sep = btif_av_get_peer_sep(local_a2dp_type);
101   if (peer_type_sep == AVDT_TSEP_SRC) {
102     btif_a2dp_sink_on_stopped(p_av_suspend);
103     return;
104   }
105   if (peer_type_sep == AVDT_TSEP_SNK) {
106     if (bluetooth::audio::a2dp::is_hal_enabled() || !btif_av_is_a2dp_offload_running()) {
107       btif_a2dp_source_on_stopped(p_av_suspend);
108       return;
109     }
110   }
111 }
112 
btif_a2dp_on_suspended(tBTA_AV_SUSPEND * p_av_suspend,const A2dpType local_a2dp_type)113 void btif_a2dp_on_suspended(tBTA_AV_SUSPEND* p_av_suspend, const A2dpType local_a2dp_type) {
114   log::info("## ON A2DP SUSPENDED ## p_av_suspend={}", std::format_ptr(p_av_suspend));
115   const uint8_t peer_type_sep = btif_av_get_peer_sep(local_a2dp_type);
116   if (peer_type_sep == AVDT_TSEP_SRC) {
117     btif_a2dp_sink_on_suspended(p_av_suspend);
118     return;
119   }
120   if (peer_type_sep == AVDT_TSEP_SNK) {
121     if (bluetooth::audio::a2dp::is_hal_enabled() || !btif_av_is_a2dp_offload_running()) {
122       btif_a2dp_source_on_suspended(p_av_suspend);
123       return;
124     }
125   }
126 }
127 
btif_a2dp_on_offload_started(const RawAddress & peer_addr,tBTA_AV_STATUS status)128 void btif_a2dp_on_offload_started(const RawAddress& peer_addr, tBTA_AV_STATUS status) {
129   Status ack;
130   log::info("peer {} status {}", peer_addr, status);
131 
132   switch (status) {
133     case BTA_AV_SUCCESS:
134       // Call required to update the session state for metrics.
135       btif_a2dp_source_start_audio_req();
136       ack = Status::SUCCESS;
137       break;
138     case BTA_AV_FAIL_RESOURCES:
139       log::error("peer {} FAILED UNSUPPORTED", peer_addr);
140       ack = Status::UNSUPPORTED_CODEC_CONFIGURATION;
141       break;
142     default:
143       log::error("peer {} FAILED: status = {}", peer_addr, status);
144       ack = Status::FAILURE;
145       break;
146   }
147 
148   if (btif_av_is_a2dp_offload_running()) {
149     if (ack != Status::SUCCESS && btif_av_stream_started_ready(A2dpType::kSource)) {
150       log::error("peer {} offload start failed", peer_addr);
151       if (com::android::bluetooth::flags::stop_on_offload_fail()) {
152         btif_av_stream_stop(peer_addr);
153       } else {
154         // Offload request will return with failure from btif_av sm if
155         // suspend is triggered for remote start. Disconnect only if SoC
156         // returned failure for offload VSC
157         btif_av_source_disconnect(peer_addr);
158       }
159     }
160   }
161 
162   bluetooth::audio::a2dp::ack_stream_started(ack);
163 }
164 
btif_debug_a2dp_dump(int fd)165 void btif_debug_a2dp_dump(int fd) {
166   btif_a2dp_source_debug_dump(fd);
167   btif_a2dp_sink_debug_dump(fd);
168   btif_a2dp_codec_debug_dump(fd);
169 }
170