1767a662ecde33c3979bf02b793d392aca0403162Wink Saville/*
2767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Copyright (C) 2008 The Android Open Source Project
3767a662ecde33c3979bf02b793d392aca0403162Wink Saville *
4767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Licensed under the Apache License, Version 2.0 (the "License");
5767a662ecde33c3979bf02b793d392aca0403162Wink Saville * you may not use this file except in compliance with the License.
6767a662ecde33c3979bf02b793d392aca0403162Wink Saville * You may obtain a copy of the License at
7767a662ecde33c3979bf02b793d392aca0403162Wink Saville *
8767a662ecde33c3979bf02b793d392aca0403162Wink Saville *      http://www.apache.org/licenses/LICENSE-2.0
9767a662ecde33c3979bf02b793d392aca0403162Wink Saville *
10767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Unless required by applicable law or agreed to in writing, software
11767a662ecde33c3979bf02b793d392aca0403162Wink Saville * distributed under the License is distributed on an "AS IS" BASIS,
12767a662ecde33c3979bf02b793d392aca0403162Wink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13767a662ecde33c3979bf02b793d392aca0403162Wink Saville * See the License for the specific language governing permissions and
14767a662ecde33c3979bf02b793d392aca0403162Wink Saville * limitations under the License.
15767a662ecde33c3979bf02b793d392aca0403162Wink Saville */
16767a662ecde33c3979bf02b793d392aca0403162Wink Saville
17767a662ecde33c3979bf02b793d392aca0403162Wink Savillepackage com.android.internal.telephony.cdma;
18767a662ecde33c3979bf02b793d392aca0403162Wink Saville
19767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.os.Parcel;
201f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalinkimport android.os.SystemProperties;
214e4ad34159dc1c720a3e6145bb9f14c60fb1a3f7Soojung Shinimport android.telephony.PhoneNumberUtils;
223e3c3f80a90b156ff500076f8655647dfb317acfJake Hambyimport android.telephony.SmsCbLocation;
233e3c3f80a90b156ff500076f8655647dfb317acfJake Hambyimport android.telephony.SmsCbMessage;
243e3c3f80a90b156ff500076f8655647dfb317acfJake Hambyimport android.telephony.cdma.CdmaSmsCbProgramData;
25767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.util.Log;
263e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby
27767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.IccUtils;
28767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.SmsHeader;
29767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.SmsMessageBase;
301f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalinkimport com.android.internal.telephony.TelephonyProperties;
31767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.cdma.sms.BearerData;
32767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.cdma.sms.CdmaSmsAddress;
337d16427653e047e4901988e7ee04d637e65253b7Naveen Kallaimport com.android.internal.telephony.cdma.sms.CdmaSmsSubaddress;
34767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.cdma.sms.SmsEnvelope;
35767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.cdma.sms.UserData;
36ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumarimport com.android.internal.util.BitwiseInputStream;
3749bd918dc26a3a599d8d04212de5600abc3e48c4Tammo Spalinkimport com.android.internal.util.HexDump;
38767a662ecde33c3979bf02b793d392aca0403162Wink Saville
39767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport java.io.BufferedOutputStream;
40767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport java.io.ByteArrayInputStream;
41767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport java.io.ByteArrayOutputStream;
42767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport java.io.DataInputStream;
43767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport java.io.DataOutputStream;
44767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport java.io.IOException;
457b661fb3fc17f981bb122520791344891a3c1661Jake Hambyimport java.util.ArrayList;
463e3c3f80a90b156ff500076f8655647dfb317acfJake Hambyimport java.util.List;
473e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby
483e3c3f80a90b156ff500076f8655647dfb317acfJake Hambyimport static android.telephony.SmsMessage.MessageClass;
49767a662ecde33c3979bf02b793d392aca0403162Wink Saville
508478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink/**
518478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink * TODO(cleanup): these constants are disturbing... are they not just
528478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink * different interpretations on one number?  And if we did not have
538478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink * terrible class name overlap, they would not need to be directly
548478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink * imported like this.  The class in this file could just as well be
558478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink * named CdmaSmsMessage, could it not?
568478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink */
578478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink
58767a662ecde33c3979bf02b793d392aca0403162Wink Saville/**
598478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink * TODO(cleanup): internally returning null in many places makes
608478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink * debugging very hard (among many other reasons) and should be made
61cbcd9be4104b3872902898b84fae92d1623fd8f1Jake Hamby * more meaningful (replaced with exceptions for example).  Null
628478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink * returns should only occur at the very outside of the module/class
638478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink * scope.
648478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink */
658478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink
668478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink/**
67767a662ecde33c3979bf02b793d392aca0403162Wink Saville * A Short Message Service message.
68767a662ecde33c3979bf02b793d392aca0403162Wink Saville *
69767a662ecde33c3979bf02b793d392aca0403162Wink Saville */
70767a662ecde33c3979bf02b793d392aca0403162Wink Savillepublic class SmsMessage extends SmsMessageBase {
71767a662ecde33c3979bf02b793d392aca0403162Wink Saville    static final String LOG_TAG = "CDMA";
7250f7ea53c3f356453fc4304b911c9a022290d924jsh    static private final String LOGGABLE_TAG = "CDMA:SMS";
73767a662ecde33c3979bf02b793d392aca0403162Wink Saville
74ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar    private final static byte TELESERVICE_IDENTIFIER                    = 0x00;
75ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar    private final static byte SERVICE_CATEGORY                          = 0x01;
76ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar    private final static byte ORIGINATING_ADDRESS                       = 0x02;
77ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar    private final static byte ORIGINATING_SUB_ADDRESS                   = 0x03;
78ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar    private final static byte DESTINATION_ADDRESS                       = 0x04;
79ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar    private final static byte DESTINATION_SUB_ADDRESS                   = 0x05;
80ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar    private final static byte BEARER_REPLY_OPTION                       = 0x06;
81ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar    private final static byte CAUSE_CODES                               = 0x07;
82ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar    private final static byte BEARER_DATA                               = 0x08;
83ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar
84767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
85767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *  Status of a previously submitted SMS.
86767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *  This field applies to SMS Delivery Acknowledge messages. 0 indicates success;
87767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *  Here, the error class is defined by the bits from 9-8, the status code by the bits from 7-0.
88767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *  See C.S0015-B, v2.0, 4.5.21 for a detailed description of possible values.
89767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
90767a662ecde33c3979bf02b793d392aca0403162Wink Saville    private int status;
91767a662ecde33c3979bf02b793d392aca0403162Wink Saville
92767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /** Specifies if a return of an acknowledgment is requested for send SMS */
93767a662ecde33c3979bf02b793d392aca0403162Wink Saville    private static final int RETURN_NO_ACK  = 0;
94767a662ecde33c3979bf02b793d392aca0403162Wink Saville    private static final int RETURN_ACK     = 1;
95767a662ecde33c3979bf02b793d392aca0403162Wink Saville
96767a662ecde33c3979bf02b793d392aca0403162Wink Saville    private SmsEnvelope mEnvelope;
97767a662ecde33c3979bf02b793d392aca0403162Wink Saville    private BearerData mBearerData;
98767a662ecde33c3979bf02b793d392aca0403162Wink Saville
99767a662ecde33c3979bf02b793d392aca0403162Wink Saville    public static class SubmitPdu extends SubmitPduBase {
100767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
101767a662ecde33c3979bf02b793d392aca0403162Wink Saville
102767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
103767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * Create an SmsMessage from a raw PDU.
104767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * Note: In CDMA the PDU is just a byte representation of the received Sms.
105767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
106767a662ecde33c3979bf02b793d392aca0403162Wink Saville    public static SmsMessage createFromPdu(byte[] pdu) {
107767a662ecde33c3979bf02b793d392aca0403162Wink Saville        SmsMessage msg = new SmsMessage();
108767a662ecde33c3979bf02b793d392aca0403162Wink Saville
109767a662ecde33c3979bf02b793d392aca0403162Wink Saville        try {
110767a662ecde33c3979bf02b793d392aca0403162Wink Saville            msg.parsePdu(pdu);
111767a662ecde33c3979bf02b793d392aca0403162Wink Saville            return msg;
112767a662ecde33c3979bf02b793d392aca0403162Wink Saville        } catch (RuntimeException ex) {
113767a662ecde33c3979bf02b793d392aca0403162Wink Saville            Log.e(LOG_TAG, "SMS PDU parsing failed: ", ex);
114767a662ecde33c3979bf02b793d392aca0403162Wink Saville            return null;
115767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
116767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
117767a662ecde33c3979bf02b793d392aca0403162Wink Saville
118767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
119767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *  Create a "raw" CDMA SmsMessage from a Parcel that was forged in ril.cpp.
120767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *  Note: Only primitive fields are set.
121767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
122767a662ecde33c3979bf02b793d392aca0403162Wink Saville    public static SmsMessage newFromParcel(Parcel p) {
123767a662ecde33c3979bf02b793d392aca0403162Wink Saville        // Note: Parcel.readByte actually reads one Int and masks to byte
124767a662ecde33c3979bf02b793d392aca0403162Wink Saville        SmsMessage msg = new SmsMessage();
125767a662ecde33c3979bf02b793d392aca0403162Wink Saville        SmsEnvelope env = new SmsEnvelope();
126767a662ecde33c3979bf02b793d392aca0403162Wink Saville        CdmaSmsAddress addr = new CdmaSmsAddress();
1277d16427653e047e4901988e7ee04d637e65253b7Naveen Kalla        CdmaSmsSubaddress subaddr = new CdmaSmsSubaddress();
128767a662ecde33c3979bf02b793d392aca0403162Wink Saville        byte[] data;
129767a662ecde33c3979bf02b793d392aca0403162Wink Saville        byte count;
130767a662ecde33c3979bf02b793d392aca0403162Wink Saville        int countInt;
131e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville        int addressDigitMode;
132767a662ecde33c3979bf02b793d392aca0403162Wink Saville
133767a662ecde33c3979bf02b793d392aca0403162Wink Saville        //currently not supported by the modem-lib: env.mMessageType
134767a662ecde33c3979bf02b793d392aca0403162Wink Saville        env.teleService = p.readInt(); //p_cur->uTeleserviceID
135767a662ecde33c3979bf02b793d392aca0403162Wink Saville
136767a662ecde33c3979bf02b793d392aca0403162Wink Saville        if (0 != p.readByte()) { //p_cur->bIsServicePresent
137767a662ecde33c3979bf02b793d392aca0403162Wink Saville            env.messageType = SmsEnvelope.MESSAGE_TYPE_BROADCAST;
138767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
139767a662ecde33c3979bf02b793d392aca0403162Wink Saville        else {
140767a662ecde33c3979bf02b793d392aca0403162Wink Saville            if (SmsEnvelope.TELESERVICE_NOT_SET == env.teleService) {
141767a662ecde33c3979bf02b793d392aca0403162Wink Saville                // assume type ACK
142767a662ecde33c3979bf02b793d392aca0403162Wink Saville                env.messageType = SmsEnvelope.MESSAGE_TYPE_ACKNOWLEDGE;
143767a662ecde33c3979bf02b793d392aca0403162Wink Saville            } else {
144767a662ecde33c3979bf02b793d392aca0403162Wink Saville                env.messageType = SmsEnvelope.MESSAGE_TYPE_POINT_TO_POINT;
145767a662ecde33c3979bf02b793d392aca0403162Wink Saville            }
146767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
147767a662ecde33c3979bf02b793d392aca0403162Wink Saville        env.serviceCategory = p.readInt(); //p_cur->uServicecategory
148767a662ecde33c3979bf02b793d392aca0403162Wink Saville
149767a662ecde33c3979bf02b793d392aca0403162Wink Saville        // address
150e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville        addressDigitMode = p.readInt();
151e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville        addr.digitMode = (byte) (0xFF & addressDigitMode); //p_cur->sAddress.digit_mode
152767a662ecde33c3979bf02b793d392aca0403162Wink Saville        addr.numberMode = (byte) (0xFF & p.readInt()); //p_cur->sAddress.number_mode
153767a662ecde33c3979bf02b793d392aca0403162Wink Saville        addr.ton = p.readInt(); //p_cur->sAddress.number_type
154767a662ecde33c3979bf02b793d392aca0403162Wink Saville        addr.numberPlan = (byte) (0xFF & p.readInt()); //p_cur->sAddress.number_plan
155767a662ecde33c3979bf02b793d392aca0403162Wink Saville        count = p.readByte(); //p_cur->sAddress.number_of_digits
156767a662ecde33c3979bf02b793d392aca0403162Wink Saville        addr.numberOfDigits = count;
157767a662ecde33c3979bf02b793d392aca0403162Wink Saville        data = new byte[count];
158767a662ecde33c3979bf02b793d392aca0403162Wink Saville        //p_cur->sAddress.digits[digitCount]
159767a662ecde33c3979bf02b793d392aca0403162Wink Saville        for (int index=0; index < count; index++) {
160767a662ecde33c3979bf02b793d392aca0403162Wink Saville            data[index] = p.readByte();
161e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville
162e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville            // convert the value if it is 4-bit DTMF to 8 bit
163e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville            if (addressDigitMode == CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF) {
164e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville                data[index] = msg.convertDtmfToAscii(data[index]);
165e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville            }
166767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
167e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville
168767a662ecde33c3979bf02b793d392aca0403162Wink Saville        addr.origBytes = data;
169767a662ecde33c3979bf02b793d392aca0403162Wink Saville
1707d16427653e047e4901988e7ee04d637e65253b7Naveen Kalla        subaddr.type = p.readInt(); // p_cur->sSubAddress.subaddressType
1717d16427653e047e4901988e7ee04d637e65253b7Naveen Kalla        subaddr.odd = p.readByte();     // p_cur->sSubAddress.odd
1727d16427653e047e4901988e7ee04d637e65253b7Naveen Kalla        count = p.readByte();           // p_cur->sSubAddress.number_of_digits
1737d16427653e047e4901988e7ee04d637e65253b7Naveen Kalla
1747d16427653e047e4901988e7ee04d637e65253b7Naveen Kalla        if (count < 0) {
1757d16427653e047e4901988e7ee04d637e65253b7Naveen Kalla            count = 0;
176767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
177767a662ecde33c3979bf02b793d392aca0403162Wink Saville
1787d16427653e047e4901988e7ee04d637e65253b7Naveen Kalla        // p_cur->sSubAddress.digits[digitCount] :
1797d16427653e047e4901988e7ee04d637e65253b7Naveen Kalla
1807d16427653e047e4901988e7ee04d637e65253b7Naveen Kalla        data = new byte[count];
1817d16427653e047e4901988e7ee04d637e65253b7Naveen Kalla
1827d16427653e047e4901988e7ee04d637e65253b7Naveen Kalla        for (int index = 0; index < count; ++index) {
1837d16427653e047e4901988e7ee04d637e65253b7Naveen Kalla            data[index] = p.readByte();
1847d16427653e047e4901988e7ee04d637e65253b7Naveen Kalla        }
1857d16427653e047e4901988e7ee04d637e65253b7Naveen Kalla
1867d16427653e047e4901988e7ee04d637e65253b7Naveen Kalla        subaddr.origBytes = data;
1877d16427653e047e4901988e7ee04d637e65253b7Naveen Kalla
188767a662ecde33c3979bf02b793d392aca0403162Wink Saville        /* currently not supported by the modem-lib:
189767a662ecde33c3979bf02b793d392aca0403162Wink Saville            env.bearerReply
190767a662ecde33c3979bf02b793d392aca0403162Wink Saville            env.replySeqNo
191767a662ecde33c3979bf02b793d392aca0403162Wink Saville            env.errorClass
192767a662ecde33c3979bf02b793d392aca0403162Wink Saville            env.causeCode
193767a662ecde33c3979bf02b793d392aca0403162Wink Saville        */
194767a662ecde33c3979bf02b793d392aca0403162Wink Saville
195767a662ecde33c3979bf02b793d392aca0403162Wink Saville        // bearer data
196767a662ecde33c3979bf02b793d392aca0403162Wink Saville        countInt = p.readInt(); //p_cur->uBearerDataLen
1973e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby        if (countInt < 0) {
1983e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby            countInt = 0;
1990c49f03a0429b5c0c4a619256f7bca86a4997ae8Jake Hamby        }
2000c49f03a0429b5c0c4a619256f7bca86a4997ae8Jake Hamby
2013e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby        data = new byte[countInt];
2023e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby        for (int index=0; index < countInt; index++) {
2033e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby            data[index] = p.readByte();
2043e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby        }
2053e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby        // BD gets further decoded when accessed in SMSDispatcher
2063e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby        env.bearerData = data;
2073e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby
208767a662ecde33c3979bf02b793d392aca0403162Wink Saville        // link the the filled objects to the SMS
209767a662ecde33c3979bf02b793d392aca0403162Wink Saville        env.origAddress = addr;
2107d16427653e047e4901988e7ee04d637e65253b7Naveen Kalla        env.origSubaddress = subaddr;
211767a662ecde33c3979bf02b793d392aca0403162Wink Saville        msg.originatingAddress = addr;
212767a662ecde33c3979bf02b793d392aca0403162Wink Saville        msg.mEnvelope = env;
213767a662ecde33c3979bf02b793d392aca0403162Wink Saville
214767a662ecde33c3979bf02b793d392aca0403162Wink Saville        // create byte stream representation for transportation through the layers.
215767a662ecde33c3979bf02b793d392aca0403162Wink Saville        msg.createPdu();
216767a662ecde33c3979bf02b793d392aca0403162Wink Saville
217767a662ecde33c3979bf02b793d392aca0403162Wink Saville        return msg;
218767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
219767a662ecde33c3979bf02b793d392aca0403162Wink Saville
220767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
221767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * Create an SmsMessage from an SMS EF record.
222767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *
223767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param index Index of SMS record. This should be index in ArrayList
224767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *              returned by RuimSmsInterfaceManager.getAllMessagesFromIcc + 1.
225767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param data Record data.
226767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @return An SmsMessage representing the record.
227767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *
228767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @hide
229767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
230767a662ecde33c3979bf02b793d392aca0403162Wink Saville    public static SmsMessage createFromEfRecord(int index, byte[] data) {
231767a662ecde33c3979bf02b793d392aca0403162Wink Saville        try {
232767a662ecde33c3979bf02b793d392aca0403162Wink Saville            SmsMessage msg = new SmsMessage();
233767a662ecde33c3979bf02b793d392aca0403162Wink Saville
234767a662ecde33c3979bf02b793d392aca0403162Wink Saville            msg.indexOnIcc = index;
235767a662ecde33c3979bf02b793d392aca0403162Wink Saville
236767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // First byte is status: RECEIVED_READ, RECEIVED_UNREAD, STORED_SENT,
237767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // or STORED_UNSENT
238767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // See 3GPP2 C.S0023 3.4.27
239767a662ecde33c3979bf02b793d392aca0403162Wink Saville            if ((data[0] & 1) == 0) {
240767a662ecde33c3979bf02b793d392aca0403162Wink Saville                Log.w(LOG_TAG, "SMS parsing failed: Trying to parse a free record");
241767a662ecde33c3979bf02b793d392aca0403162Wink Saville                return null;
242767a662ecde33c3979bf02b793d392aca0403162Wink Saville            } else {
243767a662ecde33c3979bf02b793d392aca0403162Wink Saville                msg.statusOnIcc = data[0] & 0x07;
244767a662ecde33c3979bf02b793d392aca0403162Wink Saville            }
245767a662ecde33c3979bf02b793d392aca0403162Wink Saville
246767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // Second byte is the MSG_LEN, length of the message
247767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // See 3GPP2 C.S0023 3.4.27
248767a662ecde33c3979bf02b793d392aca0403162Wink Saville            int size = data[1];
249767a662ecde33c3979bf02b793d392aca0403162Wink Saville
250767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // Note: Data may include trailing FF's.  That's OK; message
251767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // should still parse correctly.
252767a662ecde33c3979bf02b793d392aca0403162Wink Saville            byte[] pdu = new byte[size];
253767a662ecde33c3979bf02b793d392aca0403162Wink Saville            System.arraycopy(data, 2, pdu, 0, size);
254767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // the message has to be parsed before it can be displayed
255767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // see gsm.SmsMessage
256ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar            msg.parsePduFromEfRecord(pdu);
257767a662ecde33c3979bf02b793d392aca0403162Wink Saville            return msg;
258767a662ecde33c3979bf02b793d392aca0403162Wink Saville        } catch (RuntimeException ex) {
259767a662ecde33c3979bf02b793d392aca0403162Wink Saville            Log.e(LOG_TAG, "SMS PDU parsing failed: ", ex);
260767a662ecde33c3979bf02b793d392aca0403162Wink Saville            return null;
261767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
262767a662ecde33c3979bf02b793d392aca0403162Wink Saville
263767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
264767a662ecde33c3979bf02b793d392aca0403162Wink Saville
265767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
266767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * Note: This function is a GSM specific functionality which is not supported in CDMA mode.
267767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
268767a662ecde33c3979bf02b793d392aca0403162Wink Saville    public static int getTPLayerLengthForPDU(String pdu) {
269767a662ecde33c3979bf02b793d392aca0403162Wink Saville        Log.w(LOG_TAG, "getTPLayerLengthForPDU: is not supported in CDMA mode.");
270767a662ecde33c3979bf02b793d392aca0403162Wink Saville        return 0;
271767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
272767a662ecde33c3979bf02b793d392aca0403162Wink Saville
273767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
27464c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink     * TODO(cleanup): why do getSubmitPdu methods take an scAddr input
27564c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink     * and do nothing with it?  GSM allows us to specify a SC (eg,
27664c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink     * when responding to an SMS that explicitly requests the response
27764c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink     * is sent to a specific SC), or pass null to use the default
27864c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink     * value.  Is there no similar notion in CDMA? Or do we just not
27964c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink     * have it hooked up?
28064c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink     */
28164c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink
28264c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink    /**
283767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * Get an SMS-SUBMIT PDU for a destination address and a message
284767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *
2858478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink     * @param scAddr                Service Centre address.  Null means use default.
2868478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink     * @param destAddr              Address of the recipient.
287767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param message               String representation of the message payload.
288767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param statusReportRequested Indicates whether a report is requested for this message.
2899e397775e18f369f7855affd23a3ce6a24053218Jake Hamby     * @param smsHeader             Array containing the data for the User Data Header, preceded
290767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *                              by the Element Identifiers.
291767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @return a <code>SubmitPdu</code> containing the encoded SC
292767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *         address, if applicable, and the encoded message.
293767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *         Returns null on encode error.
294767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @hide
295767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
29664c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink    public static SubmitPdu getSubmitPdu(String scAddr, String destAddr, String message,
29764c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink            boolean statusReportRequested, SmsHeader smsHeader) {
29864c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink
2998478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink        /**
30064c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         * TODO(cleanup): Do we really want silent failure like this?
30164c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         * Would it not be much more reasonable to make sure we don't
30264c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         * call this function if we really want nothing done?
3038478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink         */
3048478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink        if (message == null || destAddr == null) {
305767a662ecde33c3979bf02b793d392aca0403162Wink Saville            return null;
306767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
307767a662ecde33c3979bf02b793d392aca0403162Wink Saville
3088478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink        UserData uData = new UserData();
3098478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink        uData.payloadStr = message;
31064c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        uData.userDataHeader = smsHeader;
31164c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        return privateGetSubmitPdu(destAddr, statusReportRequested, uData);
312767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
313767a662ecde33c3979bf02b793d392aca0403162Wink Saville
314767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
315390de220248d05ccb9dc10a197700ad3c1595937Jake Hamby     * Get an SMS-SUBMIT PDU for a data message to a destination address and port.
316767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *
31764c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink     * @param scAddr Service Centre address. null == use default
31864c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink     * @param destAddr the address of the destination for the message
31964c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink     * @param destPort the port to deliver the message to at the
320767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *        destination
321767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param data the data for the message
322767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @return a <code>SubmitPdu</code> containing the encoded SC
323767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *         address, if applicable, and the encoded message.
324767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *         Returns null on encode error.
325767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
3261f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink    public static SubmitPdu getSubmitPdu(String scAddr, String destAddr, int destPort,
32764c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink            byte[] data, boolean statusReportRequested) {
328767a662ecde33c3979bf02b793d392aca0403162Wink Saville
3298478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink        /**
33064c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         * TODO(cleanup): this is not a general-purpose SMS creation
33164c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         * method, but rather something specialized to messages
33264c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         * containing OCTET encoded (meaning non-human-readable) user
33364c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         * data.  The name should reflect that, and not just overload.
3348478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink         */
335767a662ecde33c3979bf02b793d392aca0403162Wink Saville
33664c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        SmsHeader.PortAddrs portAddrs = new SmsHeader.PortAddrs();
33764c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        portAddrs.destPort = destPort;
33864c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        portAddrs.origPort = 0;
33964c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        portAddrs.areEightBits = false;
34064c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink
3418478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink        SmsHeader smsHeader = new SmsHeader();
34264c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        smsHeader.portAddrs = portAddrs;
343767a662ecde33c3979bf02b793d392aca0403162Wink Saville
3448478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink        UserData uData = new UserData();
3458478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink        uData.userDataHeader = smsHeader;
34683917db040bd7498ebca3b74f879dc1c9e223d8eTammo Spalink        uData.msgEncoding = UserData.ENCODING_OCTET;
3478478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink        uData.msgEncodingSet = true;
34883917db040bd7498ebca3b74f879dc1c9e223d8eTammo Spalink        uData.payload = data;
349767a662ecde33c3979bf02b793d392aca0403162Wink Saville
35064c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        return privateGetSubmitPdu(destAddr, statusReportRequested, uData);
351767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
352767a662ecde33c3979bf02b793d392aca0403162Wink Saville
353767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
354fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink     * Get an SMS-SUBMIT PDU for a data message to a destination address &amp; port
355a94945d3a1cf23caf33759eb1de84195d3fcb37bTammo Spalink     *
356fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink     * @param destAddr the address of the destination for the message
3579e397775e18f369f7855affd23a3ce6a24053218Jake Hamby     * @param userData the data for the message
358fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink     * @param statusReportRequested Indicates whether a report is requested for this message.
359fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink     * @return a <code>SubmitPdu</code> containing the encoded SC
360fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink     *         address, if applicable, and the encoded message.
361fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink     *         Returns null on encode error.
362a94945d3a1cf23caf33759eb1de84195d3fcb37bTammo Spalink     */
363fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink    public static SubmitPdu getSubmitPdu(String destAddr, UserData userData,
364fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink            boolean statusReportRequested) {
365fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink        return privateGetSubmitPdu(destAddr, statusReportRequested, userData);
366a94945d3a1cf23caf33759eb1de84195d3fcb37bTammo Spalink    }
367a94945d3a1cf23caf33759eb1de84195d3fcb37bTammo Spalink
368a94945d3a1cf23caf33759eb1de84195d3fcb37bTammo Spalink    /**
369767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * Note: This function is a GSM specific functionality which is not supported in CDMA mode.
370767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
371767a662ecde33c3979bf02b793d392aca0403162Wink Saville    public int getProtocolIdentifier() {
372767a662ecde33c3979bf02b793d392aca0403162Wink Saville        Log.w(LOG_TAG, "getProtocolIdentifier: is not supported in CDMA mode.");
373767a662ecde33c3979bf02b793d392aca0403162Wink Saville        // (3GPP TS 23.040): "no interworking, but SME to SME protocol":
374767a662ecde33c3979bf02b793d392aca0403162Wink Saville        return 0;
375767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
376767a662ecde33c3979bf02b793d392aca0403162Wink Saville
377767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
378767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * Note: This function is a GSM specific functionality which is not supported in CDMA mode.
379767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
380767a662ecde33c3979bf02b793d392aca0403162Wink Saville    public boolean isReplace() {
381767a662ecde33c3979bf02b793d392aca0403162Wink Saville        Log.w(LOG_TAG, "isReplace: is not supported in CDMA mode.");
382767a662ecde33c3979bf02b793d392aca0403162Wink Saville        return false;
383767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
384767a662ecde33c3979bf02b793d392aca0403162Wink Saville
385767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
386767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * {@inheritDoc}
387767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * Note: This function is a GSM specific functionality which is not supported in CDMA mode.
388767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
389767a662ecde33c3979bf02b793d392aca0403162Wink Saville    public boolean isCphsMwiMessage() {
390767a662ecde33c3979bf02b793d392aca0403162Wink Saville        Log.w(LOG_TAG, "isCphsMwiMessage: is not supported in CDMA mode.");
391767a662ecde33c3979bf02b793d392aca0403162Wink Saville        return false;
392767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
393767a662ecde33c3979bf02b793d392aca0403162Wink Saville
394767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
395767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * {@inheritDoc}
396767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
397767a662ecde33c3979bf02b793d392aca0403162Wink Saville    public boolean isMWIClearMessage() {
39864c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        return ((mBearerData != null) && (mBearerData.numberOfMessages == 0));
399767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
400767a662ecde33c3979bf02b793d392aca0403162Wink Saville
401767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
402767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * {@inheritDoc}
403767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
404767a662ecde33c3979bf02b793d392aca0403162Wink Saville    public boolean isMWISetMessage() {
40564c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        return ((mBearerData != null) && (mBearerData.numberOfMessages > 0));
406767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
407767a662ecde33c3979bf02b793d392aca0403162Wink Saville
408767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
409767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * {@inheritDoc}
410767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
411767a662ecde33c3979bf02b793d392aca0403162Wink Saville    public boolean isMwiDontStore() {
41264c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        return ((mBearerData != null) &&
41364c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink                (mBearerData.numberOfMessages > 0) &&
41464c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink                (mBearerData.userData == null));
415767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
416767a662ecde33c3979bf02b793d392aca0403162Wink Saville
417767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
418767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * Returns the status for a previously submitted message.
419767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * For not interfering with status codes from GSM, this status code is
420767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * shifted to the bits 31-16.
421767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
422767a662ecde33c3979bf02b793d392aca0403162Wink Saville    public int getStatus() {
42364c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        return (status << 16);
424767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
425767a662ecde33c3979bf02b793d392aca0403162Wink Saville
426d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink    /** Return true iff the bearer data message type is DELIVERY_ACK. */
427767a662ecde33c3979bf02b793d392aca0403162Wink Saville    public boolean isStatusReportMessage() {
428d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink        return (mBearerData.messageType == BearerData.MESSAGE_TYPE_DELIVERY_ACK);
429767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
430767a662ecde33c3979bf02b793d392aca0403162Wink Saville
431767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
432767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * Note: This function is a GSM specific functionality which is not supported in CDMA mode.
433767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
434767a662ecde33c3979bf02b793d392aca0403162Wink Saville    public boolean isReplyPathPresent() {
435767a662ecde33c3979bf02b793d392aca0403162Wink Saville        Log.w(LOG_TAG, "isReplyPathPresent: is not supported in CDMA mode.");
436767a662ecde33c3979bf02b793d392aca0403162Wink Saville        return false;
437767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
438767a662ecde33c3979bf02b793d392aca0403162Wink Saville
439767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
440fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink     * Calculate the number of septets needed to encode the message.
441fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink     *
442fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink     * @param messageBody the message to encode
443fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink     * @param use7bitOnly ignore (but still count) illegal characters if true
444fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink     * @return TextEncodingDetails
445fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink     */
446fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink    public static TextEncodingDetails calculateLength(CharSequence messageBody,
447fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink            boolean use7bitOnly) {
44817f616823a562ceb3a008f91e05d43bc56d37caeJake Hamby        return BearerData.calcTextEncodingDetails(messageBody, use7bitOnly);
449fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink    }
450fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink
451fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink    /**
452767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * Returns the teleservice type of the message.
453767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @return the teleservice:
454767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *  {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#TELESERVICE_NOT_SET},
455767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *  {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#TELESERVICE_WMT},
456767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *  {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#TELESERVICE_WEMT},
457767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *  {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#TELESERVICE_VMN},
458767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *  {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#TELESERVICE_WAP}
459767a662ecde33c3979bf02b793d392aca0403162Wink Saville    */
46083fd7b0d53f2fecb5b92cb911910e07659e246caJohn Joseph    /* package */ int getTeleService() {
461767a662ecde33c3979bf02b793d392aca0403162Wink Saville        return mEnvelope.teleService;
462767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
463767a662ecde33c3979bf02b793d392aca0403162Wink Saville
464767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
46583fd7b0d53f2fecb5b92cb911910e07659e246caJohn Joseph     * Returns the message type of the message.
46683fd7b0d53f2fecb5b92cb911910e07659e246caJohn Joseph     * @return the message type:
46783fd7b0d53f2fecb5b92cb911910e07659e246caJohn Joseph     *  {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#MESSAGE_TYPE_POINT_TO_POINT},
46883fd7b0d53f2fecb5b92cb911910e07659e246caJohn Joseph     *  {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#MESSAGE_TYPE_BROADCAST},
46983fd7b0d53f2fecb5b92cb911910e07659e246caJohn Joseph     *  {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#MESSAGE_TYPE_ACKNOWLEDGE},
47083fd7b0d53f2fecb5b92cb911910e07659e246caJohn Joseph    */
47183fd7b0d53f2fecb5b92cb911910e07659e246caJohn Joseph    /* package */ int getMessageType() {
47215c257eb8f077fc4f6c95f8a7bc84dd9a7b39c61Jake Hamby        // NOTE: mEnvelope.messageType is not set correctly for cell broadcasts with some RILs.
47315c257eb8f077fc4f6c95f8a7bc84dd9a7b39c61Jake Hamby        // Use the service category parameter to detect CMAS and other cell broadcast messages.
47415c257eb8f077fc4f6c95f8a7bc84dd9a7b39c61Jake Hamby        if (mEnvelope.serviceCategory != 0) {
47515c257eb8f077fc4f6c95f8a7bc84dd9a7b39c61Jake Hamby            return SmsEnvelope.MESSAGE_TYPE_BROADCAST;
47615c257eb8f077fc4f6c95f8a7bc84dd9a7b39c61Jake Hamby        } else {
47715c257eb8f077fc4f6c95f8a7bc84dd9a7b39c61Jake Hamby            return SmsEnvelope.MESSAGE_TYPE_POINT_TO_POINT;
47815c257eb8f077fc4f6c95f8a7bc84dd9a7b39c61Jake Hamby        }
47983fd7b0d53f2fecb5b92cb911910e07659e246caJohn Joseph    }
48083fd7b0d53f2fecb5b92cb911910e07659e246caJohn Joseph
48183fd7b0d53f2fecb5b92cb911910e07659e246caJohn Joseph    /**
482767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * Decodes pdu to an empty SMS object.
483767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * In the CDMA case the pdu is just an internal byte stream representation
484767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * of the SMS Java-object.
485767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @see #createPdu()
486767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
487767a662ecde33c3979bf02b793d392aca0403162Wink Saville    private void parsePdu(byte[] pdu) {
488767a662ecde33c3979bf02b793d392aca0403162Wink Saville        ByteArrayInputStream bais = new ByteArrayInputStream(pdu);
48964c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        DataInputStream dis = new DataInputStream(bais);
490767a662ecde33c3979bf02b793d392aca0403162Wink Saville        byte length;
491e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville        int bearerDataLength;
492767a662ecde33c3979bf02b793d392aca0403162Wink Saville        SmsEnvelope env = new SmsEnvelope();
493767a662ecde33c3979bf02b793d392aca0403162Wink Saville        CdmaSmsAddress addr = new CdmaSmsAddress();
494767a662ecde33c3979bf02b793d392aca0403162Wink Saville
495767a662ecde33c3979bf02b793d392aca0403162Wink Saville        try {
496767a662ecde33c3979bf02b793d392aca0403162Wink Saville            env.messageType = dis.readInt();
497767a662ecde33c3979bf02b793d392aca0403162Wink Saville            env.teleService = dis.readInt();
498767a662ecde33c3979bf02b793d392aca0403162Wink Saville            env.serviceCategory = dis.readInt();
499767a662ecde33c3979bf02b793d392aca0403162Wink Saville
500767a662ecde33c3979bf02b793d392aca0403162Wink Saville            addr.digitMode = dis.readByte();
501767a662ecde33c3979bf02b793d392aca0403162Wink Saville            addr.numberMode = dis.readByte();
502767a662ecde33c3979bf02b793d392aca0403162Wink Saville            addr.ton = dis.readByte();
503767a662ecde33c3979bf02b793d392aca0403162Wink Saville            addr.numberPlan = dis.readByte();
504767a662ecde33c3979bf02b793d392aca0403162Wink Saville
505767a662ecde33c3979bf02b793d392aca0403162Wink Saville            length = dis.readByte();
506767a662ecde33c3979bf02b793d392aca0403162Wink Saville            addr.numberOfDigits = length;
507767a662ecde33c3979bf02b793d392aca0403162Wink Saville            addr.origBytes = new byte[length];
508767a662ecde33c3979bf02b793d392aca0403162Wink Saville            dis.read(addr.origBytes, 0, length); // digits
509767a662ecde33c3979bf02b793d392aca0403162Wink Saville
510767a662ecde33c3979bf02b793d392aca0403162Wink Saville            env.bearerReply = dis.readInt();
511767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // CauseCode values:
512767a662ecde33c3979bf02b793d392aca0403162Wink Saville            env.replySeqNo = dis.readByte();
513767a662ecde33c3979bf02b793d392aca0403162Wink Saville            env.errorClass = dis.readByte();
514767a662ecde33c3979bf02b793d392aca0403162Wink Saville            env.causeCode = dis.readByte();
515767a662ecde33c3979bf02b793d392aca0403162Wink Saville
516767a662ecde33c3979bf02b793d392aca0403162Wink Saville            //encoded BearerData:
517e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville            bearerDataLength = dis.readInt();
518e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville            env.bearerData = new byte[bearerDataLength];
519e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville            dis.read(env.bearerData, 0, bearerDataLength);
520767a662ecde33c3979bf02b793d392aca0403162Wink Saville            dis.close();
521767a662ecde33c3979bf02b793d392aca0403162Wink Saville        } catch (Exception ex) {
522767a662ecde33c3979bf02b793d392aca0403162Wink Saville            Log.e(LOG_TAG, "createFromPdu: conversion from byte array to object failed: " + ex);
523767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
524767a662ecde33c3979bf02b793d392aca0403162Wink Saville
525767a662ecde33c3979bf02b793d392aca0403162Wink Saville        // link the filled objects to this SMS
526767a662ecde33c3979bf02b793d392aca0403162Wink Saville        originatingAddress = addr;
527767a662ecde33c3979bf02b793d392aca0403162Wink Saville        env.origAddress = addr;
528767a662ecde33c3979bf02b793d392aca0403162Wink Saville        mEnvelope = env;
5295082fd58e33aa54d760459de3368912c37864a4fSatish Roddom        mPdu = pdu;
530767a662ecde33c3979bf02b793d392aca0403162Wink Saville
531767a662ecde33c3979bf02b793d392aca0403162Wink Saville        parseSms();
532767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
533767a662ecde33c3979bf02b793d392aca0403162Wink Saville
534767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
535ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar     * Decodes 3GPP2 sms stored in CSIM/RUIM cards As per 3GPP2 C.S0015-0
536ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar     */
537ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar    private void parsePduFromEfRecord(byte[] pdu) {
538ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar        ByteArrayInputStream bais = new ByteArrayInputStream(pdu);
539ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar        DataInputStream dis = new DataInputStream(bais);
540ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar        SmsEnvelope env = new SmsEnvelope();
541ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar        CdmaSmsAddress addr = new CdmaSmsAddress();
542ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar        CdmaSmsSubaddress subAddr = new CdmaSmsSubaddress();
543ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar
544ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar        try {
545ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar            env.messageType = dis.readByte();
546ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar
547ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar            while (dis.available() > 0) {
548ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                int parameterId = dis.readByte();
549ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                int parameterLen = dis.readByte();
550ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                byte[] parameterData = new byte[parameterLen];
551ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar
552ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                switch (parameterId) {
553ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                    case TELESERVICE_IDENTIFIER:
554ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        /*
555ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                         * 16 bit parameter that identifies which upper layer
556ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                         * service access point is sending or should receive
557ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                         * this message
558ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                         */
559ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        env.teleService = dis.readUnsignedShort();
560ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        Log.i(LOG_TAG, "teleservice = " + env.teleService);
561ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        break;
562ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                    case SERVICE_CATEGORY:
563ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        /*
564ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                         * 16 bit parameter that identifies type of service as
565ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                         * in 3GPP2 C.S0015-0 Table 3.4.3.2-1
566ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                         */
567ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        env.serviceCategory = dis.readUnsignedShort();
568ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        break;
569ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                    case ORIGINATING_ADDRESS:
570ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                    case DESTINATION_ADDRESS:
571ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        dis.read(parameterData, 0, parameterLen);
572ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        BitwiseInputStream addrBis = new BitwiseInputStream(parameterData);
573ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        addr.digitMode = addrBis.read(1);
574ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        addr.numberMode = addrBis.read(1);
575ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        int numberType = 0;
576ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR) {
577ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                            numberType = addrBis.read(3);
578ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                            addr.ton = numberType;
579ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar
580ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                            if (addr.numberMode == CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK)
581ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                                addr.numberPlan = addrBis.read(4);
582ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        }
583ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar
584ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        addr.numberOfDigits = addrBis.read(8);
585ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar
586ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        byte[] data = new byte[addr.numberOfDigits];
587ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        byte b = 0x00;
588ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar
589ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF) {
590ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                            /* As per 3GPP2 C.S0005-0 Table 2.7.1.3.2.4-4 */
591ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                            for (int index = 0; index < addr.numberOfDigits; index++) {
592ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                                b = (byte) (0xF & addrBis.read(4));
593ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                                // convert the value if it is 4-bit DTMF to 8
594ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                                // bit
595ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                                data[index] = convertDtmfToAscii(b);
596ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                            }
597ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        } else if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR) {
598ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                            if (addr.numberMode == CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK) {
599ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                                for (int index = 0; index < addr.numberOfDigits; index++) {
600ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                                    b = (byte) (0xFF & addrBis.read(8));
601ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                                    data[index] = b;
602ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                                }
603ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar
604ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                            } else if (addr.numberMode == CdmaSmsAddress.NUMBER_MODE_DATA_NETWORK) {
605ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                                if (numberType == 2)
606ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                                    Log.e(LOG_TAG, "TODO: Originating Addr is email id");
607ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                                else
608ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                                    Log.e(LOG_TAG,
609ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                                          "TODO: Originating Addr is data network address");
610ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                            } else {
611ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                                Log.e(LOG_TAG, "Originating Addr is of incorrect type");
612ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                            }
613ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        } else {
614ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                            Log.e(LOG_TAG, "Incorrect Digit mode");
615ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        }
616ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        addr.origBytes = data;
617ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        Log.i(LOG_TAG, "Originating Addr=" + addr.toString());
618ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        break;
619ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                    case ORIGINATING_SUB_ADDRESS:
620ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                    case DESTINATION_SUB_ADDRESS:
621ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        dis.read(parameterData, 0, parameterLen);
622ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        BitwiseInputStream subAddrBis = new BitwiseInputStream(parameterData);
623ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        subAddr.type = subAddrBis.read(3);
624ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        subAddr.odd = subAddrBis.readByteArray(1)[0];
625ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        int subAddrLen = subAddrBis.read(8);
626ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        byte[] subdata = new byte[subAddrLen];
627ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        for (int index = 0; index < subAddrLen; index++) {
628ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                            b = (byte) (0xFF & subAddrBis.read(4));
629ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                            // convert the value if it is 4-bit DTMF to 8 bit
630ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                            subdata[index] = convertDtmfToAscii(b);
631ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        }
632ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        subAddr.origBytes = subdata;
633ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        break;
634ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                    case BEARER_REPLY_OPTION:
635ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        dis.read(parameterData, 0, parameterLen);
636ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        BitwiseInputStream replyOptBis = new BitwiseInputStream(parameterData);
637ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        env.bearerReply = replyOptBis.read(6);
638ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        break;
639ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                    case CAUSE_CODES:
640ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        dis.read(parameterData, 0, parameterLen);
641ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        BitwiseInputStream ccBis = new BitwiseInputStream(parameterData);
642ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        env.replySeqNo = ccBis.readByteArray(6)[0];
643ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        env.errorClass = ccBis.readByteArray(2)[0];
644ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        if (env.errorClass != 0x00)
645ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                            env.causeCode = ccBis.readByteArray(8)[0];
646ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        break;
647ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                    case BEARER_DATA:
648ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        dis.read(parameterData, 0, parameterLen);
649ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        env.bearerData = parameterData;
650ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        break;
651ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                    default:
652ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                        throw new Exception("unsupported parameterId (" + parameterId + ")");
653ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar                }
654ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar            }
655ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar            bais.close();
656ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar            dis.close();
657ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar        } catch (Exception ex) {
658ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar            Log.e(LOG_TAG, "parsePduFromEfRecord: conversion from pdu to SmsMessage failed" + ex);
659ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar        }
660ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar
661ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar        // link the filled objects to this SMS
662ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar        originatingAddress = addr;
663ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar        env.origAddress = addr;
664ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar        env.origSubaddress = subAddr;
665ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar        mEnvelope = env;
666ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar        mPdu = pdu;
667ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar
668ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar        parseSms();
669ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar    }
670ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar
671ee7d1973ff3cd7c9c8744696901b37833027cafbRekha Kumar    /**
672767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * Parses a SMS message from its BearerData stream. (mobile-terminated only)
673767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
674767a662ecde33c3979bf02b793d392aca0403162Wink Saville    protected void parseSms() {
675c84401fb8b3ed90039bd132b343852303ef88ce6yong liu        // Message Waiting Info Record defined in 3GPP2 C.S-0005, 3.7.5.6
676c84401fb8b3ed90039bd132b343852303ef88ce6yong liu        // It contains only an 8-bit number with the number of messages waiting
677c84401fb8b3ed90039bd132b343852303ef88ce6yong liu        if (mEnvelope.teleService == SmsEnvelope.TELESERVICE_MWI) {
678c84401fb8b3ed90039bd132b343852303ef88ce6yong liu            mBearerData = new BearerData();
679c84401fb8b3ed90039bd132b343852303ef88ce6yong liu            if (mEnvelope.bearerData != null) {
680c84401fb8b3ed90039bd132b343852303ef88ce6yong liu                mBearerData.numberOfMessages = 0x000000FF & mEnvelope.bearerData[0];
681c84401fb8b3ed90039bd132b343852303ef88ce6yong liu            }
68243a17654cf4bfe7f1ec22bd8b7b32daccdf27c09Joe Onorato            if (false) {
683c84401fb8b3ed90039bd132b343852303ef88ce6yong liu                Log.d(LOG_TAG, "parseSms: get MWI " +
684c84401fb8b3ed90039bd132b343852303ef88ce6yong liu                      Integer.toString(mBearerData.numberOfMessages));
685c84401fb8b3ed90039bd132b343852303ef88ce6yong liu            }
686c84401fb8b3ed90039bd132b343852303ef88ce6yong liu            return;
687c84401fb8b3ed90039bd132b343852303ef88ce6yong liu        }
68883917db040bd7498ebca3b74f879dc1c9e223d8eTammo Spalink        mBearerData = BearerData.decode(mEnvelope.bearerData);
68950f7ea53c3f356453fc4304b911c9a022290d924jsh        if (Log.isLoggable(LOGGABLE_TAG, Log.VERBOSE)) {
69049bd918dc26a3a599d8d04212de5600abc3e48c4Tammo Spalink            Log.d(LOG_TAG, "MT raw BearerData = '" +
69149bd918dc26a3a599d8d04212de5600abc3e48c4Tammo Spalink                      HexDump.toHexString(mEnvelope.bearerData) + "'");
69249bd918dc26a3a599d8d04212de5600abc3e48c4Tammo Spalink            Log.d(LOG_TAG, "MT (decoded) BearerData = " + mBearerData);
69349bd918dc26a3a599d8d04212de5600abc3e48c4Tammo Spalink        }
69483917db040bd7498ebca3b74f879dc1c9e223d8eTammo Spalink        messageRef = mBearerData.messageId;
69564c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        if (mBearerData.userData != null) {
69664c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink            userData = mBearerData.userData.payload;
69764c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink            userDataHeader = mBearerData.userData.userDataHeader;
69864c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink            messageBody = mBearerData.userData.payloadStr;
69964c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        }
700767a662ecde33c3979bf02b793d392aca0403162Wink Saville
701767a662ecde33c3979bf02b793d392aca0403162Wink Saville        if (originatingAddress != null) {
702767a662ecde33c3979bf02b793d392aca0403162Wink Saville            originatingAddress.address = new String(originatingAddress.origBytes);
70343a17654cf4bfe7f1ec22bd8b7b32daccdf27c09Joe Onorato            if (false) Log.v(LOG_TAG, "SMS originating address: "
704767a662ecde33c3979bf02b793d392aca0403162Wink Saville                    + originatingAddress.address);
705767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
706767a662ecde33c3979bf02b793d392aca0403162Wink Saville
707baae313f896d8048f23e4acc76e554c8aa4667bdTammo Spalink        if (mBearerData.msgCenterTimeStamp != null) {
708baae313f896d8048f23e4acc76e554c8aa4667bdTammo Spalink            scTimeMillis = mBearerData.msgCenterTimeStamp.toMillis(true);
709767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
710767a662ecde33c3979bf02b793d392aca0403162Wink Saville
71143a17654cf4bfe7f1ec22bd8b7b32daccdf27c09Joe Onorato        if (false) Log.d(LOG_TAG, "SMS SC timestamp: " + scTimeMillis);
712767a662ecde33c3979bf02b793d392aca0403162Wink Saville
713d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink        // Message Type (See 3GPP2 C.S0015-B, v2, 4.5.1)
714d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink        if (mBearerData.messageType == BearerData.MESSAGE_TYPE_DELIVERY_ACK) {
715d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink            // The BearerData MsgStatus subparameter should only be
716d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink            // included for DELIVERY_ACK messages.  If it occurred for
717d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink            // other messages, it would be unclear what the status
718d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink            // being reported refers to.  The MsgStatus subparameter
719d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink            // is primarily useful to indicate error conditions -- a
720d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink            // message without this subparameter is assumed to
721d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink            // indicate successful delivery (status == 0).
722d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink            if (! mBearerData.messageStatusSet) {
723d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink                Log.d(LOG_TAG, "DELIVERY_ACK message without msgStatus (" +
724d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink                        (userData == null ? "also missing" : "does have") +
725d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink                        " userData).");
726d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink                status = 0;
727d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink            } else {
728d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink                status = mBearerData.errorClass << 8;
729d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink                status |= mBearerData.messageStatus;
730d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink            }
731d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink        } else if (mBearerData.messageType != BearerData.MESSAGE_TYPE_DELIVER) {
732d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink            throw new RuntimeException("Unsupported message type: " + mBearerData.messageType);
733767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
734767a662ecde33c3979bf02b793d392aca0403162Wink Saville
735767a662ecde33c3979bf02b793d392aca0403162Wink Saville        if (messageBody != null) {
73643a17654cf4bfe7f1ec22bd8b7b32daccdf27c09Joe Onorato            if (false) Log.v(LOG_TAG, "SMS message body: '" + messageBody + "'");
737767a662ecde33c3979bf02b793d392aca0403162Wink Saville            parseMessageBody();
73843a17654cf4bfe7f1ec22bd8b7b32daccdf27c09Joe Onorato        } else if ((userData != null) && (false)) {
7398c49d32cb9980959c402eaa243fd5129cd9942fcTammo Spalink            Log.v(LOG_TAG, "SMS payload: '" + IccUtils.bytesToHexString(userData) + "'");
740767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
741767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
742767a662ecde33c3979bf02b793d392aca0403162Wink Saville
743767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
7443e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby     * Parses a broadcast SMS, possibly containing a CMAS alert.
7453e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby     */
7463e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby    SmsCbMessage parseBroadcastSms() {
7473e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby        BearerData bData = BearerData.decode(mEnvelope.bearerData, mEnvelope.serviceCategory);
7483e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby        if (bData == null) {
7493e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby            Log.w(LOG_TAG, "BearerData.decode() returned null");
7503e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby            return null;
7513e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby        }
7523e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby
7533e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby        if (Log.isLoggable(LOGGABLE_TAG, Log.VERBOSE)) {
7543e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby            Log.d(LOG_TAG, "MT raw BearerData = " + HexDump.toHexString(mEnvelope.bearerData));
7553e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby        }
7563e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby
7573e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby        String plmn = SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC);
7583e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby        SmsCbLocation location = new SmsCbLocation(plmn);
7593e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby
7603e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby        return new SmsCbMessage(SmsCbMessage.MESSAGE_FORMAT_3GPP2,
7613e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby                SmsCbMessage.GEOGRAPHICAL_SCOPE_PLMN_WIDE, bData.messageId, location,
7623e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby                mEnvelope.serviceCategory, bData.getLanguage(), bData.userData.payloadStr,
7633e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby                bData.priority, null, bData.cmasWarningInfo);
7643e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby    }
7653e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby
7663e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby    /**
767767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * {@inheritDoc}
768767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
769767a662ecde33c3979bf02b793d392aca0403162Wink Saville    public MessageClass getMessageClass() {
7708c49d32cb9980959c402eaa243fd5129cd9942fcTammo Spalink        if (BearerData.DISPLAY_MODE_IMMEDIATE == mBearerData.displayMode ) {
771767a662ecde33c3979bf02b793d392aca0403162Wink Saville            return MessageClass.CLASS_0;
772767a662ecde33c3979bf02b793d392aca0403162Wink Saville        } else {
773767a662ecde33c3979bf02b793d392aca0403162Wink Saville            return MessageClass.UNKNOWN;
774767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
775767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
776767a662ecde33c3979bf02b793d392aca0403162Wink Saville
777767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
77898a5ba78f99f6537b34b673521f7d4ab9893c80bTammo Spalink     * Calculate the next message id, starting at 1 and iteratively
77998a5ba78f99f6537b34b673521f7d4ab9893c80bTammo Spalink     * incrementing within the range 1..65535 remembering the state
7801f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink     * via a persistent system property.  (See C.S0015-B, v2.0,
78198a5ba78f99f6537b34b673521f7d4ab9893c80bTammo Spalink     * 4.3.1.5) Since this routine is expected to be accessed via via
782cbcd9be4104b3872902898b84fae92d1623fd8f1Jake Hamby     * binder-call, and hence should be thread-safe, it has been
78398a5ba78f99f6537b34b673521f7d4ab9893c80bTammo Spalink     * synchronized.
784767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
7857b661fb3fc17f981bb122520791344891a3c1661Jake Hamby    synchronized static int getNextMessageId() {
78698a5ba78f99f6537b34b673521f7d4ab9893c80bTammo Spalink        // Testing and dialog with partners has indicated that
78798a5ba78f99f6537b34b673521f7d4ab9893c80bTammo Spalink        // msgId==0 is (sometimes?) treated specially by lower levels.
78898a5ba78f99f6537b34b673521f7d4ab9893c80bTammo Spalink        // Specifically, the ID is not preserved for delivery ACKs.
78998a5ba78f99f6537b34b673521f7d4ab9893c80bTammo Spalink        // Hence, avoid 0 -- constraining the range to 1..65535.
79098a5ba78f99f6537b34b673521f7d4ab9893c80bTammo Spalink        int msgId = SystemProperties.getInt(TelephonyProperties.PROPERTY_CDMA_MSG_ID, 1);
79198a5ba78f99f6537b34b673521f7d4ab9893c80bTammo Spalink        String nextMsgId = Integer.toString((msgId % 0xFFFF) + 1);
7921f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink        SystemProperties.set(TelephonyProperties.PROPERTY_CDMA_MSG_ID, nextMsgId);
79350f7ea53c3f356453fc4304b911c9a022290d924jsh        if (Log.isLoggable(LOGGABLE_TAG, Log.VERBOSE)) {
7941f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink            Log.d(LOG_TAG, "next " + TelephonyProperties.PROPERTY_CDMA_MSG_ID + " = " + nextMsgId);
7951f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink            Log.d(LOG_TAG, "readback gets " +
7961f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink                    SystemProperties.get(TelephonyProperties.PROPERTY_CDMA_MSG_ID));
797767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
7981f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink        return msgId;
799767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
800767a662ecde33c3979bf02b793d392aca0403162Wink Saville
801767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
8028478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink     * Creates BearerData and Envelope from parameters for a Submit SMS.
8038478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink     * @return byte stream for SubmitPdu.
804767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
8058478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink    private static SubmitPdu privateGetSubmitPdu(String destAddrStr, boolean statusReportRequested,
80664c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink            UserData userData) {
8078478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink
8088478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink        /**
8098478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink         * TODO(cleanup): give this function a more meaningful name.
8108478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink         */
8118478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink
8121424fe0059a3fe163fb98bad807a1eb635b0a161Tammo Spalink        /**
8131424fe0059a3fe163fb98bad807a1eb635b0a161Tammo Spalink         * TODO(cleanup): Make returning null from the getSubmitPdu
8141424fe0059a3fe163fb98bad807a1eb635b0a161Tammo Spalink         * variations meaningful -- clean up the error feedback
8151424fe0059a3fe163fb98bad807a1eb635b0a161Tammo Spalink         * mechanism, and avoid null pointer exceptions.
8161424fe0059a3fe163fb98bad807a1eb635b0a161Tammo Spalink         */
8171424fe0059a3fe163fb98bad807a1eb635b0a161Tammo Spalink
8184e4ad34159dc1c720a3e6145bb9f14c60fb1a3f7Soojung Shin        /**
8194e4ad34159dc1c720a3e6145bb9f14c60fb1a3f7Soojung Shin         * North America Plus Code :
8204e4ad34159dc1c720a3e6145bb9f14c60fb1a3f7Soojung Shin         * Convert + code to 011 and dial out for international SMS
8214e4ad34159dc1c720a3e6145bb9f14c60fb1a3f7Soojung Shin         */
8224e4ad34159dc1c720a3e6145bb9f14c60fb1a3f7Soojung Shin        CdmaSmsAddress destAddr = CdmaSmsAddress.parse(
8234e4ad34159dc1c720a3e6145bb9f14c60fb1a3f7Soojung Shin                PhoneNumberUtils.cdmaCheckAndProcessPlusCode(destAddrStr));
8248478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink        if (destAddr == null) return null;
8258478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink
8268478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink        BearerData bearerData = new BearerData();
8278478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink        bearerData.messageType = BearerData.MESSAGE_TYPE_SUBMIT;
8288478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink
8291f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink        bearerData.messageId = getNextMessageId();
8308478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink
8318478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink        bearerData.deliveryAckReq = statusReportRequested;
8328478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink        bearerData.userAckReq = false;
8338478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink        bearerData.readAckReq = false;
8348478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink        bearerData.reportReq = false;
8358478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink
8368478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink        bearerData.userData = userData;
837fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink
8388478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink        byte[] encodedBearerData = BearerData.encode(bearerData);
83950f7ea53c3f356453fc4304b911c9a022290d924jsh        if (Log.isLoggable(LOGGABLE_TAG, Log.VERBOSE)) {
84049bd918dc26a3a599d8d04212de5600abc3e48c4Tammo Spalink            Log.d(LOG_TAG, "MO (encoded) BearerData = " + bearerData);
84149bd918dc26a3a599d8d04212de5600abc3e48c4Tammo Spalink            Log.d(LOG_TAG, "MO raw BearerData = '" + HexDump.toHexString(encodedBearerData) + "'");
84249bd918dc26a3a599d8d04212de5600abc3e48c4Tammo Spalink        }
8438478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink        if (encodedBearerData == null) return null;
8448478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink
845079ad20da7df79f26880c9076967dc3fbce6528cTammo Spalink        int teleservice = bearerData.hasUserDataHeader ?
846079ad20da7df79f26880c9076967dc3fbce6528cTammo Spalink                SmsEnvelope.TELESERVICE_WEMT : SmsEnvelope.TELESERVICE_WMT;
847079ad20da7df79f26880c9076967dc3fbce6528cTammo Spalink
8488478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink        SmsEnvelope envelope = new SmsEnvelope();
8498478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink        envelope.messageType = SmsEnvelope.MESSAGE_TYPE_POINT_TO_POINT;
850fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink        envelope.teleService = teleservice;
8518478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink        envelope.destAddress = destAddr;
8528478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink        envelope.bearerReply = RETURN_ACK;
8538478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink        envelope.bearerData = encodedBearerData;
8548478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink
8558478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink        /**
8568478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink         * TODO(cleanup): envelope looks to be a pointless class, get
8578478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink         * rid of it.  Also -- most of the envelope fields set here
8588478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink         * are ignored, why?
8598478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink         */
860767a662ecde33c3979bf02b793d392aca0403162Wink Saville
861767a662ecde33c3979bf02b793d392aca0403162Wink Saville        try {
8628478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink            /**
8638478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink             * TODO(cleanup): reference a spec and get rid of the ugly comments
8648478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink             */
8658478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink            ByteArrayOutputStream baos = new ByteArrayOutputStream(100);
8668478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink            DataOutputStream dos = new DataOutputStream(baos);
8678478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink            dos.writeInt(envelope.teleService);
868767a662ecde33c3979bf02b793d392aca0403162Wink Saville            dos.writeInt(0); //servicePresent
869767a662ecde33c3979bf02b793d392aca0403162Wink Saville            dos.writeInt(0); //serviceCategory
8708478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink            dos.write(destAddr.digitMode);
8718478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink            dos.write(destAddr.numberMode);
8728478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink            dos.write(destAddr.ton); // number_type
8738478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink            dos.write(destAddr.numberPlan);
8748478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink            dos.write(destAddr.numberOfDigits);
8758478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink            dos.write(destAddr.origBytes, 0, destAddr.origBytes.length); // digits
876767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // Subaddress is not supported.
877767a662ecde33c3979bf02b793d392aca0403162Wink Saville            dos.write(0); //subaddressType
878767a662ecde33c3979bf02b793d392aca0403162Wink Saville            dos.write(0); //subaddr_odd
879767a662ecde33c3979bf02b793d392aca0403162Wink Saville            dos.write(0); //subaddr_nbr_of_digits
8808478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink            dos.write(encodedBearerData.length);
8818478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink            dos.write(encodedBearerData, 0, encodedBearerData.length);
882767a662ecde33c3979bf02b793d392aca0403162Wink Saville            dos.close();
8838478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink
8848478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink            SubmitPdu pdu = new SubmitPdu();
8858478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink            pdu.encodedMessage = baos.toByteArray();
8868478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink            pdu.encodedScAddress = null;
8878478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink            return pdu;
888767a662ecde33c3979bf02b793d392aca0403162Wink Saville        } catch(IOException ex) {
8898478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink            Log.e(LOG_TAG, "creating SubmitPdu failed: " + ex);
890767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
8918478b59f177ec97a9996b71f7fac1509ba9ef493Tammo Spalink        return null;
892767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
893767a662ecde33c3979bf02b793d392aca0403162Wink Saville
894767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
895767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * Creates byte array (pseudo pdu) from SMS object.
896767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * Note: Do not call this method more than once per object!
897767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
898767a662ecde33c3979bf02b793d392aca0403162Wink Saville    private void createPdu() {
899767a662ecde33c3979bf02b793d392aca0403162Wink Saville        SmsEnvelope env = mEnvelope;
900767a662ecde33c3979bf02b793d392aca0403162Wink Saville        CdmaSmsAddress addr = env.origAddress;
901767a662ecde33c3979bf02b793d392aca0403162Wink Saville        ByteArrayOutputStream baos = new ByteArrayOutputStream(100);
902767a662ecde33c3979bf02b793d392aca0403162Wink Saville        DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(baos));
903767a662ecde33c3979bf02b793d392aca0403162Wink Saville
904767a662ecde33c3979bf02b793d392aca0403162Wink Saville        try {
905767a662ecde33c3979bf02b793d392aca0403162Wink Saville            dos.writeInt(env.messageType);
906767a662ecde33c3979bf02b793d392aca0403162Wink Saville            dos.writeInt(env.teleService);
907767a662ecde33c3979bf02b793d392aca0403162Wink Saville            dos.writeInt(env.serviceCategory);
908767a662ecde33c3979bf02b793d392aca0403162Wink Saville
909767a662ecde33c3979bf02b793d392aca0403162Wink Saville            dos.writeByte(addr.digitMode);
910767a662ecde33c3979bf02b793d392aca0403162Wink Saville            dos.writeByte(addr.numberMode);
911767a662ecde33c3979bf02b793d392aca0403162Wink Saville            dos.writeByte(addr.ton);
912767a662ecde33c3979bf02b793d392aca0403162Wink Saville            dos.writeByte(addr.numberPlan);
913767a662ecde33c3979bf02b793d392aca0403162Wink Saville            dos.writeByte(addr.numberOfDigits);
914767a662ecde33c3979bf02b793d392aca0403162Wink Saville            dos.write(addr.origBytes, 0, addr.origBytes.length); // digits
915767a662ecde33c3979bf02b793d392aca0403162Wink Saville
916767a662ecde33c3979bf02b793d392aca0403162Wink Saville            dos.writeInt(env.bearerReply);
917767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // CauseCode values:
918767a662ecde33c3979bf02b793d392aca0403162Wink Saville            dos.writeByte(env.replySeqNo);
919767a662ecde33c3979bf02b793d392aca0403162Wink Saville            dos.writeByte(env.errorClass);
920767a662ecde33c3979bf02b793d392aca0403162Wink Saville            dos.writeByte(env.causeCode);
921767a662ecde33c3979bf02b793d392aca0403162Wink Saville            //encoded BearerData:
922e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville            dos.writeInt(env.bearerData.length);
923767a662ecde33c3979bf02b793d392aca0403162Wink Saville            dos.write(env.bearerData, 0, env.bearerData.length);
924767a662ecde33c3979bf02b793d392aca0403162Wink Saville            dos.close();
925767a662ecde33c3979bf02b793d392aca0403162Wink Saville
92664c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink            /**
9275082fd58e33aa54d760459de3368912c37864a4fSatish Roddom             * TODO(cleanup) -- The mPdu field is managed in
9285082fd58e33aa54d760459de3368912c37864a4fSatish Roddom             * a fragile manner, and it would be much nicer if
92964c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink             * accessing the serialized representation used a less
93064c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink             * fragile mechanism.  Maybe the getPdu method could
93164c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink             * generate a representation if there was not yet one?
93264c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink             */
93364c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink
934767a662ecde33c3979bf02b793d392aca0403162Wink Saville            mPdu = baos.toByteArray();
935767a662ecde33c3979bf02b793d392aca0403162Wink Saville        } catch (IOException ex) {
936767a662ecde33c3979bf02b793d392aca0403162Wink Saville            Log.e(LOG_TAG, "createPdu: conversion from object to byte array failed: " + ex);
937767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
938767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
939767a662ecde33c3979bf02b793d392aca0403162Wink Saville
940e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville    /**
941e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville     * Converts a 4-Bit DTMF encoded symbol from the calling address number to ASCII character
942e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville     */
943e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville    private byte convertDtmfToAscii(byte dtmfDigit) {
944e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville        byte asciiDigit;
945e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville
946e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville        switch (dtmfDigit) {
947e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville        case  0: asciiDigit = 68; break; // 'D'
948e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville        case  1: asciiDigit = 49; break; // '1'
949e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville        case  2: asciiDigit = 50; break; // '2'
950e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville        case  3: asciiDigit = 51; break; // '3'
951e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville        case  4: asciiDigit = 52; break; // '4'
952e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville        case  5: asciiDigit = 53; break; // '5'
953e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville        case  6: asciiDigit = 54; break; // '6'
954e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville        case  7: asciiDigit = 55; break; // '7'
955e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville        case  8: asciiDigit = 56; break; // '8'
956e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville        case  9: asciiDigit = 57; break; // '9'
957e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville        case 10: asciiDigit = 48; break; // '0'
958e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville        case 11: asciiDigit = 42; break; // '*'
959e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville        case 12: asciiDigit = 35; break; // '#'
960e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville        case 13: asciiDigit = 65; break; // 'A'
961e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville        case 14: asciiDigit = 66; break; // 'B'
962e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville        case 15: asciiDigit = 67; break; // 'C'
963e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville        default:
964e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville            asciiDigit = 32; // Invalid DTMF code
965e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville            break;
966e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville        }
967e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville
968e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville        return asciiDigit;
969e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville    }
970e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville
971ce099c3226b33b43e0dd5d1f24347b14a2223ee1David Krause    /** This function  shall be called to get the number of voicemails.
972ce099c3226b33b43e0dd5d1f24347b14a2223ee1David Krause     * @hide
973ce099c3226b33b43e0dd5d1f24347b14a2223ee1David Krause     */
974ce099c3226b33b43e0dd5d1f24347b14a2223ee1David Krause    /*package*/ int getNumOfVoicemails() {
975ce099c3226b33b43e0dd5d1f24347b14a2223ee1David Krause        return mBearerData.numberOfMessages;
976ce099c3226b33b43e0dd5d1f24347b14a2223ee1David Krause    }
977e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville
9789d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson    /**
9799d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson     * Returns a byte array that can be use to uniquely identify a received SMS message.
9809d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson     * C.S0015-B  4.3.1.6 Unique Message Identification.
9819d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson     *
9829d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson     * @return byte array uniquely identifying the message.
9839d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson     * @hide
9849d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson     */
9859d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson    /* package */ byte[] getIncomingSmsFingerprint() {
9869d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson        ByteArrayOutputStream output = new ByteArrayOutputStream();
9879d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson
9889d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson        output.write(mEnvelope.teleService);
9899d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson        output.write(mEnvelope.origAddress.origBytes, 0, mEnvelope.origAddress.origBytes.length);
9909d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson        output.write(mEnvelope.bearerData, 0, mEnvelope.bearerData.length);
9917d16427653e047e4901988e7ee04d637e65253b7Naveen Kalla        output.write(mEnvelope.origSubaddress.origBytes, 0,
9927d16427653e047e4901988e7ee04d637e65253b7Naveen Kalla                mEnvelope.origSubaddress.origBytes.length);
993e66b5c43cb2d0aece7f4a636a2368a9c66c46cf5Wink Saville
9949d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson        return output.toByteArray();
9959d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson    }
9963e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby
9973e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby    /**
9983e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby     * Returns the list of service category program data, if present.
9993e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby     * @return a list of CdmaSmsCbProgramData objects, or null if not present
10003e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby     */
10017b661fb3fc17f981bb122520791344891a3c1661Jake Hamby    ArrayList<CdmaSmsCbProgramData> getSmsCbProgramData() {
10023e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby        return mBearerData.serviceCategoryProgramData;
10033e3c3f80a90b156ff500076f8655647dfb317acfJake Hamby    }
1004767a662ecde33c3979bf02b793d392aca0403162Wink Saville}
1005