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