1 /*
2 * Copyright 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #define LOG_TAG "BTAudioHfpAIDL"
17
18 #include "hfp_client_interface_aidl.h"
19
20 #include <bluetooth/log.h>
21
22 #include <map>
23
24 #include "aidl/android/hardware/bluetooth/audio/AudioConfiguration.h"
25 #include "aidl/transport_instance.h"
26 #include "bta/ag/bta_ag_int.h"
27 #include "btif/include/btif_hf.h"
28 #include "btm_api_types.h"
29 #include "hardware/bluetooth.h"
30 #include "hardware/bluetooth_headset_interface.h"
31 #include "provider_info.h"
32 #include "types/raw_address.h"
33
34 namespace bluetooth {
35 namespace audio {
36 namespace aidl {
37 namespace hfp {
38
39 std::map<bt_status_t, BluetoothAudioCtrlAck> status_to_ack_map = {
40 {BT_STATUS_SUCCESS, BluetoothAudioCtrlAck::SUCCESS_FINISHED},
41 {BT_STATUS_DONE, BluetoothAudioCtrlAck::SUCCESS_FINISHED},
42 {BT_STATUS_FAIL, BluetoothAudioCtrlAck::FAILURE},
43 {BT_STATUS_NOT_READY, BluetoothAudioCtrlAck::FAILURE_BUSY},
44 {BT_STATUS_BUSY, BluetoothAudioCtrlAck::FAILURE_BUSY},
45 {BT_STATUS_UNSUPPORTED, BluetoothAudioCtrlAck::FAILURE_UNSUPPORTED},
46 };
47
get_hfp_active_device_callback()48 tBTA_AG_SCB* get_hfp_active_device_callback() {
49 const RawAddress& addr = bta_ag_get_active_device();
50 if (addr.IsEmpty()) {
51 log::error("No active device found");
52 return nullptr;
53 }
54 auto idx = bta_ag_idx_by_bdaddr(&addr);
55 if (idx == 0) {
56 log::error("No index found for active device");
57 return nullptr;
58 }
59 auto cb = bta_ag_scb_by_idx(idx);
60 if (cb == nullptr) {
61 log::error("No callback for the active device");
62 return nullptr;
63 }
64 return cb;
65 }
66
GetHfpScoConfig(SessionType sessionType)67 std::unordered_map<int, ::hfp::sco_config> HfpTransport::GetHfpScoConfig(
68 SessionType sessionType) {
69 auto providerInfo =
70 ::bluetooth::audio::aidl::ProviderInfo::GetProviderInfo(sessionType);
71 return providerInfo->GetHfpScoConfig();
72 }
73
HfpTransport()74 HfpTransport::HfpTransport() { hfp_pending_cmd_ = HFP_CTRL_CMD_NONE; }
75
StartRequest()76 BluetoothAudioCtrlAck HfpTransport::StartRequest() {
77 if (hfp_pending_cmd_ == HFP_CTRL_CMD_START) {
78 log::info("HFP_CTRL_CMD_START in progress");
79 return BluetoothAudioCtrlAck::PENDING;
80 } else if (hfp_pending_cmd_ != HFP_CTRL_CMD_NONE) {
81 log::warn("busy in pending_cmd={}", hfp_pending_cmd_);
82 return BluetoothAudioCtrlAck::FAILURE_BUSY;
83 }
84
85 auto cb = get_hfp_active_device_callback();
86 if (cb == nullptr) return BluetoothAudioCtrlAck::FAILURE;
87
88 if (bta_ag_sco_is_open(cb)) {
89 // Already started, ACK back immediately.
90 return BluetoothAudioCtrlAck::SUCCESS_FINISHED;
91 }
92
93 /* Post start SCO event and wait for sco to open */
94 hfp_pending_cmd_ = HFP_CTRL_CMD_START;
95 // as ConnectAudio only queues the command into main thread, keep PENDING
96 // status
97 auto status =
98 bluetooth::headset::GetInterface()->ConnectAudio(&cb->peer_addr, 0);
99 log::info("ConnectAudio status = {} - {}", status, bt_status_text(status));
100 auto ctrl_ack = status_to_ack_map.find(status);
101 if (ctrl_ack == status_to_ack_map.end()) {
102 log::warn("Unmapped status={}", status);
103 return BluetoothAudioCtrlAck::FAILURE;
104 }
105 if (ctrl_ack->second != BluetoothAudioCtrlAck::SUCCESS_FINISHED) {
106 return ctrl_ack->second;
107 }
108 return BluetoothAudioCtrlAck::PENDING;
109 }
110
StopRequest()111 void HfpTransport::StopRequest() {
112 log::info("handling");
113 RawAddress addr = bta_ag_get_active_device();
114 if (addr.IsEmpty()) {
115 log::error("No active device found");
116 return;
117 }
118 hfp_pending_cmd_ = HFP_CTRL_CMD_STOP;
119 auto status = bluetooth::headset::GetInterface()->DisconnectAudio(&addr);
120 log::info("DisconnectAudio status = {} - {}", status, bt_status_text(status));
121 hfp_pending_cmd_ = HFP_CTRL_CMD_NONE;
122 return;
123 }
124
ResetPendingCmd()125 void HfpTransport::ResetPendingCmd() { hfp_pending_cmd_ = HFP_CTRL_CMD_NONE; }
126
GetPendingCmd() const127 uint8_t HfpTransport::GetPendingCmd() const { return hfp_pending_cmd_; }
128
129 // Unimplemented functions
LogBytesProcessed(size_t bytes_read)130 void HfpTransport::LogBytesProcessed(size_t bytes_read) {}
131
SuspendRequest()132 BluetoothAudioCtrlAck HfpTransport::SuspendRequest() {
133 return BluetoothAudioCtrlAck::FAILURE_UNSUPPORTED;
134 }
135
SetLatencyMode(LatencyMode latency_mode)136 void HfpTransport::SetLatencyMode(LatencyMode latency_mode) {}
137
SourceMetadataChanged(const source_metadata_v7_t & source_metadata)138 void HfpTransport::SourceMetadataChanged(
139 const source_metadata_v7_t& source_metadata) {}
140
SinkMetadataChanged(const sink_metadata_v7_t &)141 void HfpTransport::SinkMetadataChanged(const sink_metadata_v7_t&) {}
142
ResetPresentationPosition()143 void HfpTransport::ResetPresentationPosition() {}
144
GetPresentationPosition(uint64_t * remote_delay_report_ns,uint64_t * total_bytes_read,timespec * data_position)145 bool HfpTransport::GetPresentationPosition(uint64_t* remote_delay_report_ns,
146 uint64_t* total_bytes_read,
147 timespec* data_position) {
148 return false;
149 }
150
151 // Source / sink functions
HfpDecodingTransport(SessionType session_type)152 HfpDecodingTransport::HfpDecodingTransport(SessionType session_type)
153 : IBluetoothSinkTransportInstance(session_type, (AudioConfiguration){}) {
154 transport_ = new HfpTransport();
155 };
156
~HfpDecodingTransport()157 HfpDecodingTransport::~HfpDecodingTransport() { delete transport_; }
158
StartRequest(bool is_low_latency)159 BluetoothAudioCtrlAck HfpDecodingTransport::StartRequest(bool is_low_latency) {
160 return transport_->StartRequest();
161 }
162
SuspendRequest()163 BluetoothAudioCtrlAck HfpDecodingTransport::SuspendRequest() {
164 return transport_->SuspendRequest();
165 }
166
SetLatencyMode(LatencyMode latency_mode)167 void HfpDecodingTransport::SetLatencyMode(LatencyMode latency_mode) {
168 transport_->SetLatencyMode(latency_mode);
169 }
170
GetPresentationPosition(uint64_t * remote_delay_report_ns,uint64_t * total_bytes_written,timespec * data_position)171 bool HfpDecodingTransport::GetPresentationPosition(
172 uint64_t* remote_delay_report_ns, uint64_t* total_bytes_written,
173 timespec* data_position) {
174 return transport_->GetPresentationPosition(
175 remote_delay_report_ns, total_bytes_written, data_position);
176 }
177
SourceMetadataChanged(const source_metadata_v7_t & source_metadata)178 void HfpDecodingTransport::SourceMetadataChanged(
179 const source_metadata_v7_t& source_metadata) {
180 transport_->SourceMetadataChanged(source_metadata);
181 }
182
SinkMetadataChanged(const sink_metadata_v7_t & sink_metadata)183 void HfpDecodingTransport::SinkMetadataChanged(
184 const sink_metadata_v7_t& sink_metadata) {
185 transport_->SinkMetadataChanged(sink_metadata);
186 }
187
ResetPresentationPosition()188 void HfpDecodingTransport::ResetPresentationPosition() {
189 transport_->ResetPresentationPosition();
190 }
191
LogBytesRead(size_t bytes_written)192 void HfpDecodingTransport::LogBytesRead(size_t bytes_written) {
193 transport_->LogBytesProcessed(bytes_written);
194 }
195
GetPendingCmd() const196 uint8_t HfpDecodingTransport::GetPendingCmd() const {
197 return transport_->GetPendingCmd();
198 }
199
ResetPendingCmd()200 void HfpDecodingTransport::ResetPendingCmd() { transport_->ResetPendingCmd(); }
201
StopRequest()202 void HfpDecodingTransport::StopRequest() { transport_->StopRequest(); }
203
HfpEncodingTransport(SessionType session_type)204 HfpEncodingTransport::HfpEncodingTransport(SessionType session_type)
205 : IBluetoothSourceTransportInstance(session_type, (AudioConfiguration){}) {
206 transport_ = new HfpTransport();
207 };
208
~HfpEncodingTransport()209 HfpEncodingTransport::~HfpEncodingTransport() { delete transport_; }
210
StartRequest(bool is_low_latency)211 BluetoothAudioCtrlAck HfpEncodingTransport::StartRequest(bool is_low_latency) {
212 return transport_->StartRequest();
213 }
214
SuspendRequest()215 BluetoothAudioCtrlAck HfpEncodingTransport::SuspendRequest() {
216 return transport_->SuspendRequest();
217 }
218
StopRequest()219 void HfpEncodingTransport::StopRequest() { transport_->StopRequest(); }
220
SetLatencyMode(LatencyMode latency_mode)221 void HfpEncodingTransport::SetLatencyMode(LatencyMode latency_mode) {
222 transport_->SetLatencyMode(latency_mode);
223 }
224
GetPresentationPosition(uint64_t * remote_delay_report_ns,uint64_t * total_bytes_written,timespec * data_position)225 bool HfpEncodingTransport::GetPresentationPosition(
226 uint64_t* remote_delay_report_ns, uint64_t* total_bytes_written,
227 timespec* data_position) {
228 return transport_->GetPresentationPosition(
229 remote_delay_report_ns, total_bytes_written, data_position);
230 }
231
SourceMetadataChanged(const source_metadata_v7_t & source_metadata)232 void HfpEncodingTransport::SourceMetadataChanged(
233 const source_metadata_v7_t& source_metadata) {
234 transport_->SourceMetadataChanged(source_metadata);
235 }
236
SinkMetadataChanged(const sink_metadata_v7_t & sink_metadata)237 void HfpEncodingTransport::SinkMetadataChanged(
238 const sink_metadata_v7_t& sink_metadata) {
239 transport_->SinkMetadataChanged(sink_metadata);
240 }
241
ResetPresentationPosition()242 void HfpEncodingTransport::ResetPresentationPosition() {
243 transport_->ResetPresentationPosition();
244 }
245
LogBytesWritten(size_t bytes_written)246 void HfpEncodingTransport::LogBytesWritten(size_t bytes_written) {
247 transport_->LogBytesProcessed(bytes_written);
248 }
249
GetPendingCmd() const250 uint8_t HfpEncodingTransport::GetPendingCmd() const {
251 return transport_->GetPendingCmd();
252 }
253
ResetPendingCmd()254 void HfpEncodingTransport::ResetPendingCmd() { transport_->ResetPendingCmd(); }
255
256 } // namespace hfp
257 } // namespace aidl
258 } // namespace audio
259 } // namespace bluetooth
260