1 /*
2 * Copyright (C) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "hfp_hf_audio_connection.h"
17
18 #include "btstack.h"
19 #include "hfp_hf_profile_event_sender.h"
20 #include "log_util.h"
21 #include "raw_address.h"
22 #include "securec.h"
23
24 namespace OHOS {
25 namespace bluetooth {
26 std::vector<HfpHfAudioConnection::AudioDevice> HfpHfAudioConnection::g_audioDevices;
27
28 BtmScoCallbacks HfpHfAudioConnection::g_cbs = {
29 &HfpHfAudioConnection::OnConnectCompleted,
30 &HfpHfAudioConnection::OnConnectionChanged,
31 &HfpHfAudioConnection::OnDisconnectCompleted,
32 &HfpHfAudioConnection::OnConnectRequest,
33 &HfpHfAudioConnection::OnWriteVoiceSettingCompleted,
34 };
35
SetRemoteAddr(const std::string & addr)36 void HfpHfAudioConnection::SetRemoteAddr(const std::string &addr)
37 {
38 remoteAddr_ = addr;
39 }
40
ConvertToBtAddr(const std::string & address)41 BtAddr HfpHfAudioConnection::ConvertToBtAddr(const std::string &address)
42 {
43 RawAddress rawAddr(address);
44 BtAddr btAddr;
45 rawAddr.ConvertToUint8(btAddr.addr);
46 btAddr.type = BT_PUBLIC_DEVICE_ADDRESS;
47 return btAddr;
48 }
49
Register()50 int HfpHfAudioConnection::Register()
51 {
52 HILOGI("[HFP HF] Audio Register start");
53 std::vector<HfpHfAudioConnection::AudioDevice>().swap(g_audioDevices);
54 int ret = BTM_RegisterScoCallbacks(&g_cbs, nullptr);
55 HFP_HF_RETURN_IF_FAIL(ret);
56 return ret;
57 }
58
Deregister()59 int HfpHfAudioConnection::Deregister()
60 {
61 HILOGI("[HFP HF] Audio Deregister start");
62 std::vector<HfpHfAudioConnection::AudioDevice>().swap(g_audioDevices);
63 int ret = BTM_DeregisterScoCallbacks(&g_cbs);
64 HFP_HF_RETURN_IF_FAIL(ret);
65 return ret;
66 }
67
IsAudioConnected()68 bool HfpHfAudioConnection::IsAudioConnected()
69 {
70 std::vector<HfpHfAudioConnection::AudioDevice>::iterator it;
71 for (it = g_audioDevices.begin(); it != g_audioDevices.end(); ++it) {
72 if (it->lastConnectResult == CONNECT_SUCCESS) {
73 return true;
74 }
75 }
76 return false;
77 }
78
SetSupportFeatures(bool escoSupport,bool escoS4Support,int inUseCodec)79 void HfpHfAudioConnection::SetSupportFeatures(bool escoSupport, bool escoS4Support, int inUseCodec)
80 {
81 escoSupport_ = escoSupport;
82 escoS4Support_ = escoS4Support;
83 inUseCodec_ = inUseCodec;
84 HILOGI("[HFP HF] escoSupport_[%{public}d], escoS4Support_[%{public}d], inUseCodec_[%{public}d]",
85 escoSupport_, escoS4Support_, inUseCodec_);
86 }
87
GetDeviceByAddr(const std::string & addr)88 std::vector<HfpHfAudioConnection::AudioDevice>::iterator HfpHfAudioConnection::GetDeviceByAddr(const std::string &addr)
89 {
90 std::vector<HfpHfAudioConnection::AudioDevice>::iterator it;
91 for (it = g_audioDevices.begin(); it != g_audioDevices.end(); ++it) {
92 if (it->addr == addr) {
93 break;
94 }
95 }
96 return it;
97 }
98
GetDeviceByHandle(uint16_t handle)99 std::vector<HfpHfAudioConnection::AudioDevice>::iterator HfpHfAudioConnection::GetDeviceByHandle(uint16_t handle)
100 {
101 std::vector<HfpHfAudioConnection::AudioDevice>::iterator it;
102 for (it = g_audioDevices.begin(); it != g_audioDevices.end(); ++it) {
103 if (it->handle == handle) {
104 break;
105 }
106 }
107 return it;
108 }
109
ConnectByCvsd(AudioDevice & dev,BtAddr btAddr,bool cvsdEscoFailed) const110 int HfpHfAudioConnection::ConnectByCvsd(AudioDevice &dev, BtAddr btAddr, bool cvsdEscoFailed) const
111 {
112 int ret = BTM_WriteVoiceSetting(BTM_VOICE_SETTING_CVSD);
113 HFP_HF_RETURN_IF_FAIL(ret);
114
115 if (escoSupport_ && !cvsdEscoFailed) {
116 dev.linkType = LINK_TYPE_ESCO;
117 if (escoS4Support_) {
118 HILOGI("[HFP HF] Try connect by CVSD ESCO S4.");
119 dev.lastParam = CVSD_ESCO_S4;
120 BtmCreateEscoConnectionParam param = CVSD_ESCO_S4_PARAM;
121 param.addr = btAddr;
122 ret = BTM_CreateEscoConnection(¶m);
123 HFP_HF_RETURN_IF_FAIL(ret);
124 } else {
125 HILOGI("[HFP HF] Try connect by CVSD ESCO S1.");
126 dev.lastParam = CVSD_ESCO_S1;
127 BtmCreateEscoConnectionParam param = CVSD_ESCO_S1_PARAM;
128 param.addr = btAddr;
129 ret = BTM_CreateEscoConnection(¶m);
130 HFP_HF_RETURN_IF_FAIL(ret);
131 }
132 } else {
133 if (!BTM_IsSecureConnection(&btAddr)) {
134 dev.linkType = LINK_TYPE_SCO;
135 HILOGI("[HFP HF] Try connect by CVSD SCO.");
136 dev.lastParam = CVSD_SCO;
137 BtmCreateScoConnectionParam param = CVSD_SCO_PARAM;
138 param.addr = btAddr;
139 ret = BTM_CreateScoConnection(¶m);
140 HFP_HF_RETURN_IF_FAIL(ret);
141 } else {
142 HfpHfProfileEventSender::GetInstance().UpdateScoConnectState(remoteAddr_, HFP_HF_AUDIO_CONNECT_FAILED_EVT);
143 return ret;
144 }
145 }
146
147 HfpHfProfileEventSender::GetInstance().UpdateScoConnectState(remoteAddr_, HFP_HF_AUDIO_CONNECTING_EVT);
148 return ret;
149 }
150
ConnectAudio() const151 int HfpHfAudioConnection::ConnectAudio() const
152 {
153 HILOGI("[HFP HF] Connect SCO to %{public}s", GetEncryptAddr(remoteAddr_).c_str());
154
155 auto dev = GetDeviceByAddr(remoteAddr_);
156 if (dev == g_audioDevices.end()) {
157 HfpHfAudioConnection::AudioDevice audioDev;
158 audioDev.role = ROLE_INITIATOR;
159 audioDev.addr = remoteAddr_;
160 g_audioDevices.push_back(audioDev);
161 dev = GetDeviceByAddr(remoteAddr_);
162 HILOGI("[HFP HF] Create Audio device for [%{public}s]", GetEncryptAddr(remoteAddr_).c_str());
163 } else {
164 HILOGI("[HFP HF] Audio device [%{public}s] already in device list ", GetEncryptAddr(remoteAddr_).c_str());
165 }
166
167 bool cvsdEscoFailed = false;
168 if (dev->lastConnectResult == CONNECT_FAIL) {
169 if (dev->lastParam == CVSD_ESCO_S4 || dev->lastParam == CVSD_ESCO_S1) {
170 cvsdEscoFailed = true;
171 } else {
172 LOG_INFO("[HFP HF] Audio device [%{public}s], lastParam[%{public}d]",
173 GetEncryptAddr(remoteAddr_).c_str(), dev->lastParam);
174 }
175 }
176
177 BtAddr btAddr = ConvertToBtAddr(remoteAddr_);
178 return ConnectByCvsd(*dev, btAddr, cvsdEscoFailed);
179 }
180
DisconnectAudio() const181 int HfpHfAudioConnection::DisconnectAudio() const
182 {
183 HILOGI("[HFP HF] Disconnect SCO from %{public}s", GetEncryptAddr(remoteAddr_).c_str());
184
185 int ret;
186 auto dev = GetDeviceByAddr(remoteAddr_);
187 if (dev != g_audioDevices.end()) {
188 ret = BTM_DisconnectScoConnection(dev->handle, REMOTE_USER_TERMINATED_CONNECTION);
189 HFP_HF_RETURN_IF_FAIL(ret);
190 HfpHfProfileEventSender::GetInstance().UpdateScoConnectState(remoteAddr_, HFP_HF_AUDIO_DISCONNECTING_EVT);
191 } else {
192 HILOGE("[HFP HF] Invalid Address remoteAddr_ %{public}s", GetEncryptAddr(remoteAddr_).c_str());
193 ret = BT_DEVICE_ERROR;
194 }
195 return ret;
196 }
197
AcceptByMsbc(BtAddr btAddr)198 int HfpHfAudioConnection::AcceptByMsbc(BtAddr btAddr)
199 {
200 int ret = BTM_WriteVoiceSetting(BTM_VOICE_SETTING_TRANS);
201 HFP_HF_RETURN_IF_FAIL(ret);
202
203 if (BTM_IsSecureConnection(&btAddr)) {
204 HILOGI("[HFP HF] Accept by MSBC T2.");
205 BtmCreateEscoConnectionParam param = MSBC_T2_PARAM;
206 param.addr = btAddr;
207 ret = BTM_AcceptEscoConnectionRequest(¶m);
208 HFP_HF_RETURN_IF_FAIL(ret);
209 } else {
210 HILOGI("[HFP HF] Accept by MSBC T1.");
211 BtmCreateEscoConnectionParam param = MSBC_T1_PARAM;
212 param.addr = btAddr;
213 ret = BTM_AcceptEscoConnectionRequest(¶m);
214 HFP_HF_RETURN_IF_FAIL(ret);
215 }
216 return ret;
217 }
218
AcceptByCvsd(AudioDevice & dev,BtAddr btAddr) const219 int HfpHfAudioConnection::AcceptByCvsd(AudioDevice &dev, BtAddr btAddr) const
220 {
221 int ret = BTM_WriteVoiceSetting(BTM_VOICE_SETTING_CVSD);
222 HFP_HF_RETURN_IF_FAIL(ret);
223
224 if (dev.linkType == LINK_TYPE_ESCO && escoSupport_) {
225 if (escoS4Support_) {
226 HILOGI("[HFP HF] Accept by CVSD ESCO S4.");
227 BtmCreateEscoConnectionParam param = CVSD_ESCO_S4_PARAM;
228 param.addr = btAddr;
229 ret = BTM_AcceptEscoConnectionRequest(¶m);
230 HFP_HF_RETURN_IF_FAIL(ret);
231 } else {
232 HILOGI("[HFP HF] Accept by CVSD ESCO S1.");
233 BtmCreateEscoConnectionParam param = CVSD_ESCO_S1_PARAM;
234 param.addr = btAddr;
235 ret = BTM_AcceptEscoConnectionRequest(¶m);
236 HFP_HF_RETURN_IF_FAIL(ret);
237 }
238 } else if (dev.linkType == LINK_TYPE_SCO) {
239 HILOGI("[HFP HF] Accept by CVSD SCO.");
240 BtmCreateScoConnectionParam param = CVSD_SCO_PARAM;
241 param.addr = btAddr;
242 ret = BTM_AcceptScoConnectionRequest(¶m);
243 HFP_HF_RETURN_IF_FAIL(ret);
244 } else {
245 HILOGE("[HFP HF] Can not cvsd e(sco) connection, "
246 "because linktype[%{public}d] and escoSupport[%{public}d] are not matched!", dev.linkType, escoSupport_);
247 return BT_BAD_PARAM;
248 }
249 return ret;
250 }
251
AcceptAudioConnection() const252 int HfpHfAudioConnection::AcceptAudioConnection() const
253 {
254 int ret = BT_SUCCESS;
255 BtAddr btAddr = ConvertToBtAddr(remoteAddr_);
256
257 // Only accpet CVSD sco from remote device.
258 auto dev = GetDeviceByAddr(remoteAddr_);
259 if (dev != g_audioDevices.end()) {
260 if (inUseCodec_ == HFP_HF_CODEC_MSBC) {
261 if (dev->linkType == LINK_TYPE_ESCO && escoSupport_) {
262 return AcceptByMsbc(btAddr);
263 } else {
264 HILOGI("[HFP HF] Accpet MSBC ESCO connection failed, "
265 "linktype[%{public}hhu] and escoSupport[%{public}d] are not matched", dev->linkType, escoSupport_);
266 return BT_BAD_PARAM;
267 }
268 } else if (inUseCodec_ == HFP_HF_CODEC_CVSD) {
269 return AcceptByCvsd(*dev, btAddr);
270 } else {
271 HILOGI("[HFP HF] Invalid Codec[%{public}d]!", inUseCodec_);
272 return BT_BAD_PARAM;
273 }
274 } else {
275 HILOGE("[HFP HF] %{public}s:Invalid Address", GetEncryptAddr(remoteAddr_).c_str());
276 return BT_BAD_PARAM;
277 }
278
279 return ret;
280 }
281
RejectAudioConnection() const282 int HfpHfAudioConnection::RejectAudioConnection() const
283 {
284 HILOGI("[HFP HF] Reject sco connect request from %{public}s", GetEncryptAddr(remoteAddr_).c_str());
285 BtAddr btAddr = ConvertToBtAddr(remoteAddr_);
286 BtmRejectScoConnectionRequestParam param = {btAddr, REJECT_DUE_TO_LIMITED_RESOURCES};
287
288 int ret = BTM_RejectScoConnectionRequest(¶m);
289 HFP_HF_RETURN_IF_FAIL(ret);
290
291 return ret;
292 }
293
OnConnectRequest(const BtmScoConnectionRequestParam * param,void * context)294 void HfpHfAudioConnection::OnConnectRequest(const BtmScoConnectionRequestParam *param, void *context)
295 {
296 HILOGI("[HFP HF] enter");
297 HfpScoConnectionRequestParam parameters;
298 parameters.linkType = param->linkType;
299 (void)memcpy_s(¶meters.addr, sizeof(BtAddr), param->addr, sizeof(BtAddr));
300 HfpHfProfileEventSender::GetInstance().GetDispatchter()->PostTask(
301 std::bind(&HfpHfAudioConnection::ProcessOnConnectRequest, parameters));
302 }
303
ProcessOnConnectRequest(HfpScoConnectionRequestParam parameters)304 void HfpHfAudioConnection::ProcessOnConnectRequest(HfpScoConnectionRequestParam parameters)
305 {
306 HILOGI("[HFP HF] enter");
307
308 RawAddress btAddr = RawAddress::ConvertToString(parameters.addr.addr);
309 std::string address = btAddr.GetAddress();
310 auto dev = GetDeviceByAddr(address);
311 if (dev == g_audioDevices.end()) {
312 HfpHfAudioConnection::AudioDevice audioDev;
313 audioDev.role = ROLE_ACCEPTOR;
314 audioDev.addr = address;
315 audioDev.linkType = parameters.linkType;
316 g_audioDevices.push_back(audioDev);
317 HILOGI("[HFP HF] Create Audio device for [%{public}s]", GetEncryptAddr(address).c_str());
318 } else {
319 dev->linkType = parameters.linkType;
320 HILOGI("[HFP HF] Audio device [%{public}s] already in device list", GetEncryptAddr(address).c_str());
321 }
322 HfpHfProfileEventSender::GetInstance().ScoConnectRequest(
323 btAddr.GetAddress(), HFP_HF_AUDIO_CONNECT_REQUEST_EVT, parameters.linkType);
324 }
325
OnConnectCompleted(const BtmScoConnectionCompleteParam * param,void * context)326 void HfpHfAudioConnection::OnConnectCompleted(const BtmScoConnectionCompleteParam *param, void *context)
327 {
328 HILOGI("[HFP HF] enter");
329 HfpScoConnectionCompleteParam parameters;
330 parameters.status = param->status;
331 parameters.connectionHandle = param->connectionHandle;
332 (void)memcpy_s(¶meters.addr, sizeof(BtAddr), param->addr, sizeof(BtAddr));
333 HfpHfProfileEventSender::GetInstance().GetDispatchter()->PostTask(
334 std::bind(&HfpHfAudioConnection::ProcessOnConnectCompleted, parameters));
335 }
336
ProcessOnConnectCompleted(HfpScoConnectionCompleteParam parameters)337 void HfpHfAudioConnection::ProcessOnConnectCompleted(HfpScoConnectionCompleteParam parameters)
338 {
339 HILOGI("[HFP HF] enter");
340
341 RawAddress btAddr = RawAddress::ConvertToString(parameters.addr.addr);
342 std::string address = btAddr.GetAddress();
343 auto dev = GetDeviceByAddr(address);
344 if (dev != g_audioDevices.end()) {
345 dev->addr = address;
346 dev->handle = parameters.connectionHandle;
347 if (!parameters.status) {
348 HILOGI("[HFP HF] SCO connect successfully!");
349 dev->lastConnectResult = CONNECT_SUCCESS;
350 HfpHfProfileEventSender::GetInstance().UpdateScoConnectState(dev->addr, HFP_HF_AUDIO_CONNECTED_EVT);
351 } else {
352 ProcessOnConnectCompletedFail(dev, address);
353 }
354 } else {
355 HILOGI("[HFP HF] %{public}s: Invalid audio device", GetEncryptAddr(address).c_str());
356 }
357 }
358
ProcessOnConnectCompletedFail(std::vector<HfpHfAudioConnection::AudioDevice>::iterator dev,const std::string & address)359 void HfpHfAudioConnection::ProcessOnConnectCompletedFail(
360 std::vector<HfpHfAudioConnection::AudioDevice>::iterator dev, const std::string &address)
361 {
362 dev->lastConnectResult = CONNECT_FAIL;
363 if (dev->role == ROLE_INITIATOR) {
364 if (dev->lastParam == CVSD_ESCO_S4 || dev->lastParam == CVSD_ESCO_S1) {
365 HILOGI("[HFP HF] CVSD ESCO failed, try CVSD SCO");
366 HfpHfProfileEventSender::GetInstance().UpdateScoConnectState(dev->addr, HFP_HF_RETRY_CONNECT_AUDIO_EVT);
367 } else if (dev->lastParam == CVSD_SCO) {
368 HILOGI("[HFP HF] CVSD SCO failed, report fail event to service");
369 HfpHfProfileEventSender::GetInstance().UpdateScoConnectState(dev->addr, HFP_HF_AUDIO_CONNECT_FAILED_EVT);
370 } else {
371 HILOGI("[HFP HF] address[%{public}s] lastParam[%{public}d] is invalid",
372 GetEncryptAddr(address).c_str(), dev->lastParam);
373 }
374 } else {
375 // As acceptor, report connect failed event to service directly.
376 HfpHfProfileEventSender::GetInstance().UpdateScoConnectState(dev->addr, HFP_HF_AUDIO_CONNECT_FAILED_EVT);
377 HILOGI("[HFP HF] Accept SCO from address[%{public}s]failed", GetEncryptAddr(address).c_str());
378 }
379 }
380
OnDisconnectCompleted(const BtmScoDisconnectionCompleteParam * param,void * context)381 void HfpHfAudioConnection::OnDisconnectCompleted(const BtmScoDisconnectionCompleteParam *param, void *context)
382 {
383 HILOGI("[HFP HF] enter");
384 HfpScoDisconnectionCompleteParam parameters;
385 parameters.connectionHandle = param->connectionHandle;
386 parameters.reason = param->reason;
387 parameters.status = param->status;
388 HfpHfProfileEventSender::GetInstance().GetDispatchter()->PostTask(
389 std::bind(&HfpHfAudioConnection::ProcessOnDisconnectCompleted, parameters));
390 }
391
ProcessOnDisconnectCompleted(HfpScoDisconnectionCompleteParam parameters)392 void HfpHfAudioConnection::ProcessOnDisconnectCompleted(HfpScoDisconnectionCompleteParam parameters)
393 {
394 HILOGI("[HFP HF] enter");
395
396 auto it = GetDeviceByHandle(parameters.connectionHandle);
397 if (it != g_audioDevices.end()) {
398 if (!parameters.status) {
399 HILOGI("Disconnect SCO from address: %{public}s successfully.", GetEncryptAddr(it->addr).c_str());
400 HfpHfProfileEventSender::GetInstance().UpdateScoConnectState(it->addr, HFP_HF_AUDIO_DISCONNECTED_EVT);
401 g_audioDevices.erase(it);
402 } else {
403 HILOGI("Disconnect SCO from address: %{public}s failed.", GetEncryptAddr(it->addr).c_str());
404 HfpHfProfileEventSender::GetInstance().UpdateScoConnectState(
405 it->addr, HFP_HF_AUDIO_DISCONNECT_FAILED_EVT);
406 }
407 } else {
408 HILOGE("[HFP HF] Invalid audio device");
409 }
410 }
411
OnConnectionChanged(const BtmScoConnectionChangedParam * param,void * context)412 void HfpHfAudioConnection::OnConnectionChanged(const BtmScoConnectionChangedParam *param, void *context)
413 {
414 HILOGI("[HFP HF] connectionHandle[%{public}hu]", param->connectionHandle);
415 }
416
OnWriteVoiceSettingCompleted(uint8_t status,void * context)417 void HfpHfAudioConnection::OnWriteVoiceSettingCompleted(uint8_t status, void *context)
418 {
419 HILOGI("[HFP HF] status[%{public}hhu]", status);
420 }
421 } // namespace bluetooth
422 } // namespace OHOS