10825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/*
20825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Copyright (C) 2006 The Android Open Source Project
30825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
40825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Licensed under the Apache License, Version 2.0 (the "License");
50825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * you may not use this file except in compliance with the License.
60825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * You may obtain a copy of the License at
70825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
80825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *      http://www.apache.org/licenses/LICENSE-2.0
90825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Unless required by applicable law or agreed to in writing, software
110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * distributed under the License is distributed on an "AS IS" BASIS,
120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * See the License for the specific language governing permissions and
140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * limitations under the License.
150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */
160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
170825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepackage com.android.internal.telephony;
180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
190825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.SmsConstants;
200825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.util.HexDump;
210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
220825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.io.ByteArrayInputStream;
230825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.io.ByteArrayOutputStream;
240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
250825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.ArrayList;
260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/**
280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * SMS user data header, as specified in TS 23.040 9.2.3.24.
290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */
300825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepublic class SmsHeader {
310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // TODO(cleanup): this data structure is generally referred to as
330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // the 'user data header' or UDH, and so the class name should
340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // change to reflect this...
350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** SMS user data header information element identifiers.
370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * (see TS 23.040 9.2.3.24)
380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static final int ELT_ID_CONCATENATED_8_BIT_REFERENCE       = 0x00;
400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static final int ELT_ID_SPECIAL_SMS_MESSAGE_INDICATION     = 0x01;
410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static final int ELT_ID_APPLICATION_PORT_ADDRESSING_8_BIT  = 0x04;
420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static final int ELT_ID_APPLICATION_PORT_ADDRESSING_16_BIT = 0x05;
430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static final int ELT_ID_SMSC_CONTROL_PARAMS                = 0x06;
440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static final int ELT_ID_UDH_SOURCE_INDICATION              = 0x07;
450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static final int ELT_ID_CONCATENATED_16_BIT_REFERENCE      = 0x08;
460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static final int ELT_ID_WIRELESS_CTRL_MSG_PROTOCOL         = 0x09;
470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static final int ELT_ID_TEXT_FORMATTING                    = 0x0A;
480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static final int ELT_ID_PREDEFINED_SOUND                   = 0x0B;
490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static final int ELT_ID_USER_DEFINED_SOUND                 = 0x0C;
500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static final int ELT_ID_PREDEFINED_ANIMATION               = 0x0D;
510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static final int ELT_ID_LARGE_ANIMATION                    = 0x0E;
520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static final int ELT_ID_SMALL_ANIMATION                    = 0x0F;
530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static final int ELT_ID_LARGE_PICTURE                      = 0x10;
540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static final int ELT_ID_SMALL_PICTURE                      = 0x11;
550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static final int ELT_ID_VARIABLE_PICTURE                   = 0x12;
560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static final int ELT_ID_USER_PROMPT_INDICATOR              = 0x13;
570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static final int ELT_ID_EXTENDED_OBJECT                    = 0x14;
580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static final int ELT_ID_REUSED_EXTENDED_OBJECT             = 0x15;
590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static final int ELT_ID_COMPRESSION_CONTROL                = 0x16;
600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static final int ELT_ID_OBJECT_DISTR_INDICATOR             = 0x17;
610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static final int ELT_ID_STANDARD_WVG_OBJECT                = 0x18;
620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static final int ELT_ID_CHARACTER_SIZE_WVG_OBJECT          = 0x19;
630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static final int ELT_ID_EXTENDED_OBJECT_DATA_REQUEST_CMD   = 0x1A;
640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static final int ELT_ID_RFC_822_EMAIL_HEADER               = 0x20;
650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static final int ELT_ID_HYPERLINK_FORMAT_ELEMENT           = 0x21;
660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static final int ELT_ID_REPLY_ADDRESS_ELEMENT              = 0x22;
670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static final int ELT_ID_ENHANCED_VOICE_MAIL_INFORMATION    = 0x23;
680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static final int ELT_ID_NATIONAL_LANGUAGE_SINGLE_SHIFT     = 0x24;
690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static final int ELT_ID_NATIONAL_LANGUAGE_LOCKING_SHIFT    = 0x25;
700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static final int PORT_WAP_PUSH = 2948;
720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static final int PORT_WAP_WSP  = 9200;
730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static class PortAddrs {
750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        public int destPort;
760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        public int origPort;
770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        public boolean areEightBits;
780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static class ConcatRef {
810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        public int refNumber;
820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        public int seqNumber;
830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        public int msgCount;
840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        public boolean isEightBits;
850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
87299a348cd9bdcc21c5c4a6cd6c9a825e5d711908Uma Maheswari Ramalingam    public static class SpecialSmsMsg {
88299a348cd9bdcc21c5c4a6cd6c9a825e5d711908Uma Maheswari Ramalingam        public int msgIndType;
89299a348cd9bdcc21c5c4a6cd6c9a825e5d711908Uma Maheswari Ramalingam        public int msgCount;
90299a348cd9bdcc21c5c4a6cd6c9a825e5d711908Uma Maheswari Ramalingam    }
91299a348cd9bdcc21c5c4a6cd6c9a825e5d711908Uma Maheswari Ramalingam
920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * A header element that is not explicitly parsed, meaning not
94299a348cd9bdcc21c5c4a6cd6c9a825e5d711908Uma Maheswari Ramalingam     * PortAddrs or ConcatRef or SpecialSmsMsg.
950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static class MiscElt {
970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        public int id;
980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        public byte[] data;
990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public PortAddrs portAddrs;
1020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public ConcatRef concatRef;
103299a348cd9bdcc21c5c4a6cd6c9a825e5d711908Uma Maheswari Ramalingam    public ArrayList<SpecialSmsMsg> specialSmsMsgList = new ArrayList<SpecialSmsMsg>();
1040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public ArrayList<MiscElt> miscEltList = new ArrayList<MiscElt>();
1050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** 7 bit national language locking shift table, or 0 for GSM default 7 bit alphabet. */
1070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public int languageTable;
1080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** 7 bit national language single shift table, or 0 for GSM default 7 bit extension table. */
1100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public int languageShiftTable;
1110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public SmsHeader() {}
1130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
1150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Create structured SmsHeader object from serialized byte array representation.
1160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * (see TS 23.040 9.2.3.24)
1170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param data is user data header bytes
1180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @return SmsHeader object
1190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
1200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static SmsHeader fromByteArray(byte[] data) {
1210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        ByteArrayInputStream inStream = new ByteArrayInputStream(data);
1220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        SmsHeader smsHeader = new SmsHeader();
1230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        while (inStream.available() > 0) {
1240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            /**
1250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville             * NOTE: as defined in the spec, ConcatRef and PortAddr
1260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville             * fields should not reoccur, but if they do the last
1270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville             * occurrence is to be used.  Also, for ConcatRef
1280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville             * elements, if the count is zero, sequence is zero, or
1290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville             * sequence is larger than count, the entire element is to
1300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville             * be ignored.
1310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville             */
1320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            int id = inStream.read();
1330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            int length = inStream.read();
1340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            ConcatRef concatRef;
1350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            PortAddrs portAddrs;
1360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            switch (id) {
1370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case ELT_ID_CONCATENATED_8_BIT_REFERENCE:
1380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                concatRef = new ConcatRef();
1390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                concatRef.refNumber = inStream.read();
1400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                concatRef.msgCount = inStream.read();
1410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                concatRef.seqNumber = inStream.read();
1420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                concatRef.isEightBits = true;
1430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (concatRef.msgCount != 0 && concatRef.seqNumber != 0 &&
1440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        concatRef.seqNumber <= concatRef.msgCount) {
1450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    smsHeader.concatRef = concatRef;
1460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
1470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
1480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case ELT_ID_CONCATENATED_16_BIT_REFERENCE:
1490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                concatRef = new ConcatRef();
1500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                concatRef.refNumber = (inStream.read() << 8) | inStream.read();
1510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                concatRef.msgCount = inStream.read();
1520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                concatRef.seqNumber = inStream.read();
1530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                concatRef.isEightBits = false;
1540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (concatRef.msgCount != 0 && concatRef.seqNumber != 0 &&
1550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        concatRef.seqNumber <= concatRef.msgCount) {
1560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    smsHeader.concatRef = concatRef;
1570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
1580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
1590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case ELT_ID_APPLICATION_PORT_ADDRESSING_8_BIT:
1600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                portAddrs = new PortAddrs();
1610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                portAddrs.destPort = inStream.read();
1620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                portAddrs.origPort = inStream.read();
1630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                portAddrs.areEightBits = true;
1640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                smsHeader.portAddrs = portAddrs;
1650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
1660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case ELT_ID_APPLICATION_PORT_ADDRESSING_16_BIT:
1670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                portAddrs = new PortAddrs();
1680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                portAddrs.destPort = (inStream.read() << 8) | inStream.read();
1690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                portAddrs.origPort = (inStream.read() << 8) | inStream.read();
1700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                portAddrs.areEightBits = false;
1710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                smsHeader.portAddrs = portAddrs;
1720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
1730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case ELT_ID_NATIONAL_LANGUAGE_SINGLE_SHIFT:
1740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                smsHeader.languageShiftTable = inStream.read();
1750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
1760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case ELT_ID_NATIONAL_LANGUAGE_LOCKING_SHIFT:
1770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                smsHeader.languageTable = inStream.read();
1780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
179299a348cd9bdcc21c5c4a6cd6c9a825e5d711908Uma Maheswari Ramalingam            case ELT_ID_SPECIAL_SMS_MESSAGE_INDICATION:
180299a348cd9bdcc21c5c4a6cd6c9a825e5d711908Uma Maheswari Ramalingam                SpecialSmsMsg specialSmsMsg = new SpecialSmsMsg();
181299a348cd9bdcc21c5c4a6cd6c9a825e5d711908Uma Maheswari Ramalingam                specialSmsMsg.msgIndType = inStream.read();
182299a348cd9bdcc21c5c4a6cd6c9a825e5d711908Uma Maheswari Ramalingam                specialSmsMsg.msgCount = inStream.read();
183299a348cd9bdcc21c5c4a6cd6c9a825e5d711908Uma Maheswari Ramalingam                smsHeader.specialSmsMsgList.add(specialSmsMsg);
184299a348cd9bdcc21c5c4a6cd6c9a825e5d711908Uma Maheswari Ramalingam                break;
1850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            default:
1860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                MiscElt miscElt = new MiscElt();
1870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                miscElt.id = id;
1880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                miscElt.data = new byte[length];
1890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                inStream.read(miscElt.data, 0, length);
1900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                smsHeader.miscEltList.add(miscElt);
1910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
1920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
1930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return smsHeader;
1940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
1970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Create serialized byte array representation from structured SmsHeader object.
1980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * (see TS 23.040 9.2.3.24)
1990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @return Byte array representing the SmsHeader
2000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
2010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static byte[] toByteArray(SmsHeader smsHeader) {
2020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if ((smsHeader.portAddrs == null) &&
2030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            (smsHeader.concatRef == null) &&
204299a348cd9bdcc21c5c4a6cd6c9a825e5d711908Uma Maheswari Ramalingam            (smsHeader.specialSmsMsgList.isEmpty()) &&
2050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            (smsHeader.miscEltList.isEmpty()) &&
2060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            (smsHeader.languageShiftTable == 0) &&
2070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            (smsHeader.languageTable == 0)) {
2080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return null;
2090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
2100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        ByteArrayOutputStream outStream =
2120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                new ByteArrayOutputStream(SmsConstants.MAX_USER_DATA_BYTES);
2130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        ConcatRef concatRef = smsHeader.concatRef;
2140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (concatRef != null) {
2150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (concatRef.isEightBits) {
2160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                outStream.write(ELT_ID_CONCATENATED_8_BIT_REFERENCE);
2170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                outStream.write(3);
2180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                outStream.write(concatRef.refNumber);
2190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else {
2200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                outStream.write(ELT_ID_CONCATENATED_16_BIT_REFERENCE);
2210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                outStream.write(4);
2220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                outStream.write(concatRef.refNumber >>> 8);
2230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                outStream.write(concatRef.refNumber & 0x00FF);
2240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
2250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            outStream.write(concatRef.msgCount);
2260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            outStream.write(concatRef.seqNumber);
2270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
2280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        PortAddrs portAddrs = smsHeader.portAddrs;
2290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (portAddrs != null) {
2300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (portAddrs.areEightBits) {
2310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                outStream.write(ELT_ID_APPLICATION_PORT_ADDRESSING_8_BIT);
2320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                outStream.write(2);
2330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                outStream.write(portAddrs.destPort);
2340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                outStream.write(portAddrs.origPort);
2350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else {
2360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                outStream.write(ELT_ID_APPLICATION_PORT_ADDRESSING_16_BIT);
2370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                outStream.write(4);
2380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                outStream.write(portAddrs.destPort >>> 8);
2390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                outStream.write(portAddrs.destPort & 0x00FF);
2400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                outStream.write(portAddrs.origPort >>> 8);
2410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                outStream.write(portAddrs.origPort & 0x00FF);
2420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
2430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
2440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (smsHeader.languageShiftTable != 0) {
2450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            outStream.write(ELT_ID_NATIONAL_LANGUAGE_SINGLE_SHIFT);
2460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            outStream.write(1);
2470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            outStream.write(smsHeader.languageShiftTable);
2480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
2490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (smsHeader.languageTable != 0) {
2500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            outStream.write(ELT_ID_NATIONAL_LANGUAGE_LOCKING_SHIFT);
2510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            outStream.write(1);
2520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            outStream.write(smsHeader.languageTable);
2530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
254299a348cd9bdcc21c5c4a6cd6c9a825e5d711908Uma Maheswari Ramalingam        for (SpecialSmsMsg specialSmsMsg : smsHeader.specialSmsMsgList) {
255299a348cd9bdcc21c5c4a6cd6c9a825e5d711908Uma Maheswari Ramalingam            outStream.write(ELT_ID_SPECIAL_SMS_MESSAGE_INDICATION);
256299a348cd9bdcc21c5c4a6cd6c9a825e5d711908Uma Maheswari Ramalingam            outStream.write(2);
257299a348cd9bdcc21c5c4a6cd6c9a825e5d711908Uma Maheswari Ramalingam            outStream.write(specialSmsMsg.msgIndType & 0xFF);
258299a348cd9bdcc21c5c4a6cd6c9a825e5d711908Uma Maheswari Ramalingam            outStream.write(specialSmsMsg.msgCount & 0xFF);
259299a348cd9bdcc21c5c4a6cd6c9a825e5d711908Uma Maheswari Ramalingam        }
2600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        for (MiscElt miscElt : smsHeader.miscEltList) {
2610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            outStream.write(miscElt.id);
2620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            outStream.write(miscElt.data.length);
2630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            outStream.write(miscElt.data, 0, miscElt.data.length);
2640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
2650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return outStream.toByteArray();
2660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
2670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    @Override
2690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public String toString() {
2700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        StringBuilder builder = new StringBuilder();
2710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        builder.append("UserDataHeader ");
2720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        builder.append("{ ConcatRef ");
2730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (concatRef == null) {
2740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            builder.append("unset");
2750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else {
2760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            builder.append("{ refNumber=" + concatRef.refNumber);
2770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            builder.append(", msgCount=" + concatRef.msgCount);
2780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            builder.append(", seqNumber=" + concatRef.seqNumber);
2790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            builder.append(", isEightBits=" + concatRef.isEightBits);
2800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            builder.append(" }");
2810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
2820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        builder.append(", PortAddrs ");
2830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (portAddrs == null) {
2840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            builder.append("unset");
2850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else {
2860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            builder.append("{ destPort=" + portAddrs.destPort);
2870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            builder.append(", origPort=" + portAddrs.origPort);
2880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            builder.append(", areEightBits=" + portAddrs.areEightBits);
2890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            builder.append(" }");
2900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
2910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (languageShiftTable != 0) {
2920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            builder.append(", languageShiftTable=" + languageShiftTable);
2930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
2940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (languageTable != 0) {
2950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            builder.append(", languageTable=" + languageTable);
2960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
297299a348cd9bdcc21c5c4a6cd6c9a825e5d711908Uma Maheswari Ramalingam        for (SpecialSmsMsg specialSmsMsg : specialSmsMsgList) {
298299a348cd9bdcc21c5c4a6cd6c9a825e5d711908Uma Maheswari Ramalingam            builder.append(", SpecialSmsMsg ");
299299a348cd9bdcc21c5c4a6cd6c9a825e5d711908Uma Maheswari Ramalingam            builder.append("{ msgIndType=" + specialSmsMsg.msgIndType);
300299a348cd9bdcc21c5c4a6cd6c9a825e5d711908Uma Maheswari Ramalingam            builder.append(", msgCount=" + specialSmsMsg.msgCount);
301299a348cd9bdcc21c5c4a6cd6c9a825e5d711908Uma Maheswari Ramalingam            builder.append(" }");
302299a348cd9bdcc21c5c4a6cd6c9a825e5d711908Uma Maheswari Ramalingam        }
3030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        for (MiscElt miscElt : miscEltList) {
3040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            builder.append(", MiscElt ");
3050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            builder.append("{ id=" + miscElt.id);
3060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            builder.append(", length=" + miscElt.data.length);
3070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            builder.append(", data=" + HexDump.toHexString(miscElt.data));
3080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            builder.append(" }");
3090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
3100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        builder.append(" }");
3110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return builder.toString();
3120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville}
315