1 /*
2 * Copyright (C) 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 "cdma_sms_common.h"
17 #include "gsm_cb_gsm_codec.h"
18 #include "gsm_cb_umts_codec.h"
19 #include "gsm_pdu_hex_value.h"
20 #include "securec.h"
21 #include "sms_common_utils.h"
22 #include "string_utils.h"
23 #include "telephony_log_wrapper.h"
24 #include "text_coder.h"
25
26 namespace OHOS {
27 namespace Telephony {
28 static constexpr uint8_t SMS_BYTE_BIT = 8;
29 static constexpr uint8_t GSM_CB_HEADER_LEN = 6;
30 static constexpr uint16_t MAX_CB_MSG_LEN = 4200;
31 static constexpr uint8_t MAX_PAGE_PDU_LEN = 82;
32 static constexpr uint8_t CB_FORMAT_3GPP = 1;
33 static constexpr uint16_t ETWS_TYPE = 0x1100;
34 static constexpr uint16_t ETWS_TYPE_MASK = 0xFFF8;
35 static constexpr uint16_t CMAS_FIRST_ID = 0x1112;
36 static constexpr uint16_t CMAS_LAST_ID = 0x112F;
37 static constexpr uint16_t EMERGENCY_USER_ALERT = 0x2000;
38 static constexpr uint16_t ETWS_POPUP = 0x1000;
39 static constexpr uint16_t PWS_FIRST_ID = 0x1100;
40 static constexpr uint16_t PWS_LAST_ID = 0x18FF;
41
operator ==(const GsmCbCodec & codec) const42 bool GsmCbCodec::operator==(const GsmCbCodec &codec) const
43 {
44 if (cbHeader_ == nullptr || codec.cbHeader_ == nullptr) {
45 TELEPHONY_LOGE("nullptr error.");
46 return false;
47 }
48 return cbHeader_->serialNum.geoScope == codec.cbHeader_->serialNum.geoScope &&
49 cbHeader_->serialNum.msgCode == codec.cbHeader_->serialNum.msgCode &&
50 cbHeader_->msgId == codec.cbHeader_->msgId;
51 }
52
CreateCbMessage(const std::string & pdu)53 std::shared_ptr<GsmCbCodec> GsmCbCodec::CreateCbMessage(const std::string &pdu)
54 {
55 bool result = false;
56 std::shared_ptr<GsmCbCodec> message = std::make_shared<GsmCbCodec>();
57 if (message == nullptr) {
58 TELEPHONY_LOGE("message is nullptr.");
59 return nullptr;
60 }
61 result = message->PduAnalysis(StringUtils::HexToByteVector(pdu));
62 return (result ? message : nullptr);
63 }
64
CreateCbMessage(const std::vector<unsigned char> & pdu)65 std::shared_ptr<GsmCbCodec> GsmCbCodec::CreateCbMessage(const std::vector<unsigned char> &pdu)
66 {
67 bool result = false;
68 std::shared_ptr<GsmCbCodec> message = std::make_shared<GsmCbCodec>();
69 if (message == nullptr) {
70 TELEPHONY_LOGE("message is nullptr.");
71 return nullptr;
72 }
73 result = message->PduAnalysis(pdu);
74 return (result ? message : nullptr);
75 }
76
GetCbHeader() const77 std::shared_ptr<GsmCbCodec::GsmCbMessageHeader> GsmCbCodec::GetCbHeader() const
78 {
79 return cbHeader_;
80 }
81
GetCbMessageRaw() const82 std::string GsmCbCodec::GetCbMessageRaw() const
83 {
84 return messageRaw_;
85 }
86
SetCbMessageRaw(std::string & raw)87 void GsmCbCodec::SetCbMessageRaw(std::string &raw)
88 {
89 messageRaw_ = raw;
90 }
91
IsSinglePageMsg() const92 bool GsmCbCodec::IsSinglePageMsg() const
93 {
94 return cbHeader_ != nullptr && (cbHeader_->totalPages == 1);
95 }
96
97 /**
98 * refer to 3GPP TS 23.041 V4.1.0 9.1.1 9.1.2 section Protocols and Protocol Architecture
99 * refer to 3GPP TS 23.041 V4.1.0 9.3 Parameters
100 */
PduAnalysis(const std::vector<unsigned char> & pdu)101 bool GsmCbCodec::PduAnalysis(const std::vector<unsigned char> &pdu)
102 {
103 if (!ParamsCheck(pdu)) {
104 TELEPHONY_LOGE("params error.");
105 return false;
106 }
107 auto gsmCodec = std::make_shared<GsmCbGsmCodec>(cbHeader_, cbPduBuffer_, shared_from_this());
108 auto umtsCodec = std::make_shared<GsmCbUmtsCodec>(cbHeader_, cbPduBuffer_, shared_from_this());
109 if (gsmCodec == nullptr || umtsCodec == nullptr) {
110 TELEPHONY_LOGE("nullptr error.");
111 return false;
112 }
113
114 // refer to 3GPP TS 23.041 V4.1.0 9.1.1 9.1.2 section Protocols and Protocol Architecture
115 bool decodeResult = false;
116 if (pdu.size() <= (MAX_PAGE_PDU_LEN + GSM_CB_HEADER_LEN)) {
117 cbHeader_->cbMsgType = GSM_CBS;
118 cbHeader_->cbNetType = GSM_NET_CB;
119 decodeResult = gsmCodec->Decode2gHeader();
120 } else if (pdu.size() <= MAX_CB_MSG_LEN) {
121 uint8_t oneByte = 0;
122 if (!cbPduBuffer_->PickOneByte(oneByte)) {
123 TELEPHONY_LOGE("get data error.");
124 return false;
125 }
126 cbHeader_->cbMsgType = oneByte;
127 cbHeader_->cbNetType = UMTS_NET_CB;
128 decodeResult = umtsCodec->Decode3gHeader();
129 } else {
130 TELEPHONY_LOGE("pdu size over max.");
131 return false;
132 }
133
134 if (!decodeResult || cbPduBuffer_->GetCurPosition() >= pdu.size()) {
135 TELEPHONY_LOGE("CB decode head fail.");
136 return false;
137 }
138 if (cbHeader_->bEtwsMessage && cbHeader_->cbEtwsType == ETWS_PRIMARY) {
139 return gsmCodec->DecodeEtwsMsg();
140 }
141
142 if (cbHeader_->cbNetType == GSM_NET_CB) {
143 decodeResult = gsmCodec->Decode2gCbMsg();
144 } else if (cbHeader_->cbNetType == UMTS_NET_CB) {
145 decodeResult = umtsCodec->Decode3gCbMsg();
146 }
147 TELEPHONY_LOGI("CB decode result:%{public}d.", decodeResult);
148 return decodeResult;
149 }
150
ParamsCheck(const std::vector<unsigned char> & pdu)151 bool GsmCbCodec::ParamsCheck(const std::vector<unsigned char> &pdu)
152 {
153 if (pdu.size() == 0 && pdu.size() > MAX_CB_MSG_LEN) {
154 TELEPHONY_LOGE("pdu data error.");
155 return false;
156 }
157 cbPduBuffer_ = std::make_shared<GsmCbPduDecodeBuffer>(pdu.size());
158 cbHeader_ = std::make_shared<GsmCbCodec::GsmCbMessageHeader>();
159 if (cbPduBuffer_ == nullptr || cbHeader_ == nullptr || cbPduBuffer_->pduBuffer_ == nullptr) {
160 TELEPHONY_LOGE("nullptr error.");
161 return false;
162 }
163 for (size_t index = 0; index < pdu.size() && index < cbPduBuffer_->GetSize(); index++) {
164 cbPduBuffer_->pduBuffer_[index] = static_cast<char>(pdu[index]);
165 }
166 return true;
167 }
168
GetPduData(std::vector<unsigned char> & dataPdu)169 void GsmCbCodec::GetPduData(std::vector<unsigned char> &dataPdu)
170 {
171 if (cbPduBuffer_ == nullptr) {
172 TELEPHONY_LOGE("nullptr error.");
173 return;
174 }
175
176 uint32_t current = cbPduBuffer_->GetCurPosition();
177 uint8_t oneByte = 0;
178 while (cbPduBuffer_->GetCurPosition() < cbPduBuffer_->GetSize()) {
179 if (!cbPduBuffer_->GetOneByte(oneByte)) {
180 TELEPHONY_LOGE("get data error.");
181 }
182 dataPdu.push_back(oneByte);
183 }
184 cbPduBuffer_->SetPointer(current);
185 }
186
ConvertToUTF8(const std::string & raw,std::string & message) const187 void GsmCbCodec::ConvertToUTF8(const std::string &raw, std::string &message) const
188 {
189 if (cbHeader_ == nullptr) {
190 TELEPHONY_LOGE("ConvertToUTF8 cbHeader null err.");
191 return;
192 }
193 if (cbHeader_->bEtwsMessage && cbHeader_->cbEtwsType == ETWS_PRIMARY) {
194 message.assign(raw);
195 } else {
196 uint16_t codeSize = 0;
197 MsgLangInfo langInfo;
198 uint8_t outBuf[MAX_CB_MSG_LEN + 1] = { 0 };
199 const uint8_t *src = reinterpret_cast<const uint8_t *>(raw.data());
200 if (cbHeader_->dcs.codingScheme == DATA_CODING_7BIT) {
201 codeSize = TextCoder::Instance().Gsm7bitToUtf8(outBuf, sizeof(outBuf), src, raw.length(), langInfo);
202 } else if (cbHeader_->dcs.codingScheme == DATA_CODING_UCS2) {
203 codeSize = TextCoder::Instance().Ucs2ToUtf8(outBuf, sizeof(outBuf), src, raw.length());
204 } else {
205 TELEPHONY_LOGI("CB message data encoding 8bit");
206 message.assign(raw);
207 return;
208 }
209 if (codeSize >= MAX_CB_MSG_LEN) {
210 TELEPHONY_LOGE("codeSize over size.");
211 return;
212 }
213 outBuf[codeSize] = '\0';
214 for (uint16_t index = 0; index < codeSize; index++) {
215 message.push_back(static_cast<char>(outBuf[index]));
216 }
217 }
218 }
219
EncodeCbSerialNum(const GsmCBMsgSerialNum & snFields)220 unsigned short GsmCbCodec::EncodeCbSerialNum(const GsmCBMsgSerialNum &snFields)
221 {
222 unsigned short serialNum = ((snFields.geoScope & HEX_VALUE_03) << HEX_VALUE_0E) |
223 ((snFields.msgCode & HEX_VALUE_03FF) << HEX_VALUE_04) |
224 (snFields.updateNum & HEX_VALUE_0F);
225 return serialNum;
226 }
227
CMASClass(const uint16_t messageId) const228 uint8_t GsmCbCodec::CMASClass(const uint16_t messageId) const
229 {
230 uint8_t ret = 0;
231 switch (messageId) {
232 case PRESIDENTIAL:
233 case PRESIDENTIAL_SPANISH:
234 ret = CMAS_PRESIDENTIAL;
235 break;
236 case EXTREME_OBSERVED:
237 case EXTREME_OBSERVED_SPANISH:
238 case EXTREME_LIKELY:
239 case EXTREME_LIKELY_SPANISH:
240 ret = CMAS_EXTREME;
241 break;
242 case SEVERE_OBSERVED:
243 case SEVERE_OBSERVED_SPANISH:
244 case SEVERE_LIKELY:
245 case SEVERE_LIKELY_SPANISH:
246 case ALERT_OBSERVED_DEFUALT:
247 case ALERT_OBSERVED_SPANISH:
248 case ALERT_LIKELY:
249 case ALERT_LIKELY_SPANISH:
250 case EXPECTED_OBSERVED:
251 case EXPECTED_OBSERVED_SPANISH:
252 case EXPECTED_LIKELY:
253 case EXPECTED_LIKELY_SPANISH:
254 ret = CMAS_SEVERE;
255 break;
256 case AMBER_ALERT:
257 case AMBER_ALERT_SPANISH:
258 ret = CMAS_AMBER;
259 break;
260 case MONTHLY_ALERT:
261 case MONTHLY_ALERT_SPANISH:
262 ret = CMAS_TEST;
263 break;
264 case EXERCISE_ALERT:
265 case EXERCISE_ALERT_SPANISH:
266 ret = CMAS_EXERCISE;
267 break;
268 case OPERATOR_ALERT:
269 case OPERATOR_ALERT_SPANISH:
270 ret = CMAS_OPERATOR_DEFINED;
271 break;
272 default:
273 break;
274 }
275 return ret;
276 }
277
278 /**
279 * refer to 3GPP TS 23.038 V4.3.0 6.1.1 section
280 */
DecodeIos639Dcs(const uint8_t dcsData,const unsigned short iosData,GsmCbMsgDcs & dcs) const281 void GsmCbCodec::DecodeIos639Dcs(const uint8_t dcsData, const unsigned short iosData, GsmCbMsgDcs &dcs) const
282 {
283 uint8_t dcsLow = (dcsData & HEX_VALUE_0F);
284 switch (dcsLow) {
285 case 0x00:
286 case HEX_VALUE_01: {
287 dcs.codingGroup = SMS_CBMSG_CODGRP_GENERAL_DCS;
288 dcs.codingScheme = (dcsData & HEX_VALUE_01) ? DATA_CODING_UCS2 : DATA_CODING_7BIT;
289 dcs.langType = CB_LANG_ISO639;
290 uint8_t hight = (iosData >> SMS_BYTE_BIT);
291 uint8_t low = iosData;
292
293 // refer to 3GPP TS 23.038 V4.3.0 6.1.1 section Control characters
294 if (hight && low) {
295 dcs.iso639Lang[0x00] = hight & HEX_VALUE_7F;
296 dcs.iso639Lang[HEX_VALUE_01] = (hight & HEX_VALUE_80) >> HEX_VALUE_07;
297 dcs.iso639Lang[HEX_VALUE_01] |= (low & HEX_VALUE_3F) << HEX_VALUE_01;
298 dcs.iso639Lang[HEX_VALUE_02] = HEX_VALUE_13; /* CR */
299 } else {
300 dcs.iso639Lang[0x00] = HEX_VALUE_45; /* E */
301 dcs.iso639Lang[HEX_VALUE_01] = HEX_VALUE_4E; /* N */
302 dcs.iso639Lang[HEX_VALUE_02] = HEX_VALUE_13; /* CR */
303 }
304 break;
305 }
306 default:
307 break;
308 }
309 }
310
311 /**
312 * refer to 3GPP TS 23.038 V4.3.0 6 section
313 */
DecodeGeneralDcs(const uint8_t dcsData,GsmCbMsgDcs & dcs) const314 void GsmCbCodec::DecodeGeneralDcs(const uint8_t dcsData, GsmCbMsgDcs &dcs) const
315 {
316 dcs.codingGroup = SMS_CBMSG_CODGRP_GENERAL_DCS;
317 dcs.bCompressed = (dcsData & HEX_VALUE_20) ? true : false;
318 if (dcsData & HEX_VALUE_10) {
319 dcs.classType = (dcsData & HEX_VALUE_03);
320 }
321 uint8_t tmpScheme = (dcsData & HEX_VALUE_0C) >> HEX_VALUE_02;
322 switch (tmpScheme) {
323 case 0x00:
324 dcs.codingScheme = DATA_CODING_7BIT;
325 break;
326 case HEX_VALUE_01:
327 dcs.codingScheme = DATA_CODING_8BIT;
328 break;
329 case HEX_VALUE_02:
330 dcs.codingScheme = DATA_CODING_UCS2;
331 break;
332 default:
333 break;
334 }
335 }
336
337 /**
338 * refer to 3GPP TS 23.038 V4.3.0 6 section
339 */
DecodeCbMsgDCS(const uint8_t dcsData,const unsigned short iosData,GsmCbMsgDcs & dcs) const340 void GsmCbCodec::DecodeCbMsgDCS(const uint8_t dcsData, const unsigned short iosData, GsmCbMsgDcs &dcs) const
341 {
342 dcs.codingGroup = SMS_CBMSG_CODGRP_GENERAL_DCS;
343 dcs.classType = SMS_CLASS_UNKNOWN;
344 dcs.bCompressed = false;
345 dcs.codingScheme = DATA_CODING_7BIT;
346 dcs.langType = CB_MSG_UNSPECIFIED;
347 if (memset_s(dcs.iso639Lang, sizeof(dcs.iso639Lang), 0x00, sizeof(dcs.iso639Lang)) != EOK) {
348 TELEPHONY_LOGE("memset_s error!");
349 return;
350 }
351 dcs.bUDH = false;
352 dcs.rawData = dcsData;
353 uint8_t codingGroup = (dcsData & HEX_VALUE_F0) >> HEX_VALUE_04;
354 switch (codingGroup) {
355 case 0x00:
356 case HEX_VALUE_02:
357 case HEX_VALUE_03:
358 dcs.codingGroup = SMS_CBMSG_CODGRP_GENERAL_DCS;
359 dcs.langType = dcsData;
360 break;
361 case HEX_VALUE_01:
362 DecodeIos639Dcs(dcsData, iosData, dcs);
363 break;
364 case HEX_VALUE_04:
365 case HEX_VALUE_05:
366 case HEX_VALUE_06:
367 case HEX_VALUE_07:
368 DecodeGeneralDcs(dcsData, dcs);
369 break;
370 case HEX_VALUE_09:
371 dcs.bUDH = true;
372 dcs.classType = dcsData & HEX_VALUE_03;
373 dcs.codingScheme = (dcsData & HEX_VALUE_0C) >> HEX_VALUE_02;
374 break;
375 case HEX_VALUE_0E:
376 dcs.codingGroup = SMS_CBMSG_CODGRP_WAP;
377 break;
378 case HEX_VALUE_0F:
379 dcs.codingGroup = SMS_CBMSG_CODGRP_CLASS_CODING;
380 dcs.codingScheme = (dcsData & HEX_VALUE_04) ? DATA_CODING_8BIT : DATA_CODING_7BIT;
381 dcs.classType = dcsData & HEX_VALUE_03;
382 break;
383 default:
384 TELEPHONY_LOGI("codingGrp: [0x%{public}x]", codingGroup);
385 break;
386 }
387 }
388
GetRecvTime() const389 int64_t GsmCbCodec::GetRecvTime() const
390 {
391 time_t recvTime = time(NULL);
392 return static_cast<int64_t>(recvTime);
393 }
394
ToString() const395 std::string GsmCbCodec::ToString() const
396 {
397 if (cbHeader_ == nullptr) {
398 TELEPHONY_LOGE("cbHeader_ is nullptr");
399 return "GsmCbCodec Header nullptr";
400 }
401 std::string cbMsgId("msgId:" + std::to_string(cbHeader_->msgId));
402 std::string cbLangType("\nlangType:" + std::to_string(cbHeader_->langType));
403 std::string cbIsEtwsMessage("\nisEtws:" + std::to_string(cbHeader_->bEtwsMessage));
404 std::string cbMsgType("\ncbMsgType:" + std::to_string(cbHeader_->cbMsgType));
405 std::string cbWarningType("\nwarningType:" + std::to_string(cbHeader_->warningType));
406 std::string cbSerialNum("\nserialNum: geoScope " + std::to_string(cbHeader_->serialNum.geoScope) + "| updateNum " +
407 std::to_string(cbHeader_->serialNum.updateNum) + "| msgCode " +
408 std::to_string(cbHeader_->serialNum.msgCode));
409 std::string cbPage(
410 "\ntotal pages: " + std::to_string(cbHeader_->totalPages) + " page:" + std::to_string(cbHeader_->page));
411 std::string cbRecvTime("\nrecv time: " + std::to_string(cbHeader_->recvTime));
412 std::string cbDcsRaw("\ndcs: " + std::to_string(cbHeader_->dcs.rawData));
413 std::string cbMsgBody;
414 ConvertToUTF8(messageRaw_, cbMsgBody);
415 return cbMsgId.append(cbLangType)
416 .append(cbIsEtwsMessage)
417 .append(cbMsgType)
418 .append(cbWarningType)
419 .append(cbSerialNum)
420 .append(cbPage)
421 .append(cbRecvTime)
422 .append(cbDcsRaw)
423 .append("\nbody:")
424 .append(cbMsgBody);
425 }
426
GetFormat(int8_t & cbFormat) const427 bool GsmCbCodec::GetFormat(int8_t &cbFormat) const
428 {
429 cbFormat = CB_FORMAT_3GPP;
430 return true;
431 }
432
GetPriority(int8_t & cbPriority) const433 bool GsmCbCodec::GetPriority(int8_t &cbPriority) const
434 {
435 if (cbHeader_ == nullptr) {
436 TELEPHONY_LOGE("cbHeader_ is nullptr");
437 return false;
438 }
439 const int8_t normal = 0x00;
440 const int8_t emergency = HEX_VALUE_03;
441 if (cbHeader_->msgId >= PWS_FIRST_ID && cbHeader_->msgId <= PWS_LAST_ID) {
442 cbPriority = emergency;
443 } else {
444 cbPriority = normal;
445 }
446 return true;
447 }
448
GetGeoScope(uint8_t & geoScope) const449 bool GsmCbCodec::GetGeoScope(uint8_t &geoScope) const
450 {
451 if (cbHeader_ == nullptr) {
452 TELEPHONY_LOGE("cbHeader_ is nullptr");
453 return false;
454 }
455 geoScope = cbHeader_->serialNum.geoScope;
456 return true;
457 }
458
GetSerialNum(uint16_t & cbSerial) const459 bool GsmCbCodec::GetSerialNum(uint16_t &cbSerial) const
460 {
461 if (cbHeader_ == nullptr) {
462 TELEPHONY_LOGE("cbHeader_ is nullptr");
463 return false;
464 }
465 cbSerial = ((cbHeader_->serialNum.geoScope & HEX_VALUE_03) << HEX_VALUE_0E) |
466 ((cbHeader_->serialNum.msgCode & HEX_VALUE_03FF) << HEX_VALUE_04) |
467 (cbHeader_->serialNum.updateNum & HEX_VALUE_0F);
468 return true;
469 }
470
GetServiceCategory(uint16_t & cbCategoty) const471 bool GsmCbCodec::GetServiceCategory(uint16_t &cbCategoty) const
472 {
473 if (cbHeader_ == nullptr) {
474 TELEPHONY_LOGE("cbHeader_ is nullptr");
475 return false;
476 }
477 cbCategoty = cbHeader_->msgId;
478 return true;
479 }
480
GetWarningType(uint16_t & type) const481 bool GsmCbCodec::GetWarningType(uint16_t &type) const
482 {
483 if (cbHeader_ == nullptr) {
484 TELEPHONY_LOGE("cbHeader_ is nullptr");
485 return false;
486 }
487 type = cbHeader_->warningType;
488 return true;
489 }
490
IsEtwsPrimary(bool & primary) const491 bool GsmCbCodec::IsEtwsPrimary(bool &primary) const
492 {
493 if (cbHeader_ == nullptr) {
494 TELEPHONY_LOGE("cbHeader_ is nullptr");
495 return false;
496 }
497 primary = (cbHeader_->cbEtwsType == ETWS_PRIMARY);
498 return true;
499 }
500
IsEtwsMessage(bool & etws) const501 bool GsmCbCodec::IsEtwsMessage(bool &etws) const
502 {
503 if (cbHeader_ == nullptr) {
504 TELEPHONY_LOGE("cbHeader_ is nullptr");
505 return false;
506 }
507 etws = ((cbHeader_->msgId & ETWS_TYPE_MASK) == ETWS_TYPE);
508 return true;
509 }
510
IsCmasMessage(bool & cmas) const511 bool GsmCbCodec::IsCmasMessage(bool &cmas) const
512 {
513 if (cbHeader_ == nullptr) {
514 TELEPHONY_LOGE("cbHeader_ is nullptr");
515 return false;
516 }
517 cmas = ((cbHeader_->msgId >= CMAS_FIRST_ID) && (cbHeader_->msgId <= CMAS_LAST_ID));
518 return true;
519 }
520
IsEtwsEmergencyUserAlert(bool & alert) const521 bool GsmCbCodec::IsEtwsEmergencyUserAlert(bool &alert) const
522 {
523 uint16_t serial = 0;
524 if (!GetSerialNum(serial)) {
525 TELEPHONY_LOGE("Get serial num fail.");
526 return false;
527 }
528 alert = ((serial & EMERGENCY_USER_ALERT) != 0);
529 return true;
530 }
531
IsEtwsPopupAlert(bool & alert) const532 bool GsmCbCodec::IsEtwsPopupAlert(bool &alert) const
533 {
534 uint16_t serial = 0;
535 if (!GetSerialNum(serial)) {
536 TELEPHONY_LOGE("Get serial num fail.");
537 return false;
538 }
539 alert = ((serial & ETWS_POPUP) != 0);
540 return true;
541 }
542
GetCmasSeverity(uint8_t & severity) const543 bool GsmCbCodec::GetCmasSeverity(uint8_t &severity) const
544 {
545 uint16_t msgId = 0;
546 if (!GetMessageId(msgId)) {
547 TELEPHONY_LOGE("Get message id fail.");
548 return false;
549 }
550 switch (static_cast<CmasMsgType>(msgId)) {
551 case CmasMsgType::EXTREME_OBSERVED:
552 case CmasMsgType::EXTREME_OBSERVED_SPANISH:
553 case CmasMsgType::EXTREME_LIKELY:
554 case CmasMsgType::EXTREME_LIKELY_SPANISH:
555 case CmasMsgType::SEVERE_OBSERVED:
556 case CmasMsgType::SEVERE_OBSERVED_SPANISH:
557 case CmasMsgType::SEVERE_LIKELY:
558 case CmasMsgType::SEVERE_LIKELY_SPANISH:
559 severity = static_cast<uint8_t>(SmsCmaeSeverity::EXTREME);
560 break;
561 case CmasMsgType::ALERT_OBSERVED_DEFUALT:
562 case CmasMsgType::ALERT_OBSERVED_SPANISH:
563 case CmasMsgType::ALERT_LIKELY:
564 case CmasMsgType::ALERT_LIKELY_SPANISH:
565 case CmasMsgType::EXPECTED_OBSERVED:
566 case CmasMsgType::EXPECTED_OBSERVED_SPANISH:
567 case CmasMsgType::EXPECTED_LIKELY:
568 case CmasMsgType::EXPECTED_LIKELY_SPANISH:
569 severity = static_cast<uint8_t>(SmsCmaeSeverity::SEVERE);
570 break;
571 default:
572 severity = static_cast<uint8_t>(SmsCmaeSeverity::RESERVED);
573 break;
574 }
575 return true;
576 }
577
GetCmasUrgency(uint8_t & urgency) const578 bool GsmCbCodec::GetCmasUrgency(uint8_t &urgency) const
579 {
580 uint16_t msgId = 0;
581 if (!GetMessageId(msgId)) {
582 TELEPHONY_LOGE("Get message id fail.");
583 return false;
584 }
585 switch (static_cast<CmasMsgType>(msgId)) {
586 case CmasMsgType::EXTREME_OBSERVED:
587 case CmasMsgType::EXTREME_OBSERVED_SPANISH:
588 case CmasMsgType::EXTREME_LIKELY:
589 case CmasMsgType::EXTREME_LIKELY_SPANISH:
590 case CmasMsgType::ALERT_OBSERVED_DEFUALT:
591 case CmasMsgType::ALERT_OBSERVED_SPANISH:
592 case CmasMsgType::ALERT_LIKELY:
593 case CmasMsgType::ALERT_LIKELY_SPANISH:
594 urgency = static_cast<uint8_t>(SmsCmaeUrgency::IMMEDIATE);
595 break;
596 case CmasMsgType::SEVERE_OBSERVED:
597 case CmasMsgType::SEVERE_OBSERVED_SPANISH:
598 case CmasMsgType::SEVERE_LIKELY:
599 case CmasMsgType::SEVERE_LIKELY_SPANISH:
600 case CmasMsgType::EXPECTED_OBSERVED:
601 case CmasMsgType::EXPECTED_OBSERVED_SPANISH:
602 case CmasMsgType::EXPECTED_LIKELY:
603 case CmasMsgType::EXPECTED_LIKELY_SPANISH:
604 urgency = static_cast<uint8_t>(SmsCmaeUrgency::EXPECTED);
605 break;
606 default:
607 urgency = static_cast<uint8_t>(SmsCmaeUrgency::RESERVED);
608 break;
609 }
610 return true;
611 }
612
GetCmasCertainty(uint8_t & certainty) const613 bool GsmCbCodec::GetCmasCertainty(uint8_t &certainty) const
614 {
615 uint16_t msgId = 0;
616 if (!GetMessageId(msgId)) {
617 TELEPHONY_LOGE("Get message id fail.");
618 return false;
619 }
620 switch (static_cast<CmasMsgType>(msgId)) {
621 case CmasMsgType::EXTREME_OBSERVED:
622 case CmasMsgType::EXTREME_OBSERVED_SPANISH:
623 case CmasMsgType::SEVERE_OBSERVED:
624 case CmasMsgType::SEVERE_OBSERVED_SPANISH:
625 case CmasMsgType::ALERT_OBSERVED_DEFUALT:
626 case CmasMsgType::ALERT_OBSERVED_SPANISH:
627 case CmasMsgType::EXPECTED_OBSERVED:
628 case CmasMsgType::EXPECTED_OBSERVED_SPANISH:
629 certainty = static_cast<uint8_t>(SmsCmaeCertainty::OBSERVED);
630 break;
631 case CmasMsgType::EXTREME_LIKELY:
632 case CmasMsgType::EXTREME_LIKELY_SPANISH:
633 case CmasMsgType::SEVERE_LIKELY:
634 case CmasMsgType::SEVERE_LIKELY_SPANISH:
635 case CmasMsgType::ALERT_LIKELY:
636 case CmasMsgType::ALERT_LIKELY_SPANISH:
637 case CmasMsgType::EXPECTED_LIKELY:
638 case CmasMsgType::EXPECTED_LIKELY_SPANISH:
639 certainty = static_cast<uint8_t>(SmsCmaeCertainty::LIKELY);
640 break;
641 default:
642 certainty = static_cast<uint8_t>(SmsCmaeCertainty::RESERVED);
643 break;
644 }
645 return true;
646 }
647
GetCmasCategory(uint8_t & cmasCategory) const648 bool GsmCbCodec::GetCmasCategory(uint8_t &cmasCategory) const
649 {
650 cmasCategory = static_cast<uint8_t>(SmsCmaeCategory::RESERVED);
651 return true;
652 }
653
GetCmasResponseType(uint8_t & cmasRes) const654 bool GsmCbCodec::GetCmasResponseType(uint8_t &cmasRes) const
655 {
656 cmasRes = static_cast<uint8_t>(SmsCmaeResponseType::RESERVED);
657 return true;
658 }
659
GetMessageId(uint16_t & msgId) const660 bool GsmCbCodec::GetMessageId(uint16_t &msgId) const
661 {
662 if (cbHeader_ == nullptr) {
663 TELEPHONY_LOGE("cbHeader_ is nullptr");
664 return false;
665 }
666 msgId = cbHeader_->msgId;
667 return true;
668 }
669
GetCmasMessageClass(uint8_t & cmasClass) const670 bool GsmCbCodec::GetCmasMessageClass(uint8_t &cmasClass) const
671 {
672 uint16_t cbMsgId = 0;
673 if (!GetMessageId(cbMsgId)) {
674 TELEPHONY_LOGE("get cb id fail.");
675 return false;
676 }
677 cmasClass = CMASClass(cbMsgId);
678 return true;
679 }
680
GetMsgType(uint8_t & msgType) const681 bool GsmCbCodec::GetMsgType(uint8_t &msgType) const
682 {
683 if (cbHeader_ == nullptr) {
684 TELEPHONY_LOGE("cbHeader_ is nullptr");
685 return false;
686 }
687 msgType = cbHeader_->cbMsgType;
688 return true;
689 }
690
GetLangType(uint8_t & lan) const691 bool GsmCbCodec::GetLangType(uint8_t &lan) const
692 {
693 if (cbHeader_ == nullptr) {
694 TELEPHONY_LOGE("cbHeader_ is nullptr");
695 return false;
696 }
697 lan = cbHeader_->langType;
698 return true;
699 }
700
GetDcs(uint8_t & dcs) const701 bool GsmCbCodec::GetDcs(uint8_t &dcs) const
702 {
703 if (cbHeader_ == nullptr) {
704 TELEPHONY_LOGE("cbHeader_ is nullptr");
705 return false;
706 }
707 dcs = cbHeader_->dcs.codingScheme;
708 return true;
709 }
710
GetReceiveTime(int64_t & receiveTime) const711 bool GsmCbCodec::GetReceiveTime(int64_t &receiveTime) const
712 {
713 if (cbHeader_ == nullptr) {
714 TELEPHONY_LOGE("nullptr error.");
715 return false;
716 }
717 receiveTime = cbHeader_->recvTime;
718 if (receiveTime == 0) {
719 TELEPHONY_LOGI("receiveTime = 0");
720 time_t recvTime = time(NULL);
721 receiveTime = static_cast<int64_t>(recvTime);
722 }
723 return true;
724 }
725 } // namespace Telephony
726 } // namespace OHOS