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 "call_number_utils.h"
17 
18 #include <regex>
19 
20 #include "phonenumbers/phonenumber.pb.h"
21 #include "telephony_log_wrapper.h"
22 #include "telephony_types.h"
23 #include "call_manager_errors.h"
24 #include "cellular_call_connection.h"
25 #include "core_service_client.h"
26 #include "cellular_data_client.h"
27 #include "call_ability_report_proxy.h"
28 #include "number_identity_data_base_helper.h"
29 #include "asyoutypeformatter.h"
30 #include "call_voice_assistant_manager.h"
31 
32 namespace OHOS {
33 namespace Telephony {
CallNumberUtils()34 CallNumberUtils::CallNumberUtils() {}
35 
~CallNumberUtils()36 CallNumberUtils::~CallNumberUtils() {}
37 
FormatPhoneNumber(const std::string & phoneNumber,const std::string & countryCode,std::string & formatNumber)38 int32_t CallNumberUtils::FormatPhoneNumber(
39     const std::string &phoneNumber, const std::string &countryCode, std::string &formatNumber)
40 {
41     if (phoneNumber.empty()) {
42         TELEPHONY_LOGE("phoneNumber is nullptr!");
43         return TELEPHONY_ERR_ARGUMENT_INVALID;
44     }
45     if (phoneNumber.front() == '#' || phoneNumber.front() == '*') {
46         formatNumber = phoneNumber;
47         return TELEPHONY_SUCCESS;
48     }
49     i18n::phonenumbers::PhoneNumberUtil *phoneUtils = i18n::phonenumbers::PhoneNumberUtil::GetInstance();
50     if (phoneUtils == nullptr) {
51         TELEPHONY_LOGE("phoneUtils is nullptr");
52         return TELEPHONY_ERR_LOCAL_PTR_NULL;
53     }
54     std::string tmpCode = countryCode;
55     transform(tmpCode.begin(), tmpCode.end(), tmpCode.begin(), ::toupper);
56     i18n::phonenumbers::PhoneNumber parseResult;
57     phoneUtils->ParseAndKeepRawInput(phoneNumber, tmpCode, &parseResult);
58     phoneUtils->FormatInOriginalFormat(parseResult, tmpCode, &formatNumber);
59     if (formatNumber.empty() || formatNumber == "0") {
60         formatNumber = "";
61     }
62     return TELEPHONY_SUCCESS;
63 }
64 
FormatPhoneNumberToE164(const std::string phoneNumber,const std::string countryCode,std::string & formatNumber)65 int32_t CallNumberUtils::FormatPhoneNumberToE164(
66     const std::string phoneNumber, const std::string countryCode, std::string &formatNumber)
67 {
68     return FormatNumberBase(phoneNumber, countryCode, i18n::phonenumbers::PhoneNumberUtil::E164, formatNumber);
69 }
70 
FormatPhoneNumberToNational(const std::string phoneNumber,const std::string countryCode,std::string & formatNumber)71 int32_t CallNumberUtils::FormatPhoneNumberToNational(
72     const std::string phoneNumber, const std::string countryCode, std::string &formatNumber)
73 {
74     int32_t ret = FormatNumberBase(phoneNumber, countryCode,
75         i18n::phonenumbers::PhoneNumberUtil::PhoneNumberFormat::NATIONAL, formatNumber);
76     ProcessSpace(formatNumber);
77     return ret;
78 }
79 
FormatPhoneNumberToInternational(const std::string phoneNumber,const std::string countryCode,std::string & formatNumber)80 int32_t CallNumberUtils::FormatPhoneNumberToInternational(
81     const std::string phoneNumber, const std::string countryCode, std::string &formatNumber)
82 {
83     int32_t ret = FormatNumberBase(phoneNumber, countryCode,
84         i18n::phonenumbers::PhoneNumberUtil::PhoneNumberFormat::INTERNATIONAL, formatNumber);
85     ProcessSpace(formatNumber);
86     return ret;
87 }
88 
FormatNumberBase(const std::string phoneNumber,std::string countryCode,const i18n::phonenumbers::PhoneNumberUtil::PhoneNumberFormat formatInfo,std::string & formatNumber)89 int32_t CallNumberUtils::FormatNumberBase(const std::string phoneNumber, std::string countryCode,
90     const i18n::phonenumbers::PhoneNumberUtil::PhoneNumberFormat formatInfo, std::string &formatNumber)
91 {
92     if (phoneNumber.empty()) {
93         TELEPHONY_LOGE("phoneNumber is nullptr!");
94         return TELEPHONY_ERR_ARGUMENT_INVALID;
95     }
96     i18n::phonenumbers::PhoneNumberUtil *phoneUtils = i18n::phonenumbers::PhoneNumberUtil::GetInstance();
97     if (phoneUtils == nullptr) {
98         TELEPHONY_LOGE("phoneUtils is nullptr");
99         return TELEPHONY_ERR_LOCAL_PTR_NULL;
100     }
101     transform(countryCode.begin(), countryCode.end(), countryCode.begin(), ::toupper);
102     i18n::phonenumbers::PhoneNumber parseResult;
103     phoneUtils->Parse(phoneNumber, countryCode, &parseResult);
104     if (phoneUtils->IsValidNumber(parseResult) || HasBCPhoneNumber(phoneNumber)) {
105         phoneUtils->Format(parseResult, formatInfo, &formatNumber);
106     }
107     return TELEPHONY_SUCCESS;
108 }
109 
FormatPhoneNumberAsYouType(const std::string & phoneNumber,const std::string & countryCode,std::string & formatNumber)110 int32_t CallNumberUtils::FormatPhoneNumberAsYouType(
111     const std::string &phoneNumber, const std::string &countryCode, std::string &formatNumber)
112 {
113     if (phoneNumber.empty()) {
114         TELEPHONY_LOGE("phoneNumber is nullptr!");
115         return TELEPHONY_ERR_ARGUMENT_INVALID;
116     }
117     if (phoneNumber.front() == '#' || phoneNumber.front() == '*') {
118         formatNumber = phoneNumber;
119         return TELEPHONY_SUCCESS;
120     }
121     i18n::phonenumbers::PhoneNumberUtil *phoneUtils = i18n::phonenumbers::PhoneNumberUtil::GetInstance();
122     if (phoneUtils == nullptr) {
123         TELEPHONY_LOGE("phoneUtils is nullptr");
124         return TELEPHONY_ERR_LOCAL_PTR_NULL;
125     }
126     std::string tmpCode = countryCode;
127     transform(tmpCode.begin(), tmpCode.end(), tmpCode.begin(), ::toupper);
128     std::unique_ptr<i18n::phonenumbers::AsYouTypeFormatter> formatter(phoneUtils->GetAsYouTypeFormatter(tmpCode));
129     if (formatter == nullptr) {
130         TELEPHONY_LOGE("formatter is nullptr");
131         return TELEPHONY_ERR_LOCAL_PTR_NULL;
132     }
133     formatter->Clear();
134     std::string result;
135     for (size_t i = 0; i < phoneNumber.length(); i++) {
136         char c = phoneNumber.at(i);
137         formatNumber = formatter->InputDigit(c, &result);
138     }
139     if (formatNumber.empty() || formatNumber == "0") {
140         formatNumber = "";
141     }
142     return TELEPHONY_SUCCESS;
143 }
144 
ProcessSpace(std::string & number)145 void CallNumberUtils::ProcessSpace(std::string &number)
146 {
147     std::string word;
148     std::stringstream streamNum(number);
149     std::string store;
150     while (streamNum >> word) {
151         store += word;
152     }
153     number = store;
154 }
155 
CheckNumberIsEmergency(const std::string & phoneNumber,const int32_t slotId,bool & enabled)156 int32_t CallNumberUtils::CheckNumberIsEmergency(const std::string &phoneNumber, const int32_t slotId, bool &enabled)
157 {
158     return DelayedSingleton<CellularCallConnection>::GetInstance()->IsEmergencyPhoneNumber(
159         phoneNumber, slotId, enabled);
160 }
161 
IsValidSlotId(int32_t slotId) const162 bool CallNumberUtils::IsValidSlotId(int32_t slotId) const
163 {
164     if (SIM_SLOT_COUNT == HAS_A_SLOT) {
165         return slotId == SIM_SLOT_0;
166     }
167     if (SIM_SLOT_COUNT == HAS_TWO_SLOT) {
168         if (slotId == SIM_SLOT_0 || slotId == SIM_SLOT_1) {
169             return true;
170         }
171     }
172     return false;
173 }
174 
IsMMICode(const std::string & number)175 bool CallNumberUtils::IsMMICode(const std::string &number)
176 {
177     if (number.empty()) {
178         TELEPHONY_LOGE("number is empty.");
179         return false;
180     }
181     if (RegexMatchMmi(number)) {
182         return true;
183     }
184 
185     if ((number.front() == '*' || number.front() == '#') && number.back() == '#') {
186         TELEPHONY_LOGI("number start with * or # and end with #");
187         return true;
188     }
189 
190     return false;
191 }
192 
RegexMatchMmi(const std::string & number)193 bool CallNumberUtils::RegexMatchMmi(const std::string &number)
194 {
195     std::string symbols =
196         "((\\*|#|\\*#|\\*\\*|##)(\\d{2,3})(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*))?)?)?)?#)(.*)";
197     std::regex pattern(symbols);
198     std::smatch results;
199     if (regex_match(number, results, pattern)) {
200         TELEPHONY_LOGI("regex_match ture");
201         return true;
202     }
203     return false;
204 }
205 
RemoveSeparatorsPhoneNumber(const std::string & phoneString)206 std::string CallNumberUtils::RemoveSeparatorsPhoneNumber(const std::string &phoneString)
207 {
208     std::string newString;
209     if (phoneString.empty()) {
210         TELEPHONY_LOGE("RemoveSeparatorsPhoneNumber return, phoneStr is empty.");
211         return newString;
212     }
213     for (char c : phoneString) {
214         if ((c >= '0' && c <= '9') || c == '*' || c == '#' || c == '+' || c == 'N' || c == ',' || c == ';') {
215             newString += c;
216         }
217     }
218 
219     return newString;
220 }
221 
RemovePostDialPhoneNumber(const std::string & phoneString)222 std::string CallNumberUtils::RemovePostDialPhoneNumber(const std::string &phoneString)
223 {
224     std::string newString = "";
225     if (phoneString.empty()) {
226         TELEPHONY_LOGE("RemovePostDialPhoneNumber return, phoneStr is empty.");
227         return newString;
228     }
229     for (char c : phoneString) {
230         if ((c >= '0' && c <= '9') || c == '*' || c == '#' || c == '+' || c == 'N') {
231             newString += c;
232         } else if (c == ',' || c == ';') {
233             break;
234         }
235     }
236 
237     return newString;
238 }
239 
HasBCPhoneNumber(const std::string & phoneNumber)240 bool CallNumberUtils::HasBCPhoneNumber(const std::string &phoneNumber)
241 {
242     int32_t phoneNumberStart = 0;
243     int32_t phoneNumberStartLength = 3;
244     size_t bCNumberLength = 11;
245     std::string bCNumberStart = "192";
246     if (phoneNumber.length() == bCNumberLength &&
247         phoneNumber.substr(phoneNumberStart, phoneNumberStartLength) == bCNumberStart) {
248         return true;
249     }
250     return false;
251 }
252 
SelectAccountId(int32_t slotId,AppExecFwk::PacMap & extras)253 bool CallNumberUtils::SelectAccountId(int32_t slotId, AppExecFwk::PacMap &extras)
254 {
255     if (IsValidSlotId(slotId)) {
256         return true;
257     }
258     int32_t defaultVoiceSlotId = DelayedRefSingleton<CoreServiceClient>::GetInstance().GetDefaultVoiceSlotId();
259     if (defaultVoiceSlotId != TELEPHONY_ERR_IPC_CONNECT_STUB_FAIL && IsValidSlotId(defaultVoiceSlotId)) {
260         extras.PutIntValue("accountId", defaultVoiceSlotId);
261         TELEPHONY_LOGI("select accountId to defaultVoiceSlotId = %{public}d", defaultVoiceSlotId);
262         return true;
263     }
264 #ifdef CELLULAR_DATA_SUPPORT
265     int32_t defaultDataSlotId = DelayedRefSingleton<CellularDataClient>::GetInstance().GetDefaultCellularDataSlotId();
266     if (defaultDataSlotId != TELEPHONY_ERR_IPC_CONNECT_STUB_FAIL && IsValidSlotId(defaultDataSlotId)) {
267         extras.PutIntValue("accountId", defaultDataSlotId);
268         TELEPHONY_LOGI("select accountId to defaultDataSlotId = %{public}d", defaultDataSlotId);
269         return true;
270     }
271 #endif
272     return false;
273 }
274 
QueryNumberLocationInfo(std::string & numberLocation,std::string accountNumber)275 int32_t CallNumberUtils::QueryNumberLocationInfo(std::string &numberLocation, std::string accountNumber)
276 {
277     TELEPHONY_LOGI("QueryNumberLocationInfo");
278     if (accountNumber == "") {
279         TELEPHONY_LOGE("accountNumber is null");
280         return TELEPHONY_ERR_ARGUMENT_INVALID;
281     }
282     std::shared_ptr<NumberIdentityDataBaseHelper> callDataPtr =
283         DelayedSingleton<NumberIdentityDataBaseHelper>::GetInstance();
284     if (callDataPtr == nullptr) {
285         TELEPHONY_LOGE("callDataPtr is nullptr!");
286         return TELEPHONY_ERR_LOCAL_PTR_NULL;
287     }
288 
289     DataShare::DataSharePredicates predicates;
290     std::vector<std::string> phoneNumber;
291     phoneNumber.push_back(accountNumber);
292     predicates.SetWhereArgs(phoneNumber);
293     bool ret = callDataPtr->Query(numberLocation, predicates);
294     if (!ret) {
295         TELEPHONY_LOGE("Query number location database fail!");
296         return TELEPHONY_ERR_DATABASE_READ_FAIL;
297     }
298     return TELEPHONY_SUCCESS;
299 }
300 
NumberLocationUpdate(const sptr<CallBase> & callObjectPtr)301 void CallNumberUtils::NumberLocationUpdate(const sptr<CallBase> &callObjectPtr)
302 {
303     CallAttributeInfo info;
304     callObjectPtr->GetCallAttributeBaseInfo(info);
305     TELEPHONY_LOGI("NumberLocationUpdate, callId[%{public}d]", info.callId);
306     std::string numberLocation = callObjectPtr->GetNumberLocation();
307     int32_t ret = QueryNumberLocationInfo(numberLocation, callObjectPtr->GetAccountNumber());
308     if (ret != TELEPHONY_SUCCESS) {
309         return;
310     }
311     sptr<CallBase> call = callObjectPtr;
312     if (info.callState == TelCallState::CALL_STATUS_DIALING) {
313         call = CallObjectManager::GetOneCallObject(info.callId);
314         if (call == nullptr) {
315             TELEPHONY_LOGE("call is nullptr");
316             return;
317         }
318     }
319     call->SetNumberLocation(numberLocation);
320     CallVoiceAssistantManager::GetInstance()->UpdateNumberLocation(numberLocation, info.callId);
321     if (!CallObjectManager::IsCallExist(info.callId)) {
322         TELEPHONY_LOGE("call is not exist");
323         return;
324     }
325     if (numberLocation != "" && numberLocation != "default") {
326         TELEPHONY_LOGI("need report call info of numberLocation");
327         call->GetCallAttributeBaseInfo(info);
328         DelayedSingleton<CallAbilityReportProxy>::GetInstance()->ReportCallStateInfo(info);
329     }
330 }
331 
YellowPageAndMarkUpdate(const sptr<CallBase> & callObjectPtr)332 void CallNumberUtils::YellowPageAndMarkUpdate(const sptr<CallBase> &callObjectPtr)
333 {
334     CallAttributeInfo info;
335     callObjectPtr->GetCallAttributeBaseInfo(info);
336     TELEPHONY_LOGI("YellowPageAndMarkUpdate, callId[%{public}d]", info.callId);
337     NumberMarkInfo numberMarkInfo;
338     int32_t ret = QueryYellowPageAndMarkInfo(numberMarkInfo, callObjectPtr->GetAccountNumber());
339     if (ret != TELEPHONY_SUCCESS) {
340         return;
341     }
342     sptr<CallBase> call = callObjectPtr;
343     if (info.callState == TelCallState::CALL_STATUS_DIALING) {
344         call = CallObjectManager::GetOneCallObject(info.callId);
345         if (call == nullptr) {
346             TELEPHONY_LOGE("call is nullptr");
347             return;
348         }
349     }
350     call->SetNumberMarkInfo(numberMarkInfo);
351     if (!CallObjectManager::IsCallExist(info.callId)) {
352         TELEPHONY_LOGE("call is not exist");
353         return;
354     }
355     if (numberMarkInfo.markType != MarkType::MARK_TYPE_NONE) {
356         call->GetCallAttributeBaseInfo(info);
357         DelayedSingleton<CallAbilityReportProxy>::GetInstance()->ReportCallStateInfo(info);
358     }
359 }
360 
QueryYellowPageAndMarkInfo(NumberMarkInfo & numberMarkInfo,std::string accountNumber)361 int32_t CallNumberUtils::QueryYellowPageAndMarkInfo(NumberMarkInfo &numberMarkInfo, std::string accountNumber)
362 {
363     TELEPHONY_LOGI("QueryYellowPageAndMarkInfo");
364     if (accountNumber == "") {
365         TELEPHONY_LOGE("accountNumber is null");
366         return TELEPHONY_ERR_ARGUMENT_INVALID;
367     }
368     std::shared_ptr<NumberIdentityDataBaseHelper> callDataPtr =
369         DelayedSingleton<NumberIdentityDataBaseHelper>::GetInstance();
370     if (callDataPtr == nullptr) {
371         TELEPHONY_LOGE("callDataPtr is nullptr!");
372         return TELEPHONY_ERR_LOCAL_PTR_NULL;
373     }
374 
375     DataShare::DataSharePredicates predicates;
376     std::vector<std::string> phoneNumber;
377     phoneNumber.push_back(accountNumber);
378     predicates.SetWhereArgs(phoneNumber);
379     bool ret = callDataPtr->QueryYellowPageAndMark(numberMarkInfo, predicates);
380     if (!ret) {
381         TELEPHONY_LOGE("Query yellow page and mark fail!");
382         return TELEPHONY_ERR_DATABASE_READ_FAIL;
383     }
384     return TELEPHONY_SUCCESS;
385 }
386 } // namespace Telephony
387 } // namespace OHOS
388