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 <cstring>
17 #include "btstack.h"
18 #include "hfp_ag_profile_event_sender.h"
19 #include "log_util.h"
20 #include "raw_address.h"
21 #include "securec.h"
22 #include "hfp_ag_audio_connection.h"
23 
24 namespace OHOS {
25 namespace bluetooth {
26 std::string HfpAgAudioConnection::g_activeAddr {NULL_ADDRESS};
27 std::vector<HfpAgAudioConnection::AudioDevice> HfpAgAudioConnection::g_audioDevices {};
28 
29 BtmScoCallbacks HfpAgAudioConnection::g_cbs = {
30     &HfpAgAudioConnection::OnConnectCompleted,
31     &HfpAgAudioConnection::OnConnectionChanged,
32     &HfpAgAudioConnection::OnDisconnectCompleted,
33     &HfpAgAudioConnection::OnConnectRequest,
34     &HfpAgAudioConnection::OnWriteVoiceSettingCompleted,
35 };
36 
SetRemoteAddr(const std::string & addr)37 void HfpAgAudioConnection::SetRemoteAddr(const std::string &addr)
38 {
39     remoteAddr_ = addr;
40 }
41 
SetActiveDevice(const std::string & address)42 void HfpAgAudioConnection::SetActiveDevice(const std::string &address)
43 {
44     g_activeAddr = address;
45 }
46 
IsAudioConnected(const std::string & address)47 bool HfpAgAudioConnection::IsAudioConnected(const std::string &address)
48 {
49     auto dev = GetDeviceByAddr(address);
50     if (dev != g_audioDevices.end()) {
51         if (dev->lastConnectResult == CONNECT_SUCCESS) {
52             return true;
53         }
54     }
55 
56     return false;
57 }
58 
GetActiveDevice()59 std::string HfpAgAudioConnection::GetActiveDevice()
60 {
61     return g_activeAddr;
62 }
63 
ConvertToBtAddr(std::string address)64 BtAddr HfpAgAudioConnection::ConvertToBtAddr(std::string address)
65 {
66     RawAddress rawAddr(address);
67     BtAddr btAddr;
68     rawAddr.ConvertToUint8(btAddr.addr);
69     btAddr.type = BT_PUBLIC_DEVICE_ADDRESS;
70     return btAddr;
71 }
72 
Register()73 int HfpAgAudioConnection::Register()
74 {
75     HILOGI("enter");
76     g_activeAddr = NULL_ADDRESS;
77     std::vector<HfpAgAudioConnection::AudioDevice>().swap(g_audioDevices);
78     int ret = BTM_RegisterScoCallbacks(&g_cbs, nullptr);
79     HFP_AG_RETURN_IF_FAIL(ret);
80     return ret;
81 }
82 
Deregister()83 int HfpAgAudioConnection::Deregister()
84 {
85     HILOGI("enter");
86     g_activeAddr = NULL_ADDRESS;
87     std::vector<HfpAgAudioConnection::AudioDevice>().swap(g_audioDevices);
88     int ret = BTM_DeregisterScoCallbacks(&g_cbs);
89     HFP_AG_RETURN_IF_FAIL(ret);
90     return ret;
91 }
92 
SetSupportFeatures(bool escoSupport,bool escoS4Support,int inUseCodec)93 void HfpAgAudioConnection::SetSupportFeatures(bool escoSupport, bool escoS4Support, int inUseCodec)
94 {
95     escoSupport_ = escoSupport;
96     escoS4Support_ = escoS4Support;
97     inUseCodec_ = inUseCodec;
98     HILOGI("escoSupport_: %{public}d, escoS4Support_: %{public}d, inUseCodec_: %{public}d",
99         escoSupport_,
100         escoS4Support_,
101         inUseCodec_);
102 }
103 
GetDeviceByAddr(const std::string & addr)104 std::vector<HfpAgAudioConnection::AudioDevice>::iterator HfpAgAudioConnection::GetDeviceByAddr(const std::string &addr)
105 {
106     std::vector<HfpAgAudioConnection::AudioDevice>::iterator it;
107     for (it = g_audioDevices.begin(); it != g_audioDevices.end(); ++it) {
108         if (it->addr == addr) {
109             break;
110         }
111     }
112     return it;
113 }
114 
GetDeviceByHandle(uint16_t handle)115 std::vector<HfpAgAudioConnection::AudioDevice>::iterator HfpAgAudioConnection::GetDeviceByHandle(uint16_t handle)
116 {
117     std::vector<HfpAgAudioConnection::AudioDevice>::iterator it;
118     for (it = g_audioDevices.begin(); it != g_audioDevices.end(); ++it) {
119         if (it->handle == handle) {
120             break;
121         }
122     }
123     return it;
124 }
125 
ConnectByMsbc(AudioDevice & dev,BtAddr btAddr) const126 int HfpAgAudioConnection::ConnectByMsbc(AudioDevice &dev, BtAddr btAddr) const
127 {
128     int ret = BTM_WriteVoiceSetting(BTM_VOICE_SETTING_TRANS);
129     HFP_AG_RETURN_IF_FAIL(ret);
130 
131     dev.linkType = LINK_TYPE_ESCO;
132 
133     if (dev.lastParam != MSBC_ESCO_T2) {
134         HILOGI("Try connect by MSBC T2.");
135         BtmCreateEscoConnectionParam param = MSBC_T2_PARAM;
136         param.addr = btAddr;
137         ret = BTM_CreateEscoConnection(&param);
138         HFP_AG_RETURN_IF_FAIL(ret);
139         dev.lastParam = MSBC_ESCO_T2;
140     } else if (!BTM_IsSecureConnection(&btAddr)) {
141         HILOGI("Try connect by MSBC T1.");
142         BtmCreateEscoConnectionParam param = MSBC_T1_PARAM;
143         param.addr = btAddr;
144         ret = BTM_CreateEscoConnection(&param);
145         HFP_AG_RETURN_IF_FAIL(ret);
146         dev.lastParam = MSBC_ESCO_T1;
147     }
148     HFP_AG_RETURN_IF_FAIL(ret);
149 
150     HfpAgProfileEventSender::GetInstance().UpdateScoConnectState(remoteAddr_, HFP_AG_AUDIO_CONNECTING_EVT);
151     return ret;
152 }
153 
ConnectByCvsd(AudioDevice & dev,BtAddr btAddr,bool cvsdEscoFailed) const154 int HfpAgAudioConnection::ConnectByCvsd(AudioDevice &dev, BtAddr btAddr, bool cvsdEscoFailed) const
155 {
156     int ret = BTM_WriteVoiceSetting(BTM_VOICE_SETTING_CVSD);
157     HFP_AG_RETURN_IF_FAIL(ret);
158 
159     if (escoSupport_ && !cvsdEscoFailed && escoS4Support_) {
160             HILOGI("Try connect by CVSD ESCO S4.");
161             dev.linkType = LINK_TYPE_ESCO;
162             dev.lastParam = CVSD_ESCO_S4;
163             BtmCreateEscoConnectionParam param = CVSD_ESCO_S4_PARAM;
164             param.addr = btAddr;
165             ret = BTM_CreateEscoConnection(&param);
166             HFP_AG_RETURN_IF_FAIL(ret);
167     } else if ((dev.lastParam == CVSD_ESCO_S4) && !BTM_IsSecureConnection(&btAddr)) {
168             HILOGI("Try connect by CVSD ESCO S1.");
169             dev.linkType = LINK_TYPE_ESCO;
170             dev.lastParam = CVSD_ESCO_S1;
171             BtmCreateEscoConnectionParam param = CVSD_ESCO_S1_PARAM;
172             param.addr = btAddr;
173             ret = BTM_CreateEscoConnection(&param);
174             HFP_AG_RETURN_IF_FAIL(ret);
175     } else if (!BTM_IsSecureConnection(&btAddr)) {
176             dev.linkType = LINK_TYPE_SCO;
177             HILOGI("Try connect by CVSD SCO.");
178             dev.lastParam = CVSD_SCO;
179             BtmCreateScoConnectionParam param = CVSD_SCO_PARAM;
180             param.addr = btAddr;
181             ret = BTM_CreateScoConnection(&param);
182             HFP_AG_RETURN_IF_FAIL(ret);
183     } else {
184             HfpAgProfileEventSender::GetInstance().UpdateScoConnectState(remoteAddr_, HFP_AG_AUDIO_CONNECT_FAILED_EVT);
185             return ret;
186     }
187 
188     HfpAgProfileEventSender::GetInstance().UpdateScoConnectState(remoteAddr_, HFP_AG_AUDIO_CONNECTING_EVT);
189     return ret;
190 }
191 
ConnectAudio() const192 int HfpAgAudioConnection::ConnectAudio() const
193 {
194     HILOGI("Connect SCO to %{public}s", GetEncryptAddr(remoteAddr_).c_str());
195 
196     if (remoteAddr_ != g_activeAddr) {
197         HILOGW("remoteAddr: %{public}s and g_activeAddr: %{public}s match failed!",
198             GetEncryptAddr(remoteAddr_).c_str(), GetEncryptAddr(g_activeAddr).c_str());
199         HfpAgProfileEventSender::GetInstance().UpdateScoConnectState(remoteAddr_, HFP_AG_AUDIO_CONNECT_FAILED_EVT);
200         return BT_BAD_PARAM;
201     }
202 
203     auto dev = GetDeviceByAddr(remoteAddr_);
204     if (dev == g_audioDevices.end()) {
205         HfpAgAudioConnection::AudioDevice audioDev;
206         audioDev.role = ROLE_INITIATOR;
207         audioDev.addr = remoteAddr_;
208         g_audioDevices.push_back(audioDev);
209         dev = GetDeviceByAddr(remoteAddr_);
210         HILOGI("Create Audio device for %{public}s", GetEncryptAddr(remoteAddr_).c_str());
211     } else {
212         HILOGI("Audio device: %{public}s already in device list", GetEncryptAddr(remoteAddr_).c_str());
213     }
214 
215     bool msbcEscoFailed = false;
216     bool cvsdEscoFailed = false;
217     if (dev->lastConnectResult == CONNECT_FAIL) {
218         if (dev->lastParam == MSBC_ESCO_T2 || dev->lastParam == MSBC_ESCO_T1) {
219             msbcEscoFailed = true;
220         } else if (dev->lastParam == CVSD_ESCO_S4 || dev->lastParam == CVSD_ESCO_S1) {
221             cvsdEscoFailed = true;
222         } else {
223             HILOGI("Audio device: %{public}s, lastParam: %{public}d",
224                 GetEncryptAddr(remoteAddr_).c_str(), dev->lastParam);
225         }
226     }
227 
228     BtAddr btAddr = ConvertToBtAddr(remoteAddr_);
229     if (inUseCodec_ == HFP_AG_CODEC_MSBC) {
230         if ((!msbcEscoFailed || (dev->lastParam == MSBC_ESCO_T2)) && escoSupport_) {
231             return ConnectByMsbc(*dev, btAddr);
232         } else {
233             HILOGW("Need re-negotiate codec.");
234             HfpAgProfileEventSender::GetInstance().UpdateScoConnectState(dev->addr, HFP_AG_SETUP_CODEC_CVSD);
235             return BT_BAD_PARAM;
236         }
237     } else if (inUseCodec_ == HFP_AG_CODEC_CVSD) {
238         return ConnectByCvsd(*dev, btAddr, cvsdEscoFailed);
239     } else {
240         HILOGI("RemoteAddr: %{public}s, invalid codec: %{public}d",
241             GetEncryptAddr(remoteAddr_).c_str(), inUseCodec_);
242         return BT_BAD_PARAM;
243     }
244 
245     return BT_SUCCESS;
246 }
247 
DisconnectAudio() const248 int HfpAgAudioConnection::DisconnectAudio() const
249 {
250     HILOGI("Disconnect SCO from %{public}s", GetEncryptAddr(remoteAddr_).c_str());
251 
252     int ret;
253     auto dev = GetDeviceByAddr(remoteAddr_);
254     if (dev != g_audioDevices.end()) {
255         ret = BTM_DisconnectScoConnection(dev->handle, REMOTE_USER_TERMINATED_CONNECTION);
256         HFP_AG_RETURN_IF_FAIL(ret);
257         HfpAgProfileEventSender::GetInstance().UpdateScoConnectState(remoteAddr_, HFP_AG_AUDIO_DISCONNECTING_EVT);
258     } else {
259         HILOGW("%{public}s: Invalid Address", GetEncryptAddr(remoteAddr_).c_str());
260         ret = BT_DEVICE_ERROR;
261     }
262     return ret;
263 }
264 
AcceptByMsbc(BtAddr btAddr)265 int HfpAgAudioConnection::AcceptByMsbc(BtAddr btAddr)
266 {
267     int ret = BTM_WriteVoiceSetting(BTM_VOICE_SETTING_TRANS);
268     HFP_AG_RETURN_IF_FAIL(ret);
269 
270     if (BTM_IsSecureConnection(&btAddr)) {
271         HILOGI("Accept by MSBC T2.");
272         BtmCreateEscoConnectionParam param = MSBC_T2_PARAM;
273         param.addr = btAddr;
274         ret = BTM_AcceptEscoConnectionRequest(&param);
275         HFP_AG_RETURN_IF_FAIL(ret);
276     } else {
277         HILOGI("Accept by MSBC T1.");
278         BtmCreateEscoConnectionParam param = MSBC_T1_PARAM;
279         param.addr = btAddr;
280         ret = BTM_AcceptEscoConnectionRequest(&param);
281         HFP_AG_RETURN_IF_FAIL(ret);
282     }
283 
284     return ret;
285 }
286 
AcceptByCvsd(const AudioDevice & dev,BtAddr btAddr) const287 int HfpAgAudioConnection::AcceptByCvsd(const AudioDevice &dev, BtAddr btAddr) const
288 {
289     int ret = BTM_WriteVoiceSetting(BTM_VOICE_SETTING_CVSD);
290     HFP_AG_RETURN_IF_FAIL(ret);
291 
292     if (dev.linkType == LINK_TYPE_ESCO && escoSupport_) {
293         if (escoS4Support_) {
294             HILOGI("Accept by CVSD ESCO S4.");
295             BtmCreateEscoConnectionParam param = CVSD_ESCO_S4_PARAM;
296             param.addr = btAddr;
297             ret = BTM_AcceptEscoConnectionRequest(&param);
298             HFP_AG_RETURN_IF_FAIL(ret);
299         } else {
300             HILOGI("Accept by CVSD ESCO S1.");
301             BtmCreateEscoConnectionParam param = CVSD_ESCO_S1_PARAM;
302             param.addr = btAddr;
303             ret = BTM_AcceptEscoConnectionRequest(&param);
304             HFP_AG_RETURN_IF_FAIL(ret);
305         }
306     } else if (dev.linkType == LINK_TYPE_SCO) {
307         HILOGI("Accept by CVSD SCO.");
308         BtmCreateScoConnectionParam param = CVSD_SCO_PARAM;
309         param.addr = btAddr;
310         ret = BTM_AcceptScoConnectionRequest(&param);
311         HFP_AG_RETURN_IF_FAIL(ret);
312     } else {
313         HILOGI("CVSD ESCO connection fail, "
314             "linktype: %{public}hhu and escoSupport: %{public}d are not matched!",
315             dev.linkType,
316             escoSupport_);
317         return BT_BAD_PARAM;
318     }
319 
320     return ret;
321 }
322 
AcceptAudioConnection() const323 int HfpAgAudioConnection::AcceptAudioConnection() const
324 {
325     int ret = BT_SUCCESS;
326     BtAddr btAddr = ConvertToBtAddr(remoteAddr_);
327 
328     // Only accpet CVSD sco from remote device.
329     auto dev = GetDeviceByAddr(remoteAddr_);
330     if (dev != g_audioDevices.end()) {
331         if (inUseCodec_ == HFP_AG_CODEC_MSBC) {
332             if (dev->linkType == LINK_TYPE_ESCO && escoSupport_) {
333                 return AcceptByMsbc(btAddr);
334             } else {
335                 HILOGI("MSBC ESCO connection fail, "
336                     "linktype: %{public}hhu and escoSupport: %{public}d are not matched!",
337                     dev->linkType,
338                     escoSupport_);
339                 return BT_BAD_PARAM;
340             }
341         } else if (inUseCodec_ == HFP_AG_CODEC_CVSD) {
342             return AcceptByCvsd(*dev, btAddr);
343         } else {
344             HILOGI("Invalid Codec: %{public}d", inUseCodec_);
345             return BT_BAD_PARAM;
346         }
347     } else {
348         HILOGW("%{public}s: Invalid Address", GetEncryptAddr(remoteAddr_).c_str());
349         return BT_BAD_PARAM;
350     }
351 
352     return ret;
353 }
354 
RejectAudioConnection() const355 int HfpAgAudioConnection::RejectAudioConnection() const
356 {
357     HILOGI("Reject sco connect request from %{public}s", GetEncryptAddr(remoteAddr_).c_str());
358     BtAddr btAddr = ConvertToBtAddr(remoteAddr_);
359     BtmRejectScoConnectionRequestParam param = {btAddr, REJECT_DUE_TO_LIMITED_RESOURCES};
360 
361     int ret = BTM_RejectScoConnectionRequest(&param);
362     HFP_AG_RETURN_IF_FAIL(ret);
363 
364     return ret;
365 }
366 
OnConnectRequest(const BtmScoConnectionRequestParam * param,void * context)367 void HfpAgAudioConnection::OnConnectRequest(const BtmScoConnectionRequestParam *param, void *context)
368 {
369     HILOGI("enter");
370     HfpScoConnectionRequestParam parameters;
371     parameters.linkType = param->linkType;
372     (void)memcpy_s(&parameters.addr, sizeof(BtAddr), param->addr, sizeof(BtAddr));
373     if (HfpAgProfileEventSender::GetInstance().GetDispatchter() == nullptr) {
374         HILOGI("GetDispatchter() return nullptr");
375         return;
376     }
377     HfpAgProfileEventSender::GetInstance().GetDispatchter()->PostTask(
378         std::bind(&HfpAgAudioConnection::ProcessOnConnectRequest, parameters));
379 }
380 
ProcessOnConnectRequest(HfpScoConnectionRequestParam parameters)381 void HfpAgAudioConnection::ProcessOnConnectRequest(HfpScoConnectionRequestParam parameters)
382 {
383     HILOGI("enter");
384 
385     RawAddress btAddr = RawAddress::ConvertToString(parameters.addr.addr);
386     std::string address = btAddr.GetAddress();
387 
388     auto dev = GetDeviceByAddr(address);
389     if (dev == g_audioDevices.end()) {
390         HfpAgAudioConnection::AudioDevice audioDev;
391         audioDev.role = ROLE_ACCEPTOR;
392         audioDev.addr = address;
393         audioDev.linkType = parameters.linkType;
394         g_audioDevices.push_back(audioDev);
395         HILOGI("Create Audio device for %{public}s", GetEncryptAddr(address).c_str());
396     } else {
397         dev->linkType = parameters.linkType;
398         HILOGI("Audio device %{public}s already in device list",
399             GetEncryptAddr(address).c_str());
400     }
401     HfpAgProfileEventSender::GetInstance().ScoConnectRequest(
402         btAddr.GetAddress(), HFP_AG_AUDIO_CONNECT_REQUEST_EVT, parameters.linkType);
403 }
404 
OnConnectCompleted(const BtmScoConnectionCompleteParam * param,void * context)405 void HfpAgAudioConnection::OnConnectCompleted(const BtmScoConnectionCompleteParam *param, void *context)
406 {
407     HILOGI("enter");
408     HfpScoConnectionCompleteParam parameters;
409     parameters.status = param->status;
410     parameters.connectionHandle = param->connectionHandle;
411     (void)memcpy_s(&parameters.addr, sizeof(BtAddr), param->addr, sizeof(BtAddr));
412     if (HfpAgProfileEventSender::GetInstance().GetDispatchter() == nullptr) {
413         HILOGI("GetDispatchter() return nullptr");
414         return;
415     }
416     HfpAgProfileEventSender::GetInstance().GetDispatchter()->PostTask(
417         std::bind(&HfpAgAudioConnection::ProcessOnConnectCompleted, parameters));
418 }
419 
ProcessOnConnectCompletedFail(std::vector<HfpAgAudioConnection::AudioDevice>::iterator dev,const std::string & address)420 void HfpAgAudioConnection::ProcessOnConnectCompletedFail(
421     std::vector<HfpAgAudioConnection::AudioDevice>::iterator dev, const std::string &address)
422 {
423     dev->lastConnectResult = CONNECT_FAIL;
424     if (dev->role == ROLE_INITIATOR) {
425         switch (dev->lastParam) {
426             case MSBC_ESCO_T2:
427                 HILOGI("MSBC ESCO T2 failed, Retry MSBC ESCO.");
428                 HfpAgProfileEventSender::GetInstance().UpdateScoConnectState(dev->addr,
429                     HFP_AG_RETRY_CONNECT_AUDIO_EVT);
430                 break;
431             case MSBC_ESCO_T1:
432                 HILOGI("MSBC ESCO T1 failed, try CVSD ESCO.");
433                 HfpAgProfileEventSender::GetInstance().UpdateScoConnectState(dev->addr, HFP_AG_SETUP_CODEC_CVSD);
434                 break;
435             case CVSD_ESCO_S4:
436                 HILOGI("CVSD ESCO S4 failed, Retry CVSD ESCO");
437                 HfpAgProfileEventSender::GetInstance().UpdateScoConnectState(dev->addr,
438                     HFP_AG_RETRY_CONNECT_AUDIO_EVT);
439                 break;
440             case CVSD_ESCO_S1:
441                 HILOGI("CVSD ESCO S1 failed, try CVSD SCO");
442                 HfpAgProfileEventSender::GetInstance().UpdateScoConnectState(dev->addr,
443                     HFP_AG_RETRY_CONNECT_AUDIO_EVT);
444                 break;
445             case CVSD_SCO:
446                 HILOGI("CVSD SCO failed, report fail event to service");
447                 HfpAgProfileEventSender::GetInstance().UpdateScoConnectState(dev->addr,
448                     HFP_AG_AUDIO_CONNECT_FAILED_EVT);
449                 break;
450             default:
451                 HILOGI("Invalidaddress: %{public}s, lastParam: %{public}d",
452                     GetEncryptAddr(address).c_str(), dev->lastParam);
453             }
454     } else {
455         // As acceptor, report connect failed event to service directly.
456         HfpAgProfileEventSender::GetInstance().UpdateScoConnectState(dev->addr, HFP_AG_AUDIO_CONNECT_FAILED_EVT);
457         HILOGI("Accept SCO from address: %{public}s failed", GetEncryptAddr(address).c_str());
458     }
459 }
460 
ProcessOnConnectCompleted(HfpScoConnectionCompleteParam parameters)461 void HfpAgAudioConnection::ProcessOnConnectCompleted(HfpScoConnectionCompleteParam parameters)
462 {
463     HILOGI("enter");
464 
465     RawAddress btAddr = RawAddress::ConvertToString(parameters.addr.addr);
466     std::string address = btAddr.GetAddress();
467     auto dev = GetDeviceByAddr(address);
468     if (dev != g_audioDevices.end()) {
469         dev->addr = address;
470         dev->handle = parameters.connectionHandle;
471         if (!parameters.status) {
472             HILOGI("SCO connect successfully!");
473             dev->lastConnectResult = CONNECT_SUCCESS;
474             HfpAgProfileEventSender::GetInstance().UpdateScoConnectState(dev->addr, HFP_AG_AUDIO_CONNECTED_EVT);
475         } else {
476             ProcessOnConnectCompletedFail(dev, address);
477         }
478     } else {
479         HILOGI("%{public}s: Invalid audio device", GetEncryptAddr(address).c_str());
480     }
481 }
482 
OnDisconnectCompleted(const BtmScoDisconnectionCompleteParam * param,void * context)483 void HfpAgAudioConnection::OnDisconnectCompleted(const BtmScoDisconnectionCompleteParam *param, void *context)
484 {
485     HILOGI("enter");
486     HfpScoDisconnectionCompleteParam parameters;
487     parameters.connectionHandle = param->connectionHandle;
488     parameters.reason = param->reason;
489     parameters.status = param->status;
490     if (HfpAgProfileEventSender::GetInstance().GetDispatchter() == nullptr) {
491         HILOGI("GetDispatchter() return nullptr");
492         return;
493     }
494     HfpAgProfileEventSender::GetInstance().GetDispatchter()->PostTask(
495         std::bind(&HfpAgAudioConnection::ProcessOnDisconnectCompleted, parameters));
496 }
497 
ProcessOnDisconnectCompleted(HfpScoDisconnectionCompleteParam parameters)498 void HfpAgAudioConnection::ProcessOnDisconnectCompleted(HfpScoDisconnectionCompleteParam parameters)
499 {
500     HILOGI("enter");
501 
502     auto it = GetDeviceByHandle(parameters.connectionHandle);
503     if (it != g_audioDevices.end()) {
504         if (!parameters.status) {
505             HILOGI("Disconnect SCO from address: %{public}s successfully.", GetEncryptAddr(it->addr).c_str());
506             HfpAgProfileEventSender::GetInstance().UpdateScoConnectState(it->addr, HFP_AG_AUDIO_DISCONNECTED_EVT);
507             g_audioDevices.erase(it);
508         } else {
509             HILOGI("Disconnect SCO from address: %{public}s failed.", GetEncryptAddr(it->addr).c_str());
510             HfpAgProfileEventSender::GetInstance().UpdateScoConnectState(
511                 it->addr, HFP_AG_AUDIO_DISCONNECT_FAILED_EVT);
512         }
513     } else {
514         HILOGI("Invalid audio device");
515     }
516 }
517 
OnConnectionChanged(const BtmScoConnectionChangedParam * param,void * context)518 void HfpAgAudioConnection::OnConnectionChanged(const BtmScoConnectionChangedParam *param, void *context)
519 {
520     HILOGI("enter, connectionHandle: %{public}hu", param->connectionHandle);
521 }
522 
OnWriteVoiceSettingCompleted(uint8_t status,void * context)523 void HfpAgAudioConnection::OnWriteVoiceSettingCompleted(uint8_t status, void *context)
524 {
525     HILOGI("enter, status: %{public}hhu", status);
526 }
527 }  // namespace bluetooth
528 }  // namespace OHOS