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