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