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