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