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 "ims_control.h"
17d95e75fdSopenharmony_ci
18d95e75fdSopenharmony_ci#include "cellular_call_hisysevent.h"
19d95e75fdSopenharmony_ci#include "cellular_call_register.h"
20d95e75fdSopenharmony_ci#include "emergency_utils.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_ciIMSControl::~IMSControl()
28d95e75fdSopenharmony_ci{
29d95e75fdSopenharmony_ci    TELEPHONY_LOGI("~IMSControl start");
30d95e75fdSopenharmony_ci    ReleaseAllConnection();
31d95e75fdSopenharmony_ci}
32d95e75fdSopenharmony_ci
33d95e75fdSopenharmony_ciint32_t IMSControl::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    ModuleServiceUtils moduleServiceUtils;
43d95e75fdSopenharmony_ci    RegServiceState regState = moduleServiceUtils.GetPsRegState(callInfo.slotId);
44d95e75fdSopenharmony_ci    if (!(regState == RegServiceState::REG_STATE_IN_SERVICE || isEcc)) {
45d95e75fdSopenharmony_ci        TELEPHONY_LOGE("can not dial.");
46d95e75fdSopenharmony_ci        return TELEPHONY_ERR_NETWORK_NOT_IN_SERVICE;
47d95e75fdSopenharmony_ci    }
48d95e75fdSopenharmony_ci    // sip uri needs to remove separator
49d95e75fdSopenharmony_ci    std::string newPhoneNum(callInfo.phoneNum);
50d95e75fdSopenharmony_ci    StandardizeUtils standardizeUtils;
51d95e75fdSopenharmony_ci    if (newPhoneNum.find('@') != std::string::npos || newPhoneNum.find("%40") != std::string::npos) {
52d95e75fdSopenharmony_ci        newPhoneNum = standardizeUtils.RemoveSeparatorsPhoneNumber(newPhoneNum);
53d95e75fdSopenharmony_ci    }
54d95e75fdSopenharmony_ci
55d95e75fdSopenharmony_ci    CLIRMode clirMode = CLIRMode::DEFAULT;
56d95e75fdSopenharmony_ci    if (IsNeedExecuteMMI(callInfo.slotId, newPhoneNum, clirMode, true)) {
57d95e75fdSopenharmony_ci        TELEPHONY_LOGI("Dial return, mmi code type.");
58d95e75fdSopenharmony_ci        return RETURN_TYPE_MMI;
59d95e75fdSopenharmony_ci    }
60d95e75fdSopenharmony_ci    return DialJudgment(callInfo.slotId, newPhoneNum, clirMode, callInfo.videoState);
61d95e75fdSopenharmony_ci}
62d95e75fdSopenharmony_ci
63d95e75fdSopenharmony_ciint32_t IMSControl::DialJudgment(int32_t slotId, const std::string &phoneNum, CLIRMode &clirMode, int32_t videoState)
64d95e75fdSopenharmony_ci{
65d95e75fdSopenharmony_ci    TELEPHONY_LOGI("DialJudgment entry.");
66d95e75fdSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
67d95e75fdSopenharmony_ci    if (!CanCall(connectionMap_)) {
68d95e75fdSopenharmony_ci        TELEPHONY_LOGE("DialJudgment return, error type: call state error.");
69d95e75fdSopenharmony_ci        CellularCallHiSysEvent::WriteDialCallFaultEvent(
70d95e75fdSopenharmony_ci            slotId, INVALID_PARAMETER, videoState, CALL_ERR_CALL_COUNTS_EXCEED_LIMIT, "ims dial call state error");
71d95e75fdSopenharmony_ci        return CALL_ERR_CALL_COUNTS_EXCEED_LIMIT;
72d95e75fdSopenharmony_ci    }
73d95e75fdSopenharmony_ci    pendingPhoneNumber_ = phoneNum;
74d95e75fdSopenharmony_ci    // Calls can be put on hold, recovered, released, added to conversation,
75d95e75fdSopenharmony_ci    // and transferred similarly as defined in 3GPP TS 22.030 [19].
76d95e75fdSopenharmony_ci    for (auto &connection : connectionMap_) {
77d95e75fdSopenharmony_ci        if (connection.second.GetStatus() == TelCallState::CALL_STATUS_ACTIVE &&
78d95e75fdSopenharmony_ci            !connection.second.IsPendingHangup()) {
79d95e75fdSopenharmony_ci            TELEPHONY_LOGI("DialJudgment, have connection in active state.");
80d95e75fdSopenharmony_ci            EmergencyUtils emergencyUtils;
81d95e75fdSopenharmony_ci            bool isEmergency = false;
82d95e75fdSopenharmony_ci            emergencyUtils.IsEmergencyCall(slotId, phoneNum, isEmergency);
83d95e75fdSopenharmony_ci            connection.second.SetHoldToDialInfo(phoneNum, clirMode, videoState, isEmergency);
84d95e75fdSopenharmony_ci            connection.second.SetDialFlag(true);
85d95e75fdSopenharmony_ci            // - a call can be temporarily disconnected from the ME but the connection is retained by the network
86d95e75fdSopenharmony_ci            return connection.second.SwitchCallRequest(slotId);
87d95e75fdSopenharmony_ci        }
88d95e75fdSopenharmony_ci    }
89d95e75fdSopenharmony_ci    return EncapsulateDial(slotId, phoneNum, clirMode, videoState);
90d95e75fdSopenharmony_ci}
91d95e75fdSopenharmony_ci
92d95e75fdSopenharmony_ciint32_t IMSControl::EncapsulateDial(
93d95e75fdSopenharmony_ci    int32_t slotId, const std::string &phoneNum, CLIRMode &clirMode, int32_t videoState) const
94d95e75fdSopenharmony_ci{
95d95e75fdSopenharmony_ci    TELEPHONY_LOGI("EncapsulateDial start");
96d95e75fdSopenharmony_ci
97d95e75fdSopenharmony_ci    ImsDialInfoStruct dialInfo;
98d95e75fdSopenharmony_ci    dialInfo.videoState = videoState;
99d95e75fdSopenharmony_ci    dialInfo.bEmergencyCall = false;
100d95e75fdSopenharmony_ci    EmergencyUtils emergencyUtils;
101d95e75fdSopenharmony_ci    emergencyUtils.IsEmergencyCall(slotId, phoneNum, dialInfo.bEmergencyCall);
102d95e75fdSopenharmony_ci
103d95e75fdSopenharmony_ci    /**
104d95e75fdSopenharmony_ci     * <idx>: integer type;
105d95e75fdSopenharmony_ci     * call identification number as described in 3GPP TS 22.030 [19] subclause 4.5.5.1
106d95e75fdSopenharmony_ci     * this number can be used in +CHLD command operations
107d95e75fdSopenharmony_ci     * <dir>:
108d95e75fdSopenharmony_ci     */
109d95e75fdSopenharmony_ci    dialInfo.phoneNum = phoneNum;
110d95e75fdSopenharmony_ci    /**
111d95e75fdSopenharmony_ci     * <n> (parameter sets the adjustment for outgoing calls):
112d95e75fdSopenharmony_ci     *  0	presentation indicator is used according to the subscription of the CLIR service
113d95e75fdSopenharmony_ci     *  1	CLIR invocation
114d95e75fdSopenharmony_ci     *  2	CLIR suppression
115d95e75fdSopenharmony_ci     */
116d95e75fdSopenharmony_ci    dialInfo.clirMode = clirMode;
117d95e75fdSopenharmony_ci    /**
118d95e75fdSopenharmony_ci     * An example of voice group call service request usage:
119d95e75fdSopenharmony_ci     * ATD*17*753#500; (originate voice group call with the priority level 3)
120d95e75fdSopenharmony_ci     * OK (voice group call setup was successful)
121d95e75fdSopenharmony_ci     */
122d95e75fdSopenharmony_ci
123d95e75fdSopenharmony_ci    CellularCallConnectionIMS cellularCallConnectionIms;
124d95e75fdSopenharmony_ci    return cellularCallConnectionIms.DialRequest(slotId, dialInfo);
125d95e75fdSopenharmony_ci}
126d95e75fdSopenharmony_ci
127d95e75fdSopenharmony_ciint32_t IMSControl::HangUp(const CellularCallInfo &callInfo, CallSupplementType type)
128d95e75fdSopenharmony_ci{
129d95e75fdSopenharmony_ci    TELEPHONY_LOGI("HangUp start");
130d95e75fdSopenharmony_ci    switch (type) {
131d95e75fdSopenharmony_ci        case CallSupplementType::TYPE_DEFAULT: {
132d95e75fdSopenharmony_ci            std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
133d95e75fdSopenharmony_ci            auto pConnection = FindConnectionByIndex<ImsConnectionMap &, CellularCallConnectionIMS *>(
134d95e75fdSopenharmony_ci                connectionMap_, callInfo.index);
135d95e75fdSopenharmony_ci            if (pConnection == nullptr) {
136d95e75fdSopenharmony_ci                TELEPHONY_LOGE("HangUp return, error type: connection is null");
137d95e75fdSopenharmony_ci                return CALL_ERR_CALL_CONNECTION_NOT_EXIST;
138d95e75fdSopenharmony_ci            }
139d95e75fdSopenharmony_ci            pConnection->SetHangupFlag(true);
140d95e75fdSopenharmony_ci            if (DelayedSingleton<CellularCallRegister>::GetInstance() != nullptr) {
141d95e75fdSopenharmony_ci                DelayedSingleton<CellularCallRegister>::GetInstance()->ReportSingleCallInfo(
142d95e75fdSopenharmony_ci                    pConnection->GetCallReportInfo(), TelCallState::CALL_STATUS_DISCONNECTING);
143d95e75fdSopenharmony_ci            }
144d95e75fdSopenharmony_ci            return pConnection->HangUpRequest(callInfo.slotId, callInfo.phoneNum, callInfo.index);
145d95e75fdSopenharmony_ci        }
146d95e75fdSopenharmony_ci        case CallSupplementType::TYPE_HANG_UP_HOLD_WAIT:
147d95e75fdSopenharmony_ci            // release the second (active) call and recover the first (held) call
148d95e75fdSopenharmony_ci        case CallSupplementType::TYPE_HANG_UP_ACTIVE: {
149d95e75fdSopenharmony_ci            CellularCallConnectionIMS connection;
150d95e75fdSopenharmony_ci            return connection.CallSupplementRequest(callInfo.slotId, type);
151d95e75fdSopenharmony_ci        }
152d95e75fdSopenharmony_ci        case CallSupplementType::TYPE_HANG_UP_ALL: {
153d95e75fdSopenharmony_ci            TELEPHONY_LOGI("HangUp, hang up all call");
154d95e75fdSopenharmony_ci            CellularCallConnectionIMS connection;
155d95e75fdSopenharmony_ci            // The AT command for hanging up all calls is the same as the AT command for rejecting calls,
156d95e75fdSopenharmony_ci            // so the reject interface is reused.
157d95e75fdSopenharmony_ci            return connection.RejectRequest(callInfo.slotId, callInfo.phoneNum, callInfo.index);
158d95e75fdSopenharmony_ci        }
159d95e75fdSopenharmony_ci        default: {
160d95e75fdSopenharmony_ci            TELEPHONY_LOGE("HangUp warring, type is invalid");
161d95e75fdSopenharmony_ci            return TELEPHONY_ERR_ARGUMENT_INVALID;
162d95e75fdSopenharmony_ci        }
163d95e75fdSopenharmony_ci    }
164d95e75fdSopenharmony_ci}
165d95e75fdSopenharmony_ci
166d95e75fdSopenharmony_ciint32_t IMSControl::Answer(const CellularCallInfo &callInfo)
167d95e75fdSopenharmony_ci{
168d95e75fdSopenharmony_ci    TELEPHONY_LOGI("IMSControl::Answer start");
169d95e75fdSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
170d95e75fdSopenharmony_ci    auto pConnection = FindConnectionByIndex<ImsConnectionMap &, CellularCallConnectionIMS *>(
171d95e75fdSopenharmony_ci        connectionMap_, callInfo.index);
172d95e75fdSopenharmony_ci    if (pConnection == nullptr) {
173d95e75fdSopenharmony_ci        TELEPHONY_LOGE("HangUp return, error type: connection is null");
174d95e75fdSopenharmony_ci        return CALL_ERR_CALL_CONNECTION_NOT_EXIST;
175d95e75fdSopenharmony_ci    }
176d95e75fdSopenharmony_ci    if (IsInState(connectionMap_, TelCallState::CALL_STATUS_HOLDING) &&
177d95e75fdSopenharmony_ci        IsInState(connectionMap_, TelCallState::CALL_STATUS_ACTIVE)) {
178d95e75fdSopenharmony_ci        TELEPHONY_LOGD("already threeway mode. hangup holding call and pickup new call");
179d95e75fdSopenharmony_ci        int32_t ret = CheckAndHangupHoldingCall();
180d95e75fdSopenharmony_ci        if (ret != TELEPHONY_SUCCESS) {
181d95e75fdSopenharmony_ci            TELEPHONY_LOGE("hangup holding call failed");
182d95e75fdSopenharmony_ci            return ret;
183d95e75fdSopenharmony_ci        }
184d95e75fdSopenharmony_ci    }
185d95e75fdSopenharmony_ci    auto con = FindConnectionByState<ImsConnectionMap &, CellularCallConnectionIMS *>(
186d95e75fdSopenharmony_ci        connectionMap_, TelCallState::CALL_STATUS_ACTIVE);
187d95e75fdSopenharmony_ci    if (con != nullptr && !con->IsPendingHold() &&
188d95e75fdSopenharmony_ci        pConnection->GetStatus() == TelCallState::CALL_STATUS_WAITING) {
189d95e75fdSopenharmony_ci        TELEPHONY_LOGI("Answer there is an active call when you call, or third party call waiting");
190d95e75fdSopenharmony_ci        return con->SwitchCallRequest(callInfo.slotId);
191d95e75fdSopenharmony_ci    }
192d95e75fdSopenharmony_ci    if (pConnection->GetStatus() == TelCallState::CALL_STATUS_ALERTING ||
193d95e75fdSopenharmony_ci        pConnection->GetStatus() == TelCallState::CALL_STATUS_INCOMING ||
194d95e75fdSopenharmony_ci        pConnection->GetStatus() == TelCallState::CALL_STATUS_WAITING) {
195d95e75fdSopenharmony_ci        return pConnection->AnswerRequest(callInfo.slotId, callInfo.phoneNum, callInfo.videoState, callInfo.index);
196d95e75fdSopenharmony_ci    }
197d95e75fdSopenharmony_ci    TELEPHONY_LOGE("IMSControl::Answer return, error type: call state error, phone not ringing.");
198d95e75fdSopenharmony_ci    return CALL_ERR_CALL_STATE;
199d95e75fdSopenharmony_ci}
200d95e75fdSopenharmony_ci
201d95e75fdSopenharmony_ciint32_t IMSControl::CheckAndHangupHoldingCall()
202d95e75fdSopenharmony_ci{
203d95e75fdSopenharmony_ci    for (auto &it : connectionMap_) {
204d95e75fdSopenharmony_ci        CellularCallConnectionIMS holdConn = it.second;
205d95e75fdSopenharmony_ci        if (holdConn.GetStatus() == TelCallState::CALL_STATUS_HOLDING) {
206d95e75fdSopenharmony_ci            auto callReportInfo = holdConn.GetCallReportInfo();
207d95e75fdSopenharmony_ci            int32_t result = holdConn.HangUpRequest(callReportInfo.accountId,
208d95e75fdSopenharmony_ci                callReportInfo.accountNum, callReportInfo.index);
209d95e75fdSopenharmony_ci            if (result != TELEPHONY_SUCCESS) {
210d95e75fdSopenharmony_ci                return result;
211d95e75fdSopenharmony_ci            }
212d95e75fdSopenharmony_ci        }
213d95e75fdSopenharmony_ci    }
214d95e75fdSopenharmony_ci    return TELEPHONY_SUCCESS;
215d95e75fdSopenharmony_ci}
216d95e75fdSopenharmony_ci
217d95e75fdSopenharmony_ciint32_t IMSControl::Reject(const CellularCallInfo &callInfo)
218d95e75fdSopenharmony_ci{
219d95e75fdSopenharmony_ci    TELEPHONY_LOGI("IMSControl::Reject start");
220d95e75fdSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
221d95e75fdSopenharmony_ci    auto pConnection =
222d95e75fdSopenharmony_ci        FindConnectionByIndex<ImsConnectionMap &, CellularCallConnectionIMS *>(connectionMap_, callInfo.index);
223d95e75fdSopenharmony_ci    if (pConnection == nullptr) {
224d95e75fdSopenharmony_ci        TELEPHONY_LOGE("IMSControl::Reject, error type: connection is null");
225d95e75fdSopenharmony_ci        return CALL_ERR_CALL_CONNECTION_NOT_EXIST;
226d95e75fdSopenharmony_ci    }
227d95e75fdSopenharmony_ci    if (!pConnection->IsRingingState()) {
228d95e75fdSopenharmony_ci        TELEPHONY_LOGE("IMSControl::Reject return, error type: call state error, phone not ringing.");
229d95e75fdSopenharmony_ci        return CALL_ERR_CALL_STATE;
230d95e75fdSopenharmony_ci    }
231d95e75fdSopenharmony_ci    if (DelayedSingleton<CellularCallRegister>::GetInstance() != nullptr) {
232d95e75fdSopenharmony_ci        DelayedSingleton<CellularCallRegister>::GetInstance()->ReportSingleCallInfo(
233d95e75fdSopenharmony_ci            pConnection->GetCallReportInfo(), TelCallState::CALL_STATUS_DISCONNECTING);
234d95e75fdSopenharmony_ci    }
235d95e75fdSopenharmony_ci    return pConnection->RejectRequest(callInfo.slotId, callInfo.phoneNum, callInfo.index);
236d95e75fdSopenharmony_ci}
237d95e75fdSopenharmony_ci
238d95e75fdSopenharmony_ciint32_t IMSControl::HoldCall(int32_t slotId)
239d95e75fdSopenharmony_ci{
240d95e75fdSopenharmony_ci    TELEPHONY_LOGI("HoldCall start");
241d95e75fdSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
242d95e75fdSopenharmony_ci    if (IsInState(connectionMap_, TelCallState::CALL_STATUS_INCOMING)) {
243d95e75fdSopenharmony_ci        TELEPHONY_LOGE("HoldCall return, error type: call state error.");
244d95e75fdSopenharmony_ci        return CALL_ERR_CALL_STATE;
245d95e75fdSopenharmony_ci    }
246d95e75fdSopenharmony_ci    CellularCallConnectionIMS cellularCallConnectionIms;
247d95e75fdSopenharmony_ci    return cellularCallConnectionIms.HoldCallRequest(slotId);
248d95e75fdSopenharmony_ci}
249d95e75fdSopenharmony_ci
250d95e75fdSopenharmony_ciint32_t IMSControl::UnHoldCall(int32_t slotId)
251d95e75fdSopenharmony_ci{
252d95e75fdSopenharmony_ci    TELEPHONY_LOGI("UnHoldCall start");
253d95e75fdSopenharmony_ci    CellularCallConnectionIMS cellularCallConnectionIms;
254d95e75fdSopenharmony_ci    return cellularCallConnectionIms.UnHoldCallRequest(slotId);
255d95e75fdSopenharmony_ci}
256d95e75fdSopenharmony_ci
257d95e75fdSopenharmony_ciint32_t IMSControl::SwitchCall(int32_t slotId)
258d95e75fdSopenharmony_ci{
259d95e75fdSopenharmony_ci    TELEPHONY_LOGI("SwitchCall start");
260d95e75fdSopenharmony_ci    CellularCallConnectionIMS cellularCallConnectionIms;
261d95e75fdSopenharmony_ci    return cellularCallConnectionIms.SwitchCallRequest(slotId);
262d95e75fdSopenharmony_ci}
263d95e75fdSopenharmony_ci
264d95e75fdSopenharmony_ci/**
265d95e75fdSopenharmony_ci * Add another remote party, to which a private communication has been established using
266d95e75fdSopenharmony_ci * the same procedures as in Section 1.3.8.1, if the number of remote parties does not then
267d95e75fdSopenharmony_ci * exceed the maximum number allowed, which results in an active multiParty call.
268d95e75fdSopenharmony_ci */
269d95e75fdSopenharmony_ciint32_t IMSControl::CombineConference(int32_t slotId)
270d95e75fdSopenharmony_ci{
271d95e75fdSopenharmony_ci    TELEPHONY_LOGI("CombineConference entry");
272d95e75fdSopenharmony_ci    CellularCallConnectionIMS connection;
273d95e75fdSopenharmony_ci    int32_t voiceCall = 0;
274d95e75fdSopenharmony_ci    return connection.CombineConferenceRequest(slotId, voiceCall);
275d95e75fdSopenharmony_ci}
276d95e75fdSopenharmony_ci
277d95e75fdSopenharmony_ciint32_t IMSControl::HangUpAllConnection(int32_t slotId)
278d95e75fdSopenharmony_ci{
279d95e75fdSopenharmony_ci    TELEPHONY_LOGI("HangUpAllConnection entry");
280d95e75fdSopenharmony_ci    CellularCallConnectionIMS connection;
281d95e75fdSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
282d95e75fdSopenharmony_ci    if (connectionMap_.empty()) {
283d95e75fdSopenharmony_ci        TELEPHONY_LOGI("connectionMap_ is empty.");
284d95e75fdSopenharmony_ci        return TELEPHONY_ERROR;
285d95e75fdSopenharmony_ci    }
286d95e75fdSopenharmony_ci    for (auto &it : connectionMap_) {
287d95e75fdSopenharmony_ci        int32_t index = it.second.GetIndex();
288d95e75fdSopenharmony_ci        std::string number = it.second.GetNumber();
289d95e75fdSopenharmony_ci        connection.RejectRequest(slotId, number, index);
290d95e75fdSopenharmony_ci    }
291d95e75fdSopenharmony_ci    // The AT command for hanging up all calls is the same as the AT command for rejecting calls,
292d95e75fdSopenharmony_ci    // so the reject interface is reused.
293d95e75fdSopenharmony_ci    return TELEPHONY_SUCCESS;
294d95e75fdSopenharmony_ci}
295d95e75fdSopenharmony_ci
296d95e75fdSopenharmony_ciint32_t IMSControl::InviteToConference(int32_t slotId, const std::vector<std::string> &numberList)
297d95e75fdSopenharmony_ci{
298d95e75fdSopenharmony_ci    TELEPHONY_LOGI("InviteToConference entry");
299d95e75fdSopenharmony_ci    CellularCallConnectionIMS connection;
300d95e75fdSopenharmony_ci    return connection.InviteToConferenceRequest(slotId, numberList);
301d95e75fdSopenharmony_ci}
302d95e75fdSopenharmony_ci
303d95e75fdSopenharmony_ciint32_t IMSControl::KickOutFromConference(int32_t slotId, const std::string &KickOutString, int32_t index)
304d95e75fdSopenharmony_ci{
305d95e75fdSopenharmony_ci    TELEPHONY_LOGI("KickOutFromConference entry");
306d95e75fdSopenharmony_ci    if (KickOutString.empty()) {
307d95e75fdSopenharmony_ci        TELEPHONY_LOGW("KickOutFromConference, splitString is empty.");
308d95e75fdSopenharmony_ci    }
309d95e75fdSopenharmony_ci
310d95e75fdSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
311d95e75fdSopenharmony_ci    auto pConnection = FindConnectionByIndex<ImsConnectionMap &, CellularCallConnectionIMS *>(connectionMap_, index);
312d95e75fdSopenharmony_ci    if (pConnection != nullptr) {
313d95e75fdSopenharmony_ci        return pConnection->KickOutFromConferenceRequest(slotId, pConnection->GetIndex());
314d95e75fdSopenharmony_ci    }
315d95e75fdSopenharmony_ci
316d95e75fdSopenharmony_ci    TELEPHONY_LOGI("KickOutFromConference: connection cannot be matched, use index directly");
317d95e75fdSopenharmony_ci    CellularCallConnectionIMS connection;
318d95e75fdSopenharmony_ci    return connection.KickOutFromConferenceRequest(slotId, index);
319d95e75fdSopenharmony_ci}
320d95e75fdSopenharmony_ci
321d95e75fdSopenharmony_ciint32_t IMSControl::StartRtt(int32_t slotId, const std::string &msg)
322d95e75fdSopenharmony_ci{
323d95e75fdSopenharmony_ci    TELEPHONY_LOGI("StartRtt entry");
324d95e75fdSopenharmony_ci    CellularCallConnectionIMS connection;
325d95e75fdSopenharmony_ci    return connection.StartRttRequest(slotId, msg);
326d95e75fdSopenharmony_ci}
327d95e75fdSopenharmony_ci
328d95e75fdSopenharmony_ciint32_t IMSControl::StopRtt(int32_t slotId)
329d95e75fdSopenharmony_ci{
330d95e75fdSopenharmony_ci    TELEPHONY_LOGI("StopRtt entry");
331d95e75fdSopenharmony_ci    CellularCallConnectionIMS connection;
332d95e75fdSopenharmony_ci    return connection.StopRttRequest(slotId);
333d95e75fdSopenharmony_ci}
334d95e75fdSopenharmony_ci
335d95e75fdSopenharmony_civoid IMSControl::ReleaseAllConnection()
336d95e75fdSopenharmony_ci{
337d95e75fdSopenharmony_ci    TELEPHONY_LOGI("ReleaseAllConnection entry");
338d95e75fdSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
339d95e75fdSopenharmony_ci    connectionMap_.clear();
340d95e75fdSopenharmony_ci}
341d95e75fdSopenharmony_ci
342d95e75fdSopenharmony_ciImsConnectionMap IMSControl::GetConnectionMap()
343d95e75fdSopenharmony_ci{
344d95e75fdSopenharmony_ci    TELEPHONY_LOGI("GetConnectionMap entry");
345d95e75fdSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
346d95e75fdSopenharmony_ci    return connectionMap_;
347d95e75fdSopenharmony_ci}
348d95e75fdSopenharmony_ci
349d95e75fdSopenharmony_ciint32_t IMSControl::ReportImsCallsData(int32_t slotId, const ImsCurrentCallList &callInfoList)
350d95e75fdSopenharmony_ci{
351d95e75fdSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
352d95e75fdSopenharmony_ci    if (callInfoList.callSize <= 0) {
353d95e75fdSopenharmony_ci        return ReportHangUpInfo(slotId);
354d95e75fdSopenharmony_ci    } else if (callInfoList.callSize > 0 && connectionMap_.empty()) {
355d95e75fdSopenharmony_ci        return ReportIncomingInfo(slotId, callInfoList);
356d95e75fdSopenharmony_ci    } else if (callInfoList.callSize > 0 && !connectionMap_.empty()) {
357d95e75fdSopenharmony_ci        return ReportUpdateInfo(slotId, callInfoList);
358d95e75fdSopenharmony_ci    }
359d95e75fdSopenharmony_ci    return TELEPHONY_ERROR;
360d95e75fdSopenharmony_ci}
361d95e75fdSopenharmony_ci
362d95e75fdSopenharmony_ciint32_t IMSControl::ReportCallsData(int32_t slotId, const CallInfoList &callInfoList)
363d95e75fdSopenharmony_ci{
364d95e75fdSopenharmony_ci    return TELEPHONY_ERROR;
365d95e75fdSopenharmony_ci}
366d95e75fdSopenharmony_ci
367d95e75fdSopenharmony_ciint32_t IMSControl::ReportHangUpInfo(int32_t slotId)
368d95e75fdSopenharmony_ci{
369d95e75fdSopenharmony_ci    TELEPHONY_LOGI("ReportHangUpInfo entry");
370d95e75fdSopenharmony_ci    CallsReportInfo callsReportInfo;
371d95e75fdSopenharmony_ci    for (auto &it : connectionMap_) {
372d95e75fdSopenharmony_ci        CallReportInfo reportInfo = it.second.GetCallReportInfo();
373d95e75fdSopenharmony_ci        reportInfo.state = TelCallState::CALL_STATUS_DISCONNECTED;
374d95e75fdSopenharmony_ci        reportInfo.accountId = slotId;
375d95e75fdSopenharmony_ci        callsReportInfo.callVec.push_back(reportInfo);
376d95e75fdSopenharmony_ci        GetCallFailReason(slotId, connectionMap_);
377d95e75fdSopenharmony_ci    }
378d95e75fdSopenharmony_ci    if (connectionMap_.empty()) {
379d95e75fdSopenharmony_ci        TELEPHONY_LOGI("connectionMap_ is empty");
380d95e75fdSopenharmony_ci        CallReportInfo reportInfo;
381d95e75fdSopenharmony_ci        reportInfo.state = TelCallState::CALL_STATUS_DISCONNECTED;
382d95e75fdSopenharmony_ci        reportInfo.accountId = slotId;
383d95e75fdSopenharmony_ci        callsReportInfo.callVec.push_back(reportInfo);
384d95e75fdSopenharmony_ci    }
385d95e75fdSopenharmony_ci    if (DelayedSingleton<CellularCallRegister>::GetInstance() == nullptr) {
386d95e75fdSopenharmony_ci        TELEPHONY_LOGE("ReportHangUpInfo return, GetInstance() is nullptr.");
387d95e75fdSopenharmony_ci        return TELEPHONY_ERR_LOCAL_PTR_NULL;
388d95e75fdSopenharmony_ci    }
389d95e75fdSopenharmony_ci    callsReportInfo.slotId = slotId;
390d95e75fdSopenharmony_ci    if (isIgnoredIncomingCall_) {
391d95e75fdSopenharmony_ci        isIgnoredIncomingCall_ = false;
392d95e75fdSopenharmony_ci    } else {
393d95e75fdSopenharmony_ci        DelayedSingleton<CellularCallRegister>::GetInstance()->ReportCallsInfo(callsReportInfo);
394d95e75fdSopenharmony_ci    }
395d95e75fdSopenharmony_ci    ReleaseAllConnection();
396d95e75fdSopenharmony_ci    return TELEPHONY_SUCCESS;
397d95e75fdSopenharmony_ci}
398d95e75fdSopenharmony_ci
399d95e75fdSopenharmony_ciint32_t IMSControl::ReportIncomingInfo(int32_t slotId, const ImsCurrentCallList &imsCurrentCallInfoList)
400d95e75fdSopenharmony_ci{
401d95e75fdSopenharmony_ci    TELEPHONY_LOGI("ReportIncomingInfo entry");
402d95e75fdSopenharmony_ci    CallsReportInfo callsReportInfo;
403d95e75fdSopenharmony_ci    for (int32_t i = 0; i < imsCurrentCallInfoList.callSize; ++i) {
404d95e75fdSopenharmony_ci        CallReportInfo reportInfo = EncapsulationCallReportInfo(slotId, imsCurrentCallInfoList.calls[i]);
405d95e75fdSopenharmony_ci
406d95e75fdSopenharmony_ci        CellularCallConnectionIMS connection;
407d95e75fdSopenharmony_ci        connection.SetStatus(static_cast<TelCallState>(imsCurrentCallInfoList.calls[i].state));
408d95e75fdSopenharmony_ci        connection.SetIndex(imsCurrentCallInfoList.calls[i].index);
409d95e75fdSopenharmony_ci        connection.SetNumber(imsCurrentCallInfoList.calls[i].number);
410d95e75fdSopenharmony_ci        connection.SetOrUpdateCallReportInfo(reportInfo);
411d95e75fdSopenharmony_ci        SetConnectionData(connectionMap_, imsCurrentCallInfoList.calls[i].index, connection);
412d95e75fdSopenharmony_ci
413d95e75fdSopenharmony_ci        callsReportInfo.callVec.push_back(reportInfo);
414d95e75fdSopenharmony_ci    }
415d95e75fdSopenharmony_ci    if (DelayedSingleton<CellularCallRegister>::GetInstance() == nullptr) {
416d95e75fdSopenharmony_ci        TELEPHONY_LOGE("ReportIncomingInfo return, GetInstance() is nullptr.");
417d95e75fdSopenharmony_ci        return TELEPHONY_ERR_ARGUMENT_INVALID;
418d95e75fdSopenharmony_ci    }
419d95e75fdSopenharmony_ci    callsReportInfo.slotId = slotId;
420d95e75fdSopenharmony_ci    if (!DelayedSingleton<CellularCallRegister>::GetInstance()->IsCallManagerCallBackRegistered() &&
421d95e75fdSopenharmony_ci        callsReportInfo.callVec.size() != 0 && callsReportInfo.callVec[0].state == TelCallState::CALL_STATUS_INCOMING) {
422d95e75fdSopenharmony_ci        isIgnoredIncomingCall_ = true;
423d95e75fdSopenharmony_ci    } else {
424d95e75fdSopenharmony_ci        DelayedSingleton<CellularCallRegister>::GetInstance()->ReportCallsInfo(callsReportInfo);
425d95e75fdSopenharmony_ci    }
426d95e75fdSopenharmony_ci    return TELEPHONY_SUCCESS;
427d95e75fdSopenharmony_ci}
428d95e75fdSopenharmony_ci
429d95e75fdSopenharmony_ciint32_t IMSControl::ReportUpdateInfo(int32_t slotId, const ImsCurrentCallList &callInfoList)
430d95e75fdSopenharmony_ci{
431d95e75fdSopenharmony_ci    TELEPHONY_LOGD("ReportUpdateInfo entry");
432d95e75fdSopenharmony_ci    CallsReportInfo callsReportInfo;
433d95e75fdSopenharmony_ci    for (int32_t i = 0; i < callInfoList.callSize; ++i) {
434d95e75fdSopenharmony_ci        CallReportInfo reportInfo = EncapsulationCallReportInfo(slotId, callInfoList.calls[i]);
435d95e75fdSopenharmony_ci        if (callInfoList.callSize == 1 && reportInfo.state == TelCallState::CALL_STATUS_WAITING) {
436d95e75fdSopenharmony_ci            TELEPHONY_LOGI("only one call, report incoming state instead of waiting state");
437d95e75fdSopenharmony_ci            reportInfo.state = TelCallState::CALL_STATUS_INCOMING;
438d95e75fdSopenharmony_ci        }
439d95e75fdSopenharmony_ci        auto pConnection = FindConnectionByIndex<ImsConnectionMap &, CellularCallConnectionIMS *>(
440d95e75fdSopenharmony_ci            connectionMap_, callInfoList.calls[i].index);
441d95e75fdSopenharmony_ci        if (pConnection == nullptr) {
442d95e75fdSopenharmony_ci            CellularCallConnectionIMS connection;
443d95e75fdSopenharmony_ci            connection.SetOrUpdateCallReportInfo(reportInfo);
444d95e75fdSopenharmony_ci            connection.SetFlag(true);
445d95e75fdSopenharmony_ci            connection.SetIndex(callInfoList.calls[i].index);
446d95e75fdSopenharmony_ci            connection.SetNumber(callInfoList.calls[i].number);
447d95e75fdSopenharmony_ci            SetConnectionData(connectionMap_, callInfoList.calls[i].index, connection);
448d95e75fdSopenharmony_ci        } else {
449d95e75fdSopenharmony_ci            TelCallState preCallState = pConnection->GetStatus();
450d95e75fdSopenharmony_ci            pConnection->SetFlag(true);
451d95e75fdSopenharmony_ci            pConnection->SetIndex(callInfoList.calls[i].index);
452d95e75fdSopenharmony_ci            pConnection->SetNumber(callInfoList.calls[i].number);
453d95e75fdSopenharmony_ci            pConnection->SetOrUpdateCallReportInfo(reportInfo);
454d95e75fdSopenharmony_ci            TelCallState curCallState = pConnection->GetStatus();
455d95e75fdSopenharmony_ci            if (IsConnectedOut(preCallState, curCallState)) {
456d95e75fdSopenharmony_ci                pConnection->UpdateCallNumber(pendingPhoneNumber_);
457d95e75fdSopenharmony_ci                pendingPhoneNumber_.clear();
458d95e75fdSopenharmony_ci                ExecutePostDial(slotId, pConnection->GetIndex());
459d95e75fdSopenharmony_ci            }
460d95e75fdSopenharmony_ci        }
461d95e75fdSopenharmony_ci        callsReportInfo.callVec.push_back(reportInfo);
462d95e75fdSopenharmony_ci    }
463d95e75fdSopenharmony_ci    callsReportInfo.slotId = slotId;
464d95e75fdSopenharmony_ci    DeleteConnection(callsReportInfo, callInfoList);
465d95e75fdSopenharmony_ci    if (DelayedSingleton<CellularCallRegister>::GetInstance() == nullptr) {
466d95e75fdSopenharmony_ci        TELEPHONY_LOGE("ReportUpdateInfo return, GetInstance() is nullptr.");
467d95e75fdSopenharmony_ci        return TELEPHONY_ERR_LOCAL_PTR_NULL;
468d95e75fdSopenharmony_ci    }
469d95e75fdSopenharmony_ci    if (isIgnoredIncomingCall_) {
470d95e75fdSopenharmony_ci        isIgnoredIncomingCall_ = false;
471d95e75fdSopenharmony_ci    } else {
472d95e75fdSopenharmony_ci        DelayedSingleton<CellularCallRegister>::GetInstance()->ReportCallsInfo(callsReportInfo);
473d95e75fdSopenharmony_ci    }
474d95e75fdSopenharmony_ci    return TELEPHONY_SUCCESS;
475d95e75fdSopenharmony_ci}
476d95e75fdSopenharmony_ci
477d95e75fdSopenharmony_ciCallReportInfo IMSControl::EncapsulationCallReportInfo(int32_t slotId, const ImsCurrentCall &callInfo)
478d95e75fdSopenharmony_ci{
479d95e75fdSopenharmony_ci    TELEPHONY_LOGD("EncapsulationCallReportInfo entry");
480d95e75fdSopenharmony_ci    CallReportInfo callReportInfo;
481d95e75fdSopenharmony_ci    if (memset_s(&callReportInfo, sizeof(callReportInfo), 0, sizeof(callReportInfo)) != EOK) {
482d95e75fdSopenharmony_ci        TELEPHONY_LOGE("EncapsulationCallReportInfo return, memset_s fail.");
483d95e75fdSopenharmony_ci        return callReportInfo;
484d95e75fdSopenharmony_ci    }
485d95e75fdSopenharmony_ci
486d95e75fdSopenharmony_ci    StandardizeUtils standardizeUtils;
487d95e75fdSopenharmony_ci    std::string phoneNumber = callInfo.number.empty() ? callInfo.name : callInfo.number;
488d95e75fdSopenharmony_ci    std::string newString = standardizeUtils.FormatNumberAndToa(phoneNumber, callInfo.toa);
489d95e75fdSopenharmony_ci    size_t cpyLen = strlen(newString.c_str()) + 1;
490d95e75fdSopenharmony_ci    if (cpyLen > static_cast<size_t>(kMaxNumberLen + 1)) {
491d95e75fdSopenharmony_ci        TELEPHONY_LOGE("EncapsulationCallReportInfo return, strcpy_s fail.");
492d95e75fdSopenharmony_ci        return callReportInfo;
493d95e75fdSopenharmony_ci    }
494d95e75fdSopenharmony_ci    if (strcpy_s(callReportInfo.accountNum, cpyLen, newString.c_str()) != EOK) {
495d95e75fdSopenharmony_ci        TELEPHONY_LOGE("EncapsulationCallReportInfo return, strcpy_s fail.");
496d95e75fdSopenharmony_ci        return callReportInfo;
497d95e75fdSopenharmony_ci    }
498d95e75fdSopenharmony_ci    callReportInfo.index = callInfo.index;
499d95e75fdSopenharmony_ci    callReportInfo.accountId = slotId;
500d95e75fdSopenharmony_ci    callReportInfo.state = static_cast<TelCallState>(callInfo.state);
501d95e75fdSopenharmony_ci    callReportInfo.voiceDomain = callInfo.voiceDomain;
502d95e75fdSopenharmony_ci    callReportInfo.callType = CallType::TYPE_IMS;
503d95e75fdSopenharmony_ci    switch (callInfo.callType) {
504d95e75fdSopenharmony_ci        case ImsCallType::TEL_IMS_CALL_TYPE_VOICE:
505d95e75fdSopenharmony_ci            callReportInfo.callMode = VideoStateType::TYPE_VOICE;
506d95e75fdSopenharmony_ci            break;
507d95e75fdSopenharmony_ci        case ImsCallType::TEL_IMS_CALL_TYPE_VT_TX:
508d95e75fdSopenharmony_ci            callReportInfo.callMode = VideoStateType::TYPE_SEND_ONLY;
509d95e75fdSopenharmony_ci            break;
510d95e75fdSopenharmony_ci        case ImsCallType::TEL_IMS_CALL_TYPE_VT_RX:
511d95e75fdSopenharmony_ci            callReportInfo.callMode = VideoStateType::TYPE_RECEIVE_ONLY;
512d95e75fdSopenharmony_ci            break;
513d95e75fdSopenharmony_ci        case ImsCallType::TEL_IMS_CALL_TYPE_VT:
514d95e75fdSopenharmony_ci            callReportInfo.callMode = VideoStateType::TYPE_VIDEO;
515d95e75fdSopenharmony_ci            break;
516d95e75fdSopenharmony_ci        default:
517d95e75fdSopenharmony_ci            callReportInfo.callMode = VideoStateType::TYPE_VOICE;
518d95e75fdSopenharmony_ci            break;
519d95e75fdSopenharmony_ci    }
520d95e75fdSopenharmony_ci    callReportInfo.mpty = callInfo.mpty;
521d95e75fdSopenharmony_ci    callReportInfo.crsType = callInfo.toneType;
522d95e75fdSopenharmony_ci    callReportInfo.originalCallType = callInfo.callInitialType;
523d95e75fdSopenharmony_ci    return callReportInfo;
524d95e75fdSopenharmony_ci}
525d95e75fdSopenharmony_ci
526d95e75fdSopenharmony_civoid IMSControl::DeleteConnection(CallsReportInfo &callsReportInfo, const ImsCurrentCallList &callInfoList)
527d95e75fdSopenharmony_ci{
528d95e75fdSopenharmony_ci    TELEPHONY_LOGI("DeleteConnection entry");
529d95e75fdSopenharmony_ci    auto it = connectionMap_.begin();
530d95e75fdSopenharmony_ci    while (it != connectionMap_.end()) {
531d95e75fdSopenharmony_ci        if (!it->second.GetFlag()) {
532d95e75fdSopenharmony_ci            CallReportInfo callReportInfo = it->second.GetCallReportInfo();
533d95e75fdSopenharmony_ci            callReportInfo.state = TelCallState::CALL_STATUS_DISCONNECTED;
534d95e75fdSopenharmony_ci            callsReportInfo.callVec.push_back(callReportInfo);
535d95e75fdSopenharmony_ci            it = connectionMap_.erase(it);
536d95e75fdSopenharmony_ci            GetCallFailReason(callsReportInfo.slotId, connectionMap_);
537d95e75fdSopenharmony_ci        } else {
538d95e75fdSopenharmony_ci            it->second.SetFlag(false);
539d95e75fdSopenharmony_ci            ++it;
540d95e75fdSopenharmony_ci        }
541d95e75fdSopenharmony_ci    }
542d95e75fdSopenharmony_ci}
543d95e75fdSopenharmony_ci
544d95e75fdSopenharmony_ciint32_t IMSControl::ExecutePostDial(int32_t slotId, int64_t callId)
545d95e75fdSopenharmony_ci{
546d95e75fdSopenharmony_ci    TELEPHONY_LOGI("ExecutePostDial entry");
547d95e75fdSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
548d95e75fdSopenharmony_ci    if (connectionMap_.empty()) {
549d95e75fdSopenharmony_ci        TELEPHONY_LOGE("connectionMap_ is empty.");
550d95e75fdSopenharmony_ci        return TELEPHONY_ERROR;
551d95e75fdSopenharmony_ci    }
552d95e75fdSopenharmony_ci    auto pConnection = FindConnectionByIndex<ImsConnectionMap &, CellularCallConnectionIMS *>(connectionMap_, callId);
553d95e75fdSopenharmony_ci    if (pConnection == nullptr) {
554d95e75fdSopenharmony_ci        return TELEPHONY_ERR_LOCAL_PTR_NULL;
555d95e75fdSopenharmony_ci    }
556d95e75fdSopenharmony_ci    char currentChar;
557d95e75fdSopenharmony_ci    PostDialCallState state = pConnection->ProcessNextChar(slotId, currentChar);
558d95e75fdSopenharmony_ci    switch (state) {
559d95e75fdSopenharmony_ci        case PostDialCallState::POST_DIAL_CALL_STARTED:
560d95e75fdSopenharmony_ci            DelayedSingleton<CellularCallRegister>::GetInstance()->ReportPostDialChar(currentChar);
561d95e75fdSopenharmony_ci            break;
562d95e75fdSopenharmony_ci        case PostDialCallState::POST_DIAL_CALL_DELAY:
563d95e75fdSopenharmony_ci            DelayedSingleton<CellularCallRegister>::GetInstance()->ReportPostDialDelay(
564d95e75fdSopenharmony_ci                pConnection->GetLeftPostDialCallString());
565d95e75fdSopenharmony_ci            break;
566d95e75fdSopenharmony_ci        default:
567d95e75fdSopenharmony_ci            break;
568d95e75fdSopenharmony_ci    }
569d95e75fdSopenharmony_ci    return TELEPHONY_SUCCESS;
570d95e75fdSopenharmony_ci}
571d95e75fdSopenharmony_ci
572d95e75fdSopenharmony_ciint32_t IMSControl::PostDialProceed(const CellularCallInfo &callInfo, const bool proceed)
573d95e75fdSopenharmony_ci{
574d95e75fdSopenharmony_ci    TELEPHONY_LOGI("PostDialProceed entry");
575d95e75fdSopenharmony_ci    std::string networkAddress;
576d95e75fdSopenharmony_ci    std::string postDialString;
577d95e75fdSopenharmony_ci    StandardizeUtils standardizeUtils;
578d95e75fdSopenharmony_ci    standardizeUtils.ExtractAddressAndPostDial(callInfo.phoneNum, networkAddress, postDialString);
579d95e75fdSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
580d95e75fdSopenharmony_ci    auto pConnection = FindConnectionByIndex<ImsConnectionMap &, CellularCallConnectionIMS *>(connectionMap_,
581d95e75fdSopenharmony_ci        callInfo.index);
582d95e75fdSopenharmony_ci    if (pConnection == nullptr) {
583d95e75fdSopenharmony_ci        TELEPHONY_LOGE("ims pConnection is nullptr!");
584d95e75fdSopenharmony_ci        return TELEPHONY_ERR_LOCAL_PTR_NULL;
585d95e75fdSopenharmony_ci    }
586d95e75fdSopenharmony_ci    if (proceed) {
587d95e75fdSopenharmony_ci        ExecutePostDial(callInfo.slotId, pConnection->GetIndex());
588d95e75fdSopenharmony_ci    } else {
589d95e75fdSopenharmony_ci        pConnection->SetPostDialCallState(PostDialCallState::POST_DIAL_CALL_CANCELED);
590d95e75fdSopenharmony_ci    }
591d95e75fdSopenharmony_ci    return TELEPHONY_SUCCESS;
592d95e75fdSopenharmony_ci}
593d95e75fdSopenharmony_ci
594d95e75fdSopenharmony_ciint32_t IMSControl::RestoreConnection(const std::vector<CellularCallInfo> &infos, int32_t slotId)
595d95e75fdSopenharmony_ci{
596d95e75fdSopenharmony_ci    TELEPHONY_LOGI("RestoreConnection entry");
597d95e75fdSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
598d95e75fdSopenharmony_ci    for (auto &info : infos) {
599d95e75fdSopenharmony_ci        if (info.callType == CallType::TYPE_IMS && info.slotId == slotId) {
600d95e75fdSopenharmony_ci            CellularCallConnectionIMS connectionIMS;
601d95e75fdSopenharmony_ci            connectionIMS.SetIndex(info.index);
602d95e75fdSopenharmony_ci            connectionIMS.SetNumber(info.phoneNum);
603d95e75fdSopenharmony_ci            SetConnectionData(connectionMap_, info.index, connectionIMS);
604d95e75fdSopenharmony_ci        }
605d95e75fdSopenharmony_ci    }
606d95e75fdSopenharmony_ci    return TELEPHONY_SUCCESS;
607d95e75fdSopenharmony_ci}
608d95e75fdSopenharmony_ci
609d95e75fdSopenharmony_ciint32_t IMSControl::ReportHangUp(const std::vector<CellularCallInfo> &infos, int32_t slotId)
610d95e75fdSopenharmony_ci{
611d95e75fdSopenharmony_ci    CallsReportInfo callsReportInfo;
612d95e75fdSopenharmony_ci    callsReportInfo.slotId = slotId;
613d95e75fdSopenharmony_ci    for (const auto &info : infos) {
614d95e75fdSopenharmony_ci        if (info.callType == CallType::TYPE_IMS && info.slotId == slotId) {
615d95e75fdSopenharmony_ci            CallReportInfo imsCallReportInfo;
616d95e75fdSopenharmony_ci            if (memset_s(imsCallReportInfo.accountNum, kMaxNumberLen + 1, 0, kMaxNumberLen + 1) != EOK) {
617d95e75fdSopenharmony_ci                TELEPHONY_LOGE("memset_s fail");
618d95e75fdSopenharmony_ci                return TELEPHONY_ERR_MEMSET_FAIL;
619d95e75fdSopenharmony_ci            }
620d95e75fdSopenharmony_ci            if (memcpy_s(imsCallReportInfo.accountNum, kMaxNumberLen, info.phoneNum, kMaxNumberLen) != EOK) {
621d95e75fdSopenharmony_ci                TELEPHONY_LOGE("memcpy_s fail");
622d95e75fdSopenharmony_ci                return TELEPHONY_ERR_MEMCPY_FAIL;
623d95e75fdSopenharmony_ci            }
624d95e75fdSopenharmony_ci            imsCallReportInfo.index = info.index;
625d95e75fdSopenharmony_ci            imsCallReportInfo.accountId = info.slotId;
626d95e75fdSopenharmony_ci            imsCallReportInfo.callType = CallType::TYPE_IMS;
627d95e75fdSopenharmony_ci            imsCallReportInfo.callMode =
628d95e75fdSopenharmony_ci                static_cast<bool>(info.callType) ? VideoStateType::TYPE_VIDEO : VideoStateType::TYPE_VOICE;
629d95e75fdSopenharmony_ci            imsCallReportInfo.state = TelCallState::CALL_STATUS_DISCONNECTED;
630d95e75fdSopenharmony_ci            callsReportInfo.callVec.push_back(imsCallReportInfo);
631d95e75fdSopenharmony_ci        }
632d95e75fdSopenharmony_ci    }
633d95e75fdSopenharmony_ci    if (DelayedSingleton<CellularCallRegister>::GetInstance() == nullptr) {
634d95e75fdSopenharmony_ci        TELEPHONY_LOGE("CellularCallRegister instance is nullptr");
635d95e75fdSopenharmony_ci        return TELEPHONY_ERR_LOCAL_PTR_NULL;
636d95e75fdSopenharmony_ci    }
637d95e75fdSopenharmony_ci    DelayedSingleton<CellularCallRegister>::GetInstance()->ReportCallsInfo(callsReportInfo);
638d95e75fdSopenharmony_ci    return TELEPHONY_SUCCESS;
639d95e75fdSopenharmony_ci}
640d95e75fdSopenharmony_ci
641d95e75fdSopenharmony_civoid IMSControl::DialAfterHold(int32_t slotId)
642d95e75fdSopenharmony_ci{
643d95e75fdSopenharmony_ci    TELEPHONY_LOGI("DialAfterHold entry");
644d95e75fdSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
645d95e75fdSopenharmony_ci    for (auto &connection : connectionMap_) {
646d95e75fdSopenharmony_ci        if (connection.second.IsNeedToDial()) {
647d95e75fdSopenharmony_ci            ImsDialInfoStruct holdToDialInfo = connection.second.GetHoldToDialInfo();
648d95e75fdSopenharmony_ci            CellularCallConnectionIMS cellularCallConnectionIms;
649d95e75fdSopenharmony_ci            cellularCallConnectionIms.DialRequest(slotId, holdToDialInfo);
650d95e75fdSopenharmony_ci            connection.second.SetDialFlag(false);
651d95e75fdSopenharmony_ci            break;
652d95e75fdSopenharmony_ci        }
653d95e75fdSopenharmony_ci    }
654d95e75fdSopenharmony_ci}
655d95e75fdSopenharmony_ci
656d95e75fdSopenharmony_civoid IMSControl::RecoverPendingHold()
657d95e75fdSopenharmony_ci{
658d95e75fdSopenharmony_ci    TELEPHONY_LOGI("RecoverPendingHold entry");
659d95e75fdSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_);
660d95e75fdSopenharmony_ci    for (auto &connection : connectionMap_) {
661d95e75fdSopenharmony_ci        if (connection.second.IsPendingHold()) {
662d95e75fdSopenharmony_ci            connection.second.UpdatePendingHoldFlag(false);
663d95e75fdSopenharmony_ci            break;
664d95e75fdSopenharmony_ci        }
665d95e75fdSopenharmony_ci    }
666d95e75fdSopenharmony_ci}
667d95e75fdSopenharmony_ci} // namespace Telephony
668d95e75fdSopenharmony_ci} // namespace OHOS
669