• 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 "mmi_code_utils.h"
17 
18 #include <regex>
19 
20 #include "cellular_call_service.h"
21 #include "cellular_call_supplement.h"
22 #include "core_manager_inner.h"
23 #include "standardize_utils.h"
24 #include "telephony_log_wrapper.h"
25 
26 namespace OHOS {
27 namespace Telephony {
28 const int32_t MAX_LENGTH_SHORT_CODE = 2;
29 
30 // 3GPP TS 22.030 V16.0.0 (2020-07) 6.5.3.2	Handling of not-implemented supplementary services
operator ""_hash(char const * p,size_t s)31 constexpr unsigned long long operator"" _hash(char const *p, size_t s)
32 {
33     return StandardizeUtils::HashCompileTime(p);
34 }
35 
IsNeedExecuteMmi(const std::string & analyseString,bool isNeedUseIms)36 bool MMICodeUtils::IsNeedExecuteMmi(const std::string &analyseString, bool isNeedUseIms)
37 {
38     isNeedUseIms_ = isNeedUseIms;
39     if (analyseString.empty()) {
40         TELEPHONY_LOGE("analyseString is empty.");
41         return false;
42     }
43     if (IsShortCode(analyseString)) {
44         mmiData_.fullString = analyseString;
45         return true;
46     }
47     if (RegexMatchMmi(analyseString)) {
48         return true;
49     }
50 
51     // 3GPP TS 22.030 V16.0.0 (2020-07) 6.5.3.2	Handling of not-implemented supplementary services
52     if ((analyseString.front() == '*' || analyseString.front() == '#') && analyseString.back() == '#') {
53         TELEPHONY_LOGI("analyseString start with * or # and end with #");
54         mmiData_.fullString = analyseString;
55         return true;
56     }
57     return false;
58 }
59 
InitCallTransferMmiCodeFunc(std::map<std::uint64_t,std::function<void (CellularCallSupplement * supplement,int32_t slotId,const MMIData & mmiData)>> & mmiCodeFunc)60 void InitCallTransferMmiCodeFunc(std::map<std::uint64_t,
61     std::function<void(CellularCallSupplement *supplement, int32_t slotId, const MMIData &mmiData)>> &mmiCodeFunc)
62 {
63     /**
64      * "21" Deal with unconditional transfer
65      * "61" Handling no answer transfer
66      * "62" Handling no signal transfer
67      * "67" Deal with busy transfer
68      * "002" Process all transfers
69      * "004" Handle transfer under all conditions
70      */
71     mmiCodeFunc["21"_hash] = [](CellularCallSupplement *supplement, int32_t slotId, const MMIData &mmiData) {
72         supplement->HandleCallTransfer(slotId, mmiData);
73     };
74     mmiCodeFunc["61"_hash] = [](CellularCallSupplement *supplement, int32_t slotId, const MMIData &mmiData) {
75         supplement->HandleCallTransfer(slotId, mmiData);
76     };
77     mmiCodeFunc["62"_hash] = [](CellularCallSupplement *supplement, int32_t slotId, const MMIData &mmiData) {
78         supplement->HandleCallTransfer(slotId, mmiData);
79     };
80     mmiCodeFunc["67"_hash] = [](CellularCallSupplement *supplement, int32_t slotId, const MMIData &mmiData) {
81         supplement->HandleCallTransfer(slotId, mmiData);
82     };
83     mmiCodeFunc["002"_hash] = [](CellularCallSupplement *supplement, int32_t slotId, const MMIData &mmiData) {
84         supplement->HandleCallTransfer(slotId, mmiData);
85     };
86     mmiCodeFunc["004"_hash] = [](CellularCallSupplement *supplement, int32_t slotId, const MMIData &mmiData) {
87         supplement->HandleCallTransfer(slotId, mmiData);
88     };
89 }
90 
InitCallRestrictionCodeFunc(std::map<std::uint64_t,std::function<void (CellularCallSupplement * supplement,int32_t slotId,const MMIData & mmiData)>> & mmiCodeFunc)91 void InitCallRestrictionCodeFunc(std::map<std::uint64_t,
92     std::function<void(CellularCallSupplement *supplement, int32_t slotId, const MMIData &mmiData)>> &mmiCodeFunc)
93 {
94     /**
95      * "33" Processing limits all outgoing calls
96      * "330" Processing all restrictions
97      * "331" Processing limits all international calls
98      * "332" Handling international outgoing calls belonging to foreign countries when roaming is
99      * restricted
100      * "333" Processing limits outgoing calls
101      * "35" Processing limits all incoming calls
102      * "351" Handle all incoming calls when roaming is restricted
103      * "353" Processing limits incoming calls
104      */
105     mmiCodeFunc["33"_hash] = [](CellularCallSupplement *supplement, int32_t slotId, const MMIData &mmiData) {
106         supplement->HandleCallRestriction(slotId, mmiData);
107     };
108     mmiCodeFunc["330"_hash] = [](CellularCallSupplement *supplement, int32_t slotId, const MMIData &mmiData) {
109         supplement->HandleCallRestriction(slotId, mmiData);
110     };
111     mmiCodeFunc["331"_hash] = [](CellularCallSupplement *supplement, int32_t slotId, const MMIData &mmiData) {
112         supplement->HandleCallRestriction(slotId, mmiData);
113     };
114     mmiCodeFunc["332"_hash] = [](CellularCallSupplement *supplement, int32_t slotId, const MMIData &mmiData) {
115         supplement->HandleCallRestriction(slotId, mmiData);
116     };
117     mmiCodeFunc["333"_hash] = [](CellularCallSupplement *supplement, int32_t slotId, const MMIData &mmiData) {
118         supplement->HandleCallRestriction(slotId, mmiData);
119     };
120     mmiCodeFunc["35"_hash] = [](CellularCallSupplement *supplement, int32_t slotId, const MMIData &mmiData) {
121         supplement->HandleCallRestriction(slotId, mmiData);
122     };
123     mmiCodeFunc["351"_hash] = [](CellularCallSupplement *supplement, int32_t slotId, const MMIData &mmiData) {
124         supplement->HandleCallRestriction(slotId, mmiData);
125     };
126     mmiCodeFunc["353"_hash] = [](CellularCallSupplement *supplement, int32_t slotId, const MMIData &mmiData) {
127         supplement->HandleCallRestriction(slotId, mmiData);
128     };
129 }
130 
InitAdditionalMmiCodeFunc(std::map<std::uint64_t,std::function<void (CellularCallSupplement * supplement,int32_t slotId,const MMIData & mmiData)>> & mmiCodeFunc)131 void InitAdditionalMmiCodeFunc(std::map<std::uint64_t,
132     std::function<void(CellularCallSupplement *supplement, int32_t slotId, const MMIData &mmiData)>> &mmiCodeFunc)
133 {
134     /**
135      * "30" Processing caller ID
136      * "31" Processing calling number display
137      * "04" Change pin password
138      * "05" Use puk unlock sim and change pin password
139      * "042" Change pin2 password
140      * "052" Use puk2 unlock sim and change pin2 password
141      * "43" Handling call waiting
142      */
143     mmiCodeFunc["30"_hash] = [](CellularCallSupplement *supplement, int32_t slotId, const MMIData &mmiData) {
144         supplement->HandleClip(slotId, mmiData);
145     };
146     mmiCodeFunc["31"_hash] = [](CellularCallSupplement *supplement, int32_t slotId, const MMIData &mmiData) {
147         supplement->HandleClir(slotId, mmiData);
148     };
149     mmiCodeFunc["04"_hash] = [](CellularCallSupplement *supplement, int32_t slotId, const MMIData &mmiData) {
150         supplement->AlterPinPassword(slotId, mmiData);
151     };
152     mmiCodeFunc["05"_hash] = [](CellularCallSupplement *supplement, int32_t slotId, const MMIData &mmiData) {
153         supplement->UnlockPuk(slotId, mmiData);
154     };
155     mmiCodeFunc["042"_hash] = [](CellularCallSupplement *supplement, int32_t slotId, const MMIData &mmiData) {
156         supplement->AlterPin2Password(slotId, mmiData);
157     };
158     mmiCodeFunc["052"_hash] = [](CellularCallSupplement *supplement, int32_t slotId, const MMIData &mmiData) {
159         supplement->UnlockPuk2(slotId, mmiData);
160     };
161     mmiCodeFunc["43"_hash] = [](CellularCallSupplement *supplement, int32_t slotId, const MMIData &mmiData) {
162         supplement->HandleCallWaiting(slotId, mmiData);
163     };
164 }
165 
InitImsMmiCodeFunc(std::map<std::uint64_t,std::function<void (CellularCallSupplement * supplement,int32_t slotId,const MMIData & mmiData)>> & mmiCodeFunc)166 void InitImsMmiCodeFunc(std::map<std::uint64_t,
167     std::function<void(CellularCallSupplement *supplement, int32_t slotId, const MMIData &mmiData)>> &mmiCodeFunc)
168 {
169     /**
170      * "76" Connected line identification presentation
171      * "77" Connected line identification restriction
172      */
173     mmiCodeFunc["76"_hash] = [](CellularCallSupplement *supplement, int32_t slotId, const MMIData &mmiData) {
174         supplement->HandleColp(slotId, mmiData);
175     };
176     mmiCodeFunc["77"_hash] = [](CellularCallSupplement *supplement, int32_t slotId, const MMIData &mmiData) {
177         supplement->HandleColr(slotId, mmiData);
178     };
179 }
180 
ExecuteMmiCode(int32_t slotId)181 bool MMICodeUtils::ExecuteMmiCode(int32_t slotId)
182 {
183     using MmiCodeFunc =
184         std::function<void(CellularCallSupplement * supplement, int32_t slotId, const MMIData &mmiData)>;
185     std::map<std::uint64_t, MmiCodeFunc> mmiCodeFunc;
186     InitCallTransferMmiCodeFunc(mmiCodeFunc);
187     InitCallRestrictionCodeFunc(mmiCodeFunc);
188     InitAdditionalMmiCodeFunc(mmiCodeFunc);
189     if (isNeedUseIms_) {
190         InitImsMmiCodeFunc(mmiCodeFunc);
191     }
192 
193     CellularCallSupplement supplement;
194     if (!mmiData_.serviceCode.empty()) {
195         auto serviceCode = StandardizeUtils::Hash_(mmiData_.serviceCode.c_str());
196         // "03" Processing network password
197         if (serviceCode == "03"_hash) {
198             return true;
199         }
200         auto itFunc = mmiCodeFunc.find(serviceCode);
201         if (itFunc != mmiCodeFunc.end()) {
202             auto func = itFunc->second;
203             if (func != nullptr) {
204                 func(&supplement, slotId, mmiData_);
205                 return true;
206             }
207         }
208         TELEPHONY_LOGI("Function not found, need check serviceCode.");
209     }
210     if (!mmiData_.fullString.empty()) {
211         TELEPHONY_LOGD("fullString is not empty.");
212         supplement.SendUssd(slotId, mmiData_.fullString);
213         return true;
214     }
215 
216     TELEPHONY_LOGW("default case, need check.");
217     return false;
218 }
219 
RegexMatchMmi(const std::string & analyseString)220 bool MMICodeUtils::RegexMatchMmi(const std::string &analyseString)
221 {
222     std::string symbols =
223         "((\\*|#|\\*#|\\*\\*|##)(\\d{2,3})(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*))?)?)?)?#)(.*)";
224     std::regex pattern(symbols);
225     std::smatch results;
226     if (regex_match(analyseString, results, pattern)) {
227         TELEPHONY_LOGD("regex_match true");
228 
229         /**
230          * The following sequence of functions shall be used for the control of Supplementary Services:
231          *  SELECT:	Entry of the procedure information (may be a digit or a sequence of characters).
232          *  SEND: Transmission of the information to the network.
233          *  INDICATION:	Call progress indications.
234          */
235         int32_t fullString = 1;
236         int32_t action = 2;
237         // 3GPP TS 22.030 V4.0.0 (2001-03)  6.5.2 Structure of the MMI
238         // This structure consists of the following parts:
239         //     Service Code, SC( (2 or 3 digits)
240         //     Supplementary Information, SI (variable length).
241         int32_t serviceCode = 3;
242         int32_t sia = 5;
243         int32_t sib = 7;
244         int32_t sic = 9;
245         int32_t pwdConfirm = 11;
246         int32_t dialingNumber = 12;
247         mmiData_.fullString = results.str(fullString);
248         mmiData_.actionString = results.str(action);
249         mmiData_.serviceCode = results.str(serviceCode);
250         mmiData_.serviceInfoA = results.str(sia);
251         mmiData_.serviceInfoB = results.str(sib);
252         mmiData_.serviceInfoC = results.str(sic);
253         mmiData_.pwdString = results.str(pwdConfirm);
254         mmiData_.dialString = results.str(dialingNumber);
255 
256         /* 3GPP TS 22.030 V4.0.0 (2001-03)  6.5.2 Structure of the MMI
257          * The procedure always starts with *, #, **, ## or *# and is finished by #.
258          * Each part within the procedure is separated by *.
259          */
260         if (analyseString.back() == '#' && !mmiData_.dialString.empty() && mmiData_.dialString.back() == '#') {
261             mmiData_.fullString = analyseString;
262         }
263         return true;
264     }
265     return false;
266 }
267 
GetMMIData()268 MMIData MMICodeUtils::GetMMIData()
269 {
270     return mmiData_;
271 }
272 
IsShortCode(const std::string & analyseString)273 bool MMICodeUtils::IsShortCode(const std::string &analyseString)
274 {
275     if (HasCellularCallExist()) {
276         return IsShortCodeWithCellularCall(analyseString);
277     }
278     return IsShortCodeWithoutCellularCall(analyseString);
279 }
280 
IsShortCodeWithoutCellularCall(const std::string & analyseString)281 bool MMICodeUtils::IsShortCodeWithoutCellularCall(const std::string &analyseString)
282 {
283     if (analyseString.length() > MAX_LENGTH_SHORT_CODE) {
284         return false;
285     }
286     if (analyseString[0] == '1' && std::isdigit(analyseString[1])) {
287         return false;
288     }
289     return true;
290 }
291 
IsShortCodeWithCellularCall(const std::string & analyseString)292 bool MMICodeUtils::IsShortCodeWithCellularCall(const std::string &analyseString)
293 {
294     if (analyseString.length() < 1 || analyseString.length() > MAX_LENGTH_SHORT_CODE) {
295         return false;
296     }
297     return true;
298 }
299 
HasCellularCallExist()300 bool MMICodeUtils::HasCellularCallExist()
301 {
302     int32_t simCount = CoreManagerInner::GetInstance().GetMaxSimCount();
303     if (simCount == 0) {
304         return false;
305     }
306     auto serviceInstance = DelayedSingleton<CellularCallService>::GetInstance();
307     if (serviceInstance == nullptr) {
308         TELEPHONY_LOGE("serviceInstance is null");
309         return false;
310     }
311     for (int32_t i = 0; i < simCount; i++) {
312         auto imsControl = serviceInstance->GetImsControl(i);
313         if (imsControl != nullptr && !imsControl->GetConnectionMap().empty()) {
314             return true;
315         }
316         auto csControl = serviceInstance->GetCsControl(i);
317         if (csControl != nullptr && !csControl->GetConnectionMap().empty()) {
318             return true;
319         }
320         auto satelliteControl = serviceInstance->GetSatelliteControl(i);
321         if (satelliteControl != nullptr && !satelliteControl->GetConnectionMap().empty()) {
322             return true;
323         }
324     }
325     return false;
326 }
327 } // namespace Telephony
328 } // namespace OHOS
329