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