• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2025 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 #ifndef LOG_TAG
16 #define LOG_TAG "BluetoothScoManager"
17 #endif
18 
19 #include "bluetooth_sco_manager.h"
20 #include "bluetooth_errorcode.h"
21 #include "audio_errors.h"
22 #include "audio_common_log.h"
23 #include "audio_utils.h"
24 #include "bluetooth_device_utils.h"
25 #include "bluetooth_hfp_interface.h"
26 #include "hisysevent.h"
27 
28 namespace OHOS {
29 namespace Bluetooth {
30 using namespace AudioStandard;
31 
GetInstance()32 BluetoothScoManager &BluetoothScoManager::GetInstance()
33 {
34     static BluetoothScoManager scoManager;
35     return scoManager;
36 }
37 
BluetoothScoManager()38 BluetoothScoManager::BluetoothScoManager()
39 {
40     currentScoDevice_ = BluetoothHfpInterface::GetInstance().GetActiveDevice();
41     currentScoState_ = BluetoothHfpInterface::GetInstance().GetScoState(currentScoDevice_);
42     CHECK_AND_RETURN_LOG(currentScoState_ != AudioScoState::DISCONNECTED, "sco state is disconnected");
43     ScoCategory category = SCO_DEFAULT;
44     int32_t ret = BluetoothHfpInterface::GetInstance().GetCurrentCategory(category);
45     CHECK_AND_RETURN_LOG(ret == SUCCESS, "get sco category failed");
46     currentScoCategory_ = category;
47     AUDIO_INFO_LOG("current sco category %{public}d state %{public}d of device %{public}s",
48         currentScoCategory_, currentScoState_,
49         GetEncryptAddr(currentScoDevice_.GetDeviceAddr()).c_str());
50 }
51 
UpdateScoState(HfpScoConnectState scoState,const BluetoothRemoteDevice & device,int reason)52 void BluetoothScoManager::UpdateScoState(HfpScoConnectState scoState,
53     const BluetoothRemoteDevice &device, int reason)
54 {
55     std::unique_lock<std::mutex> stateLock(scoLock_);
56     AUDIO_INFO_LOG("recv sco %{public}s state of %{public}s device and current sco state %{public}d of %{public}s",
57         scoState == HfpScoConnectState::SCO_DISCONNECTED ? "diconnect" : "connect",
58         GetEncryptAddr(device.GetDeviceAddr()).c_str(), currentScoState_,
59         GetEncryptAddr(currentScoDevice_.GetDeviceAddr()).c_str());
60 
61     if (!IsSameHfpDevice(currentScoDevice_, device)) {
62         WriteScoStateFaultEvent(scoState, device, reason);
63         return;
64     }
65     switch (currentScoState_) {
66         case AudioScoState::DISCONNECTED:
67             UpdateScoStateWhenDisconnected(scoState, device, reason);
68             break;
69         case AudioScoState::CONNECTED:
70             UpdateScoStateWhenConnected(scoState, device, reason);
71             break;
72         case AudioScoState::CONNECTING:
73             UpdateScoStateWhenConnecting(scoState, device, reason);
74             break;
75         case AudioScoState::DISCONNECTING:
76             UpdateScoStateWhenDisconnecting(scoState, device, reason);
77             break;
78         default:
79             break;
80     }
81 }
82 
UpdateScoStateWhenDisconnected(HfpScoConnectState scoState,const BluetoothRemoteDevice & device,int reason)83 void BluetoothScoManager::UpdateScoStateWhenDisconnected(HfpScoConnectState scoState,
84     const BluetoothRemoteDevice &device, int reason)
85 {
86     WriteScoStateFaultEvent(scoState, device, reason);
87     if (scoState == HfpScoConnectState::SCO_CONNECTED) {
88         ForceUpdateScoCategory();
89     }
90 }
91 
UpdateScoStateWhenConnected(HfpScoConnectState scoState,const BluetoothRemoteDevice & device,int reason)92 void BluetoothScoManager::UpdateScoStateWhenConnected(HfpScoConnectState scoState,
93     const BluetoothRemoteDevice &device, int reason)
94 {
95     WriteScoStateFaultEvent(scoState, device, reason);
96     if (scoState == HfpScoConnectState::SCO_DISCONNECTED) {
97         SetAudioScoState(AudioScoState::DISCONNECTED);
98     } else if (scoState == HfpScoConnectState::SCO_CONNECTED) {
99         ScoCategory category = SCO_DEFAULT;
100         int32_t ret = BluetoothHfpInterface::GetInstance().GetCurrentCategory(category);
101         CHECK_AND_RETURN_LOG(ret == SUCCESS, "get sco category failed");
102         if (currentScoCategory_ != category) {
103             AUDIO_INFO_LOG("update sco category from %{public}d to %{public}d of device %{public}s",
104                 currentScoCategory_, category,
105                 GetEncryptAddr(currentScoDevice_.GetDeviceAddr()).c_str());
106             currentScoCategory_ = category;
107         }
108     }
109 }
110 
UpdateScoStateWhenConnecting(HfpScoConnectState scoState,const BluetoothRemoteDevice & device,int reason)111 void BluetoothScoManager::UpdateScoStateWhenConnecting(HfpScoConnectState scoState,
112     const BluetoothRemoteDevice &device, int reason)
113 {
114     if (scoState == HfpScoConnectState::SCO_DISCONNECTED) {
115         WriteScoStateFaultEvent(scoState, device, reason);
116         SetAudioScoState(AudioScoState::DISCONNECTED);
117     } else if (scoState == HfpScoConnectState::SCO_CONNECTED) {
118         SetAudioScoState(AudioScoState::CONNECTED);
119     }
120     ProcCacheRequest();
121 }
122 
UpdateScoStateWhenDisconnecting(HfpScoConnectState scoState,const BluetoothRemoteDevice & device,int reason)123 void BluetoothScoManager::UpdateScoStateWhenDisconnecting(HfpScoConnectState scoState,
124     const BluetoothRemoteDevice &device, int reason)
125 {
126     if (scoState == HfpScoConnectState::SCO_DISCONNECTED) {
127         SetAudioScoState(AudioScoState::DISCONNECTED);
128     } else if (scoState == HfpScoConnectState::SCO_CONNECTED) {
129         WriteScoStateFaultEvent(scoState, device, reason);
130         ForceUpdateScoCategory();
131     }
132     ProcCacheRequest();
133 }
134 
WriteScoStateFaultEvent(HfpScoConnectState scoState,const BluetoothRemoteDevice & device,int reason)135 void BluetoothScoManager::WriteScoStateFaultEvent(HfpScoConnectState scoState,
136     const BluetoothRemoteDevice &device, int reason)
137 {
138     auto ret = HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::AUDIO, "SCO_STATE_BT",
139         HiviewDFX::HiSysEvent::EventType::FAULT,
140         "SCO_STATE", static_cast<uint8_t>(currentScoState_),
141         "REASON", static_cast<uint8_t>(reason),
142         "SCO_ADDRESS", device.GetDeviceAddr());
143     if (ret) {
144         AUDIO_ERR_LOG("write event fail: SCO_STATE_BT, ret = %{public}d", ret);
145     }
146 }
147 
ForceUpdateScoCategory()148 void BluetoothScoManager::ForceUpdateScoCategory()
149 {
150     // need query sco type from bluetooth to refresh local
151     ScoCategory category = SCO_DEFAULT;
152     int32_t ret = BluetoothHfpInterface::GetInstance().GetCurrentCategory(category);
153     CHECK_AND_RETURN_LOG(ret == SUCCESS, "get sco category failed");
154     AUDIO_INFO_LOG("force update sco category from %{public}d to %{public}d of device %{public}s",
155         currentScoCategory_, category,
156         GetEncryptAddr(currentScoDevice_.GetDeviceAddr()).c_str());
157     currentScoCategory_ = category;
158     SetAudioScoState(AudioScoState::CONNECTED);
159 }
160 
ProcCacheRequest()161 void BluetoothScoManager::ProcCacheRequest()
162 {
163     std::shared_ptr<ScoCacheRequest> req = nullptr;
164     {
165         req = cacheReq_;
166         cacheReq_ = nullptr;
167     }
168     if (req == nullptr) {
169         return;
170     }
171 
172     AUDIO_INFO_LOG("proc cache %{public}s request category %{public}d and current sco state %{public}d",
173         req->connectReq ? "connect" : "disconnect", req->category, currentScoState_);
174     if (req->connectReq) {
175         HandleScoConnectNoLock(req->category, req->device);
176     } else {
177         HandleScoDisconnectNoLock(req->device);
178     }
179 }
180 
HandleScoConnect(ScoCategory scoCategory,const BluetoothRemoteDevice & device)181 int32_t BluetoothScoManager::HandleScoConnect(ScoCategory scoCategory,
182     const BluetoothRemoteDevice &device)
183 {
184     std::lock_guard<std::mutex> stateLock(scoLock_);
185     return HandleScoConnectNoLock(scoCategory, device);
186 }
187 
HandleScoConnectNoLock(ScoCategory scoCategory,const BluetoothRemoteDevice & device)188 int32_t BluetoothScoManager::HandleScoConnectNoLock(ScoCategory scoCategory,
189     const BluetoothRemoteDevice &device)
190 {
191     int32_t ret = SUCCESS;
192     switch (currentScoState_) {
193         case AudioScoState::DISCONNECTED:
194             ret = ProcConnectReqWhenDisconnected(scoCategory, device);
195             break;
196         case AudioScoState::CONNECTED:
197             ret = ProcConnectReqWhenConnected(scoCategory, device);
198             break;
199         case AudioScoState::CONNECTING:
200             ret = ProcConnectReqWhenConnecting(scoCategory, device);
201             break;
202         case AudioScoState::DISCONNECTING:
203             ret = SaveRequestToCache(true, scoCategory, device, "connect request when disconnecting");
204             break;
205         default:
206             ret = ERROR;
207             break;
208     }
209     return ret;
210 }
211 
ProcConnectReqWhenDisconnected(ScoCategory scoCategory,const BluetoothRemoteDevice & device)212 int32_t BluetoothScoManager::ProcConnectReqWhenDisconnected(ScoCategory scoCategory,
213     const BluetoothRemoteDevice &device)
214 {
215     int32_t ret = ConnectSco(scoCategory, device);
216     if (ret == BT_ERR_SCO_HAS_BEEN_CONNECTED) {
217         AUDIO_WARNING_LOG("category %{public}d has been connected", scoCategory);
218         SetAudioScoState(AudioScoState::CONNECTED);
219     } else if (ret != 0) {
220         AUDIO_ERR_LOG("connect scoCategory: %{public}d ret: %{public}d ", scoCategory, ret);
221         int32_t restoreRet = TryRestoreHfpDevice(scoCategory, device);
222         CHECK_AND_RETURN_RET_LOG(restoreRet == 0, restoreRet, "try restore hfp device failed");
223         SetAudioScoState(AudioScoState::CONNECTING);
224     } else {
225         AUDIO_INFO_LOG("connect scoCategory: %{public}d success ", scoCategory);
226         SetAudioScoState(AudioScoState::CONNECTING);
227     }
228     currentScoCategory_ = scoCategory;
229     currentScoDevice_ = device;
230     return SUCCESS;
231 }
232 
ProcConnectReqWhenConnected(ScoCategory scoCategory,const BluetoothRemoteDevice & device)233 int32_t BluetoothScoManager::ProcConnectReqWhenConnected(ScoCategory scoCategory,
234     const BluetoothRemoteDevice &device)
235 {
236     bool isSameDevice = IsSameHfpDevice(currentScoDevice_, device);
237     if (!IsNeedSwitchScoCategory(scoCategory) && isSameDevice) {
238         AUDIO_INFO_LOG("bypass connect category %{public}d current category %{public}d for device %{public}s",
239             scoCategory, currentScoCategory_, GetEncryptAddr(device.GetDeviceAddr()).c_str());
240         return SUCCESS;
241     }
242 
243     AUDIO_INFO_LOG("connect category %{public}d current %{public}d for device %{public}s current %{public}s",
244         scoCategory, currentScoCategory_, GetEncryptAddr(device.GetDeviceAddr()).c_str(),
245         GetEncryptAddr(currentScoDevice_.GetDeviceAddr()).c_str());
246     int32_t ret = DisconnectScoReliable(currentScoCategory_, currentScoDevice_);
247     if (ret != 0) {
248         SetAudioScoState(AudioScoState::DISCONNECTED);
249         return ProcConnectReqWhenDisconnected(scoCategory, device);
250     }
251 
252     SetAudioScoState(AudioScoState::DISCONNECTING);
253     return SaveRequestToCache(true, scoCategory, device, "ProcConnectReqWhenConnected");
254 }
255 
ProcConnectReqWhenConnecting(ScoCategory scoCategory,const BluetoothRemoteDevice & device)256 int32_t BluetoothScoManager::ProcConnectReqWhenConnecting(ScoCategory scoCategory,
257     const BluetoothRemoteDevice &device)
258 {
259     bool isSameDevice = IsSameHfpDevice(currentScoDevice_, device);
260     if (!IsNeedSwitchScoCategory(scoCategory) && isSameDevice) {
261         AUDIO_INFO_LOG("connect category %{public}d current category %{public}d for device %{public}s",
262             scoCategory, currentScoCategory_, GetEncryptAddr(device.GetDeviceAddr()).c_str());
263         return SUCCESS;
264     }
265     return SaveRequestToCache(true, scoCategory, device, "ProcConnectReqWhenConnecting");
266 }
267 
IsNeedSwitchScoCategory(ScoCategory scoCategory)268 bool BluetoothScoManager::IsNeedSwitchScoCategory(ScoCategory scoCategory)
269 {
270     if (scoCategory == currentScoCategory_) {
271         return false;
272     }
273 
274     if ((currentScoCategory_ == ScoCategory::SCO_DEFAULT &&
275         scoCategory == ScoCategory::SCO_VIRTUAL) ||
276         (currentScoCategory_ == ScoCategory::SCO_VIRTUAL &&
277         scoCategory == ScoCategory::SCO_DEFAULT)) {
278         return false;
279     }
280     return true;
281 }
282 
HandleScoDisconnect(const BluetoothRemoteDevice & device)283 int32_t BluetoothScoManager::HandleScoDisconnect(const BluetoothRemoteDevice &device)
284 {
285     std::lock_guard<std::mutex> stateLock(scoLock_);
286     return HandleScoDisconnectNoLock(device);
287 }
288 
HandleScoDisconnectNoLock(const BluetoothRemoteDevice & device)289 int32_t BluetoothScoManager::HandleScoDisconnectNoLock(const BluetoothRemoteDevice &device)
290 {
291     int32_t ret = SUCCESS;
292     switch (currentScoState_) {
293         case AudioScoState::DISCONNECTED:
294         case AudioScoState::DISCONNECTING:
295             cacheReq_ = nullptr;
296             break;
297         case AudioScoState::CONNECTED:
298             ret = ProcDisconnectReqWhenConnected(device);
299             break;
300         case AudioScoState::CONNECTING:
301             ret = ProcDisconnectReqWhenConnecting(device);
302             break;
303         default:
304             ret = ERROR;
305             break;
306     }
307     return ret;
308 }
309 
ProcDisconnectReqWhenConnected(const BluetoothRemoteDevice & device)310 int32_t BluetoothScoManager::ProcDisconnectReqWhenConnected(const BluetoothRemoteDevice &device)
311 {
312     if (!IsSameHfpDevice(currentScoDevice_, device)) {
313         AUDIO_WARNING_LOG("disconnect device %{public}s but current is %{public}s",
314             GetEncryptAddr(device.GetDeviceAddr()).c_str(),
315             GetEncryptAddr(currentScoDevice_.GetDeviceAddr()).c_str());
316     }
317     cacheReq_ = nullptr;
318     int32_t ret = DisconnectScoReliable(currentScoCategory_, currentScoDevice_);
319     if (ret != 0) {
320         SetAudioScoState(AudioScoState::DISCONNECTED);
321     } else {
322         SetAudioScoState(AudioScoState::DISCONNECTING);
323     }
324     return SUCCESS;
325 }
326 
ProcDisconnectReqWhenConnecting(const BluetoothRemoteDevice & device)327 int32_t BluetoothScoManager::ProcDisconnectReqWhenConnecting(const BluetoothRemoteDevice &device)
328 {
329     if (!IsSameHfpDevice(currentScoDevice_, device)) {
330         AUDIO_WARNING_LOG("disconnect device %{public}s but current is %{public}s",
331             GetEncryptAddr(device.GetDeviceAddr()).c_str(),
332             GetEncryptAddr(currentScoDevice_.GetDeviceAddr()).c_str());
333     }
334     cacheReq_ = nullptr;
335     return SaveRequestToCache(false, currentScoCategory_, device, "ProcDisconnectReqWhenConnecting");
336 }
337 
SaveRequestToCache(bool isConnect,ScoCategory scoCategory,const BluetoothRemoteDevice & device,const std::string & reason)338 int32_t BluetoothScoManager::SaveRequestToCache(bool isConnect, ScoCategory scoCategory,
339     const BluetoothRemoteDevice &device, const std::string &reason)
340 {
341     if (cacheReq_ == nullptr) {
342         cacheReq_ = std::make_shared<ScoCacheRequest>();
343     } else {
344         if (cacheReq_->connectReq == isConnect && cacheReq_->category == scoCategory &&
345             IsSameHfpDevice(cacheReq_->device, device)) {
346             return SUCCESS;
347         }
348     }
349     CHECK_AND_RETURN_RET_LOG(cacheReq_ != nullptr, ERROR, "request cache is nullptr");
350     cacheReq_->connectReq = isConnect;
351     cacheReq_->category = scoCategory;
352     cacheReq_->device = device;
353     AUDIO_INFO_LOG("%{public}s cache request, scoCategory: %{public}d isConnect: %{public}d",
354         reason.c_str(), scoCategory, isConnect);
355     return SUCCESS;
356 }
357 
IsSameHfpDevice(const BluetoothRemoteDevice & device1,const BluetoothRemoteDevice & device2)358 bool BluetoothScoManager::IsSameHfpDevice(const BluetoothRemoteDevice &device1,
359     const BluetoothRemoteDevice &device2)
360 {
361     return device1.GetDeviceAddr() == device2.GetDeviceAddr();
362 }
363 
ConnectSco(ScoCategory scoCategory,const BluetoothRemoteDevice & device)364 int32_t BluetoothScoManager::ConnectSco(ScoCategory scoCategory, const BluetoothRemoteDevice &device)
365 {
366     int32_t ret = ERROR;
367     if (scoCategory == ScoCategory::SCO_RECOGNITION) {
368         ret = BluetoothHfpInterface::GetInstance().OpenVoiceRecognition(device);
369     } else {
370         if (scoCategory == ScoCategory::SCO_DEFAULT) {
371             scoCategory = ScoCategory::SCO_VIRTUAL;
372         }
373         ret = BluetoothHfpInterface::GetInstance().ConnectSco(static_cast<uint8_t>(scoCategory));
374     }
375     return ret;
376 }
377 
TryRestoreHfpDevice(ScoCategory scoCategory,const BluetoothRemoteDevice & device)378 int32_t BluetoothScoManager::TryRestoreHfpDevice(ScoCategory scoCategory, const BluetoothRemoteDevice &device)
379 {
380     int32_t ret = BluetoothHfpInterface::GetInstance().SetActiveDevice(device);
381     CHECK_AND_RETURN_RET_LOG(ret == 0, ret, "set active hfp device failed");
382     return ConnectSco(scoCategory, device);
383 }
384 
DisconnectSco(ScoCategory scoCategory,const BluetoothRemoteDevice & device)385 int32_t BluetoothScoManager::DisconnectSco(ScoCategory scoCategory, const BluetoothRemoteDevice &device)
386 {
387     int32_t ret = ERROR;
388     if (scoCategory == ScoCategory::SCO_RECOGNITION) {
389         ret = BluetoothHfpInterface::GetInstance().CloseVoiceRecognition(device);
390     } else {
391         if (scoCategory == ScoCategory::SCO_DEFAULT) {
392             scoCategory = SCO_VIRTUAL;
393         }
394         ret = BluetoothHfpInterface::GetInstance().DisconnectSco(static_cast<uint8_t>(scoCategory));
395     }
396 
397     return ret;
398 }
399 
DisconnectScoReliable(ScoCategory scoCategory,const BluetoothRemoteDevice & device)400 int32_t BluetoothScoManager::DisconnectScoReliable(ScoCategory scoCategory, const BluetoothRemoteDevice &device)
401 {
402     int32_t ret = DisconnectSco(scoCategory, device);
403     if (ret == BT_ERR_VIRTUAL_CALL_NOT_STARTED) {
404         // try to get current category form bluetooth
405         AUDIO_WARNING_LOG("DisconnectSco, scoCategory: %{public}d failed", scoCategory);
406         ScoCategory tmp = SCO_DEFAULT;
407         ret = BluetoothHfpInterface::GetInstance().GetCurrentCategory(tmp);
408         CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "get sco category failed");
409         ret = DisconnectSco(tmp, device);
410         AUDIO_INFO_LOG("DisconnectSco, scoCategory: %{public}d ret: %{public}d", tmp, ret);
411     } else if (ret != 0) {
412         AUDIO_ERR_LOG("DisconnectSco, scoCategory: %{public}d ret: %{public}d", scoCategory, ret);
413     } else {
414         AUDIO_INFO_LOG("DisconnectSco, scoCategory: %{public}d success", scoCategory);
415     }
416     return ret;
417 }
418 
GetAudioScoState()419 AudioScoState BluetoothScoManager::GetAudioScoState()
420 {
421     std::lock_guard<std::mutex> stateLock(scoLock_);
422     return currentScoState_;
423 }
424 
GetAudioScoCategory()425 ScoCategory BluetoothScoManager::GetAudioScoCategory()
426 {
427     std::lock_guard<std::mutex> stateLock(scoLock_);
428     return currentScoCategory_;
429 }
430 
ResetScoState(const BluetoothRemoteDevice & device)431 void BluetoothScoManager::ResetScoState(const BluetoothRemoteDevice &device)
432 {
433     std::lock_guard<std::mutex> stateLock(scoLock_);
434     if (!IsSameHfpDevice(currentScoDevice_, device)) {
435         AUDIO_WARNING_LOG("reset device %{public}s but current is %{public}s",
436             GetEncryptAddr(device.GetDeviceAddr()).c_str(),
437             GetEncryptAddr(currentScoDevice_.GetDeviceAddr()).c_str());
438         return;
439     }
440 
441     cacheReq_ = nullptr;
442     SetAudioScoState(AudioScoState::DISCONNECTED);
443     currentScoDevice_ = BluetoothRemoteDevice();
444 }
445 
SetAudioScoState(AudioScoState state)446 void BluetoothScoManager::SetAudioScoState(AudioScoState state)
447 {
448     if (currentScoState_ == state) {
449         return;
450     }
451     currentScoState_ = state;
452     if (currentScoState_ == AudioScoState::CONNECTING ||
453         currentScoState_ == AudioScoState::DISCONNECTING) {
454         if (scoTimer_ != nullptr) {
455             scoTimer_->StopTimer();
456         } else {
457             scoTimer_ = std::make_shared<AudioTimer>(std::bind(
458                 &BluetoothScoManager::OnScoStateTimeOut, this));
459             if (scoTimer_ == nullptr) {
460                 AUDIO_ERR_LOG("create audio timer failed");
461                 return;
462             }
463         }
464         scoTimer_->StartTimer(scoStateDuration_);
465         AUDIO_DEBUG_LOG("start timer for state %{public}d", currentScoState_);
466     } else {
467         scoTimer_ = nullptr;
468         AUDIO_DEBUG_LOG("delete timer for state %{public}d", currentScoState_);
469     }
470 }
471 
OnScoStateTimeOut()472 void BluetoothScoManager::OnScoStateTimeOut()
473 {
474     std::lock_guard<std::mutex> stateLock(scoLock_);
475     AUDIO_ERR_LOG("scoCategory: %{public}d state: %{public}d time out",
476         currentScoCategory_, currentScoState_);
477 }
478 
GetAudioScoDevice()479 BluetoothRemoteDevice BluetoothScoManager::GetAudioScoDevice()
480 {
481     std::lock_guard<std::mutex> stateLock(scoLock_);
482     return currentScoDevice_;
483 }
484 
IsInScoCategory(ScoCategory scoCategory)485 bool BluetoothScoManager::IsInScoCategory(ScoCategory scoCategory)
486 {
487     std::lock_guard<std::mutex> stateLock(scoLock_);
488     return (currentScoCategory_ == scoCategory) &&
489         (currentScoState_ == AudioScoState::CONNECTING ||
490         currentScoState_ == AudioScoState::CONNECTED);
491 }
492 } // Bluetooth
493 } // OHOS