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 "gsm_sms_cb_handler.h"
17 
18 #include "cb_start_ability.h"
19 #include "common_event_support.h"
20 #include "core_manager_inner.h"
21 #include "radio_event.h"
22 #include "securec.h"
23 #include "singleton.h"
24 #include "sms_hisysevent.h"
25 #include "string_utils.h"
26 #include "telephony_log_wrapper.h"
27 #include "telephony_permission.h"
28 
29 namespace OHOS {
30 namespace Telephony {
31 using namespace OHOS::EventFwk;
GsmSmsCbHandler(int32_t slotId)32 GsmSmsCbHandler::GsmSmsCbHandler(int32_t slotId) : TelEventHandler("GsmSmsCbHandler"), slotId_(slotId)
33 {
34     TELEPHONY_LOGI("GsmSmsCbHandler Create slotId (%{public}d)", slotId_);
35 }
36 
Init()37 void GsmSmsCbHandler::Init()
38 {
39     cbMsgList_.clear();
40     CoreManagerInner::GetInstance().RegisterCoreNotify(
41         slotId_, shared_from_this(), RadioEvent::RADIO_CELL_BROADCAST, nullptr);
42     TELEPHONY_LOGI("GsmSmsCbHandler::RegisterHandler::slotId= %{public}d", slotId_);
43 }
44 
UnRegisterHandler()45 void GsmSmsCbHandler::UnRegisterHandler()
46 {
47     CoreManagerInner::GetInstance().UnRegisterCoreNotify(slotId_, shared_from_this(), RadioEvent::RADIO_CELL_BROADCAST);
48 }
49 
CheckCbActive(const std::shared_ptr<GsmCbCodec> & cbMessage)50 bool GsmSmsCbHandler::CheckCbActive(const std::shared_ptr<GsmCbCodec> &cbMessage)
51 {
52     if (cbMessage == nullptr) {
53         TELEPHONY_LOGE("CbMessage is null!");
54         return false;
55     }
56     return true;
57 }
58 
CheckCbMessage(const std::shared_ptr<GsmCbCodec> & cbMessage)59 uint8_t GsmSmsCbHandler::CheckCbMessage(const std::shared_ptr<GsmCbCodec> &cbMessage)
60 {
61     uint8_t currPageCnt = 0;
62     bool bFind = false;
63     if (cbMessage == nullptr) {
64         TELEPHONY_LOGE("CheckCbMessage cbMessage nullptr err.");
65         return currPageCnt;
66     }
67 
68     std::shared_ptr<GsmCbCodec::GsmCbMessageHeader> cbHeader = cbMessage->GetCbHeader();
69     if (cbHeader == nullptr) {
70         TELEPHONY_LOGE("CheckCbMessage GetCbHeader err.");
71         return currPageCnt;
72     }
73 
74     for (std::size_t i = 0; i < cbMsgList_.size(); i++) {
75         SmsCbInfo &cbInfo = cbMsgList_[i];
76         if (*cbInfo.header.get() == *cbHeader.get()) {
77             int updateNum = cbHeader->serialNum.updateNum - cbInfo.header->serialNum.updateNum;
78             if (updateNum != 0) {
79                 break;
80             }
81 
82             if (cbInfo.cbMsgs.count(cbHeader->page)) {
83                 currPageCnt = 0x01;
84                 return currPageCnt;
85             }
86             cbInfo.cbMsgs.insert(std::make_pair(cbHeader->page, cbMessage));
87             currPageCnt = cbInfo.cbMsgs.size();
88             bFind = true;
89             break;
90         }
91     }
92 
93     if (bFind == false || cbHeader->totalPages == 0x01) {
94         AddCbMessageToList(cbMessage);
95         currPageCnt = 0x01;
96     }
97 
98     return currPageCnt;
99 }
100 
FindCbMessage(const std::shared_ptr<GsmCbCodec> & cbMessage)101 std::unique_ptr<SmsCbInfo> GsmSmsCbHandler::FindCbMessage(const std::shared_ptr<GsmCbCodec> &cbMessage)
102 {
103     std::unique_ptr<SmsCbInfo> cbInfo = nullptr;
104     if (cbMessage == nullptr) {
105         TELEPHONY_LOGE("FindCbMessage cbMessage nullptr err.");
106         return cbInfo;
107     }
108 
109     std::shared_ptr<GsmCbCodec::GsmCbMessageHeader> cbHeader = cbMessage->GetCbHeader();
110     if (cbHeader == nullptr) {
111         TELEPHONY_LOGE("FindCbMessage header err.");
112         return cbInfo;
113     }
114 
115     for (std::size_t i = 0; i < cbMsgList_.size(); i++) {
116         SmsCbInfo &info = cbMsgList_[i];
117         if (*info.header.get() == *cbHeader.get()) {
118             cbInfo = std::make_unique<SmsCbInfo>(info.header, info.cbMsgs);
119             if (cbInfo == nullptr) {
120                 TELEPHONY_LOGE("Make SmsCbInfo err.");
121                 return cbInfo;
122             }
123         }
124     }
125     return cbInfo;
126 }
127 
AddCbMessageToList(const std::shared_ptr<GsmCbCodec> & cbMessage)128 bool GsmSmsCbHandler::AddCbMessageToList(const std::shared_ptr<GsmCbCodec> &cbMessage)
129 {
130     if (cbMessage == nullptr) {
131         TELEPHONY_LOGE("AddCbMessageToList cbMessage nullptr err.");
132         return false;
133     }
134     std::shared_ptr<GsmCbCodec::GsmCbMessageHeader> cbHeader = cbMessage->GetCbHeader();
135     if (cbHeader == nullptr) {
136         TELEPHONY_LOGE("AddCbMessageToList header err.");
137         return false;
138     }
139     std::unique_ptr<SmsCbInfo> cbInfo = FindCbMessage(cbMessage);
140     if (cbInfo == nullptr) {
141         SmsCbInfo info;
142         info.header = cbHeader;
143         info.cbMsgs.insert(std::make_pair(cbHeader->page, cbMessage));
144         InitLocation(info);
145         auto size = cbMsgList_.size();
146         if (size > MAX_CB_MSG_LIST_SIZE) {
147             auto halfSize = size / 2;
148             cbMsgList_.erase(cbMsgList_.begin(), cbMsgList_.begin() + halfSize);
149             TELEPHONY_LOGI("AddCbMessageToList clear message count: %{public}zu", halfSize);
150         }
151         cbMsgList_.push_back(info);
152         return true;
153     }
154     return false;
155 }
156 
ClearExpiredMessage()157 void GsmSmsCbHandler::ClearExpiredMessage()
158 {
159     if (cbMsgList_.empty()) {
160         return;
161     }
162     std::time_t timep;
163     int64_t currentTime = time(&timep);
164     for (auto i = cbMsgList_.size() - 1; i > 0; i--) {
165         if (currentTime - cbMsgList_[i].header->recvTime > static_cast<long long>(DEFAULT_EXPIRED_TIME)) {
166             cbMsgList_.erase(cbMsgList_.begin(), cbMsgList_.begin() + i + 1);
167             TELEPHONY_LOGI("ClearExpiredMessage clear message count: %{public}zu", i);
168             return;
169         }
170     }
171 }
172 
InitLocation(SmsCbInfo & info)173 bool GsmSmsCbHandler::InitLocation(SmsCbInfo &info)
174 {
175     const uint8_t cellWideImmediate = 0;
176     const uint8_t plmnWide = 1;
177     const uint8_t LaWide = 2;
178     const uint8_t cellWide = 3;
179     const int32_t defaultValue = -1;
180     info.plmn_ = CoreManagerInner::GetInstance().GetOperatorNumeric(slotId_);
181     sptr<CellLocation> location = CoreManagerInner::GetInstance().GetCellLocation(slotId_);
182     if (location == nullptr) {
183         TELEPHONY_LOGE("location is nullptr.");
184         return false;
185     }
186     if (location->GetCellLocationType() != CellLocation::CellType::CELL_TYPE_GSM) {
187         TELEPHONY_LOGE("location type isn't GSM.");
188         return false;
189     }
190     sptr<GsmCellLocation> gsmLocation = sptr<GsmCellLocation>(static_cast<GsmCellLocation *>(location.GetRefPtr()));
191     info.lac_ = gsmLocation->GetLac();
192     info.cid_ = gsmLocation->GetCellId();
193     TELEPHONY_LOGI("plmn = %{private}s lac = %{private}s cid = %{private}s", StringUtils::ToUtf8(info.plmn_).c_str(),
194         std::to_string(info.lac_).c_str(), std::to_string(info.cid_).c_str());
195     switch (info.header->serialNum.geoScope) {
196         case LaWide:
197             info.cid_ = defaultValue;
198             break;
199         case cellWide:
200         case cellWideImmediate:
201             break;
202         case plmnWide:
203         default:
204             info.cid_ = defaultValue;
205             info.lac_ = defaultValue;
206             break;
207     }
208     plmn_ = info.plmn_;
209     cid_ = info.cid_;
210     lac_ = info.lac_;
211     return true;
212 }
213 
RemoveCbMessageFromList(const std::shared_ptr<GsmCbCodec> & cbMessage)214 bool GsmSmsCbHandler::RemoveCbMessageFromList(const std::shared_ptr<GsmCbCodec> &cbMessage)
215 {
216     bool result = false;
217     if (cbMessage == nullptr) {
218         TELEPHONY_LOGE("RemoveCbMessageFromList cbMessage nullptr err.");
219         return false;
220     }
221 
222     std::shared_ptr<GsmCbCodec::GsmCbMessageHeader> header = cbMessage->GetCbHeader();
223     if (header == nullptr) {
224         TELEPHONY_LOGE("RemoveCbMessageFromList header err.");
225         return false;
226     }
227     auto it = cbMsgList_.begin();
228     while (it != cbMsgList_.end()) {
229         SmsCbInfo &info = *it;
230         if (*info.header.get() == *header.get() || !info.MatchLocation(plmn_, lac_, cid_)) {
231             it = cbMsgList_.erase(it);
232             result = true;
233         } else {
234             ++it;
235         }
236     }
237     return result;
238 }
239 
HandleCbMessage(std::shared_ptr<CBConfigReportInfo> & message)240 void GsmSmsCbHandler::HandleCbMessage(std::shared_ptr<CBConfigReportInfo> &message)
241 {
242     if (message == nullptr) {
243         TELEPHONY_LOGE("GsmSmsCbHandler HandleCbMessage message == nullptr");
244         return;
245     }
246 
247     std::string pdu(message->pdu);
248     std::shared_ptr<GsmCbCodec> cbMessage = GsmCbCodec::CreateCbMessage(pdu);
249     if (cbMessage == nullptr) {
250         TELEPHONY_LOGE("create Sms CbMessage fail");
251         SmsHiSysEvent::WriteSmsReceiveFaultEvent(slotId_, SmsMmsMessageType::CELL_BROAD_CAST,
252             SmsMmsErrorCode::SMS_ERROR_CELL_BROADCAST_PUD_ANALYSIS_FAIL, "publish cell broadcast event fail");
253         return;
254     }
255     std::shared_ptr<GsmCbCodec::GsmCbMessageHeader> header = cbMessage->GetCbHeader();
256     if (header == nullptr) {
257         TELEPHONY_LOGE("HandleCbMessage header is null.");
258         return;
259     }
260 
261     if (!CheckCbActive(cbMessage)) {
262         TELEPHONY_LOGE("The Cell Broadcast msg is not active");
263         return;
264     }
265 
266     ClearExpiredMessage();
267     uint8_t pageCnt = CheckCbMessage(cbMessage);
268     if (header->totalPages == pageCnt) {
269         SendCbMessageBroadcast(cbMessage);
270         RemoveCbMessageFromList(cbMessage);
271     }
272 }
273 
SendCbMessageBroadcast(const std::shared_ptr<GsmCbCodec> & cbMessage)274 bool GsmSmsCbHandler::SendCbMessageBroadcast(const std::shared_ptr<GsmCbCodec> &cbMessage)
275 {
276     if (cbMessage == nullptr) {
277         TELEPHONY_LOGE("SendCbMessageBroadcast cbMessage nullptr err.");
278         return false;
279     }
280     EventFwk::Want want;
281     EventFwk::CommonEventData data;
282     if (!SetWantData(want, cbMessage)) {
283         TELEPHONY_LOGE("SendCbMessageBroadcast SetWantData fail.");
284         return false;
285     }
286     DelayedSingleton<CbStartAbility>::GetInstance()->StartAbility(want);
287     data.SetWant(want);
288     EventFwk::CommonEventPublishInfo publishInfo;
289     publishInfo.SetOrdered(true);
290     std::vector<std::string> gsmCbPermissions;
291     gsmCbPermissions.emplace_back(Permission::RECEIVE_MESSAGES);
292     publishInfo.SetSubscriberPermissions(gsmCbPermissions);
293     bool publishResult = EventFwk::CommonEventManager::PublishCommonEvent(data, publishInfo, nullptr);
294     if (!publishResult) {
295         TELEPHONY_LOGE("SendBroadcast PublishBroadcastEvent result fail");
296         SmsHiSysEvent::WriteSmsReceiveFaultEvent(slotId_, SmsMmsMessageType::CELL_BROAD_CAST,
297             SmsMmsErrorCode::SMS_ERROR_PUBLISH_COMMON_EVENT_FAIL, "publish cell broadcast event fail");
298         return false;
299     }
300     DelayedSingleton<SmsHiSysEvent>::GetInstance()->SetCbBroadcastStartTime();
301     return true;
302 }
303 
ProcessEvent(const AppExecFwk::InnerEvent::Pointer & event)304 void GsmSmsCbHandler::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event)
305 {
306     if (event == nullptr) {
307         TELEPHONY_LOGE("GsmSmsCbHandler event nullptr error.");
308         return;
309     }
310 
311     uint32_t eventId = 0;
312     eventId = event->GetInnerEventId();
313     TELEPHONY_LOGI("ProcessEvent eventId = %{public}d", eventId);
314     switch (eventId) {
315         case RadioEvent::RADIO_CELL_BROADCAST: {
316             std::shared_ptr<CBConfigReportInfo> cbMessage = nullptr;
317             cbMessage = event->GetSharedObject<CBConfigReportInfo>();
318             HandleCbMessage(cbMessage);
319             break;
320         }
321         default:
322             TELEPHONY_LOGE("GsmSmsCbHandler eventId unknown error.");
323             break;
324     }
325 }
326 
SetWantData(EventFwk::Want & want,const std::shared_ptr<GsmCbCodec> & cbMessage)327 bool GsmSmsCbHandler::SetWantData(EventFwk::Want &want, const std::shared_ptr<GsmCbCodec> &cbMessage)
328 {
329     if (cbMessage == nullptr) {
330         TELEPHONY_LOGE("cbMessage is nullptr.");
331         return false;
332     }
333     SmsCbData::CbData sendData;
334     std::unique_ptr<SmsCbInfo> info = FindCbMessage(cbMessage);
335     if (info == nullptr) {
336         TELEPHONY_LOGE("find cb message fail.");
337         return false;
338     }
339     std::string rawMsgBody;
340     TELEPHONY_LOGI("cbMsgs size:%{public}zu.", info->cbMsgs.size());
341     for (auto it = info->cbMsgs.begin(); it != info->cbMsgs.end(); it++) {
342         rawMsgBody.append(it->second->GetCbMessageRaw());
343     }
344     GetCbData(cbMessage, sendData);
345     cbMessage->ConvertToUTF8(rawMsgBody, sendData.msgBody);
346     PackageWantData(sendData, want);
347     if (sendData.isPrimary && !StringUtils::IsEmpty(sendData.msgBody)) {
348         TELEPHONY_LOGI("secondary cb msg");
349         sendData.isPrimary = false;
350         want.SetParam(SmsCbData::IS_ETWS_PRIMARY, sendData.isPrimary);
351     }
352     if (sendData.isPrimary) {
353         want.SetAction(CommonEventSupport::COMMON_EVENT_SMS_EMERGENCY_CB_RECEIVE_COMPLETED);
354     } else {
355         want.SetAction(CommonEventSupport::COMMON_EVENT_SMS_CB_RECEIVE_COMPLETED);
356     }
357     return true;
358 }
359 
GetCbData(const std::shared_ptr<GsmCbCodec> & cbMessage,SmsCbData::CbData & sendData)360 void GsmSmsCbHandler::GetCbData(const std::shared_ptr<GsmCbCodec> &cbMessage, SmsCbData::CbData &sendData)
361 {
362     if (cbMessage == nullptr) {
363         TELEPHONY_LOGE("Get Cb Data error.");
364         return;
365     }
366     cbMessage->GetMsgType(sendData.msgType);
367     cbMessage->GetLangType(sendData.langType);
368     cbMessage->GetDcs(sendData.dcs);
369     cbMessage->GetPriority(sendData.priority);
370     cbMessage->GetCmasMessageClass(sendData.cmasClass);
371     cbMessage->GetCmasResponseType(sendData.cmasRes);
372     cbMessage->GetCmasSeverity(sendData.severity);
373     cbMessage->GetCmasUrgency(sendData.urgency);
374     cbMessage->GetCmasCertainty(sendData.certainty);
375     cbMessage->IsEtwsMessage(sendData.isEtws);
376     cbMessage->GetWarningType(sendData.warnType);
377     cbMessage->IsCmasMessage(sendData.isCmas);
378     cbMessage->GetSerialNum(sendData.serial);
379     cbMessage->GetReceiveTime(sendData.recvTime);
380     cbMessage->GetMessageId(sendData.msgId);
381     cbMessage->GetServiceCategory(sendData.category);
382     cbMessage->GetFormat(sendData.format);
383     cbMessage->IsEtwsPrimary(sendData.isPrimary);
384     cbMessage->GetGeoScope(sendData.geoScope);
385     cbMessage->GetCmasCategory(sendData.cmasCate);
386 }
387 
PackageWantData(SmsCbData::CbData & sendData,EventFwk::Want & want)388 void GsmSmsCbHandler::PackageWantData(SmsCbData::CbData &sendData, EventFwk::Want &want)
389 {
390     want.SetParam(SmsCbData::GEO_SCOPE, static_cast<char>(sendData.geoScope));
391     want.SetParam(SmsCbData::CMAS_RESPONSE, static_cast<char>(sendData.cmasRes));
392     want.SetParam(SmsCbData::SLOT_ID, static_cast<int>(slotId_));
393     want.SetParam(SmsCbData::FORMAT, static_cast<char>(sendData.format));
394     want.SetParam(SmsCbData::CB_MSG_TYPE, static_cast<char>(sendData.msgType));
395     want.SetParam(SmsCbData::MSG_ID, static_cast<int>(sendData.msgId));
396     want.SetParam(SmsCbData::SERVICE_CATEGORY, static_cast<int>(sendData.category));
397     want.SetParam(SmsCbData::LANG_TYPE, static_cast<char>(sendData.langType));
398     want.SetParam(SmsCbData::PRIORITY, static_cast<char>(sendData.priority));
399     want.SetParam(SmsCbData::MSG_BODY, sendData.msgBody);
400     want.SetParam(SmsCbData::CMAS_CLASS, static_cast<char>(sendData.cmasClass));
401     want.SetParam(SmsCbData::CMAS_CATEGORY, static_cast<char>(sendData.cmasCate));
402     want.SetParam(SmsCbData::SEVERITY, static_cast<char>(sendData.severity));
403     want.SetParam(SmsCbData::URGENCY, static_cast<char>(sendData.urgency));
404     want.SetParam(SmsCbData::CERTAINTY, static_cast<char>(sendData.certainty));
405     want.SetParam(SmsCbData::IS_CMAS_MESSAGE, sendData.isCmas);
406     want.SetParam(SmsCbData::SERIAL_NUM, static_cast<int>(sendData.serial));
407     want.SetParam(SmsCbData::RECV_TIME, std::to_string(sendData.recvTime));
408     want.SetParam(SmsCbData::DCS, static_cast<char>(sendData.dcs));
409     want.SetParam(SmsCbData::IS_ETWS_PRIMARY, sendData.isPrimary);
410     want.SetParam(SmsCbData::IS_ETWS_MESSAGE, sendData.isEtws);
411     want.SetParam(SmsCbData::PLMN, StringUtils::ToUtf8(plmn_));
412     want.SetParam(SmsCbData::LAC, static_cast<int>(lac_));
413     want.SetParam(SmsCbData::CID, static_cast<int>(cid_));
414     want.SetParam(SmsCbData::WARNING_TYPE, static_cast<int>(sendData.warnType));
415 }
416 } // namespace Telephony
417 } // namespace OHOS