1/* 2 * Copyright (C) 2021-2023 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 "sms_misc_manager.h" 17 18#include "core_manager_inner.h" 19#include "short_message.h" 20#include "sms_mms_errors.h" 21#include "string_utils.h" 22#include "telephony_common_utils.h" 23#include "telephony_log_wrapper.h" 24 25namespace OHOS { 26namespace Telephony { 27static constexpr int32_t WAIT_TIME_SECOND = 1; 28static constexpr int32_t TIME_OUT_SECOND = 3; 29static constexpr uint8_t GSM_TYPE = 1; 30static constexpr uint8_t MIN_SMSC_LEN = 2; 31static constexpr uint32_t RANG_MAX = 65535; 32bool SmsMiscManager::hasGotCbRange_ = false; 33 34SmsMiscManager::SmsMiscManager(int32_t slotId) : TelEventHandler("SmsMiscManager"), slotId_(slotId) {} 35 36int32_t SmsMiscManager::SetCBConfig(bool enable, uint32_t fromMsgId, uint32_t toMsgId, uint8_t netType) 37{ 38 bool ret = false; 39 if ((toMsgId > RANG_MAX) || (fromMsgId > toMsgId) || (netType != GSM_TYPE)) { 40 TELEPHONY_LOGI("cb channel invalid"); 41 return TELEPHONY_ERR_ARGUMENT_INVALID; 42 } 43 std::unique_lock<std::mutex> lock(cbMutex_); 44 if (!hasGotCbRange_) { 45 GetModemCBRange(); 46 if (mdRangeList_.size() != 0) { 47 if (!SendDataToRil(false, mdRangeList_)) { 48 return TELEPHONY_ERR_RIL_CMD_FAIL; 49 } 50 mdRangeList_.clear(); 51 } 52 } 53 std::list<gsmCBRangeInfo> oldRangeList = rangeList_; 54 if (enable) { 55 ret = OpenCBRange(fromMsgId, toMsgId); 56 } else { 57 ret = CloseCBRange(fromMsgId, toMsgId); 58 } 59 if (ret) { 60 if (!SendDataToRil(false, oldRangeList)) { 61 rangeList_ = oldRangeList; 62 return TELEPHONY_ERR_RIL_CMD_FAIL; 63 } 64 if (!SendDataToRil(true, rangeList_)) { 65 rangeList_ = oldRangeList; 66 return TELEPHONY_ERR_RIL_CMD_FAIL; 67 } 68 } else { 69 rangeList_ = oldRangeList; 70 } 71 return TELEPHONY_ERR_SUCCESS; 72} 73 74std::list<SmsMiscManager::gsmCBRangeInfo> SmsMiscManager::GetRangeInfo() const 75{ 76 return rangeList_; 77} 78 79// from 3GPP TS 27.005 3.3.4 Select Cell Broadcast Message Types 80bool SmsMiscManager::OpenCBRange(uint32_t fromMsgId, uint32_t toMsgId) 81{ 82 infoData data(fromMsgId, toMsgId); 83 rangeList_.emplace_back(fromMsgId, toMsgId); 84 CombineCBRange(); 85 return true; 86} 87 88void SmsMiscManager::SplitMsgId( 89 uint32_t fromMsgId, uint32_t toMsgId, const std::list<gsmCBRangeInfo>::iterator &oldIter) 90{ 91 auto &info = *oldIter; 92 if (fromMsgId == UINT32_MAX || fromMsgId < 1) { 93 return; 94 } 95 rangeList_.emplace_back(info.fromMsgId, fromMsgId - 1); 96 rangeList_.emplace_back(toMsgId + 1, info.toMsgId); 97 rangeList_.erase(oldIter); 98} 99 100// from 3GPP TS 27.005 3.3.4 Select Cell Broadcast Message Types 101bool SmsMiscManager::CloseCBRange(uint32_t fromMsgId, uint32_t toMsgId) 102{ 103 if (fromMsgId == UINT32_MAX || fromMsgId < 1) { 104 return false; 105 } 106 107 auto iter = rangeList_.begin(); 108 while (iter != rangeList_.end()) { 109 auto oldIter = iter++; 110 auto &info = *oldIter; 111 if (fromMsgId == info.fromMsgId && toMsgId == info.toMsgId) { 112 rangeList_.erase(oldIter); 113 continue; 114 } else if (fromMsgId == info.fromMsgId && toMsgId > info.toMsgId) { 115 rangeList_.erase(oldIter); 116 continue; 117 } else if (fromMsgId == info.fromMsgId && toMsgId < info.toMsgId) { 118 rangeList_.emplace_back(toMsgId + 1, info.toMsgId); 119 rangeList_.erase(oldIter); 120 continue; 121 } else if (fromMsgId < info.fromMsgId && toMsgId == info.toMsgId) { 122 rangeList_.erase(oldIter); 123 continue; 124 } else if (fromMsgId > info.fromMsgId && toMsgId == info.toMsgId) { 125 rangeList_.emplace_back(info.fromMsgId, fromMsgId - 1); 126 rangeList_.erase(oldIter); 127 continue; 128 } else if (fromMsgId > info.fromMsgId && toMsgId < info.toMsgId) { 129 SplitMsgId(fromMsgId, toMsgId, oldIter); 130 continue; 131 } else if (fromMsgId > info.fromMsgId && fromMsgId <= info.toMsgId) { 132 rangeList_.emplace_back(info.fromMsgId, fromMsgId - 1); 133 rangeList_.erase(oldIter); 134 continue; 135 } else if (fromMsgId < info.fromMsgId && toMsgId > info.toMsgId) { 136 rangeList_.erase(oldIter); 137 continue; 138 } else if (toMsgId < info.toMsgId && toMsgId >= info.fromMsgId) { 139 rangeList_.emplace_back(toMsgId + 1, info.toMsgId); 140 rangeList_.erase(oldIter); 141 continue; 142 } 143 } 144 CombineCBRange(); 145 return true; 146} 147 148void SmsMiscManager::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event) 149{ 150 if (event == nullptr) { 151 TELEPHONY_LOGE("SmsMiscManager ProcessEvent event == nullptr"); 152 return; 153 } 154 155 uint32_t eventId = 0; 156 eventId = event->GetInnerEventId(); 157 switch (eventId) { 158 case SET_CB_CONFIG_FINISH: { 159 TELEPHONY_LOGD("SmsMiscManager::ProcessEvent Set cb config finish"); 160 isSuccess_ = true; 161 std::shared_ptr<RadioResponseInfo> res = event->GetSharedObject<RadioResponseInfo>(); 162 if (res != nullptr) { 163 isSuccess_ = (res->error == ErrType::NONE); 164 } 165 NotifyHasResponse(); 166 break; 167 } 168 case GET_CB_CONFIG_FINISH: { 169 TELEPHONY_LOGI("SmsMiscManager::ProcessEvent Get cb config finish"); 170 GetCBConfigFinish(event); 171 break; 172 } 173 case SET_SMSC_ADDR_FINISH: { 174 TELEPHONY_LOGI("SmsMiscManager::ProcessEvent Set smsc addr finish"); 175 isSuccess_ = true; 176 std::shared_ptr<RadioResponseInfo> res = event->GetSharedObject<RadioResponseInfo>(); 177 if (res != nullptr) { 178 isSuccess_ = (res->error == ErrType::NONE); 179 } 180 NotifyHasResponse(); 181 break; 182 } 183 case GET_SMSC_ADDR_FINISH: { 184 TELEPHONY_LOGI("SmsMiscManager::ProcessEvent Get smsc addr finish"); 185 isSuccess_ = true; 186 std::shared_ptr<ServiceCenterAddress> addr = event->GetSharedObject<ServiceCenterAddress>(); 187 if (addr != nullptr) { 188 smscAddr_ = addr->address; 189 } 190 NotifyHasResponse(); 191 break; 192 } 193 default: 194 TELEPHONY_LOGI("SmsMiscManager::ProcessEvent default!"); 195 break; 196 } 197} 198 199void SmsMiscManager::GetCBConfigFinish(const AppExecFwk::InnerEvent::Pointer &event) 200{ 201 isSuccess_ = true; 202 std::shared_ptr<CBConfigInfo> res = event->GetSharedObject<CBConfigInfo>(); 203 if (res == nullptr) { 204 isSuccess_ = false; 205 } else { 206 UpdateCbRangList(res); 207 } 208 NotifyHasResponse(); 209} 210 211bool SmsMiscManager::IsEmpty() const 212{ 213 return rangeList_.empty(); 214} 215 216void SmsMiscManager::NotifyHasResponse() 217{ 218 std::unique_lock<std::mutex> lock(mutex_); 219 if (fairList_.size() > 0) { 220 fairVar_ = fairList_.front(); 221 fairList_.pop_front(); 222 } else { 223 return; 224 } 225 condVar_.notify_all(); 226} 227 228void SmsMiscManager::UpdateCbRangList(std::shared_ptr<CBConfigInfo> res) 229{ 230 mdRangeList_.clear(); 231 if (res->mids.empty()) { 232 return; 233 } 234 std::vector<std::string> dest; 235 SplitMids(res->mids, dest, ","); 236 for (auto v : dest) { 237 std::string start; 238 std::string end; 239 if (!SplitMidValue(v, start, end, "-")) { 240 continue; 241 } 242 if (!IsValidDecValue(start) || !IsValidDecValue(end)) { 243 TELEPHONY_LOGE("start or end not decimal"); 244 return; 245 } 246 if (std::stoi(start) <= std::stoi(end)) { 247 infoData data(std::stoi(start), std::stoi(end)); 248 mdRangeList_.emplace_back(data.startPos, data.endPos); 249 } 250 } 251 rangeList_ = mdRangeList_; 252 CombineCBRange(); 253} 254 255void SmsMiscManager::CombineCBRange() 256{ 257 rangeList_.sort(); 258 rangeList_.unique(); 259 auto iter = rangeList_.begin(); 260 while (iter != rangeList_.end()) { 261 auto OtherIter = iter; 262 OtherIter++; 263 bool eraseFlag = false; 264 while (OtherIter != rangeList_.end()) { 265 if (OtherIter->fromMsgId == iter->fromMsgId) { 266 eraseFlag = true; 267 break; 268 } else if (OtherIter->toMsgId <= iter->toMsgId) { 269 OtherIter = rangeList_.erase(OtherIter); 270 continue; 271 } else if (OtherIter->fromMsgId <= static_cast<uint32_t>(iter->toMsgId + 1)) { 272 iter->toMsgId = OtherIter->toMsgId; 273 OtherIter = rangeList_.erase(OtherIter); 274 continue; 275 } 276 OtherIter++; 277 } 278 if (eraseFlag) { 279 iter = rangeList_.erase(iter); 280 } else { 281 iter++; 282 } 283 } 284} 285 286void SmsMiscManager::SplitMids(std::string src, std::vector<std::string> &dest, const std::string delimiter) 287{ 288 size_t pos = src.find(delimiter); 289 while (pos != std::string::npos) { 290 dest.push_back(src.substr(0, pos)); 291 src.erase(0, pos + delimiter.length()); 292 pos = src.find(delimiter); 293 } 294 dest.push_back(src); 295} 296 297bool SmsMiscManager::SplitMidValue(std::string value, std::string &start, std::string &end, const std::string delimiter) 298{ 299 if (value.empty()) { 300 return false; 301 } 302 size_t pos = value.find(delimiter); 303 if (value.size() == 0) { 304 return false; 305 } 306 if (pos == 0 || pos == value.size() - 1) { 307 return false; 308 } else if (pos == std::string::npos) { 309 start = value; 310 end = value; 311 return true; 312 } 313 start = value.substr(0, pos); 314 end = value.substr(pos + 1); 315 return true; 316} 317 318std::string SmsMiscManager::RangeListToString(const std::list<gsmCBRangeInfo> rangeList) 319{ 320 std::string ret; 321 bool isFirst = true; 322 for (const auto &item : rangeList) { 323 if (isFirst) { 324 isFirst = false; 325 } else { 326 ret += ","; 327 } 328 if (item.fromMsgId == item.toMsgId) { 329 ret += std::to_string(item.fromMsgId); 330 } else { 331 ret += std::to_string(item.fromMsgId) + "-" + std::to_string(item.toMsgId); 332 } 333 } 334 return ret; 335} 336 337bool SmsMiscManager::SendDataToRil(bool enable, std::list<gsmCBRangeInfo> list) 338{ 339 TELEPHONY_LOGI("enable CB channel:%{public}d", enable); 340 for (auto item : list) { 341 TELEPHONY_LOGD("[%{public}d-%{public}d]", item.fromMsgId, item.toMsgId); 342 } 343 std::unique_lock<std::mutex> lock(mutex_); 344 if (!list.empty()) { 345 isSuccess_ = false; 346 int32_t condition = conditonVar_++; 347 fairList_.push_back(condition); 348 CBConfigParam cbData; 349 cbData.mode = enable ? 1 : 0; 350 cbData.idList = RangeListToString(list); 351 cbData.dcsList = codeScheme_; 352 CoreManagerInner::GetInstance().SetCBConfig( 353 slotId_, SmsMiscManager::SET_CB_CONFIG_FINISH, cbData, shared_from_this()); 354 while (!isSuccess_) { 355 TELEPHONY_LOGD("SendDataToRil::wait(), isSuccess_ = false"); 356 if (condVar_.wait_for(lock, std::chrono::seconds(WAIT_TIME_SECOND)) == std::cv_status::timeout) { 357 break; 358 } 359 } 360 return isSuccess_; 361 } else { 362 return true; 363 } 364} 365 366void SmsMiscManager::GetModemCBRange() 367{ 368 std::unique_lock<std::mutex> lock(mutex_); 369 if (!hasGotCbRange_) { 370 isSuccess_ = false; 371 int32_t condition = conditonVar_++; 372 fairList_.push_back(condition); 373 CoreManagerInner::GetInstance().GetCBConfig(slotId_, SmsMiscManager::GET_CB_CONFIG_FINISH, shared_from_this()); 374 while (!isSuccess_) { 375 TELEPHONY_LOGI("GetCBConfig::wait(), isSuccess_ = false"); 376 if (condVar_.wait_for(lock, std::chrono::seconds(WAIT_TIME_SECOND)) == std::cv_status::timeout) { 377 break; 378 } 379 } 380 hasGotCbRange_ = true; 381 } 382} 383 384int32_t SmsMiscManager::AddSimMessage( 385 const std::string &smsc, const std::string &pdu, ISmsServiceInterface::SimMessageStatus status) 386{ 387 std::vector<ShortMessage> message; 388 int32_t result = GetAllSimMessages(message); 389 if (result != TELEPHONY_ERR_SUCCESS) { 390 TELEPHONY_LOGE("SmsMiscManager::AddSimMessage get result fail"); 391 return result; 392 } 393 int32_t smsCountCurrent = static_cast<int32_t>(message.size()); 394 TELEPHONY_LOGI("smsCountCurrent = %{public}d smsCapacityOfSim_ = %{public}d", smsCountCurrent, smsCapacityOfSim_); 395 if (smsCountCurrent >= smsCapacityOfSim_) { 396 TELEPHONY_LOGE("AddSimMessage sim card is full"); 397 return TELEPHONY_ERR_FAIL; 398 } 399 400 TELEPHONY_LOGI("smscLen = %{public}zu pudLen = %{public}zu status = %{public}d", smsc.size(), pdu.size(), status); 401 std::string smscAddr(smsc); 402 if (smsc.length() <= MIN_SMSC_LEN) { 403 smscAddr.clear(); 404 smscAddr.insert(0, "00"); 405 } 406 TELEPHONY_LOGD("smscAddr = %{private}s", smscAddr.c_str()); 407 return CoreManagerInner::GetInstance().AddSmsToIcc( 408 slotId_, static_cast<int>(status), const_cast<std::string &>(pdu), smscAddr); 409} 410 411int32_t SmsMiscManager::DelSimMessage(uint32_t msgIndex) 412{ 413 TELEPHONY_LOGI("messageIndex = %{public}d", msgIndex); 414 bool hasSimCard = false; 415 CoreManagerInner::GetInstance().HasSimCard(slotId_, hasSimCard); 416 if (!hasSimCard) { 417 TELEPHONY_LOGE("no sim card"); 418 return TELEPHONY_ERR_SLOTID_INVALID; 419 } 420 return CoreManagerInner::GetInstance().DelSmsIcc(slotId_, msgIndex); 421} 422 423int32_t SmsMiscManager::UpdateSimMessage(uint32_t msgIndex, ISmsServiceInterface::SimMessageStatus newStatus, 424 const std::string &pdu, const std::string &smsc) 425{ 426 std::string smscAddr(smsc); 427 if (smsc.length() <= MIN_SMSC_LEN) { 428 smscAddr.clear(); 429 smscAddr.insert(0, "00"); 430 } 431 return CoreManagerInner::GetInstance().UpdateSmsIcc( 432 slotId_, msgIndex, static_cast<int>(newStatus), const_cast<std::string &>(pdu), smscAddr); 433} 434 435int32_t SmsMiscManager::GetAllSimMessages(std::vector<ShortMessage> &message) 436{ 437 bool hasSimCard = false; 438 CoreManagerInner::GetInstance().HasSimCard(slotId_, hasSimCard); 439 if (!hasSimCard) { 440 TELEPHONY_LOGE("no sim card"); 441 return TELEPHONY_ERR_SLOTID_INVALID; 442 } 443 std::vector<std::string> pdus = CoreManagerInner::GetInstance().ObtainAllSmsOfIcc(slotId_); 444 smsCapacityOfSim_ = static_cast<int32_t>(pdus.size()); 445 TELEPHONY_LOGI("smsCapacityOfSim_[%{public}d]", smsCapacityOfSim_); 446 int index = 1; 447 PhoneType type = CoreManagerInner::GetInstance().GetPhoneType(slotId_); 448 std::string specification; 449 if (PhoneType::PHONE_TYPE_IS_GSM == type) { 450 specification = "3gpp"; 451 } else if (PhoneType::PHONE_TYPE_IS_CDMA == type) { 452 specification = "3gpp2"; 453 } else { 454 return TELEPHONY_ERR_UNKNOWN_NETWORK_TYPE; 455 } 456 for (auto &v : pdus) { 457 v = v.substr(0, v.find("FFFFF")); 458 if (v.compare("00") == 0) { 459 index++; 460 continue; 461 } 462 std::vector<unsigned char> pdu = StringUtils::HexToByteVector(v); 463 ShortMessage item = ShortMessage::CreateIccMessage(pdu, specification, index); 464 if (item.GetIccMessageStatus() != ShortMessage::SMS_SIM_MESSAGE_STATUS_FREE) { 465 message.emplace_back(item); 466 } 467 index++; 468 } 469 return TELEPHONY_ERR_SUCCESS; 470} 471 472int32_t SmsMiscManager::SetSmscAddr(const std::string &scAddr) 473{ 474 TELEPHONY_LOGI("SmsMiscManager::SetSmscAddr [%{private}s]", scAddr.c_str()); 475 std::unique_lock<std::mutex> lock(mutex_); 476 isSuccess_ = false; 477 int32_t condition = conditonVar_++; 478 fairList_.push_back(condition); 479 CoreManagerInner::GetInstance().SetSmscAddr( 480 slotId_, SmsMiscManager::SET_SMSC_ADDR_FINISH, 0, scAddr, shared_from_this()); 481 while (!isSuccess_) { 482 TELEPHONY_LOGI("SetSmscAddr::wait(), isSuccess_ = false"); 483 if (condVar_.wait_for(lock, std::chrono::seconds(TIME_OUT_SECOND)) == std::cv_status::timeout) { 484 break; 485 } 486 } 487 488 if (isSuccess_ == false) { 489 return TELEPHONY_ERR_RIL_CMD_FAIL; 490 } 491 return TELEPHONY_ERR_SUCCESS; 492} 493 494int32_t SmsMiscManager::GetSmscAddr(std::u16string &smscAddress) 495{ 496 TELEPHONY_LOGI("SmsMiscManager::GetSmscAddr"); 497 std::unique_lock<std::mutex> lock(mutex_); 498 smscAddr_.clear(); 499 isSuccess_ = false; 500 int32_t condition = conditonVar_++; 501 fairList_.push_back(condition); 502 CoreManagerInner::GetInstance().GetSmscAddr(slotId_, SmsMiscManager::GET_SMSC_ADDR_FINISH, shared_from_this()); 503 while (!isSuccess_) { 504 TELEPHONY_LOGI("GetSmscAddr::wait(), isSuccess_ = false"); 505 if (condVar_.wait_for(lock, std::chrono::seconds(TIME_OUT_SECOND)) == std::cv_status::timeout) { 506 break; 507 } 508 } 509 smscAddress = StringUtils::ToUtf16(smscAddr_); 510 return TELEPHONY_ERR_SUCCESS; 511} 512 513int32_t SmsMiscManager::SetDefaultSmsSlotId(int32_t slotId) 514{ 515 TELEPHONY_LOGI("SetDefaultSmsSlotId slotId = %{public}d", slotId); 516 return CoreManagerInner::GetInstance().SetDefaultSmsSlotId(slotId); 517} 518 519int32_t SmsMiscManager::GetDefaultSmsSlotId() 520{ 521 TELEPHONY_LOGI("GetDefaultSmsSlotId"); 522 return CoreManagerInner::GetInstance().GetDefaultSmsSlotId(); 523} 524 525int32_t SmsMiscManager::GetDefaultSmsSimId(int32_t &simId) 526{ 527 TELEPHONY_LOGI("GetDefaultSmsSimId"); 528 return CoreManagerInner::GetInstance().GetDefaultSmsSimId(simId); 529} 530} // namespace Telephony 531} // namespace OHOS 532