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