1 /*
2 * Copyright (C) 2021-2022 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 "ims_control.h"
17
18 #include "cellular_call_hisysevent.h"
19 #include "cellular_call_register.h"
20 #include "emergency_utils.h"
21 #include "module_service_utils.h"
22 #include "securec.h"
23 #include "standardize_utils.h"
24
25 namespace OHOS {
26 namespace Telephony {
~IMSControl()27 IMSControl::~IMSControl()
28 {
29 TELEPHONY_LOGI("~IMSControl start");
30 ReleaseAllConnection();
31 }
32
Dial(const CellularCallInfo & callInfo,bool isEcc)33 int32_t IMSControl::Dial(const CellularCallInfo &callInfo, bool isEcc)
34 {
35 TELEPHONY_LOGI("Dial start");
36 DelayedSingleton<CellularCallHiSysEvent>::GetInstance()->SetCallParameterInfo(
37 callInfo.slotId, static_cast<int32_t>(callInfo.callType), callInfo.videoState);
38 int32_t ret = DialPreJudgment(callInfo, isEcc);
39 if (ret != TELEPHONY_SUCCESS) {
40 return ret;
41 }
42 ModuleServiceUtils moduleServiceUtils;
43 RegServiceState regState = moduleServiceUtils.GetPsRegState(callInfo.slotId);
44 if (!(regState == RegServiceState::REG_STATE_IN_SERVICE || isEcc)) {
45 TELEPHONY_LOGE("can not dial.");
46 return TELEPHONY_ERR_NETWORK_NOT_IN_SERVICE;
47 }
48 // sip uri needs to remove separator
49 std::string newPhoneNum(callInfo.phoneNum);
50 StandardizeUtils standardizeUtils;
51 if (newPhoneNum.find('@') != std::string::npos || newPhoneNum.find("%40") != std::string::npos) {
52 newPhoneNum = standardizeUtils.RemoveSeparatorsPhoneNumber(newPhoneNum);
53 }
54
55 CLIRMode clirMode = CLIRMode::DEFAULT;
56 if (IsNeedExecuteMMI(callInfo.slotId, newPhoneNum, clirMode, true)) {
57 TELEPHONY_LOGI("Dial return, mmi code type.");
58 return RETURN_TYPE_MMI;
59 }
60 return DialJudgment(callInfo.slotId, newPhoneNum, clirMode, callInfo.videoState);
61 }
62
DialJudgment(int32_t slotId,const std::string & phoneNum,CLIRMode & clirMode,int32_t videoState)63 int32_t IMSControl::DialJudgment(int32_t slotId, const std::string &phoneNum, CLIRMode &clirMode, int32_t videoState)
64 {
65 TELEPHONY_LOGI("DialJudgment entry.");
66 std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
67 if (!CanCall(connectionMap_)) {
68 TELEPHONY_LOGE("DialJudgment return, error type: call state error.");
69 CellularCallHiSysEvent::WriteDialCallFaultEvent(
70 slotId, INVALID_PARAMETER, videoState, CALL_ERR_CALL_COUNTS_EXCEED_LIMIT, "ims dial call state error");
71 return CALL_ERR_CALL_COUNTS_EXCEED_LIMIT;
72 }
73 pendingPhoneNumber_ = phoneNum;
74 // Calls can be put on hold, recovered, released, added to conversation,
75 // and transferred similarly as defined in 3GPP TS 22.030 [19].
76 for (auto &connection : connectionMap_) {
77 if (connection.second.GetStatus() == TelCallState::CALL_STATUS_ACTIVE) {
78 TELEPHONY_LOGI("DialJudgment, have connection in active state.");
79 EmergencyUtils emergencyUtils;
80 bool isEmergency = false;
81 emergencyUtils.IsEmergencyCall(slotId, phoneNum, isEmergency);
82 connection.second.SetHoldToDialInfo(phoneNum, clirMode, videoState, isEmergency);
83 connection.second.SetDialFlag(true);
84 // - a call can be temporarily disconnected from the ME but the connection is retained by the network
85 return connection.second.SwitchCallRequest(slotId);
86 }
87 }
88 return EncapsulateDial(slotId, phoneNum, clirMode, videoState);
89 }
90
EncapsulateDial(int32_t slotId,const std::string & phoneNum,CLIRMode & clirMode,int32_t videoState) const91 int32_t IMSControl::EncapsulateDial(
92 int32_t slotId, const std::string &phoneNum, CLIRMode &clirMode, int32_t videoState) const
93 {
94 TELEPHONY_LOGI("EncapsulateDial start");
95
96 ImsDialInfoStruct dialInfo;
97 dialInfo.videoState = videoState;
98 dialInfo.bEmergencyCall = false;
99 EmergencyUtils emergencyUtils;
100 emergencyUtils.IsEmergencyCall(slotId, phoneNum, dialInfo.bEmergencyCall);
101
102 /**
103 * <idx>: integer type;
104 * call identification number as described in 3GPP TS 22.030 [19] subclause 4.5.5.1
105 * this number can be used in +CHLD command operations
106 * <dir>:
107 */
108 dialInfo.phoneNum = phoneNum;
109 /**
110 * <n> (parameter sets the adjustment for outgoing calls):
111 * 0 presentation indicator is used according to the subscription of the CLIR service
112 * 1 CLIR invocation
113 * 2 CLIR suppression
114 */
115 dialInfo.clirMode = clirMode;
116 /**
117 * An example of voice group call service request usage:
118 * ATD*17*753#500; (originate voice group call with the priority level 3)
119 * OK (voice group call setup was successful)
120 */
121
122 CellularCallConnectionIMS cellularCallConnectionIms;
123 return cellularCallConnectionIms.DialRequest(slotId, dialInfo);
124 }
125
HangUp(const CellularCallInfo & callInfo,CallSupplementType type)126 int32_t IMSControl::HangUp(const CellularCallInfo &callInfo, CallSupplementType type)
127 {
128 TELEPHONY_LOGI("HangUp start");
129 switch (type) {
130 case CallSupplementType::TYPE_DEFAULT: {
131 std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
132 auto pConnection = FindConnectionByIndex<ImsConnectionMap &, CellularCallConnectionIMS *>(
133 connectionMap_, callInfo.index);
134 if (pConnection == nullptr) {
135 TELEPHONY_LOGE("HangUp return, error type: connection is null");
136 return CALL_ERR_CALL_CONNECTION_NOT_EXIST;
137 }
138
139 if (DelayedSingleton<CellularCallRegister>::GetInstance() != nullptr) {
140 DelayedSingleton<CellularCallRegister>::GetInstance()->ReportSingleCallInfo(
141 pConnection->GetCallReportInfo(), TelCallState::CALL_STATUS_DISCONNECTING);
142 }
143 return pConnection->HangUpRequest(callInfo.slotId, callInfo.phoneNum, callInfo.index);
144 }
145 case CallSupplementType::TYPE_HANG_UP_HOLD_WAIT:
146 // release the second (active) call and recover the first (held) call
147 case CallSupplementType::TYPE_HANG_UP_ACTIVE: {
148 CellularCallConnectionIMS connection;
149 return connection.CallSupplementRequest(callInfo.slotId, type);
150 }
151 case CallSupplementType::TYPE_HANG_UP_ALL: {
152 TELEPHONY_LOGI("HangUp, hang up all call");
153 CellularCallConnectionIMS connection;
154 // The AT command for hanging up all calls is the same as the AT command for rejecting calls,
155 // so the reject interface is reused.
156 return connection.RejectRequest(callInfo.slotId, callInfo.phoneNum, callInfo.index);
157 }
158 default: {
159 TELEPHONY_LOGE("HangUp warring, type is invalid");
160 return TELEPHONY_ERR_ARGUMENT_INVALID;
161 }
162 }
163 }
164
Answer(const CellularCallInfo & callInfo)165 int32_t IMSControl::Answer(const CellularCallInfo &callInfo)
166 {
167 TELEPHONY_LOGI("IMSControl::Answer start");
168 std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
169 auto pConnection = FindConnectionByIndex<ImsConnectionMap &, CellularCallConnectionIMS *>(
170 connectionMap_, callInfo.index);
171 if (pConnection == nullptr) {
172 TELEPHONY_LOGE("HangUp return, error type: connection is null");
173 return CALL_ERR_CALL_CONNECTION_NOT_EXIST;
174 }
175 if (IsInState(connectionMap_, TelCallState::CALL_STATUS_HOLDING) &&
176 IsInState(connectionMap_, TelCallState::CALL_STATUS_ACTIVE)) {
177 TELEPHONY_LOGD("already threeway mode. hangup holding call and pickup new call");
178 int32_t ret = CheckAndHangupHoldingCall();
179 if (ret != TELEPHONY_SUCCESS) {
180 TELEPHONY_LOGE("hangup holding call failed");
181 return ret;
182 }
183 }
184 auto con = FindConnectionByState<ImsConnectionMap &, CellularCallConnectionIMS *>(
185 connectionMap_, TelCallState::CALL_STATUS_ACTIVE);
186 if (con != nullptr && !con->IsPendingHold() &&
187 pConnection->GetStatus() == TelCallState::CALL_STATUS_WAITING) {
188 TELEPHONY_LOGI("Answer there is an active call when you call, or third party call waiting");
189 if (con == nullptr) {
190 TELEPHONY_LOGE("Answer return, error type: con is null, there are no active calls");
191 return CALL_ERR_CALL_CONNECTION_NOT_EXIST;
192 }
193 return con->SwitchCallRequest(callInfo.slotId);
194 }
195 if (pConnection->GetStatus() == TelCallState::CALL_STATUS_ALERTING ||
196 pConnection->GetStatus() == TelCallState::CALL_STATUS_INCOMING ||
197 pConnection->GetStatus() == TelCallState::CALL_STATUS_WAITING) {
198 return pConnection->AnswerRequest(callInfo.slotId, callInfo.phoneNum, callInfo.videoState, callInfo.index);
199 }
200 TELEPHONY_LOGE("IMSControl::Answer return, error type: call state error, phone not ringing.");
201 return CALL_ERR_CALL_STATE;
202 }
203
CheckAndHangupHoldingCall()204 int32_t IMSControl::CheckAndHangupHoldingCall()
205 {
206 for (auto &it : connectionMap_) {
207 CellularCallConnectionIMS holdConn = it.second;
208 if (holdConn.GetStatus() == TelCallState::CALL_STATUS_HOLDING) {
209 auto callReportInfo = holdConn.GetCallReportInfo();
210 int32_t result = holdConn.HangUpRequest(callReportInfo.accountId,
211 callReportInfo.accountNum, callReportInfo.index);
212 if (result != TELEPHONY_SUCCESS) {
213 return result;
214 }
215 }
216 }
217 return TELEPHONY_SUCCESS;
218 }
219
Reject(const CellularCallInfo & callInfo)220 int32_t IMSControl::Reject(const CellularCallInfo &callInfo)
221 {
222 TELEPHONY_LOGI("IMSControl::Reject start");
223 std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
224 auto pConnection =
225 FindConnectionByIndex<ImsConnectionMap &, CellularCallConnectionIMS *>(connectionMap_, callInfo.index);
226 if (pConnection == nullptr) {
227 TELEPHONY_LOGE("IMSControl::Reject, error type: connection is null");
228 return CALL_ERR_CALL_CONNECTION_NOT_EXIST;
229 }
230 if (!pConnection->IsRingingState()) {
231 TELEPHONY_LOGE("IMSControl::Reject return, error type: call state error, phone not ringing.");
232 return CALL_ERR_CALL_STATE;
233 }
234 if (DelayedSingleton<CellularCallRegister>::GetInstance() != nullptr) {
235 DelayedSingleton<CellularCallRegister>::GetInstance()->ReportSingleCallInfo(
236 pConnection->GetCallReportInfo(), TelCallState::CALL_STATUS_DISCONNECTING);
237 }
238 return pConnection->RejectRequest(callInfo.slotId, callInfo.phoneNum, callInfo.index);
239 }
240
HoldCall(int32_t slotId)241 int32_t IMSControl::HoldCall(int32_t slotId)
242 {
243 TELEPHONY_LOGI("HoldCall start");
244 std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
245 if (IsInState(connectionMap_, TelCallState::CALL_STATUS_INCOMING)) {
246 TELEPHONY_LOGE("HoldCall return, error type: call state error.");
247 return CALL_ERR_CALL_STATE;
248 }
249 CellularCallConnectionIMS cellularCallConnectionIms;
250 return cellularCallConnectionIms.HoldCallRequest(slotId);
251 }
252
UnHoldCall(int32_t slotId)253 int32_t IMSControl::UnHoldCall(int32_t slotId)
254 {
255 TELEPHONY_LOGI("UnHoldCall start");
256 CellularCallConnectionIMS cellularCallConnectionIms;
257 return cellularCallConnectionIms.UnHoldCallRequest(slotId);
258 }
259
SwitchCall(int32_t slotId)260 int32_t IMSControl::SwitchCall(int32_t slotId)
261 {
262 TELEPHONY_LOGI("SwitchCall start");
263 CellularCallConnectionIMS cellularCallConnectionIms;
264 return cellularCallConnectionIms.SwitchCallRequest(slotId);
265 }
266
267 /**
268 * Add another remote party, to which a private communication has been established using
269 * the same procedures as in Section 1.3.8.1, if the number of remote parties does not then
270 * exceed the maximum number allowed, which results in an active multiParty call.
271 */
CombineConference(int32_t slotId)272 int32_t IMSControl::CombineConference(int32_t slotId)
273 {
274 TELEPHONY_LOGI("CombineConference entry");
275 CellularCallConnectionIMS connection;
276 int32_t voiceCall = 0;
277 return connection.CombineConferenceRequest(slotId, voiceCall);
278 }
279
HangUpAllConnection(int32_t slotId)280 int32_t IMSControl::HangUpAllConnection(int32_t slotId)
281 {
282 TELEPHONY_LOGI("HangUpAllConnection entry");
283 CellularCallConnectionIMS connection;
284 std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
285 if (connectionMap_.empty()) {
286 TELEPHONY_LOGI("connectionMap_ is empty.");
287 return TELEPHONY_ERROR;
288 }
289 for (auto &it : connectionMap_) {
290 int32_t index = it.second.GetIndex();
291 std::string number = it.second.GetNumber();
292 connection.RejectRequest(slotId, number, index);
293 }
294 // The AT command for hanging up all calls is the same as the AT command for rejecting calls,
295 // so the reject interface is reused.
296 return TELEPHONY_SUCCESS;
297 }
298
InviteToConference(int32_t slotId,const std::vector<std::string> & numberList)299 int32_t IMSControl::InviteToConference(int32_t slotId, const std::vector<std::string> &numberList)
300 {
301 TELEPHONY_LOGI("InviteToConference entry");
302 CellularCallConnectionIMS connection;
303 return connection.InviteToConferenceRequest(slotId, numberList);
304 }
305
KickOutFromConference(int32_t slotId,const std::string & KickOutString,int32_t index)306 int32_t IMSControl::KickOutFromConference(int32_t slotId, const std::string &KickOutString, int32_t index)
307 {
308 TELEPHONY_LOGI("KickOutFromConference entry");
309 if (KickOutString.empty()) {
310 TELEPHONY_LOGW("KickOutFromConference, splitString is empty.");
311 }
312
313 std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
314 auto pConnection = FindConnectionByIndex<ImsConnectionMap &, CellularCallConnectionIMS *>(connectionMap_, index);
315 if (pConnection != nullptr) {
316 return pConnection->KickOutFromConferenceRequest(slotId, pConnection->GetIndex());
317 }
318
319 TELEPHONY_LOGI("KickOutFromConference: connection cannot be matched, use index directly");
320 CellularCallConnectionIMS connection;
321 return connection.KickOutFromConferenceRequest(slotId, index);
322 }
323
StartRtt(int32_t slotId,const std::string & msg)324 int32_t IMSControl::StartRtt(int32_t slotId, const std::string &msg)
325 {
326 TELEPHONY_LOGI("StartRtt entry");
327 CellularCallConnectionIMS connection;
328 return connection.StartRttRequest(slotId, msg);
329 }
330
StopRtt(int32_t slotId)331 int32_t IMSControl::StopRtt(int32_t slotId)
332 {
333 TELEPHONY_LOGI("StopRtt entry");
334 CellularCallConnectionIMS connection;
335 return connection.StopRttRequest(slotId);
336 }
337
ReleaseAllConnection()338 void IMSControl::ReleaseAllConnection()
339 {
340 TELEPHONY_LOGI("ReleaseAllConnection entry");
341 std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
342 connectionMap_.clear();
343 }
344
GetConnectionMap()345 ImsConnectionMap IMSControl::GetConnectionMap()
346 {
347 TELEPHONY_LOGI("GetConnectionMap entry");
348 std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
349 return connectionMap_;
350 }
351
ReportImsCallsData(int32_t slotId,const ImsCurrentCallList & callInfoList)352 int32_t IMSControl::ReportImsCallsData(int32_t slotId, const ImsCurrentCallList &callInfoList)
353 {
354 std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
355 if (callInfoList.callSize <= 0) {
356 return ReportHangUpInfo(slotId);
357 } else if (callInfoList.callSize > 0 && connectionMap_.empty()) {
358 return ReportIncomingInfo(slotId, callInfoList);
359 } else if (callInfoList.callSize > 0 && !connectionMap_.empty()) {
360 return ReportUpdateInfo(slotId, callInfoList);
361 }
362 return TELEPHONY_ERROR;
363 }
364
ReportCallsData(int32_t slotId,const CallInfoList & callInfoList)365 int32_t IMSControl::ReportCallsData(int32_t slotId, const CallInfoList &callInfoList)
366 {
367 return TELEPHONY_ERROR;
368 }
369
ReportHangUpInfo(int32_t slotId)370 int32_t IMSControl::ReportHangUpInfo(int32_t slotId)
371 {
372 TELEPHONY_LOGI("ReportHangUpInfo entry");
373 CallsReportInfo callsReportInfo;
374 for (auto &it : connectionMap_) {
375 CallReportInfo reportInfo = it.second.GetCallReportInfo();
376 reportInfo.state = TelCallState::CALL_STATUS_DISCONNECTED;
377 reportInfo.accountId = slotId;
378 callsReportInfo.callVec.push_back(reportInfo);
379 GetCallFailReason(slotId, connectionMap_);
380 }
381 if (connectionMap_.empty()) {
382 TELEPHONY_LOGI("connectionMap_ is empty");
383 CallReportInfo reportInfo;
384 reportInfo.state = TelCallState::CALL_STATUS_DISCONNECTED;
385 reportInfo.accountId = slotId;
386 callsReportInfo.callVec.push_back(reportInfo);
387 }
388 if (DelayedSingleton<CellularCallRegister>::GetInstance() == nullptr) {
389 TELEPHONY_LOGE("ReportHangUpInfo return, GetInstance() is nullptr.");
390 return TELEPHONY_ERR_LOCAL_PTR_NULL;
391 }
392 callsReportInfo.slotId = slotId;
393 if (isIgnoredIncomingCall_) {
394 isIgnoredIncomingCall_ = false;
395 } else {
396 DelayedSingleton<CellularCallRegister>::GetInstance()->ReportCallsInfo(callsReportInfo);
397 }
398 ReleaseAllConnection();
399 return TELEPHONY_SUCCESS;
400 }
401
ReportIncomingInfo(int32_t slotId,const ImsCurrentCallList & imsCurrentCallInfoList)402 int32_t IMSControl::ReportIncomingInfo(int32_t slotId, const ImsCurrentCallList &imsCurrentCallInfoList)
403 {
404 TELEPHONY_LOGI("ReportIncomingInfo entry");
405 CallsReportInfo callsReportInfo;
406 for (int32_t i = 0; i < imsCurrentCallInfoList.callSize; ++i) {
407 CallReportInfo reportInfo = EncapsulationCallReportInfo(slotId, imsCurrentCallInfoList.calls[i]);
408
409 CellularCallConnectionIMS connection;
410 connection.SetStatus(static_cast<TelCallState>(imsCurrentCallInfoList.calls[i].state));
411 connection.SetIndex(imsCurrentCallInfoList.calls[i].index);
412 connection.SetNumber(imsCurrentCallInfoList.calls[i].number);
413 connection.SetOrUpdateCallReportInfo(reportInfo);
414 SetConnectionData(connectionMap_, imsCurrentCallInfoList.calls[i].index, connection);
415
416 callsReportInfo.callVec.push_back(reportInfo);
417 }
418 if (DelayedSingleton<CellularCallRegister>::GetInstance() == nullptr) {
419 TELEPHONY_LOGE("ReportIncomingInfo return, GetInstance() is nullptr.");
420 return TELEPHONY_ERR_ARGUMENT_INVALID;
421 }
422 callsReportInfo.slotId = slotId;
423 if (!DelayedSingleton<CellularCallRegister>::GetInstance()->IsCallManagerCallBackRegistered() &&
424 callsReportInfo.callVec.size() != 0 && callsReportInfo.callVec[0].state == TelCallState::CALL_STATUS_INCOMING) {
425 isIgnoredIncomingCall_ = true;
426 } else {
427 DelayedSingleton<CellularCallRegister>::GetInstance()->ReportCallsInfo(callsReportInfo);
428 }
429 return TELEPHONY_SUCCESS;
430 }
431
ReportUpdateInfo(int32_t slotId,const ImsCurrentCallList & callInfoList)432 int32_t IMSControl::ReportUpdateInfo(int32_t slotId, const ImsCurrentCallList &callInfoList)
433 {
434 TELEPHONY_LOGD("ReportUpdateInfo entry");
435 CallsReportInfo callsReportInfo;
436 for (int32_t i = 0; i < callInfoList.callSize; ++i) {
437 CallReportInfo reportInfo = EncapsulationCallReportInfo(slotId, callInfoList.calls[i]);
438 if (callInfoList.callSize == 1 && reportInfo.state == TelCallState::CALL_STATUS_WAITING) {
439 TELEPHONY_LOGI("only one call, report incoming state instead of waiting state");
440 reportInfo.state = TelCallState::CALL_STATUS_INCOMING;
441 }
442 auto pConnection = FindConnectionByIndex<ImsConnectionMap &, CellularCallConnectionIMS *>(
443 connectionMap_, callInfoList.calls[i].index);
444 if (pConnection == nullptr) {
445 CellularCallConnectionIMS connection;
446 connection.SetOrUpdateCallReportInfo(reportInfo);
447 connection.SetFlag(true);
448 connection.SetIndex(callInfoList.calls[i].index);
449 connection.SetNumber(callInfoList.calls[i].number);
450 SetConnectionData(connectionMap_, callInfoList.calls[i].index, connection);
451 } else {
452 TelCallState preCallState = pConnection->GetStatus();
453 pConnection->SetFlag(true);
454 pConnection->SetIndex(callInfoList.calls[i].index);
455 pConnection->SetNumber(callInfoList.calls[i].number);
456 pConnection->SetOrUpdateCallReportInfo(reportInfo);
457 TelCallState curCallState = pConnection->GetStatus();
458 if (IsConnectedOut(preCallState, curCallState)) {
459 pConnection->UpdateCallNumber(pendingPhoneNumber_);
460 pendingPhoneNumber_.clear();
461 ExecutePostDial(slotId, pConnection->GetIndex());
462 }
463 }
464 callsReportInfo.callVec.push_back(reportInfo);
465 }
466 callsReportInfo.slotId = slotId;
467 DeleteConnection(callsReportInfo, callInfoList);
468 if (DelayedSingleton<CellularCallRegister>::GetInstance() == nullptr) {
469 TELEPHONY_LOGE("ReportUpdateInfo return, GetInstance() is nullptr.");
470 return TELEPHONY_ERR_LOCAL_PTR_NULL;
471 }
472 if (isIgnoredIncomingCall_) {
473 isIgnoredIncomingCall_ = false;
474 } else {
475 DelayedSingleton<CellularCallRegister>::GetInstance()->ReportCallsInfo(callsReportInfo);
476 }
477 return TELEPHONY_SUCCESS;
478 }
479
EncapsulationCallReportInfo(int32_t slotId,const ImsCurrentCall & callInfo)480 CallReportInfo IMSControl::EncapsulationCallReportInfo(int32_t slotId, const ImsCurrentCall &callInfo)
481 {
482 TELEPHONY_LOGD("EncapsulationCallReportInfo entry");
483 CallReportInfo callReportInfo;
484 if (memset_s(&callReportInfo, sizeof(callReportInfo), 0, sizeof(callReportInfo)) != EOK) {
485 TELEPHONY_LOGE("EncapsulationCallReportInfo return, memset_s fail.");
486 return callReportInfo;
487 }
488
489 StandardizeUtils standardizeUtils;
490 std::string phoneNumber = callInfo.number.empty() ? callInfo.name : callInfo.number;
491 std::string newString = standardizeUtils.FormatNumberAndToa(phoneNumber, callInfo.toa);
492 size_t cpyLen = strlen(newString.c_str()) + 1;
493 if (cpyLen > static_cast<size_t>(kMaxNumberLen + 1)) {
494 TELEPHONY_LOGE("EncapsulationCallReportInfo return, strcpy_s fail.");
495 return callReportInfo;
496 }
497 if (strcpy_s(callReportInfo.accountNum, cpyLen, newString.c_str()) != EOK) {
498 TELEPHONY_LOGE("EncapsulationCallReportInfo return, strcpy_s fail.");
499 return callReportInfo;
500 }
501 callReportInfo.index = callInfo.index;
502 callReportInfo.accountId = slotId;
503 callReportInfo.state = static_cast<TelCallState>(callInfo.state);
504 callReportInfo.voiceDomain = callInfo.voiceDomain;
505 callReportInfo.callType = CallType::TYPE_IMS;
506 switch (callInfo.callType) {
507 case ImsCallType::TEL_IMS_CALL_TYPE_VOICE:
508 callReportInfo.callMode = VideoStateType::TYPE_VOICE;
509 break;
510 case ImsCallType::TEL_IMS_CALL_TYPE_VT_TX:
511 callReportInfo.callMode = VideoStateType::TYPE_SEND_ONLY;
512 break;
513 case ImsCallType::TEL_IMS_CALL_TYPE_VT_RX:
514 callReportInfo.callMode = VideoStateType::TYPE_RECEIVE_ONLY;
515 break;
516 case ImsCallType::TEL_IMS_CALL_TYPE_VT:
517 callReportInfo.callMode = VideoStateType::TYPE_VIDEO;
518 break;
519 default:
520 callReportInfo.callMode = VideoStateType::TYPE_VOICE;
521 break;
522 }
523 callReportInfo.mpty = callInfo.mpty;
524 callReportInfo.crsType = callInfo.toneType;
525 callReportInfo.originalCallType = callInfo.callInitialType;
526 return callReportInfo;
527 }
528
DeleteConnection(CallsReportInfo & callsReportInfo,const ImsCurrentCallList & callInfoList)529 void IMSControl::DeleteConnection(CallsReportInfo &callsReportInfo, const ImsCurrentCallList &callInfoList)
530 {
531 TELEPHONY_LOGI("DeleteConnection entry");
532 auto it = connectionMap_.begin();
533 while (it != connectionMap_.end()) {
534 if (!it->second.GetFlag()) {
535 CallReportInfo callReportInfo = it->second.GetCallReportInfo();
536 callReportInfo.state = TelCallState::CALL_STATUS_DISCONNECTED;
537 callsReportInfo.callVec.push_back(callReportInfo);
538 connectionMap_.erase(it++);
539 GetCallFailReason(callsReportInfo.slotId, connectionMap_);
540 } else {
541 it->second.SetFlag(false);
542 ++it;
543 }
544 }
545 }
546
ExecutePostDial(int32_t slotId,int64_t callId)547 int32_t IMSControl::ExecutePostDial(int32_t slotId, int64_t callId)
548 {
549 TELEPHONY_LOGI("ExecutePostDial entry");
550 std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
551 if (connectionMap_.empty()) {
552 TELEPHONY_LOGE("connectionMap_ is empty.");
553 return TELEPHONY_ERROR;
554 }
555 auto pConnection = FindConnectionByIndex<ImsConnectionMap &, CellularCallConnectionIMS *>(connectionMap_, callId);
556 if (pConnection == nullptr) {
557 return TELEPHONY_ERR_LOCAL_PTR_NULL;
558 }
559 char currentChar;
560 PostDialCallState state = pConnection->ProcessNextChar(slotId, currentChar);
561 switch (state) {
562 case PostDialCallState::POST_DIAL_CALL_STARTED:
563 DelayedSingleton<CellularCallRegister>::GetInstance()->ReportPostDialChar(currentChar);
564 break;
565 case PostDialCallState::POST_DIAL_CALL_DELAY:
566 DelayedSingleton<CellularCallRegister>::GetInstance()->ReportPostDialDelay(
567 pConnection->GetLeftPostDialCallString());
568 break;
569 default:
570 break;
571 }
572 return TELEPHONY_SUCCESS;
573 }
574
PostDialProceed(const CellularCallInfo & callInfo,const bool proceed)575 int32_t IMSControl::PostDialProceed(const CellularCallInfo &callInfo, const bool proceed)
576 {
577 TELEPHONY_LOGI("PostDialProceed entry");
578 std::string networkAddress;
579 std::string postDialString;
580 StandardizeUtils standardizeUtils;
581 standardizeUtils.ExtractAddressAndPostDial(callInfo.phoneNum, networkAddress, postDialString);
582 std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
583 auto pConnection = FindConnectionByIndex<ImsConnectionMap &, CellularCallConnectionIMS *>(connectionMap_,
584 callInfo.index);
585 if (pConnection == nullptr) {
586 TELEPHONY_LOGE("ims pConnection is nullptr!");
587 return TELEPHONY_ERR_LOCAL_PTR_NULL;
588 }
589 if (proceed) {
590 ExecutePostDial(callInfo.slotId, pConnection->GetIndex());
591 } else {
592 pConnection->SetPostDialCallState(PostDialCallState::POST_DIAL_CALL_CANCELED);
593 }
594 return TELEPHONY_SUCCESS;
595 }
596
RestoreConnection(const std::vector<CellularCallInfo> & infos,int32_t slotId)597 int32_t IMSControl::RestoreConnection(const std::vector<CellularCallInfo> &infos, int32_t slotId)
598 {
599 TELEPHONY_LOGI("RestoreConnection entry");
600 std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
601 for (auto &info : infos) {
602 if (info.callType == CallType::TYPE_IMS && info.slotId == slotId) {
603 CellularCallConnectionIMS connectionIMS;
604 connectionIMS.SetIndex(info.index);
605 connectionIMS.SetNumber(info.phoneNum);
606 SetConnectionData(connectionMap_, info.index, connectionIMS);
607 }
608 }
609 return TELEPHONY_SUCCESS;
610 }
611
ReportHangUp(const std::vector<CellularCallInfo> & infos,int32_t slotId)612 int32_t IMSControl::ReportHangUp(const std::vector<CellularCallInfo> &infos, int32_t slotId)
613 {
614 CallsReportInfo callsReportInfo;
615 callsReportInfo.slotId = slotId;
616 for (const auto &info : infos) {
617 if (info.callType == CallType::TYPE_IMS && info.slotId == slotId) {
618 CallReportInfo imsCallReportInfo;
619 if (memset_s(imsCallReportInfo.accountNum, kMaxNumberLen + 1, 0, kMaxNumberLen + 1) != EOK) {
620 TELEPHONY_LOGE("memset_s fail");
621 return TELEPHONY_ERR_MEMSET_FAIL;
622 }
623 if (memcpy_s(imsCallReportInfo.accountNum, kMaxNumberLen, info.phoneNum, kMaxNumberLen) != EOK) {
624 TELEPHONY_LOGE("memcpy_s fail");
625 return TELEPHONY_ERR_MEMCPY_FAIL;
626 }
627 imsCallReportInfo.index = info.index;
628 imsCallReportInfo.accountId = info.slotId;
629 imsCallReportInfo.callType = CallType::TYPE_IMS;
630 imsCallReportInfo.callMode =
631 static_cast<bool>(info.callType) ? VideoStateType::TYPE_VIDEO : VideoStateType::TYPE_VOICE;
632 imsCallReportInfo.state = TelCallState::CALL_STATUS_DISCONNECTED;
633 callsReportInfo.callVec.push_back(imsCallReportInfo);
634 }
635 }
636 if (DelayedSingleton<CellularCallRegister>::GetInstance() == nullptr) {
637 TELEPHONY_LOGE("CellularCallRegister instance is nullptr");
638 return TELEPHONY_ERR_LOCAL_PTR_NULL;
639 }
640 DelayedSingleton<CellularCallRegister>::GetInstance()->ReportCallsInfo(callsReportInfo);
641 return TELEPHONY_SUCCESS;
642 }
643
DialAfterHold(int32_t slotId)644 void IMSControl::DialAfterHold(int32_t slotId)
645 {
646 TELEPHONY_LOGI("DialAfterHold entry");
647 std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
648 for (auto &connection : connectionMap_) {
649 if (connection.second.IsNeedToDial()) {
650 ImsDialInfoStruct holdToDialInfo = connection.second.GetHoldToDialInfo();
651 CellularCallConnectionIMS cellularCallConnectionIms;
652 cellularCallConnectionIms.DialRequest(slotId, holdToDialInfo);
653 connection.second.SetDialFlag(false);
654 break;
655 }
656 }
657 }
658
RecoverPendingHold()659 void IMSControl::RecoverPendingHold()
660 {
661 TELEPHONY_LOGI("RecoverPendingHold entry");
662 std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
663 for (auto &connection : connectionMap_) {
664 if (connection.second.IsPendingHold()) {
665 connection.second.UpdatePendingHoldFlag(false);
666 break;
667 }
668 }
669 }
670 } // namespace Telephony
671 } // namespace OHOS
672