• 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 "cs_control.h"
17 
18 #include "cellular_call_hisysevent.h"
19 #include "cellular_call_register.h"
20 #include "module_service_utils.h"
21 #include "securec.h"
22 #include "standardize_utils.h"
23 
24 namespace OHOS {
25 namespace Telephony {
~CSControl()26 CSControl::~CSControl()
27 {
28     ReleaseAllConnection();
29 }
30 
Dial(const CellularCallInfo & callInfo)31 int32_t CSControl::Dial(const CellularCallInfo &callInfo)
32 {
33     TELEPHONY_LOGI("Dial start");
34     DelayedSingleton<CellularCallHiSysEvent>::GetInstance()->SetCallParameterInfo(
35         callInfo.slotId, static_cast<int32_t>(callInfo.callType), callInfo.videoState);
36     int32_t ret = DialPreJudgment(callInfo);
37     if (ret != TELEPHONY_SUCCESS) {
38         return ret;
39     }
40 
41     ModuleServiceUtils moduleServiceUtils;
42     PhoneType netType = moduleServiceUtils.GetNetworkStatus(callInfo.slotId);
43     if (netType == PhoneType::PHONE_TYPE_IS_GSM) {
44         return DialGsm(callInfo);
45     }
46     if (netType == PhoneType::PHONE_TYPE_IS_CDMA) {
47         return DialCdma(callInfo);
48     }
49     TELEPHONY_LOGE("Dial return, net type error.");
50     CellularCallHiSysEvent::WriteDialCallFaultEvent(callInfo.slotId, static_cast<int32_t>(callInfo.callType),
51         callInfo.videoState, CALL_ERR_UNSUPPORTED_NETWORK_TYPE, "Network type error");
52     return CALL_ERR_UNSUPPORTED_NETWORK_TYPE;
53 }
54 
DialCdma(const CellularCallInfo & callInfo)55 int32_t CSControl::DialCdma(const CellularCallInfo &callInfo)
56 {
57     TELEPHONY_LOGI("DialCdma entry.");
58     StandardizeUtils standardizeUtils;
59     // Remove the phone number separator
60     std::string newPhoneNum = standardizeUtils.RemoveSeparatorsPhoneNumber(callInfo.phoneNum);
61 
62     CLIRMode clirMode = CLIRMode::DEFAULT;
63     if (IsNeedExecuteMMI(callInfo.slotId, newPhoneNum, clirMode)) {
64         TELEPHONY_LOGI("DialCdma return, mmi code type.");
65         return RETURN_TYPE_MMI;
66     }
67 
68     if (!CanCall(connectionMap_)) {
69         TELEPHONY_LOGE("CSControl::DialCdma return, error type: call state error.");
70         CellularCallHiSysEvent::WriteDialCallFaultEvent(callInfo.slotId, static_cast<int32_t>(callInfo.callType),
71             callInfo.videoState, CALL_ERR_CALL_COUNTS_EXCEED_LIMIT, "cs cdma dial call state error");
72         return CALL_ERR_CALL_COUNTS_EXCEED_LIMIT;
73     }
74 
75     if (IsInState(connectionMap_, TelCallState::CALL_STATUS_ACTIVE)) {
76         TELEPHONY_LOGI("DialCdma, CDMA is have connection in active state.");
77         CellularCallConnectionCS csConnection;
78         return csConnection.SendCDMAThreeWayDialRequest(callInfo.slotId);
79     }
80 
81     return EncapsulateDialCommon(callInfo.slotId, newPhoneNum, clirMode);
82 }
83 
DialGsm(const CellularCallInfo & callInfo)84 int32_t CSControl::DialGsm(const CellularCallInfo &callInfo)
85 {
86     TELEPHONY_LOGI("DialGsm entry.");
87     StandardizeUtils standardizeUtils;
88     // Remove the phone number separator
89     std::string newPhoneNum = standardizeUtils.RemoveSeparatorsPhoneNumber(callInfo.phoneNum);
90 
91     CLIRMode clirMode = CLIRMode::DEFAULT;
92     if (IsNeedExecuteMMI(callInfo.slotId, newPhoneNum, clirMode)) {
93         TELEPHONY_LOGI("DialGsm return, mmi code type.");
94         return RETURN_TYPE_MMI;
95     }
96 
97     if (!CanCall(connectionMap_)) {
98         TELEPHONY_LOGE("DialGsm return, error type: call state error.");
99         CellularCallHiSysEvent::WriteDialCallFaultEvent(callInfo.slotId, static_cast<int32_t>(callInfo.callType),
100             callInfo.videoState, CALL_ERR_CALL_COUNTS_EXCEED_LIMIT, "cs gsm dial call state error");
101         return CALL_ERR_CALL_COUNTS_EXCEED_LIMIT;
102     }
103 
104     // Calls can be put on hold, recovered, released, added to conversation,
105     // and transferred similarly as defined in 3GPP TS 22.030 [19].
106     if (IsInState(connectionMap_, TelCallState::CALL_STATUS_ACTIVE)) {
107         // New calls must be active, so other calls need to be hold
108         TELEPHONY_LOGI("DialGsm, GSM is have connection in active state.");
109         CellularCallConnectionCS pConnection;
110 
111         // Delay dialing to prevent failure to add a new call while making a multi-party call
112         // Will it block the main thread or other threads? Will the reception of messages be blocked during sleep?
113         // - a call can be temporarily disconnected from the ME but the connection is retained by the network
114         pConnection.SwitchCallRequest(callInfo.slotId);
115     }
116     return EncapsulateDialCommon(callInfo.slotId, newPhoneNum, clirMode);
117 }
118 
EncapsulateDialCommon(int32_t slotId,const std::string & phoneNum,CLIRMode & clirMode)119 int32_t CSControl::EncapsulateDialCommon(int32_t slotId, const std::string &phoneNum, CLIRMode &clirMode)
120 {
121     DialRequestStruct dialRequest;
122     /**
123      * <idx>: integer type;
124      * call identification number as described in 3GPP TS 22.030 [19] subclause 4.5.5.1
125      * this number can be used in +CHLD command operations
126      * <dir>:
127      */
128     dialRequest.phoneNum = phoneNum;
129 
130     /**
131      * <n> (parameter sets the adjustment for outgoing calls):
132      *  0	presentation indicator is used according to the subscription of the CLIR service
133      *  1	CLIR invocation
134      *  2	CLIR suppression
135      */
136     dialRequest.clirMode = clirMode;
137 
138     /**
139      * An example of voice group call service request usage:
140      * ATD*17*753#500; (originate voice group call with the priority level 3)
141      * OK (voice group call setup was successful)
142      */
143     CellularCallConnectionCS csConnection;
144     return csConnection.DialRequest(slotId, dialRequest);
145 }
146 
HangUp(const CellularCallInfo & callInfo,CallSupplementType type)147 int32_t CSControl::HangUp(const CellularCallInfo &callInfo, CallSupplementType type)
148 {
149     TELEPHONY_LOGI("HangUp start");
150     switch (type) {
151         case CallSupplementType::TYPE_DEFAULT: {
152             // Match the session connection according to the phone number string
153             auto pConnection =
154                 GetConnectionData<CsConnectionMap &, CellularCallConnectionCS *>(connectionMap_, callInfo.phoneNum);
155             if (pConnection == nullptr) {
156                 TELEPHONY_LOGI("HangUp: connection cannot be matched, use index directly");
157                 pConnection = FindConnectionByIndex<CsConnectionMap &, CellularCallConnectionCS *>(
158                     connectionMap_, callInfo.index);
159             }
160             if (pConnection == nullptr) {
161                 TELEPHONY_LOGE("CSControl::HangUp, error type: connection is null");
162                 CellularCallHiSysEvent::WriteHangUpFaultEvent(
163                     callInfo.slotId, callInfo.callId, CALL_ERR_CALL_CONNECTION_NOT_EXIST, "HangUp pConnection is null");
164                 return CALL_ERR_CALL_CONNECTION_NOT_EXIST;
165             }
166 
167             if (DelayedSingleton<CellularCallRegister>::GetInstance() != nullptr) {
168                 DelayedSingleton<CellularCallRegister>::GetInstance()->ReportSingleCallInfo(
169                     pConnection->GetCallReportInfo(), TelCallState::CALL_STATUS_DISCONNECTING);
170             }
171 
172             /**
173              * The "directory number" case shall be handled with dial command D,
174              * and the END case with hangup command H (or +CHUP).
175              * (e.g. +CHLD: (0,1,1x,2,2x,3)).
176              * NOTE: Call Hold, MultiParty and Explicit Call Transfer are only applicable to teleservice 11.
177              */
178             return pConnection->HangUpRequest(callInfo.slotId);
179         }
180         // 3GPP TS 27.007 V3.9.0 (2001-06) Call related supplementary services +CHLD
181         // 3GPP TS 27.007 V3.9.0 (2001-06) 7.22	Informative examples
182         case CallSupplementType::TYPE_HANG_UP_HOLD_WAIT:
183         // release the second (active) call and recover the first (held) call
184         case CallSupplementType::TYPE_HANG_UP_ACTIVE: {
185             CellularCallConnectionCS connection;
186             return connection.CallSupplementRequest(callInfo.slotId, type);
187         }
188         case CallSupplementType::TYPE_HANG_UP_ALL: {
189             TELEPHONY_LOGI("HangUp, hang up all call");
190             CellularCallConnectionCS connection;
191             // The AT command for hanging up all calls is the same as the AT command for rejecting calls,
192             // so the reject interface is reused.
193             return connection.RejectRequest(callInfo.slotId);
194         }
195         default: {
196             TELEPHONY_LOGE("HangUp warring, type is invalid");
197             CellularCallHiSysEvent::WriteHangUpFaultEvent(
198                 callInfo.slotId, callInfo.callId, TELEPHONY_ERR_ARGUMENT_INVALID, "HangUp type is invalid");
199             return TELEPHONY_ERR_ARGUMENT_INVALID;
200         }
201     }
202 }
203 
Answer(const CellularCallInfo & callInfo)204 int32_t CSControl::Answer(const CellularCallInfo &callInfo)
205 {
206     auto pConnection =
207         GetConnectionData<CsConnectionMap &, CellularCallConnectionCS *>(connectionMap_, callInfo.phoneNum);
208     if (pConnection == nullptr) {
209         TELEPHONY_LOGI("Answer: connection cannot be matched, use index directly");
210         pConnection =
211             FindConnectionByIndex<CsConnectionMap &, CellularCallConnectionCS *>(connectionMap_, callInfo.index);
212     }
213     if (pConnection == nullptr) {
214         TELEPHONY_LOGE("Answer return, error type: connection is null");
215         CellularCallHiSysEvent::WriteAnswerCallFaultEvent(callInfo.slotId, callInfo.callId, callInfo.videoState,
216             CALL_ERR_CALL_CONNECTION_NOT_EXIST, "get connection data is null");
217         return CALL_ERR_CALL_CONNECTION_NOT_EXIST;
218     }
219 
220     /**
221      * <stat> (state of the call):
222      * 0 active
223      * 1 held
224      * 2 dialing (MO call)
225      * 3 alerting (MO call)
226      * 4 incoming (MT call)
227      * 5 waiting (MT call)
228      */
229     // There is an active call when you call, or third party call waiting
230     if (IsInState(connectionMap_, TelCallState::CALL_STATUS_ACTIVE) ||
231         pConnection->GetStatus() == TelCallState::CALL_STATUS_WAITING) {
232         TELEPHONY_LOGI("Answer there is an active call when you call, or third party call waiting");
233         auto con = FindConnectionByState<CsConnectionMap &, CellularCallConnectionCS *>(
234             connectionMap_, TelCallState::CALL_STATUS_ACTIVE);
235         if (con != nullptr) {
236             /**
237              * shows commands to start the call, to switch from voice to data (In Call Modification) and to hang up
238              * the call. +CMOD and +FCLASS commands indicate the current settings before dialling or answering
239              * command, not that they shall be given just before D or A command.
240              */
241             TELEPHONY_LOGI("Answer: There is an active session currently, and it needs to hold");
242             con->SwitchCallRequest(callInfo.slotId);
243         } else {
244             TELEPHONY_LOGE("Answer return, error type: con is null, there are no active calls");
245         }
246     }
247 
248     if (pConnection->GetStatus() == TelCallState::CALL_STATUS_INCOMING ||
249         pConnection->GetStatus() == TelCallState::CALL_STATUS_ALERTING ||
250         pConnection->GetStatus() == TelCallState::CALL_STATUS_WAITING) {
251         return pConnection->AnswerRequest(callInfo.slotId);
252     }
253 
254     TELEPHONY_LOGE("CSControl::Answer return, error type: call state error, phone not ringing.");
255     CellularCallHiSysEvent::WriteAnswerCallFaultEvent(callInfo.slotId, callInfo.callId, callInfo.videoState,
256         CALL_ERR_CALL_STATE, "call state error phone not ringing");
257     return CALL_ERR_CALL_STATE;
258 }
259 
Reject(const CellularCallInfo & callInfo)260 int32_t CSControl::Reject(const CellularCallInfo &callInfo)
261 {
262     auto pConnection =
263         GetConnectionData<CsConnectionMap &, CellularCallConnectionCS *>(connectionMap_, callInfo.phoneNum);
264     if (pConnection == nullptr) {
265         TELEPHONY_LOGI("Reject: connection cannot be matched, use index directly");
266         pConnection =
267             FindConnectionByIndex<CsConnectionMap &, CellularCallConnectionCS *>(connectionMap_, callInfo.index);
268     }
269     if (pConnection == nullptr) {
270         TELEPHONY_LOGE("CSControl::Reject, error type: connection is null");
271         CellularCallHiSysEvent::WriteHangUpFaultEvent(
272             callInfo.slotId, callInfo.callId, CALL_ERR_CALL_CONNECTION_NOT_EXIST, "Reject pConnection is null");
273         return CALL_ERR_CALL_CONNECTION_NOT_EXIST;
274     }
275 
276     /**
277      * shows commands to start the call, to switch from voice to data (In Call Modification) and to hang up the call.
278      * +CMOD and +FCLASS commands indicate the current settings before dialling or answering command,
279      * not that they shall be given just before D or A command.
280      */
281     if (!pConnection->IsRingingState()) {
282         TELEPHONY_LOGE("CSControl::Reject return, error type: call state error, phone not ringing.");
283         CellularCallHiSysEvent::WriteHangUpFaultEvent(
284             callInfo.slotId, callInfo.callId, CALL_ERR_CALL_STATE, "Reject call state error phone not ringing");
285         return CALL_ERR_CALL_STATE;
286     }
287     if (DelayedSingleton<CellularCallRegister>::GetInstance() != nullptr) {
288         DelayedSingleton<CellularCallRegister>::GetInstance()->ReportSingleCallInfo(
289             pConnection->GetCallReportInfo(), TelCallState::CALL_STATUS_DISCONNECTING);
290     }
291     return pConnection->RejectRequest(callInfo.slotId);
292 }
293 
HoldCall(int32_t slotId)294 int32_t CSControl::HoldCall(int32_t slotId)
295 {
296     /**
297      * When the call hold service is invoked, communication is interrupted on the traffic channel and the traffic
298      * channel is released from the existing call. The traffic channel is reserved for the served mobile subscriber
299      * invoking the call hold service. The served mobile subscriber can only have one call on hold at a time.
300      */
301     if (IsInState(connectionMap_, TelCallState::CALL_STATUS_INCOMING)) {
302         TELEPHONY_LOGE("HoldCall return, error type: call state error.");
303         return CALL_ERR_CALL_STATE;
304     }
305     CellularCallConnectionCS connection;
306     return connection.HoldRequest(slotId);
307 }
308 
UnHoldCall(int32_t slotId)309 int32_t CSControl::UnHoldCall(int32_t slotId)
310 {
311     // A notification shall be send towards the previously held party that the call has been retrieved.
312     if (IsInState(connectionMap_, TelCallState::CALL_STATUS_INCOMING)) {
313         TELEPHONY_LOGE("UnHoldCall return, error type: call state error.");
314         return CALL_ERR_CALL_STATE;
315     }
316     CellularCallConnectionCS connection;
317     return connection.UnHoldCallRequest(slotId);
318 }
319 
SwitchCall(int32_t slotId)320 int32_t CSControl::SwitchCall(int32_t slotId)
321 {
322     /**
323      * If the served mobile subscriber is connected to an active call and has another call on hold, she can:
324      * 1) Alternate from one call to the other.
325      * 2) Disconnect the active call.
326      * 3) Disconnect the held call.
327      * 4) Disconnect both calls.
328      */
329     if (IsInState(connectionMap_, TelCallState::CALL_STATUS_INCOMING)) {
330         TELEPHONY_LOGE("SwitchCall return, error type: call state error.");
331         return CALL_ERR_CALL_STATE;
332     }
333     CellularCallConnectionCS connection;
334     return connection.SwitchCallRequest(slotId);
335 }
336 
337 /**
338  * Explicitly choose one remote party to have a private communication with.
339  * This results in that remote party being removed from the multiParty call which is placed on hold,
340  * and the conversation between the served mobile subscriber and the designated remote party being a normal
341  * active call. The remaining remote parties may have communication with each other in this state.
342  */
SeparateConference(int32_t slotId,const std::string & splitString,int32_t index)343 int32_t CSControl::SeparateConference(int32_t slotId, const std::string &splitString, int32_t index)
344 {
345     if (splitString.empty()) {
346         TELEPHONY_LOGW("SeparateConference, splitString is empty.");
347     }
348 
349     auto pConnection = GetConnectionData<CsConnectionMap &, CellularCallConnectionCS *>(connectionMap_, splitString);
350     if (pConnection != nullptr) {
351         return pConnection->SeparateConferenceRequest(slotId, pConnection->GetIndex(), VOICE_CALL);
352     }
353 
354     TELEPHONY_LOGI("SeparateConference: connection cannot be matched, use index directly");
355     CellularCallConnectionCS connection;
356     return connection.SeparateConferenceRequest(slotId, index, VOICE_CALL);
357 }
358 
359 /**
360  * Add another remote party, to which a private communication has been established using
361  * the same procedures as in Section 1.3.8.1, if the number of remote parties does not then
362  * exceed the maximum number allowed, which results in an active multiParty call.
363  */
CombineConference(int32_t slotId)364 int32_t CSControl::CombineConference(int32_t slotId)
365 {
366     CellularCallConnectionCS connectionCs;
367     return connectionCs.CombineConferenceRequest(slotId, VOICE_CALL);
368 }
369 
HangUpAllConnection(int32_t slotId)370 int32_t CSControl::HangUpAllConnection(int32_t slotId)
371 {
372     TELEPHONY_LOGI("HangUpAllConnection entry");
373     CellularCallConnectionCS connection;
374     // The AT command for hanging up all calls is the same as the AT command for rejecting calls,
375     // so the reject interface is reused.
376     return connection.RejectRequest(slotId);
377 }
378 
CalculateInternationalRoaming(int32_t slotId) const379 bool CSControl::CalculateInternationalRoaming(int32_t slotId) const
380 {
381     bool ret = true;
382     ModuleServiceUtils moduleServiceUtils;
383     std::string operatorCountryIso = moduleServiceUtils.GetNetworkCountryCode(slotId);
384     std::string simCountryIso = moduleServiceUtils.GetIsoCountryCode(slotId);
385     ret = !operatorCountryIso.empty() && !simCountryIso.empty() && (operatorCountryIso != simCountryIso);
386     if (ret) {
387         if (simCountryIso == "us") {
388             ret = operatorCountryIso != "vi";
389         } else if (simCountryIso == "vi") {
390             ret = operatorCountryIso != "us";
391         }
392     }
393     return ret;
394 }
395 
ReportCallsData(int32_t slotId,const CallInfoList & callInfoList)396 int32_t CSControl::ReportCallsData(int32_t slotId, const CallInfoList &callInfoList)
397 {
398     if (callInfoList.callSize <= 0 && !connectionMap_.empty()) {
399         return ReportHungUpInfo(slotId);
400     } else if (callInfoList.callSize > 0 && connectionMap_.empty()) {
401         return ReportIncomingInfo(slotId, callInfoList);
402     } else if (callInfoList.callSize > 0 && !connectionMap_.empty()) {
403         return ReportUpdateInfo(slotId, callInfoList);
404     }
405     return TELEPHONY_ERROR;
406 }
407 
ReportUpdateInfo(int32_t slotId,const CallInfoList & callInfoList)408 int32_t CSControl::ReportUpdateInfo(int32_t slotId, const CallInfoList &callInfoList)
409 {
410     TELEPHONY_LOGI("ReportUpdateInfo entry");
411     CallsReportInfo callsReportInfo;
412     for (int32_t i = 0; i < callInfoList.callSize; ++i) {
413         CallReportInfo reportInfo = EncapsulationCallReportInfo(slotId, callInfoList.calls[i]);
414 
415         auto pConnection = GetConnectionData<CsConnectionMap &, CellularCallConnectionCS *>(
416             connectionMap_, callInfoList.calls[i].number);
417         if (pConnection == nullptr) {
418             CellularCallConnectionCS connection;
419             connection.SetOrUpdateCallReportInfo(reportInfo);
420             connection.SetFlag(true);
421             connection.SetIndex(callInfoList.calls[i].index);
422             SetConnectionData(connectionMap_, callInfoList.calls[i].number, connection);
423         } else {
424             pConnection->SetFlag(true);
425             pConnection->SetIndex(callInfoList.calls[i].index);
426             pConnection->SetOrUpdateCallReportInfo(reportInfo);
427         }
428         callsReportInfo.callVec.push_back(reportInfo);
429     }
430     callsReportInfo.slotId = slotId;
431     DeleteConnection(callsReportInfo, callInfoList);
432     if (DelayedSingleton<CellularCallRegister>::GetInstance() == nullptr) {
433         TELEPHONY_LOGE("ReportUpdateInfo return, GetInstance() is nullptr.");
434         return TELEPHONY_ERR_LOCAL_PTR_NULL;
435     }
436     if (!isIgnoredIncomingCall_) {
437         DelayedSingleton<CellularCallRegister>::GetInstance()->ReportCallsInfo(callsReportInfo);
438     }
439     return TELEPHONY_SUCCESS;
440 }
441 
DeleteConnection(CallsReportInfo & callsReportInfo,const CallInfoList & callInfoList)442 void CSControl::DeleteConnection(CallsReportInfo &callsReportInfo, const CallInfoList &callInfoList)
443 {
444     auto it = connectionMap_.begin();
445     while (it != connectionMap_.end()) {
446         CallReportInfo callReportInfo = it->second.GetCallReportInfo();
447         if (!it->second.GetFlag()) {
448             callReportInfo.state = TelCallState::CALL_STATUS_DISCONNECTED;
449             callsReportInfo.callVec.push_back(callReportInfo);
450             connectionMap_.erase(it++);
451             GetCallFailReason(callsReportInfo.slotId, connectionMap_);
452         } else {
453             it->second.SetFlag(false);
454             ++it;
455         }
456     }
457 }
458 
EncapsulationCallReportInfo(int32_t slotId,const CallInfo & callInfo)459 CallReportInfo CSControl::EncapsulationCallReportInfo(int32_t slotId, const CallInfo &callInfo)
460 {
461     CallReportInfo callReportInfo;
462     if (memset_s(&callReportInfo, sizeof(callReportInfo), 0, sizeof(callReportInfo)) != EOK) {
463         TELEPHONY_LOGE("EncapsulationCallReportInfo return, memset_s fail.");
464         return callReportInfo;
465     }
466 
467     /**
468      * <idx>: integer type;
469      * call identification number as described in 3GPP TS 22.030 [19] subclause 4.5.5.1
470      * this number can be used in +CHLD command operations
471      * <dir>:
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 
483     /**
484      * <stat> (state of the call):
485      * 0 active
486      * 1 held
487      * 2 dialing (MO call)
488      * 3 alerting (MO call)
489      * 4 incoming (MT call)
490      * 5 waiting (MT call)
491      */
492     callReportInfo.index = callInfo.index;
493     callReportInfo.accountId = slotId;
494     callReportInfo.voiceDomain = callInfo.voiceDomain;
495     callReportInfo.state = static_cast<TelCallState>(callInfo.state);
496     callReportInfo.callType = CallType::TYPE_CS;
497     callReportInfo.callMode = VideoStateType::TYPE_VOICE;
498     return callReportInfo;
499 }
500 
ReportIncomingInfo(int32_t slotId,const CallInfoList & callInfoList)501 int32_t CSControl::ReportIncomingInfo(int32_t slotId, const CallInfoList &callInfoList)
502 {
503     TELEPHONY_LOGI("ReportIncomingInfo entry");
504     CallsReportInfo callsReportInfo;
505     for (int32_t i = 0; i < callInfoList.callSize; ++i) {
506         CallReportInfo cellularCallReportInfo = EncapsulationCallReportInfo(slotId, callInfoList.calls[i]);
507 
508         CellularCallConnectionCS connection;
509         connection.SetStatus(static_cast<TelCallState>(callInfoList.calls[i].state));
510         connection.SetIndex(callInfoList.calls[i].index);
511         connection.SetOrUpdateCallReportInfo(cellularCallReportInfo);
512         SetConnectionData(connectionMap_, callInfoList.calls[i].number, connection);
513 
514         callsReportInfo.callVec.push_back(cellularCallReportInfo);
515     }
516     if (DelayedSingleton<CellularCallRegister>::GetInstance() == nullptr) {
517         TELEPHONY_LOGE("ReportIncomingInfo return, GetInstance() is nullptr.");
518         return TELEPHONY_ERR_ARGUMENT_INVALID;
519     }
520     callsReportInfo.slotId = slotId;
521     if (!DelayedSingleton<CellularCallRegister>::GetInstance()->IsCallManagerCallBackRegistered() &&
522         callsReportInfo.callVec.size() != 0 && callsReportInfo.callVec[0].state == TelCallState::CALL_STATUS_INCOMING) {
523         isIgnoredIncomingCall_ = true;
524     } else {
525         DelayedSingleton<CellularCallRegister>::GetInstance()->ReportCallsInfo(callsReportInfo);
526     }
527     return TELEPHONY_SUCCESS;
528 }
529 
ReportHungUpInfo(int32_t slotId)530 int32_t CSControl::ReportHungUpInfo(int32_t slotId)
531 {
532     TELEPHONY_LOGI("ReportHungUpInfo entry");
533     CallsReportInfo callsReportInfo;
534     for (auto &it : connectionMap_) {
535         CallReportInfo callReportInfo = it.second.GetCallReportInfo();
536         callReportInfo.state = TelCallState::CALL_STATUS_DISCONNECTED;
537         callReportInfo.accountId = slotId;
538         callsReportInfo.callVec.push_back(callReportInfo);
539         GetCallFailReason(slotId, connectionMap_);
540     }
541     if (DelayedSingleton<CellularCallRegister>::GetInstance() == nullptr) {
542         TELEPHONY_LOGE("ReportHungUpInfo return, GetInstance() is nullptr.");
543         return TELEPHONY_ERR_LOCAL_PTR_NULL;
544     }
545     callsReportInfo.slotId = slotId;
546     if (isIgnoredHangupReport_) {
547         SetHangupReportIgnoredFlag(false);
548     } else if (isIgnoredIncomingCall_) {
549         isIgnoredIncomingCall_ = false;
550     } else {
551         DelayedSingleton<CellularCallRegister>::GetInstance()->ReportCallsInfo(callsReportInfo);
552     }
553     ReleaseAllConnection();
554     return TELEPHONY_SUCCESS;
555 }
556 
ReleaseAllConnection()557 void CSControl::ReleaseAllConnection()
558 {
559     connectionMap_.clear();
560 }
561 
GetConnectionMap()562 CsConnectionMap CSControl::GetConnectionMap()
563 {
564     return connectionMap_;
565 }
566 } // namespace Telephony
567 } // namespace OHOS
568