1/*
2 * Copyright (C) 2021 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 "call_request_process.h"
17
18#include "call_ability_report_proxy.h"
19#include "call_control_manager.h"
20#include "call_dialog.h"
21#include "call_manager_errors.h"
22#include "call_manager_hisysevent.h"
23#include "call_number_utils.h"
24#include "call_request_event_handler_helper.h"
25#include "cellular_call_connection.h"
26#include "common_type.h"
27#include "core_service_client.h"
28#include "core_service_connection.h"
29#include "cs_call.h"
30#include "ims_call.h"
31#include "ott_call.h"
32#include "report_call_info_handler.h"
33#include "telephony_log_wrapper.h"
34
35namespace OHOS {
36namespace Telephony {
37bool g_flagForDsda = false;
38
39CallRequestProcess::CallRequestProcess() {}
40
41CallRequestProcess::~CallRequestProcess() {}
42
43int32_t CallRequestProcess::DialRequest()
44{
45    DialParaInfo info;
46    DelayedSingleton<CallControlManager>::GetInstance()->GetDialParaInfo(info);
47    if (!info.isDialing) {
48        TELEPHONY_LOGE("the device is not dialing!");
49        CallManagerHisysevent::WriteDialCallFaultEvent(info.accountId, static_cast<int32_t>(info.callType),
50            static_cast<int32_t>(info.videoState), static_cast<int32_t>(CallErrorCode::CALL_ERROR_DEVICE_NOT_DIALING),
51            "the device is not dialing");
52        return CALL_ERR_ILLEGAL_CALL_OPERATION;
53    }
54    if (info.number.length() > static_cast<size_t>(kMaxNumberLen)) {
55        TELEPHONY_LOGE("Number out of limit!");
56        return CALL_ERR_NUMBER_OUT_OF_RANGE;
57    }
58    bool isEcc = false;
59    DelayedSingleton<CallNumberUtils>::GetInstance()->CheckNumberIsEmergency(info.number, info.accountId, isEcc);
60    if (!isEcc && info.dialType == DialType::DIAL_CARRIER_TYPE &&
61        DelayedSingleton<CoreServiceConnection>::GetInstance()->IsFdnEnabled(info.accountId)) {
62        std::vector<std::u16string> fdnNumberList =
63            DelayedSingleton<CoreServiceConnection>::GetInstance()->GetFdnNumberList(info.accountId);
64        if (fdnNumberList.empty() || !IsFdnNumber(fdnNumberList, info.number)) {
65            CallEventInfo eventInfo;
66            (void)memset_s(eventInfo.phoneNum, kMaxNumberLen, 0, kMaxNumberLen);
67            eventInfo.eventId = CallAbilityEventId::EVENT_INVALID_FDN_NUMBER;
68            (void)memcpy_s(eventInfo.phoneNum, kMaxNumberLen, info.number.c_str(), info.number.length());
69            DelayedSingleton<CallControlManager>::GetInstance()->NotifyCallEventUpdated(eventInfo);
70            CallManagerHisysevent::WriteDialCallFaultEvent(info.accountId, static_cast<int32_t>(info.callType),
71                static_cast<int32_t>(info.videoState),
72                static_cast<int32_t>(CallErrorCode::CALL_ERROR_INVALID_FDN_NUMBER), "invalid fdn number!");
73            DelayedSingleton<CallDialog>::GetInstance()->DialogConnectExtension("CALL_FAILED_DUE_TO_FDN");
74            return CALL_ERR_DIAL_FAILED;
75        }
76    }
77    TELEPHONY_LOGI("dialType:%{public}d", info.dialType);
78    int32_t ret = CALL_ERR_UNKNOW_DIAL_TYPE;
79    switch (info.dialType) {
80        case DialType::DIAL_CARRIER_TYPE:
81            ret = CarrierDialProcess(info);
82            break;
83        case DialType::DIAL_VOICE_MAIL_TYPE:
84            ret = VoiceMailDialProcess(info);
85            break;
86        case DialType::DIAL_OTT_TYPE:
87            ret = OttDialProcess(info);
88            break;
89        default:
90            break;
91    }
92    return ret;
93}
94
95void CallRequestProcess::AnswerRequest(int32_t callId, int32_t videoState)
96{
97    sptr<CallBase> call = GetOneCallObject(callId);
98    if (call == nullptr) {
99        TELEPHONY_LOGE("the call object is nullptr, callId:%{public}d", callId);
100        return;
101    }
102    call->SetAnswerVideoState(videoState);
103    if (call->GetCallType() == CallType::TYPE_VOIP) {
104        int32_t ret = call->AnswerCall(videoState);
105        if (ret != TELEPHONY_SUCCESS) {
106            TELEPHONY_LOGE("AnswerCall failed!");
107            return;
108        }
109        DelayedSingleton<CallControlManager>::GetInstance()->NotifyIncomingCallAnswered(call);
110        return;
111    }
112    AnswerRequestForDsda(call, callId, videoState);
113}
114
115void CallRequestProcess::AnswerRequestForDsda(sptr<CallBase> call, int32_t callId, int32_t videoState)
116{
117    int32_t slotId = call->GetSlotId();
118    int32_t callCrsType = 2;
119    if (IsDsdsMode3()) {
120        DisconnectOtherSubIdCall(callId, slotId, videoState);
121    } else if (IsDsdsMode5()) {
122        if (NeedAnswerVTAndEndActiveVO(callId, videoState)) {
123            TELEPHONY_LOGI("Answer videoCall for Dsda");
124            DisconnectOtherCallForVideoCall(callId);
125            call->SetAutoAnswerState(true);
126            return;
127        } else if (NeedAnswerVOAndEndActiveVT(callId, videoState)) {
128            TELEPHONY_LOGI("Answer voiceCall for Dsda, but has video call");
129            DisconnectOtherCallForVideoCall(callId);
130            call->SetAutoAnswerState(true);
131            return;
132        }
133        // There is already an incoming call to the CRS.
134        int32_t otherRingCallId = GetOtherRingingCall(callId);
135        if (otherRingCallId != INVALID_CALLID) {
136            sptr<CallBase> ringingCall = GetOneCallObject(otherRingCallId);
137            if (ringingCall != nullptr && ringingCall->GetCrsType() == callCrsType) {
138                ringingCall->HangUpCall();
139                call->SetAutoAnswerState(true);
140                return;
141            }
142        }
143        call->SetAutoAnswerState(true);
144        HoldOrDisconnectedCall(callId, slotId, videoState);
145    } else {
146        int32_t ret = call->AnswerCall(videoState);
147        if (ret != TELEPHONY_SUCCESS) {
148            TELEPHONY_LOGE("AnswerCall failed!");
149            return;
150        }
151        DelayedSingleton<CallControlManager>::GetInstance()->NotifyIncomingCallAnswered(call);
152    }
153}
154
155bool CallRequestProcess::IsDsdsMode3()
156{
157    int32_t dsdsMode = DSDS_MODE_V2;
158    DelayedRefSingleton<CoreServiceClient>::GetInstance().GetDsdsMode(dsdsMode);
159    TELEPHONY_LOGI("dsdsMode:%{public}d", dsdsMode);
160    if (dsdsMode == DSDS_MODE_V3) {
161        return true;
162    }
163    return false;
164}
165
166bool CallRequestProcess::IsDsdsMode5()
167{
168    int32_t dsdsMode = DSDS_MODE_V2;
169    DelayedRefSingleton<CoreServiceClient>::GetInstance().GetDsdsMode(dsdsMode);
170    TELEPHONY_LOGI("IsDsdsMode5:%{public}d", dsdsMode);
171    if (dsdsMode == static_cast<int32_t>(DsdsMode::DSDS_MODE_V5_DSDA) ||
172        dsdsMode == static_cast<int32_t>(DsdsMode::DSDS_MODE_V5_TDM)) {
173        return true;
174    }
175    return false;
176}
177
178bool CallRequestProcess::HasDialingCall()
179{
180    int32_t dialingCallNum = GetCallNum(TelCallState::CALL_STATUS_DIALING);
181    int32_t alertingCallNum = GetCallNum(TelCallState::CALL_STATUS_ALERTING);
182    if (dialingCallNum == 0 && alertingCallNum == 0) {
183        return false;
184    }
185    return true;
186}
187
188bool CallRequestProcess::HasActiveCall()
189{
190    int32_t activeCallNum = GetCallNum(TelCallState::CALL_STATUS_ACTIVE);
191    int32_t holdingCallNum = GetCallNum(TelCallState::CALL_STATUS_HOLDING);
192    int32_t answeredCallNum = GetCallNum(TelCallState::CALL_STATUS_ANSWERED);
193    if (activeCallNum == 0 && holdingCallNum == 0 && answeredCallNum == 0) {
194        return false;
195    }
196    return true;
197}
198
199bool CallRequestProcess::NeedAnswerVTAndEndActiveVO(int32_t callId, int32_t videoState)
200{
201    TELEPHONY_LOGI("Enter NeedAnswerVTAndEndActiveVO");
202    sptr<CallBase> activeCall = GetOneCallObject(CallRunningState::CALL_RUNNING_STATE_ACTIVE);
203    sptr<CallBase> holdingCall = GetOneCallObject(CallRunningState::CALL_RUNNING_STATE_HOLD);
204    // if this call is existed foreground or backgroud call, don't hang up it.
205    if ((activeCall != nullptr && activeCall->GetCallID() == callId) ||
206        (holdingCall != nullptr && holdingCall->GetCallID() == callId)) {
207        return false;
208    }
209    if (HasDialingCall() || HasActiveCall()) {
210        if (videoState != static_cast<int32_t>(VideoStateType::TYPE_VOICE)) {
211            TELEPHONY_LOGI("answer a new video call, need to hang up the exist call");
212            return true;
213        }
214    }
215    return false;
216}
217
218bool CallRequestProcess::NeedAnswerVOAndEndActiveVT(int32_t callId, int32_t videoState)
219{
220    if (videoState != static_cast<int32_t>(VideoStateType::TYPE_VOICE)) {
221        return false;
222    }
223    if (HasActiveCall()) {
224        sptr<CallBase> activeCall = GetOneCallObject(CallRunningState::CALL_RUNNING_STATE_ACTIVE);
225        sptr<CallBase> holdingCall = GetOneCallObject(CallRunningState::CALL_RUNNING_STATE_HOLD);
226        if ((activeCall != nullptr && activeCall->GetVideoStateType() != VideoStateType::TYPE_VOICE &&
227                activeCall->GetCallID() != callId) ||
228            (holdingCall != nullptr && holdingCall->GetVideoStateType() != VideoStateType::TYPE_VOICE &&
229                holdingCall->GetCallID() != callId)) {
230            TELEPHONY_LOGI("answer a new voice call, need to hang up the exist video call");
231            return true;
232        }
233    }
234    return false;
235}
236
237int32_t CallRequestProcess::GetOtherRingingCall(int32_t currentCallId)
238{
239    int32_t otherRingCallId = INVALID_CALLID;
240    std::list<int32_t> callIdList;
241    GetCarrierCallList(callIdList);
242    for (int32_t otherCallId : callIdList) {
243        if (otherCallId == currentCallId) {
244            continue;
245        }
246        sptr<CallBase> call = GetOneCallObject(otherCallId);
247        if (call != nullptr && call->GetCallRunningState() == CallRunningState::CALL_RUNNING_STATE_RINGING) {
248            otherRingCallId = call->GetCallID();
249            break;
250        }
251    }
252    return otherRingCallId;
253}
254
255void CallRequestProcess::HoldOrDisconnectedCall(int32_t callId, int32_t slotId, int32_t videoState)
256{
257    TELEPHONY_LOGI("Enter HoldOrDisconnectedCall");
258    std::list<int32_t> callIdList;
259    bool noOtherCall = true;
260    bool flagForConference = false;
261    GetCarrierCallList(callIdList);
262    IsExistCallOtherSlot(callIdList, slotId, noOtherCall);
263    if (noOtherCall) {
264        TELEPHONY_LOGI("no Other Slot Call");
265        sptr<CallBase> call = GetOneCallObject(callId);
266        if (call == nullptr) {
267            TELEPHONY_LOGE("call is nullptr");
268            return;
269        }
270        int32_t ret = call->AnswerCall(videoState);
271        call->SetAutoAnswerState(false);
272        if (ret != TELEPHONY_SUCCESS) {
273            return;
274        }
275        DelayedSingleton<CallControlManager>::GetInstance()->NotifyIncomingCallAnswered(call);
276        return;
277    }
278    sptr<CallBase> incomingCall = GetOneCallObject(callId);
279    int32_t waitingCallNum = GetCallNum(TelCallState::CALL_STATUS_WAITING);
280    int32_t activeCallNum = GetCallNum(TelCallState::CALL_STATUS_ACTIVE);
281    int32_t callNum = 4;
282    for (int32_t otherCallId : callIdList) {
283        sptr<CallBase> call = GetOneCallObject(otherCallId);
284        if (call != nullptr && incomingCall != nullptr && call != incomingCall) {
285            if (HandleDsdaIncomingCall(call, activeCallNum, slotId, videoState, incomingCall)) {
286                continue;
287            }
288            if (call->GetSlotId() != slotId) {
289                TELEPHONY_LOGI("exist other slot call");
290                noOtherCall = false;
291            }
292            int32_t currentCallNum = GetCurrentCallNum();
293            if (waitingCallNum > 1 || currentCallNum == callNum) {
294                HandleCallWaitingNumTwo(incomingCall, call, slotId, activeCallNum, flagForConference);
295            } else if (waitingCallNum == 1) {
296                HandleCallWaitingNumOne(incomingCall, call, slotId, activeCallNum, flagForConference);
297            } else {
298                HandleCallWaitingNumZero(incomingCall, call, slotId, activeCallNum, flagForConference);
299            }
300        }
301    }
302}
303
304bool CallRequestProcess::HandleDsdaIncomingCall(
305    sptr<CallBase> call, int32_t activeCallNum, int32_t slotId, int32_t videoState, sptr<CallBase> incomingCall)
306{
307    int32_t alertingCallNum = GetCallNum(TelCallState::CALL_STATUS_ALERTING);
308    int32_t dialingCallNum = GetCallNum(TelCallState::CALL_STATUS_DIALING);
309    int32_t answeredCallNum = GetCallNum(TelCallState::CALL_STATUS_ANSWERED);
310    if ((call->GetTelCallState() == TelCallState::CALL_STATUS_DISCONNECTING ||
311            call->GetTelCallState() == TelCallState::CALL_STATUS_HOLDING) &&
312        (activeCallNum == 0 && alertingCallNum == 0 && dialingCallNum == 0 && answeredCallNum == 0)) {
313        if (call->GetSlotId() != slotId) {
314            TELEPHONY_LOGI("enter HandleDsdaIncomingCall");
315            incomingCall->AnswerCall(videoState);
316            incomingCall->SetAutoAnswerState(false);
317        }
318        return true;
319    }
320    return false;
321}
322
323void CallRequestProcess::IsExistCallOtherSlot(std::list<int32_t> &list, int32_t slotId, bool &noOtherCall)
324{
325    if (list.size() > 1) {
326        for (int32_t otherCallId : list) {
327            sptr<CallBase> call = GetOneCallObject(otherCallId);
328            if (call != nullptr && call->GetSlotId() != slotId) {
329                noOtherCall = false;
330                break;
331            }
332        }
333    }
334}
335
336void CallRequestProcess::HandleCallWaitingNumTwo(
337    sptr<CallBase> incomingCall, sptr<CallBase> call, int32_t slotId, int32_t activeCallNum, bool &flagForConference)
338{
339    TELEPHONY_LOGI("enter HandleCallWaitingNumTwo");
340    sptr<CallBase> holdCall = GetOneCallObject(CallRunningState::CALL_RUNNING_STATE_HOLD);
341    int32_t callNum = 3;
342    int32_t currentCallNum = GetCurrentCallNum();
343    if (currentCallNum == callNum) {
344        TELEPHONY_LOGI("enter two waitingCall process");
345        HandleCallWaitingNumOne(incomingCall, call, slotId, activeCallNum, flagForConference);
346        return;
347    }
348    if (holdCall != nullptr) {
349        TELEPHONY_LOGI("enter two holdcall hangup");
350        holdCall->HangUpCall();
351    }
352    TELEPHONY_LOGI("enter two GetTelCallState =:%{public}d", call->GetCallRunningState());
353    if (call->GetCallRunningState() == CallRunningState::CALL_RUNNING_STATE_ACTIVE && !flagForConference) {
354        if (call->GetSlotId() == slotId) {
355            TELEPHONY_LOGI("enter two activecall hold");
356            call->HoldCall();
357            flagForConference = true;
358        } else {
359            TELEPHONY_LOGI(" enter two  activecall hangup");
360            call->HangUpCall();
361        }
362    }
363}
364
365void CallRequestProcess::HandleCallWaitingNumOne(
366    sptr<CallBase> incomingCall, sptr<CallBase> call, int32_t slotId, int32_t activeCallNum, bool &flagForConference)
367{
368    TELEPHONY_LOGI("enter HandleCallWaitingNumOne");
369    sptr<CallBase> holdCall = GetOneCallObject(CallRunningState::CALL_RUNNING_STATE_HOLD);
370    TELEPHONY_LOGI("enter one GetTelCallState =:%{public}d", call->GetTelCallState());
371    int32_t callNum = 2;
372    int32_t currentCallNum = GetCurrentCallNum();
373    if (holdCall != nullptr) {
374        HandleCallWaitingNumOneNext(incomingCall, call, holdCall, slotId, flagForConference);
375    } else if (currentCallNum == callNum) {
376        TELEPHONY_LOGI("enter two call process");
377        HandleCallWaitingNumZero(incomingCall, call, slotId, activeCallNum, flagForConference);
378    } else if (call->GetCallRunningState() == CallRunningState::CALL_RUNNING_STATE_ACTIVE && !flagForConference) {
379        if (call->GetSlotId() != slotId && g_flagForDsda == true) {
380            TELEPHONY_LOGI("enter one hold call is null active call hold for Special Dsda Scenario");
381            call->HoldCall();
382            flagForConference = true;
383            g_flagForDsda = false;
384        } else if (call->GetSlotId() != slotId) {
385            TELEPHONY_LOGI("enter one hold call is null active call hangup");
386            call->HangUpCall();
387        } else {
388            TELEPHONY_LOGI("enter one hold call is null active call hold");
389            call->HoldCall();
390            flagForConference = true;
391        }
392    }
393}
394
395void CallRequestProcess::HandleCallWaitingNumOneNext(
396    sptr<CallBase> incomingCall, sptr<CallBase> call, sptr<CallBase> holdCall, int32_t slotId, bool &flagForConference)
397{
398    TELEPHONY_LOGI("enter HandleCallWaitingNumOneNext");
399    int32_t activeCallNum = GetCallNum(TelCallState::CALL_STATUS_ACTIVE);
400    int32_t dialingCallNum = GetCallNum(TelCallState::CALL_STATUS_DIALING);
401    int32_t alertingCallNum = GetCallNum(TelCallState::CALL_STATUS_ALERTING);
402    if (call->GetTelCallState() == TelCallState ::CALL_STATUS_DIALING ||
403        call->GetTelCallState() == TelCallState ::CALL_STATUS_ALERTING) {
404        TELEPHONY_LOGI("enter one dialing call hangup");
405        call->HangUpCall();
406    } else if (activeCallNum > 0) {
407        TELEPHONY_LOGI("enter one hold call hangup");
408        holdCall->HangUpCall();
409        g_flagForDsda = true;
410    }
411    if (call->GetCallRunningState() == CallRunningState::CALL_RUNNING_STATE_ACTIVE && !flagForConference) {
412        if (CallObjectManager::IsCallExist(call->GetCallType(), TelCallState::CALL_STATUS_INCOMING) &&
413            call->GetSlotId() != slotId) {
414            TELEPHONY_LOGI("enter one active call hangup");
415            call->HangUpCall();
416        } else {
417            TELEPHONY_LOGI("enter one active call hold");
418            call->HoldCall();
419            flagForConference = true;
420        }
421    } else if (activeCallNum == 0 && incomingCall->GetAutoAnswerState() && alertingCallNum == 0 &&
422               dialingCallNum == 0) {
423        TELEPHONY_LOGI("enter one active with two incoming call");
424        incomingCall->AnswerCall(static_cast<int32_t>(incomingCall->GetVideoStateType()));
425        incomingCall->SetAutoAnswerState(false);
426    }
427}
428
429void CallRequestProcess::HandleCallWaitingNumZero(
430    sptr<CallBase> incomingCall, sptr<CallBase> call, int32_t slotId, int32_t activeCallNum, bool &flagForConference)
431{
432    TELEPHONY_LOGI("enter HandleCallWaitingNumZero");
433    sptr<CallBase> holdCall = GetOneCallObject(CallRunningState::CALL_RUNNING_STATE_HOLD);
434    if (holdCall != nullptr) {
435        TELEPHONY_LOGI("enter zero holdcall is not null");
436        if (call->GetTelCallState() == TelCallState ::CALL_STATUS_DIALING ||
437            call->GetTelCallState() == TelCallState ::CALL_STATUS_ALERTING) {
438            TELEPHONY_LOGI("enter zero dialing call hangup");
439            call->HangUpCall();
440        } else if (activeCallNum > 0) {
441            TELEPHONY_LOGI("enter zero hold call hangup");
442            holdCall->HangUpCall();
443        }
444        if (call->GetCallRunningState() == CallRunningState::CALL_RUNNING_STATE_ACTIVE && !flagForConference) {
445            TELEPHONY_LOGI("enter active call hangup");
446            call->HoldCall();
447            flagForConference = true;
448        }
449    } else {
450        TELEPHONY_LOGI("enter zero holdcall is null");
451        if (call->GetTelCallState() == TelCallState ::CALL_STATUS_DIALING ||
452            call->GetTelCallState() == TelCallState ::CALL_STATUS_ALERTING) {
453            TELEPHONY_LOGI("enter zero dialing incoming call hangup");
454            call->HangUpCall();
455        } else if (call->GetCallRunningState() == CallRunningState::CALL_RUNNING_STATE_ACTIVE && !flagForConference) {
456            sptr<IMSCall> imsCall = reinterpret_cast<IMSCall *>(call.GetRefPtr());
457            if (imsCall != nullptr && imsCall->IsVoiceModifyToVideo()) {
458                TELEPHONY_LOGI("hangup call during voice to video when answerCall");
459                call->HangUpCall();
460                return;
461            }
462            TELEPHONY_LOGI("enter zero active call hold");
463            call->HoldCall();
464            flagForConference = true;
465        } else if (incomingCall->GetAutoAnswerState() &&
466                   (call->GetTelCallState() == TelCallState ::CALL_STATUS_INCOMING ||
467                       call->GetTelCallState() == TelCallState ::CALL_STATUS_WAITING)) {
468            TELEPHONY_LOGI("enter two incoming call active");
469            incomingCall->AnswerCall(static_cast<int32_t>(incomingCall->GetVideoStateType()));
470            incomingCall->SetAutoAnswerState(false);
471        }
472    }
473}
474
475void CallRequestProcess::DisconnectOtherSubIdCall(int32_t callId, int32_t slotId, int32_t videoState)
476{
477    sptr<CallBase> incomingCall = GetOneCallObject(callId);
478    if (incomingCall == nullptr) {
479        TELEPHONY_LOGE("the call object is nullptr, callId:%{public}d", callId);
480        return;
481    }
482    std::list<int32_t> callIdList;
483    bool noOtherCall = true;
484    GetCarrierCallList(callIdList);
485    if (callIdList.size() > 1) {
486        for (int32_t otherCallId : callIdList) {
487            sptr<CallBase> call = GetOneCallObject(otherCallId);
488            if (call != nullptr && call->GetSlotId() != slotId) {
489                incomingCall->SetAutoAnswerState(true);
490                TELEPHONY_LOGI("Hangup call callid:%{public}d", call->GetCallID());
491                call->HangUpCall();
492                noOtherCall = false;
493            }
494        }
495    }
496    if (noOtherCall == true) {
497        int32_t ret = incomingCall->AnswerCall(videoState);
498        if (ret != TELEPHONY_SUCCESS) {
499            return;
500        }
501        DelayedSingleton<CallControlManager>::GetInstance()->NotifyIncomingCallAnswered(incomingCall);
502    }
503}
504
505void CallRequestProcess::DisconnectOtherCallForVideoCall(int32_t callId)
506{
507    std::list<int32_t> callIdList;
508    GetCarrierCallList(callIdList);
509    for (int32_t otherCallId : callIdList) {
510        sptr<CallBase> call = GetOneCallObject(otherCallId);
511        if (call != nullptr && call->GetCallID() != callId &&
512            (call->GetCallRunningState() == CallRunningState::CALL_RUNNING_STATE_ACTIVE ||
513                call->GetCallRunningState() == CallRunningState::CALL_RUNNING_STATE_DIALING ||
514                call->GetCallRunningState() == CallRunningState::CALL_RUNNING_STATE_HOLD)) {
515            TELEPHONY_LOGI("Hangup call callid:%{public}d", call->GetCallID());
516            call->HangUpCall();
517        }
518    }
519}
520
521void CallRequestProcess::RejectRequest(int32_t callId, bool isSendSms, std::string &content)
522{
523    sptr<CallBase> call = GetOneCallObject(callId);
524    if (call == nullptr) {
525        TELEPHONY_LOGE("the call object is nullptr, callId:%{public}d", callId);
526        return;
527    }
528
529    int32_t ret = call->RejectCall();
530    if (ret != TELEPHONY_SUCCESS) {
531        TELEPHONY_LOGE("RejectCall failed!");
532        return;
533    }
534    std::list<int32_t> callIdList;
535    GetCarrierCallList(callIdList);
536    sptr<CallBase> holdCall = CallObjectManager::GetOneCallObject(CallRunningState::CALL_RUNNING_STATE_HOLD);
537    if (holdCall) {
538        TELEPHONY_LOGI("release the incoming/waiting call but can not recover the held call");
539        holdCall->SetCanUnHoldState(false);
540    }
541    TELEPHONY_LOGI("start to send reject message...");
542    DelayedSingleton<CallControlManager>::GetInstance()->NotifyIncomingCallRejected(call, isSendSms, content);
543}
544
545void CallRequestProcess::HangUpRequest(int32_t callId)
546{
547    sptr<CallBase> call = GetOneCallObject(callId);
548    if (call == nullptr) {
549        TELEPHONY_LOGE("the call object is nullptr, callId:%{public}d", callId);
550        return;
551    }
552    int32_t waitingCallNum = GetCallNum(TelCallState::CALL_STATUS_WAITING);
553    TelCallState state = call->GetTelCallState();
554    TelConferenceState confState = call->GetTelConferenceState();
555    if ((((state == TelCallState::CALL_STATUS_ACTIVE) &&
556        (CallObjectManager::IsCallExist(call->GetCallType(), TelCallState::CALL_STATUS_HOLDING))) ||
557        (confState == TelConferenceState::TEL_CONFERENCE_ACTIVE)) && waitingCallNum == 0) {
558        if (HangUpForDsdaRequest(call)) {
559            TELEPHONY_LOGI("hangup for dsda Request success");
560        } else {
561            TELEPHONY_LOGI("release the active call and recover the held call");
562            call->SetPolicyFlag(PolicyFlag::POLICY_FLAG_HANG_UP_ACTIVE);
563        }
564    } else if (confState == TelConferenceState::TEL_CONFERENCE_HOLDING && waitingCallNum == 0) {
565        TELEPHONY_LOGI("release the held call and the wait call");
566        call->SetPolicyFlag(PolicyFlag::POLICY_FLAG_HANG_UP_HOLD_WAIT);
567    } else if (((confState == TelConferenceState::TEL_CONFERENCE_HOLDING) ||
568        (confState == TelConferenceState::TEL_CONFERENCE_ACTIVE)) && waitingCallNum != 0) {
569        TELEPHONY_LOGI("conference call and holding state, hangup conference call");
570        std::vector<std::u16string> callIdList;
571        call->GetSubCallIdList(callIdList);
572        for (auto it = callIdList.begin(); it != callIdList.end(); ++it) {
573            int32_t callId = -1;
574            StrToInt(Str16ToStr8(*it), callId);
575            KickOutFromConferenceRequest(callId);
576        }
577    }
578    call->HangUpCall();
579}
580
581bool CallRequestProcess::HangUpForDsdaRequest(sptr<CallBase> call)
582{
583    int32_t dsdsMode = DSDS_MODE_V2;
584    DelayedRefSingleton<CoreServiceClient>::GetInstance().GetDsdsMode(dsdsMode);
585    bool noOtherCall = true;
586    std::list<int32_t> allCallIdList;
587    GetCarrierCallList(allCallIdList);
588    IsExistCallOtherSlot(allCallIdList, call->GetSlotId(), noOtherCall);
589    if ((dsdsMode == static_cast<int32_t>(DsdsMode::DSDS_MODE_V5_DSDA) ||
590            dsdsMode == static_cast<int32_t>(DsdsMode::DSDS_MODE_V5_TDM)) &&
591        (!noOtherCall)) {
592        TELEPHONY_LOGI("release the active call but not recover the held call for dsda");
593        std::vector<std::u16string> callIdList;
594        call->GetSubCallIdList(callIdList);
595        for (auto it = callIdList.begin(); it != callIdList.end(); ++it) {
596            int32_t callId = -1;
597            StrToInt(Str16ToStr8(*it), callId);
598            KickOutFromConferenceRequest(callId);
599        }
600        return true;
601    }
602    return false;
603}
604
605void CallRequestProcess::HoldRequest(int32_t callId)
606{
607    sptr<CallBase> call = GetOneCallObject(callId);
608    if (call == nullptr) {
609        TELEPHONY_LOGE("the call object is nullptr, callId:%{public}d", callId);
610        return;
611    }
612    call->HoldCall();
613}
614
615void CallRequestProcess::UnHoldRequest(int32_t callId)
616{
617    TELEPHONY_LOGI("Enter UnHoldRequest");
618    sptr<CallBase> call = GetOneCallObject(callId);
619    if (call == nullptr) {
620        TELEPHONY_LOGE("the call object is nullptr, callId:%{public}d", callId);
621        return;
622    }
623    call->SetCanUnHoldState(true);
624    bool noOtherCall = true;
625    std::list<int32_t> callIdList;
626    GetCarrierCallList(callIdList);
627    IsExistCallOtherSlot(callIdList, call->GetSlotId(), noOtherCall);
628    for (int32_t otherCallId : callIdList) {
629        sptr<CallBase> otherCall = GetOneCallObject(otherCallId);
630        if (otherCall == nullptr) {
631            TELEPHONY_LOGE("otherCall is nullptr");
632            return;
633        }
634        TelCallState state = otherCall->GetTelCallState();
635        TelConferenceState confState = otherCall->GetTelConferenceState();
636        int32_t conferenceId = ERR_ID;
637        otherCall->GetMainCallId(conferenceId);
638        TELEPHONY_LOGI("otherCall->GetTelCallState(): %{public}d ,callid:%{public}d", state, otherCallId);
639        if (IsDsdsMode5() && !noOtherCall && state == TelCallState::CALL_STATUS_ACTIVE &&
640            ((confState != TelConferenceState::TEL_CONFERENCE_IDLE && conferenceId == otherCallId) ||
641                confState == TelConferenceState::TEL_CONFERENCE_IDLE)) {
642            if (otherCall->GetCanSwitchCallState()) {
643                TELEPHONY_LOGI("Hold other call in other slotId for switch Dsda call");
644                otherCall->SetCanSwitchCallState(false);
645                otherCall->HoldCall();
646                return;
647            } else {
648                TELEPHONY_LOGI("Currently can not swap this call");
649                return;
650            }
651        }
652    }
653    if (noOtherCall) {
654        call->UnHoldCall();
655    }
656}
657
658void CallRequestProcess::SwitchRequest(int32_t callId)
659{
660    sptr<CallBase> call = GetOneCallObject(callId);
661    if (call == nullptr) {
662        TELEPHONY_LOGE("the call object is nullptr, callId:%{public}d", callId);
663        return;
664    }
665    call->SwitchCall();
666}
667
668void CallRequestProcess::CombineConferenceRequest(int32_t mainCallId)
669{
670    sptr<CallBase> call = GetOneCallObject(mainCallId);
671    if (call == nullptr) {
672        TELEPHONY_LOGE("the call object is nullptr, mainCallId:%{public}d", mainCallId);
673        return;
674    }
675    int32_t ret = call->CombineConference();
676    if (ret != TELEPHONY_SUCCESS) {
677        TELEPHONY_LOGE("CombineConference failed");
678    }
679}
680
681void CallRequestProcess::SeparateConferenceRequest(int32_t callId)
682{
683    sptr<CallBase> call = GetOneCallObject(callId);
684    if (call == nullptr) {
685        TELEPHONY_LOGE("the call object is nullptr, callId:%{public}d", callId);
686        return;
687    }
688    int32_t ret = call->SeparateConference();
689    if (ret != TELEPHONY_SUCCESS) {
690        TELEPHONY_LOGE("SeparateConference failed");
691    }
692}
693
694void CallRequestProcess::KickOutFromConferenceRequest(int32_t callId)
695{
696    sptr<CallBase> call = GetOneCallObject(callId);
697    if (call == nullptr) {
698        TELEPHONY_LOGE("the call object is nullptr, callId:%{public}d", callId);
699        return;
700    }
701    int32_t ret = call->KickOutFromConference();
702    if (ret != TELEPHONY_SUCCESS) {
703        TELEPHONY_LOGE("KickOutFormConference failed");
704    }
705}
706
707void CallRequestProcess::StartRttRequest(int32_t callId, std::u16string &msg)
708{
709    sptr<CallBase> call = GetOneCallObject(callId);
710    if (call == nullptr) {
711        TELEPHONY_LOGE("the call object is nullptr, callId:%{public}d", callId);
712        return;
713    }
714    if (call->GetCallType() != CallType::TYPE_IMS) {
715        TELEPHONY_LOGE("Unsupported Network type, callId:%{public}d", callId);
716        return;
717    } else {
718        sptr<IMSCall> imsCall = reinterpret_cast<IMSCall *>(call.GetRefPtr());
719        imsCall->StartRtt(msg);
720    }
721}
722
723void CallRequestProcess::StopRttRequest(int32_t callId)
724{
725    sptr<CallBase> call = GetOneCallObject(callId);
726    if (call == nullptr) {
727        TELEPHONY_LOGE("the call object is nullptr, callId:%{public}d", callId);
728        return;
729    }
730    if (call->GetCallType() != CallType::TYPE_IMS) {
731        TELEPHONY_LOGE("Unsupported Network type, callId:%{public}d", callId);
732        return;
733    } else {
734        sptr<IMSCall> imsCall = reinterpret_cast<IMSCall *>(call.GetRefPtr());
735        imsCall->StopRtt();
736    }
737}
738
739void CallRequestProcess::JoinConference(int32_t callId, std::vector<std::string> &numberList)
740{
741    sptr<CallBase> call = GetOneCallObject(callId);
742    if (call == nullptr) {
743        TELEPHONY_LOGE("the call object is nullptr, callId:%{public}d", callId);
744        return;
745    }
746    int32_t ret =
747        DelayedSingleton<CellularCallConnection>::GetInstance()->InviteToConference(numberList, call->GetSlotId());
748    if (ret != TELEPHONY_SUCCESS) {
749        TELEPHONY_LOGE("Invite to conference failed!");
750        return;
751    }
752}
753
754int32_t CallRequestProcess::UpdateCallReportInfo(const DialParaInfo &info, TelCallState state)
755{
756    CallDetailInfo callDetatilInfo;
757    if (memset_s(&callDetatilInfo, sizeof(CallDetailInfo), 0, sizeof(CallDetailInfo)) != EOK) {
758        TELEPHONY_LOGE("memset_s callDetatilInfo fail");
759        return TELEPHONY_ERR_MEMSET_FAIL;
760    }
761    callDetatilInfo.callType = info.callType;
762    callDetatilInfo.accountId = info.accountId;
763    callDetatilInfo.index = info.index;
764    callDetatilInfo.state = state;
765    callDetatilInfo.callMode = info.videoState;
766    callDetatilInfo.originalCallType = info.originalCallType;
767    callDetatilInfo.voiceDomain = static_cast<int32_t>(info.callType);
768    if (info.number.length() > kMaxNumberLen) {
769        TELEPHONY_LOGE("numbser length out of range");
770        return CALL_ERR_NUMBER_OUT_OF_RANGE;
771    }
772    if (memcpy_s(&callDetatilInfo.phoneNum, kMaxNumberLen, info.number.c_str(), info.number.length()) != EOK) {
773        TELEPHONY_LOGE("memcpy_s number failed!");
774        return TELEPHONY_ERR_MEMCPY_FAIL;
775    }
776    return DelayedSingleton<ReportCallInfoHandler>::GetInstance()->UpdateCallReportInfo(callDetatilInfo);
777}
778
779int32_t CallRequestProcess::HandleDialFail()
780{
781    std::unique_lock<std::mutex> lock(mutex_);
782    while (!isFirstDialCallAdded_) {
783        if (cv_.wait_for(lock, std::chrono::seconds(WAIT_TIME_ONE_SECOND)) == std::cv_status::timeout) {
784            TELEPHONY_LOGE("CarrierDialProcess call is not added");
785            return CALL_ERR_DIAL_FAILED;
786        }
787    }
788    sptr<CallBase> call = nullptr;
789    call = GetOneCallObject(CallRunningState::CALL_RUNNING_STATE_CREATE);
790    if (call != nullptr) {
791        return DealFailDial(call);
792    }
793    call = GetOneCallObject(CallRunningState::CALL_RUNNING_STATE_CONNECTING);
794    if (call != nullptr) {
795        return DealFailDial(call);
796    }
797    call = GetOneCallObject(CallRunningState::CALL_RUNNING_STATE_DIALING);
798    if (call != nullptr) {
799        return DealFailDial(call);
800    }
801    TELEPHONY_LOGE("can not find connect call or dialing call");
802    return CALL_ERR_CALL_STATE;
803}
804
805int32_t CallRequestProcess::CarrierDialProcess(DialParaInfo &info)
806{
807    auto callRequestEventHandler = DelayedSingleton<CallRequestEventHandlerHelper>::GetInstance();
808    if (callRequestEventHandler->IsDialingCallProcessing()) {
809        return CALL_ERR_CALL_COUNTS_EXCEED_LIMIT;
810    }
811    callRequestEventHandler->RestoreDialingFlag(true);
812    callRequestEventHandler->SetDialingCallProcessing();
813    std::string newPhoneNum =
814        DelayedSingleton<CallNumberUtils>::GetInstance()->RemoveSeparatorsPhoneNumber(info.number);
815    int32_t ret = HandleDialingInfo(newPhoneNum, info);
816    if (ret != TELEPHONY_SUCCESS) {
817        TELEPHONY_LOGE("HandleDialingInfo failed!");
818        callRequestEventHandler->RestoreDialingFlag(false);
819        callRequestEventHandler->RemoveEventHandlerTask();
820        needWaitHold_ = false;
821        return ret;
822    }
823    bool isMMiCode = DelayedSingleton<CallNumberUtils>::GetInstance()->IsMMICode(newPhoneNum);
824    if (!isMMiCode) {
825        isFirstDialCallAdded_ = false;
826        info.number = newPhoneNum;
827        ret = UpdateCallReportInfo(info, TelCallState::CALL_STATUS_DIALING);
828        if (ret != TELEPHONY_SUCCESS) {
829            TELEPHONY_LOGE("UpdateCallReportInfo failed!");
830            needWaitHold_ = false;
831            return ret;
832        }
833    } else {
834        callRequestEventHandler->RestoreDialingFlag(false);
835        callRequestEventHandler->RemoveEventHandlerTask();
836    }
837    CellularCallInfo callInfo;
838    ret = PackCellularCallInfo(info, callInfo);
839    if (ret != TELEPHONY_SUCCESS) {
840        TELEPHONY_LOGW("PackCellularCallInfo failed!");
841        CallManagerHisysevent::WriteDialCallFaultEvent(info.accountId, static_cast<int32_t>(info.callType),
842            static_cast<int32_t>(info.videoState), ret, "Carrier type PackCellularCallInfo failed");
843        needWaitHold_ = false;
844        return ret;
845    }
846    if (needWaitHold_ && !isMMiCode) {
847        TELEPHONY_LOGI("waitting for call hold");
848        dialCallInfo_ = callInfo;
849        return ret;
850    }
851    ret = HandleStartDial(isMMiCode, callInfo);
852    return ret;
853}
854
855int32_t CallRequestProcess::HandleDialingInfo(std::string newPhoneNum, DialParaInfo &info)
856{
857    bool isEcc = false;
858    int32_t ret = HandleEccCallForDsda(newPhoneNum, info, isEcc);
859    if (ret != TELEPHONY_SUCCESS) {
860        return ret;
861    }
862    if (!isEcc) {
863        bool canDial = true;
864        IsNewCallAllowedCreate(canDial);
865        if (!canDial) {
866            return CALL_ERR_CALL_COUNTS_EXCEED_LIMIT;
867        }
868        if (IsDsdsMode5()) {
869            ret = IsDialCallForDsda(info);
870            if (ret != TELEPHONY_SUCCESS) {
871                TELEPHONY_LOGE("IsDialCallForDsda failed!");
872                return ret;
873            }
874        }
875    }
876    return TELEPHONY_SUCCESS;
877}
878
879int32_t CallRequestProcess::HandleStartDial(bool isMMiCode, CellularCallInfo callInfo)
880{
881    int32_t ret = DelayedSingleton<CellularCallConnection>::GetInstance()->Dial(callInfo);
882    if (ret != TELEPHONY_SUCCESS) {
883        TELEPHONY_LOGE("Dial failed!");
884        if (isMMiCode) {
885            return ret;
886        }
887        int32_t handleRet = HandleDialFail();
888        if (handleRet != TELEPHONY_SUCCESS) {
889            TELEPHONY_LOGE("HandleDialFail failed!");
890            return handleRet;
891        }
892        return ret;
893    }
894    return TELEPHONY_SUCCESS;
895}
896
897int32_t CallRequestProcess::IsDialCallForDsda(DialParaInfo &info)
898{
899    sptr<CallBase> activeCall = GetOneCallObject(CallRunningState::CALL_RUNNING_STATE_ACTIVE);
900    TELEPHONY_LOGI("Is dsdsmode5 dial call info.accountId = %{public}d", info.accountId);
901    if (activeCall != nullptr && activeCall->GetSlotId() != info.accountId) {
902        int32_t ret = activeCall->HoldCall();
903        if (ret == TELEPHONY_SUCCESS) {
904            needWaitHold_ = true;
905        }
906        return ret;
907    }
908    return TELEPHONY_SUCCESS;
909}
910
911int32_t CallRequestProcess::HandleEccCallForDsda(std::string newPhoneNum, DialParaInfo &info, bool &isEcc)
912{
913    int32_t ret =
914        DelayedSingleton<CallNumberUtils>::GetInstance()->CheckNumberIsEmergency(newPhoneNum, info.accountId, isEcc);
915    TELEPHONY_LOGE("CheckNumberIsEmergency ret is %{public}d", ret);
916    if (isEcc && IsDsdsMode5()) {
917        return EccDialPolicy();
918    } else if (isEcc) {
919        bool hasRingCall = false;
920        int32_t result = CallObjectManager::HasRingingCall(hasRingCall);
921        if ((result == TELEPHONY_SUCCESS) && hasRingCall) {
922            sptr<CallBase> call = CallObjectManager::GetOneCallObject(CallRunningState::CALL_RUNNING_STATE_RINGING);
923            call->RejectCall();
924            TELEPHONY_LOGI("has ringCall when dial. reject ringCall");
925        }
926    }
927    return TELEPHONY_SUCCESS;
928}
929
930int32_t CallRequestProcess::VoiceMailDialProcess(DialParaInfo &info)
931{
932    return CarrierDialProcess(info);
933}
934
935int32_t CallRequestProcess::OttDialProcess(DialParaInfo &info)
936{
937    AppExecFwk::PacMap callInfo;
938    callInfo.PutStringValue("phoneNumber", info.number);
939    callInfo.PutStringValue("bundleName", info.bundleName);
940    callInfo.PutIntValue("videoState", static_cast<int32_t>(info.videoState));
941    int32_t ret = DelayedSingleton<CallAbilityReportProxy>::GetInstance()->OttCallRequest(
942        OttCallRequestId::OTT_REQUEST_DIAL, callInfo);
943    if (ret != TELEPHONY_SUCCESS) {
944        TELEPHONY_LOGE("OTT call Dial failed!");
945        return ret;
946    }
947    return TELEPHONY_SUCCESS;
948}
949
950int32_t CallRequestProcess::PackCellularCallInfo(DialParaInfo &info, CellularCallInfo &callInfo)
951{
952    callInfo.callId = info.callId;
953    callInfo.accountId = info.accountId;
954    callInfo.callType = info.callType;
955    callInfo.videoState = static_cast<int32_t>(info.videoState);
956    callInfo.index = info.index;
957    callInfo.slotId = info.accountId;
958    if (memset_s(callInfo.phoneNum, kMaxNumberLen, 0, kMaxNumberLen) != EOK) {
959        TELEPHONY_LOGW("memset_s failed!");
960        return TELEPHONY_ERR_MEMSET_FAIL;
961    }
962    if (info.number.length() > static_cast<size_t>(kMaxNumberLen)) {
963        TELEPHONY_LOGE("Number out of limit!");
964        return CALL_ERR_NUMBER_OUT_OF_RANGE;
965    }
966    if (memcpy_s(callInfo.phoneNum, kMaxNumberLen, info.number.c_str(), info.number.length()) != EOK) {
967        TELEPHONY_LOGE("memcpy_s failed!");
968        return TELEPHONY_ERR_MEMCPY_FAIL;
969    }
970    return TELEPHONY_SUCCESS;
971}
972
973bool CallRequestProcess::IsFdnNumber(std::vector<std::u16string> fdnNumberList, std::string phoneNumber)
974{
975    char number[kMaxNumberLen + 1] = { 0 };
976    int32_t j = 0;
977    for (int32_t i = 0; i < static_cast<int32_t>(phoneNumber.length()); i++) {
978        if (i >= kMaxNumberLen) {
979            break;
980        }
981        if (*(phoneNumber.c_str() + i) != ' ') {
982            number[j++] = *(phoneNumber.c_str() + i);
983        }
984    }
985    for (std::vector<std::u16string>::iterator it = fdnNumberList.begin(); it != fdnNumberList.end(); ++it) {
986        if (strstr(number, Str16ToStr8(*it).c_str()) != nullptr) {
987            TELEPHONY_LOGI("you are allowed to dial!");
988            return true;
989        }
990    }
991    TELEPHONY_LOGW("There is no fixed number.");
992    return false;
993}
994
995int32_t CallRequestProcess::EccDialPolicy()
996{
997    std::list<int32_t> callIdList;
998    std::list<sptr<CallBase>> hangupList;
999    std::list<sptr<CallBase>> rejectList;
1000    GetCarrierCallList(callIdList);
1001    for (int32_t callId : callIdList) {
1002        sptr<CallBase> call = GetOneCallObject(callId);
1003        if (call == nullptr) {
1004            continue;
1005        }
1006        CallRunningState crState = call->GetCallRunningState();
1007        if (call->GetCallType() == CallType::TYPE_SATELLITE) {
1008            hangupList.emplace_back(call);
1009        } else if (crState == CallRunningState::CALL_RUNNING_STATE_CREATE ||
1010            crState == CallRunningState::CALL_RUNNING_STATE_CONNECTING ||
1011            crState == CallRunningState::CALL_RUNNING_STATE_DIALING) {
1012            if (call->GetEmergencyState()) {
1013                hangupList.clear();
1014                rejectList.clear();
1015                TELEPHONY_LOGE("already has ecc call dailing!");
1016                return CALL_ERR_CALL_COUNTS_EXCEED_LIMIT;
1017            }
1018            hangupList.emplace_back(call);
1019        } else if (crState == CallRunningState::CALL_RUNNING_STATE_RINGING) {
1020            rejectList.emplace_back(call);
1021        } else if (crState == CallRunningState::CALL_RUNNING_STATE_ACTIVE) {
1022            hangupList.emplace_back(call);
1023        }
1024    }
1025    for (sptr<CallBase> call : hangupList) {
1026        int32_t callId = call->GetCallID();
1027        CallRunningState crState = call->GetCallRunningState();
1028        TELEPHONY_LOGE("HangUpCall call[id:%{public}d state:%{public}d]", callId, crState);
1029        call->HangUpCall();
1030    }
1031    for (sptr<CallBase> call : rejectList) {
1032        int32_t callId = call->GetCallID();
1033        CallRunningState crState = call->GetCallRunningState();
1034        TELEPHONY_LOGE("RejectCall call[id:%{public}d state:%{public}d]", callId, crState);
1035        call->RejectCall();
1036    }
1037    hangupList.clear();
1038    return TELEPHONY_SUCCESS;
1039}
1040} // namespace Telephony
1041} // namespace OHOS
1042