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