• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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