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