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
25 namespace OHOS {
26 namespace Telephony {
27 static constexpr int32_t WAIT_TIME_SECOND = 1;
28 static constexpr int32_t TIME_OUT_SECOND = 3;
29 static constexpr uint8_t GSM_TYPE = 1;
30 static constexpr uint8_t MIN_SMSC_LEN = 2;
31 static constexpr uint32_t RANG_MAX = 65535;
32 bool SmsMiscManager::hasGotCbRange_ = false;
33
SmsMiscManager(int32_t slotId)34 SmsMiscManager::SmsMiscManager(int32_t slotId) : TelEventHandler("SmsMiscManager"), slotId_(slotId) {}
35
SetCBConfig(bool enable,uint32_t fromMsgId,uint32_t toMsgId,uint8_t netType)36 int32_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
GetRangeInfo() const74 std::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
OpenCBRange(uint32_t fromMsgId,uint32_t toMsgId)80 bool 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
SplitMsgId(uint32_t fromMsgId,uint32_t toMsgId,const std::list<gsmCBRangeInfo>::iterator & oldIter)88 void 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
CloseCBRange(uint32_t fromMsgId,uint32_t toMsgId)101 bool 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
ProcessEvent(const AppExecFwk::InnerEvent::Pointer & event)148 void 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
GetCBConfigFinish(const AppExecFwk::InnerEvent::Pointer & event)199 void 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
IsEmpty() const211 bool SmsMiscManager::IsEmpty() const
212 {
213 return rangeList_.empty();
214 }
215
NotifyHasResponse()216 void 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
UpdateCbRangList(std::shared_ptr<CBConfigInfo> res)228 void 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
CombineCBRange()255 void 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
SplitMids(std::string src,std::vector<std::string> & dest,const std::string delimiter)286 void 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
SplitMidValue(std::string value,std::string & start,std::string & end,const std::string delimiter)297 bool 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
RangeListToString(const std::list<gsmCBRangeInfo> rangeList)318 std::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
SendDataToRil(bool enable,std::list<gsmCBRangeInfo> list)337 bool 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
GetModemCBRange()366 void 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
AddSimMessage(const std::string & smsc,const std::string & pdu,ISmsServiceInterface::SimMessageStatus status)384 int32_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
DelSimMessage(uint32_t msgIndex)411 int32_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
UpdateSimMessage(uint32_t msgIndex,ISmsServiceInterface::SimMessageStatus newStatus,const std::string & pdu,const std::string & smsc)423 int32_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
GetAllSimMessages(std::vector<ShortMessage> & message)435 int32_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
SetSmscAddr(const std::string & scAddr)472 int32_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
GetSmscAddr(std::u16string & smscAddress)494 int32_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
SetDefaultSmsSlotId(int32_t slotId)513 int32_t SmsMiscManager::SetDefaultSmsSlotId(int32_t slotId)
514 {
515 TELEPHONY_LOGI("SetDefaultSmsSlotId slotId = %{public}d", slotId);
516 return CoreManagerInner::GetInstance().SetDefaultSmsSlotId(slotId);
517 }
518
GetDefaultSmsSlotId()519 int32_t SmsMiscManager::GetDefaultSmsSlotId()
520 {
521 TELEPHONY_LOGI("GetDefaultSmsSlotId");
522 return CoreManagerInner::GetInstance().GetDefaultSmsSlotId();
523 }
524
GetDefaultSmsSimId(int32_t & simId)525 int32_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