10825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/*
20825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Copyright (C) 2008 The Android Open Source Project
30825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
40825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Licensed under the Apache License, Version 2.0 (the "License");
50825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * you may not use this file except in compliance with the License.
60825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * You may obtain a copy of the License at
70825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
80825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *      http://www.apache.org/licenses/LICENSE-2.0
90825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Unless required by applicable law or agreed to in writing, software
110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * distributed under the License is distributed on an "AS IS" BASIS,
120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * See the License for the specific language governing permissions and
140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * limitations under the License.
150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */
160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
170825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepackage com.android.internal.telephony.cdma;
180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
190825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Parcel;
200825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.SystemProperties;
210825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.telephony.PhoneNumberUtils;
220825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.telephony.SmsCbLocation;
230825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.telephony.SmsCbMessage;
24e70617d81dcd42350a737b11c25532e1d43df4ffLegler Wuimport android.telephony.TelephonyManager;
250825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.telephony.cdma.CdmaSmsCbProgramData;
26ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Savilleimport android.telephony.Rlog;
270825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.util.Log;
288b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Yingimport android.text.TextUtils;
298b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Yingimport android.content.res.Resources;
300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
310825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.GsmAlphabet.TextEncodingDetails;
320825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.SmsConstants;
330825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.SmsHeader;
340825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.SmsMessageBase;
350825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.TelephonyProperties;
360825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.cdma.sms.BearerData;
370825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.cdma.sms.CdmaSmsAddress;
380825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.cdma.sms.CdmaSmsSubaddress;
390825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.cdma.sms.SmsEnvelope;
400825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.cdma.sms.UserData;
41d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.IccUtils;
420825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.util.BitwiseInputStream;
430825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.util.HexDump;
448b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Yingimport com.android.internal.telephony.Sms7BitEncodingTranslator;
450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
460825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.io.BufferedOutputStream;
470825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.io.ByteArrayInputStream;
480825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.io.ByteArrayOutputStream;
490825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.io.DataInputStream;
500825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.io.DataOutputStream;
510825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.io.IOException;
52b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hambyimport java.util.ArrayList;
530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/**
550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * TODO(cleanup): these constants are disturbing... are they not just
560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * different interpretations on one number?  And if we did not have
570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * terrible class name overlap, they would not need to be directly
580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * imported like this.  The class in this file could just as well be
590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * named CdmaSmsMessage, could it not?
600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */
610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/**
630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * TODO(cleanup): internally returning null in many places makes
640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * debugging very hard (among many other reasons) and should be made
650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * more meaningful (replaced with exceptions for example).  Null
660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * returns should only occur at the very outside of the module/class
670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * scope.
680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */
690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/**
710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * A Short Message Service message.
720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */
740825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepublic class SmsMessage extends SmsMessageBase {
75cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    static final String LOG_TAG = "SmsMessage";
760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static private final String LOGGABLE_TAG = "CDMA:SMS";
77cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    private static final boolean VDBG = false;
780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private final static byte TELESERVICE_IDENTIFIER                    = 0x00;
800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private final static byte SERVICE_CATEGORY                          = 0x01;
810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private final static byte ORIGINATING_ADDRESS                       = 0x02;
820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private final static byte ORIGINATING_SUB_ADDRESS                   = 0x03;
830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private final static byte DESTINATION_ADDRESS                       = 0x04;
840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private final static byte DESTINATION_SUB_ADDRESS                   = 0x05;
850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private final static byte BEARER_REPLY_OPTION                       = 0x06;
860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private final static byte CAUSE_CODES                               = 0x07;
870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private final static byte BEARER_DATA                               = 0x08;
880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  Status of a previously submitted SMS.
910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  This field applies to SMS Delivery Acknowledge messages. 0 indicates success;
920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  Here, the error class is defined by the bits from 9-8, the status code by the bits from 7-0.
930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  See C.S0015-B, v2.0, 4.5.21 for a detailed description of possible values.
940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private int status;
960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** Specifies if a return of an acknowledgment is requested for send SMS */
980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int RETURN_NO_ACK  = 0;
990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int RETURN_ACK     = 1;
1000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private SmsEnvelope mEnvelope;
1020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private BearerData mBearerData;
1030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static class SubmitPdu extends SubmitPduBase {
1050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
1080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Create an SmsMessage from a raw PDU.
1090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Note: In CDMA the PDU is just a byte representation of the received Sms.
1100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
1110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static SmsMessage createFromPdu(byte[] pdu) {
1120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        SmsMessage msg = new SmsMessage();
1130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        try {
1150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            msg.parsePdu(pdu);
1160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return msg;
1170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } catch (RuntimeException ex) {
118ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville            Rlog.e(LOG_TAG, "SMS PDU parsing failed: ", ex);
1190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return null;
1201260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        } catch (OutOfMemoryError e) {
1211260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            Log.e(LOG_TAG, "SMS PDU parsing failed with out of memory: ", e);
1221260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            return null;
1230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
1240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
1270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  Create a "raw" CDMA SmsMessage from a Parcel that was forged in ril.cpp.
1280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  Note: Only primitive fields are set.
1290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
1300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static SmsMessage newFromParcel(Parcel p) {
1310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // Note: Parcel.readByte actually reads one Int and masks to byte
1320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        SmsMessage msg = new SmsMessage();
1330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        SmsEnvelope env = new SmsEnvelope();
1340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        CdmaSmsAddress addr = new CdmaSmsAddress();
1350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        CdmaSmsSubaddress subaddr = new CdmaSmsSubaddress();
1360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        byte[] data;
1370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        byte count;
1380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int countInt;
1390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int addressDigitMode;
1400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        //currently not supported by the modem-lib: env.mMessageType
1420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        env.teleService = p.readInt(); //p_cur->uTeleserviceID
1430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (0 != p.readByte()) { //p_cur->bIsServicePresent
1450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            env.messageType = SmsEnvelope.MESSAGE_TYPE_BROADCAST;
1460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
1470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        else {
1480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (SmsEnvelope.TELESERVICE_NOT_SET == env.teleService) {
1490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // assume type ACK
1500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                env.messageType = SmsEnvelope.MESSAGE_TYPE_ACKNOWLEDGE;
1510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else {
1520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                env.messageType = SmsEnvelope.MESSAGE_TYPE_POINT_TO_POINT;
1530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
1540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
1550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        env.serviceCategory = p.readInt(); //p_cur->uServicecategory
1560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // address
1580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        addressDigitMode = p.readInt();
1590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        addr.digitMode = (byte) (0xFF & addressDigitMode); //p_cur->sAddress.digit_mode
1600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        addr.numberMode = (byte) (0xFF & p.readInt()); //p_cur->sAddress.number_mode
1610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        addr.ton = p.readInt(); //p_cur->sAddress.number_type
1620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        addr.numberPlan = (byte) (0xFF & p.readInt()); //p_cur->sAddress.number_plan
1630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        count = p.readByte(); //p_cur->sAddress.number_of_digits
1640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        addr.numberOfDigits = count;
1650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        data = new byte[count];
1660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        //p_cur->sAddress.digits[digitCount]
1670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        for (int index=0; index < count; index++) {
1680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            data[index] = p.readByte();
1690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // convert the value if it is 4-bit DTMF to 8 bit
1710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (addressDigitMode == CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF) {
1720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                data[index] = msg.convertDtmfToAscii(data[index]);
1730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
1740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
1750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        addr.origBytes = data;
1770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        subaddr.type = p.readInt(); // p_cur->sSubAddress.subaddressType
1790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        subaddr.odd = p.readByte();     // p_cur->sSubAddress.odd
1800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        count = p.readByte();           // p_cur->sSubAddress.number_of_digits
1810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (count < 0) {
1830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            count = 0;
1840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
1850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // p_cur->sSubAddress.digits[digitCount] :
1870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        data = new byte[count];
1890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        for (int index = 0; index < count; ++index) {
1910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            data[index] = p.readByte();
1920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
1930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        subaddr.origBytes = data;
1950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        /* currently not supported by the modem-lib:
1970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            env.bearerReply
1980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            env.replySeqNo
1990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            env.errorClass
2000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            env.causeCode
2010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        */
2020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // bearer data
2040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        countInt = p.readInt(); //p_cur->uBearerDataLen
2050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (countInt < 0) {
2060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            countInt = 0;
2070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
2080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        data = new byte[countInt];
2100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        for (int index=0; index < countInt; index++) {
2110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            data[index] = p.readByte();
2120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
2130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // BD gets further decoded when accessed in SMSDispatcher
2140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        env.bearerData = data;
2150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // link the the filled objects to the SMS
2170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        env.origAddress = addr;
2180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        env.origSubaddress = subaddr;
21922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        msg.mOriginatingAddress = addr;
2200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        msg.mEnvelope = env;
2210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // create byte stream representation for transportation through the layers.
2230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        msg.createPdu();
2240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return msg;
2260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
2270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
2290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Create an SmsMessage from an SMS EF record.
2300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
2310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param index Index of SMS record. This should be index in ArrayList
2320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *              returned by RuimSmsInterfaceManager.getAllMessagesFromIcc + 1.
2330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param data Record data.
2340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @return An SmsMessage representing the record.
2350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
2360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @hide
2370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
2380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static SmsMessage createFromEfRecord(int index, byte[] data) {
2390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        try {
2400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            SmsMessage msg = new SmsMessage();
2410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
24222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            msg.mIndexOnIcc = index;
2430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // First byte is status: RECEIVED_READ, RECEIVED_UNREAD, STORED_SENT,
2450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // or STORED_UNSENT
2460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // See 3GPP2 C.S0023 3.4.27
2470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if ((data[0] & 1) == 0) {
248ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                Rlog.w(LOG_TAG, "SMS parsing failed: Trying to parse a free record");
2490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                return null;
2500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else {
25122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                msg.mStatusOnIcc = data[0] & 0x07;
2520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
2530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // Second byte is the MSG_LEN, length of the message
2550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // See 3GPP2 C.S0023 3.4.27
2560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            int size = data[1];
2570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // Note: Data may include trailing FF's.  That's OK; message
2590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // should still parse correctly.
2600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            byte[] pdu = new byte[size];
2610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            System.arraycopy(data, 2, pdu, 0, size);
2620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // the message has to be parsed before it can be displayed
2630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // see gsm.SmsMessage
2640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            msg.parsePduFromEfRecord(pdu);
2650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return msg;
2660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } catch (RuntimeException ex) {
267ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville            Rlog.e(LOG_TAG, "SMS PDU parsing failed: ", ex);
2680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return null;
2690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
2700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
2720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
2740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Note: This function is a GSM specific functionality which is not supported in CDMA mode.
2750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
2760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static int getTPLayerLengthForPDU(String pdu) {
277ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville        Rlog.w(LOG_TAG, "getTPLayerLengthForPDU: is not supported in CDMA mode.");
2780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return 0;
2790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
2800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
2820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * TODO(cleanup): why do getSubmitPdu methods take an scAddr input
2830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * and do nothing with it?  GSM allows us to specify a SC (eg,
2840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * when responding to an SMS that explicitly requests the response
2850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * is sent to a specific SC), or pass null to use the default
2860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * value.  Is there no similar notion in CDMA? Or do we just not
2870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * have it hooked up?
2880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
2890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
2910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Get an SMS-SUBMIT PDU for a destination address and a message
2920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
2930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param scAddr                Service Centre address.  Null means use default.
2940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param destAddr              Address of the recipient.
2950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param message               String representation of the message payload.
2960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param statusReportRequested Indicates whether a report is requested for this message.
2970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param smsHeader             Array containing the data for the User Data Header, preceded
2980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *                              by the Element Identifiers.
2990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @return a <code>SubmitPdu</code> containing the encoded SC
3000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *         address, if applicable, and the encoded message.
3010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *         Returns null on encode error.
3020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @hide
3030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
3040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static SubmitPdu getSubmitPdu(String scAddr, String destAddr, String message,
3050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            boolean statusReportRequested, SmsHeader smsHeader) {
3060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        /**
3080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville         * TODO(cleanup): Do we really want silent failure like this?
3090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville         * Would it not be much more reasonable to make sure we don't
3100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville         * call this function if we really want nothing done?
3110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville         */
3120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (message == null || destAddr == null) {
3130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return null;
3140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
3150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        UserData uData = new UserData();
3170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        uData.payloadStr = message;
3180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        uData.userDataHeader = smsHeader;
3190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return privateGetSubmitPdu(destAddr, statusReportRequested, uData);
3200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
3230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Get an SMS-SUBMIT PDU for a data message to a destination address and port.
3240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
3250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param scAddr Service Centre address. null == use default
3260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param destAddr the address of the destination for the message
3270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param destPort the port to deliver the message to at the
3280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *        destination
3290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param data the data for the message
3300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @return a <code>SubmitPdu</code> containing the encoded SC
3310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *         address, if applicable, and the encoded message.
3320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *         Returns null on encode error.
3330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
3340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static SubmitPdu getSubmitPdu(String scAddr, String destAddr, int destPort,
3350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            byte[] data, boolean statusReportRequested) {
3360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        /**
3380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville         * TODO(cleanup): this is not a general-purpose SMS creation
3390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville         * method, but rather something specialized to messages
3400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville         * containing OCTET encoded (meaning non-human-readable) user
3410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville         * data.  The name should reflect that, and not just overload.
3420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville         */
3430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        SmsHeader.PortAddrs portAddrs = new SmsHeader.PortAddrs();
3450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        portAddrs.destPort = destPort;
3460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        portAddrs.origPort = 0;
3470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        portAddrs.areEightBits = false;
3480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        SmsHeader smsHeader = new SmsHeader();
3500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        smsHeader.portAddrs = portAddrs;
3510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        UserData uData = new UserData();
3530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        uData.userDataHeader = smsHeader;
3540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        uData.msgEncoding = UserData.ENCODING_OCTET;
3550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        uData.msgEncodingSet = true;
3560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        uData.payload = data;
3570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return privateGetSubmitPdu(destAddr, statusReportRequested, uData);
3590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
3620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Get an SMS-SUBMIT PDU for a data message to a destination address &amp; port
3630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
3640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param destAddr the address of the destination for the message
3650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param userData the data for the message
3660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param statusReportRequested Indicates whether a report is requested for this message.
3670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @return a <code>SubmitPdu</code> containing the encoded SC
3680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *         address, if applicable, and the encoded message.
3690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *         Returns null on encode error.
3700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
3710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static SubmitPdu getSubmitPdu(String destAddr, UserData userData,
3720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            boolean statusReportRequested) {
3730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return privateGetSubmitPdu(destAddr, statusReportRequested, userData);
3740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
3770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Note: This function is a GSM specific functionality which is not supported in CDMA mode.
3780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
379cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
3800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public int getProtocolIdentifier() {
381ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville        Rlog.w(LOG_TAG, "getProtocolIdentifier: is not supported in CDMA mode.");
3820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // (3GPP TS 23.040): "no interworking, but SME to SME protocol":
3830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return 0;
3840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
3870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Note: This function is a GSM specific functionality which is not supported in CDMA mode.
3880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
389cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
3900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public boolean isReplace() {
391ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville        Rlog.w(LOG_TAG, "isReplace: is not supported in CDMA mode.");
3920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return false;
3930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
3960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * {@inheritDoc}
3970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Note: This function is a GSM specific functionality which is not supported in CDMA mode.
3980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
399cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
4000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public boolean isCphsMwiMessage() {
401ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville        Rlog.w(LOG_TAG, "isCphsMwiMessage: is not supported in CDMA mode.");
4020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return false;
4030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
4040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
4060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * {@inheritDoc}
4070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
408cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
4090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public boolean isMWIClearMessage() {
4100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return ((mBearerData != null) && (mBearerData.numberOfMessages == 0));
4110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
4120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
4140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * {@inheritDoc}
4150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
416cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
4170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public boolean isMWISetMessage() {
4180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return ((mBearerData != null) && (mBearerData.numberOfMessages > 0));
4190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
4200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
4220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * {@inheritDoc}
4230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
424cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
4250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public boolean isMwiDontStore() {
4260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return ((mBearerData != null) &&
4270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                (mBearerData.numberOfMessages > 0) &&
4280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                (mBearerData.userData == null));
4290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
4300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
4320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Returns the status for a previously submitted message.
4330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * For not interfering with status codes from GSM, this status code is
4340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * shifted to the bits 31-16.
4350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
436cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
4370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public int getStatus() {
4380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return (status << 16);
4390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
4400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** Return true iff the bearer data message type is DELIVERY_ACK. */
442cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
4430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public boolean isStatusReportMessage() {
4440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return (mBearerData.messageType == BearerData.MESSAGE_TYPE_DELIVERY_ACK);
4450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
4460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
4480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Note: This function is a GSM specific functionality which is not supported in CDMA mode.
4490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
450cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
4510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public boolean isReplyPathPresent() {
452ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville        Rlog.w(LOG_TAG, "isReplyPathPresent: is not supported in CDMA mode.");
4530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return false;
4540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
4550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
4570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Calculate the number of septets needed to encode the message.
4580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
4590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param messageBody the message to encode
4600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param use7bitOnly ignore (but still count) illegal characters if true
4613ce96a061c2c6e24f4ff3bd237e18c29fc0c0108Amit Mahajan     * @param isEntireMsg indicates if this is entire msg or a segment in multipart msg
4620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @return TextEncodingDetails
4630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
4640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static TextEncodingDetails calculateLength(CharSequence messageBody,
4653ce96a061c2c6e24f4ff3bd237e18c29fc0c0108Amit Mahajan            boolean use7bitOnly, boolean isEntireMsg) {
4668b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        CharSequence newMsgBody = null;
4678b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        Resources r = Resources.getSystem();
4688b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        if (r.getBoolean(com.android.internal.R.bool.config_sms_force_7bit_encoding)) {
4698b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            newMsgBody  = Sms7BitEncodingTranslator.translate(messageBody);
4708b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        }
4718b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        if (TextUtils.isEmpty(newMsgBody)) {
4728b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            newMsgBody = messageBody;
4738b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        }
4743ce96a061c2c6e24f4ff3bd237e18c29fc0c0108Amit Mahajan        return BearerData.calcTextEncodingDetails(newMsgBody, use7bitOnly, isEntireMsg);
4750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
4760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
4780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Returns the teleservice type of the message.
4790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @return the teleservice:
4800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#TELESERVICE_NOT_SET},
4810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#TELESERVICE_WMT},
4820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#TELESERVICE_WEMT},
4830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#TELESERVICE_VMN},
4840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#TELESERVICE_WAP}
4850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    */
48652f23cd068ffc05a2aaa101472d36a2861e55f29Amit Mahajan    public int getTeleService() {
4870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return mEnvelope.teleService;
4880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
4890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
4910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Returns the message type of the message.
4920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @return the message type:
4930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#MESSAGE_TYPE_POINT_TO_POINT},
4940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#MESSAGE_TYPE_BROADCAST},
4950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#MESSAGE_TYPE_ACKNOWLEDGE},
4960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    */
49752f23cd068ffc05a2aaa101472d36a2861e55f29Amit Mahajan    public int getMessageType() {
49834661b1e9381d56b168777e3f18f6f9f2ad305c1Jake Hamby        // NOTE: mEnvelope.messageType is not set correctly for cell broadcasts with some RILs.
49934661b1e9381d56b168777e3f18f6f9f2ad305c1Jake Hamby        // Use the service category parameter to detect CMAS and other cell broadcast messages.
50034661b1e9381d56b168777e3f18f6f9f2ad305c1Jake Hamby        if (mEnvelope.serviceCategory != 0) {
50134661b1e9381d56b168777e3f18f6f9f2ad305c1Jake Hamby            return SmsEnvelope.MESSAGE_TYPE_BROADCAST;
50234661b1e9381d56b168777e3f18f6f9f2ad305c1Jake Hamby        } else {
50334661b1e9381d56b168777e3f18f6f9f2ad305c1Jake Hamby            return SmsEnvelope.MESSAGE_TYPE_POINT_TO_POINT;
50434661b1e9381d56b168777e3f18f6f9f2ad305c1Jake Hamby        }
5050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
5060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
5080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Decodes pdu to an empty SMS object.
5090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * In the CDMA case the pdu is just an internal byte stream representation
5100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * of the SMS Java-object.
5110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @see #createPdu()
5120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
5130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void parsePdu(byte[] pdu) {
5140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        ByteArrayInputStream bais = new ByteArrayInputStream(pdu);
5150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        DataInputStream dis = new DataInputStream(bais);
516e72ec3f4031a24982d402bb35a7d17dc1868958dkyunga        int length;
5170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int bearerDataLength;
5180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        SmsEnvelope env = new SmsEnvelope();
5190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        CdmaSmsAddress addr = new CdmaSmsAddress();
5200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        try {
5220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            env.messageType = dis.readInt();
5230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            env.teleService = dis.readInt();
5240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            env.serviceCategory = dis.readInt();
5250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            addr.digitMode = dis.readByte();
5270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            addr.numberMode = dis.readByte();
5280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            addr.ton = dis.readByte();
5290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            addr.numberPlan = dis.readByte();
5300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
531e72ec3f4031a24982d402bb35a7d17dc1868958dkyunga            length = dis.readUnsignedByte();
5320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            addr.numberOfDigits = length;
5331260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
5341260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            // sanity check on the length
5351260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            if (length > pdu.length) {
5361260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                throw new RuntimeException(
5371260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                        "createFromPdu: Invalid pdu, addr.numberOfDigits " + length
5381260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                        + " > pdu len " + pdu.length);
5391260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            }
5400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            addr.origBytes = new byte[length];
5410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            dis.read(addr.origBytes, 0, length); // digits
5420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            env.bearerReply = dis.readInt();
5440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // CauseCode values:
5450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            env.replySeqNo = dis.readByte();
5460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            env.errorClass = dis.readByte();
5470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            env.causeCode = dis.readByte();
5480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            //encoded BearerData:
5500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            bearerDataLength = dis.readInt();
5511260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            // sanity check on the length
5521260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            if (bearerDataLength > pdu.length) {
5531260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                throw new RuntimeException(
5541260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                        "createFromPdu: Invalid pdu, bearerDataLength " + bearerDataLength
5551260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                        + " > pdu len " + pdu.length);
5561260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            }
5570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            env.bearerData = new byte[bearerDataLength];
5580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            dis.read(env.bearerData, 0, bearerDataLength);
5590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            dis.close();
5601260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        } catch (IOException ex) {
5611260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            throw new RuntimeException(
5621260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                    "createFromPdu: conversion from byte array to object failed: " + ex, ex);
5630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } catch (Exception ex) {
564ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville            Rlog.e(LOG_TAG, "createFromPdu: conversion from byte array to object failed: " + ex);
5650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
5660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // link the filled objects to this SMS
56822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mOriginatingAddress = addr;
5690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        env.origAddress = addr;
5700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mEnvelope = env;
5710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mPdu = pdu;
5720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        parseSms();
5740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
5750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
5770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Decodes 3GPP2 sms stored in CSIM/RUIM cards As per 3GPP2 C.S0015-0
5780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
5790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void parsePduFromEfRecord(byte[] pdu) {
5800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        ByteArrayInputStream bais = new ByteArrayInputStream(pdu);
5810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        DataInputStream dis = new DataInputStream(bais);
5820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        SmsEnvelope env = new SmsEnvelope();
5830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        CdmaSmsAddress addr = new CdmaSmsAddress();
5840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        CdmaSmsSubaddress subAddr = new CdmaSmsSubaddress();
5850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        try {
5870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            env.messageType = dis.readByte();
5880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            while (dis.available() > 0) {
5900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                int parameterId = dis.readByte();
591e72ec3f4031a24982d402bb35a7d17dc1868958dkyunga                int parameterLen = dis.readUnsignedByte();
5920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                byte[] parameterData = new byte[parameterLen];
5930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                switch (parameterId) {
5950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    case TELESERVICE_IDENTIFIER:
5960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        /*
5970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                         * 16 bit parameter that identifies which upper layer
5980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                         * service access point is sending or should receive
5990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                         * this message
6000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                         */
6010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        env.teleService = dis.readUnsignedShort();
602ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                        Rlog.i(LOG_TAG, "teleservice = " + env.teleService);
6030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        break;
6040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    case SERVICE_CATEGORY:
6050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        /*
6060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                         * 16 bit parameter that identifies type of service as
6070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                         * in 3GPP2 C.S0015-0 Table 3.4.3.2-1
6080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                         */
6090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        env.serviceCategory = dis.readUnsignedShort();
6100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        break;
6110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    case ORIGINATING_ADDRESS:
6120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    case DESTINATION_ADDRESS:
6130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        dis.read(parameterData, 0, parameterLen);
6140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        BitwiseInputStream addrBis = new BitwiseInputStream(parameterData);
6150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        addr.digitMode = addrBis.read(1);
6160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        addr.numberMode = addrBis.read(1);
6170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        int numberType = 0;
6180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR) {
6190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            numberType = addrBis.read(3);
6200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            addr.ton = numberType;
6210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            if (addr.numberMode == CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK)
6230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                addr.numberPlan = addrBis.read(4);
6240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        }
6250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        addr.numberOfDigits = addrBis.read(8);
6270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        byte[] data = new byte[addr.numberOfDigits];
6290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        byte b = 0x00;
6300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF) {
6320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            /* As per 3GPP2 C.S0005-0 Table 2.7.1.3.2.4-4 */
6330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            for (int index = 0; index < addr.numberOfDigits; index++) {
6340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                b = (byte) (0xF & addrBis.read(4));
6350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                // convert the value if it is 4-bit DTMF to 8
6360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                // bit
6370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                data[index] = convertDtmfToAscii(b);
6380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            }
6390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        } else if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR) {
6400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            if (addr.numberMode == CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK) {
6410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                for (int index = 0; index < addr.numberOfDigits; index++) {
6420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                    b = (byte) (0xFF & addrBis.read(8));
6430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                    data[index] = b;
6440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                }
6450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            } else if (addr.numberMode == CdmaSmsAddress.NUMBER_MODE_DATA_NETWORK) {
6470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                if (numberType == 2)
648ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                                    Rlog.e(LOG_TAG, "TODO: Originating Addr is email id");
6490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                else
650ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                                    Rlog.e(LOG_TAG,
6510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                          "TODO: Originating Addr is data network address");
6520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            } else {
653ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                                Rlog.e(LOG_TAG, "Originating Addr is of incorrect type");
6540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            }
6550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        } else {
656ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                            Rlog.e(LOG_TAG, "Incorrect Digit mode");
6570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        }
6580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        addr.origBytes = data;
659ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                        Rlog.i(LOG_TAG, "Originating Addr=" + addr.toString());
6600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        break;
6610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    case ORIGINATING_SUB_ADDRESS:
6620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    case DESTINATION_SUB_ADDRESS:
6630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        dis.read(parameterData, 0, parameterLen);
6640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        BitwiseInputStream subAddrBis = new BitwiseInputStream(parameterData);
6650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        subAddr.type = subAddrBis.read(3);
6660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        subAddr.odd = subAddrBis.readByteArray(1)[0];
6670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        int subAddrLen = subAddrBis.read(8);
6680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        byte[] subdata = new byte[subAddrLen];
6690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        for (int index = 0; index < subAddrLen; index++) {
6700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            b = (byte) (0xFF & subAddrBis.read(4));
6710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            // convert the value if it is 4-bit DTMF to 8 bit
6720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            subdata[index] = convertDtmfToAscii(b);
6730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        }
6740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        subAddr.origBytes = subdata;
6750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        break;
6760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    case BEARER_REPLY_OPTION:
6770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        dis.read(parameterData, 0, parameterLen);
6780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        BitwiseInputStream replyOptBis = new BitwiseInputStream(parameterData);
6790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        env.bearerReply = replyOptBis.read(6);
6800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        break;
6810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    case CAUSE_CODES:
6820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        dis.read(parameterData, 0, parameterLen);
6830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        BitwiseInputStream ccBis = new BitwiseInputStream(parameterData);
6840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        env.replySeqNo = ccBis.readByteArray(6)[0];
6850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        env.errorClass = ccBis.readByteArray(2)[0];
6860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        if (env.errorClass != 0x00)
6870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            env.causeCode = ccBis.readByteArray(8)[0];
6880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        break;
6890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    case BEARER_DATA:
6900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        dis.read(parameterData, 0, parameterLen);
6910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        env.bearerData = parameterData;
6920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        break;
6930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    default:
6940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        throw new Exception("unsupported parameterId (" + parameterId + ")");
6950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
6960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
6970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            bais.close();
6980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            dis.close();
6990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } catch (Exception ex) {
700ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville            Rlog.e(LOG_TAG, "parsePduFromEfRecord: conversion from pdu to SmsMessage failed" + ex);
7010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
7020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // link the filled objects to this SMS
70422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mOriginatingAddress = addr;
7050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        env.origAddress = addr;
7060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        env.origSubaddress = subAddr;
7070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mEnvelope = env;
7080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mPdu = pdu;
7090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        parseSms();
7110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
7120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
7140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Parses a SMS message from its BearerData stream. (mobile-terminated only)
7150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
7161a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu    public void parseSms() {
7170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // Message Waiting Info Record defined in 3GPP2 C.S-0005, 3.7.5.6
7180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // It contains only an 8-bit number with the number of messages waiting
7190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (mEnvelope.teleService == SmsEnvelope.TELESERVICE_MWI) {
7200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mBearerData = new BearerData();
7210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (mEnvelope.bearerData != null) {
7220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mBearerData.numberOfMessages = 0x000000FF & mEnvelope.bearerData[0];
7230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
724cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville            if (VDBG) {
725ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                Rlog.d(LOG_TAG, "parseSms: get MWI " +
7260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                      Integer.toString(mBearerData.numberOfMessages));
7270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
7280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return;
7290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
7300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mBearerData = BearerData.decode(mEnvelope.bearerData);
731ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville        if (Rlog.isLoggable(LOGGABLE_TAG, Log.VERBOSE)) {
732ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville            Rlog.d(LOG_TAG, "MT raw BearerData = '" +
7330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                      HexDump.toHexString(mEnvelope.bearerData) + "'");
734ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville            Rlog.d(LOG_TAG, "MT (decoded) BearerData = " + mBearerData);
7350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
73622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mMessageRef = mBearerData.messageId;
7370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (mBearerData.userData != null) {
73822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mUserData = mBearerData.userData.payload;
73922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mUserDataHeader = mBearerData.userData.userDataHeader;
74022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mMessageBody = mBearerData.userData.payloadStr;
7410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
7420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
74322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mOriginatingAddress != null) {
74422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mOriginatingAddress.address = new String(mOriginatingAddress.origBytes);
74504187ec4d9cdef64cc1257815fa9e44e37202a86Sudheer Reddy Yampalla            if (mOriginatingAddress.ton == CdmaSmsAddress.TON_INTERNATIONAL_OR_IP) {
74604187ec4d9cdef64cc1257815fa9e44e37202a86Sudheer Reddy Yampalla                if (mOriginatingAddress.address.charAt(0) != '+') {
74704187ec4d9cdef64cc1257815fa9e44e37202a86Sudheer Reddy Yampalla                    mOriginatingAddress.address = "+" + mOriginatingAddress.address;
74804187ec4d9cdef64cc1257815fa9e44e37202a86Sudheer Reddy Yampalla                }
74904187ec4d9cdef64cc1257815fa9e44e37202a86Sudheer Reddy Yampalla            }
750cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville            if (VDBG) Rlog.v(LOG_TAG, "SMS originating address: "
75122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    + mOriginatingAddress.address);
7520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
7530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (mBearerData.msgCenterTimeStamp != null) {
75522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mScTimeMillis = mBearerData.msgCenterTimeStamp.toMillis(true);
7560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
7570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
75822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (VDBG) Rlog.d(LOG_TAG, "SMS SC timestamp: " + mScTimeMillis);
7590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // Message Type (See 3GPP2 C.S0015-B, v2, 4.5.1)
7610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (mBearerData.messageType == BearerData.MESSAGE_TYPE_DELIVERY_ACK) {
7620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // The BearerData MsgStatus subparameter should only be
7630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // included for DELIVERY_ACK messages.  If it occurred for
7640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // other messages, it would be unclear what the status
7650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // being reported refers to.  The MsgStatus subparameter
7660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // is primarily useful to indicate error conditions -- a
7670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // message without this subparameter is assumed to
7680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // indicate successful delivery (status == 0).
7690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (! mBearerData.messageStatusSet) {
770ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                Rlog.d(LOG_TAG, "DELIVERY_ACK message without msgStatus (" +
77122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        (mUserData == null ? "also missing" : "does have") +
7720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        " userData).");
7730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                status = 0;
7740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else {
7750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                status = mBearerData.errorClass << 8;
7760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                status |= mBearerData.messageStatus;
7770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
7780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else if (mBearerData.messageType != BearerData.MESSAGE_TYPE_DELIVER) {
7790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            throw new RuntimeException("Unsupported message type: " + mBearerData.messageType);
7800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
7810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
78222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mMessageBody != null) {
78322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            if (VDBG) Rlog.v(LOG_TAG, "SMS message body: '" + mMessageBody + "'");
7840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            parseMessageBody();
78522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        } else if ((mUserData != null) && VDBG) {
78622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            Rlog.v(LOG_TAG, "SMS payload: '" + IccUtils.bytesToHexString(mUserData) + "'");
7870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
7880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
7890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
7910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Parses a broadcast SMS, possibly containing a CMAS alert.
7920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
7931a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu    public SmsCbMessage parseBroadcastSms() {
7940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        BearerData bData = BearerData.decode(mEnvelope.bearerData, mEnvelope.serviceCategory);
7950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (bData == null) {
796ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville            Rlog.w(LOG_TAG, "BearerData.decode() returned null");
7970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return null;
7980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
7990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
800ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville        if (Rlog.isLoggable(LOGGABLE_TAG, Log.VERBOSE)) {
801ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville            Rlog.d(LOG_TAG, "MT raw BearerData = " + HexDump.toHexString(mEnvelope.bearerData));
8020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
8030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
804e70617d81dcd42350a737b11c25532e1d43df4ffLegler Wu        String plmn = TelephonyManager.getDefault().getNetworkOperator();
8050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        SmsCbLocation location = new SmsCbLocation(plmn);
8060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return new SmsCbMessage(SmsCbMessage.MESSAGE_FORMAT_3GPP2,
8080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                SmsCbMessage.GEOGRAPHICAL_SCOPE_PLMN_WIDE, bData.messageId, location,
8090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mEnvelope.serviceCategory, bData.getLanguage(), bData.userData.payloadStr,
8100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                bData.priority, null, bData.cmasWarningInfo);
8110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
8120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
8140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * {@inheritDoc}
8150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
8160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    @Override
8170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public SmsConstants.MessageClass getMessageClass() {
8180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (BearerData.DISPLAY_MODE_IMMEDIATE == mBearerData.displayMode ) {
8190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return SmsConstants.MessageClass.CLASS_0;
8200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else {
8210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return SmsConstants.MessageClass.UNKNOWN;
8220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
8230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
8240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
8260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Calculate the next message id, starting at 1 and iteratively
8270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * incrementing within the range 1..65535 remembering the state
8280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * via a persistent system property.  (See C.S0015-B, v2.0,
8290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * 4.3.1.5) Since this routine is expected to be accessed via via
8300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * binder-call, and hence should be thread-safe, it has been
8310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * synchronized.
8320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
83352f23cd068ffc05a2aaa101472d36a2861e55f29Amit Mahajan    public synchronized static int getNextMessageId() {
8340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // Testing and dialog with partners has indicated that
8350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // msgId==0 is (sometimes?) treated specially by lower levels.
8360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // Specifically, the ID is not preserved for delivery ACKs.
8370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // Hence, avoid 0 -- constraining the range to 1..65535.
8380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int msgId = SystemProperties.getInt(TelephonyProperties.PROPERTY_CDMA_MSG_ID, 1);
8390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        String nextMsgId = Integer.toString((msgId % 0xFFFF) + 1);
840f06b7cffd2240725be159097be048fc1d3a7653cfionaxu        try{
841f06b7cffd2240725be159097be048fc1d3a7653cfionaxu            SystemProperties.set(TelephonyProperties.PROPERTY_CDMA_MSG_ID, nextMsgId);
842f06b7cffd2240725be159097be048fc1d3a7653cfionaxu            if (Rlog.isLoggable(LOGGABLE_TAG, Log.VERBOSE)) {
843f06b7cffd2240725be159097be048fc1d3a7653cfionaxu                Rlog.d(LOG_TAG, "next " + TelephonyProperties.PROPERTY_CDMA_MSG_ID + " = " + nextMsgId);
844f06b7cffd2240725be159097be048fc1d3a7653cfionaxu                Rlog.d(LOG_TAG, "readback gets " +
845f06b7cffd2240725be159097be048fc1d3a7653cfionaxu                        SystemProperties.get(TelephonyProperties.PROPERTY_CDMA_MSG_ID));
846f06b7cffd2240725be159097be048fc1d3a7653cfionaxu            }
847f06b7cffd2240725be159097be048fc1d3a7653cfionaxu        } catch(RuntimeException ex) {
848f06b7cffd2240725be159097be048fc1d3a7653cfionaxu            Rlog.e(LOG_TAG, "set nextMessage ID failed: " + ex);
8490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
8500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return msgId;
8510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
8520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
8540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Creates BearerData and Envelope from parameters for a Submit SMS.
8550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @return byte stream for SubmitPdu.
8560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
8570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static SubmitPdu privateGetSubmitPdu(String destAddrStr, boolean statusReportRequested,
8580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            UserData userData) {
8590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        /**
8610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville         * TODO(cleanup): give this function a more meaningful name.
8620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville         */
8630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        /**
8650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville         * TODO(cleanup): Make returning null from the getSubmitPdu
8660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville         * variations meaningful -- clean up the error feedback
8670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville         * mechanism, and avoid null pointer exceptions.
8680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville         */
8690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        /**
8710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville         * North America Plus Code :
8720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville         * Convert + code to 011 and dial out for international SMS
8730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville         */
8740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        CdmaSmsAddress destAddr = CdmaSmsAddress.parse(
8758409d93cf9f3ed23db12f24b4f49063ea416b30bJake Hamby                PhoneNumberUtils.cdmaCheckAndProcessPlusCodeForSms(destAddrStr));
8760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (destAddr == null) return null;
8770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        BearerData bearerData = new BearerData();
8790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        bearerData.messageType = BearerData.MESSAGE_TYPE_SUBMIT;
8800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        bearerData.messageId = getNextMessageId();
8820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        bearerData.deliveryAckReq = statusReportRequested;
8840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        bearerData.userAckReq = false;
8850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        bearerData.readAckReq = false;
8860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        bearerData.reportReq = false;
8870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        bearerData.userData = userData;
8890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        byte[] encodedBearerData = BearerData.encode(bearerData);
891ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville        if (Rlog.isLoggable(LOGGABLE_TAG, Log.VERBOSE)) {
892ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville            Rlog.d(LOG_TAG, "MO (encoded) BearerData = " + bearerData);
893ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville            Rlog.d(LOG_TAG, "MO raw BearerData = '" + HexDump.toHexString(encodedBearerData) + "'");
8940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
8950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (encodedBearerData == null) return null;
8960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int teleservice = bearerData.hasUserDataHeader ?
8980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                SmsEnvelope.TELESERVICE_WEMT : SmsEnvelope.TELESERVICE_WMT;
8990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        SmsEnvelope envelope = new SmsEnvelope();
9010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        envelope.messageType = SmsEnvelope.MESSAGE_TYPE_POINT_TO_POINT;
9020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        envelope.teleService = teleservice;
9030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        envelope.destAddress = destAddr;
9040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        envelope.bearerReply = RETURN_ACK;
9050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        envelope.bearerData = encodedBearerData;
9060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        /**
9080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville         * TODO(cleanup): envelope looks to be a pointless class, get
9090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville         * rid of it.  Also -- most of the envelope fields set here
9100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville         * are ignored, why?
9110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville         */
9120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        try {
9140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            /**
9150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville             * TODO(cleanup): reference a spec and get rid of the ugly comments
9160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville             */
9170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            ByteArrayOutputStream baos = new ByteArrayOutputStream(100);
9180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            DataOutputStream dos = new DataOutputStream(baos);
9190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            dos.writeInt(envelope.teleService);
9200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            dos.writeInt(0); //servicePresent
9210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            dos.writeInt(0); //serviceCategory
9220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            dos.write(destAddr.digitMode);
9230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            dos.write(destAddr.numberMode);
9240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            dos.write(destAddr.ton); // number_type
9250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            dos.write(destAddr.numberPlan);
9260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            dos.write(destAddr.numberOfDigits);
9270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            dos.write(destAddr.origBytes, 0, destAddr.origBytes.length); // digits
9280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // Subaddress is not supported.
9290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            dos.write(0); //subaddressType
9300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            dos.write(0); //subaddr_odd
9310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            dos.write(0); //subaddr_nbr_of_digits
9320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            dos.write(encodedBearerData.length);
9330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            dos.write(encodedBearerData, 0, encodedBearerData.length);
9340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            dos.close();
9350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            SubmitPdu pdu = new SubmitPdu();
9370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            pdu.encodedMessage = baos.toByteArray();
9380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            pdu.encodedScAddress = null;
9390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return pdu;
9400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } catch(IOException ex) {
941ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville            Rlog.e(LOG_TAG, "creating SubmitPdu failed: " + ex);
9420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
9430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return null;
9440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
9450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
9470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Creates byte array (pseudo pdu) from SMS object.
9480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Note: Do not call this method more than once per object!
9490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
9500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void createPdu() {
9510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        SmsEnvelope env = mEnvelope;
9520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        CdmaSmsAddress addr = env.origAddress;
9530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        ByteArrayOutputStream baos = new ByteArrayOutputStream(100);
9540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(baos));
9550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        try {
9570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            dos.writeInt(env.messageType);
9580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            dos.writeInt(env.teleService);
9590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            dos.writeInt(env.serviceCategory);
9600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            dos.writeByte(addr.digitMode);
9620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            dos.writeByte(addr.numberMode);
9630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            dos.writeByte(addr.ton);
9640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            dos.writeByte(addr.numberPlan);
9650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            dos.writeByte(addr.numberOfDigits);
9660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            dos.write(addr.origBytes, 0, addr.origBytes.length); // digits
9670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            dos.writeInt(env.bearerReply);
9690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // CauseCode values:
9700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            dos.writeByte(env.replySeqNo);
9710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            dos.writeByte(env.errorClass);
9720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            dos.writeByte(env.causeCode);
9730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            //encoded BearerData:
9740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            dos.writeInt(env.bearerData.length);
9750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            dos.write(env.bearerData, 0, env.bearerData.length);
9760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            dos.close();
9770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            /**
9790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville             * TODO(cleanup) -- The mPdu field is managed in
9800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville             * a fragile manner, and it would be much nicer if
9810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville             * accessing the serialized representation used a less
9820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville             * fragile mechanism.  Maybe the getPdu method could
9830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville             * generate a representation if there was not yet one?
9840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville             */
9850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mPdu = baos.toByteArray();
9870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } catch (IOException ex) {
988ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville            Rlog.e(LOG_TAG, "createPdu: conversion from object to byte array failed: " + ex);
9890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
9900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
9910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
9930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Converts a 4-Bit DTMF encoded symbol from the calling address number to ASCII character
9940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
9950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private byte convertDtmfToAscii(byte dtmfDigit) {
9960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        byte asciiDigit;
9970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        switch (dtmfDigit) {
9990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case  0: asciiDigit = 68; break; // 'D'
10000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case  1: asciiDigit = 49; break; // '1'
10010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case  2: asciiDigit = 50; break; // '2'
10020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case  3: asciiDigit = 51; break; // '3'
10030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case  4: asciiDigit = 52; break; // '4'
10040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case  5: asciiDigit = 53; break; // '5'
10050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case  6: asciiDigit = 54; break; // '6'
10060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case  7: asciiDigit = 55; break; // '7'
10070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case  8: asciiDigit = 56; break; // '8'
10080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case  9: asciiDigit = 57; break; // '9'
10090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case 10: asciiDigit = 48; break; // '0'
10100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case 11: asciiDigit = 42; break; // '*'
10110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case 12: asciiDigit = 35; break; // '#'
10120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case 13: asciiDigit = 65; break; // 'A'
10130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case 14: asciiDigit = 66; break; // 'B'
10140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case 15: asciiDigit = 67; break; // 'C'
10150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        default:
10160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            asciiDigit = 32; // Invalid DTMF code
10170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
10180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
10190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
10200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return asciiDigit;
10210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
10220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
10230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** This function  shall be called to get the number of voicemails.
10240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @hide
10250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
102652f23cd068ffc05a2aaa101472d36a2861e55f29Amit Mahajan    public int getNumOfVoicemails() {
10270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return mBearerData.numberOfMessages;
10280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
10290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
10300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
10310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Returns a byte array that can be use to uniquely identify a received SMS message.
10320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * C.S0015-B  4.3.1.6 Unique Message Identification.
10330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
10340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @return byte array uniquely identifying the message.
10350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @hide
10360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
103752f23cd068ffc05a2aaa101472d36a2861e55f29Amit Mahajan    public byte[] getIncomingSmsFingerprint() {
10380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        ByteArrayOutputStream output = new ByteArrayOutputStream();
10390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
10409ebea45a36838f0547a9c30f7cd9c60b03aab3b4Siddartha Pothapragada        output.write(mEnvelope.serviceCategory);
10410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        output.write(mEnvelope.teleService);
10420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        output.write(mEnvelope.origAddress.origBytes, 0, mEnvelope.origAddress.origBytes.length);
10430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        output.write(mEnvelope.bearerData, 0, mEnvelope.bearerData.length);
10440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        output.write(mEnvelope.origSubaddress.origBytes, 0,
10450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mEnvelope.origSubaddress.origBytes.length);
10460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
10470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return output.toByteArray();
10480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
10490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
10500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
10510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Returns the list of service category program data, if present.
10520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @return a list of CdmaSmsCbProgramData objects, or null if not present
1053a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * @hide
10540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
1055a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public ArrayList<CdmaSmsCbProgramData> getSmsCbProgramData() {
10560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return mBearerData.serviceCategoryProgramData;
10570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
10580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville}
1059