1/* 2 * Copyright (C) 2021-2022 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 "control_base.h" 17 18#include "cellular_call_config.h" 19#include "cellular_call_hisysevent.h" 20#include "cellular_call_service.h" 21#include "core_service_client.h" 22#include "module_service_utils.h" 23#include "standardize_utils.h" 24 25namespace OHOS { 26namespace Telephony { 27const uint32_t WAIT_TIME_SECOND = 5; 28 29int32_t ControlBase::DialPreJudgment(const CellularCallInfo &callInfo, bool isEcc) 30{ 31 HandleEcc(callInfo, isEcc, CheckAirplaneModeScene(callInfo), CheckActivateSimScene(callInfo.slotId)); 32 std::string dialString(callInfo.phoneNum); 33 if (dialString.empty()) { 34 TELEPHONY_LOGE("DialPreJudgment return, dialString is empty."); 35 CellularCallHiSysEvent::WriteDialCallFaultEvent(callInfo.accountId, static_cast<int32_t>(callInfo.callType), 36 callInfo.videoState, CALL_ERR_PHONE_NUMBER_EMPTY, "dialString is empty"); 37 return CALL_ERR_PHONE_NUMBER_EMPTY; 38 } 39 40 ModuleServiceUtils moduleServiceUtils; 41 if (!moduleServiceUtils.GetRadioState(callInfo.slotId)) { 42 TELEPHONY_LOGE("DialPreJudgment return, radio state error."); 43 CellularCallHiSysEvent::WriteDialCallFaultEvent(callInfo.accountId, static_cast<int32_t>(callInfo.callType), 44 callInfo.videoState, CALL_ERR_GET_RADIO_STATE_FAILED, "radio state error"); 45 return CALL_ERR_GET_RADIO_STATE_FAILED; 46 } 47 return TELEPHONY_SUCCESS; 48} 49 50bool ControlBase::IsNeedExecuteMMI(int32_t slotId, std::string &phoneString, CLIRMode &clirMode, bool isNeedUseIms) 51{ 52 TELEPHONY_LOGI("IsNeedExecuteMMI start"); 53 // Also supplementary services may be controlled using dial command according to 3GPP TS 22.030 [19]. 54 // An example of call forwarding on no reply for telephony with the adjustment of the 55 // no reply condition timer on 25 seconds: 56 // Parse the MMI code from the string 57 std::unique_ptr<MMICodeUtils> mmiCodeUtils = std::make_unique<MMICodeUtils>(); 58 // Parse the MMI code from the string 59 if (mmiCodeUtils == nullptr) { 60 TELEPHONY_LOGE("IsNeedExecuteMMI return, mmiCodeUtils is nullptr"); 61 return false; 62 } 63 if (!mmiCodeUtils->IsNeedExecuteMmi(phoneString, isNeedUseIms)) { 64 TELEPHONY_LOGI("IsNeedExecuteMMI return, isn't need to execute mmi"); 65 return false; 66 } 67 if (mmiCodeUtils->GetMMIData().serviceCode == "30" && !mmiCodeUtils->GetMMIData().dialString.empty()) { 68 TELEPHONY_LOGI("IsNeedExecuteMMI, handle additional CLIR mode"); 69 if (mmiCodeUtils->GetMMIData().actionString == "*") { 70 phoneString = mmiCodeUtils->GetMMIData().dialString; 71 clirMode = CLIRMode::TRANSFER; 72 return false; 73 } else if (mmiCodeUtils->GetMMIData().actionString == "#") { 74 phoneString = mmiCodeUtils->GetMMIData().dialString; 75 clirMode = CLIRMode::INHIBITION; 76 return false; 77 } 78 } 79 if (DelayedSingleton<CellularCallService>::GetInstance() == nullptr) { 80 TELEPHONY_LOGI("IsNeedExecuteMMI return, GetInstance is nullptr"); 81 return false; 82 } 83 if (DelayedSingleton<CellularCallService>::GetInstance()->GetHandler(slotId) == nullptr) { 84 TELEPHONY_LOGI("IsNeedExecuteMMI return, GetHandler is nullptr"); 85 return false; 86 } 87 return DelayedSingleton<CellularCallService>::GetInstance()->GetHandler(slotId)->SendEvent( 88 MMIHandlerId::EVENT_MMI_Id, mmiCodeUtils); 89} 90 91bool ControlBase::IsDtmfKey(char c) const 92{ 93 /** 94 * 1. <DTMF>. A single ASCII character in the set 0 9, #,*,A D. This is interpreted as a single ASCII character 95 * whose duration is set by the +VTD command. NOTE 2: In GSM this operates only in voice mode. 96 */ 97 return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'D') || c == '*' || c == '#'; 98} 99 100bool ControlBase::IsConnectedOut(TelCallState preState, TelCallState curState) 101{ 102 if ((preState == TelCallState::CALL_STATUS_DIALING || preState == TelCallState::CALL_STATUS_ALERTING) && 103 !(curState == TelCallState::CALL_STATUS_DIALING || curState == TelCallState::CALL_STATUS_ALERTING)) { 104 return true; 105 } 106 return false; 107} 108 109bool ControlBase::CheckAirplaneModeScene(const CellularCallInfo &callInfo) 110{ 111 bool isAirplaneModeOn = false; 112 ModuleServiceUtils moduleServiceUtils; 113 return moduleServiceUtils.GetAirplaneMode(isAirplaneModeOn) == TELEPHONY_SUCCESS && isAirplaneModeOn; 114} 115 116bool ControlBase::CheckActivateSimScene(int32_t slotId) 117{ 118 bool hasSimCard = false; 119 DelayedRefSingleton<CoreServiceClient>::GetInstance().HasSimCard(slotId, hasSimCard); 120 bool isActivateSim = true; 121 if (hasSimCard) { 122 isActivateSim = DelayedRefSingleton<CoreServiceClient>::GetInstance().IsSimActive(slotId); 123 } 124 return isActivateSim; 125} 126 127int32_t ControlBase::HandleEcc(const CellularCallInfo &callInfo, bool isEcc, bool isAirplaneModeOn, bool isActivateSim) 128{ 129 if (!isEcc) { 130 TELEPHONY_LOGE("HandleEcc airplane mode is not ecc"); 131 return TELEPHONY_ERR_AIRPLANE_MODE_ON; 132 } 133 134 if (isAirplaneModeOn) { 135 ModuleServiceUtils moduleServiceUtils; 136 int32_t ret = moduleServiceUtils.UpdateRadioOn(callInfo.slotId); 137 if (ret != TELEPHONY_SUCCESS) { 138 TELEPHONY_LOGE("UpdateRadioOn fail"); 139 return ret; 140 } 141 } 142 if (!isActivateSim) { 143 int32_t ret = DelayedRefSingleton<CoreServiceClient>::GetInstance().SetActiveSim(callInfo.slotId, true); 144 if (ret != TELEPHONY_SUCCESS) { 145 TELEPHONY_LOGE("UpdateSimState fail"); 146 return ret; 147 } 148 int32_t otherSlotId = callInfo.slotId == SLOT_0 ? SLOT_1 : SLOT_0; 149 if (!CheckActivateSimScene(otherSlotId)) { 150 ret = DelayedRefSingleton<CoreServiceClient>::GetInstance().SetActiveSim(otherSlotId, true); 151 if (ret != TELEPHONY_SUCCESS) { 152 TELEPHONY_LOGE("UpdateSecondSimCardState fail"); 153 return ret; 154 } 155 } 156 } 157 std::unique_lock<std::mutex> lock(mutex_); 158 CellularCallConfig cellularCallConfig; 159 while (!cellularCallConfig.IsReadyToCall(callInfo.slotId)) { 160 if (cv_.wait_for(lock, std::chrono::seconds(WAIT_TIME_SECOND)) == std::cv_status::timeout) { 161 TELEPHONY_LOGE("HandleEcc network in service timeout"); 162 return CALL_ERR_DIAL_FAILED; 163 } 164 } 165 166 return TELEPHONY_SUCCESS; 167} 168 169int32_t ControlBase::SetReadyToCall(int32_t slotId, bool isReadyToCall) 170{ 171 std::unique_lock<std::mutex> lock(mutex_); 172 CellularCallConfig cellularCallConfig; 173 if (!cellularCallConfig.IsReadyToCall(slotId) && isReadyToCall) { 174 cellularCallConfig.SetReadyToCall(slotId, isReadyToCall); 175 cv_.notify_all(); 176 } 177 return TELEPHONY_SUCCESS; 178} 179} // namespace Telephony 180} // namespace OHOS 181