1d95e75fdSopenharmony_ci/*
2d95e75fdSopenharmony_ci * Copyright (C) 2021-2022 Huawei Device Co., Ltd.
3d95e75fdSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4d95e75fdSopenharmony_ci * you may not use this file except in compliance with the License.
5d95e75fdSopenharmony_ci * You may obtain a copy of the License at
6d95e75fdSopenharmony_ci *
7d95e75fdSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8d95e75fdSopenharmony_ci *
9d95e75fdSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10d95e75fdSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11d95e75fdSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12d95e75fdSopenharmony_ci * See the License for the specific language governing permissions and
13d95e75fdSopenharmony_ci * limitations under the License.
14d95e75fdSopenharmony_ci */
15d95e75fdSopenharmony_ci
16d95e75fdSopenharmony_ci#include "cs_control.h"
17d95e75fdSopenharmony_ci
18d95e75fdSopenharmony_ci#include "cellular_call_hisysevent.h"
19d95e75fdSopenharmony_ci#include "cellular_call_register.h"
20d95e75fdSopenharmony_ci#include "cellular_call_service.h"
21d95e75fdSopenharmony_ci#include "module_service_utils.h"
22d95e75fdSopenharmony_ci#include "securec.h"
23d95e75fdSopenharmony_ci#include "standardize_utils.h"
24d95e75fdSopenharmony_ci
25d95e75fdSopenharmony_cinamespace OHOS {
26d95e75fdSopenharmony_cinamespace Telephony {
27d95e75fdSopenharmony_ci
28d95e75fdSopenharmony_ciCSControl::~CSControl()
29d95e75fdSopenharmony_ci{
30d95e75fdSopenharmony_ci    ReleaseAllConnection();
31d95e75fdSopenharmony_ci}
32d95e75fdSopenharmony_ci
33d95e75fdSopenharmony_ciint32_t CSControl::Dial(const CellularCallInfo &callInfo, bool isEcc)
34d95e75fdSopenharmony_ci{
35d95e75fdSopenharmony_ci    TELEPHONY_LOGI("Dial start");
36d95e75fdSopenharmony_ci    DelayedSingleton<CellularCallHiSysEvent>::GetInstance()->SetCallParameterInfo(
37d95e75fdSopenharmony_ci        callInfo.slotId, static_cast<int32_t>(callInfo.callType), callInfo.videoState);
38d95e75fdSopenharmony_ci    int32_t ret = DialPreJudgment(callInfo, isEcc);
39d95e75fdSopenharmony_ci    if (ret != TELEPHONY_SUCCESS) {
40d95e75fdSopenharmony_ci        return ret;
41d95e75fdSopenharmony_ci    }
42d95e75fdSopenharmony_ci
43d95e75fdSopenharmony_ci    ModuleServiceUtils moduleServiceUtils;
44d95e75fdSopenharmony_ci    RegServiceState regState = moduleServiceUtils.GetCsRegState(callInfo.slotId);
45d95e75fdSopenharmony_ci    if (!(regState == RegServiceState::REG_STATE_IN_SERVICE || isEcc)) {
46d95e75fdSopenharmony_ci        TELEPHONY_LOGE("can not dial.");
47d95e75fdSopenharmony_ci        return TELEPHONY_ERR_NETWORK_NOT_IN_SERVICE;
48d95e75fdSopenharmony_ci    }
49d95e75fdSopenharmony_ci    PhoneType netType = moduleServiceUtils.GetNetworkStatus(callInfo.slotId);
50d95e75fdSopenharmony_ci    if (netType == PhoneType::PHONE_TYPE_IS_GSM) {
51d95e75fdSopenharmony_ci        return DialGsm(callInfo);
52d95e75fdSopenharmony_ci    }
53d95e75fdSopenharmony_ci    if (netType == PhoneType::PHONE_TYPE_IS_CDMA) {
54d95e75fdSopenharmony_ci        return DialCdma(callInfo);
55d95e75fdSopenharmony_ci    }
56d95e75fdSopenharmony_ci    TELEPHONY_LOGE("Dial return, net type error.");
57d95e75fdSopenharmony_ci    CellularCallHiSysEvent::WriteDialCallFaultEvent(callInfo.slotId, static_cast<int32_t>(callInfo.callType),
58d95e75fdSopenharmony_ci        callInfo.videoState, CALL_ERR_UNSUPPORTED_NETWORK_TYPE, "Network type error");
59d95e75fdSopenharmony_ci    return CALL_ERR_UNSUPPORTED_NETWORK_TYPE;
60d95e75fdSopenharmony_ci}
61d95e75fdSopenharmony_ci
62d95e75fdSopenharmony_ciint32_t CSControl::DialCdma(const CellularCallInfo &callInfo)
63d95e75fdSopenharmony_ci{
64d95e75fdSopenharmony_ci    TELEPHONY_LOGI("DialCdma entry.");
65d95e75fdSopenharmony_ci    StandardizeUtils standardizeUtils;
66d95e75fdSopenharmony_ci    // Remove the phone number separator
67d95e75fdSopenharmony_ci    std::string newPhoneNum = standardizeUtils.RemoveSeparatorsPhoneNumber(callInfo.phoneNum);
68d95e75fdSopenharmony_ci
69d95e75fdSopenharmony_ci    CLIRMode clirMode = CLIRMode::DEFAULT;
70d95e75fdSopenharmony_ci    if (IsNeedExecuteMMI(callInfo.slotId, newPhoneNum, clirMode, false)) {
71d95e75fdSopenharmony_ci        TELEPHONY_LOGI("DialCdma return, mmi code type.");
72d95e75fdSopenharmony_ci        return RETURN_TYPE_MMI;
73d95e75fdSopenharmony_ci    }
74d95e75fdSopenharmony_ci
75d95e75fdSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
76d95e75fdSopenharmony_ci    if (!CanCall(connectionMap_)) {
77d95e75fdSopenharmony_ci        TELEPHONY_LOGE("CSControl::DialCdma return, error type: call state error.");
78d95e75fdSopenharmony_ci        CellularCallHiSysEvent::WriteDialCallFaultEvent(callInfo.slotId, static_cast<int32_t>(callInfo.callType),
79d95e75fdSopenharmony_ci            callInfo.videoState, CALL_ERR_CALL_COUNTS_EXCEED_LIMIT, "cs cdma dial call state error");
80d95e75fdSopenharmony_ci        return CALL_ERR_CALL_COUNTS_EXCEED_LIMIT;
81d95e75fdSopenharmony_ci    }
82d95e75fdSopenharmony_ci
83d95e75fdSopenharmony_ci    if (IsInState(connectionMap_, TelCallState::CALL_STATUS_ACTIVE)) {
84d95e75fdSopenharmony_ci        TELEPHONY_LOGI("DialCdma, CDMA is have connection in active state.");
85d95e75fdSopenharmony_ci        CellularCallConnectionCS csConnection;
86d95e75fdSopenharmony_ci        return csConnection.SendCDMAThreeWayDialRequest(callInfo.slotId);
87d95e75fdSopenharmony_ci    }
88d95e75fdSopenharmony_ci
89d95e75fdSopenharmony_ci    return EncapsulateDialCommon(callInfo.slotId, newPhoneNum, clirMode);
90d95e75fdSopenharmony_ci}
91d95e75fdSopenharmony_ci
92d95e75fdSopenharmony_ciint32_t CSControl::DialGsm(const CellularCallInfo &callInfo)
93d95e75fdSopenharmony_ci{
94d95e75fdSopenharmony_ci    TELEPHONY_LOGI("DialGsm entry.");
95d95e75fdSopenharmony_ci    StandardizeUtils standardizeUtils;
96d95e75fdSopenharmony_ci    // Remove the phone number separator
97d95e75fdSopenharmony_ci    std::string newPhoneNum = standardizeUtils.RemoveSeparatorsPhoneNumber(callInfo.phoneNum);
98d95e75fdSopenharmony_ci
99d95e75fdSopenharmony_ci    CLIRMode clirMode = CLIRMode::DEFAULT;
100d95e75fdSopenharmony_ci    if (IsNeedExecuteMMI(callInfo.slotId, newPhoneNum, clirMode, false)) {
101d95e75fdSopenharmony_ci        TELEPHONY_LOGI("DialGsm return, mmi code type.");
102d95e75fdSopenharmony_ci        return RETURN_TYPE_MMI;
103d95e75fdSopenharmony_ci    }
104d95e75fdSopenharmony_ci
105d95e75fdSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
106d95e75fdSopenharmony_ci    if (!CanCall(connectionMap_)) {
107d95e75fdSopenharmony_ci        TELEPHONY_LOGE("DialGsm return, error type: call state error.");
108d95e75fdSopenharmony_ci        CellularCallHiSysEvent::WriteDialCallFaultEvent(callInfo.slotId, static_cast<int32_t>(callInfo.callType),
109d95e75fdSopenharmony_ci            callInfo.videoState, CALL_ERR_CALL_COUNTS_EXCEED_LIMIT, "cs gsm dial call state error");
110d95e75fdSopenharmony_ci        return CALL_ERR_CALL_COUNTS_EXCEED_LIMIT;
111d95e75fdSopenharmony_ci    }
112d95e75fdSopenharmony_ci
113d95e75fdSopenharmony_ci    // Calls can be put on hold, recovered, released, added to conversation,
114d95e75fdSopenharmony_ci    // and transferred similarly as defined in 3GPP TS 22.030 [19].
115d95e75fdSopenharmony_ci    if (IsInState(connectionMap_, TelCallState::CALL_STATUS_ACTIVE)) {
116d95e75fdSopenharmony_ci        // New calls must be active, so other calls need to be hold
117d95e75fdSopenharmony_ci        TELEPHONY_LOGI("DialGsm, GSM is have connection in active state.");
118d95e75fdSopenharmony_ci        CellularCallConnectionCS pConnection;
119d95e75fdSopenharmony_ci
120d95e75fdSopenharmony_ci        // Delay dialing to prevent failure to add a new call while making a multi-party call
121d95e75fdSopenharmony_ci        // Will it block the main thread or other threads? Will the reception of messages be blocked during sleep?
122d95e75fdSopenharmony_ci        // - a call can be temporarily disconnected from the ME but the connection is retained by the network
123d95e75fdSopenharmony_ci        pConnection.SwitchCallRequest(callInfo.slotId);
124d95e75fdSopenharmony_ci    }
125d95e75fdSopenharmony_ci    return EncapsulateDialCommon(callInfo.slotId, newPhoneNum, clirMode);
126d95e75fdSopenharmony_ci}
127d95e75fdSopenharmony_ci
128d95e75fdSopenharmony_ciint32_t CSControl::EncapsulateDialCommon(int32_t slotId, const std::string &phoneNum, CLIRMode &clirMode)
129d95e75fdSopenharmony_ci{
130d95e75fdSopenharmony_ci    pendingPhoneNumber_ = phoneNum;
131d95e75fdSopenharmony_ci    DialRequestStruct dialRequest;
132d95e75fdSopenharmony_ci    /**
133d95e75fdSopenharmony_ci     * <idx>: integer type;
134d95e75fdSopenharmony_ci     * call identification number as described in 3GPP TS 22.030 [19] subclause 4.5.5.1
135d95e75fdSopenharmony_ci     * this number can be used in +CHLD command operations
136d95e75fdSopenharmony_ci     * <dir>:
137d95e75fdSopenharmony_ci     */
138d95e75fdSopenharmony_ci    dialRequest.phoneNum = phoneNum;
139d95e75fdSopenharmony_ci
140d95e75fdSopenharmony_ci    /**
141d95e75fdSopenharmony_ci     * <n> (parameter sets the adjustment for outgoing calls):
142d95e75fdSopenharmony_ci     *  0	presentation indicator is used according to the subscription of the CLIR service
143d95e75fdSopenharmony_ci     *  1	CLIR invocation
144d95e75fdSopenharmony_ci     *  2	CLIR suppression
145d95e75fdSopenharmony_ci     */
146d95e75fdSopenharmony_ci    dialRequest.clirMode = clirMode;
147d95e75fdSopenharmony_ci
148d95e75fdSopenharmony_ci    /**
149d95e75fdSopenharmony_ci     * An example of voice group call service request usage:
150d95e75fdSopenharmony_ci     * ATD*17*753#500; (originate voice group call with the priority level 3)
151d95e75fdSopenharmony_ci     * OK (voice group call setup was successful)
152d95e75fdSopenharmony_ci     */
153d95e75fdSopenharmony_ci    CellularCallConnectionCS csConnection;
154d95e75fdSopenharmony_ci    TELEPHONY_LOGI("Set Mute to false");
155d95e75fdSopenharmony_ci    if (DelayedSingleton<CellularCallService>::GetInstance() == nullptr) {
156d95e75fdSopenharmony_ci        TELEPHONY_LOGE("SetMute return, error type: GetInstance() is nullptr.");
157d95e75fdSopenharmony_ci        return CALL_ERR_RESOURCE_UNAVAILABLE;
158d95e75fdSopenharmony_ci    }
159d95e75fdSopenharmony_ci    DelayedSingleton<CellularCallService>::GetInstance()->SetMute(slotId, false);
160d95e75fdSopenharmony_ci    return csConnection.DialRequest(slotId, dialRequest);
161d95e75fdSopenharmony_ci}
162d95e75fdSopenharmony_ci
163d95e75fdSopenharmony_ciint32_t CSControl::HangUp(const CellularCallInfo &callInfo, CallSupplementType type)
164d95e75fdSopenharmony_ci{
165d95e75fdSopenharmony_ci    TELEPHONY_LOGI("HangUp start");
166d95e75fdSopenharmony_ci    switch (type) {
167d95e75fdSopenharmony_ci        case CallSupplementType::TYPE_DEFAULT: {
168d95e75fdSopenharmony_ci            // Match the session connection according to the phone number string
169d95e75fdSopenharmony_ci            std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
170d95e75fdSopenharmony_ci            auto pConnection = FindConnectionByIndex<CsConnectionMap &, CellularCallConnectionCS *>(
171d95e75fdSopenharmony_ci                connectionMap_, callInfo.index);
172d95e75fdSopenharmony_ci            if (pConnection == nullptr) {
173d95e75fdSopenharmony_ci                TELEPHONY_LOGE("CSControl::HangUp, error type: connection is null");
174d95e75fdSopenharmony_ci                CellularCallHiSysEvent::WriteHangUpFaultEvent(
175d95e75fdSopenharmony_ci                    callInfo.slotId, callInfo.callId, CALL_ERR_CALL_CONNECTION_NOT_EXIST, "HangUp pConnection is null");
176d95e75fdSopenharmony_ci                return CALL_ERR_CALL_CONNECTION_NOT_EXIST;
177d95e75fdSopenharmony_ci            }
178d95e75fdSopenharmony_ci
179d95e75fdSopenharmony_ci            if (DelayedSingleton<CellularCallRegister>::GetInstance() != nullptr) {
180d95e75fdSopenharmony_ci                DelayedSingleton<CellularCallRegister>::GetInstance()->ReportSingleCallInfo(
181d95e75fdSopenharmony_ci                    pConnection->GetCallReportInfo(), TelCallState::CALL_STATUS_DISCONNECTING);
182d95e75fdSopenharmony_ci            }
183d95e75fdSopenharmony_ci
184d95e75fdSopenharmony_ci            /**
185d95e75fdSopenharmony_ci             * The "directory number" case shall be handled with dial command D,
186d95e75fdSopenharmony_ci             * and the END case with hangup command H (or +CHUP).
187d95e75fdSopenharmony_ci             * (e.g. +CHLD: (0,1,1x,2,2x,3)).
188d95e75fdSopenharmony_ci             * NOTE: Call Hold, MultiParty and Explicit Call Transfer are only applicable to teleservice 11.
189d95e75fdSopenharmony_ci             */
190d95e75fdSopenharmony_ci            return pConnection->HangUpRequest(callInfo.slotId);
191d95e75fdSopenharmony_ci        }
192d95e75fdSopenharmony_ci        // 3GPP TS 27.007 V3.9.0 (2001-06) Call related supplementary services +CHLD
193d95e75fdSopenharmony_ci        // 3GPP TS 27.007 V3.9.0 (2001-06) 7.22 Informative examples
194d95e75fdSopenharmony_ci        case CallSupplementType::TYPE_HANG_UP_HOLD_WAIT:
195d95e75fdSopenharmony_ci        // release the second (active) call and recover the first (held) call
196d95e75fdSopenharmony_ci        case CallSupplementType::TYPE_HANG_UP_ACTIVE: {
197d95e75fdSopenharmony_ci            CellularCallConnectionCS connection;
198d95e75fdSopenharmony_ci            return connection.CallSupplementRequest(callInfo.slotId, type);
199d95e75fdSopenharmony_ci        }
200d95e75fdSopenharmony_ci        case CallSupplementType::TYPE_HANG_UP_ALL: {
201d95e75fdSopenharmony_ci            TELEPHONY_LOGI("HangUp, hang up all call");
202d95e75fdSopenharmony_ci            CellularCallConnectionCS connection;
203d95e75fdSopenharmony_ci            // The AT command for hanging up all calls is the same as the AT command for rejecting calls,
204d95e75fdSopenharmony_ci            // so the reject interface is reused.
205d95e75fdSopenharmony_ci            return connection.RejectRequest(callInfo.slotId);
206d95e75fdSopenharmony_ci        }
207d95e75fdSopenharmony_ci        default: {
208d95e75fdSopenharmony_ci            TELEPHONY_LOGE("HangUp warring, type is invalid");
209d95e75fdSopenharmony_ci            CellularCallHiSysEvent::WriteHangUpFaultEvent(
210d95e75fdSopenharmony_ci                callInfo.slotId, callInfo.callId, TELEPHONY_ERR_ARGUMENT_INVALID, "HangUp type is invalid");
211d95e75fdSopenharmony_ci            return TELEPHONY_ERR_ARGUMENT_INVALID;
212d95e75fdSopenharmony_ci        }
213d95e75fdSopenharmony_ci    }
214d95e75fdSopenharmony_ci}
215d95e75fdSopenharmony_ci
216d95e75fdSopenharmony_ciint32_t CSControl::Answer(const CellularCallInfo &callInfo)
217d95e75fdSopenharmony_ci{
218d95e75fdSopenharmony_ci    TELEPHONY_LOGI("CSControl::Answer start");
219d95e75fdSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
220d95e75fdSopenharmony_ci    auto pConnection =
221d95e75fdSopenharmony_ci        FindConnectionByIndex<CsConnectionMap &, CellularCallConnectionCS *>(connectionMap_, callInfo.index);
222d95e75fdSopenharmony_ci    if (pConnection == nullptr) {
223d95e75fdSopenharmony_ci        TELEPHONY_LOGE("Answer return, error type: connection is null");
224d95e75fdSopenharmony_ci        CellularCallHiSysEvent::WriteAnswerCallFaultEvent(callInfo.slotId, callInfo.callId, callInfo.videoState,
225d95e75fdSopenharmony_ci            CALL_ERR_CALL_CONNECTION_NOT_EXIST, "get connection data is null");
226d95e75fdSopenharmony_ci        return CALL_ERR_CALL_CONNECTION_NOT_EXIST;
227d95e75fdSopenharmony_ci    }
228d95e75fdSopenharmony_ci
229d95e75fdSopenharmony_ci    if (IsInState(connectionMap_, TelCallState::CALL_STATUS_HOLDING) &&
230d95e75fdSopenharmony_ci        IsInState(connectionMap_, TelCallState::CALL_STATUS_ACTIVE)) {
231d95e75fdSopenharmony_ci        int32_t ret = CheckAndHangupHoldingCall();
232d95e75fdSopenharmony_ci        if (ret != TELEPHONY_SUCCESS) {
233d95e75fdSopenharmony_ci            TELEPHONY_LOGE("hangup holding call failed");
234d95e75fdSopenharmony_ci            return ret;
235d95e75fdSopenharmony_ci        }
236d95e75fdSopenharmony_ci    }
237d95e75fdSopenharmony_ci    /**
238d95e75fdSopenharmony_ci     * <stat> (state of the call):
239d95e75fdSopenharmony_ci     * 0 active
240d95e75fdSopenharmony_ci     * 1 held
241d95e75fdSopenharmony_ci     * 2 dialing (MO call)
242d95e75fdSopenharmony_ci     * 3 alerting (MO call)
243d95e75fdSopenharmony_ci     * 4 incoming (MT call)
244d95e75fdSopenharmony_ci     * 5 waiting (MT call)
245d95e75fdSopenharmony_ci     */
246d95e75fdSopenharmony_ci    // There is an active call when you call, or third party call waiting
247d95e75fdSopenharmony_ci    if (IsInState(connectionMap_, TelCallState::CALL_STATUS_ACTIVE) ||
248d95e75fdSopenharmony_ci        pConnection->GetStatus() == TelCallState::CALL_STATUS_WAITING) {
249d95e75fdSopenharmony_ci        TELEPHONY_LOGI("Answer there is an active call when you call, or third party call waiting");
250d95e75fdSopenharmony_ci        auto con = FindConnectionByState<CsConnectionMap &, CellularCallConnectionCS *>(
251d95e75fdSopenharmony_ci            connectionMap_, TelCallState::CALL_STATUS_ACTIVE);
252d95e75fdSopenharmony_ci        if (con != nullptr) {
253d95e75fdSopenharmony_ci            /**
254d95e75fdSopenharmony_ci             * shows commands to start the call, to switch from voice to data (In Call Modification) and to hang up
255d95e75fdSopenharmony_ci             * the call. +CMOD and +FCLASS commands indicate the current settings before dialling or answering
256d95e75fdSopenharmony_ci             * command, not that they shall be given just before D or A command.
257d95e75fdSopenharmony_ci             */
258d95e75fdSopenharmony_ci            TELEPHONY_LOGI("Answer: There is an active session currently, and it needs to hold");
259d95e75fdSopenharmony_ci            con->SwitchCallRequest(callInfo.slotId);
260d95e75fdSopenharmony_ci        } else {
261d95e75fdSopenharmony_ci            TELEPHONY_LOGE("Answer return, error type: con is null, there are no active calls");
262d95e75fdSopenharmony_ci        }
263d95e75fdSopenharmony_ci    }
264d95e75fdSopenharmony_ci
265d95e75fdSopenharmony_ci    if (pConnection->GetStatus() == TelCallState::CALL_STATUS_INCOMING ||
266d95e75fdSopenharmony_ci        pConnection->GetStatus() == TelCallState::CALL_STATUS_ALERTING ||
267d95e75fdSopenharmony_ci        pConnection->GetStatus() == TelCallState::CALL_STATUS_WAITING) {
268d95e75fdSopenharmony_ci        return pConnection->AnswerRequest(callInfo.slotId);
269d95e75fdSopenharmony_ci    }
270d95e75fdSopenharmony_ci
271d95e75fdSopenharmony_ci    TELEPHONY_LOGE("CSControl::Answer return, error type: call state error, phone not ringing.");
272d95e75fdSopenharmony_ci    CellularCallHiSysEvent::WriteAnswerCallFaultEvent(callInfo.slotId, callInfo.callId, callInfo.videoState,
273d95e75fdSopenharmony_ci        CALL_ERR_CALL_STATE, "call state error phone not ringing");
274d95e75fdSopenharmony_ci    return CALL_ERR_CALL_STATE;
275d95e75fdSopenharmony_ci}
276d95e75fdSopenharmony_ci
277d95e75fdSopenharmony_ciint32_t CSControl::CheckAndHangupHoldingCall()
278d95e75fdSopenharmony_ci{
279d95e75fdSopenharmony_ci    for (auto &it : connectionMap_) {
280d95e75fdSopenharmony_ci        CellularCallConnectionCS holdConn = it.second;
281d95e75fdSopenharmony_ci        if (holdConn.GetStatus() == TelCallState::CALL_STATUS_HOLDING) {
282d95e75fdSopenharmony_ci            auto callReportInfo = holdConn.GetCallReportInfo();
283d95e75fdSopenharmony_ci            int32_t result = holdConn.HangUpRequest(callReportInfo.accountId);
284d95e75fdSopenharmony_ci            if (result != TELEPHONY_SUCCESS) {
285d95e75fdSopenharmony_ci                return result;
286d95e75fdSopenharmony_ci            }
287d95e75fdSopenharmony_ci        }
288d95e75fdSopenharmony_ci    }
289d95e75fdSopenharmony_ci    return TELEPHONY_SUCCESS;
290d95e75fdSopenharmony_ci}
291d95e75fdSopenharmony_ci
292d95e75fdSopenharmony_ciint32_t CSControl::Reject(const CellularCallInfo &callInfo)
293d95e75fdSopenharmony_ci{
294d95e75fdSopenharmony_ci    TELEPHONY_LOGI("CSControl::Reject start");
295d95e75fdSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
296d95e75fdSopenharmony_ci    auto pConnection =
297d95e75fdSopenharmony_ci        FindConnectionByIndex<CsConnectionMap &, CellularCallConnectionCS *>(connectionMap_, callInfo.index);
298d95e75fdSopenharmony_ci    if (pConnection == nullptr) {
299d95e75fdSopenharmony_ci        TELEPHONY_LOGE("CSControl::Reject, error type: connection is null");
300d95e75fdSopenharmony_ci        CellularCallHiSysEvent::WriteHangUpFaultEvent(
301d95e75fdSopenharmony_ci            callInfo.slotId, callInfo.callId, CALL_ERR_CALL_CONNECTION_NOT_EXIST, "Reject pConnection is null");
302d95e75fdSopenharmony_ci        return CALL_ERR_CALL_CONNECTION_NOT_EXIST;
303d95e75fdSopenharmony_ci    }
304d95e75fdSopenharmony_ci
305d95e75fdSopenharmony_ci    /**
306d95e75fdSopenharmony_ci     * shows commands to start the call, to switch from voice to data (In Call Modification) and to hang up the call.
307d95e75fdSopenharmony_ci     * +CMOD and +FCLASS commands indicate the current settings before dialling or answering command,
308d95e75fdSopenharmony_ci     * not that they shall be given just before D or A command.
309d95e75fdSopenharmony_ci     */
310d95e75fdSopenharmony_ci    if (!pConnection->IsRingingState()) {
311d95e75fdSopenharmony_ci        TELEPHONY_LOGE("CSControl::Reject return, error type: call state error, phone not ringing.");
312d95e75fdSopenharmony_ci        CellularCallHiSysEvent::WriteHangUpFaultEvent(
313d95e75fdSopenharmony_ci            callInfo.slotId, callInfo.callId, CALL_ERR_CALL_STATE, "Reject call state error phone not ringing");
314d95e75fdSopenharmony_ci        return CALL_ERR_CALL_STATE;
315d95e75fdSopenharmony_ci    }
316d95e75fdSopenharmony_ci    if (DelayedSingleton<CellularCallRegister>::GetInstance() != nullptr) {
317d95e75fdSopenharmony_ci        DelayedSingleton<CellularCallRegister>::GetInstance()->ReportSingleCallInfo(
318d95e75fdSopenharmony_ci            pConnection->GetCallReportInfo(), TelCallState::CALL_STATUS_DISCONNECTING);
319d95e75fdSopenharmony_ci    }
320d95e75fdSopenharmony_ci    return pConnection->RejectRequest(callInfo.slotId);
321d95e75fdSopenharmony_ci}
322d95e75fdSopenharmony_ci
323d95e75fdSopenharmony_ciint32_t CSControl::HoldCall(int32_t slotId)
324d95e75fdSopenharmony_ci{
325d95e75fdSopenharmony_ci    /**
326d95e75fdSopenharmony_ci     * When the call hold service is invoked, communication is interrupted on the traffic channel and the traffic
327d95e75fdSopenharmony_ci     * channel is released from the existing call. The traffic channel is reserved for the served mobile subscriber
328d95e75fdSopenharmony_ci     * invoking the call hold service. The served mobile subscriber can only have one call on hold at a time.
329d95e75fdSopenharmony_ci     */
330d95e75fdSopenharmony_ci    TELEPHONY_LOGI("HoldCall start");
331d95e75fdSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
332d95e75fdSopenharmony_ci    if (IsInState(connectionMap_, TelCallState::CALL_STATUS_INCOMING)) {
333d95e75fdSopenharmony_ci        TELEPHONY_LOGE("HoldCall return, error type: call state error.");
334d95e75fdSopenharmony_ci        return CALL_ERR_CALL_STATE;
335d95e75fdSopenharmony_ci    }
336d95e75fdSopenharmony_ci    CellularCallConnectionCS connection;
337d95e75fdSopenharmony_ci    return connection.HoldRequest(slotId);
338d95e75fdSopenharmony_ci}
339d95e75fdSopenharmony_ci
340d95e75fdSopenharmony_ciint32_t CSControl::UnHoldCall(int32_t slotId)
341d95e75fdSopenharmony_ci{
342d95e75fdSopenharmony_ci    // A notification shall be send towards the previously held party that the call has been retrieved.
343d95e75fdSopenharmony_ci    TELEPHONY_LOGI("UnHoldCall start");
344d95e75fdSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
345d95e75fdSopenharmony_ci    if (IsInState(connectionMap_, TelCallState::CALL_STATUS_INCOMING)) {
346d95e75fdSopenharmony_ci        TELEPHONY_LOGE("UnHoldCall return, error type: call state error.");
347d95e75fdSopenharmony_ci        return CALL_ERR_CALL_STATE;
348d95e75fdSopenharmony_ci    }
349d95e75fdSopenharmony_ci    CellularCallConnectionCS connection;
350d95e75fdSopenharmony_ci    return connection.UnHoldCallRequest(slotId);
351d95e75fdSopenharmony_ci}
352d95e75fdSopenharmony_ci
353d95e75fdSopenharmony_ciint32_t CSControl::SwitchCall(int32_t slotId)
354d95e75fdSopenharmony_ci{
355d95e75fdSopenharmony_ci    /**
356d95e75fdSopenharmony_ci     * If the served mobile subscriber is connected to an active call and has another call on hold, she can:
357d95e75fdSopenharmony_ci     * 1) Alternate from one call to the other.
358d95e75fdSopenharmony_ci     * 2) Disconnect the active call.
359d95e75fdSopenharmony_ci     * 3) Disconnect the held call.
360d95e75fdSopenharmony_ci     * 4) Disconnect both calls.
361d95e75fdSopenharmony_ci     */
362d95e75fdSopenharmony_ci    TELEPHONY_LOGI("SwitchCall start");
363d95e75fdSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
364d95e75fdSopenharmony_ci    if (IsInState(connectionMap_, TelCallState::CALL_STATUS_INCOMING)) {
365d95e75fdSopenharmony_ci        TELEPHONY_LOGE("SwitchCall return, error type: call state error.");
366d95e75fdSopenharmony_ci        return CALL_ERR_CALL_STATE;
367d95e75fdSopenharmony_ci    }
368d95e75fdSopenharmony_ci    CellularCallConnectionCS connection;
369d95e75fdSopenharmony_ci    return connection.SwitchCallRequest(slotId);
370d95e75fdSopenharmony_ci}
371d95e75fdSopenharmony_ci
372d95e75fdSopenharmony_ci/**
373d95e75fdSopenharmony_ci * Explicitly choose one remote party to have a private communication with.
374d95e75fdSopenharmony_ci * This results in that remote party being removed from the multiParty call which is placed on hold,
375d95e75fdSopenharmony_ci * and the conversation between the served mobile subscriber and the designated remote party being a normal
376d95e75fdSopenharmony_ci * active call. The remaining remote parties may have communication with each other in this state.
377d95e75fdSopenharmony_ci */
378d95e75fdSopenharmony_ciint32_t CSControl::SeparateConference(int32_t slotId, const std::string &splitString, int32_t index)
379d95e75fdSopenharmony_ci{
380d95e75fdSopenharmony_ci    TELEPHONY_LOGI("SeparateConference entry");
381d95e75fdSopenharmony_ci    if (splitString.empty()) {
382d95e75fdSopenharmony_ci        TELEPHONY_LOGW("SeparateConference, splitString is empty.");
383d95e75fdSopenharmony_ci    }
384d95e75fdSopenharmony_ci
385d95e75fdSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
386d95e75fdSopenharmony_ci    auto pConnection = FindConnectionByIndex<CsConnectionMap &, CellularCallConnectionCS *>(connectionMap_, index);
387d95e75fdSopenharmony_ci    if (pConnection != nullptr) {
388d95e75fdSopenharmony_ci        return pConnection->SeparateConferenceRequest(slotId, pConnection->GetIndex(), VOICE_CALL);
389d95e75fdSopenharmony_ci    }
390d95e75fdSopenharmony_ci
391d95e75fdSopenharmony_ci    TELEPHONY_LOGI("SeparateConference: connection cannot be matched, use index directly");
392d95e75fdSopenharmony_ci    CellularCallConnectionCS connection;
393d95e75fdSopenharmony_ci    return connection.SeparateConferenceRequest(slotId, index, VOICE_CALL);
394d95e75fdSopenharmony_ci}
395d95e75fdSopenharmony_ci
396d95e75fdSopenharmony_ci/**
397d95e75fdSopenharmony_ci * Add another remote party, to which a private communication has been established using
398d95e75fdSopenharmony_ci * the same procedures as in Section 1.3.8.1, if the number of remote parties does not then
399d95e75fdSopenharmony_ci * exceed the maximum number allowed, which results in an active multiParty call.
400d95e75fdSopenharmony_ci */
401d95e75fdSopenharmony_ciint32_t CSControl::CombineConference(int32_t slotId)
402d95e75fdSopenharmony_ci{
403d95e75fdSopenharmony_ci    CellularCallConnectionCS connectionCs;
404d95e75fdSopenharmony_ci    return connectionCs.CombineConferenceRequest(slotId, VOICE_CALL);
405d95e75fdSopenharmony_ci}
406d95e75fdSopenharmony_ci
407d95e75fdSopenharmony_ciint32_t CSControl::HangUpAllConnection(int32_t slotId)
408d95e75fdSopenharmony_ci{
409d95e75fdSopenharmony_ci    TELEPHONY_LOGI("HangUpAllConnection entry");
410d95e75fdSopenharmony_ci    CellularCallConnectionCS connection;
411d95e75fdSopenharmony_ci    // The AT command for hanging up all calls is the same as the AT command for rejecting calls,
412d95e75fdSopenharmony_ci    // so the reject interface is reused.
413d95e75fdSopenharmony_ci    return connection.RejectRequest(slotId);
414d95e75fdSopenharmony_ci}
415d95e75fdSopenharmony_ci
416d95e75fdSopenharmony_cibool CSControl::CalculateInternationalRoaming(int32_t slotId) const
417d95e75fdSopenharmony_ci{
418d95e75fdSopenharmony_ci    bool ret = true;
419d95e75fdSopenharmony_ci    ModuleServiceUtils moduleServiceUtils;
420d95e75fdSopenharmony_ci    std::string operatorCountryIso = moduleServiceUtils.GetNetworkCountryCode(slotId);
421d95e75fdSopenharmony_ci    std::string simCountryIso = moduleServiceUtils.GetIsoCountryCode(slotId);
422d95e75fdSopenharmony_ci    ret = !operatorCountryIso.empty() && !simCountryIso.empty() && (operatorCountryIso != simCountryIso);
423d95e75fdSopenharmony_ci    if (ret) {
424d95e75fdSopenharmony_ci        if (simCountryIso == "us") {
425d95e75fdSopenharmony_ci            ret = operatorCountryIso != "vi";
426d95e75fdSopenharmony_ci        } else if (simCountryIso == "vi") {
427d95e75fdSopenharmony_ci            ret = operatorCountryIso != "us";
428d95e75fdSopenharmony_ci        }
429d95e75fdSopenharmony_ci    }
430d95e75fdSopenharmony_ci    return ret;
431d95e75fdSopenharmony_ci}
432d95e75fdSopenharmony_ci
433d95e75fdSopenharmony_ciint32_t CSControl::ReportCallsData(int32_t slotId, const CallInfoList &callInfoList)
434d95e75fdSopenharmony_ci{
435d95e75fdSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
436d95e75fdSopenharmony_ci    if (callInfoList.callSize <= 0) {
437d95e75fdSopenharmony_ci        return ReportHangUpInfo(slotId);
438d95e75fdSopenharmony_ci    } else if (callInfoList.callSize > 0 && connectionMap_.empty()) {
439d95e75fdSopenharmony_ci        return ReportIncomingInfo(slotId, callInfoList);
440d95e75fdSopenharmony_ci    } else if (callInfoList.callSize > 0 && !connectionMap_.empty()) {
441d95e75fdSopenharmony_ci        return ReportUpdateInfo(slotId, callInfoList);
442d95e75fdSopenharmony_ci    }
443d95e75fdSopenharmony_ci    return TELEPHONY_ERROR;
444d95e75fdSopenharmony_ci}
445d95e75fdSopenharmony_ci
446d95e75fdSopenharmony_ciint32_t CSControl::ReportUpdateInfo(int32_t slotId, const CallInfoList &callInfoList)
447d95e75fdSopenharmony_ci{
448d95e75fdSopenharmony_ci    TELEPHONY_LOGD("ReportUpdateInfo entry");
449d95e75fdSopenharmony_ci    CallsReportInfo callsReportInfo;
450d95e75fdSopenharmony_ci    for (int32_t i = 0; i < callInfoList.callSize; ++i) {
451d95e75fdSopenharmony_ci        CallReportInfo reportInfo = EncapsulationCallReportInfo(slotId, callInfoList.calls[i]);
452d95e75fdSopenharmony_ci        if (callInfoList.callSize == 1 && reportInfo.state == TelCallState::CALL_STATUS_WAITING) {
453d95e75fdSopenharmony_ci            TELEPHONY_LOGI("only one call, report incoming state instead of waiting state");
454d95e75fdSopenharmony_ci            reportInfo.state = TelCallState::CALL_STATUS_INCOMING;
455d95e75fdSopenharmony_ci        }
456d95e75fdSopenharmony_ci        auto pConnection = FindConnectionByIndex<CsConnectionMap &, CellularCallConnectionCS *>(
457d95e75fdSopenharmony_ci            connectionMap_, callInfoList.calls[i].index);
458d95e75fdSopenharmony_ci        if (pConnection == nullptr) {
459d95e75fdSopenharmony_ci            CellularCallConnectionCS connection;
460d95e75fdSopenharmony_ci            connection.SetOrUpdateCallReportInfo(reportInfo);
461d95e75fdSopenharmony_ci            connection.SetFlag(true);
462d95e75fdSopenharmony_ci            connection.SetIndex(callInfoList.calls[i].index);
463d95e75fdSopenharmony_ci            connection.SetNumber(callInfoList.calls[i].number);
464d95e75fdSopenharmony_ci            SetConnectionData(connectionMap_, callInfoList.calls[i].index, connection);
465d95e75fdSopenharmony_ci        } else {
466d95e75fdSopenharmony_ci            TelCallState preCallState = pConnection->GetStatus();
467d95e75fdSopenharmony_ci            pConnection->SetFlag(true);
468d95e75fdSopenharmony_ci            pConnection->SetIndex(callInfoList.calls[i].index);
469d95e75fdSopenharmony_ci            pConnection->SetOrUpdateCallReportInfo(reportInfo);
470d95e75fdSopenharmony_ci            pConnection->SetNumber(callInfoList.calls[i].number);
471d95e75fdSopenharmony_ci            TelCallState curCallState = pConnection->GetStatus();
472d95e75fdSopenharmony_ci            if (IsConnectedOut(preCallState, curCallState)) {
473d95e75fdSopenharmony_ci                pConnection->UpdateCallNumber(pendingPhoneNumber_);
474d95e75fdSopenharmony_ci                pendingPhoneNumber_.clear();
475d95e75fdSopenharmony_ci                ExecutePostDial(slotId, pConnection->GetIndex());
476d95e75fdSopenharmony_ci            }
477d95e75fdSopenharmony_ci        }
478d95e75fdSopenharmony_ci        callsReportInfo.callVec.push_back(reportInfo);
479d95e75fdSopenharmony_ci    }
480d95e75fdSopenharmony_ci    callsReportInfo.slotId = slotId;
481d95e75fdSopenharmony_ci    DeleteConnection(callsReportInfo, callInfoList);
482d95e75fdSopenharmony_ci    if (DelayedSingleton<CellularCallRegister>::GetInstance() == nullptr) {
483d95e75fdSopenharmony_ci        TELEPHONY_LOGE("ReportUpdateInfo return, GetInstance() is nullptr.");
484d95e75fdSopenharmony_ci        return TELEPHONY_ERR_LOCAL_PTR_NULL;
485d95e75fdSopenharmony_ci    }
486d95e75fdSopenharmony_ci    if (!isIgnoredIncomingCall_) {
487d95e75fdSopenharmony_ci        DelayedSingleton<CellularCallRegister>::GetInstance()->ReportCallsInfo(callsReportInfo);
488d95e75fdSopenharmony_ci    }
489d95e75fdSopenharmony_ci    return TELEPHONY_SUCCESS;
490d95e75fdSopenharmony_ci}
491d95e75fdSopenharmony_ci
492d95e75fdSopenharmony_civoid CSControl::DeleteConnection(CallsReportInfo &callsReportInfo, const CallInfoList &callInfoList)
493d95e75fdSopenharmony_ci{
494d95e75fdSopenharmony_ci    TELEPHONY_LOGI("DeleteConnection entry");
495d95e75fdSopenharmony_ci    auto it = connectionMap_.begin();
496d95e75fdSopenharmony_ci    while (it != connectionMap_.end()) {
497d95e75fdSopenharmony_ci        CallReportInfo callReportInfo = it->second.GetCallReportInfo();
498d95e75fdSopenharmony_ci        if (!it->second.GetFlag()) {
499d95e75fdSopenharmony_ci            callReportInfo.state = TelCallState::CALL_STATUS_DISCONNECTED;
500d95e75fdSopenharmony_ci            callsReportInfo.callVec.push_back(callReportInfo);
501d95e75fdSopenharmony_ci            it = connectionMap_.erase(it);
502d95e75fdSopenharmony_ci            GetCallFailReason(callsReportInfo.slotId, connectionMap_);
503d95e75fdSopenharmony_ci        } else {
504d95e75fdSopenharmony_ci            it->second.SetFlag(false);
505d95e75fdSopenharmony_ci            ++it;
506d95e75fdSopenharmony_ci        }
507d95e75fdSopenharmony_ci    }
508d95e75fdSopenharmony_ci}
509d95e75fdSopenharmony_ci
510d95e75fdSopenharmony_ciCallReportInfo CSControl::EncapsulationCallReportInfo(int32_t slotId, const CallInfo &callInfo)
511d95e75fdSopenharmony_ci{
512d95e75fdSopenharmony_ci    CallReportInfo callReportInfo;
513d95e75fdSopenharmony_ci    if (memset_s(&callReportInfo, sizeof(callReportInfo), 0, sizeof(callReportInfo)) != EOK) {
514d95e75fdSopenharmony_ci        TELEPHONY_LOGE("EncapsulationCallReportInfo return, memset_s fail.");
515d95e75fdSopenharmony_ci        return callReportInfo;
516d95e75fdSopenharmony_ci    }
517d95e75fdSopenharmony_ci    StandardizeUtils standardizeUtils;
518d95e75fdSopenharmony_ci    std::string newString = standardizeUtils.FormatNumberAndToa(callInfo.number, callInfo.type);
519d95e75fdSopenharmony_ci
520d95e75fdSopenharmony_ci    /**
521d95e75fdSopenharmony_ci     * <idx>: integer type;
522d95e75fdSopenharmony_ci     * call identification number as described in 3GPP TS 22.030 [19] subclause 4.5.5.1
523d95e75fdSopenharmony_ci     * this number can be used in +CHLD command operations
524d95e75fdSopenharmony_ci     * <dir>:
525d95e75fdSopenharmony_ci     */
526d95e75fdSopenharmony_ci    size_t cpyLen = strlen(newString.c_str()) + 1;
527d95e75fdSopenharmony_ci    if (cpyLen > static_cast<size_t>(kMaxNumberLen + 1)) {
528d95e75fdSopenharmony_ci        TELEPHONY_LOGE("EncapsulationCallReportInfo return, strcpy_s fail.");
529d95e75fdSopenharmony_ci        return callReportInfo;
530d95e75fdSopenharmony_ci    }
531d95e75fdSopenharmony_ci    if (strcpy_s(callReportInfo.accountNum, cpyLen, newString.c_str()) != EOK) {
532d95e75fdSopenharmony_ci        TELEPHONY_LOGE("EncapsulationCallReportInfo return, strcpy_s fail.");
533d95e75fdSopenharmony_ci        return callReportInfo;
534d95e75fdSopenharmony_ci    }
535d95e75fdSopenharmony_ci
536d95e75fdSopenharmony_ci    /**
537d95e75fdSopenharmony_ci     * <stat> (state of the call):
538d95e75fdSopenharmony_ci     * 0 active
539d95e75fdSopenharmony_ci     * 1 held
540d95e75fdSopenharmony_ci     * 2 dialing (MO call)
541d95e75fdSopenharmony_ci     * 3 alerting (MO call)
542d95e75fdSopenharmony_ci     * 4 incoming (MT call)
543d95e75fdSopenharmony_ci     * 5 waiting (MT call)
544d95e75fdSopenharmony_ci     */
545d95e75fdSopenharmony_ci    callReportInfo.index = callInfo.index;
546d95e75fdSopenharmony_ci    callReportInfo.accountId = slotId;
547d95e75fdSopenharmony_ci    callReportInfo.voiceDomain = callInfo.voiceDomain;
548d95e75fdSopenharmony_ci    callReportInfo.state = static_cast<TelCallState>(callInfo.state);
549d95e75fdSopenharmony_ci    callReportInfo.callType = CallType::TYPE_CS;
550d95e75fdSopenharmony_ci    callReportInfo.callMode = VideoStateType::TYPE_VOICE;
551d95e75fdSopenharmony_ci    callReportInfo.mpty = callInfo.mpty;
552d95e75fdSopenharmony_ci    return callReportInfo;
553d95e75fdSopenharmony_ci}
554d95e75fdSopenharmony_ci
555d95e75fdSopenharmony_ciint32_t CSControl::ReportIncomingInfo(int32_t slotId, const CallInfoList &callInfoList)
556d95e75fdSopenharmony_ci{
557d95e75fdSopenharmony_ci    TELEPHONY_LOGI("ReportIncomingInfo entry");
558d95e75fdSopenharmony_ci    CallsReportInfo callsReportInfo;
559d95e75fdSopenharmony_ci    for (int32_t i = 0; i < callInfoList.callSize; ++i) {
560d95e75fdSopenharmony_ci        CallReportInfo cellularCallReportInfo = EncapsulationCallReportInfo(slotId, callInfoList.calls[i]);
561d95e75fdSopenharmony_ci
562d95e75fdSopenharmony_ci        CellularCallConnectionCS connection;
563d95e75fdSopenharmony_ci        connection.SetStatus(static_cast<TelCallState>(callInfoList.calls[i].state));
564d95e75fdSopenharmony_ci        connection.SetIndex(callInfoList.calls[i].index);
565d95e75fdSopenharmony_ci        connection.SetOrUpdateCallReportInfo(cellularCallReportInfo);
566d95e75fdSopenharmony_ci        connection.SetNumber(callInfoList.calls[i].number);
567d95e75fdSopenharmony_ci        SetConnectionData(connectionMap_, callInfoList.calls[i].index, connection);
568d95e75fdSopenharmony_ci
569d95e75fdSopenharmony_ci        callsReportInfo.callVec.push_back(cellularCallReportInfo);
570d95e75fdSopenharmony_ci    }
571d95e75fdSopenharmony_ci    if (DelayedSingleton<CellularCallRegister>::GetInstance() == nullptr) {
572d95e75fdSopenharmony_ci        TELEPHONY_LOGE("ReportIncomingInfo return, GetInstance() is nullptr.");
573d95e75fdSopenharmony_ci        return TELEPHONY_ERR_ARGUMENT_INVALID;
574d95e75fdSopenharmony_ci    }
575d95e75fdSopenharmony_ci    callsReportInfo.slotId = slotId;
576d95e75fdSopenharmony_ci    if (!DelayedSingleton<CellularCallRegister>::GetInstance()->IsCallManagerCallBackRegistered() &&
577d95e75fdSopenharmony_ci        callsReportInfo.callVec.size() != 0 && callsReportInfo.callVec[0].state == TelCallState::CALL_STATUS_INCOMING) {
578d95e75fdSopenharmony_ci        isIgnoredIncomingCall_ = true;
579d95e75fdSopenharmony_ci    } else {
580d95e75fdSopenharmony_ci        DelayedSingleton<CellularCallRegister>::GetInstance()->ReportCallsInfo(callsReportInfo);
581d95e75fdSopenharmony_ci    }
582d95e75fdSopenharmony_ci    return TELEPHONY_SUCCESS;
583d95e75fdSopenharmony_ci}
584d95e75fdSopenharmony_ci
585d95e75fdSopenharmony_ciint32_t CSControl::ReportHangUpInfo(int32_t slotId)
586d95e75fdSopenharmony_ci{
587d95e75fdSopenharmony_ci    TELEPHONY_LOGD("ReportHangUpInfo entry");
588d95e75fdSopenharmony_ci    CallsReportInfo callsReportInfo;
589d95e75fdSopenharmony_ci    for (auto &it : connectionMap_) {
590d95e75fdSopenharmony_ci        CallReportInfo callReportInfo = it.second.GetCallReportInfo();
591d95e75fdSopenharmony_ci        callReportInfo.state = TelCallState::CALL_STATUS_DISCONNECTED;
592d95e75fdSopenharmony_ci        callReportInfo.accountId = slotId;
593d95e75fdSopenharmony_ci        callsReportInfo.callVec.push_back(callReportInfo);
594d95e75fdSopenharmony_ci        GetCallFailReason(slotId, connectionMap_);
595d95e75fdSopenharmony_ci    }
596d95e75fdSopenharmony_ci    if (connectionMap_.empty()) {
597d95e75fdSopenharmony_ci        TELEPHONY_LOGI("connectionMap_ is empty");
598d95e75fdSopenharmony_ci        CallReportInfo reportInfo;
599d95e75fdSopenharmony_ci        reportInfo.state = TelCallState::CALL_STATUS_DISCONNECTED;
600d95e75fdSopenharmony_ci        reportInfo.accountId = slotId;
601d95e75fdSopenharmony_ci        callsReportInfo.callVec.push_back(reportInfo);
602d95e75fdSopenharmony_ci    }
603d95e75fdSopenharmony_ci    if (DelayedSingleton<CellularCallRegister>::GetInstance() == nullptr) {
604d95e75fdSopenharmony_ci        TELEPHONY_LOGE("ReportHangUpInfo return, GetInstance() is nullptr.");
605d95e75fdSopenharmony_ci        return TELEPHONY_ERR_LOCAL_PTR_NULL;
606d95e75fdSopenharmony_ci    }
607d95e75fdSopenharmony_ci    callsReportInfo.slotId = slotId;
608d95e75fdSopenharmony_ci    if (isIgnoredIncomingCall_) {
609d95e75fdSopenharmony_ci        isIgnoredIncomingCall_ = false;
610d95e75fdSopenharmony_ci    } else {
611d95e75fdSopenharmony_ci        DelayedSingleton<CellularCallRegister>::GetInstance()->ReportCallsInfo(callsReportInfo);
612d95e75fdSopenharmony_ci    }
613d95e75fdSopenharmony_ci    ReleaseAllConnection();
614d95e75fdSopenharmony_ci    return TELEPHONY_SUCCESS;
615d95e75fdSopenharmony_ci}
616d95e75fdSopenharmony_ci
617d95e75fdSopenharmony_ciint32_t CSControl::ExecutePostDial(int32_t slotId, int64_t callId)
618d95e75fdSopenharmony_ci{
619d95e75fdSopenharmony_ci    TELEPHONY_LOGI("ExecutePostDial entry");
620d95e75fdSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
621d95e75fdSopenharmony_ci    if (connectionMap_.empty()) {
622d95e75fdSopenharmony_ci        TELEPHONY_LOGE("connectionMap_ is empty.");
623d95e75fdSopenharmony_ci        return TELEPHONY_ERROR;
624d95e75fdSopenharmony_ci    }
625d95e75fdSopenharmony_ci    auto pConnection = FindConnectionByIndex<CsConnectionMap &, CellularCallConnectionCS *>(connectionMap_, callId);
626d95e75fdSopenharmony_ci    if (pConnection == nullptr) {
627d95e75fdSopenharmony_ci        return TELEPHONY_ERR_LOCAL_PTR_NULL;
628d95e75fdSopenharmony_ci    }
629d95e75fdSopenharmony_ci    char currentChar;
630d95e75fdSopenharmony_ci    PostDialCallState state = pConnection->ProcessNextChar(slotId, currentChar);
631d95e75fdSopenharmony_ci    switch (state) {
632d95e75fdSopenharmony_ci        case PostDialCallState::POST_DIAL_CALL_STARTED:
633d95e75fdSopenharmony_ci            DelayedSingleton<CellularCallRegister>::GetInstance()->ReportPostDialChar(currentChar);
634d95e75fdSopenharmony_ci            break;
635d95e75fdSopenharmony_ci        case PostDialCallState::POST_DIAL_CALL_DELAY:
636d95e75fdSopenharmony_ci            DelayedSingleton<CellularCallRegister>::GetInstance()->ReportPostDialDelay(
637d95e75fdSopenharmony_ci                pConnection->GetLeftPostDialCallString());
638d95e75fdSopenharmony_ci            break;
639d95e75fdSopenharmony_ci        default:
640d95e75fdSopenharmony_ci            break;
641d95e75fdSopenharmony_ci    }
642d95e75fdSopenharmony_ci    return TELEPHONY_SUCCESS;
643d95e75fdSopenharmony_ci}
644d95e75fdSopenharmony_ci
645d95e75fdSopenharmony_ciint32_t CSControl::PostDialProceed(const CellularCallInfo &callInfo, const bool proceed)
646d95e75fdSopenharmony_ci{
647d95e75fdSopenharmony_ci    TELEPHONY_LOGI("PostDialProceed entry");
648d95e75fdSopenharmony_ci    std::string networkAddress;
649d95e75fdSopenharmony_ci    std::string postDialString;
650d95e75fdSopenharmony_ci    StandardizeUtils standardizeUtils;
651d95e75fdSopenharmony_ci    standardizeUtils.ExtractAddressAndPostDial(callInfo.phoneNum, networkAddress, postDialString);
652d95e75fdSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
653d95e75fdSopenharmony_ci    auto pConnection = FindConnectionByIndex<CsConnectionMap &, CellularCallConnectionCS *>(
654d95e75fdSopenharmony_ci        connectionMap_, callInfo.index);
655d95e75fdSopenharmony_ci    if (pConnection == nullptr) {
656d95e75fdSopenharmony_ci        TELEPHONY_LOGE("cs pConnection is nullptr!");
657d95e75fdSopenharmony_ci        return TELEPHONY_ERR_LOCAL_PTR_NULL;
658d95e75fdSopenharmony_ci    }
659d95e75fdSopenharmony_ci    if (proceed) {
660d95e75fdSopenharmony_ci        ExecutePostDial(callInfo.slotId, pConnection->GetIndex());
661d95e75fdSopenharmony_ci    } else {
662d95e75fdSopenharmony_ci        pConnection->SetPostDialCallState(PostDialCallState::POST_DIAL_CALL_CANCELED);
663d95e75fdSopenharmony_ci    }
664d95e75fdSopenharmony_ci    return TELEPHONY_SUCCESS;
665d95e75fdSopenharmony_ci}
666d95e75fdSopenharmony_ci
667d95e75fdSopenharmony_civoid CSControl::ReleaseAllConnection()
668d95e75fdSopenharmony_ci{
669d95e75fdSopenharmony_ci    TELEPHONY_LOGI("ReleaseAllConnection entry");
670d95e75fdSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
671d95e75fdSopenharmony_ci    connectionMap_.clear();
672d95e75fdSopenharmony_ci}
673d95e75fdSopenharmony_ci
674d95e75fdSopenharmony_ciCsConnectionMap CSControl::GetConnectionMap()
675d95e75fdSopenharmony_ci{
676d95e75fdSopenharmony_ci    TELEPHONY_LOGI("GetConnectionMap entry");
677d95e75fdSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
678d95e75fdSopenharmony_ci    return connectionMap_;
679d95e75fdSopenharmony_ci}
680d95e75fdSopenharmony_ci
681d95e75fdSopenharmony_ciint32_t CSControl::ReportHangUp(const std::vector<CellularCallInfo> &infos, int32_t slotId)
682d95e75fdSopenharmony_ci{
683d95e75fdSopenharmony_ci    CallsReportInfo callsReportInfo;
684d95e75fdSopenharmony_ci    callsReportInfo.slotId = slotId;
685d95e75fdSopenharmony_ci    for (const auto &info : infos) {
686d95e75fdSopenharmony_ci        if (info.callType == CallType::TYPE_CS && info.slotId == slotId) {
687d95e75fdSopenharmony_ci            CallReportInfo csCallReportInfo;
688d95e75fdSopenharmony_ci            if (memset_s(csCallReportInfo.accountNum, kMaxNumberLen + 1, 0, kMaxNumberLen + 1) != EOK) {
689d95e75fdSopenharmony_ci                TELEPHONY_LOGE("memset_s fail");
690d95e75fdSopenharmony_ci                return TELEPHONY_ERR_MEMSET_FAIL;
691d95e75fdSopenharmony_ci            }
692d95e75fdSopenharmony_ci            if (memcpy_s(csCallReportInfo.accountNum, kMaxNumberLen, info.phoneNum, kMaxNumberLen) != EOK) {
693d95e75fdSopenharmony_ci                TELEPHONY_LOGE("memcpy_s fail");
694d95e75fdSopenharmony_ci                return TELEPHONY_ERR_MEMCPY_FAIL;
695d95e75fdSopenharmony_ci            }
696d95e75fdSopenharmony_ci            csCallReportInfo.index = info.index;
697d95e75fdSopenharmony_ci            csCallReportInfo.accountId = info.slotId;
698d95e75fdSopenharmony_ci            csCallReportInfo.callType = CallType::TYPE_CS;
699d95e75fdSopenharmony_ci            csCallReportInfo.callMode = VideoStateType::TYPE_VOICE;
700d95e75fdSopenharmony_ci            csCallReportInfo.state = TelCallState::CALL_STATUS_DISCONNECTED;
701d95e75fdSopenharmony_ci            callsReportInfo.callVec.push_back(csCallReportInfo);
702d95e75fdSopenharmony_ci        }
703d95e75fdSopenharmony_ci    }
704d95e75fdSopenharmony_ci    if (DelayedSingleton<CellularCallRegister>::GetInstance() == nullptr) {
705d95e75fdSopenharmony_ci        TELEPHONY_LOGE("CellularCallRegister instance is nullptr");
706d95e75fdSopenharmony_ci        return TELEPHONY_ERR_LOCAL_PTR_NULL;
707d95e75fdSopenharmony_ci    }
708d95e75fdSopenharmony_ci    DelayedSingleton<CellularCallRegister>::GetInstance()->ReportCallsInfo(callsReportInfo);
709d95e75fdSopenharmony_ci    ReleaseAllConnection();
710d95e75fdSopenharmony_ci    return TELEPHONY_SUCCESS;
711d95e75fdSopenharmony_ci}
712d95e75fdSopenharmony_ci} // namespace Telephony
713d95e75fdSopenharmony_ci} // namespace OHOS
714