1 /*
2  * Copyright (C) 2023-2024 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 #include <dlfcn.h>
19 
20 #include "distributed_call_manager.h"
21 #include "audio_control_manager.h"
22 #include "telephony_log_wrapper.h"
23 #include "nlohmann/json.hpp"
24 
25 using json = nlohmann::json;
26 
27 namespace OHOS {
28 namespace Telephony {
29 namespace {
30 const size_t INT32_MIN_ID_LENGTH = 3;
31 const size_t INT32_SHORT_ID_LENGTH = 20;
32 const size_t INT32_PLAINTEXT_LENGTH = 4;
33 const int32_t DCALL_SWITCH_DEVICE_TYPE_SOURCE = 0;
34 const int32_t DCALL_SWITCH_DEVICE_TYPE_SINK = 1;
35 const int32_t DISTRIBUTED_CALL_SOURCE_SA_ID = 9855;
36 const int32_t WAIT_DCALL_INIT_100MS = 100 * 1000;
37 const std::string CALLBACK_NAME = "telephony";
38 const std::string DISTRIBUTED_AUDIO_DEV_CAR = "dCar";
39 const std::string DISTRIBUTED_AUDIO_DEV_PHONE = "dPhone";
40 const std::string DISTRIBUTED_AUDIO_DEV_PAD = "dPad";
41 const std::string SWITCH_ON_DCALL_THREAD_NAME = "switch on dcall";
42 
43 const int32_t DISTRIBUTED_COMMUNICATION_CALL_SA_ID = 66198;
44 
GetAnonyString(const std::string & value)45 std::string GetAnonyString(const std::string &value)
46 {
47     std::string res;
48     std::string tmpStr("******");
49     size_t strLen = value.length();
50     if (strLen < INT32_MIN_ID_LENGTH) {
51         return tmpStr;
52     }
53     if (strLen <= INT32_SHORT_ID_LENGTH) {
54         res += value[0];
55         res += tmpStr;
56         res += value[strLen - 1];
57     } else {
58         res.append(value, 0, INT32_PLAINTEXT_LENGTH);
59         res += tmpStr;
60         res.append(value, strLen - INT32_PLAINTEXT_LENGTH, INT32_PLAINTEXT_LENGTH);
61     }
62     return res;
63 }
64 
IsDistributedAudioDevice(const AudioDevice & device)65 bool IsDistributedAudioDevice(const AudioDevice& device)
66 {
67     if ((device.deviceType == AudioDeviceType::DEVICE_DISTRIBUTED_PHONE) ||
68         (device.deviceType == AudioDeviceType::DEVICE_DISTRIBUTED_PAD) ||
69         (device.deviceType == AudioDeviceType::DEVICE_DISTRIBUTED_AUTOMOTIVE)) {
70         return true;
71     }
72     return false;
73 }
74 }
75 
DistributedCallManager()76 DistributedCallManager::DistributedCallManager()
77 {
78     TELEPHONY_LOGI("DistributedCallManager constructed.");
79 }
80 
~DistributedCallManager()81 DistributedCallManager::~DistributedCallManager()
82 {
83     TELEPHONY_LOGI("DistributedCallManager destructed.");
84 }
85 
Init()86 void DistributedCallManager::Init()
87 {
88     TELEPHONY_LOGI("Init start.");
89     statusChangeListener_ = new (std::nothrow) DCallSystemAbilityListener();
90     if (statusChangeListener_ == nullptr) {
91         TELEPHONY_LOGE("failed to create statusChangeListener");
92         return;
93     }
94     auto managerPtr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
95     if (managerPtr == nullptr) {
96         TELEPHONY_LOGE("get system ability manager error");
97         return;
98     }
99     int32_t ret = managerPtr->SubscribeSystemAbility(DISTRIBUTED_CALL_SOURCE_SA_ID, statusChangeListener_);
100     if (ret != TELEPHONY_SUCCESS) {
101         TELEPHONY_LOGE("failed to subscribe dcall service SA: %{public}d", DISTRIBUTED_CALL_SOURCE_SA_ID);
102         return;
103     }
104     InitDistributedCommunicationCall();
105     TELEPHONY_LOGI("Init end.");
106 }
107 
CreateDAudioDevice(const std::string & devId,AudioDevice & device)108 bool DistributedCallManager::CreateDAudioDevice(const std::string& devId, AudioDevice& device)
109 {
110     if (!devId.length()) {
111         TELEPHONY_LOGE("dcall devId is invalid");
112         return false;
113     }
114     if (dcallProxy_ == nullptr) {
115         TELEPHONY_LOGE("dcallProxy_ is nullptr");
116         return false;
117     }
118     OHOS::DistributedHardware::DCallDeviceInfo devInfo;
119     int32_t ret = dcallProxy_->GetDCallDeviceInfo(devId, devInfo);
120     if (ret != TELEPHONY_SUCCESS) {
121         TELEPHONY_LOGI("get dcall device info failed.");
122         return false;
123     }
124     std::string devTypeName;
125     std::string devName = devInfo.devName;
126     if (devInfo.devType == OHOS::DistributedHardware::DCallDeviceType::DISTRIBUTED_DEVICE_PHONE) {
127         devTypeName = DISTRIBUTED_AUDIO_DEV_PHONE;
128         device.deviceType = AudioDeviceType::DEVICE_DISTRIBUTED_PHONE;
129     } else if (devInfo.devType == OHOS::DistributedHardware::DCallDeviceType::DISTRIBUTED_DEVICE_PAD) {
130         devTypeName = DISTRIBUTED_AUDIO_DEV_PAD;
131         device.deviceType = AudioDeviceType::DEVICE_DISTRIBUTED_PAD;
132     } else {
133         devTypeName = DISTRIBUTED_AUDIO_DEV_CAR;
134         device.deviceType = AudioDeviceType::DEVICE_DISTRIBUTED_AUTOMOTIVE;
135     }
136     json addressJson;
137     addressJson["devName"] = devName;
138     addressJson["devId"] = devId;
139     std::string addressStr = addressJson.dump();
140     if (memcpy_s(device.address, kMaxAddressLen, addressStr.c_str(), addressStr.length()) != EOK) {
141         TELEPHONY_LOGE("memcpy_s failed.");
142         return false;
143     }
144     TELEPHONY_LOGI("create distributed audio device succeed.");
145     return true;
146 }
147 
GetDevIdFromAudioDevice(const AudioDevice & device)148 std::string DistributedCallManager::GetDevIdFromAudioDevice(const AudioDevice& device)
149 {
150     std::string devId = "";
151     if (!IsDistributedAudioDevice(device)) {
152         TELEPHONY_LOGE("not distributed audio device, device type: %{public}d", device.deviceType);
153         return devId;
154     }
155     std::string address = device.address;
156     if (!address.length()) {
157         TELEPHONY_LOGE("invalid address");
158         return devId;
159     }
160     json addressJson = json::parse(address, nullptr, false);
161     if (addressJson.is_null() || addressJson.is_discarded()) {
162         TELEPHONY_LOGE("json value is null or discarded.");
163         return devId;
164     }
165     if (!addressJson.contains("devId")) {
166         TELEPHONY_LOGE("json not contain devId.");
167         return devId;
168     }
169     if (!addressJson["devId"].is_string()) {
170         TELEPHONY_LOGE("json has no devId string.");
171         return devId;
172     }
173     devId = addressJson["devId"];
174     TELEPHONY_LOGI("devId: %{public}s", GetAnonyString(devId).c_str());
175     return devId;
176 }
177 
AddDCallDevice(const std::string & devId)178 int32_t DistributedCallManager::AddDCallDevice(const std::string& devId)
179 {
180     TELEPHONY_LOGI("add dcall device, devId: %{public}s.", GetAnonyString(devId).c_str());
181     std::lock_guard<std::mutex> lock(onlineDeviceMtx_);
182 
183     auto iter = onlineDCallDevices_.find(devId);
184     if (iter != onlineDCallDevices_.end()) {
185         TELEPHONY_LOGW("device is already exist, devId: %{public}s", GetAnonyString(devId).c_str());
186         return TELEPHONY_SUCCESS;
187     }
188 
189     AudioDevice device;
190     if (!CreateDAudioDevice(devId, device)) {
191         TELEPHONY_LOGE("failed to create distributed audio device, devId: %{public}s", GetAnonyString(devId).c_str());
192         return TELEPHONY_ERR_FAIL;
193     }
194 
195     DelayedSingleton<AudioDeviceManager>::GetInstance()->AddAudioDeviceList(device.address, device.deviceType, "");
196     onlineDCallDevices_.emplace(devId, device);
197 
198     if (!dCallDeviceSwitchedOn_.load() && isCallActived_.load()) {
199         if (device.deviceType == AudioDeviceType::DEVICE_DISTRIBUTED_AUTOMOTIVE) {
200             TELEPHONY_LOGI("switch call to auto motive as it is online");
201             SwitchOnDCallDeviceAsync(device);
202         }
203     }
204     return TELEPHONY_SUCCESS;
205 }
206 
RemoveDCallDevice(const std::string & devId)207 int32_t DistributedCallManager::RemoveDCallDevice(const std::string& devId)
208 {
209     TELEPHONY_LOGI("remove dcall device, devId: %{public}s.", GetAnonyString(devId).c_str());
210     std::lock_guard<std::mutex> lock(onlineDeviceMtx_);
211     auto iter = onlineDCallDevices_.find(devId);
212     if (iter != onlineDCallDevices_.end()) {
213         std::string devId = GetDevIdFromAudioDevice(iter->second);
214         std::string curDevId = GetConnectedDCallDeviceId();
215         TELEPHONY_LOGI("removed devId: %{public}s, current devId: %{public}s",
216             GetAnonyString(devId).c_str(), GetAnonyString(curDevId).c_str());
217         DelayedSingleton<AudioDeviceManager>::GetInstance()->RemoveAudioDeviceList(
218             iter->second.address, iter->second.deviceType);
219         onlineDCallDevices_.erase(iter);
220         if (curDevId == devId) {
221             TELEPHONY_LOGI("current dcall device is removed, now reinit audio device.");
222             dCallDeviceSwitchedOn_.store(false);
223             ClearConnectedDCallDevice();
224             DelayedSingleton<AudioDeviceManager>::GetInstance()->InitAudioDevice();
225         }
226     }
227     return TELEPHONY_SUCCESS;
228 }
229 
ClearDCallDevices()230 void DistributedCallManager::ClearDCallDevices()
231 {
232     TELEPHONY_LOGI("clear dcall device.");
233     std::lock_guard<std::mutex> lock(onlineDeviceMtx_);
234     onlineDCallDevices_.clear();
235 }
236 
NotifyOnlineDCallDevices(std::vector<std::string> devices)237 void DistributedCallManager::NotifyOnlineDCallDevices(std::vector<std::string> devices)
238 {
239     TELEPHONY_LOGI("notify online dcall devices start, size: %{public}d", static_cast<int32_t>(devices.size()));
240     for (auto item : devices) {
241         AddDCallDevice(item);
242         TELEPHONY_LOGI("notify dcall device, devId: %{public}s", GetAnonyString(item).c_str());
243     }
244     TELEPHONY_LOGI("notify online dcall devices end.");
245 }
246 
GetConnectedDCallDeviceAddr()247 std::string DistributedCallManager::GetConnectedDCallDeviceAddr()
248 {
249     std::lock_guard<std::mutex> lock(connectedDevMtx_);
250     std::string addr = connectedAudioDevice_.address;
251     return addr;
252 }
253 
GetConnectedDCallDeviceType()254 AudioDeviceType DistributedCallManager::GetConnectedDCallDeviceType()
255 {
256     std::lock_guard<std::mutex> lock(connectedDevMtx_);
257     AudioDeviceType type = connectedAudioDevice_.deviceType;
258     return type;
259 }
260 
GetConnectedDCallDeviceId()261 std::string DistributedCallManager::GetConnectedDCallDeviceId()
262 {
263     std::lock_guard<std::mutex> lock(connectedDevMtx_);
264     std::string devId = "";
265     if (dCallDeviceSwitchedOn_.load()) {
266         devId = GetDevIdFromAudioDevice(connectedAudioDevice_);
267     }
268     return devId;
269 }
270 
GetConnectedDCallDevice(AudioDevice & device)271 void DistributedCallManager::GetConnectedDCallDevice(AudioDevice& device)
272 {
273     std::lock_guard<std::mutex> lock(connectedDevMtx_);
274     device.deviceType = connectedAudioDevice_.deviceType;
275     if (memcpy_s(device.address, kMaxAddressLen, connectedAudioDevice_.address, kMaxAddressLen) != EOK) {
276         TELEPHONY_LOGE("memcpy_s failed.");
277     }
278 }
279 
SetConnectedDCallDevice(const AudioDevice & device)280 void DistributedCallManager::SetConnectedDCallDevice(const AudioDevice& device)
281 {
282     std::lock_guard<std::mutex> lock(connectedDevMtx_);
283     connectedAudioDevice_.deviceType = device.deviceType;
284     if (memcpy_s(connectedAudioDevice_.address, kMaxAddressLen, device.address, kMaxAddressLen) != EOK) {
285         TELEPHONY_LOGE("memcpy_s failed.");
286     }
287 }
288 
ClearConnectedDCallDevice()289 void DistributedCallManager::ClearConnectedDCallDevice()
290 {
291     std::lock_guard<std::mutex> lock(connectedDevMtx_);
292     connectedAudioDevice_.deviceType = AudioDeviceType::DEVICE_UNKNOWN;
293     if (memset_s(connectedAudioDevice_.address, kMaxAddressLen, 0, kMaxAddressLen) != EOK) {
294         TELEPHONY_LOGE("memset_s failed.");
295     }
296 }
297 
SwitchOnDCallDeviceSync(const AudioDevice & device)298 bool DistributedCallManager::SwitchOnDCallDeviceSync(const AudioDevice& device)
299 {
300     TELEPHONY_LOGI("switch dcall device on sync");
301     if (!IsDistributedAudioDevice(device)) {
302         TELEPHONY_LOGE("not distributed audio device, device type: %{public}d", device.deviceType);
303         return false;
304     }
305     std::string devId = GetDevIdFromAudioDevice(device);
306     if (!devId.length()) {
307         TELEPHONY_LOGE("dcall devId is invalid");
308         return false;
309     }
310     TELEPHONY_LOGI("switch dcall device on start, devId: %{public}s", GetAnonyString(devId).c_str());
311     if (dcallProxy_ == nullptr) {
312         TELEPHONY_LOGE("dcallProxy_ is nullptr");
313         return false;
314     }
315     int32_t ret = dcallProxy_->SwitchDevice(devId, DCALL_SWITCH_DEVICE_TYPE_SINK);
316     if (ret == TELEPHONY_SUCCESS) {
317         dCallDeviceSwitchedOn_.store(true);
318         SetConnectedDCallDevice(device);
319         DelayedSingleton<AudioDeviceManager>::GetInstance()->SetCurrentAudioDevice(device.deviceType);
320         TELEPHONY_LOGI("switch dcall device on succeed.");
321         return true;
322     }
323     TELEPHONY_LOGI("switch dcall device on failed, ret: %{public}d.", ret);
324     return false;
325 }
326 
SetCallState(bool isActive)327 void DistributedCallManager::SetCallState(bool isActive)
328 {
329     isCallActived_.store(isActive);
330 }
331 
DealDisconnectCall()332 void DistributedCallManager::DealDisconnectCall()
333 {
334     dCallDeviceSwitchedOn_.store(false);
335     ClearConnectedDCallDevice();
336 }
337 
SwitchOnDCallDeviceAsync(const AudioDevice & device)338 void DistributedCallManager::SwitchOnDCallDeviceAsync(const AudioDevice& device)
339 {
340     TELEPHONY_LOGI("switch dcall device on async");
341     std::thread switchThread = std::thread([this, device]() { this->SwitchOnDCallDeviceSync(device); });
342     pthread_setname_np(switchThread.native_handle(), SWITCH_ON_DCALL_THREAD_NAME.c_str());
343     switchThread.detach();
344 }
345 
SwitchOffDCallDeviceSync()346 void DistributedCallManager::SwitchOffDCallDeviceSync()
347 {
348     TELEPHONY_LOGI("switch dcall device off sync");
349     if (!dCallDeviceSwitchedOn_.load()) {
350         TELEPHONY_LOGE("distributed audio device not connected.");
351         return;
352     }
353     std::string devId = GetConnectedDCallDeviceId();
354     if (!devId.length()) {
355         TELEPHONY_LOGE("dcall devId is invalid");
356         return;
357     }
358     TELEPHONY_LOGI("switch dcall device off start, devId: %{public}s", GetAnonyString(devId).c_str());
359     if (dcallProxy_ == nullptr) {
360         TELEPHONY_LOGE("dcallProxy_ is nullptr");
361         return;
362     }
363     int32_t ret = dcallProxy_->SwitchDevice(devId, DCALL_SWITCH_DEVICE_TYPE_SOURCE);
364     if (ret == TELEPHONY_SUCCESS) {
365         dCallDeviceSwitchedOn_.store(false);
366         ClearConnectedDCallDevice();
367         TELEPHONY_LOGI("switch dcall device off succeed.");
368     } else {
369         TELEPHONY_LOGE("switch dcall device off failed, %{public}d", ret);
370     }
371 }
372 
IsDCallDeviceSwitchedOn()373 bool DistributedCallManager::IsDCallDeviceSwitchedOn()
374 {
375     return dCallDeviceSwitchedOn_.load();
376 }
377 
OnDCallDeviceOnline(const std::string & devId)378 int32_t DistributedCallManager::OnDCallDeviceOnline(const std::string &devId)
379 {
380     TELEPHONY_LOGI("dcall device is online, devId: %{public}s", GetAnonyString(devId).c_str());
381     return AddDCallDevice(devId);
382 }
383 
OnDCallDeviceOffline(const std::string & devId)384 int32_t DistributedCallManager::OnDCallDeviceOffline(const std::string &devId)
385 {
386     TELEPHONY_LOGI("dcall device is offline, devId: %{public}s", GetAnonyString(devId).c_str());
387     return RemoveDCallDevice(devId);
388 }
389 
OnDCallDeviceOnline(const std::string & devId)390 int32_t DistributedCallManager::DistributedCallDeviceListener::OnDCallDeviceOnline(const std::string &devId)
391 {
392     TELEPHONY_LOGI("dcall device is online, devId: %{public}s", GetAnonyString(devId).c_str());
393     return DelayedSingleton<DistributedCallManager>::GetInstance()->OnDCallDeviceOnline(devId);
394 }
395 
OnDCallDeviceOffline(const std::string & devId)396 int32_t DistributedCallManager::DistributedCallDeviceListener::OnDCallDeviceOffline(const std::string &devId)
397 {
398     TELEPHONY_LOGI("dcall device is offline, devId: %{public}s", GetAnonyString(devId).c_str());
399     return DelayedSingleton<DistributedCallManager>::GetInstance()->OnDCallDeviceOffline(devId);
400 }
401 
OnDCallSystemAbilityAdded(const std::string & deviceId)402 void DistributedCallManager::OnDCallSystemAbilityAdded(const std::string &deviceId)
403 {
404     TELEPHONY_LOGI("dcall source service is added, deviceId: %{public}s", GetAnonyString(deviceId).c_str());
405     // wait 100ms for dcall-sa to complete init.
406     usleep(WAIT_DCALL_INIT_100MS);
407     dcallProxy_ = std::make_shared<DistributedCallProxy>();
408     if (dcallProxy_ == nullptr) {
409         TELEPHONY_LOGE("fail to create dcall proxy obj");
410         return;
411     }
412     if (dcallProxy_->Init() != TELEPHONY_SUCCESS) {
413         TELEPHONY_LOGE("init dcall proxy failed");
414         return;
415     }
416     dcallDeviceListener_ = std::make_shared<DistributedCallDeviceListener>();
417     if (dcallDeviceListener_ == nullptr) {
418         TELEPHONY_LOGE("dcallDeviceListener_ is nullptr");
419         return;
420     }
421     if (dcallProxy_->RegisterDeviceCallback(CALLBACK_NAME, dcallDeviceListener_) != TELEPHONY_SUCCESS) {
422         TELEPHONY_LOGE("register dcall callback failed");
423         return;
424     }
425     std::vector<std::string> dcallDevices;
426     if (dcallProxy_->GetOnlineDeviceList(dcallDevices) != TELEPHONY_SUCCESS) {
427         TELEPHONY_LOGE("get dcall device list failed");
428         return;
429     }
430     if (dcallDevices.size() > 0) {
431         NotifyOnlineDCallDevices(dcallDevices);
432     }
433     TELEPHONY_LOGI("OnDCallSystemAbilityAdded end.");
434 }
435 
OnDCallSystemAbilityRemoved(const std::string & deviceId)436 void DistributedCallManager::OnDCallSystemAbilityRemoved(const std::string &deviceId)
437 {
438     TELEPHONY_LOGI("dcall source service is removed, deviceId: %{public}s", GetAnonyString(deviceId).c_str());
439     dcallDeviceListener_ = nullptr;
440     dcallProxy_ = nullptr;
441     dCallDeviceSwitchedOn_.store(false);
442     ClearDCallDevices();
443     ClearConnectedDCallDevice();
444     DelayedSingleton<AudioDeviceManager>::GetInstance()->ResetDistributedCallDevicesList();
445     DelayedSingleton<AudioDeviceManager>::GetInstance()->InitAudioDevice();
446     TELEPHONY_LOGI("OnDCallSystemAbilityRemoved end.");
447 }
448 
OnAddSystemAbility(int32_t systemAbilityId,const std::string & deviceId)449 void DCallSystemAbilityListener::OnAddSystemAbility(int32_t systemAbilityId, const std::string &deviceId)
450 {
451     TELEPHONY_LOGI("SA: %{public}d is added!", systemAbilityId);
452     if (!CheckInputSysAbilityId(systemAbilityId)) {
453         TELEPHONY_LOGE("added SA is invalid!");
454         return;
455     }
456     if (systemAbilityId != DISTRIBUTED_CALL_SOURCE_SA_ID) {
457         TELEPHONY_LOGE("added SA is not dcall source service, ignored.");
458         return;
459     }
460     TELEPHONY_LOGI("notify dcall source service added event to distributed call manager");
461     DelayedSingleton<DistributedCallManager>::GetInstance()->OnDCallSystemAbilityAdded(deviceId);
462 }
463 
OnRemoveSystemAbility(int32_t systemAbilityId,const std::string & deviceId)464 void DCallSystemAbilityListener::OnRemoveSystemAbility(int32_t systemAbilityId, const std::string &deviceId)
465 {
466     TELEPHONY_LOGI("SA: %{public}d is removed!", systemAbilityId);
467     if (!CheckInputSysAbilityId(systemAbilityId)) {
468         TELEPHONY_LOGE("removed SA is invalid!");
469         return;
470     }
471     if (systemAbilityId != DISTRIBUTED_CALL_SOURCE_SA_ID) {
472         TELEPHONY_LOGE("removed SA is not dcall source service, ignored.");
473         return;
474     }
475     TELEPHONY_LOGI("notify dcall source service removed event to distributed call manager");
476     DelayedSingleton<DistributedCallManager>::GetInstance()->OnDCallSystemAbilityRemoved(deviceId);
477 }
478 
InitDistributedCommunicationCall()479 void DistributedCallManager::InitDistributedCommunicationCall()
480 {
481     TELEPHONY_LOGI("Init distributed communication call");
482     dcCallSaListener_ = new (std::nothrow) DcCallSystemAbilityListener();
483     if (dcCallSaListener_ == nullptr) {
484         TELEPHONY_LOGE("init dc-call fail, create sa linstener fail");
485         return;
486     }
487     auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
488     if (saManager == nullptr) {
489         TELEPHONY_LOGE("init dc-call fail, get system ability manager fail");
490         return;
491     }
492     int32_t ret = saManager->SubscribeSystemAbility(DISTRIBUTED_COMMUNICATION_CALL_SA_ID, dcCallSaListener_);
493     if (ret != TELEPHONY_SUCCESS) {
494         TELEPHONY_LOGE("failed to subscribe dc-call service SA: %{public}d", DISTRIBUTED_COMMUNICATION_CALL_SA_ID);
495         return;
496     }
497 }
498 
OnDcCallSystemAbilityAdded()499 void DistributedCallManager::OnDcCallSystemAbilityAdded()
500 {
501     TELEPHONY_LOGI("dc-call service added");
502     auto handle = dlopen("libtelephony_ext_innerkits.z.so", RTLD_NOW);
503     if (handle == nullptr) {
504         TELEPHONY_LOGE("open so failed");
505         return;
506     }
507     typedef int32_t (*REGISTER_DC_CALL)();
508     auto regFunc = (REGISTER_DC_CALL)dlsym(handle, "RegisterDcCall");
509     if (regFunc == nullptr) {
510         TELEPHONY_LOGE("get reg function failed");
511         dlclose(handle);
512         return;
513     }
514     auto ret = regFunc();
515     TELEPHONY_LOGI("reg dc-call service result %{public}d", ret);
516     dlclose(handle);
517 }
518 
OnDcCallSystemAbilityRemoved()519 void DistributedCallManager::OnDcCallSystemAbilityRemoved()
520 {
521     TELEPHONY_LOGI("dc-call service removed");
522 }
523 
OnAddSystemAbility(int32_t systemAbilityId,const std::string & deviceId)524 void DcCallSystemAbilityListener::OnAddSystemAbility(int32_t systemAbilityId, const std::string &deviceId)
525 {
526     if (!CheckInputSysAbilityId(systemAbilityId)) {
527         TELEPHONY_LOGE("invalid sa");
528         return;
529     }
530     if (systemAbilityId != DISTRIBUTED_COMMUNICATION_CALL_SA_ID) {
531         TELEPHONY_LOGE("added SA is not dc-call service, ignored");
532         return;
533     }
534     DelayedSingleton<DistributedCallManager>::GetInstance()->OnDcCallSystemAbilityAdded();
535 }
536 
OnRemoveSystemAbility(int32_t systemAbilityId,const std::string & deviceId)537 void DcCallSystemAbilityListener::OnRemoveSystemAbility(int32_t systemAbilityId, const std::string &deviceId)
538 {
539     if (!CheckInputSysAbilityId(systemAbilityId)) {
540         TELEPHONY_LOGE("invalid sa");
541         return;
542     }
543     if (systemAbilityId != DISTRIBUTED_COMMUNICATION_CALL_SA_ID) {
544         TELEPHONY_LOGE("removed SA is not dc-call service, ignored");
545         return;
546     }
547     DelayedSingleton<DistributedCallManager>::GetInstance()->OnDcCallSystemAbilityRemoved();
548 }
549 
550 } // namespace Telephony
551 } // namespace OHOS