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