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