• 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 
16 #include <thread>
17 #include <pthread.h>
18 
19 #include "distributed_call_manager.h"
20 #include "audio_control_manager.h"
21 #include "call_object_manager.h"
22 #include "telephony_log_wrapper.h"
23 #include "nlohmann/json.hpp"
24 #include "i_distributed_device_callback.h"
25 #ifdef ABILITY_BLUETOOTH_SUPPORT
26 #include "bluetooth_device.h"
27 #endif
28 
29 using json = nlohmann::json;
30 
31 namespace OHOS {
32 namespace Telephony {
33 using namespace AudioStandard;
34 namespace {
35 const size_t INT32_MIN_ID_LENGTH = 3;
36 const size_t INT32_SHORT_ID_LENGTH = 20;
37 const size_t INT32_PLAINTEXT_LENGTH = 4;
38 const int32_t DCALL_SWITCH_DEVICE_TYPE_SOURCE = 0;
39 const int32_t DCALL_SWITCH_DEVICE_TYPE_SINK = 1;
40 const int32_t DISTRIBUTED_CALL_SOURCE_SA_ID = 9855;
41 const int32_t IS_CELIA_CALL = 1;
42 const int32_t DEFAULT_DCALL_HFP_FLAG_VALUE = -1;
43 const int32_t DCALL_BT_HEADSET_UNWEAR_ACTION = 1;
44 const std::string CALLBACK_NAME = "telephony";
45 const std::string DISTRIBUTED_AUDIO_DEV_CAR = "dCar";
46 const std::string DISTRIBUTED_AUDIO_DEV_PHONE = "dPhone";
47 const std::string DISTRIBUTED_AUDIO_DEV_PAD = "dPad";
48 const std::string SWITCH_ON_DCALL_THREAD_NAME = "switch on dcall";
49 
GetAnonyString(const std::string & value)50 std::string GetAnonyString(const std::string &value)
51 {
52     std::string res;
53     std::string tmpStr("******");
54     size_t strLen = value.length();
55     if (strLen < INT32_MIN_ID_LENGTH) {
56         return tmpStr;
57     }
58     if (strLen <= INT32_SHORT_ID_LENGTH) {
59         res += value[0];
60         res += tmpStr;
61         res += value[strLen - 1];
62     } else {
63         res.append(value, 0, INT32_PLAINTEXT_LENGTH);
64         res += tmpStr;
65         res.append(value, strLen - INT32_PLAINTEXT_LENGTH, INT32_PLAINTEXT_LENGTH);
66     }
67     return res;
68 }
69 
IsDistributedAudioDevice(const AudioDevice & device)70 bool IsDistributedAudioDevice(const AudioDevice& device)
71 {
72     if ((device.deviceType == AudioDeviceType::DEVICE_DISTRIBUTED_PHONE) ||
73         (device.deviceType == AudioDeviceType::DEVICE_DISTRIBUTED_PAD) ||
74         (device.deviceType == AudioDeviceType::DEVICE_DISTRIBUTED_AUTOMOTIVE)) {
75         return true;
76     }
77     return false;
78 }
79 }
80 
DistributedCallManager()81 DistributedCallManager::DistributedCallManager()
82 {
83     TELEPHONY_LOGI("DistributedCallManager constructed.");
84 }
85 
~DistributedCallManager()86 DistributedCallManager::~DistributedCallManager()
87 {
88     TELEPHONY_LOGI("DistributedCallManager destructed.");
89 }
90 
Init()91 void DistributedCallManager::Init()
92 {
93     TELEPHONY_LOGI("Init start.");
94     statusChangeListener_ = new (std::nothrow) DCallSystemAbilityListener();
95     if (statusChangeListener_ == nullptr) {
96         TELEPHONY_LOGE("failed to create statusChangeListener");
97         return;
98     }
99     auto managerPtr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
100     if (managerPtr == nullptr) {
101         TELEPHONY_LOGE("get system ability manager error");
102         return;
103     }
104     int32_t ret = managerPtr->SubscribeSystemAbility(DISTRIBUTED_CALL_SOURCE_SA_ID, statusChangeListener_);
105     if (ret != TELEPHONY_SUCCESS) {
106         TELEPHONY_LOGE("failed to subscribe dcall service SA: %{public}d", DISTRIBUTED_CALL_SOURCE_SA_ID);
107         return;
108     }
109     TELEPHONY_LOGI("Init end.");
110 }
111 
CreateDAudioDevice(const std::string & devId,AudioDevice & device)112 bool DistributedCallManager::CreateDAudioDevice(const std::string& devId, AudioDevice& device)
113 {
114     if (!devId.length()) {
115         TELEPHONY_LOGE("dcall devId is invalid");
116         return false;
117     }
118     OHOS::DistributedHardware::DCallDeviceInfo devInfo;
119     {
120         std::lock_guard<std::mutex> lock(dcallProxyMtx_);
121         if (dcallProxy_ == nullptr) {
122             TELEPHONY_LOGE("dcallProxy_ is nullptr");
123             return false;
124         }
125         int32_t ret = dcallProxy_->GetDCallDeviceInfo(devId, devInfo);
126         if (ret != TELEPHONY_SUCCESS) {
127             TELEPHONY_LOGI("get dcall device info failed.");
128             return false;
129         }
130     }
131     std::string devTypeName;
132     std::string devName = devInfo.devName;
133     if (devInfo.devType == OHOS::DistributedHardware::DCallDeviceType::DISTRIBUTED_DEVICE_PHONE) {
134         devTypeName = DISTRIBUTED_AUDIO_DEV_PHONE;
135         device.deviceType = AudioDeviceType::DEVICE_DISTRIBUTED_PHONE;
136     } else if (devInfo.devType == OHOS::DistributedHardware::DCallDeviceType::DISTRIBUTED_DEVICE_PAD) {
137         devTypeName = DISTRIBUTED_AUDIO_DEV_PAD;
138         device.deviceType = AudioDeviceType::DEVICE_DISTRIBUTED_PAD;
139     } else {
140         devTypeName = DISTRIBUTED_AUDIO_DEV_CAR;
141         device.deviceType = AudioDeviceType::DEVICE_DISTRIBUTED_AUTOMOTIVE;
142     }
143     json addressJson;
144     addressJson["devName"] = devName;
145     addressJson["devId"] = devId;
146     std::string addressStr = addressJson.dump();
147     if (memcpy_s(device.address, kMaxAddressLen, addressStr.c_str(), addressStr.length()) != EOK) {
148         TELEPHONY_LOGE("memcpy_s failed.");
149         return false;
150     }
151     TELEPHONY_LOGI("create distributed audio device succeed.");
152     return true;
153 }
154 
GetDevIdFromAudioDevice(const AudioDevice & device)155 std::string DistributedCallManager::GetDevIdFromAudioDevice(const AudioDevice& device)
156 {
157     std::string devId = "";
158     if (!IsDistributedAudioDevice(device)) {
159         TELEPHONY_LOGE("not distributed audio device, device type: %{public}d", device.deviceType);
160         return devId;
161     }
162     std::string address = device.address;
163     if (!address.length()) {
164         TELEPHONY_LOGE("invalid address");
165         return devId;
166     }
167     json addressJson = json::parse(address, nullptr, false);
168     if (addressJson.is_null() || addressJson.is_discarded()) {
169         TELEPHONY_LOGE("json value is null or discarded.");
170         return devId;
171     }
172     if (!addressJson.contains("devId")) {
173         TELEPHONY_LOGE("json not contain devId.");
174         return devId;
175     }
176     if (!addressJson["devId"].is_string()) {
177         TELEPHONY_LOGE("json has no devId string.");
178         return devId;
179     }
180     devId = addressJson["devId"];
181     TELEPHONY_LOGI("devId: %{public}s", GetAnonyString(devId).c_str());
182     return devId;
183 }
184 
AddDCallDevice(const std::string & devId)185 int32_t DistributedCallManager::AddDCallDevice(const std::string& devId)
186 {
187     TELEPHONY_LOGI("add dcall device, devId: %{public}s.", GetAnonyString(devId).c_str());
188 #ifdef ABILITY_BLUETOOTH_SUPPORT
189     {
190         std::lock_guard<std::mutex> lock(mutex_);
191         if (dcallHfpListener_ == nullptr) {
192             dcallHfpListener_ = std::make_shared<DCallHfpListener>();
193             Bluetooth::HandsFreeAudioGateway::GetProfile()->RegisterObserver(dcallHfpListener_);
194         }
195     }
196 #endif
197     std::lock_guard<std::mutex> lock(onlineDeviceMtx_);
198 
199     auto iter = onlineDCallDevices_.find(devId);
200     if (iter != onlineDCallDevices_.end()) {
201         TELEPHONY_LOGW("device is already exist, devId: %{public}s", GetAnonyString(devId).c_str());
202         return TELEPHONY_SUCCESS;
203     }
204 
205     AudioDevice device;
206     if (!CreateDAudioDevice(devId, device)) {
207         TELEPHONY_LOGE("failed to create distributed audio device, devId: %{public}s", GetAnonyString(devId).c_str());
208         return TELEPHONY_ERR_FAIL;
209     }
210 
211     DelayedSingleton<AudioDeviceManager>::GetInstance()->AddAudioDeviceList(device.address, device.deviceType, "");
212     onlineDCallDevices_.emplace(devId, device);
213 
214     if (!dCallDeviceSwitchedOn_.load() && isCallActived_.load()) {
215         if (device.deviceType == AudioDeviceType::DEVICE_DISTRIBUTED_AUTOMOTIVE && IsSelectVirtualModem()) {
216             TELEPHONY_LOGI("switch call to auto motive as it is online");
217             SwitchOnDCallDeviceAsync(device);
218         }
219     }
220     return TELEPHONY_SUCCESS;
221 }
222 
RemoveDCallDevice(const std::string & devId)223 int32_t DistributedCallManager::RemoveDCallDevice(const std::string& devId)
224 {
225     TELEPHONY_LOGI("remove dcall device, devId: %{public}s.", GetAnonyString(devId).c_str());
226     std::lock_guard<std::mutex> lock(onlineDeviceMtx_);
227     auto iter = onlineDCallDevices_.find(devId);
228     if (iter != onlineDCallDevices_.end()) {
229         std::string devId = GetDevIdFromAudioDevice(iter->second);
230         std::string curDevId = GetConnectedDCallDeviceId();
231         TELEPHONY_LOGI("removed devId: %{public}s, current devId: %{public}s",
232             GetAnonyString(devId).c_str(), GetAnonyString(curDevId).c_str());
233         DelayedSingleton<AudioDeviceManager>::GetInstance()->RemoveAudioDeviceList(
234             iter->second.address, iter->second.deviceType);
235         onlineDCallDevices_.erase(iter);
236         if (curDevId == devId) {
237             TELEPHONY_LOGI("current dcall device is removed, now reinit audio device.");
238             dCallDeviceSwitchedOn_.store(false);
239             ClearConnectedDCallDevice();
240             DelayedSingleton<AudioDeviceManager>::GetInstance()->InitAudioDevice();
241         }
242     }
243     return TELEPHONY_SUCCESS;
244 }
245 
ClearDCallDevices()246 void DistributedCallManager::ClearDCallDevices()
247 {
248     TELEPHONY_LOGI("clear dcall device.");
249     std::lock_guard<std::mutex> lock(onlineDeviceMtx_);
250     onlineDCallDevices_.clear();
251 }
252 
NotifyOnlineDCallDevices(std::vector<std::string> devices)253 void DistributedCallManager::NotifyOnlineDCallDevices(std::vector<std::string> devices)
254 {
255     TELEPHONY_LOGI("notify online dcall devices start, size: %{public}d", static_cast<int32_t>(devices.size()));
256     for (auto item : devices) {
257         AddDCallDevice(item);
258         TELEPHONY_LOGI("notify dcall device, devId: %{public}s", GetAnonyString(item).c_str());
259     }
260     TELEPHONY_LOGI("notify online dcall devices end.");
261 }
262 
GetConnectedDCallDeviceAddr()263 std::string DistributedCallManager::GetConnectedDCallDeviceAddr()
264 {
265     std::lock_guard<std::mutex> lock(connectedDevMtx_);
266     std::string addr = connectedAudioDevice_.address;
267     return addr;
268 }
269 
GetConnectedDCallDeviceType()270 AudioDeviceType DistributedCallManager::GetConnectedDCallDeviceType()
271 {
272     std::lock_guard<std::mutex> lock(connectedDevMtx_);
273     AudioDeviceType type = connectedAudioDevice_.deviceType;
274     return type;
275 }
276 
GetConnectedDCallDeviceId()277 std::string DistributedCallManager::GetConnectedDCallDeviceId()
278 {
279     std::lock_guard<std::mutex> lock(connectedDevMtx_);
280     std::string devId = "";
281     if (dCallDeviceSwitchedOn_.load()) {
282         devId = GetDevIdFromAudioDevice(connectedAudioDevice_);
283     }
284     return devId;
285 }
286 
GetConnectedDCallDevice(AudioDevice & device)287 void DistributedCallManager::GetConnectedDCallDevice(AudioDevice& device)
288 {
289     std::lock_guard<std::mutex> lock(connectedDevMtx_);
290     device.deviceType = connectedAudioDevice_.deviceType;
291     if (memcpy_s(device.address, kMaxAddressLen, connectedAudioDevice_.address, kMaxAddressLen) != EOK) {
292         TELEPHONY_LOGE("memcpy_s failed.");
293     }
294 }
295 
SetConnectedDCallDevice(const AudioDevice & device)296 void DistributedCallManager::SetConnectedDCallDevice(const AudioDevice& device)
297 {
298     std::lock_guard<std::mutex> lock(connectedDevMtx_);
299     connectedAudioDevice_.deviceType = device.deviceType;
300     if (memcpy_s(connectedAudioDevice_.address, kMaxAddressLen, device.address, kMaxAddressLen) != EOK) {
301         TELEPHONY_LOGE("memcpy_s failed.");
302     }
303 }
304 
ClearConnectedDCallDevice()305 void DistributedCallManager::ClearConnectedDCallDevice()
306 {
307     std::lock_guard<std::mutex> lock(connectedDevMtx_);
308     connectedAudioDevice_.deviceType = AudioDeviceType::DEVICE_UNKNOWN;
309     if (memset_s(connectedAudioDevice_.address, kMaxAddressLen, 0, kMaxAddressLen) != EOK) {
310         TELEPHONY_LOGE("memset_s failed.");
311     }
312 }
313 
SwitchOnDCallDeviceSync(const AudioDevice & device)314 bool DistributedCallManager::SwitchOnDCallDeviceSync(const AudioDevice& device)
315 {
316     TELEPHONY_LOGI("switch dcall device on sync");
317     if (!isCallActived_.load()) {
318         TELEPHONY_LOGW("call is not active, no need switch");
319         return true;
320     }
321     if (!IsDistributedAudioDevice(device)) {
322         TELEPHONY_LOGE("not distributed audio device, device type: %{public}d", device.deviceType);
323         return false;
324     }
325     std::string devId = GetDevIdFromAudioDevice(device);
326     if (!devId.length()) {
327         TELEPHONY_LOGE("dcall devId is invalid");
328         return false;
329     }
330     TELEPHONY_LOGI("switch dcall device on start, devId: %{public}s", GetAnonyString(devId).c_str());
331     int32_t ret;
332     {
333         std::lock_guard<std::mutex> lock(dcallProxyMtx_);
334         if (dcallProxy_ == nullptr) {
335             TELEPHONY_LOGE("dcallProxy_ is nullptr");
336             return false;
337         }
338         if (isSwitching_) {
339             TELEPHONY_LOGI("in switching");
340             return false;
341         }
342         isSwitching_ = true;
343         ReportDistributedDeviceInfo(device);
344         ret = dcallProxy_->SwitchDevice(devId, DCALL_SWITCH_DEVICE_TYPE_SINK);
345         isSwitching_ = false;
346     }
347     if (ret == TELEPHONY_SUCCESS) {
348         dCallDeviceSwitchedOn_.store(true);
349         SetConnectedDCallDevice(device);
350         DelayedSingleton<AudioDeviceManager>::GetInstance()->SetCurrentAudioDevice(device.deviceType);
351         TELEPHONY_LOGI("switch dcall device on succeed.");
352         return true;
353     }
354     TELEPHONY_LOGI("switch dcall device on failed, ret: %{public}d.", ret);
355     return false;
356 }
357 
SetCallState(bool isActive)358 void DistributedCallManager::SetCallState(bool isActive)
359 {
360     isCallActived_.store(isActive);
361 }
362 
DealDisconnectCall()363 void DistributedCallManager::DealDisconnectCall()
364 {
365     dCallDeviceSwitchedOn_.store(false);
366     ClearConnectedDCallDevice();
367 }
368 
IsDistributedCarDeviceOnline()369 bool DistributedCallManager::IsDistributedCarDeviceOnline()
370 {
371     if (onlineDCallDevices_.size() > 0) {
372         return true;
373     }
374     return false;
375 }
376 
isCeliaCall()377 bool DistributedCallManager::isCeliaCall()
378 {
379     sptr<CallBase> foregroundCall = CallObjectManager::GetForegroundCall(false);
380     if (foregroundCall == nullptr) {
381         TELEPHONY_LOGE("foregroundCall is nullptr!");
382         return false;
383     }
384     int32_t celiaCallType = foregroundCall->GetCeliaCallType();
385     if (celiaCallType == IS_CELIA_CALL) {
386         TELEPHONY_LOGI("current is celia call, no need switch on dcall device.");
387         return true;
388     }
389     return false;
390 }
391 
SwitchOnDCallDeviceAsync(const AudioDevice & device)392 void DistributedCallManager::SwitchOnDCallDeviceAsync(const AudioDevice& device)
393 {
394     if (isCeliaCall()) {
395         return;
396     }
397     auto weak = weak_from_this();
398     TELEPHONY_LOGI("switch dcall device on async");
399     std::thread switchThread = std::thread([weak, device]() {
400         auto strong = weak.lock();
401         if (strong) {
402             strong->SwitchOnDCallDeviceSync(device);
403             if (strong->isCeliaCall()) {
404                 strong->SwitchOffDCallDeviceSync();
405                 strong->ReportDistributedDeviceInfoForSwitchOff();
406             }
407         }
408     });
409     pthread_setname_np(switchThread.native_handle(), SWITCH_ON_DCALL_THREAD_NAME.c_str());
410     switchThread.detach();
411 }
412 
SwitchOffDCallDeviceSync()413 void DistributedCallManager::SwitchOffDCallDeviceSync()
414 {
415     TELEPHONY_LOGI("switch dcall device off sync");
416     if (!dCallDeviceSwitchedOn_.load()) {
417         TELEPHONY_LOGE("distributed audio device not connected.");
418         return;
419     }
420     std::string devId = GetConnectedDCallDeviceId();
421     if (!devId.length()) {
422         TELEPHONY_LOGE("dcall devId is invalid");
423         return;
424     }
425     TELEPHONY_LOGI("switch dcall device off start, devId: %{public}s", GetAnonyString(devId).c_str());
426     int32_t ret;
427     {
428         std::lock_guard<std::mutex> lock(dcallProxyMtx_);
429         if (dcallProxy_ == nullptr) {
430             TELEPHONY_LOGE("dcallProxy_ is nullptr");
431             return;
432         }
433         ret = dcallProxy_->SwitchDevice(devId, DCALL_SWITCH_DEVICE_TYPE_SOURCE);
434     }
435     if (ret == TELEPHONY_SUCCESS) {
436         dCallDeviceSwitchedOn_.store(false);
437         ClearConnectedDCallDevice();
438         TELEPHONY_LOGI("switch dcall device off succeed.");
439     } else {
440         TELEPHONY_LOGE("switch dcall device off failed, %{public}d", ret);
441     }
442 }
443 
IsSelectVirtualModem()444 bool DistributedCallManager::IsSelectVirtualModem()
445 {
446     if (onlineDCallDevices_.size() <= 0) {
447         TELEPHONY_LOGW("no dcall device");
448         return false;
449     }
450     std::lock_guard<std::mutex> lock(dcallProxyMtx_);
451     if (dcallProxy_ == nullptr) {
452         TELEPHONY_LOGE("fail to create dcall proxy obj");
453         return false;
454     }
455     return dcallProxy_->IsSelectVirtualModem();
456 }
457 
ReportDistributedDeviceInfo(const AudioDevice & device)458 void DistributedCallManager::ReportDistributedDeviceInfo(const AudioDevice& device)
459 {
460     std::string curDevId = GetDevIdFromAudioDevice(device);
461     TELEPHONY_LOGD("curDevId = %{public}s", GetAnonyString(curDevId).c_str());
462     AudioSystemManager *audioSystemMananger = AudioSystemManager::GetInstance();
463     if (audioSystemMananger == nullptr) {
464         TELEPHONY_LOGW("audioSystemMananger nullptr");
465         return;
466     }
467     std::vector<std::shared_ptr<AudioDeviceDescriptor>> descs = audioSystemMananger
468         ->GetDevices(DeviceFlag::DISTRIBUTED_OUTPUT_DEVICES_FLAG);
469     size_t size = descs.size();
470     if (descs.size() <= 0) {
471         TELEPHONY_LOGW("no distributed device");
472         return;
473     }
474     std::vector<std::shared_ptr<AudioDeviceDescriptor>> remoteDevice = descs;
475     for (auto device = descs.begin(); device != descs.end(); device++) {
476         std::string devId = (*device)->networkId_;
477         if (!devId.empty() && curDevId == devId) {
478             TELEPHONY_LOGI("curDecId is the same as devId, devId = %{public}s",
479                 GetAnonyString(devId).c_str());
480             remoteDevice.clear();
481             remoteDevice.push_back(*device);
482             break;
483         }
484     }
485     sptr<AudioRendererFilter> audioRendererFilter = new(std::nothrow) AudioRendererFilter();
486     if (audioRendererFilter == nullptr) {
487         TELEPHONY_LOGE("audioRendererFilter nullptr");
488         return;
489     }
490     audioRendererFilter->rendererInfo.contentType = ContentType::CONTENT_TYPE_SPEECH;
491     audioRendererFilter->rendererInfo.streamUsage = StreamUsage::STREAM_USAGE_VOICE_MODEM_COMMUNICATION;
492     audioSystemMananger->SelectOutputDevice(audioRendererFilter, remoteDevice);
493     TELEPHONY_LOGW("ReportDistributedDeviceInfo");
494 }
495 
ReportDistributedDeviceInfoForSwitchOff()496 void DistributedCallManager::ReportDistributedDeviceInfoForSwitchOff()
497 {
498     TELEPHONY_LOGI("ReportDistributedDeviceInfoForSwitchOff start.");
499     AudioSystemManager *audioSystemMananger = AudioSystemManager::GetInstance();
500     if (audioSystemMananger == nullptr) {
501         TELEPHONY_LOGW("audioSystemMananger nullptr");
502         return;
503     }
504     std::vector<std::shared_ptr<AudioDeviceDescriptor>> descs = audioSystemMananger
505         ->GetDevices(DeviceFlag::OUTPUT_DEVICES_FLAG);
506     size_t size = descs.size();
507     if (descs.size() <= 0) {
508         TELEPHONY_LOGW("no distributed device");
509         return;
510     }
511     std::vector<std::shared_ptr<AudioDeviceDescriptor>> remoteDevice = descs;
512     for (auto device = descs.begin(); device != descs.end(); device++) {
513         if ((*device)->deviceType_ == DeviceType::DEVICE_TYPE_EARPIECE) {
514             TELEPHONY_LOGI("curDecType is speaker.");
515             remoteDevice.clear();
516             remoteDevice.push_back(*device);
517             break;
518         }
519     }
520     sptr<AudioRendererFilter> audioRendererFilter = new(std::nothrow) AudioRendererFilter();
521     if (audioRendererFilter == nullptr) {
522         TELEPHONY_LOGE("audioRendererFilter nullptr");
523         return;
524     }
525     audioRendererFilter->rendererInfo.contentType = ContentType::CONTENT_TYPE_SPEECH;
526     audioRendererFilter->rendererInfo.streamUsage = StreamUsage::STREAM_USAGE_VOICE_MODEM_COMMUNICATION;
527     audioSystemMananger->SelectOutputDevice(audioRendererFilter, remoteDevice);
528     TELEPHONY_LOGI("ReportDistributedDeviceInfoForSwitchOff end.");
529 }
530 
IsDCallDeviceSwitchedOn()531 bool DistributedCallManager::IsDCallDeviceSwitchedOn()
532 {
533     return dCallDeviceSwitchedOn_.load();
534 }
535 
OnDCallDeviceOnline(const std::string & devId)536 int32_t DistributedCallManager::OnDCallDeviceOnline(const std::string &devId)
537 {
538     TELEPHONY_LOGI("dcall device is online, devId: %{public}s", GetAnonyString(devId).c_str());
539     return AddDCallDevice(devId);
540 }
541 
OnDCallDeviceOffline(const std::string & devId)542 int32_t DistributedCallManager::OnDCallDeviceOffline(const std::string &devId)
543 {
544     TELEPHONY_LOGI("dcall device is offline, devId: %{public}s", GetAnonyString(devId).c_str());
545     auto ret = RemoveDCallDevice(devId);
546 #ifdef ABILITY_BLUETOOTH_SUPPORT
547     bool isAllDeviceOffline = true;
548     {
549         std::lock_guard<std::mutex> lock(onlineDeviceMtx_);
550         isAllDeviceOffline = onlineDCallDevices_.empty();
551     }
552     if (isAllDeviceOffline) {
553         TELEPHONY_LOGI("all dcall device offline");
554         std::lock_guard<std::mutex> lock(mutex_);
555         if (dcallHfpListener_ != nullptr) {
556             Bluetooth::HandsFreeAudioGateway::GetProfile()->DeregisterObserver(dcallHfpListener_);
557             dcallHfpListener_ = nullptr;
558         }
559     }
560 #endif
561     return ret;
562 }
563 
OnDCallDeviceOnline(const std::string & devId)564 int32_t DistributedCallManager::DistributedCallDeviceListener::OnDCallDeviceOnline(const std::string &devId)
565 {
566     TELEPHONY_LOGI("dcall device is online, devId: %{public}s", GetAnonyString(devId).c_str());
567     return DelayedSingleton<DistributedCallManager>::GetInstance()->OnDCallDeviceOnline(devId);
568 }
569 
OnDCallDeviceOffline(const std::string & devId)570 int32_t DistributedCallManager::DistributedCallDeviceListener::OnDCallDeviceOffline(const std::string &devId)
571 {
572     TELEPHONY_LOGI("dcall device is offline, devId: %{public}s", GetAnonyString(devId).c_str());
573     return DelayedSingleton<DistributedCallManager>::GetInstance()->OnDCallDeviceOffline(devId);
574 }
575 
OnDCallSystemAbilityAdded(const std::string & deviceId)576 void DistributedCallManager::OnDCallSystemAbilityAdded(const std::string &deviceId)
577 {
578     TELEPHONY_LOGI("dcall source service is added, deviceId: %{public}s", GetAnonyString(deviceId).c_str());
579     std::vector<std::string> dcallDevices;
580     {
581         std::lock_guard<std::mutex> lock(dcallProxyMtx_);
582         dcallProxy_ = std::make_shared<DistributedCallProxy>();
583         if (dcallProxy_ == nullptr) {
584             TELEPHONY_LOGE("fail to create dcall proxy obj");
585             return;
586         }
587         if (dcallProxy_->Init() != TELEPHONY_SUCCESS) {
588             TELEPHONY_LOGE("init dcall proxy failed");
589             return;
590         }
591         dcallDeviceListener_ = std::make_shared<DistributedCallDeviceListener>();
592         if (dcallDeviceListener_ == nullptr) {
593             TELEPHONY_LOGE("dcallDeviceListener_ is nullptr");
594             return;
595         }
596         if (dcallProxy_->RegisterDeviceCallback(CALLBACK_NAME, dcallDeviceListener_) != TELEPHONY_SUCCESS) {
597             TELEPHONY_LOGE("register dcall callback failed");
598             return;
599         }
600         if (dcallProxy_->GetOnlineDeviceList(dcallDevices) != TELEPHONY_SUCCESS) {
601             TELEPHONY_LOGE("get dcall device list failed");
602             return;
603         }
604     }
605     if (dcallDevices.size() > 0) {
606         NotifyOnlineDCallDevices(dcallDevices);
607     }
608     TELEPHONY_LOGI("OnDCallSystemAbilityAdded end.");
609 }
610 
OnDCallSystemAbilityRemoved(const std::string & deviceId)611 void DistributedCallManager::OnDCallSystemAbilityRemoved(const std::string &deviceId)
612 {
613     TELEPHONY_LOGI("dcall source service is removed, deviceId: %{public}s", GetAnonyString(deviceId).c_str());
614     {
615         std::lock_guard<std::mutex> lock(dcallProxyMtx_);
616         dcallDeviceListener_ = nullptr;
617         dcallProxy_ = nullptr;
618     }
619     ClearDCallDevices();
620     ClearConnectedDCallDevice();
621     DelayedSingleton<AudioDeviceManager>::GetInstance()->ResetDistributedCallDevicesList();
622     if (dCallDeviceSwitchedOn_.load()) {
623         DelayedSingleton<AudioDeviceManager>::GetInstance()->InitAudioDevice();
624     }
625     dCallDeviceSwitchedOn_.store(false);
626     TELEPHONY_LOGI("OnDCallSystemAbilityRemoved end.");
627 }
628 
OnAddSystemAbility(int32_t systemAbilityId,const std::string & deviceId)629 void DCallSystemAbilityListener::OnAddSystemAbility(int32_t systemAbilityId, const std::string &deviceId)
630 {
631     TELEPHONY_LOGI("SA: %{public}d is added!", systemAbilityId);
632     if (!CheckInputSysAbilityId(systemAbilityId)) {
633         TELEPHONY_LOGE("added SA is invalid!");
634         return;
635     }
636     if (systemAbilityId != DISTRIBUTED_CALL_SOURCE_SA_ID) {
637         TELEPHONY_LOGE("added SA is not dcall source service, ignored.");
638         return;
639     }
640     TELEPHONY_LOGI("notify dcall source service added event to distributed call manager");
641     DelayedSingleton<DistributedCallManager>::GetInstance()->OnDCallSystemAbilityAdded(deviceId);
642 }
643 
OnRemoveSystemAbility(int32_t systemAbilityId,const std::string & deviceId)644 void DCallSystemAbilityListener::OnRemoveSystemAbility(int32_t systemAbilityId, const std::string &deviceId)
645 {
646     TELEPHONY_LOGI("SA: %{public}d is removed!", systemAbilityId);
647     if (!CheckInputSysAbilityId(systemAbilityId)) {
648         TELEPHONY_LOGE("removed SA is invalid!");
649         return;
650     }
651     if (systemAbilityId != DISTRIBUTED_CALL_SOURCE_SA_ID) {
652         TELEPHONY_LOGE("removed SA is not dcall source service, ignored.");
653         return;
654     }
655     TELEPHONY_LOGI("notify dcall source service removed event to distributed call manager");
656     DelayedSingleton<DistributedCallManager>::GetInstance()->OnDCallSystemAbilityRemoved(deviceId);
657 }
658 
659 #ifdef ABILITY_BLUETOOTH_SUPPORT
OnHfpStackChanged(const Bluetooth::BluetoothRemoteDevice & device,int32_t action)660 void DCallHfpListener::OnHfpStackChanged(const Bluetooth::BluetoothRemoteDevice &device, int32_t action)
661 {
662     TELEPHONY_LOGI("dcall hfp stack changed, action[%{public}d]", action);
663     int32_t cod = DEFAULT_DCALL_HFP_FLAG_VALUE;
664     int32_t majorClass = DEFAULT_DCALL_HFP_FLAG_VALUE;
665     int32_t majorMinorClass = DEFAULT_DCALL_HFP_FLAG_VALUE;
666     device.GetDeviceProductType(cod, majorClass, majorMinorClass);
667     bool isBtHeadset = (majorClass == Bluetooth::BluetoothDevice::MAJOR_AUDIO_VIDEO &&
668                         (majorMinorClass == Bluetooth::BluetoothDevice::AUDIO_VIDEO_HEADPHONES ||
669                          majorMinorClass == Bluetooth::BluetoothDevice::AUDIO_VIDEO_WEARABLE_HEADSET));
670     if (!isBtHeadset) {
671         return;
672     }
673     if (action == DCALL_BT_HEADSET_UNWEAR_ACTION) {
674         DelayedSingleton<AudioDeviceManager>::GetInstance()->CheckAndSwitchDistributedAudioDevice();
675     }
676 }
677 #endif
678 
679 } // namespace Telephony
680 } // namespace OHOS