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 cbMsgList_.push_back(info);
146 return true;
147 }
148 return false;
149 }
150
InitLocation(SmsCbInfo & info)151 bool GsmSmsCbHandler::InitLocation(SmsCbInfo &info)
152 {
153 const uint8_t cellWideImmediate = 0;
154 const uint8_t plmnWide = 1;
155 const uint8_t LaWide = 2;
156 const uint8_t cellWide = 3;
157 const int32_t defaultValue = -1;
158 info.plmn_ = CoreManagerInner::GetInstance().GetOperatorNumeric(slotId_);
159 sptr<CellLocation> location = CoreManagerInner::GetInstance().GetCellLocation(slotId_);
160 if (location == nullptr) {
161 TELEPHONY_LOGE("location is nullptr.");
162 return false;
163 }
164 if (location->GetCellLocationType() != CellLocation::CellType::CELL_TYPE_GSM) {
165 TELEPHONY_LOGE("location type isn't GSM.");
166 return false;
167 }
168 sptr<GsmCellLocation> gsmLocation = sptr<GsmCellLocation>(static_cast<GsmCellLocation *>(location.GetRefPtr()));
169 info.lac_ = gsmLocation->GetLac();
170 info.cid_ = gsmLocation->GetCellId();
171 TELEPHONY_LOGI("plmn = %{private}s lac = %{private}s cid = %{private}s", StringUtils::ToUtf8(info.plmn_).c_str(),
172 std::to_string(info.lac_).c_str(), std::to_string(info.cid_).c_str());
173 switch (info.header->serialNum.geoScope) {
174 case LaWide:
175 info.cid_ = defaultValue;
176 break;
177 case cellWide:
178 case cellWideImmediate:
179 break;
180 case plmnWide:
181 default:
182 info.cid_ = defaultValue;
183 info.lac_ = defaultValue;
184 break;
185 }
186 plmn_ = info.plmn_;
187 cid_ = info.cid_;
188 lac_ = info.lac_;
189 return true;
190 }
191
RemoveCbMessageFromList(const std::shared_ptr<GsmCbCodec> & cbMessage)192 bool GsmSmsCbHandler::RemoveCbMessageFromList(const std::shared_ptr<GsmCbCodec> &cbMessage)
193 {
194 bool result = false;
195 if (cbMessage == nullptr) {
196 TELEPHONY_LOGE("RemoveCbMessageFromList cbMessage nullptr err.");
197 return false;
198 }
199
200 std::shared_ptr<GsmCbCodec::GsmCbMessageHeader> header = cbMessage->GetCbHeader();
201 if (header == nullptr) {
202 TELEPHONY_LOGE("RemoveCbMessageFromList header err.");
203 return false;
204 }
205 auto it = cbMsgList_.begin();
206 while (it != cbMsgList_.end()) {
207 SmsCbInfo &info = *it;
208 if (*info.header.get() == *header.get() || !info.MatchLocation(plmn_, lac_, cid_)) {
209 it = cbMsgList_.erase(it);
210 result = true;
211 } else {
212 ++it;
213 }
214 }
215 return result;
216 }
217
HandleCbMessage(std::shared_ptr<CBConfigReportInfo> & message)218 void GsmSmsCbHandler::HandleCbMessage(std::shared_ptr<CBConfigReportInfo> &message)
219 {
220 if (message == nullptr) {
221 TELEPHONY_LOGE("GsmSmsCbHandler HandleCbMessage message == nullptr");
222 return;
223 }
224
225 std::string pdu(message->pdu);
226 std::shared_ptr<GsmCbCodec> cbMessage = GsmCbCodec::CreateCbMessage(pdu);
227 TELEPHONY_LOGE("cb message pdu:%{public}s", pdu.c_str());
228 if (cbMessage == nullptr) {
229 TELEPHONY_LOGE("create Sms CbMessage fail");
230 SmsHiSysEvent::WriteSmsReceiveFaultEvent(slotId_, SmsMmsMessageType::CELL_BROAD_CAST,
231 SmsMmsErrorCode::SMS_ERROR_CELL_BROADCAST_PUD_ANALYSIS_FAIL, "publish cell broadcast event fail");
232 return;
233 }
234 std::shared_ptr<GsmCbCodec::GsmCbMessageHeader> header = cbMessage->GetCbHeader();
235 if (header == nullptr) {
236 TELEPHONY_LOGE("HandleCbMessage header is null.");
237 return;
238 }
239
240 if (!CheckCbActive(cbMessage)) {
241 TELEPHONY_LOGE("The Cell Broadcast msg is not active");
242 return;
243 }
244
245 uint8_t pageCnt = CheckCbMessage(cbMessage);
246 if (header->totalPages == pageCnt) {
247 SendCbMessageBroadcast(cbMessage);
248 RemoveCbMessageFromList(cbMessage);
249 }
250 }
251
SendCbMessageBroadcast(const std::shared_ptr<GsmCbCodec> & cbMessage)252 bool GsmSmsCbHandler::SendCbMessageBroadcast(const std::shared_ptr<GsmCbCodec> &cbMessage)
253 {
254 if (cbMessage == nullptr) {
255 TELEPHONY_LOGE("SendCbMessageBroadcast cbMessage nullptr err.");
256 return false;
257 }
258 EventFwk::Want want;
259 EventFwk::CommonEventData data;
260 if (!SetWantData(want, cbMessage)) {
261 TELEPHONY_LOGE("SendCbMessageBroadcast SetWantData fail.");
262 return false;
263 }
264 DelayedSingleton<CbStartAbility>::GetInstance()->StartAbility(want);
265 data.SetWant(want);
266 EventFwk::CommonEventPublishInfo publishInfo;
267 publishInfo.SetOrdered(true);
268 std::vector<std::string> gsmCbPermissions;
269 gsmCbPermissions.emplace_back(Permission::RECEIVE_MESSAGES);
270 publishInfo.SetSubscriberPermissions(gsmCbPermissions);
271 bool publishResult = EventFwk::CommonEventManager::PublishCommonEvent(data, publishInfo, nullptr);
272 if (!publishResult) {
273 TELEPHONY_LOGE("SendBroadcast PublishBroadcastEvent result fail");
274 SmsHiSysEvent::WriteSmsReceiveFaultEvent(slotId_, SmsMmsMessageType::CELL_BROAD_CAST,
275 SmsMmsErrorCode::SMS_ERROR_PUBLISH_COMMON_EVENT_FAIL, "publish cell broadcast event fail");
276 return false;
277 }
278 DelayedSingleton<SmsHiSysEvent>::GetInstance()->SetCbBroadcastStartTime();
279 return true;
280 }
281
ProcessEvent(const AppExecFwk::InnerEvent::Pointer & event)282 void GsmSmsCbHandler::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event)
283 {
284 if (event == nullptr) {
285 TELEPHONY_LOGE("GsmSmsCbHandler event nullptr error.");
286 return;
287 }
288
289 uint32_t eventId = 0;
290 eventId = event->GetInnerEventId();
291 TELEPHONY_LOGI("ProcessEvent eventId = %{public}d", eventId);
292 switch (eventId) {
293 case RadioEvent::RADIO_CELL_BROADCAST: {
294 std::shared_ptr<CBConfigReportInfo> cbMessage = nullptr;
295 cbMessage = event->GetSharedObject<CBConfigReportInfo>();
296 HandleCbMessage(cbMessage);
297 break;
298 }
299 default:
300 TELEPHONY_LOGE("GsmSmsCbHandler eventId unknown error.");
301 break;
302 }
303 }
304
SetWantData(EventFwk::Want & want,const std::shared_ptr<GsmCbCodec> & cbMessage)305 bool GsmSmsCbHandler::SetWantData(EventFwk::Want &want, const std::shared_ptr<GsmCbCodec> &cbMessage)
306 {
307 if (cbMessage == nullptr) {
308 TELEPHONY_LOGE("cbMessage is nullptr.");
309 return false;
310 }
311 SmsCbData::CbData sendData;
312 std::unique_ptr<SmsCbInfo> info = FindCbMessage(cbMessage);
313 if (info == nullptr) {
314 TELEPHONY_LOGE("find cb message fail.");
315 return false;
316 }
317 std::string rawMsgBody;
318 TELEPHONY_LOGI("cbMsgs size:%{public}zu.", info->cbMsgs.size());
319 for (auto it = info->cbMsgs.begin(); it != info->cbMsgs.end(); it++) {
320 rawMsgBody.append(it->second->GetCbMessageRaw());
321 }
322 GetCbData(cbMessage, sendData);
323 TELEPHONY_LOGI("cbMessage:%{public}s.", cbMessage->ToString().c_str());
324 cbMessage->ConvertToUTF8(rawMsgBody, sendData.msgBody);
325 TELEPHONY_LOGI("msgBody:%{public}s.", sendData.msgBody.c_str());
326 PackageWantData(sendData, want);
327 if (sendData.isPrimary && !sendData.msgBody.empty()) {
328 TELEPHONY_LOGI("secondary cb msg");
329 sendData.isPrimary = false;
330 want.SetParam(SmsCbData::IS_ETWS_PRIMARY, sendData.isPrimary);
331 }
332 if (sendData.isPrimary) {
333 want.SetAction(CommonEventSupport::COMMON_EVENT_SMS_EMERGENCY_CB_RECEIVE_COMPLETED);
334 } else {
335 want.SetAction(CommonEventSupport::COMMON_EVENT_SMS_CB_RECEIVE_COMPLETED);
336 }
337 return true;
338 }
339
GetCbData(const std::shared_ptr<GsmCbCodec> & cbMessage,SmsCbData::CbData & sendData)340 void GsmSmsCbHandler::GetCbData(const std::shared_ptr<GsmCbCodec> &cbMessage, SmsCbData::CbData &sendData)
341 {
342 if (cbMessage == nullptr) {
343 TELEPHONY_LOGE("Get Cb Data error.");
344 return;
345 }
346 cbMessage->GetMsgType(sendData.msgType);
347 cbMessage->GetLangType(sendData.langType);
348 cbMessage->GetDcs(sendData.dcs);
349 cbMessage->GetPriority(sendData.priority);
350 cbMessage->GetCmasMessageClass(sendData.cmasClass);
351 cbMessage->GetCmasResponseType(sendData.cmasRes);
352 cbMessage->GetCmasSeverity(sendData.severity);
353 cbMessage->GetCmasUrgency(sendData.urgency);
354 cbMessage->GetCmasCertainty(sendData.certainty);
355 cbMessage->IsEtwsMessage(sendData.isEtws);
356 cbMessage->GetWarningType(sendData.warnType);
357 cbMessage->IsCmasMessage(sendData.isCmas);
358 cbMessage->GetSerialNum(sendData.serial);
359 cbMessage->GetReceiveTime(sendData.recvTime);
360 cbMessage->GetMessageId(sendData.msgId);
361 cbMessage->GetServiceCategory(sendData.category);
362 cbMessage->GetFormat(sendData.format);
363 cbMessage->IsEtwsPrimary(sendData.isPrimary);
364 cbMessage->GetGeoScope(sendData.geoScope);
365 cbMessage->GetCmasCategory(sendData.cmasCate);
366 }
367
PackageWantData(SmsCbData::CbData & sendData,EventFwk::Want & want)368 void GsmSmsCbHandler::PackageWantData(SmsCbData::CbData &sendData, EventFwk::Want &want)
369 {
370 want.SetParam(SmsCbData::GEO_SCOPE, static_cast<char>(sendData.geoScope));
371 want.SetParam(SmsCbData::CMAS_RESPONSE, static_cast<char>(sendData.cmasRes));
372 want.SetParam(SmsCbData::SLOT_ID, static_cast<int>(slotId_));
373 want.SetParam(SmsCbData::FORMAT, static_cast<char>(sendData.format));
374 want.SetParam(SmsCbData::CB_MSG_TYPE, static_cast<char>(sendData.msgType));
375 want.SetParam(SmsCbData::MSG_ID, static_cast<int>(sendData.msgId));
376 want.SetParam(SmsCbData::SERVICE_CATEGORY, static_cast<int>(sendData.category));
377 want.SetParam(SmsCbData::LANG_TYPE, static_cast<char>(sendData.langType));
378 want.SetParam(SmsCbData::PRIORITY, static_cast<char>(sendData.priority));
379 want.SetParam(SmsCbData::MSG_BODY, sendData.msgBody);
380 want.SetParam(SmsCbData::CMAS_CLASS, static_cast<char>(sendData.cmasClass));
381 want.SetParam(SmsCbData::CMAS_CATEGORY, static_cast<char>(sendData.cmasCate));
382 want.SetParam(SmsCbData::SEVERITY, static_cast<char>(sendData.severity));
383 want.SetParam(SmsCbData::URGENCY, static_cast<char>(sendData.urgency));
384 want.SetParam(SmsCbData::CERTAINTY, static_cast<char>(sendData.certainty));
385 want.SetParam(SmsCbData::IS_CMAS_MESSAGE, sendData.isCmas);
386 want.SetParam(SmsCbData::SERIAL_NUM, static_cast<int>(sendData.serial));
387 want.SetParam(SmsCbData::RECV_TIME, std::to_string(sendData.recvTime));
388 want.SetParam(SmsCbData::DCS, static_cast<char>(sendData.dcs));
389 want.SetParam(SmsCbData::IS_ETWS_PRIMARY, sendData.isPrimary);
390 want.SetParam(SmsCbData::IS_ETWS_MESSAGE, sendData.isEtws);
391 want.SetParam(SmsCbData::PLMN, StringUtils::ToUtf8(plmn_));
392 want.SetParam(SmsCbData::LAC, static_cast<int>(lac_));
393 want.SetParam(SmsCbData::CID, static_cast<int>(cid_));
394 want.SetParam(SmsCbData::WARNING_TYPE, static_cast<int>(sendData.warnType));
395 }
396 } // namespace Telephony
397 } // namespace OHOS