1 /*
2 * Copyright (C) 2021 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_supplement.h"
21 #include "standardize_utils.h"
22 #include "telephony_log_wrapper.h"
23
24 namespace OHOS {
25 namespace Telephony {
26 // 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)27 constexpr unsigned long long operator"" _hash(char const *p, size_t s)
28 {
29 return StandardizeUtils::HashCompileTime(p);
30 }
31
IsNeedExecuteMmi(const std::string & analyseString)32 bool MMICodeUtils::IsNeedExecuteMmi(const std::string &analyseString)
33 {
34 if (analyseString.empty()) {
35 TELEPHONY_LOGE("IsNeedExecuteMmi return, analyseString is empty.");
36 return false;
37 }
38 if (RegexMatchMmi(analyseString)) {
39 return true;
40 }
41
42 // 3GPP TS 22.030 V16.0.0 (2020-07) 6.5.3.2 Handling of not-implemented supplementary services
43 if (analyseString.back() == '#') {
44 TELEPHONY_LOGI("IsNeedExecuteMmi, analyseString is end of #");
45 mmiData_.fullString = analyseString;
46 return true;
47 }
48
49 return false;
50 }
51
InitMmiCodeFunc(std::map<std::uint64_t,void (CellularCallSupplement::*)(int32_t slotId,const MMIData & mmiData)> & mmiCodeFunc)52 void InitMmiCodeFunc(std::map<std::uint64_t,
53 void (CellularCallSupplement::*)(int32_t slotId, const MMIData &mmiData)> &mmiCodeFunc)
54 {
55 /**
56 * "30" Processing caller ID
57 * "31" Processing calling number display
58 * "21" Deal with unconditional transfer
59 * "61" Handling no answer transfer
60 * "62" Handling no signal transfer
61 * "67" Deal with busy transfer
62 * "002" Process all transfers
63 * "004" Handle transfer under all conditions
64 * "33" Processing limits all outgoing calls
65 * "330" Processing all restrictions
66 * "331" Processing limits all international calls
67 * "332" Handling international outgoing calls belonging to foreign countries when roaming is
68 * restricted
69 * "35" Processing limits all incoming calls
70 * "351" Handle all incoming calls when roaming is restricted
71 * "43" Handling call waiting
72 * "04" Change pin password
73 * "05" Use puk unlock sim and change pin password
74 * "042" Change pin2 password
75 * "052" Use puk2 unlock sim and change pin2 password
76 */
77 mmiCodeFunc["30"_hash] = &CellularCallSupplement::GetClip;
78 mmiCodeFunc["31"_hash] = &CellularCallSupplement::GetClir;
79 mmiCodeFunc["21"_hash] = &CellularCallSupplement::DealCallTransfer;
80 mmiCodeFunc["61"_hash] = &CellularCallSupplement::DealCallTransfer;
81 mmiCodeFunc["62"_hash] = &CellularCallSupplement::DealCallTransfer;
82 mmiCodeFunc["67"_hash] = &CellularCallSupplement::DealCallTransfer;
83 mmiCodeFunc["002"_hash] = &CellularCallSupplement::DealCallTransfer;
84 mmiCodeFunc["004"_hash] = &CellularCallSupplement::DealCallTransfer;
85 mmiCodeFunc["33"_hash] = &CellularCallSupplement::DealCallRestriction;
86 mmiCodeFunc["330"_hash] = &CellularCallSupplement::DealCallRestriction;
87 mmiCodeFunc["331"_hash] = &CellularCallSupplement::DealCallRestriction;
88 mmiCodeFunc["332"_hash] = &CellularCallSupplement::DealCallRestriction;
89 mmiCodeFunc["35"_hash] = &CellularCallSupplement::DealCallRestriction;
90 mmiCodeFunc["351"_hash] = &CellularCallSupplement::DealCallRestriction;
91 mmiCodeFunc["43"_hash] = &CellularCallSupplement::DealCallWaiting;
92 mmiCodeFunc["04"_hash] = &CellularCallSupplement::AlterPinPassword;
93 mmiCodeFunc["05"_hash] = &CellularCallSupplement::UnlockPuk;
94 mmiCodeFunc["042"_hash] = &CellularCallSupplement::AlterPin2Password;
95 mmiCodeFunc["052"_hash] = &CellularCallSupplement::UnlockPuk2;
96 }
97
ExecuteMmiCode(int32_t slotId)98 bool MMICodeUtils::ExecuteMmiCode(int32_t slotId)
99 {
100 TELEPHONY_LOGI("ExecuteMmiCode entry.");
101 using MmiCodeFunc = void (CellularCallSupplement::*)(int32_t slotId, const MMIData &mmiData);
102 std::map<std::uint64_t, MmiCodeFunc> mmiCodeFunc;
103 InitMmiCodeFunc(mmiCodeFunc);
104
105 CellularCallSupplement supplement;
106 if (!mmiData_.serviceCode.empty()) {
107 auto serviceCode = StandardizeUtils::Hash_(mmiData_.serviceCode.c_str());
108 // "03" Processing network password
109 if (serviceCode == "03"_hash) {
110 return true;
111 }
112 auto itFunc = mmiCodeFunc.find(serviceCode);
113 if (itFunc != mmiCodeFunc.end()) {
114 auto func = itFunc->second;
115 if (func != nullptr) {
116 (supplement.*func)(slotId, mmiData_);
117 return true;
118 }
119 }
120 TELEPHONY_LOGI("ExecuteMmiCode, default case, need check serviceCode.");
121 }
122 if (!mmiData_.fullString.empty()) {
123 TELEPHONY_LOGI("ExecuteMmiCode, fullString is not empty.");
124 supplement.SendUssd(slotId, mmiData_.fullString);
125 return true;
126 }
127
128 TELEPHONY_LOGW("ExecuteMmiCode, default case, need check.");
129 return false;
130 }
131
RegexMatchMmi(const std::string & analyseString)132 bool MMICodeUtils::RegexMatchMmi(const std::string &analyseString)
133 {
134 std::string symbols =
135 "((\\*|#|\\*#|\\*\\*|##)(\\d{2,3})(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*))?)?)?)?#)(.*)";
136 std::regex pattern(symbols);
137 std::smatch results;
138 if (regex_match(analyseString, results, pattern)) {
139 TELEPHONY_LOGI("MMICodeUtils::RegexMatchMmi, regex_match ture");
140
141 /**
142 * The following sequence of functions shall be used for the control of Supplementary Services:
143 * SELECT: Entry of the procedure information (may be a digit or a sequence of characters).
144 * SEND: Transmission of the information to the network.
145 * INDICATION: Call progress indications.
146 */
147 int32_t fullString = 1;
148 int32_t action = 2;
149 // 3GPP TS 22.030 V4.0.0 (2001-03) 6.5.2 Structure of the MMI
150 // This structure consists of the following parts:
151 // Service Code, SC( (2 or 3 digits)
152 // Supplementary Information, SI (variable length).
153 int32_t serviceCode = 3;
154 int32_t sia = 5;
155 int32_t sib = 7;
156 int32_t sic = 9;
157 int32_t pwdConfirm = 11;
158 int32_t dialingNumber = 12;
159 mmiData_.fullString = results.str(fullString);
160 mmiData_.actionString = results.str(action);
161 mmiData_.serviceCode = results.str(serviceCode);
162 mmiData_.serviceInfoA = results.str(sia);
163 mmiData_.serviceInfoB = results.str(sib);
164 mmiData_.serviceInfoC = results.str(sic);
165 mmiData_.pwdString = results.str(pwdConfirm);
166 mmiData_.dialString = results.str(dialingNumber);
167
168 /* 3GPP TS 22.030 V4.0.0 (2001-03) 6.5.2 Structure of the MMI
169 * The procedure always starts with *, #, **, ## or *# and is finished by #.
170 * Each part within the procedure is separated by *.
171 */
172 if (analyseString.back() == '#' && !mmiData_.dialString.empty() && mmiData_.dialString.back() == '#') {
173 mmiData_.fullString = analyseString;
174 }
175 return true;
176 }
177 return false;
178 }
179
GetMMIData()180 MMIData MMICodeUtils::GetMMIData()
181 {
182 return mmiData_;
183 }
184 } // namespace Telephony
185 } // namespace OHOS
186