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