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