1/* 2 * Copyright (C) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "satellite_control.h" 17 18#include "cellular_call_hisysevent.h" 19#include "cellular_call_register.h" 20#include "module_service_utils.h" 21#include "securec.h" 22#include "standardize_utils.h" 23 24namespace OHOS { 25namespace Telephony { 26 27SatelliteControl::~SatelliteControl() 28{ 29 ReleaseAllConnection(); 30} 31 32int32_t SatelliteControl::Dial(const CellularCallInfo &callInfo, bool isEcc) 33{ 34 TELEPHONY_LOGI("DialSatellite start"); 35 DelayedSingleton<CellularCallHiSysEvent>::GetInstance()->SetCallParameterInfo( 36 callInfo.slotId, static_cast<int32_t>(callInfo.callType), callInfo.videoState); 37 int32_t ret = DialPreJudgment(callInfo, false); 38 if (ret != TELEPHONY_SUCCESS) { 39 return ret; 40 } 41 StandardizeUtils standardizeUtils; 42 // Remove the phone number separator 43 std::string newPhoneNum = standardizeUtils.RemoveSeparatorsPhoneNumber(callInfo.phoneNum); 44 45 CLIRMode clirMode = CLIRMode::DEFAULT; 46 if (IsNeedExecuteMMI(callInfo.slotId, newPhoneNum, clirMode, false)) { 47 TELEPHONY_LOGI("DialSatellite return, mmi code type."); 48 return RETURN_TYPE_MMI; 49 } 50 51 std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_); 52 if (!CanCall(connectionMap_)) { 53 TELEPHONY_LOGE("DialSatellite return, error type: call state error."); 54 CellularCallHiSysEvent::WriteDialCallFaultEvent(callInfo.slotId, static_cast<int32_t>(callInfo.callType), 55 callInfo.videoState, CALL_ERR_CALL_COUNTS_EXCEED_LIMIT, "DSatellite dial call state error"); 56 return CALL_ERR_CALL_COUNTS_EXCEED_LIMIT; 57 } 58 59 return EncapsulateDialCommon(callInfo.slotId, newPhoneNum, clirMode); 60} 61 62int32_t SatelliteControl::EncapsulateDialCommon(int32_t slotId, const std::string &phoneNum, CLIRMode &clirMode) 63{ 64 pendingPhoneNumber_ = phoneNum; 65 DialRequestStruct dialRequest; 66 /** 67 * <idx>: integer type; 68 * call identification number as described in 3GPP TS 22.030 [19] subclause 4.5.5.1 69 * this number can be used in +CHLD command operations 70 * <dir>: 71 */ 72 dialRequest.phoneNum = phoneNum; 73 74 /** 75 * <n> (parameter sets the adjustment for outgoing calls): 76 * 0 presentation indicator is used according to the subscription of the CLIR service 77 * 1 CLIR invocation 78 * 2 CLIR suppression 79 */ 80 dialRequest.clirMode = clirMode; 81 82 /** 83 * An example of voice group call service request usage: 84 * ATD*17*753#500; (originate voice group call with the priority level 3) 85 * OK (voice group call setup was successful) 86 */ 87 CellularCallConnectionSatellite satelliteConnection; 88 return satelliteConnection.DialRequest(slotId, dialRequest); 89} 90 91int32_t SatelliteControl::HangUp(const CellularCallInfo &callInfo, CallSupplementType type) 92{ 93 TELEPHONY_LOGI("HangUp start"); 94 switch (type) { 95 case CallSupplementType::TYPE_DEFAULT: { 96 // Match the session connection according to the phone number string 97 std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_); 98 auto pConnection = FindConnectionByIndex<SatelliteConnectionMap &, CellularCallConnectionSatellite *>( 99 connectionMap_, callInfo.index); 100 if (pConnection == nullptr) { 101 TELEPHONY_LOGE("HangUp, error type: connection is null"); 102 CellularCallHiSysEvent::WriteHangUpFaultEvent( 103 callInfo.slotId, callInfo.callId, CALL_ERR_CALL_CONNECTION_NOT_EXIST, "HangUp pConnection is null"); 104 return CALL_ERR_CALL_CONNECTION_NOT_EXIST; 105 } 106 107 if (DelayedSingleton<CellularCallRegister>::GetInstance() != nullptr) { 108 DelayedSingleton<CellularCallRegister>::GetInstance()->ReportSingleCallInfo( 109 pConnection->GetCallReportInfo(), TelCallState::CALL_STATUS_DISCONNECTING); 110 } 111 return pConnection->HangUpRequest(callInfo.slotId); 112 } 113 default: { 114 TELEPHONY_LOGE("HangUp warring, type is invalid"); 115 CellularCallHiSysEvent::WriteHangUpFaultEvent( 116 callInfo.slotId, callInfo.callId, TELEPHONY_ERR_ARGUMENT_INVALID, "HangUp type is invalid"); 117 return TELEPHONY_ERR_ARGUMENT_INVALID; 118 } 119 } 120} 121 122int32_t SatelliteControl::Answer(const CellularCallInfo &callInfo) 123{ 124 TELEPHONY_LOGI("SatelliteControl::Answer start"); 125 std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_); 126 auto pConnection = FindConnectionByIndex<SatelliteConnectionMap &, CellularCallConnectionSatellite *>( 127 connectionMap_, callInfo.index); 128 if (pConnection == nullptr) { 129 TELEPHONY_LOGE("Answer return, error type: connection is null"); 130 CellularCallHiSysEvent::WriteAnswerCallFaultEvent(callInfo.slotId, callInfo.callId, callInfo.videoState, 131 CALL_ERR_CALL_CONNECTION_NOT_EXIST, "get connection data is null"); 132 return CALL_ERR_CALL_CONNECTION_NOT_EXIST; 133 } 134 // There is an active call when you call, or third party call waiting 135 if (IsInState(connectionMap_, TelCallState::CALL_STATUS_ACTIVE) || 136 pConnection->GetStatus() == TelCallState::CALL_STATUS_WAITING) { 137 TELEPHONY_LOGI("Answer there is an active call when you call, or third party call waiting"); 138 auto con = FindConnectionByState<SatelliteConnectionMap &, CellularCallConnectionSatellite *>( 139 connectionMap_, TelCallState::CALL_STATUS_ACTIVE); 140 if (con != nullptr) { 141 TELEPHONY_LOGI("Answer: There is an active session currently, and it needs to hold"); 142 con->HangUpRequest(callInfo.slotId); 143 } else { 144 TELEPHONY_LOGE("Answer return, error type: con is null, there are no active calls"); 145 } 146 } 147 148 if (pConnection->GetStatus() == TelCallState::CALL_STATUS_INCOMING || 149 pConnection->GetStatus() == TelCallState::CALL_STATUS_ALERTING || 150 pConnection->GetStatus() == TelCallState::CALL_STATUS_WAITING) { 151 return pConnection->AnswerRequest(callInfo.slotId); 152 } 153 154 TELEPHONY_LOGE("SatelliteControl::Answer return, error type: call state error, phone not ringing."); 155 CellularCallHiSysEvent::WriteAnswerCallFaultEvent(callInfo.slotId, callInfo.callId, callInfo.videoState, 156 CALL_ERR_CALL_STATE, "call state error phone not ringing"); 157 return CALL_ERR_CALL_STATE; 158} 159 160int32_t SatelliteControl::Reject(const CellularCallInfo &callInfo) 161{ 162 TELEPHONY_LOGI("SatelliteControl::Reject start"); 163 std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_); 164 auto pConnection = FindConnectionByIndex<SatelliteConnectionMap &, CellularCallConnectionSatellite *>( 165 connectionMap_, callInfo.index); 166 if (pConnection == nullptr) { 167 TELEPHONY_LOGE("SatelliteControl::Reject, error type: connection is null"); 168 CellularCallHiSysEvent::WriteHangUpFaultEvent( 169 callInfo.slotId, callInfo.callId, CALL_ERR_CALL_CONNECTION_NOT_EXIST, "Reject pConnection is null"); 170 return CALL_ERR_CALL_CONNECTION_NOT_EXIST; 171 } 172 if (!pConnection->IsRingingState()) { 173 TELEPHONY_LOGE("CSControl::Reject return, error type: call state error, phone not ringing."); 174 CellularCallHiSysEvent::WriteHangUpFaultEvent( 175 callInfo.slotId, callInfo.callId, CALL_ERR_CALL_STATE, "Reject call state error phone not ringing"); 176 return CALL_ERR_CALL_STATE; 177 } 178 if (DelayedSingleton<CellularCallRegister>::GetInstance() != nullptr) { 179 DelayedSingleton<CellularCallRegister>::GetInstance()->ReportSingleCallInfo( 180 pConnection->GetCallReportInfo(), TelCallState::CALL_STATUS_DISCONNECTING); 181 } 182 return pConnection->RejectRequest(callInfo.slotId); 183} 184 185int32_t SatelliteControl::ReportSatelliteCallsData(int32_t slotId, const SatelliteCurrentCallList &callInfoList) 186{ 187 std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_); 188 if (callInfoList.callSize <= 0) { 189 return ReportHangUpInfo(slotId); 190 } else if (callInfoList.callSize > 0 && connectionMap_.empty()) { 191 return ReportIncomingInfo(slotId, callInfoList); 192 } else if (callInfoList.callSize > 0 && !connectionMap_.empty()) { 193 return ReportUpdateInfo(slotId, callInfoList); 194 } 195 return TELEPHONY_ERROR; 196} 197 198int32_t SatelliteControl::ReportUpdateInfo(int32_t slotId, const SatelliteCurrentCallList &callInfoList) 199{ 200 TELEPHONY_LOGD("ReportUpdateInfo entry"); 201 CallsReportInfo callsReportInfo; 202 for (int32_t i = 0; i < callInfoList.callSize; ++i) { 203 CallReportInfo reportInfo = EncapsulationCallReportInfo(slotId, callInfoList.calls[i]); 204 205 auto pConnection = FindConnectionByIndex<SatelliteConnectionMap &, CellularCallConnectionSatellite *>( 206 connectionMap_, callInfoList.calls[i].index); 207 if (pConnection == nullptr) { 208 CellularCallConnectionSatellite connection; 209 connection.SetOrUpdateCallReportInfo(reportInfo); 210 connection.SetFlag(true); 211 connection.SetIndex(callInfoList.calls[i].index); 212 connection.SetNumber(callInfoList.calls[i].number); 213 SetConnectionData(connectionMap_, callInfoList.calls[i].index, connection); 214 } else { 215 pConnection->SetFlag(true); 216 pConnection->SetIndex(callInfoList.calls[i].index); 217 pConnection->SetOrUpdateCallReportInfo(reportInfo); 218 pConnection->SetNumber(callInfoList.calls[i].number); 219 } 220 callsReportInfo.callVec.push_back(reportInfo); 221 } 222 callsReportInfo.slotId = slotId; 223 DeleteConnection(callsReportInfo, callInfoList); 224 if (DelayedSingleton<CellularCallRegister>::GetInstance() == nullptr) { 225 TELEPHONY_LOGE("ReportUpdateInfo return, GetInstance() is nullptr."); 226 return TELEPHONY_ERR_LOCAL_PTR_NULL; 227 } 228 if (!isIgnoredIncomingCall_) { 229 DelayedSingleton<CellularCallRegister>::GetInstance()->ReportCallsInfo(callsReportInfo); 230 } 231 return TELEPHONY_SUCCESS; 232} 233 234void SatelliteControl::DeleteConnection(CallsReportInfo &callsReportInfo, const SatelliteCurrentCallList &callInfoList) 235{ 236 TELEPHONY_LOGI("DeleteConnection entry"); 237 auto it = connectionMap_.begin(); 238 while (it != connectionMap_.end()) { 239 CallReportInfo callReportInfo = it->second.GetCallReportInfo(); 240 if (!it->second.GetFlag()) { 241 callReportInfo.state = TelCallState::CALL_STATUS_DISCONNECTED; 242 callsReportInfo.callVec.push_back(callReportInfo); 243 it = connectionMap_.erase(it); 244 GetCallFailReason(callsReportInfo.slotId, connectionMap_); 245 } else { 246 it->second.SetFlag(false); 247 ++it; 248 } 249 } 250} 251 252CallReportInfo SatelliteControl::EncapsulationCallReportInfo(int32_t slotId, const SatelliteCurrentCall &callInfo) 253{ 254 CallReportInfo callReportInfo; 255 if (memset_s(&callReportInfo, sizeof(callReportInfo), 0, sizeof(callReportInfo)) != EOK) { 256 TELEPHONY_LOGE("EncapsulationCallReportInfo return, memset_s fail."); 257 return callReportInfo; 258 } 259 size_t cpyLen = strlen(callInfo.number.c_str()) + 1; 260 if (cpyLen > static_cast<size_t>(kMaxNumberLen + 1)) { 261 TELEPHONY_LOGE("EncapsulationCallReportInfo return, strcpy_s fail."); 262 return callReportInfo; 263 } 264 if (strcpy_s(callReportInfo.accountNum, cpyLen, callInfo.number.c_str()) != EOK) { 265 TELEPHONY_LOGE("EncapsulationCallReportInfo return, strcpy_s fail."); 266 return callReportInfo; 267 } 268 callReportInfo.index = callInfo.index; 269 callReportInfo.accountId = slotId; 270 callReportInfo.voiceDomain = callInfo.voiceDomain; 271 callReportInfo.state = static_cast<TelCallState>(callInfo.state); 272 callReportInfo.callType = CallType::TYPE_SATELLITE; 273 callReportInfo.callMode = VideoStateType::TYPE_VOICE; 274 callReportInfo.mpty = callInfo.mpty; 275 return callReportInfo; 276} 277 278int32_t SatelliteControl::ReportIncomingInfo(int32_t slotId, const SatelliteCurrentCallList &callInfoList) 279{ 280 TELEPHONY_LOGI("ReportIncomingInfo entry"); 281 CallsReportInfo callsReportInfo; 282 for (int32_t i = 0; i < callInfoList.callSize; ++i) { 283 CallReportInfo cellularCallReportInfo = EncapsulationCallReportInfo(slotId, callInfoList.calls[i]); 284 285 CellularCallConnectionSatellite connection; 286 connection.SetStatus(static_cast<TelCallState>(callInfoList.calls[i].state)); 287 connection.SetIndex(callInfoList.calls[i].index); 288 connection.SetOrUpdateCallReportInfo(cellularCallReportInfo); 289 connection.SetNumber(callInfoList.calls[i].number); 290 SetConnectionData(connectionMap_, callInfoList.calls[i].index, connection); 291 292 callsReportInfo.callVec.push_back(cellularCallReportInfo); 293 } 294 if (DelayedSingleton<CellularCallRegister>::GetInstance() == nullptr) { 295 TELEPHONY_LOGE("ReportIncomingInfo return, GetInstance() is nullptr."); 296 return TELEPHONY_ERR_ARGUMENT_INVALID; 297 } 298 callsReportInfo.slotId = slotId; 299 if (!DelayedSingleton<CellularCallRegister>::GetInstance()->IsCallManagerCallBackRegistered() && 300 callsReportInfo.callVec.size() != 0 && callsReportInfo.callVec[0].state == TelCallState::CALL_STATUS_INCOMING) { 301 isIgnoredIncomingCall_ = true; 302 } else { 303 DelayedSingleton<CellularCallRegister>::GetInstance()->ReportCallsInfo(callsReportInfo); 304 } 305 return TELEPHONY_SUCCESS; 306} 307 308int32_t SatelliteControl::ReportHangUpInfo(int32_t slotId) 309{ 310 TELEPHONY_LOGD("ReportHangUpInfo entry"); 311 CallsReportInfo callsReportInfo; 312 for (auto &it : connectionMap_) { 313 CallReportInfo callReportInfo = it.second.GetCallReportInfo(); 314 callReportInfo.state = TelCallState::CALL_STATUS_DISCONNECTED; 315 callReportInfo.accountId = slotId; 316 callsReportInfo.callVec.push_back(callReportInfo); 317 GetCallFailReason(slotId, connectionMap_); 318 } 319 if (connectionMap_.empty()) { 320 TELEPHONY_LOGI("connectionMap_ is empty"); 321 CallReportInfo reportInfo; 322 reportInfo.state = TelCallState::CALL_STATUS_DISCONNECTED; 323 reportInfo.accountId = slotId; 324 callsReportInfo.callVec.push_back(reportInfo); 325 } 326 if (DelayedSingleton<CellularCallRegister>::GetInstance() == nullptr) { 327 TELEPHONY_LOGE("ReportHangUpInfo return, GetInstance() is nullptr."); 328 return TELEPHONY_ERR_LOCAL_PTR_NULL; 329 } 330 callsReportInfo.slotId = slotId; 331 if (isIgnoredIncomingCall_) { 332 isIgnoredIncomingCall_ = false; 333 } else { 334 DelayedSingleton<CellularCallRegister>::GetInstance()->ReportCallsInfo(callsReportInfo); 335 } 336 ReleaseAllConnection(); 337 return TELEPHONY_SUCCESS; 338} 339 340void SatelliteControl::ReleaseAllConnection() 341{ 342 TELEPHONY_LOGI("ReleaseAllConnection entry"); 343 std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_); 344 connectionMap_.clear(); 345} 346 347SatelliteConnectionMap SatelliteControl::GetConnectionMap() 348{ 349 TELEPHONY_LOGI("GetConnectionMap entry"); 350 std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_); 351 return connectionMap_; 352} 353 354int32_t SatelliteControl::ReportHangUp(const std::vector<CellularCallInfo> &infos, int32_t slotId) 355{ 356 CallsReportInfo callsReportInfo; 357 callsReportInfo.slotId = slotId; 358 for (const auto &info : infos) { 359 if (info.callType == CallType::TYPE_SATELLITE && info.slotId == slotId) { 360 CallReportInfo satelliteCallReportInfo; 361 if (memset_s(satelliteCallReportInfo.accountNum, kMaxNumberLen + 1, 0, kMaxNumberLen + 1) != EOK) { 362 TELEPHONY_LOGE("memset_s fail"); 363 return TELEPHONY_ERR_MEMSET_FAIL; 364 } 365 if (memcpy_s(satelliteCallReportInfo.accountNum, kMaxNumberLen, info.phoneNum, kMaxNumberLen) != EOK) { 366 TELEPHONY_LOGE("memcpy_s fail"); 367 return TELEPHONY_ERR_MEMCPY_FAIL; 368 } 369 satelliteCallReportInfo.index = info.index; 370 satelliteCallReportInfo.accountId = info.slotId; 371 satelliteCallReportInfo.callType = CallType::TYPE_SATELLITE; 372 satelliteCallReportInfo.callMode = VideoStateType::TYPE_VOICE; 373 satelliteCallReportInfo.state = TelCallState::CALL_STATUS_DISCONNECTED; 374 callsReportInfo.callVec.push_back(satelliteCallReportInfo); 375 } 376 } 377 if (DelayedSingleton<CellularCallRegister>::GetInstance() == nullptr) { 378 TELEPHONY_LOGE("CellularCallRegister instance is nullptr"); 379 return TELEPHONY_ERR_LOCAL_PTR_NULL; 380 } 381 DelayedSingleton<CellularCallRegister>::GetInstance()->ReportCallsInfo(callsReportInfo); 382 ReleaseAllConnection(); 383 return TELEPHONY_SUCCESS; 384} 385 386int32_t SatelliteControl::HoldCall(int32_t slotId) 387{ 388 return TELEPHONY_ERROR; 389} 390 391int32_t SatelliteControl::UnHoldCall(int32_t slotId) 392{ 393 return TELEPHONY_ERROR; 394} 395 396int32_t SatelliteControl::SwitchCall(int32_t slotId) 397{ 398 return TELEPHONY_ERROR; 399} 400 401int32_t SatelliteControl::CombineConference(int32_t slotId) 402{ 403 return TELEPHONY_ERROR; 404} 405 406int32_t SatelliteControl::HangUpAllConnection(int32_t slotId) 407{ 408 TELEPHONY_LOGI("HangUpAllConnection entry"); 409 CellularCallConnectionSatellite connection; 410 // The AT command for hanging up all calls is the same as the AT command for rejecting calls, 411 // so the reject interface is reused. 412 connection.RejectRequest(slotId); 413 return TELEPHONY_SUCCESS; 414} 415 416int32_t SatelliteControl::ReportCallsData(int32_t slotId, const CallInfoList &callInfoList) 417{ 418 return TELEPHONY_ERROR; 419} 420 421int32_t SatelliteControl::ExecutePostDial(int32_t slotId, int64_t callId) 422{ 423 TELEPHONY_LOGI("ExecutePostDial entry"); 424 std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_); 425 if (connectionMap_.empty()) { 426 TELEPHONY_LOGE("connectionMap_ is empty."); 427 return TELEPHONY_ERROR; 428 } 429 auto pConnection = FindConnectionByIndex<SatelliteConnectionMap &, 430 CellularCallConnectionSatellite *>(connectionMap_, callId); 431 if (pConnection == nullptr) { 432 return TELEPHONY_ERR_LOCAL_PTR_NULL; 433 } 434 char currentChar; 435 PostDialCallState state = pConnection->ProcessNextChar(slotId, currentChar); 436 switch (state) { 437 case PostDialCallState::POST_DIAL_CALL_STARTED: 438 DelayedSingleton<CellularCallRegister>::GetInstance()->ReportPostDialChar(currentChar); 439 break; 440 case PostDialCallState::POST_DIAL_CALL_DELAY: 441 DelayedSingleton<CellularCallRegister>::GetInstance()->ReportPostDialDelay( 442 pConnection->GetLeftPostDialCallString()); 443 break; 444 default: 445 break; 446 } 447 return TELEPHONY_SUCCESS; 448} 449 450int32_t SatelliteControl::PostDialProceed(const CellularCallInfo &callInfo, const bool proceed) 451{ 452 TELEPHONY_LOGI("PostDialProceed entry"); 453 std::string networkAddress; 454 std::string postDialString; 455 StandardizeUtils standardizeUtils; 456 standardizeUtils.ExtractAddressAndPostDial(callInfo.phoneNum, networkAddress, postDialString); 457 std::lock_guard<std::recursive_mutex> lock(connectionMapMutex_); 458 auto pConnection = FindConnectionByIndex<SatelliteConnectionMap &, CellularCallConnectionSatellite *>( 459 connectionMap_, callInfo.index); 460 if (pConnection == nullptr) { 461 TELEPHONY_LOGE("cs pConnection is nullptr!"); 462 return TELEPHONY_ERR_LOCAL_PTR_NULL; 463 } 464 if (proceed) { 465 ExecutePostDial(callInfo.slotId, pConnection->GetIndex()); 466 } else { 467 pConnection->SetPostDialCallState(PostDialCallState::POST_DIAL_CALL_CANCELED); 468 } 469 return TELEPHONY_SUCCESS; 470} 471} // namespace Telephony 472} // namespace OHOS 473