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 & 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 46143eaf7ebbdffd1791c4b9cf0dffebdd371a0210cAmit 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, 46543eaf7ebbdffd1791c4b9cf0dffebdd371a0210cAmit 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 } 47443eaf7ebbdffd1791c4b9cf0dffebdd371a0210cAmit 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 */ 4860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /* package */ 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 */ 4970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /* package */ 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 */ 7160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected 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 */ 7930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 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 */ 833b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby 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); 8400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville SystemProperties.set(TelephonyProperties.PROPERTY_CDMA_MSG_ID, nextMsgId); 841ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville if (Rlog.isLoggable(LOGGABLE_TAG, Log.VERBOSE)) { 842ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(LOG_TAG, "next " + TelephonyProperties.PROPERTY_CDMA_MSG_ID + " = " + nextMsgId); 843ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(LOG_TAG, "readback gets " + 8440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville SystemProperties.get(TelephonyProperties.PROPERTY_CDMA_MSG_ID)); 8450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return msgId; 8470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 8500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Creates BearerData and Envelope from parameters for a Submit SMS. 8510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @return byte stream for SubmitPdu. 8520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 8530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static SubmitPdu privateGetSubmitPdu(String destAddrStr, boolean statusReportRequested, 8540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville UserData userData) { 8550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 8570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * TODO(cleanup): give this function a more meaningful name. 8580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 8590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 8610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * TODO(cleanup): Make returning null from the getSubmitPdu 8620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * variations meaningful -- clean up the error feedback 8630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * mechanism, and avoid null pointer exceptions. 8640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 8650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 8670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * North America Plus Code : 8680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Convert + code to 011 and dial out for international SMS 8690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 8700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville CdmaSmsAddress destAddr = CdmaSmsAddress.parse( 8718409d93cf9f3ed23db12f24b4f49063ea416b30bJake Hamby PhoneNumberUtils.cdmaCheckAndProcessPlusCodeForSms(destAddrStr)); 8720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (destAddr == null) return null; 8730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville BearerData bearerData = new BearerData(); 8750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bearerData.messageType = BearerData.MESSAGE_TYPE_SUBMIT; 8760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bearerData.messageId = getNextMessageId(); 8780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bearerData.deliveryAckReq = statusReportRequested; 8800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bearerData.userAckReq = false; 8810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bearerData.readAckReq = false; 8820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bearerData.reportReq = false; 8830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bearerData.userData = userData; 8850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville byte[] encodedBearerData = BearerData.encode(bearerData); 887ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville if (Rlog.isLoggable(LOGGABLE_TAG, Log.VERBOSE)) { 888ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(LOG_TAG, "MO (encoded) BearerData = " + bearerData); 889ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(LOG_TAG, "MO raw BearerData = '" + HexDump.toHexString(encodedBearerData) + "'"); 8900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (encodedBearerData == null) return null; 8920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int teleservice = bearerData.hasUserDataHeader ? 8940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville SmsEnvelope.TELESERVICE_WEMT : SmsEnvelope.TELESERVICE_WMT; 8950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville SmsEnvelope envelope = new SmsEnvelope(); 8970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville envelope.messageType = SmsEnvelope.MESSAGE_TYPE_POINT_TO_POINT; 8980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville envelope.teleService = teleservice; 8990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville envelope.destAddress = destAddr; 9000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville envelope.bearerReply = RETURN_ACK; 9010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville envelope.bearerData = encodedBearerData; 9020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 9040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * TODO(cleanup): envelope looks to be a pointless class, get 9050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * rid of it. Also -- most of the envelope fields set here 9060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * are ignored, why? 9070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 9080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 9100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 9110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * TODO(cleanup): reference a spec and get rid of the ugly comments 9120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 9130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ByteArrayOutputStream baos = new ByteArrayOutputStream(100); 9140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville DataOutputStream dos = new DataOutputStream(baos); 9150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville dos.writeInt(envelope.teleService); 9160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville dos.writeInt(0); //servicePresent 9170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville dos.writeInt(0); //serviceCategory 9180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville dos.write(destAddr.digitMode); 9190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville dos.write(destAddr.numberMode); 9200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville dos.write(destAddr.ton); // number_type 9210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville dos.write(destAddr.numberPlan); 9220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville dos.write(destAddr.numberOfDigits); 9230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville dos.write(destAddr.origBytes, 0, destAddr.origBytes.length); // digits 9240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Subaddress is not supported. 9250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville dos.write(0); //subaddressType 9260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville dos.write(0); //subaddr_odd 9270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville dos.write(0); //subaddr_nbr_of_digits 9280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville dos.write(encodedBearerData.length); 9290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville dos.write(encodedBearerData, 0, encodedBearerData.length); 9300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville dos.close(); 9310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville SubmitPdu pdu = new SubmitPdu(); 9330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville pdu.encodedMessage = baos.toByteArray(); 9340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville pdu.encodedScAddress = null; 9350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return pdu; 9360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch(IOException ex) { 937ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(LOG_TAG, "creating SubmitPdu failed: " + ex); 9380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 9390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return null; 9400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 9410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 9430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Creates byte array (pseudo pdu) from SMS object. 9440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Note: Do not call this method more than once per object! 9450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 9460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private void createPdu() { 9470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville SmsEnvelope env = mEnvelope; 9480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville CdmaSmsAddress addr = env.origAddress; 9490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ByteArrayOutputStream baos = new ByteArrayOutputStream(100); 9500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(baos)); 9510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 9530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville dos.writeInt(env.messageType); 9540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville dos.writeInt(env.teleService); 9550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville dos.writeInt(env.serviceCategory); 9560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville dos.writeByte(addr.digitMode); 9580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville dos.writeByte(addr.numberMode); 9590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville dos.writeByte(addr.ton); 9600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville dos.writeByte(addr.numberPlan); 9610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville dos.writeByte(addr.numberOfDigits); 9620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville dos.write(addr.origBytes, 0, addr.origBytes.length); // digits 9630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville dos.writeInt(env.bearerReply); 9650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // CauseCode values: 9660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville dos.writeByte(env.replySeqNo); 9670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville dos.writeByte(env.errorClass); 9680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville dos.writeByte(env.causeCode); 9690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville //encoded BearerData: 9700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville dos.writeInt(env.bearerData.length); 9710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville dos.write(env.bearerData, 0, env.bearerData.length); 9720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville dos.close(); 9730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 9750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * TODO(cleanup) -- The mPdu field is managed in 9760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * a fragile manner, and it would be much nicer if 9770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * accessing the serialized representation used a less 9780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * fragile mechanism. Maybe the getPdu method could 9790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * generate a representation if there was not yet one? 9800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 9810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mPdu = baos.toByteArray(); 9830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (IOException ex) { 984ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(LOG_TAG, "createPdu: conversion from object to byte array failed: " + ex); 9850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 9860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 9870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 9890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Converts a 4-Bit DTMF encoded symbol from the calling address number to ASCII character 9900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 9910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private byte convertDtmfToAscii(byte dtmfDigit) { 9920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville byte asciiDigit; 9930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville switch (dtmfDigit) { 9950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case 0: asciiDigit = 68; break; // 'D' 9960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case 1: asciiDigit = 49; break; // '1' 9970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case 2: asciiDigit = 50; break; // '2' 9980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case 3: asciiDigit = 51; break; // '3' 9990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case 4: asciiDigit = 52; break; // '4' 10000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case 5: asciiDigit = 53; break; // '5' 10010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case 6: asciiDigit = 54; break; // '6' 10020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case 7: asciiDigit = 55; break; // '7' 10030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case 8: asciiDigit = 56; break; // '8' 10040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case 9: asciiDigit = 57; break; // '9' 10050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case 10: asciiDigit = 48; break; // '0' 10060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case 11: asciiDigit = 42; break; // '*' 10070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case 12: asciiDigit = 35; break; // '#' 10080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case 13: asciiDigit = 65; break; // 'A' 10090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case 14: asciiDigit = 66; break; // 'B' 10100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case 15: asciiDigit = 67; break; // 'C' 10110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville default: 10120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville asciiDigit = 32; // Invalid DTMF code 10130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 10140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return asciiDigit; 10170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** This function shall be called to get the number of voicemails. 10200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @hide 10210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 10220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /*package*/ int getNumOfVoicemails() { 10230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return mBearerData.numberOfMessages; 10240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 10270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Returns a byte array that can be use to uniquely identify a received SMS message. 10280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * C.S0015-B 4.3.1.6 Unique Message Identification. 10290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 10300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @return byte array uniquely identifying the message. 10310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @hide 10320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 10330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /* package */ byte[] getIncomingSmsFingerprint() { 10340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ByteArrayOutputStream output = new ByteArrayOutputStream(); 10350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10369ebea45a36838f0547a9c30f7cd9c60b03aab3b4Siddartha Pothapragada output.write(mEnvelope.serviceCategory); 10370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville output.write(mEnvelope.teleService); 10380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville output.write(mEnvelope.origAddress.origBytes, 0, mEnvelope.origAddress.origBytes.length); 10390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville output.write(mEnvelope.bearerData, 0, mEnvelope.bearerData.length); 10400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville output.write(mEnvelope.origSubaddress.origBytes, 0, 10410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mEnvelope.origSubaddress.origBytes.length); 10420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return output.toByteArray(); 10440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 10470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Returns the list of service category program data, if present. 10480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @return a list of CdmaSmsCbProgramData objects, or null if not present 1049a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * @hide 10500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 1051a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville public ArrayList<CdmaSmsCbProgramData> getSmsCbProgramData() { 10520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return mBearerData.serviceCategoryProgramData; 10530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville} 1055