14980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen/*
24980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen * Copyright (C) 2006 The Android Open Source Project
34980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen *
44980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen * Licensed under the Apache License, Version 2.0 (the "License");
54980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen * you may not use this file except in compliance with the License.
64980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen * You may obtain a copy of the License at
74980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen *
84980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen *      http://www.apache.org/licenses/LICENSE-2.0
94980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen *
104980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen * Unless required by applicable law or agreed to in writing, software
114980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen * distributed under the License is distributed on an "AS IS" BASIS,
124980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen * See the License for the specific language governing permissions and
144980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen * limitations under the License.
154980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen */
164980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen
174980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsenpackage com.android.internal.telephony;
184980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen
194980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsenimport com.android.internal.telephony.SmsConstants;
204980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsenimport com.android.internal.util.HexDump;
214980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen
224980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsenimport java.io.ByteArrayInputStream;
234980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsenimport java.io.ByteArrayOutputStream;
244980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen
254980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsenimport java.util.ArrayList;
264980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen
274980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen/**
284980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen * SMS user data header, as specified in TS 23.040 9.2.3.24.
294980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen */
304980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsenpublic class SmsHeader {
314980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen
324980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    // TODO(cleanup): this data structure is generally referred to as
334980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    // the 'user data header' or UDH, and so the class name should
344980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    // change to reflect this...
354980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen
364980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    /** SMS user data header information element identifiers.
374980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen     * (see TS 23.040 9.2.3.24)
384980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen     */
394980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static final int ELT_ID_CONCATENATED_8_BIT_REFERENCE       = 0x00;
404980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static final int ELT_ID_SPECIAL_SMS_MESSAGE_INDICATION     = 0x01;
414980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static final int ELT_ID_APPLICATION_PORT_ADDRESSING_8_BIT  = 0x04;
424980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static final int ELT_ID_APPLICATION_PORT_ADDRESSING_16_BIT = 0x05;
434980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static final int ELT_ID_SMSC_CONTROL_PARAMS                = 0x06;
444980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static final int ELT_ID_UDH_SOURCE_INDICATION              = 0x07;
454980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static final int ELT_ID_CONCATENATED_16_BIT_REFERENCE      = 0x08;
464980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static final int ELT_ID_WIRELESS_CTRL_MSG_PROTOCOL         = 0x09;
474980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static final int ELT_ID_TEXT_FORMATTING                    = 0x0A;
484980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static final int ELT_ID_PREDEFINED_SOUND                   = 0x0B;
494980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static final int ELT_ID_USER_DEFINED_SOUND                 = 0x0C;
504980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static final int ELT_ID_PREDEFINED_ANIMATION               = 0x0D;
514980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static final int ELT_ID_LARGE_ANIMATION                    = 0x0E;
524980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static final int ELT_ID_SMALL_ANIMATION                    = 0x0F;
534980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static final int ELT_ID_LARGE_PICTURE                      = 0x10;
544980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static final int ELT_ID_SMALL_PICTURE                      = 0x11;
554980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static final int ELT_ID_VARIABLE_PICTURE                   = 0x12;
564980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static final int ELT_ID_USER_PROMPT_INDICATOR              = 0x13;
574980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static final int ELT_ID_EXTENDED_OBJECT                    = 0x14;
584980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static final int ELT_ID_REUSED_EXTENDED_OBJECT             = 0x15;
594980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static final int ELT_ID_COMPRESSION_CONTROL                = 0x16;
604980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static final int ELT_ID_OBJECT_DISTR_INDICATOR             = 0x17;
614980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static final int ELT_ID_STANDARD_WVG_OBJECT                = 0x18;
624980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static final int ELT_ID_CHARACTER_SIZE_WVG_OBJECT          = 0x19;
634980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static final int ELT_ID_EXTENDED_OBJECT_DATA_REQUEST_CMD   = 0x1A;
644980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static final int ELT_ID_RFC_822_EMAIL_HEADER               = 0x20;
654980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static final int ELT_ID_HYPERLINK_FORMAT_ELEMENT           = 0x21;
664980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static final int ELT_ID_REPLY_ADDRESS_ELEMENT              = 0x22;
674980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static final int ELT_ID_ENHANCED_VOICE_MAIL_INFORMATION    = 0x23;
684980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static final int ELT_ID_NATIONAL_LANGUAGE_SINGLE_SHIFT     = 0x24;
694980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static final int ELT_ID_NATIONAL_LANGUAGE_LOCKING_SHIFT    = 0x25;
704980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen
714980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static final int PORT_WAP_PUSH = 2948;
724980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static final int PORT_WAP_WSP  = 9200;
734980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen
744980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static class PortAddrs {
754980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        public int destPort;
764980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        public int origPort;
774980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        public boolean areEightBits;
784980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    }
794980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen
804980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static class ConcatRef {
814980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        public int refNumber;
824980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        public int seqNumber;
834980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        public int msgCount;
844980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        public boolean isEightBits;
854980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    }
864980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen
874980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static class SpecialSmsMsg {
884980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        public int msgIndType;
894980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        public int msgCount;
904980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    }
914980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen
924980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    /**
934980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen     * A header element that is not explicitly parsed, meaning not
944980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen     * PortAddrs or ConcatRef or SpecialSmsMsg.
954980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen     */
964980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static class MiscElt {
974980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        public int id;
984980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        public byte[] data;
994980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    }
1004980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen
1014980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public PortAddrs portAddrs;
1024980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public ConcatRef concatRef;
1034980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public ArrayList<SpecialSmsMsg> specialSmsMsgList = new ArrayList<SpecialSmsMsg>();
1044980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public ArrayList<MiscElt> miscEltList = new ArrayList<MiscElt>();
1054980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen
1064980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    /** 7 bit national language locking shift table, or 0 for GSM default 7 bit alphabet. */
1074980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public int languageTable;
1084980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen
1094980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    /** 7 bit national language single shift table, or 0 for GSM default 7 bit extension table. */
1104980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public int languageShiftTable;
1114980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen
1124980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public SmsHeader() {}
1134980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen
1144980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    /**
1154980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen     * Create structured SmsHeader object from serialized byte array representation.
1164980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen     * (see TS 23.040 9.2.3.24)
1174980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen     * @param data is user data header bytes
1184980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen     * @return SmsHeader object
1194980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen     */
1204980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static SmsHeader fromByteArray(byte[] data) {
1214980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        ByteArrayInputStream inStream = new ByteArrayInputStream(data);
1224980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        SmsHeader smsHeader = new SmsHeader();
1234980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        while (inStream.available() > 0) {
1244980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            /**
1254980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen             * NOTE: as defined in the spec, ConcatRef and PortAddr
1264980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen             * fields should not reoccur, but if they do the last
1274980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen             * occurrence is to be used.  Also, for ConcatRef
1284980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen             * elements, if the count is zero, sequence is zero, or
1294980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen             * sequence is larger than count, the entire element is to
1304980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen             * be ignored.
1314980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen             */
1324980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            int id = inStream.read();
1334980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            int length = inStream.read();
1344980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            ConcatRef concatRef;
1354980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            PortAddrs portAddrs;
1364980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            switch (id) {
1374980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            case ELT_ID_CONCATENATED_8_BIT_REFERENCE:
1384980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                concatRef = new ConcatRef();
1394980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                concatRef.refNumber = inStream.read();
1404980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                concatRef.msgCount = inStream.read();
1414980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                concatRef.seqNumber = inStream.read();
1424980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                concatRef.isEightBits = true;
1434980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                if (concatRef.msgCount != 0 && concatRef.seqNumber != 0 &&
1444980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                        concatRef.seqNumber <= concatRef.msgCount) {
1454980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                    smsHeader.concatRef = concatRef;
1464980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                }
1474980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                break;
1484980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            case ELT_ID_CONCATENATED_16_BIT_REFERENCE:
1494980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                concatRef = new ConcatRef();
1504980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                concatRef.refNumber = (inStream.read() << 8) | inStream.read();
1514980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                concatRef.msgCount = inStream.read();
1524980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                concatRef.seqNumber = inStream.read();
1534980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                concatRef.isEightBits = false;
1544980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                if (concatRef.msgCount != 0 && concatRef.seqNumber != 0 &&
1554980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                        concatRef.seqNumber <= concatRef.msgCount) {
1564980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                    smsHeader.concatRef = concatRef;
1574980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                }
1584980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                break;
1594980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            case ELT_ID_APPLICATION_PORT_ADDRESSING_8_BIT:
1604980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                portAddrs = new PortAddrs();
1614980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                portAddrs.destPort = inStream.read();
1624980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                portAddrs.origPort = inStream.read();
1634980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                portAddrs.areEightBits = true;
1644980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                smsHeader.portAddrs = portAddrs;
1654980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                break;
1664980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            case ELT_ID_APPLICATION_PORT_ADDRESSING_16_BIT:
1674980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                portAddrs = new PortAddrs();
1684980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                portAddrs.destPort = (inStream.read() << 8) | inStream.read();
1694980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                portAddrs.origPort = (inStream.read() << 8) | inStream.read();
1704980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                portAddrs.areEightBits = false;
1714980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                smsHeader.portAddrs = portAddrs;
1724980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                break;
1734980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            case ELT_ID_NATIONAL_LANGUAGE_SINGLE_SHIFT:
1744980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                smsHeader.languageShiftTable = inStream.read();
1754980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                break;
1764980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            case ELT_ID_NATIONAL_LANGUAGE_LOCKING_SHIFT:
1774980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                smsHeader.languageTable = inStream.read();
1784980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                break;
1794980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            case ELT_ID_SPECIAL_SMS_MESSAGE_INDICATION:
1804980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                SpecialSmsMsg specialSmsMsg = new SpecialSmsMsg();
1814980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                specialSmsMsg.msgIndType = inStream.read();
1824980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                specialSmsMsg.msgCount = inStream.read();
1834980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                smsHeader.specialSmsMsgList.add(specialSmsMsg);
1844980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                break;
1854980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            default:
1864980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                MiscElt miscElt = new MiscElt();
1874980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                miscElt.id = id;
1884980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                miscElt.data = new byte[length];
1894980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                inStream.read(miscElt.data, 0, length);
1904980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                smsHeader.miscEltList.add(miscElt);
1914980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            }
1924980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        }
1934980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        return smsHeader;
1944980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    }
1954980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen
1964980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    /**
1974980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen     * Create serialized byte array representation from structured SmsHeader object.
1984980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen     * (see TS 23.040 9.2.3.24)
1994980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen     * @return Byte array representing the SmsHeader
2004980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen     */
2014980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public static byte[] toByteArray(SmsHeader smsHeader) {
2024980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        if ((smsHeader.portAddrs == null) &&
2034980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            (smsHeader.concatRef == null) &&
2044980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            (smsHeader.specialSmsMsgList.isEmpty()) &&
2054980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            (smsHeader.miscEltList.isEmpty()) &&
2064980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            (smsHeader.languageShiftTable == 0) &&
2074980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            (smsHeader.languageTable == 0)) {
2084980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            return null;
2094980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        }
2104980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen
2114980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        ByteArrayOutputStream outStream =
2124980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                new ByteArrayOutputStream(SmsConstants.MAX_USER_DATA_BYTES);
2134980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        ConcatRef concatRef = smsHeader.concatRef;
2144980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        if (concatRef != null) {
2154980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            if (concatRef.isEightBits) {
2164980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                outStream.write(ELT_ID_CONCATENATED_8_BIT_REFERENCE);
2174980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                outStream.write(3);
2184980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                outStream.write(concatRef.refNumber);
2194980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            } else {
2204980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                outStream.write(ELT_ID_CONCATENATED_16_BIT_REFERENCE);
2214980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                outStream.write(4);
2224980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                outStream.write(concatRef.refNumber >>> 8);
2234980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                outStream.write(concatRef.refNumber & 0x00FF);
2244980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            }
2254980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            outStream.write(concatRef.msgCount);
2264980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            outStream.write(concatRef.seqNumber);
2274980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        }
2284980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        PortAddrs portAddrs = smsHeader.portAddrs;
2294980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        if (portAddrs != null) {
2304980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            if (portAddrs.areEightBits) {
2314980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                outStream.write(ELT_ID_APPLICATION_PORT_ADDRESSING_8_BIT);
2324980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                outStream.write(2);
2334980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                outStream.write(portAddrs.destPort);
2344980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                outStream.write(portAddrs.origPort);
2354980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            } else {
2364980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                outStream.write(ELT_ID_APPLICATION_PORT_ADDRESSING_16_BIT);
2374980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                outStream.write(4);
2384980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                outStream.write(portAddrs.destPort >>> 8);
2394980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                outStream.write(portAddrs.destPort & 0x00FF);
2404980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                outStream.write(portAddrs.origPort >>> 8);
2414980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen                outStream.write(portAddrs.origPort & 0x00FF);
2424980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            }
2434980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        }
2444980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        if (smsHeader.languageShiftTable != 0) {
2454980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            outStream.write(ELT_ID_NATIONAL_LANGUAGE_SINGLE_SHIFT);
2464980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            outStream.write(1);
2474980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            outStream.write(smsHeader.languageShiftTable);
2484980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        }
2494980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        if (smsHeader.languageTable != 0) {
2504980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            outStream.write(ELT_ID_NATIONAL_LANGUAGE_LOCKING_SHIFT);
2514980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            outStream.write(1);
2524980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            outStream.write(smsHeader.languageTable);
2534980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        }
2544980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        for (SpecialSmsMsg specialSmsMsg : smsHeader.specialSmsMsgList) {
2554980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            outStream.write(ELT_ID_SPECIAL_SMS_MESSAGE_INDICATION);
2564980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            outStream.write(2);
2574980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            outStream.write(specialSmsMsg.msgIndType & 0xFF);
2584980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            outStream.write(specialSmsMsg.msgCount & 0xFF);
2594980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        }
2604980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        for (MiscElt miscElt : smsHeader.miscEltList) {
2614980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            outStream.write(miscElt.id);
2624980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            outStream.write(miscElt.data.length);
2634980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            outStream.write(miscElt.data, 0, miscElt.data.length);
2644980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        }
2654980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        return outStream.toByteArray();
2664980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    }
2674980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen
2684980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    @Override
2694980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    public String toString() {
2704980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        StringBuilder builder = new StringBuilder();
2714980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        builder.append("UserDataHeader ");
2724980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        builder.append("{ ConcatRef ");
2734980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        if (concatRef == null) {
2744980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            builder.append("unset");
2754980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        } else {
2764980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            builder.append("{ refNumber=" + concatRef.refNumber);
2774980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            builder.append(", msgCount=" + concatRef.msgCount);
2784980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            builder.append(", seqNumber=" + concatRef.seqNumber);
2794980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            builder.append(", isEightBits=" + concatRef.isEightBits);
2804980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            builder.append(" }");
2814980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        }
2824980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        builder.append(", PortAddrs ");
2834980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        if (portAddrs == null) {
2844980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            builder.append("unset");
2854980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        } else {
2864980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            builder.append("{ destPort=" + portAddrs.destPort);
2874980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            builder.append(", origPort=" + portAddrs.origPort);
2884980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            builder.append(", areEightBits=" + portAddrs.areEightBits);
2894980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            builder.append(" }");
2904980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        }
2914980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        if (languageShiftTable != 0) {
2924980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            builder.append(", languageShiftTable=" + languageShiftTable);
2934980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        }
2944980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        if (languageTable != 0) {
2954980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            builder.append(", languageTable=" + languageTable);
2964980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        }
2974980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        for (SpecialSmsMsg specialSmsMsg : specialSmsMsgList) {
2984980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            builder.append(", SpecialSmsMsg ");
2994980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            builder.append("{ msgIndType=" + specialSmsMsg.msgIndType);
3004980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            builder.append(", msgCount=" + specialSmsMsg.msgCount);
3014980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            builder.append(" }");
3024980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        }
3034980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        for (MiscElt miscElt : miscEltList) {
3044980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            builder.append(", MiscElt ");
3054980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            builder.append("{ id=" + miscElt.id);
3064980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            builder.append(", length=" + miscElt.data.length);
3074980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            builder.append(", data=" + HexDump.toHexString(miscElt.data));
3084980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen            builder.append(" }");
3094980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        }
3104980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        builder.append(" }");
3114980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen        return builder.toString();
3124980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen    }
3134980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen
3144980bf4aff8d49ac4e05444a6ef40ea1536f1afbDan Willemsen}
315