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 "sms_base_message.h"
17
18#include "securec.h"
19#include "sms_mms_errors.h"
20#include "sms_service_manager_client.h"
21#include "telephony_errors.h"
22#include "telephony_log_wrapper.h"
23#include "text_coder.h"
24#include "unicode/brkiter.h"
25#include "unicode/rbbi.h"
26#include "unicode/unistr.h"
27#include "unicode/ucnv.h"
28
29namespace OHOS {
30namespace Telephony {
31using namespace std;
32static constexpr uint8_t PID_87 = 0xc0;
33static constexpr uint8_t PID_7 = 0x40;
34static constexpr uint8_t PID_10_LOW = 0x3f;
35static constexpr int16_t WAP_PUSH_PORT = 2948;
36static constexpr uint8_t MAX_GSM_7BIT_DATA_LEN = 160;
37static constexpr uint8_t MAX_UCS2_DATA_LEN = 140;
38static constexpr uint8_t BYTE_BITS = 8;
39static constexpr uint8_t MAX_ADD_PARAM_LEN = 12;
40static constexpr uint8_t GSM_BEAR_DATA_LEN = 140;
41static constexpr uint8_t CHARSET_7BIT_BITS = 7;
42static constexpr uint16_t TAPI_TEXT_SIZE_MAX = 520;
43const std::string CT_SMSC = "10659401";
44
45string SmsBaseMessage::GetSmscAddr() const
46{
47    return scAddress_;
48}
49
50void SmsBaseMessage::SetSmscAddr(const string &address)
51{
52    scAddress_ = address;
53}
54
55string SmsBaseMessage::GetOriginatingAddress() const
56{
57    return originatingAddress_;
58}
59
60string SmsBaseMessage::GetVisibleOriginatingAddress() const
61{
62    return originatingAddress_;
63}
64
65enum SmsMessageClass SmsBaseMessage::GetMessageClass() const
66{
67    return msgClass_;
68}
69
70string SmsBaseMessage::GetVisibleMessageBody() const
71{
72    return visibleMessageBody_;
73}
74
75std::vector<uint8_t> SmsBaseMessage::GetRawPdu() const
76{
77    return rawPdu_;
78}
79
80std::string SmsBaseMessage::GetRawUserData() const
81{
82    return rawUserData_;
83}
84
85std::string SmsBaseMessage::GetRawWapPushUserData() const
86{
87    return rawWapPushUserData_;
88}
89
90int64_t SmsBaseMessage::GetScTimestamp() const
91{
92    return scTimestamp_;
93}
94
95// 3GPP TS 23.040 V5.1.0 9.2.3.9 TP Protocol Identifier (TP PID)
96bool SmsBaseMessage::IsReplaceMessage()
97{
98    uint8_t temp = static_cast<uint8_t>(protocolId_);
99    uint8_t tempPid = temp & PID_10_LOW;
100    bReplaceMessage_ = ((temp & PID_87) == PID_7) && (tempPid > 0) && (tempPid < MAX_REPLY_PID);
101    return bReplaceMessage_;
102}
103
104// Message Waiting Indication Status storage on the USIM
105bool SmsBaseMessage::IsCphsMwi() const
106{
107    return bCphsMwi_;
108}
109
110// 3GPP TS 23.040 V5.1.0 3.2.6 Messages Waiting
111bool SmsBaseMessage::IsMwiClear() const
112{
113    return bMwiClear_;
114}
115
116// 3GPP TS 23.040 V5.1.0 3.2.6 Messages Waiting
117bool SmsBaseMessage::IsMwiSet() const
118{
119    return bMwiSet_;
120}
121
122// 3GPP TS 23.040 V5.1.0 3.2.6 Messages Waiting
123bool SmsBaseMessage::IsMwiNotStore() const
124{
125    return bMwiNotStore_;
126}
127
128int SmsBaseMessage::GetStatus() const
129{
130    return status_;
131}
132
133bool SmsBaseMessage::IsSmsStatusReportMessage() const
134{
135    return bStatusReportMessage_;
136}
137
138bool SmsBaseMessage::HasReplyPath() const
139{
140    return hasReplyPath_;
141}
142
143int SmsBaseMessage::GetProtocolId() const
144{
145    return protocolId_;
146}
147
148std::shared_ptr<SmsConcat> SmsBaseMessage::GetConcatMsg()
149{
150    smsConcat_ = nullptr;
151    for (int i = 0; i < smsUserData_.headerCnt; i++) {
152        if (smsUserData_.header[i].udhType == UDH_CONCAT_8BIT) {
153            smsConcat_ = std::make_shared<SmsConcat>();
154            if (smsConcat_ == nullptr) {
155                TELEPHONY_LOGE("smsConcat is nullptr.");
156                break;
157            }
158            smsConcat_->is8Bits = true;
159            smsConcat_->totalSeg = smsUserData_.header[i].udh.concat8bit.totalSeg;
160            smsConcat_->seqNum = smsUserData_.header[i].udh.concat8bit.seqNum;
161            smsConcat_->msgRef = smsUserData_.header[i].udh.concat8bit.msgRef;
162            break;
163        } else if (smsUserData_.header[i].udhType == UDH_CONCAT_16BIT) {
164            smsConcat_ = std::make_shared<SmsConcat>();
165            if (smsConcat_ == nullptr) {
166                TELEPHONY_LOGE("smsConcat is nullptr.");
167                break;
168            }
169            smsConcat_->is8Bits = false;
170            smsConcat_->totalSeg = smsUserData_.header[i].udh.concat16bit.totalSeg;
171            smsConcat_->seqNum = smsUserData_.header[i].udh.concat16bit.seqNum;
172            smsConcat_->msgRef = smsUserData_.header[i].udh.concat16bit.msgRef;
173            break;
174        }
175    }
176    return smsConcat_;
177}
178
179std::shared_ptr<SmsAppPortAddr> SmsBaseMessage::GetPortAddress()
180{
181    portAddress_ = nullptr;
182    for (int i = 0; i < smsUserData_.headerCnt; i++) {
183        if (smsUserData_.header[i].udhType == UDH_APP_PORT_8BIT) {
184            portAddress_ = std::make_shared<SmsAppPortAddr>();
185            if (portAddress_ == nullptr) {
186                TELEPHONY_LOGE("portAddress_ is nullptr.");
187                break;
188            }
189            portAddress_->is8Bits = true;
190            portAddress_->destPort = smsUserData_.header[i].udh.appPort8bit.destPort;
191            portAddress_->originPort = smsUserData_.header[i].udh.appPort8bit.originPort;
192            break;
193        } else if (smsUserData_.header[i].udhType == UDH_APP_PORT_16BIT) {
194            portAddress_ = std::make_shared<SmsAppPortAddr>();
195            if (portAddress_ == nullptr) {
196                TELEPHONY_LOGE("portAddress_ is nullptr.");
197                break;
198            }
199            portAddress_->is8Bits = false;
200            portAddress_->destPort = smsUserData_.header[i].udh.appPort16bit.destPort;
201            portAddress_->originPort = smsUserData_.header[i].udh.appPort16bit.originPort;
202            break;
203        }
204    }
205    return portAddress_;
206}
207
208std::shared_ptr<SpecialSmsIndication> SmsBaseMessage::GetSpecialSmsInd()
209{
210    specialSmsInd_ = nullptr;
211    for (int i = 0; i < smsUserData_.headerCnt; i++) {
212        if (smsUserData_.header[i].udhType == UDH_SPECIAL_SMS) {
213            specialSmsInd_ = std::make_shared<SpecialSmsIndication>();
214            if (specialSmsInd_ == nullptr) {
215                TELEPHONY_LOGE("specialSmsInd_ is nullptr.");
216                break;
217            }
218            specialSmsInd_->bStore = smsUserData_.header[i].udh.specialInd.bStore;
219            specialSmsInd_->msgInd = smsUserData_.header[i].udh.specialInd.msgInd;
220            specialSmsInd_->waitMsgNum = smsUserData_.header[i].udh.specialInd.waitMsgNum;
221            break;
222        }
223    }
224    return specialSmsInd_;
225}
226
227bool SmsBaseMessage::IsConcatMsg()
228{
229    return (GetConcatMsg() == nullptr) ? false : true;
230}
231
232bool SmsBaseMessage::IsWapPushMsg()
233{
234    std::shared_ptr<SmsAppPortAddr> portAddress = GetPortAddress();
235    if (portAddress != nullptr && !portAddress->is8Bits) {
236        return portAddress->destPort == WAP_PUSH_PORT;
237    }
238    return false;
239}
240
241void SmsBaseMessage::ConvertMessageClass(enum SmsMessageClass msgClass)
242{
243    switch (msgClass) {
244        case SMS_SIM_MESSAGE:
245            msgClass_ = SmsMessageClass::SMS_SIM_MESSAGE;
246            break;
247        case SMS_INSTANT_MESSAGE:
248            msgClass_ = SmsMessageClass::SMS_INSTANT_MESSAGE;
249            break;
250        case SMS_OPTIONAL_MESSAGE:
251            msgClass_ = SmsMessageClass::SMS_OPTIONAL_MESSAGE;
252            break;
253        case SMS_FORWARD_MESSAGE:
254            msgClass_ = SmsMessageClass::SMS_FORWARD_MESSAGE;
255            break;
256        default:
257            msgClass_ = SmsMessageClass::SMS_CLASS_UNKNOWN;
258            break;
259    }
260}
261
262int SmsBaseMessage::GetMsgRef()
263{
264    return msgRef_;
265}
266
267int SmsBaseMessage::GetSegmentSize(
268    DataCodingScheme &codingScheme, int dataLen, bool bPortNum, MSG_LANGUAGE_ID_T &langId) const
269{
270    const int multiSegSms7BitLength = 153;
271    const int multiSegSmsUcs2Length = 134;
272    const int port = 6;
273    const int lang = 3;
274    int headerSize = 0;
275    int segSize = 0;
276    int maxSize = 0;
277    if (codingScheme == DATA_CODING_7BIT || codingScheme == DATA_CODING_ASCII7BIT) {
278        maxSize = MAX_GSM_7BIT_DATA_LEN;
279    } else if (codingScheme == DATA_CODING_8BIT || codingScheme == DATA_CODING_UCS2) {
280        maxSize = MAX_UCS2_DATA_LEN;
281    }
282
283    if (bPortNum == true) {
284        headerSize += port;
285    }
286
287    if (langId != MSG_ID_RESERVED_LANG) {
288        headerSize += lang;
289    }
290
291    if (codingScheme == DATA_CODING_7BIT || codingScheme == DATA_CODING_ASCII7BIT) {
292        if ((dataLen + headerSize) > maxSize) {
293            segSize = multiSegSms7BitLength;
294        } else {
295            segSize = dataLen;
296        }
297    } else if (codingScheme == DATA_CODING_8BIT || codingScheme == DATA_CODING_UCS2) {
298        if ((dataLen + headerSize) > maxSize) {
299            segSize = multiSegSmsUcs2Length;
300        } else {
301            segSize = dataLen;
302        }
303    }
304
305    return segSize;
306}
307
308int SmsBaseMessage::GetMaxSegmentSize(
309    DataCodingScheme &codingScheme, int dataLen, bool bPortNum, MSG_LANGUAGE_ID_T &langId, int replyAddrLen) const
310{
311    const int headerLen = 1;
312    const int concat = 5;
313    const int port = 6;
314    const int lang = 3;
315    const int reply = 2;
316    int headerSize = 0;
317    int segSize = 0;
318    int maxSize = 0;
319    if (codingScheme == DATA_CODING_7BIT || codingScheme == DATA_CODING_ASCII7BIT) {
320        maxSize = MAX_GSM_7BIT_DATA_LEN;
321    } else if (codingScheme == DATA_CODING_8BIT || codingScheme == DATA_CODING_UCS2) {
322        maxSize = MAX_UCS2_DATA_LEN;
323    }
324    if (bPortNum) {
325        headerSize += port;
326    }
327    if (langId != MSG_ID_RESERVED_LANG) {
328        headerSize += lang;
329    }
330    if (replyAddrLen > 0) {
331        headerSize += reply;
332        headerSize += replyAddrLen;
333    }
334    if (codingScheme == DATA_CODING_7BIT || codingScheme == DATA_CODING_ASCII7BIT) {
335        if ((dataLen + headerSize) > maxSize) {
336            segSize =
337                ((GSM_BEAR_DATA_LEN * BYTE_BITS) - ((headerLen + concat + headerSize) * BYTE_BITS)) / CHARSET_7BIT_BITS;
338        } else {
339            segSize = maxSize - headerSize;
340        }
341    } else if (codingScheme == DATA_CODING_8BIT || codingScheme == DATA_CODING_UCS2) {
342        if ((dataLen + headerSize) > maxSize) {
343            segSize = GSM_BEAR_DATA_LEN - (headerLen + concat + headerSize);
344        } else {
345            segSize = maxSize - headerSize;
346        }
347    }
348    return segSize;
349}
350
351void SmsBaseMessage::ConvertSpiltToUtf8(SplitInfo &split, const DataCodingScheme &codingType)
352{
353    if (split.encodeData.size() <= 0) {
354        TELEPHONY_LOGE("data is null");
355        return;
356    }
357
358    int dataSize = 0;
359    uint8_t buff[MAX_MSG_TEXT_LEN + 1] = { 0 };
360    switch (codingType) {
361        case DATA_CODING_7BIT: {
362            MsgLangInfo langInfo = {
363                0,
364            };
365            langInfo.bSingleShift = false;
366            langInfo.bLockingShift = false;
367            dataSize = TextCoder::Instance().Gsm7bitToUtf8(
368                buff, MAX_MSG_TEXT_LEN, split.encodeData.data(), split.encodeData.size(), langInfo);
369            break;
370        }
371        case DATA_CODING_UCS2: {
372            dataSize = TextCoder::Instance().Ucs2ToUtf8(
373                buff, MAX_MSG_TEXT_LEN, split.encodeData.data(), split.encodeData.size());
374            break;
375        }
376        default: {
377            if (split.encodeData.size() > sizeof(buff)) {
378                TELEPHONY_LOGE("AnalsisDeliverMsg data length invalid.");
379                return;
380            }
381            if (memcpy_s(buff, sizeof(buff), split.encodeData.data(), split.encodeData.size()) != EOK) {
382                TELEPHONY_LOGE("AnalsisDeliverMsg memcpy_s fail.");
383                return;
384            }
385            dataSize = static_cast<int>(split.encodeData.size());
386            buff[dataSize] = '\0';
387            break;
388        }
389    }
390
391    split.text.insert(0, reinterpret_cast<char *>(buff), dataSize);
392    TELEPHONY_LOGI("split text");
393}
394void SmsBaseMessage::SplitMessageUcs2(std::vector<struct SplitInfo> &splitResult, const uint8_t* decodeData,
395    int32_t encodeLen, int32_t segSize, DataCodingScheme &codingType)
396{
397    // this 3 para divide 2 because breakiterator class is init by a uint16_t pointer.
398    int32_t utf16Multiples = 2;
399    int32_t dataSize = encodeLen / utf16Multiples;
400    int32_t segSizeHalf = segSize / utf16Multiples;
401    int32_t index = 0;
402    int32_t oneByte = 1;
403    int32_t bits = 8;
404    MSG_LANGUAGE_ID_T langId = MSG_ID_RESERVED_LANG;
405    /*
406     * decodeData is uint8_t array, in order to init breakiterator class, need a uint16_t array. sample:[0xa0,0xa1,
407     * 0xa2,0xa3] become [0xa1a2,0xa3a4]
408     */
409    uint16_t decodeData16Bit[dataSize];
410    for (int i = 0; i < dataSize; i++) {
411        decodeData16Bit[i] = (decodeData[i * utf16Multiples] << bits) | decodeData[i * utf16Multiples + oneByte];
412    }
413    /*
414     * init breakiterator class. attention: createCharacterInstance is a factory method, in fact breakiterator is
415     * a pure abstract class, this fuction creat a object of subclass rulebasedbreakiterator.
416     */
417    icu::UnicodeString fullData(decodeData16Bit, dataSize);
418    UErrorCode status = U_ZERO_ERROR;
419    icu::BreakIterator* fullDataIter = icu::BreakIterator::createCharacterInstance(NULL, status);
420    if (U_FAILURE(status)) {
421        TELEPHONY_LOGE("Failed to create break iterator");
422        return;
423    }
424    // let breakiterator object point data need to operate
425    fullDataIter->setText(fullData);
426    // let iterator point zero element
427    fullDataIter->first();
428    // operation of segment except the last one, such as a pdu is devide to 3 segment, 1 and 2 are operated under.
429    while ((dataSize - index) > segSizeHalf) {
430        // init struct to store data
431        struct SplitInfo splitInfo;
432        splitInfo.langId = langId;
433        splitInfo.encodeType = codingType;
434        /*
435         * judge if the end of this segment is boundary, if it is boundary, store number of segsize data in struct
436         * and move the index agter this boundary to be the head of next segment
437         * if it is not boundary, use previous function or next function(set the para to -1)to find the previous
438         * boundary before end of segment
439         */
440        if (fullDataIter->isBoundary(index + segSizeHalf)) {
441            splitInfo.encodeData = std::vector<uint8_t>(&decodeData[index * utf16Multiples],
442                &decodeData[index * utf16Multiples] + segSize);
443            index += segSizeHalf;
444        } else {
445            splitInfo.encodeData = std::vector<uint8_t>(&decodeData[index * utf16Multiples],
446                &decodeData[index * utf16Multiples] + (fullDataIter->previous() - index) * utf16Multiples);
447            index = fullDataIter->current();
448        }
449        ConvertSpiltToUtf8(splitInfo, codingType);
450        splitResult.push_back(splitInfo);
451        fullDataIter->first();
452    }
453    // operation of last segment
454    struct SplitInfo splitInfo;
455    splitInfo.langId = langId;
456    splitInfo.encodeType = codingType;
457    splitInfo.encodeData = std::vector<uint8_t>(&decodeData[index * utf16Multiples],
458        &decodeData[index * utf16Multiples] + (dataSize - index) * utf16Multiples);
459    ConvertSpiltToUtf8(splitInfo, codingType);
460    splitResult.push_back(splitInfo);
461}
462
463void SmsBaseMessage::SplitMessage(std::vector<struct SplitInfo> &splitResult, const std::string &text,
464    bool force7BitCode, DataCodingScheme &codingType, bool bPortNum, const std::string &desAddr)
465{
466    std::string msgText(text);
467    // init destination array of pdu data
468    uint8_t decodeData[(MAX_GSM_7BIT_DATA_LEN * MAX_SEGMENT_NUM) + 1];
469    if (memset_s(decodeData, sizeof(decodeData), 0x00, sizeof(decodeData)) != EOK) {
470        TELEPHONY_LOGE("SplitMessage memset_s error!");
471        return;
472    }
473    int encodeLen = 0;
474    bool bAbnormal = false;
475    MSG_LANGUAGE_ID_T langId = MSG_ID_RESERVED_LANG;
476    codingType = force7BitCode ? DATA_CODING_7BIT : DATA_CODING_AUTO;
477    if (CT_SMSC.compare(desAddr) == 0) {
478        codingType = DATA_CODING_8BIT;
479    }
480    /*
481     * src is utf-8 code, DecodeMessage function aim to trans the src to dest unicode method depend on above operation
482     * encodeLen means the data length agter trans(although the dest unicode method is ucs2 or utf16, the length is the
483     * count of uint8_t) such as utf8 is 0x41, trans utf16 is 0x00,0x41, the length is 2
484     * after DecodeMessage function, the codingType will become DATA_CODING_UCS2 although before is DATA_CODING_AUTO
485     */
486    encodeLen = DecodeMessage(decodeData, sizeof(decodeData), codingType, msgText, bAbnormal, langId);
487    if (encodeLen <= 0) {
488        TELEPHONY_LOGE("encodeLen Less than or equal to 0");
489        return;
490    }
491    int segSize = 0;
492    int segCount = 0;
493    // get segment length mainly according to codingType.
494    segSize = GetSegmentSize(codingType, encodeLen, bPortNum, langId);
495    if (segSize > 0) {
496        segCount = ceil((double)encodeLen / (double)segSize);
497    }
498    /*
499     * under code is a special condition: the length of pdu data is over segSize conculated above and codingType is
500     * utf16(although the codingType displayed is ucs2). because in this condition a emoji(takeover 4 bytes in utf16)
501     * may be cut in 2 parts(first 2 byte in segment1 and last 2 in segment 2), under code will avoid this situation.
502     */
503    if (codingType == DATA_CODING_UCS2 && segCount > 1) {
504        SplitMessageUcs2(splitResult, decodeData, encodeLen, segSize, codingType);
505    } else {
506        int32_t index = 0;
507        for (int i = 0; i < segCount; i++) {
508            int userDataLen = 0;
509            struct SplitInfo splitInfo;
510            splitInfo.langId = langId;
511            splitInfo.encodeType = codingType;
512            uint8_t textData[TAPI_TEXT_SIZE_MAX + 1];
513            (void)memset_s(textData, sizeof(textData), 0x00, sizeof(textData));
514            if ((i + 1) == segCount) {
515                userDataLen = encodeLen - (i * segSize);
516            } else {
517                userDataLen = segSize;
518            }
519            splitInfo.encodeData = std::vector<uint8_t>(&decodeData[index], &decodeData[index] + userDataLen);
520            ConvertSpiltToUtf8(splitInfo, codingType);
521            splitResult.push_back(splitInfo);
522            index += segSize;
523        }
524    }
525}
526
527int32_t SmsBaseMessage::GetSmsSegmentsInfo(const std::string &message, bool force7BitCode, LengthInfo &lenInfo)
528{
529    uint8_t decodeData[(MAX_GSM_7BIT_DATA_LEN * MAX_SEGMENT_NUM) + 1];
530    if (memset_s(decodeData, sizeof(decodeData), 0x00, sizeof(decodeData)) != EOK) {
531        TELEPHONY_LOGE("SplitMessage memset_s error!");
532        return TELEPHONY_ERR_MEMSET_FAIL;
533    }
534    const uint8_t smsEncodingUnkown = 0;
535    const uint8_t smsEncoding7Bit = 1;
536    const uint8_t smsEncoding8Bit = 2;
537    const uint8_t smsEncoding16Bit = 3;
538    int encodeLen = 0;
539    bool bAbnormal = false;
540    MSG_LANGUAGE_ID_T langId = MSG_ID_RESERVED_LANG;
541    DataCodingScheme codingType = force7BitCode ? DATA_CODING_7BIT : DATA_CODING_AUTO;
542    encodeLen = DecodeMessage(decodeData, sizeof(decodeData), codingType, message, bAbnormal, langId);
543    if (encodeLen <= 0) {
544        TELEPHONY_LOGE("encodeLen Less than or equal to 0");
545        return SMS_MMS_DECODE_DATA_EMPTY;
546    }
547    int segSize = GetMaxSegmentSize(codingType, encodeLen, false, langId, MAX_ADD_PARAM_LEN);
548    TELEPHONY_LOGI("segSize = %{public}d", segSize);
549    lenInfo.msgEncodeCount = static_cast<uint16_t>(encodeLen);
550    if (codingType == DATA_CODING_7BIT || codingType == DATA_CODING_ASCII7BIT) {
551        lenInfo.dcs = smsEncoding7Bit;
552    } else if (codingType == DATA_CODING_UCS2) {
553        lenInfo.dcs = smsEncoding16Bit;
554    } else if (codingType == DATA_CODING_8BIT) {
555        lenInfo.dcs = smsEncoding8Bit;
556    } else {
557        lenInfo.dcs = smsEncodingUnkown;
558    }
559    if (lenInfo.dcs == smsEncoding16Bit) {
560        lenInfo.msgEncodeCount = lenInfo.msgEncodeCount / 2;
561        segSize = segSize / 2;
562    }
563    if (segSize != 0) {
564        lenInfo.msgRemainCount = static_cast<uint8_t>(((segSize - (lenInfo.msgEncodeCount % segSize))) % segSize);
565        lenInfo.msgSegCount = ceil(static_cast<double>(lenInfo.msgEncodeCount) / static_cast<double>(segSize));
566    }
567    return TELEPHONY_ERR_SUCCESS;
568}
569
570int32_t SmsBaseMessage::GetIndexOnSim() const
571{
572    return indexOnSim_;
573}
574
575void SmsBaseMessage::SetIndexOnSim(int32_t index)
576{
577    indexOnSim_ = index;
578}
579} // namespace Telephony
580} // namespace OHOS
581