• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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