SmsMessage.java revision 767a662ecde33c3979bf02b793d392aca0403162
1767a662ecde33c3979bf02b793d392aca0403162Wink Saville/* 2767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Copyright (C) 2006 The Android Open Source Project 3767a662ecde33c3979bf02b793d392aca0403162Wink Saville * 4767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Licensed under the Apache License, Version 2.0 (the "License"); 5767a662ecde33c3979bf02b793d392aca0403162Wink Saville * you may not use this file except in compliance with the License. 6767a662ecde33c3979bf02b793d392aca0403162Wink Saville * You may obtain a copy of the License at 7767a662ecde33c3979bf02b793d392aca0403162Wink Saville * 8767a662ecde33c3979bf02b793d392aca0403162Wink Saville * http://www.apache.org/licenses/LICENSE-2.0 9767a662ecde33c3979bf02b793d392aca0403162Wink Saville * 10767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Unless required by applicable law or agreed to in writing, software 11767a662ecde33c3979bf02b793d392aca0403162Wink Saville * distributed under the License is distributed on an "AS IS" BASIS, 12767a662ecde33c3979bf02b793d392aca0403162Wink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13767a662ecde33c3979bf02b793d392aca0403162Wink Saville * See the License for the specific language governing permissions and 14767a662ecde33c3979bf02b793d392aca0403162Wink Saville * limitations under the License. 15767a662ecde33c3979bf02b793d392aca0403162Wink Saville */ 16767a662ecde33c3979bf02b793d392aca0403162Wink Saville 17767a662ecde33c3979bf02b793d392aca0403162Wink Savillepackage com.android.internal.telephony.gsm; 18767a662ecde33c3979bf02b793d392aca0403162Wink Saville 19767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.os.Parcel; 20767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.telephony.PhoneNumberUtils; 21767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.text.format.Time; 22767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.util.Config; 23767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.util.Log; 24767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.IccUtils; 25767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.EncodeException; 26767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.GsmAlphabet; 27767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.SmsHeader; 28767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.SmsMessageBase; 29767a662ecde33c3979bf02b793d392aca0403162Wink Saville 30767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport java.io.ByteArrayOutputStream; 31767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport java.io.UnsupportedEncodingException; 32767a662ecde33c3979bf02b793d392aca0403162Wink Saville 33767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport static android.telephony.SmsMessage.ENCODING_7BIT; 34767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport static android.telephony.SmsMessage.ENCODING_8BIT; 35767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport static android.telephony.SmsMessage.ENCODING_16BIT; 36767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport static android.telephony.SmsMessage.ENCODING_UNKNOWN; 37767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport static android.telephony.SmsMessage.MAX_USER_DATA_BYTES; 38767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport static android.telephony.SmsMessage.MAX_USER_DATA_BYTES_WITH_HEADER; 39767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport static android.telephony.SmsMessage.MAX_USER_DATA_SEPTETS; 40767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport static android.telephony.SmsMessage.MAX_USER_DATA_SEPTETS_WITH_HEADER; 41767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport static android.telephony.SmsMessage.MessageClass; 42767a662ecde33c3979bf02b793d392aca0403162Wink Saville 43767a662ecde33c3979bf02b793d392aca0403162Wink Saville/** 44767a662ecde33c3979bf02b793d392aca0403162Wink Saville * A Short Message Service message. 45767a662ecde33c3979bf02b793d392aca0403162Wink Saville * 46767a662ecde33c3979bf02b793d392aca0403162Wink Saville */ 47767a662ecde33c3979bf02b793d392aca0403162Wink Savillepublic class SmsMessage extends SmsMessageBase{ 48767a662ecde33c3979bf02b793d392aca0403162Wink Saville static final String LOG_TAG = "GSM"; 49767a662ecde33c3979bf02b793d392aca0403162Wink Saville 50767a662ecde33c3979bf02b793d392aca0403162Wink Saville private MessageClass messageClass; 51767a662ecde33c3979bf02b793d392aca0403162Wink Saville 52767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** 53767a662ecde33c3979bf02b793d392aca0403162Wink Saville * TP-Message-Type-Indicator 54767a662ecde33c3979bf02b793d392aca0403162Wink Saville * 9.2.3 55767a662ecde33c3979bf02b793d392aca0403162Wink Saville */ 56767a662ecde33c3979bf02b793d392aca0403162Wink Saville private int mti; 57767a662ecde33c3979bf02b793d392aca0403162Wink Saville 58767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** TP-Protocol-Identifier (TP-PID) */ 59767a662ecde33c3979bf02b793d392aca0403162Wink Saville private int protocolIdentifier; 60767a662ecde33c3979bf02b793d392aca0403162Wink Saville 61767a662ecde33c3979bf02b793d392aca0403162Wink Saville // TP-Data-Coding-Scheme 62767a662ecde33c3979bf02b793d392aca0403162Wink Saville // see TS 23.038 63767a662ecde33c3979bf02b793d392aca0403162Wink Saville private int dataCodingScheme; 64767a662ecde33c3979bf02b793d392aca0403162Wink Saville 65767a662ecde33c3979bf02b793d392aca0403162Wink Saville // TP-Reply-Path 66767a662ecde33c3979bf02b793d392aca0403162Wink Saville // e.g. 23.040 9.2.2.1 67767a662ecde33c3979bf02b793d392aca0403162Wink Saville private boolean replyPathPresent = false; 68767a662ecde33c3979bf02b793d392aca0403162Wink Saville 69767a662ecde33c3979bf02b793d392aca0403162Wink Saville // "Message Marked for Automatic Deletion Group" 70767a662ecde33c3979bf02b793d392aca0403162Wink Saville // 23.038 Section 4 71767a662ecde33c3979bf02b793d392aca0403162Wink Saville private boolean automaticDeletion; 72767a662ecde33c3979bf02b793d392aca0403162Wink Saville 73767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** True if Status Report is for SMS-SUBMIT; false for SMS-COMMAND. */ 74767a662ecde33c3979bf02b793d392aca0403162Wink Saville private boolean forSubmit; 75767a662ecde33c3979bf02b793d392aca0403162Wink Saville 76767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** The address of the receiver. */ 77767a662ecde33c3979bf02b793d392aca0403162Wink Saville private GsmSmsAddress recipientAddress; 78767a662ecde33c3979bf02b793d392aca0403162Wink Saville 79767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** Time when SMS-SUBMIT was delivered from SC to MSE. */ 80767a662ecde33c3979bf02b793d392aca0403162Wink Saville private long dischargeTimeMillis; 81767a662ecde33c3979bf02b793d392aca0403162Wink Saville 82767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** 83767a662ecde33c3979bf02b793d392aca0403162Wink Saville * TP-Status - status of a previously submitted SMS. 84767a662ecde33c3979bf02b793d392aca0403162Wink Saville * This field applies to SMS-STATUS-REPORT messages. 0 indicates success; 85767a662ecde33c3979bf02b793d392aca0403162Wink Saville * see TS 23.040, 9.2.3.15 for description of other possible values. 86767a662ecde33c3979bf02b793d392aca0403162Wink Saville */ 87767a662ecde33c3979bf02b793d392aca0403162Wink Saville private int status; 88767a662ecde33c3979bf02b793d392aca0403162Wink Saville 89767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** 90767a662ecde33c3979bf02b793d392aca0403162Wink Saville * TP-Status - status of a previously submitted SMS. 91767a662ecde33c3979bf02b793d392aca0403162Wink Saville * This field is true iff the message is a SMS-STATUS-REPORT message. 92767a662ecde33c3979bf02b793d392aca0403162Wink Saville */ 93767a662ecde33c3979bf02b793d392aca0403162Wink Saville private boolean isStatusReportMessage = false; 94767a662ecde33c3979bf02b793d392aca0403162Wink Saville 95767a662ecde33c3979bf02b793d392aca0403162Wink Saville public static class SubmitPdu extends SubmitPduBase { 96767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 97767a662ecde33c3979bf02b793d392aca0403162Wink Saville 98767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** 99767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Create an SmsMessage from a raw PDU. 100767a662ecde33c3979bf02b793d392aca0403162Wink Saville */ 101767a662ecde33c3979bf02b793d392aca0403162Wink Saville public static SmsMessage createFromPdu(byte[] pdu) { 102767a662ecde33c3979bf02b793d392aca0403162Wink Saville try { 103767a662ecde33c3979bf02b793d392aca0403162Wink Saville SmsMessage msg = new SmsMessage(); 104767a662ecde33c3979bf02b793d392aca0403162Wink Saville msg.parsePdu(pdu); 105767a662ecde33c3979bf02b793d392aca0403162Wink Saville return msg; 106767a662ecde33c3979bf02b793d392aca0403162Wink Saville } catch (RuntimeException ex) { 107767a662ecde33c3979bf02b793d392aca0403162Wink Saville Log.e(LOG_TAG, "SMS PDU parsing failed: ", ex); 108767a662ecde33c3979bf02b793d392aca0403162Wink Saville return null; 109767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 110767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 111767a662ecde33c3979bf02b793d392aca0403162Wink Saville 112767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** 113767a662ecde33c3979bf02b793d392aca0403162Wink Saville * TS 27.005 3.4.1 lines[0] and lines[1] are the two lines read from the 114767a662ecde33c3979bf02b793d392aca0403162Wink Saville * +CMT unsolicited response (PDU mode, of course) 115767a662ecde33c3979bf02b793d392aca0403162Wink Saville * +CMT: [<alpha>],<length><CR><LF><pdu> 116767a662ecde33c3979bf02b793d392aca0403162Wink Saville * 117767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Only public for debugging 118767a662ecde33c3979bf02b793d392aca0403162Wink Saville * 119767a662ecde33c3979bf02b793d392aca0403162Wink Saville * {@hide} 120767a662ecde33c3979bf02b793d392aca0403162Wink Saville */ 121767a662ecde33c3979bf02b793d392aca0403162Wink Saville public static SmsMessage newFromCMT(String[] lines) { 122767a662ecde33c3979bf02b793d392aca0403162Wink Saville try { 123767a662ecde33c3979bf02b793d392aca0403162Wink Saville SmsMessage msg = new SmsMessage(); 124767a662ecde33c3979bf02b793d392aca0403162Wink Saville msg.parsePdu(IccUtils.hexStringToBytes(lines[1])); 125767a662ecde33c3979bf02b793d392aca0403162Wink Saville return msg; 126767a662ecde33c3979bf02b793d392aca0403162Wink Saville } catch (RuntimeException ex) { 127767a662ecde33c3979bf02b793d392aca0403162Wink Saville Log.e(LOG_TAG, "SMS PDU parsing failed: ", ex); 128767a662ecde33c3979bf02b793d392aca0403162Wink Saville return null; 129767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 130767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 131767a662ecde33c3979bf02b793d392aca0403162Wink Saville 132767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** @hide */ 133767a662ecde33c3979bf02b793d392aca0403162Wink Saville public static SmsMessage newFromCMTI(String line) { 134767a662ecde33c3979bf02b793d392aca0403162Wink Saville // the thinking here is not to read the message immediately 135767a662ecde33c3979bf02b793d392aca0403162Wink Saville // FTA test case 136767a662ecde33c3979bf02b793d392aca0403162Wink Saville Log.e(LOG_TAG, "newFromCMTI: not yet supported"); 137767a662ecde33c3979bf02b793d392aca0403162Wink Saville return null; 138767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 139767a662ecde33c3979bf02b793d392aca0403162Wink Saville 140767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** @hide */ 141767a662ecde33c3979bf02b793d392aca0403162Wink Saville public static SmsMessage newFromCDS(String line) { 142767a662ecde33c3979bf02b793d392aca0403162Wink Saville try { 143767a662ecde33c3979bf02b793d392aca0403162Wink Saville SmsMessage msg = new SmsMessage(); 144767a662ecde33c3979bf02b793d392aca0403162Wink Saville msg.parsePdu(IccUtils.hexStringToBytes(line)); 145767a662ecde33c3979bf02b793d392aca0403162Wink Saville return msg; 146767a662ecde33c3979bf02b793d392aca0403162Wink Saville } catch (RuntimeException ex) { 147767a662ecde33c3979bf02b793d392aca0403162Wink Saville Log.e(LOG_TAG, "CDS SMS PDU parsing failed: ", ex); 148767a662ecde33c3979bf02b793d392aca0403162Wink Saville return null; 149767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 150767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 151767a662ecde33c3979bf02b793d392aca0403162Wink Saville 152767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** 153767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Note: This functionality is currently not supported in GSM mode. 154767a662ecde33c3979bf02b793d392aca0403162Wink Saville * @hide 155767a662ecde33c3979bf02b793d392aca0403162Wink Saville */ 156767a662ecde33c3979bf02b793d392aca0403162Wink Saville public static SmsMessageBase newFromParcel(Parcel p){ 157767a662ecde33c3979bf02b793d392aca0403162Wink Saville Log.w(LOG_TAG, "newFromParcel: is not supported in GSM mode."); 158767a662ecde33c3979bf02b793d392aca0403162Wink Saville return null; 159767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 160767a662ecde33c3979bf02b793d392aca0403162Wink Saville 161767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** 162767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Create an SmsMessage from an SMS EF record. 163767a662ecde33c3979bf02b793d392aca0403162Wink Saville * 164767a662ecde33c3979bf02b793d392aca0403162Wink Saville * @param index Index of SMS record. This should be index in ArrayList 165767a662ecde33c3979bf02b793d392aca0403162Wink Saville * returned by SmsManager.getAllMessagesFromSim + 1. 166767a662ecde33c3979bf02b793d392aca0403162Wink Saville * @param data Record data. 167767a662ecde33c3979bf02b793d392aca0403162Wink Saville * @return An SmsMessage representing the record. 168767a662ecde33c3979bf02b793d392aca0403162Wink Saville * 169767a662ecde33c3979bf02b793d392aca0403162Wink Saville * @hide 170767a662ecde33c3979bf02b793d392aca0403162Wink Saville */ 171767a662ecde33c3979bf02b793d392aca0403162Wink Saville public static SmsMessage createFromEfRecord(int index, byte[] data) { 172767a662ecde33c3979bf02b793d392aca0403162Wink Saville try { 173767a662ecde33c3979bf02b793d392aca0403162Wink Saville SmsMessage msg = new SmsMessage(); 174767a662ecde33c3979bf02b793d392aca0403162Wink Saville 175767a662ecde33c3979bf02b793d392aca0403162Wink Saville msg.indexOnIcc = index; 176767a662ecde33c3979bf02b793d392aca0403162Wink Saville 177767a662ecde33c3979bf02b793d392aca0403162Wink Saville // First byte is status: RECEIVED_READ, RECEIVED_UNREAD, STORED_SENT, 178767a662ecde33c3979bf02b793d392aca0403162Wink Saville // or STORED_UNSENT 179767a662ecde33c3979bf02b793d392aca0403162Wink Saville // See TS 51.011 10.5.3 180767a662ecde33c3979bf02b793d392aca0403162Wink Saville if ((data[0] & 1) == 0) { 181767a662ecde33c3979bf02b793d392aca0403162Wink Saville Log.w(LOG_TAG, 182767a662ecde33c3979bf02b793d392aca0403162Wink Saville "SMS parsing failed: Trying to parse a free record"); 183767a662ecde33c3979bf02b793d392aca0403162Wink Saville return null; 184767a662ecde33c3979bf02b793d392aca0403162Wink Saville } else { 185767a662ecde33c3979bf02b793d392aca0403162Wink Saville msg.statusOnIcc = data[0] & 0x07; 186767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 187767a662ecde33c3979bf02b793d392aca0403162Wink Saville 188767a662ecde33c3979bf02b793d392aca0403162Wink Saville int size = data.length - 1; 189767a662ecde33c3979bf02b793d392aca0403162Wink Saville 190767a662ecde33c3979bf02b793d392aca0403162Wink Saville // Note: Data may include trailing FF's. That's OK; message 191767a662ecde33c3979bf02b793d392aca0403162Wink Saville // should still parse correctly. 192767a662ecde33c3979bf02b793d392aca0403162Wink Saville byte[] pdu = new byte[size]; 193767a662ecde33c3979bf02b793d392aca0403162Wink Saville System.arraycopy(data, 1, pdu, 0, size); 194767a662ecde33c3979bf02b793d392aca0403162Wink Saville msg.parsePdu(pdu); 195767a662ecde33c3979bf02b793d392aca0403162Wink Saville return msg; 196767a662ecde33c3979bf02b793d392aca0403162Wink Saville } catch (RuntimeException ex) { 197767a662ecde33c3979bf02b793d392aca0403162Wink Saville Log.e(LOG_TAG, "SMS PDU parsing failed: ", ex); 198767a662ecde33c3979bf02b793d392aca0403162Wink Saville return null; 199767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 200767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 201767a662ecde33c3979bf02b793d392aca0403162Wink Saville 202767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** 203767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Get the TP-Layer-Length for the given SMS-SUBMIT PDU Basically, the 204767a662ecde33c3979bf02b793d392aca0403162Wink Saville * length in bytes (not hex chars) less the SMSC header 205767a662ecde33c3979bf02b793d392aca0403162Wink Saville */ 206767a662ecde33c3979bf02b793d392aca0403162Wink Saville public static int getTPLayerLengthForPDU(String pdu) { 207767a662ecde33c3979bf02b793d392aca0403162Wink Saville int len = pdu.length() / 2; 208767a662ecde33c3979bf02b793d392aca0403162Wink Saville int smscLen = 0; 209767a662ecde33c3979bf02b793d392aca0403162Wink Saville 210767a662ecde33c3979bf02b793d392aca0403162Wink Saville smscLen = Integer.parseInt(pdu.substring(0, 2), 16); 211767a662ecde33c3979bf02b793d392aca0403162Wink Saville 212767a662ecde33c3979bf02b793d392aca0403162Wink Saville return len - smscLen - 1; 213767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 214767a662ecde33c3979bf02b793d392aca0403162Wink Saville 215767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** 216767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Get an SMS-SUBMIT PDU for a destination address and a message 217767a662ecde33c3979bf02b793d392aca0403162Wink Saville * 218767a662ecde33c3979bf02b793d392aca0403162Wink Saville * @param scAddress Service Centre address. Null means use default. 219767a662ecde33c3979bf02b793d392aca0403162Wink Saville * @return a <code>SubmitPdu</code> containing the encoded SC 220767a662ecde33c3979bf02b793d392aca0403162Wink Saville * address, if applicable, and the encoded message. 221767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Returns null on encode error. 222767a662ecde33c3979bf02b793d392aca0403162Wink Saville * @hide 223767a662ecde33c3979bf02b793d392aca0403162Wink Saville */ 224767a662ecde33c3979bf02b793d392aca0403162Wink Saville public static SubmitPdu getSubmitPdu(String scAddress, 225767a662ecde33c3979bf02b793d392aca0403162Wink Saville String destinationAddress, String message, 226767a662ecde33c3979bf02b793d392aca0403162Wink Saville boolean statusReportRequested, byte[] header) { 227767a662ecde33c3979bf02b793d392aca0403162Wink Saville 228767a662ecde33c3979bf02b793d392aca0403162Wink Saville // Perform null parameter checks. 229767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (message == null || destinationAddress == null) { 230767a662ecde33c3979bf02b793d392aca0403162Wink Saville return null; 231767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 232767a662ecde33c3979bf02b793d392aca0403162Wink Saville 233767a662ecde33c3979bf02b793d392aca0403162Wink Saville SubmitPdu ret = new SubmitPdu(); 234767a662ecde33c3979bf02b793d392aca0403162Wink Saville // MTI = SMS-SUBMIT, UDHI = header != null 235767a662ecde33c3979bf02b793d392aca0403162Wink Saville byte mtiByte = (byte)(0x01 | (header != null ? 0x40 : 0x00)); 236767a662ecde33c3979bf02b793d392aca0403162Wink Saville ByteArrayOutputStream bo = getSubmitPduHead( 237767a662ecde33c3979bf02b793d392aca0403162Wink Saville scAddress, destinationAddress, mtiByte, 238767a662ecde33c3979bf02b793d392aca0403162Wink Saville statusReportRequested, ret); 239767a662ecde33c3979bf02b793d392aca0403162Wink Saville 240767a662ecde33c3979bf02b793d392aca0403162Wink Saville try { 241767a662ecde33c3979bf02b793d392aca0403162Wink Saville // First, try encoding it with the GSM alphabet 242767a662ecde33c3979bf02b793d392aca0403162Wink Saville 243767a662ecde33c3979bf02b793d392aca0403162Wink Saville // User Data (and length) 244767a662ecde33c3979bf02b793d392aca0403162Wink Saville byte[] userData = GsmAlphabet.stringToGsm7BitPackedWithHeader(message, header); 245767a662ecde33c3979bf02b793d392aca0403162Wink Saville 246767a662ecde33c3979bf02b793d392aca0403162Wink Saville if ((0xff & userData[0]) > MAX_USER_DATA_SEPTETS) { 247767a662ecde33c3979bf02b793d392aca0403162Wink Saville // Message too long 248767a662ecde33c3979bf02b793d392aca0403162Wink Saville return null; 249767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 250767a662ecde33c3979bf02b793d392aca0403162Wink Saville 251767a662ecde33c3979bf02b793d392aca0403162Wink Saville // TP-Data-Coding-Scheme 252767a662ecde33c3979bf02b793d392aca0403162Wink Saville // Default encoding, uncompressed 253767a662ecde33c3979bf02b793d392aca0403162Wink Saville bo.write(0x00); 254767a662ecde33c3979bf02b793d392aca0403162Wink Saville 255767a662ecde33c3979bf02b793d392aca0403162Wink Saville // (no TP-Validity-Period) 256767a662ecde33c3979bf02b793d392aca0403162Wink Saville 257767a662ecde33c3979bf02b793d392aca0403162Wink Saville bo.write(userData, 0, userData.length); 258767a662ecde33c3979bf02b793d392aca0403162Wink Saville } catch (EncodeException ex) { 259767a662ecde33c3979bf02b793d392aca0403162Wink Saville byte[] userData, textPart; 260767a662ecde33c3979bf02b793d392aca0403162Wink Saville // Encoding to the 7-bit alphabet failed. Let's see if we can 261767a662ecde33c3979bf02b793d392aca0403162Wink Saville // send it as a UCS-2 encoded message 262767a662ecde33c3979bf02b793d392aca0403162Wink Saville 263767a662ecde33c3979bf02b793d392aca0403162Wink Saville try { 264767a662ecde33c3979bf02b793d392aca0403162Wink Saville textPart = message.getBytes("utf-16be"); 265767a662ecde33c3979bf02b793d392aca0403162Wink Saville } catch (UnsupportedEncodingException uex) { 266767a662ecde33c3979bf02b793d392aca0403162Wink Saville Log.e(LOG_TAG, 267767a662ecde33c3979bf02b793d392aca0403162Wink Saville "Implausible UnsupportedEncodingException ", 268767a662ecde33c3979bf02b793d392aca0403162Wink Saville uex); 269767a662ecde33c3979bf02b793d392aca0403162Wink Saville return null; 270767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 271767a662ecde33c3979bf02b793d392aca0403162Wink Saville 272767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (header != null) { 273767a662ecde33c3979bf02b793d392aca0403162Wink Saville userData = new byte[header.length + textPart.length]; 274767a662ecde33c3979bf02b793d392aca0403162Wink Saville 275767a662ecde33c3979bf02b793d392aca0403162Wink Saville System.arraycopy(header, 0, userData, 0, header.length); 276767a662ecde33c3979bf02b793d392aca0403162Wink Saville System.arraycopy(textPart, 0, userData, header.length, textPart.length); 277767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 278767a662ecde33c3979bf02b793d392aca0403162Wink Saville else { 279767a662ecde33c3979bf02b793d392aca0403162Wink Saville userData = textPart; 280767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 281767a662ecde33c3979bf02b793d392aca0403162Wink Saville 282767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (userData.length > MAX_USER_DATA_BYTES) { 283767a662ecde33c3979bf02b793d392aca0403162Wink Saville // Message too long 284767a662ecde33c3979bf02b793d392aca0403162Wink Saville return null; 285767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 286767a662ecde33c3979bf02b793d392aca0403162Wink Saville 287767a662ecde33c3979bf02b793d392aca0403162Wink Saville // TP-Data-Coding-Scheme 288767a662ecde33c3979bf02b793d392aca0403162Wink Saville // Class 3, UCS-2 encoding, uncompressed 289767a662ecde33c3979bf02b793d392aca0403162Wink Saville bo.write(0x0b); 290767a662ecde33c3979bf02b793d392aca0403162Wink Saville 291767a662ecde33c3979bf02b793d392aca0403162Wink Saville // (no TP-Validity-Period) 292767a662ecde33c3979bf02b793d392aca0403162Wink Saville 293767a662ecde33c3979bf02b793d392aca0403162Wink Saville // TP-UDL 294767a662ecde33c3979bf02b793d392aca0403162Wink Saville bo.write(userData.length); 295767a662ecde33c3979bf02b793d392aca0403162Wink Saville 296767a662ecde33c3979bf02b793d392aca0403162Wink Saville bo.write(userData, 0, userData.length); 297767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 298767a662ecde33c3979bf02b793d392aca0403162Wink Saville 299767a662ecde33c3979bf02b793d392aca0403162Wink Saville ret.encodedMessage = bo.toByteArray(); 300767a662ecde33c3979bf02b793d392aca0403162Wink Saville return ret; 301767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 302767a662ecde33c3979bf02b793d392aca0403162Wink Saville 303767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** 304767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Get an SMS-SUBMIT PDU for a destination address and a message 305767a662ecde33c3979bf02b793d392aca0403162Wink Saville * 306767a662ecde33c3979bf02b793d392aca0403162Wink Saville * @param scAddress Service Centre address. Null means use default. 307767a662ecde33c3979bf02b793d392aca0403162Wink Saville * @return a <code>SubmitPdu</code> containing the encoded SC 308767a662ecde33c3979bf02b793d392aca0403162Wink Saville * address, if applicable, and the encoded message. 309767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Returns null on encode error. 310767a662ecde33c3979bf02b793d392aca0403162Wink Saville */ 311767a662ecde33c3979bf02b793d392aca0403162Wink Saville public static SubmitPdu getSubmitPdu(String scAddress, 312767a662ecde33c3979bf02b793d392aca0403162Wink Saville String destinationAddress, String message, 313767a662ecde33c3979bf02b793d392aca0403162Wink Saville boolean statusReportRequested) { 314767a662ecde33c3979bf02b793d392aca0403162Wink Saville 315767a662ecde33c3979bf02b793d392aca0403162Wink Saville return getSubmitPdu(scAddress, destinationAddress, message, statusReportRequested, null); 316767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 317767a662ecde33c3979bf02b793d392aca0403162Wink Saville 318767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** 319767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Get an SMS-SUBMIT PDU for a data message to a destination address & port 320767a662ecde33c3979bf02b793d392aca0403162Wink Saville * 321767a662ecde33c3979bf02b793d392aca0403162Wink Saville * @param scAddress Service Centre address. null == use default 322767a662ecde33c3979bf02b793d392aca0403162Wink Saville * @param destinationAddress the address of the destination for the message 323767a662ecde33c3979bf02b793d392aca0403162Wink Saville * @param destinationPort the port to deliver the message to at the 324767a662ecde33c3979bf02b793d392aca0403162Wink Saville * destination 325767a662ecde33c3979bf02b793d392aca0403162Wink Saville * @param data the dat for the message 326767a662ecde33c3979bf02b793d392aca0403162Wink Saville * @return a <code>SubmitPdu</code> containing the encoded SC 327767a662ecde33c3979bf02b793d392aca0403162Wink Saville * address, if applicable, and the encoded message. 328767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Returns null on encode error. 329767a662ecde33c3979bf02b793d392aca0403162Wink Saville */ 330767a662ecde33c3979bf02b793d392aca0403162Wink Saville public static SubmitPdu getSubmitPdu(String scAddress, 331767a662ecde33c3979bf02b793d392aca0403162Wink Saville String destinationAddress, short destinationPort, byte[] data, 332767a662ecde33c3979bf02b793d392aca0403162Wink Saville boolean statusReportRequested) { 333767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (data.length > (MAX_USER_DATA_BYTES - 7 /* UDH size */)) { 334767a662ecde33c3979bf02b793d392aca0403162Wink Saville Log.e(LOG_TAG, "SMS data message may only contain " 335767a662ecde33c3979bf02b793d392aca0403162Wink Saville + (MAX_USER_DATA_BYTES - 7) + " bytes"); 336767a662ecde33c3979bf02b793d392aca0403162Wink Saville return null; 337767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 338767a662ecde33c3979bf02b793d392aca0403162Wink Saville 339767a662ecde33c3979bf02b793d392aca0403162Wink Saville SubmitPdu ret = new SubmitPdu(); 340767a662ecde33c3979bf02b793d392aca0403162Wink Saville ByteArrayOutputStream bo = getSubmitPduHead( 341767a662ecde33c3979bf02b793d392aca0403162Wink Saville scAddress, destinationAddress, (byte) 0x41, // MTI = SMS-SUBMIT, 342767a662ecde33c3979bf02b793d392aca0403162Wink Saville // TP-UDHI = true 343767a662ecde33c3979bf02b793d392aca0403162Wink Saville statusReportRequested, ret); 344767a662ecde33c3979bf02b793d392aca0403162Wink Saville 345767a662ecde33c3979bf02b793d392aca0403162Wink Saville // TP-Data-Coding-Scheme 346767a662ecde33c3979bf02b793d392aca0403162Wink Saville // No class, 8 bit data 347767a662ecde33c3979bf02b793d392aca0403162Wink Saville bo.write(0x04); 348767a662ecde33c3979bf02b793d392aca0403162Wink Saville 349767a662ecde33c3979bf02b793d392aca0403162Wink Saville // (no TP-Validity-Period) 350767a662ecde33c3979bf02b793d392aca0403162Wink Saville 351767a662ecde33c3979bf02b793d392aca0403162Wink Saville // User data size 352767a662ecde33c3979bf02b793d392aca0403162Wink Saville bo.write(data.length + 7); 353767a662ecde33c3979bf02b793d392aca0403162Wink Saville 354767a662ecde33c3979bf02b793d392aca0403162Wink Saville // User data header size 355767a662ecde33c3979bf02b793d392aca0403162Wink Saville bo.write(0x06); // header is 6 octets 356767a662ecde33c3979bf02b793d392aca0403162Wink Saville 357767a662ecde33c3979bf02b793d392aca0403162Wink Saville // User data header, indicating the destination port 358767a662ecde33c3979bf02b793d392aca0403162Wink Saville bo.write(SmsHeader.APPLICATION_PORT_ADDRESSING_16_BIT); // port 359767a662ecde33c3979bf02b793d392aca0403162Wink Saville // addressing 360767a662ecde33c3979bf02b793d392aca0403162Wink Saville // header 361767a662ecde33c3979bf02b793d392aca0403162Wink Saville bo.write(0x04); // each port is 2 octets 362767a662ecde33c3979bf02b793d392aca0403162Wink Saville bo.write((destinationPort >> 8) & 0xFF); // MSB of destination port 363767a662ecde33c3979bf02b793d392aca0403162Wink Saville bo.write(destinationPort & 0xFF); // LSB of destination port 364767a662ecde33c3979bf02b793d392aca0403162Wink Saville bo.write(0x00); // MSB of originating port 365767a662ecde33c3979bf02b793d392aca0403162Wink Saville bo.write(0x00); // LSB of originating port 366767a662ecde33c3979bf02b793d392aca0403162Wink Saville 367767a662ecde33c3979bf02b793d392aca0403162Wink Saville // User data 368767a662ecde33c3979bf02b793d392aca0403162Wink Saville bo.write(data, 0, data.length); 369767a662ecde33c3979bf02b793d392aca0403162Wink Saville 370767a662ecde33c3979bf02b793d392aca0403162Wink Saville ret.encodedMessage = bo.toByteArray(); 371767a662ecde33c3979bf02b793d392aca0403162Wink Saville return ret; 372767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 373767a662ecde33c3979bf02b793d392aca0403162Wink Saville 374767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** 375767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Create the beginning of a SUBMIT PDU. This is the part of the 376767a662ecde33c3979bf02b793d392aca0403162Wink Saville * SUBMIT PDU that is common to the two versions of {@link #getSubmitPdu}, 377767a662ecde33c3979bf02b793d392aca0403162Wink Saville * one of which takes a byte array and the other of which takes a 378767a662ecde33c3979bf02b793d392aca0403162Wink Saville * <code>String</code>. 379767a662ecde33c3979bf02b793d392aca0403162Wink Saville * 380767a662ecde33c3979bf02b793d392aca0403162Wink Saville * @param scAddress Service Centre address. null == use default 381767a662ecde33c3979bf02b793d392aca0403162Wink Saville * @param destinationAddress the address of the destination for the message 382767a662ecde33c3979bf02b793d392aca0403162Wink Saville * @param mtiByte 383767a662ecde33c3979bf02b793d392aca0403162Wink Saville * @param ret <code>SubmitPdu</code> containing the encoded SC 384767a662ecde33c3979bf02b793d392aca0403162Wink Saville * address, if applicable, and the encoded message 385767a662ecde33c3979bf02b793d392aca0403162Wink Saville */ 386767a662ecde33c3979bf02b793d392aca0403162Wink Saville private static ByteArrayOutputStream getSubmitPduHead( 387767a662ecde33c3979bf02b793d392aca0403162Wink Saville String scAddress, String destinationAddress, byte mtiByte, 388767a662ecde33c3979bf02b793d392aca0403162Wink Saville boolean statusReportRequested, SubmitPdu ret) { 389767a662ecde33c3979bf02b793d392aca0403162Wink Saville ByteArrayOutputStream bo = new ByteArrayOutputStream( 390767a662ecde33c3979bf02b793d392aca0403162Wink Saville MAX_USER_DATA_BYTES + 40); 391767a662ecde33c3979bf02b793d392aca0403162Wink Saville 392767a662ecde33c3979bf02b793d392aca0403162Wink Saville // SMSC address with length octet, or 0 393767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (scAddress == null) { 394767a662ecde33c3979bf02b793d392aca0403162Wink Saville ret.encodedScAddress = null; 395767a662ecde33c3979bf02b793d392aca0403162Wink Saville } else { 396767a662ecde33c3979bf02b793d392aca0403162Wink Saville ret.encodedScAddress = PhoneNumberUtils.networkPortionToCalledPartyBCDWithLength( 397767a662ecde33c3979bf02b793d392aca0403162Wink Saville scAddress); 398767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 399767a662ecde33c3979bf02b793d392aca0403162Wink Saville 400767a662ecde33c3979bf02b793d392aca0403162Wink Saville // TP-Message-Type-Indicator (and friends) 401767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (statusReportRequested) { 402767a662ecde33c3979bf02b793d392aca0403162Wink Saville // Set TP-Status-Report-Request bit. 403767a662ecde33c3979bf02b793d392aca0403162Wink Saville mtiByte |= 0x20; 404767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (Config.LOGD) Log.d(LOG_TAG, "SMS status report requested"); 405767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 406767a662ecde33c3979bf02b793d392aca0403162Wink Saville bo.write(mtiByte); 407767a662ecde33c3979bf02b793d392aca0403162Wink Saville 408767a662ecde33c3979bf02b793d392aca0403162Wink Saville // space for TP-Message-Reference 409767a662ecde33c3979bf02b793d392aca0403162Wink Saville bo.write(0); 410767a662ecde33c3979bf02b793d392aca0403162Wink Saville 411767a662ecde33c3979bf02b793d392aca0403162Wink Saville byte[] daBytes; 412767a662ecde33c3979bf02b793d392aca0403162Wink Saville 413767a662ecde33c3979bf02b793d392aca0403162Wink Saville daBytes = PhoneNumberUtils.networkPortionToCalledPartyBCD(destinationAddress); 414767a662ecde33c3979bf02b793d392aca0403162Wink Saville 415767a662ecde33c3979bf02b793d392aca0403162Wink Saville // destination address length in BCD digits, ignoring TON byte and pad 416767a662ecde33c3979bf02b793d392aca0403162Wink Saville // TODO Should be better. 417767a662ecde33c3979bf02b793d392aca0403162Wink Saville bo.write((daBytes.length - 1) * 2 418767a662ecde33c3979bf02b793d392aca0403162Wink Saville - ((daBytes[daBytes.length - 1] & 0xf0) == 0xf0 ? 1 : 0)); 419767a662ecde33c3979bf02b793d392aca0403162Wink Saville 420767a662ecde33c3979bf02b793d392aca0403162Wink Saville // destination address 421767a662ecde33c3979bf02b793d392aca0403162Wink Saville bo.write(daBytes, 0, daBytes.length); 422767a662ecde33c3979bf02b793d392aca0403162Wink Saville 423767a662ecde33c3979bf02b793d392aca0403162Wink Saville // TP-Protocol-Identifier 424767a662ecde33c3979bf02b793d392aca0403162Wink Saville bo.write(0); 425767a662ecde33c3979bf02b793d392aca0403162Wink Saville return bo; 426767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 427767a662ecde33c3979bf02b793d392aca0403162Wink Saville 428767a662ecde33c3979bf02b793d392aca0403162Wink Saville static class PduParser { 429767a662ecde33c3979bf02b793d392aca0403162Wink Saville byte pdu[]; 430767a662ecde33c3979bf02b793d392aca0403162Wink Saville int cur; 431767a662ecde33c3979bf02b793d392aca0403162Wink Saville SmsHeader userDataHeader; 432767a662ecde33c3979bf02b793d392aca0403162Wink Saville byte[] userData; 433767a662ecde33c3979bf02b793d392aca0403162Wink Saville int mUserDataSeptetPadding; 434767a662ecde33c3979bf02b793d392aca0403162Wink Saville int mUserDataSize; 435767a662ecde33c3979bf02b793d392aca0403162Wink Saville 436767a662ecde33c3979bf02b793d392aca0403162Wink Saville PduParser(String s) { 437767a662ecde33c3979bf02b793d392aca0403162Wink Saville this(IccUtils.hexStringToBytes(s)); 438767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 439767a662ecde33c3979bf02b793d392aca0403162Wink Saville 440767a662ecde33c3979bf02b793d392aca0403162Wink Saville PduParser(byte[] pdu) { 441767a662ecde33c3979bf02b793d392aca0403162Wink Saville this.pdu = pdu; 442767a662ecde33c3979bf02b793d392aca0403162Wink Saville cur = 0; 443767a662ecde33c3979bf02b793d392aca0403162Wink Saville mUserDataSeptetPadding = 0; 444767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 445767a662ecde33c3979bf02b793d392aca0403162Wink Saville 446767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** 447767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Parse and return the SC address prepended to SMS messages coming via 448767a662ecde33c3979bf02b793d392aca0403162Wink Saville * the TS 27.005 / AT interface. Returns null on invalid address 449767a662ecde33c3979bf02b793d392aca0403162Wink Saville */ 450767a662ecde33c3979bf02b793d392aca0403162Wink Saville String getSCAddress() { 451767a662ecde33c3979bf02b793d392aca0403162Wink Saville int len; 452767a662ecde33c3979bf02b793d392aca0403162Wink Saville String ret; 453767a662ecde33c3979bf02b793d392aca0403162Wink Saville 454767a662ecde33c3979bf02b793d392aca0403162Wink Saville // length of SC Address 455767a662ecde33c3979bf02b793d392aca0403162Wink Saville len = getByte(); 456767a662ecde33c3979bf02b793d392aca0403162Wink Saville 457767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (len == 0) { 458767a662ecde33c3979bf02b793d392aca0403162Wink Saville // no SC address 459767a662ecde33c3979bf02b793d392aca0403162Wink Saville ret = null; 460767a662ecde33c3979bf02b793d392aca0403162Wink Saville } else { 461767a662ecde33c3979bf02b793d392aca0403162Wink Saville // SC address 462767a662ecde33c3979bf02b793d392aca0403162Wink Saville try { 463767a662ecde33c3979bf02b793d392aca0403162Wink Saville ret = PhoneNumberUtils 464767a662ecde33c3979bf02b793d392aca0403162Wink Saville .calledPartyBCDToString(pdu, cur, len); 465767a662ecde33c3979bf02b793d392aca0403162Wink Saville } catch (RuntimeException tr) { 466767a662ecde33c3979bf02b793d392aca0403162Wink Saville Log.d(LOG_TAG, "invalid SC address: ", tr); 467767a662ecde33c3979bf02b793d392aca0403162Wink Saville ret = null; 468767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 469767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 470767a662ecde33c3979bf02b793d392aca0403162Wink Saville 471767a662ecde33c3979bf02b793d392aca0403162Wink Saville cur += len; 472767a662ecde33c3979bf02b793d392aca0403162Wink Saville 473767a662ecde33c3979bf02b793d392aca0403162Wink Saville return ret; 474767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 475767a662ecde33c3979bf02b793d392aca0403162Wink Saville 476767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** 477767a662ecde33c3979bf02b793d392aca0403162Wink Saville * returns non-sign-extended byte value 478767a662ecde33c3979bf02b793d392aca0403162Wink Saville */ 479767a662ecde33c3979bf02b793d392aca0403162Wink Saville int getByte() { 480767a662ecde33c3979bf02b793d392aca0403162Wink Saville return pdu[cur++] & 0xff; 481767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 482767a662ecde33c3979bf02b793d392aca0403162Wink Saville 483767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** 484767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Any address except the SC address (eg, originating address) See TS 485767a662ecde33c3979bf02b793d392aca0403162Wink Saville * 23.040 9.1.2.5 486767a662ecde33c3979bf02b793d392aca0403162Wink Saville */ 487767a662ecde33c3979bf02b793d392aca0403162Wink Saville GsmSmsAddress getAddress() { 488767a662ecde33c3979bf02b793d392aca0403162Wink Saville GsmSmsAddress ret; 489767a662ecde33c3979bf02b793d392aca0403162Wink Saville 490767a662ecde33c3979bf02b793d392aca0403162Wink Saville // "The Address-Length field is an integer representation of 491767a662ecde33c3979bf02b793d392aca0403162Wink Saville // the number field, i.e. excludes any semi octet containing only 492767a662ecde33c3979bf02b793d392aca0403162Wink Saville // fill bits." 493767a662ecde33c3979bf02b793d392aca0403162Wink Saville // The TOA field is not included as part of this 494767a662ecde33c3979bf02b793d392aca0403162Wink Saville int addressLength = pdu[cur] & 0xff; 495767a662ecde33c3979bf02b793d392aca0403162Wink Saville int lengthBytes = 2 + (addressLength + 1) / 2; 496767a662ecde33c3979bf02b793d392aca0403162Wink Saville 497767a662ecde33c3979bf02b793d392aca0403162Wink Saville ret = new GsmSmsAddress(pdu, cur, lengthBytes); 498767a662ecde33c3979bf02b793d392aca0403162Wink Saville 499767a662ecde33c3979bf02b793d392aca0403162Wink Saville cur += lengthBytes; 500767a662ecde33c3979bf02b793d392aca0403162Wink Saville 501767a662ecde33c3979bf02b793d392aca0403162Wink Saville return ret; 502767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 503767a662ecde33c3979bf02b793d392aca0403162Wink Saville 504767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** 505767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Parses an SC timestamp and returns a currentTimeMillis()-style 506767a662ecde33c3979bf02b793d392aca0403162Wink Saville * timestamp 507767a662ecde33c3979bf02b793d392aca0403162Wink Saville */ 508767a662ecde33c3979bf02b793d392aca0403162Wink Saville 509767a662ecde33c3979bf02b793d392aca0403162Wink Saville long getSCTimestampMillis() { 510767a662ecde33c3979bf02b793d392aca0403162Wink Saville // TP-Service-Centre-Time-Stamp 511767a662ecde33c3979bf02b793d392aca0403162Wink Saville int year = IccUtils.bcdByteToInt(pdu[cur++]); 512767a662ecde33c3979bf02b793d392aca0403162Wink Saville int month = IccUtils.bcdByteToInt(pdu[cur++]); 513767a662ecde33c3979bf02b793d392aca0403162Wink Saville int day = IccUtils.bcdByteToInt(pdu[cur++]); 514767a662ecde33c3979bf02b793d392aca0403162Wink Saville int hour = IccUtils.bcdByteToInt(pdu[cur++]); 515767a662ecde33c3979bf02b793d392aca0403162Wink Saville int minute = IccUtils.bcdByteToInt(pdu[cur++]); 516767a662ecde33c3979bf02b793d392aca0403162Wink Saville int second = IccUtils.bcdByteToInt(pdu[cur++]); 517767a662ecde33c3979bf02b793d392aca0403162Wink Saville 518767a662ecde33c3979bf02b793d392aca0403162Wink Saville // For the timezone, the most significant bit of the 519767a662ecde33c3979bf02b793d392aca0403162Wink Saville // least signficant nibble is the sign byte 520767a662ecde33c3979bf02b793d392aca0403162Wink Saville // (meaning the max range of this field is 79 quarter-hours, 521767a662ecde33c3979bf02b793d392aca0403162Wink Saville // which is more than enough) 522767a662ecde33c3979bf02b793d392aca0403162Wink Saville 523767a662ecde33c3979bf02b793d392aca0403162Wink Saville byte tzByte = pdu[cur++]; 524767a662ecde33c3979bf02b793d392aca0403162Wink Saville 525767a662ecde33c3979bf02b793d392aca0403162Wink Saville // Mask out sign bit. 526767a662ecde33c3979bf02b793d392aca0403162Wink Saville int timezoneOffset = IccUtils 527767a662ecde33c3979bf02b793d392aca0403162Wink Saville .bcdByteToInt((byte) (tzByte & (~0x08))); 528767a662ecde33c3979bf02b793d392aca0403162Wink Saville 529767a662ecde33c3979bf02b793d392aca0403162Wink Saville timezoneOffset = ((tzByte & 0x08) == 0) ? timezoneOffset 530767a662ecde33c3979bf02b793d392aca0403162Wink Saville : -timezoneOffset; 531767a662ecde33c3979bf02b793d392aca0403162Wink Saville 532767a662ecde33c3979bf02b793d392aca0403162Wink Saville Time time = new Time(Time.TIMEZONE_UTC); 533767a662ecde33c3979bf02b793d392aca0403162Wink Saville 534767a662ecde33c3979bf02b793d392aca0403162Wink Saville // It's 2006. Should I really support years < 2000? 535767a662ecde33c3979bf02b793d392aca0403162Wink Saville time.year = year >= 90 ? year + 1900 : year + 2000; 536767a662ecde33c3979bf02b793d392aca0403162Wink Saville time.month = month - 1; 537767a662ecde33c3979bf02b793d392aca0403162Wink Saville time.monthDay = day; 538767a662ecde33c3979bf02b793d392aca0403162Wink Saville time.hour = hour; 539767a662ecde33c3979bf02b793d392aca0403162Wink Saville time.minute = minute; 540767a662ecde33c3979bf02b793d392aca0403162Wink Saville time.second = second; 541767a662ecde33c3979bf02b793d392aca0403162Wink Saville 542767a662ecde33c3979bf02b793d392aca0403162Wink Saville // Timezone offset is in quarter hours. 543767a662ecde33c3979bf02b793d392aca0403162Wink Saville return time.toMillis(true) - (timezoneOffset * 15 * 60 * 1000); 544767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 545767a662ecde33c3979bf02b793d392aca0403162Wink Saville 546767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** 547767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Pulls the user data out of the PDU, and separates the payload from 548767a662ecde33c3979bf02b793d392aca0403162Wink Saville * the header if there is one. 549767a662ecde33c3979bf02b793d392aca0403162Wink Saville * 550767a662ecde33c3979bf02b793d392aca0403162Wink Saville * @param hasUserDataHeader true if there is a user data header 551767a662ecde33c3979bf02b793d392aca0403162Wink Saville * @param dataInSeptets true if the data payload is in septets instead 552767a662ecde33c3979bf02b793d392aca0403162Wink Saville * of octets 553767a662ecde33c3979bf02b793d392aca0403162Wink Saville * @return the number of septets or octets in the user data payload 554767a662ecde33c3979bf02b793d392aca0403162Wink Saville */ 555767a662ecde33c3979bf02b793d392aca0403162Wink Saville int constructUserData(boolean hasUserDataHeader, boolean dataInSeptets) { 556767a662ecde33c3979bf02b793d392aca0403162Wink Saville int offset = cur; 557767a662ecde33c3979bf02b793d392aca0403162Wink Saville int userDataLength = pdu[offset++] & 0xff; 558767a662ecde33c3979bf02b793d392aca0403162Wink Saville int headerSeptets = 0; 559767a662ecde33c3979bf02b793d392aca0403162Wink Saville 560767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (hasUserDataHeader) { 561767a662ecde33c3979bf02b793d392aca0403162Wink Saville int userDataHeaderLength = pdu[offset++] & 0xff; 562767a662ecde33c3979bf02b793d392aca0403162Wink Saville 563767a662ecde33c3979bf02b793d392aca0403162Wink Saville byte[] udh = new byte[userDataHeaderLength]; 564767a662ecde33c3979bf02b793d392aca0403162Wink Saville System.arraycopy(pdu, offset, udh, 0, userDataHeaderLength); 565767a662ecde33c3979bf02b793d392aca0403162Wink Saville userDataHeader = SmsHeader.parse(udh); 566767a662ecde33c3979bf02b793d392aca0403162Wink Saville offset += userDataHeaderLength; 567767a662ecde33c3979bf02b793d392aca0403162Wink Saville 568767a662ecde33c3979bf02b793d392aca0403162Wink Saville int headerBits = (userDataHeaderLength + 1) * 8; 569767a662ecde33c3979bf02b793d392aca0403162Wink Saville headerSeptets = headerBits / 7; 570767a662ecde33c3979bf02b793d392aca0403162Wink Saville headerSeptets += (headerBits % 7) > 0 ? 1 : 0; 571767a662ecde33c3979bf02b793d392aca0403162Wink Saville mUserDataSeptetPadding = (headerSeptets * 7) - headerBits; 572767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 573767a662ecde33c3979bf02b793d392aca0403162Wink Saville 574767a662ecde33c3979bf02b793d392aca0403162Wink Saville /* 575767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Here we just create the user data length to be the remainder of 576767a662ecde33c3979bf02b793d392aca0403162Wink Saville * the pdu minus the user data hearder. This is because the count 577767a662ecde33c3979bf02b793d392aca0403162Wink Saville * could mean the number of uncompressed sepets if the userdata is 578767a662ecde33c3979bf02b793d392aca0403162Wink Saville * encoded in 7-bit. 579767a662ecde33c3979bf02b793d392aca0403162Wink Saville */ 580767a662ecde33c3979bf02b793d392aca0403162Wink Saville userData = new byte[pdu.length - offset]; 581767a662ecde33c3979bf02b793d392aca0403162Wink Saville System.arraycopy(pdu, offset, userData, 0, userData.length); 582767a662ecde33c3979bf02b793d392aca0403162Wink Saville cur = offset; 583767a662ecde33c3979bf02b793d392aca0403162Wink Saville 584767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (dataInSeptets) { 585767a662ecde33c3979bf02b793d392aca0403162Wink Saville // Return the number of septets 586767a662ecde33c3979bf02b793d392aca0403162Wink Saville return userDataLength - headerSeptets; 587767a662ecde33c3979bf02b793d392aca0403162Wink Saville } else { 588767a662ecde33c3979bf02b793d392aca0403162Wink Saville // Return the number of octets 589767a662ecde33c3979bf02b793d392aca0403162Wink Saville return userData.length; 590767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 591767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 592767a662ecde33c3979bf02b793d392aca0403162Wink Saville 593767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** 594767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Returns the user data payload, not including the headers 595767a662ecde33c3979bf02b793d392aca0403162Wink Saville * 596767a662ecde33c3979bf02b793d392aca0403162Wink Saville * @return the user data payload, not including the headers 597767a662ecde33c3979bf02b793d392aca0403162Wink Saville */ 598767a662ecde33c3979bf02b793d392aca0403162Wink Saville byte[] getUserData() { 599767a662ecde33c3979bf02b793d392aca0403162Wink Saville return userData; 600767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 601767a662ecde33c3979bf02b793d392aca0403162Wink Saville 602767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** 603767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Returns the number of padding bits at the begining of the user data 604767a662ecde33c3979bf02b793d392aca0403162Wink Saville * array before the start of the septets. 605767a662ecde33c3979bf02b793d392aca0403162Wink Saville * 606767a662ecde33c3979bf02b793d392aca0403162Wink Saville * @return the number of padding bits at the begining of the user data 607767a662ecde33c3979bf02b793d392aca0403162Wink Saville * array before the start of the septets 608767a662ecde33c3979bf02b793d392aca0403162Wink Saville */ 609767a662ecde33c3979bf02b793d392aca0403162Wink Saville int getUserDataSeptetPadding() { 610767a662ecde33c3979bf02b793d392aca0403162Wink Saville return mUserDataSeptetPadding; 611767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 612767a662ecde33c3979bf02b793d392aca0403162Wink Saville 613767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** 614767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Returns an object representing the user data headers 615767a662ecde33c3979bf02b793d392aca0403162Wink Saville * 616767a662ecde33c3979bf02b793d392aca0403162Wink Saville * @return an object representing the user data headers 617767a662ecde33c3979bf02b793d392aca0403162Wink Saville * 618767a662ecde33c3979bf02b793d392aca0403162Wink Saville * {@hide} 619767a662ecde33c3979bf02b793d392aca0403162Wink Saville */ 620767a662ecde33c3979bf02b793d392aca0403162Wink Saville SmsHeader getUserDataHeader() { 621767a662ecde33c3979bf02b793d392aca0403162Wink Saville return userDataHeader; 622767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 623767a662ecde33c3979bf02b793d392aca0403162Wink Saville 624767a662ecde33c3979bf02b793d392aca0403162Wink Saville/* 625767a662ecde33c3979bf02b793d392aca0403162Wink Saville XXX Not sure what this one is supposed to be doing, and no one is using 626767a662ecde33c3979bf02b793d392aca0403162Wink Saville it. 627767a662ecde33c3979bf02b793d392aca0403162Wink Saville String getUserDataGSM8bit() { 628767a662ecde33c3979bf02b793d392aca0403162Wink Saville // System.out.println("remainder of pud:" + 629767a662ecde33c3979bf02b793d392aca0403162Wink Saville // HexDump.dumpHexString(pdu, cur, pdu.length - cur)); 630767a662ecde33c3979bf02b793d392aca0403162Wink Saville int count = pdu[cur++] & 0xff; 631767a662ecde33c3979bf02b793d392aca0403162Wink Saville int size = pdu[cur++]; 632767a662ecde33c3979bf02b793d392aca0403162Wink Saville 633767a662ecde33c3979bf02b793d392aca0403162Wink Saville // skip over header for now 634767a662ecde33c3979bf02b793d392aca0403162Wink Saville cur += size; 635767a662ecde33c3979bf02b793d392aca0403162Wink Saville 636767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (pdu[cur - 1] == 0x01) { 637767a662ecde33c3979bf02b793d392aca0403162Wink Saville int tid = pdu[cur++] & 0xff; 638767a662ecde33c3979bf02b793d392aca0403162Wink Saville int type = pdu[cur++] & 0xff; 639767a662ecde33c3979bf02b793d392aca0403162Wink Saville 640767a662ecde33c3979bf02b793d392aca0403162Wink Saville size = pdu[cur++] & 0xff; 641767a662ecde33c3979bf02b793d392aca0403162Wink Saville 642767a662ecde33c3979bf02b793d392aca0403162Wink Saville int i = cur; 643767a662ecde33c3979bf02b793d392aca0403162Wink Saville 644767a662ecde33c3979bf02b793d392aca0403162Wink Saville while (pdu[i++] != '\0') { 645767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 646767a662ecde33c3979bf02b793d392aca0403162Wink Saville 647767a662ecde33c3979bf02b793d392aca0403162Wink Saville int length = i - cur; 648767a662ecde33c3979bf02b793d392aca0403162Wink Saville String mimeType = new String(pdu, cur, length); 649767a662ecde33c3979bf02b793d392aca0403162Wink Saville 650767a662ecde33c3979bf02b793d392aca0403162Wink Saville cur += length; 651767a662ecde33c3979bf02b793d392aca0403162Wink Saville 652767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (false) { 653767a662ecde33c3979bf02b793d392aca0403162Wink Saville System.out.println("tid = 0x" + HexDump.toHexString(tid)); 654767a662ecde33c3979bf02b793d392aca0403162Wink Saville System.out.println("type = 0x" + HexDump.toHexString(type)); 655767a662ecde33c3979bf02b793d392aca0403162Wink Saville System.out.println("header size = " + size); 656767a662ecde33c3979bf02b793d392aca0403162Wink Saville System.out.println("mimeType = " + mimeType); 657767a662ecde33c3979bf02b793d392aca0403162Wink Saville System.out.println("remainder of header:" + 658767a662ecde33c3979bf02b793d392aca0403162Wink Saville HexDump.dumpHexString(pdu, cur, (size - mimeType.length()))); 659767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 660767a662ecde33c3979bf02b793d392aca0403162Wink Saville 661767a662ecde33c3979bf02b793d392aca0403162Wink Saville cur += size - mimeType.length(); 662767a662ecde33c3979bf02b793d392aca0403162Wink Saville 663767a662ecde33c3979bf02b793d392aca0403162Wink Saville // System.out.println("data count = " + count + " cur = " + cur 664767a662ecde33c3979bf02b793d392aca0403162Wink Saville // + " :" + HexDump.dumpHexString(pdu, cur, pdu.length - cur)); 665767a662ecde33c3979bf02b793d392aca0403162Wink Saville 666767a662ecde33c3979bf02b793d392aca0403162Wink Saville MMSMessage msg = MMSMessage.parseEncoding(mContext, pdu, cur, 667767a662ecde33c3979bf02b793d392aca0403162Wink Saville pdu.length - cur); 668767a662ecde33c3979bf02b793d392aca0403162Wink Saville } else { 669767a662ecde33c3979bf02b793d392aca0403162Wink Saville System.out.println(new String(pdu, cur, pdu.length - cur - 1)); 670767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 671767a662ecde33c3979bf02b793d392aca0403162Wink Saville 672767a662ecde33c3979bf02b793d392aca0403162Wink Saville return IccUtils.bytesToHexString(pdu); 673767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 674767a662ecde33c3979bf02b793d392aca0403162Wink Saville*/ 675767a662ecde33c3979bf02b793d392aca0403162Wink Saville 676767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** 677767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Interprets the user data payload as pack GSM 7bit characters, and 678767a662ecde33c3979bf02b793d392aca0403162Wink Saville * decodes them into a String. 679767a662ecde33c3979bf02b793d392aca0403162Wink Saville * 680767a662ecde33c3979bf02b793d392aca0403162Wink Saville * @param septetCount the number of septets in the user data payload 681767a662ecde33c3979bf02b793d392aca0403162Wink Saville * @return a String with the decoded characters 682767a662ecde33c3979bf02b793d392aca0403162Wink Saville */ 683767a662ecde33c3979bf02b793d392aca0403162Wink Saville String getUserDataGSM7Bit(int septetCount) { 684767a662ecde33c3979bf02b793d392aca0403162Wink Saville String ret; 685767a662ecde33c3979bf02b793d392aca0403162Wink Saville 686767a662ecde33c3979bf02b793d392aca0403162Wink Saville ret = GsmAlphabet.gsm7BitPackedToString(pdu, cur, septetCount, 687767a662ecde33c3979bf02b793d392aca0403162Wink Saville mUserDataSeptetPadding); 688767a662ecde33c3979bf02b793d392aca0403162Wink Saville 689767a662ecde33c3979bf02b793d392aca0403162Wink Saville cur += (septetCount * 7) / 8; 690767a662ecde33c3979bf02b793d392aca0403162Wink Saville 691767a662ecde33c3979bf02b793d392aca0403162Wink Saville return ret; 692767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 693767a662ecde33c3979bf02b793d392aca0403162Wink Saville 694767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** 695767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Interprets the user data payload as UCS2 characters, and 696767a662ecde33c3979bf02b793d392aca0403162Wink Saville * decodes them into a String. 697767a662ecde33c3979bf02b793d392aca0403162Wink Saville * 698767a662ecde33c3979bf02b793d392aca0403162Wink Saville * @param byteCount the number of bytes in the user data payload 699767a662ecde33c3979bf02b793d392aca0403162Wink Saville * @return a String with the decoded characters 700767a662ecde33c3979bf02b793d392aca0403162Wink Saville */ 701767a662ecde33c3979bf02b793d392aca0403162Wink Saville String getUserDataUCS2(int byteCount) { 702767a662ecde33c3979bf02b793d392aca0403162Wink Saville String ret; 703767a662ecde33c3979bf02b793d392aca0403162Wink Saville 704767a662ecde33c3979bf02b793d392aca0403162Wink Saville try { 705767a662ecde33c3979bf02b793d392aca0403162Wink Saville ret = new String(pdu, cur, byteCount, "utf-16"); 706767a662ecde33c3979bf02b793d392aca0403162Wink Saville } catch (UnsupportedEncodingException ex) { 707767a662ecde33c3979bf02b793d392aca0403162Wink Saville ret = ""; 708767a662ecde33c3979bf02b793d392aca0403162Wink Saville Log.e(LOG_TAG, "implausible UnsupportedEncodingException", ex); 709767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 710767a662ecde33c3979bf02b793d392aca0403162Wink Saville 711767a662ecde33c3979bf02b793d392aca0403162Wink Saville cur += byteCount; 712767a662ecde33c3979bf02b793d392aca0403162Wink Saville return ret; 713767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 714767a662ecde33c3979bf02b793d392aca0403162Wink Saville 715767a662ecde33c3979bf02b793d392aca0403162Wink Saville boolean moreDataPresent() { 716767a662ecde33c3979bf02b793d392aca0403162Wink Saville return (pdu.length > cur); 717767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 718767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 719767a662ecde33c3979bf02b793d392aca0403162Wink Saville 720767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** {@inheritDoc} */ 721767a662ecde33c3979bf02b793d392aca0403162Wink Saville public int getProtocolIdentifier() { 722767a662ecde33c3979bf02b793d392aca0403162Wink Saville return protocolIdentifier; 723767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 724767a662ecde33c3979bf02b793d392aca0403162Wink Saville 725767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** {@inheritDoc} */ 726767a662ecde33c3979bf02b793d392aca0403162Wink Saville public boolean isReplace() { 727767a662ecde33c3979bf02b793d392aca0403162Wink Saville return (protocolIdentifier & 0xc0) == 0x40 728767a662ecde33c3979bf02b793d392aca0403162Wink Saville && (protocolIdentifier & 0x3f) > 0 729767a662ecde33c3979bf02b793d392aca0403162Wink Saville && (protocolIdentifier & 0x3f) < 8; 730767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 731767a662ecde33c3979bf02b793d392aca0403162Wink Saville 732767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** {@inheritDoc} */ 733767a662ecde33c3979bf02b793d392aca0403162Wink Saville public boolean isCphsMwiMessage() { 734767a662ecde33c3979bf02b793d392aca0403162Wink Saville return ((GsmSmsAddress) originatingAddress).isCphsVoiceMessageClear() 735767a662ecde33c3979bf02b793d392aca0403162Wink Saville || ((GsmSmsAddress) originatingAddress).isCphsVoiceMessageSet(); 736767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 737767a662ecde33c3979bf02b793d392aca0403162Wink Saville 738767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** {@inheritDoc} */ 739767a662ecde33c3979bf02b793d392aca0403162Wink Saville public boolean isMWIClearMessage() { 740767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (isMwi && (mwiSense == false)) { 741767a662ecde33c3979bf02b793d392aca0403162Wink Saville return true; 742767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 743767a662ecde33c3979bf02b793d392aca0403162Wink Saville 744767a662ecde33c3979bf02b793d392aca0403162Wink Saville return originatingAddress != null 745767a662ecde33c3979bf02b793d392aca0403162Wink Saville && ((GsmSmsAddress) originatingAddress).isCphsVoiceMessageClear(); 746767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 747767a662ecde33c3979bf02b793d392aca0403162Wink Saville 748767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** {@inheritDoc} */ 749767a662ecde33c3979bf02b793d392aca0403162Wink Saville public boolean isMWISetMessage() { 750767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (isMwi && (mwiSense == true)) { 751767a662ecde33c3979bf02b793d392aca0403162Wink Saville return true; 752767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 753767a662ecde33c3979bf02b793d392aca0403162Wink Saville 754767a662ecde33c3979bf02b793d392aca0403162Wink Saville return originatingAddress != null 755767a662ecde33c3979bf02b793d392aca0403162Wink Saville && ((GsmSmsAddress) originatingAddress).isCphsVoiceMessageSet(); 756767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 757767a662ecde33c3979bf02b793d392aca0403162Wink Saville 758767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** {@inheritDoc} */ 759767a662ecde33c3979bf02b793d392aca0403162Wink Saville public boolean isMwiDontStore() { 760767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (isMwi && mwiDontStore) { 761767a662ecde33c3979bf02b793d392aca0403162Wink Saville return true; 762767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 763767a662ecde33c3979bf02b793d392aca0403162Wink Saville 764767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (isCphsMwiMessage()) { 765767a662ecde33c3979bf02b793d392aca0403162Wink Saville // See CPHS 4.2 Section B.4.2.1 766767a662ecde33c3979bf02b793d392aca0403162Wink Saville // If the user data is a single space char, do not store 767767a662ecde33c3979bf02b793d392aca0403162Wink Saville // the message. Otherwise, store and display as usual 768767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (" ".equals(getMessageBody())) { 769767a662ecde33c3979bf02b793d392aca0403162Wink Saville ; 770767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 771767a662ecde33c3979bf02b793d392aca0403162Wink Saville return true; 772767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 773767a662ecde33c3979bf02b793d392aca0403162Wink Saville 774767a662ecde33c3979bf02b793d392aca0403162Wink Saville return false; 775767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 776767a662ecde33c3979bf02b793d392aca0403162Wink Saville 777767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** {@inheritDoc} */ 778767a662ecde33c3979bf02b793d392aca0403162Wink Saville public int getStatus() { 779767a662ecde33c3979bf02b793d392aca0403162Wink Saville return status; 780767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 781767a662ecde33c3979bf02b793d392aca0403162Wink Saville 782767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** {@inheritDoc} */ 783767a662ecde33c3979bf02b793d392aca0403162Wink Saville public boolean isStatusReportMessage() { 784767a662ecde33c3979bf02b793d392aca0403162Wink Saville return isStatusReportMessage; 785767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 786767a662ecde33c3979bf02b793d392aca0403162Wink Saville 787767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** {@inheritDoc} */ 788767a662ecde33c3979bf02b793d392aca0403162Wink Saville public boolean isReplyPathPresent() { 789767a662ecde33c3979bf02b793d392aca0403162Wink Saville return replyPathPresent; 790767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 791767a662ecde33c3979bf02b793d392aca0403162Wink Saville 792767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** 793767a662ecde33c3979bf02b793d392aca0403162Wink Saville * TS 27.005 3.1, <pdu> definition "In the case of SMS: 3GPP TS 24.011 [6] 794767a662ecde33c3979bf02b793d392aca0403162Wink Saville * SC address followed by 3GPP TS 23.040 [3] TPDU in hexadecimal format: 795767a662ecde33c3979bf02b793d392aca0403162Wink Saville * ME/TA converts each octet of TP data unit into two IRA character long 796767a662ecde33c3979bf02b793d392aca0403162Wink Saville * hexad number (e.g. octet with integer value 42 is presented to TE as two 797767a662ecde33c3979bf02b793d392aca0403162Wink Saville * characters 2A (IRA 50 and 65))" ...in the case of cell broadcast, 798767a662ecde33c3979bf02b793d392aca0403162Wink Saville * something else... 799767a662ecde33c3979bf02b793d392aca0403162Wink Saville */ 800767a662ecde33c3979bf02b793d392aca0403162Wink Saville private void parsePdu(byte[] pdu) { 801767a662ecde33c3979bf02b793d392aca0403162Wink Saville mPdu = pdu; 802767a662ecde33c3979bf02b793d392aca0403162Wink Saville // Log.d(LOG_TAG, "raw sms mesage:"); 803767a662ecde33c3979bf02b793d392aca0403162Wink Saville // Log.d(LOG_TAG, s); 804767a662ecde33c3979bf02b793d392aca0403162Wink Saville 805767a662ecde33c3979bf02b793d392aca0403162Wink Saville PduParser p = new PduParser(pdu); 806767a662ecde33c3979bf02b793d392aca0403162Wink Saville 807767a662ecde33c3979bf02b793d392aca0403162Wink Saville scAddress = p.getSCAddress(); 808767a662ecde33c3979bf02b793d392aca0403162Wink Saville 809767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (scAddress != null) { 810767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (Config.LOGD) Log.d(LOG_TAG, "SMS SC address: " + scAddress); 811767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 812767a662ecde33c3979bf02b793d392aca0403162Wink Saville 813767a662ecde33c3979bf02b793d392aca0403162Wink Saville // TODO(mkf) support reply path, user data header indicator 814767a662ecde33c3979bf02b793d392aca0403162Wink Saville 815767a662ecde33c3979bf02b793d392aca0403162Wink Saville // TP-Message-Type-Indicator 816767a662ecde33c3979bf02b793d392aca0403162Wink Saville // 9.2.3 817767a662ecde33c3979bf02b793d392aca0403162Wink Saville int firstByte = p.getByte(); 818767a662ecde33c3979bf02b793d392aca0403162Wink Saville 819767a662ecde33c3979bf02b793d392aca0403162Wink Saville mti = firstByte & 0x3; 820767a662ecde33c3979bf02b793d392aca0403162Wink Saville switch (mti) { 821767a662ecde33c3979bf02b793d392aca0403162Wink Saville // TP-Message-Type-Indicator 822767a662ecde33c3979bf02b793d392aca0403162Wink Saville // 9.2.3 823767a662ecde33c3979bf02b793d392aca0403162Wink Saville case 0: 824767a662ecde33c3979bf02b793d392aca0403162Wink Saville parseSmsDeliver(p, firstByte); 825767a662ecde33c3979bf02b793d392aca0403162Wink Saville break; 826767a662ecde33c3979bf02b793d392aca0403162Wink Saville case 2: 827767a662ecde33c3979bf02b793d392aca0403162Wink Saville parseSmsStatusReport(p, firstByte); 828767a662ecde33c3979bf02b793d392aca0403162Wink Saville break; 829767a662ecde33c3979bf02b793d392aca0403162Wink Saville default: 830767a662ecde33c3979bf02b793d392aca0403162Wink Saville // TODO(mkf) the rest of these 831767a662ecde33c3979bf02b793d392aca0403162Wink Saville throw new RuntimeException("Unsupported message type"); 832767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 833767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 834767a662ecde33c3979bf02b793d392aca0403162Wink Saville 835767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** 836767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Parses a SMS-STATUS-REPORT message. 837767a662ecde33c3979bf02b793d392aca0403162Wink Saville * 838767a662ecde33c3979bf02b793d392aca0403162Wink Saville * @param p A PduParser, cued past the first byte. 839767a662ecde33c3979bf02b793d392aca0403162Wink Saville * @param firstByte The first byte of the PDU, which contains MTI, etc. 840767a662ecde33c3979bf02b793d392aca0403162Wink Saville */ 841767a662ecde33c3979bf02b793d392aca0403162Wink Saville private void parseSmsStatusReport(PduParser p, int firstByte) { 842767a662ecde33c3979bf02b793d392aca0403162Wink Saville isStatusReportMessage = true; 843767a662ecde33c3979bf02b793d392aca0403162Wink Saville 844767a662ecde33c3979bf02b793d392aca0403162Wink Saville // TP-Status-Report-Qualifier bit == 0 for SUBMIT 845767a662ecde33c3979bf02b793d392aca0403162Wink Saville forSubmit = (firstByte & 0x20) == 0x00; 846767a662ecde33c3979bf02b793d392aca0403162Wink Saville // TP-Message-Reference 847767a662ecde33c3979bf02b793d392aca0403162Wink Saville messageRef = p.getByte(); 848767a662ecde33c3979bf02b793d392aca0403162Wink Saville // TP-Recipient-Address 849767a662ecde33c3979bf02b793d392aca0403162Wink Saville recipientAddress = p.getAddress(); 850767a662ecde33c3979bf02b793d392aca0403162Wink Saville // TP-Service-Centre-Time-Stamp 851767a662ecde33c3979bf02b793d392aca0403162Wink Saville scTimeMillis = p.getSCTimestampMillis(); 852767a662ecde33c3979bf02b793d392aca0403162Wink Saville // TP-Discharge-Time 853767a662ecde33c3979bf02b793d392aca0403162Wink Saville dischargeTimeMillis = p.getSCTimestampMillis(); 854767a662ecde33c3979bf02b793d392aca0403162Wink Saville // TP-Status 855767a662ecde33c3979bf02b793d392aca0403162Wink Saville status = p.getByte(); 856767a662ecde33c3979bf02b793d392aca0403162Wink Saville 857767a662ecde33c3979bf02b793d392aca0403162Wink Saville // The following are optional fields that may or may not be present. 858767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (p.moreDataPresent()) { 859767a662ecde33c3979bf02b793d392aca0403162Wink Saville // TP-Parameter-Indicator 860767a662ecde33c3979bf02b793d392aca0403162Wink Saville int extraParams = p.getByte(); 861767a662ecde33c3979bf02b793d392aca0403162Wink Saville int moreExtraParams = extraParams; 862767a662ecde33c3979bf02b793d392aca0403162Wink Saville while ((moreExtraParams & 0x80) != 0) { 863767a662ecde33c3979bf02b793d392aca0403162Wink Saville // We only know how to parse a few extra parameters, all 864767a662ecde33c3979bf02b793d392aca0403162Wink Saville // indicated in the first TP-PI octet, so skip over any 865767a662ecde33c3979bf02b793d392aca0403162Wink Saville // additional TP-PI octets. 866767a662ecde33c3979bf02b793d392aca0403162Wink Saville moreExtraParams = p.getByte(); 867767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 868767a662ecde33c3979bf02b793d392aca0403162Wink Saville // TP-Protocol-Identifier 869767a662ecde33c3979bf02b793d392aca0403162Wink Saville if ((extraParams & 0x01) != 0) { 870767a662ecde33c3979bf02b793d392aca0403162Wink Saville protocolIdentifier = p.getByte(); 871767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 872767a662ecde33c3979bf02b793d392aca0403162Wink Saville // TP-Data-Coding-Scheme 873767a662ecde33c3979bf02b793d392aca0403162Wink Saville if ((extraParams & 0x02) != 0) { 874767a662ecde33c3979bf02b793d392aca0403162Wink Saville dataCodingScheme = p.getByte(); 875767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 876767a662ecde33c3979bf02b793d392aca0403162Wink Saville // TP-User-Data-Length (implies existence of TP-User-Data) 877767a662ecde33c3979bf02b793d392aca0403162Wink Saville if ((extraParams & 0x04) != 0) { 878767a662ecde33c3979bf02b793d392aca0403162Wink Saville boolean hasUserDataHeader = (firstByte & 0x40) == 0x40; 879767a662ecde33c3979bf02b793d392aca0403162Wink Saville parseUserData(p, hasUserDataHeader); 880767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 881767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 882767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 883767a662ecde33c3979bf02b793d392aca0403162Wink Saville 884767a662ecde33c3979bf02b793d392aca0403162Wink Saville private void parseSmsDeliver(PduParser p, int firstByte) { 885767a662ecde33c3979bf02b793d392aca0403162Wink Saville replyPathPresent = (firstByte & 0x80) == 0x80; 886767a662ecde33c3979bf02b793d392aca0403162Wink Saville 887767a662ecde33c3979bf02b793d392aca0403162Wink Saville originatingAddress = p.getAddress(); 888767a662ecde33c3979bf02b793d392aca0403162Wink Saville 889767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (originatingAddress != null) { 890767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (Config.LOGV) Log.v(LOG_TAG, "SMS originating address: " 891767a662ecde33c3979bf02b793d392aca0403162Wink Saville + originatingAddress.address); 892767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 893767a662ecde33c3979bf02b793d392aca0403162Wink Saville 894767a662ecde33c3979bf02b793d392aca0403162Wink Saville // TP-Protocol-Identifier (TP-PID) 895767a662ecde33c3979bf02b793d392aca0403162Wink Saville // TS 23.040 9.2.3.9 896767a662ecde33c3979bf02b793d392aca0403162Wink Saville protocolIdentifier = p.getByte(); 897767a662ecde33c3979bf02b793d392aca0403162Wink Saville 898767a662ecde33c3979bf02b793d392aca0403162Wink Saville // TP-Data-Coding-Scheme 899767a662ecde33c3979bf02b793d392aca0403162Wink Saville // see TS 23.038 900767a662ecde33c3979bf02b793d392aca0403162Wink Saville dataCodingScheme = p.getByte(); 901767a662ecde33c3979bf02b793d392aca0403162Wink Saville 902767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (Config.LOGV) { 903767a662ecde33c3979bf02b793d392aca0403162Wink Saville Log.v(LOG_TAG, "SMS TP-PID:" + protocolIdentifier 904767a662ecde33c3979bf02b793d392aca0403162Wink Saville + " data coding scheme: " + dataCodingScheme); 905767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 906767a662ecde33c3979bf02b793d392aca0403162Wink Saville 907767a662ecde33c3979bf02b793d392aca0403162Wink Saville scTimeMillis = p.getSCTimestampMillis(); 908767a662ecde33c3979bf02b793d392aca0403162Wink Saville 909767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (Config.LOGD) Log.d(LOG_TAG, "SMS SC timestamp: " + scTimeMillis); 910767a662ecde33c3979bf02b793d392aca0403162Wink Saville 911767a662ecde33c3979bf02b793d392aca0403162Wink Saville boolean hasUserDataHeader = (firstByte & 0x40) == 0x40; 912767a662ecde33c3979bf02b793d392aca0403162Wink Saville 913767a662ecde33c3979bf02b793d392aca0403162Wink Saville parseUserData(p, hasUserDataHeader); 914767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 915767a662ecde33c3979bf02b793d392aca0403162Wink Saville 916767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** 917767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Parses the User Data of an SMS. 918767a662ecde33c3979bf02b793d392aca0403162Wink Saville * 919767a662ecde33c3979bf02b793d392aca0403162Wink Saville * @param p The current PduParser. 920767a662ecde33c3979bf02b793d392aca0403162Wink Saville * @param hasUserDataHeader Indicates whether a header is present in the 921767a662ecde33c3979bf02b793d392aca0403162Wink Saville * User Data. 922767a662ecde33c3979bf02b793d392aca0403162Wink Saville */ 923767a662ecde33c3979bf02b793d392aca0403162Wink Saville private void parseUserData(PduParser p, boolean hasUserDataHeader) { 924767a662ecde33c3979bf02b793d392aca0403162Wink Saville boolean hasMessageClass = false; 925767a662ecde33c3979bf02b793d392aca0403162Wink Saville boolean userDataCompressed = false; 926767a662ecde33c3979bf02b793d392aca0403162Wink Saville 927767a662ecde33c3979bf02b793d392aca0403162Wink Saville int encodingType = ENCODING_UNKNOWN; 928767a662ecde33c3979bf02b793d392aca0403162Wink Saville 929767a662ecde33c3979bf02b793d392aca0403162Wink Saville // Look up the data encoding scheme 930767a662ecde33c3979bf02b793d392aca0403162Wink Saville if ((dataCodingScheme & 0x80) == 0) { 931767a662ecde33c3979bf02b793d392aca0403162Wink Saville // Bits 7..4 == 0xxx 932767a662ecde33c3979bf02b793d392aca0403162Wink Saville automaticDeletion = (0 != (dataCodingScheme & 0x40)); 933767a662ecde33c3979bf02b793d392aca0403162Wink Saville userDataCompressed = (0 != (dataCodingScheme & 0x20)); 934767a662ecde33c3979bf02b793d392aca0403162Wink Saville hasMessageClass = (0 != (dataCodingScheme & 0x10)); 935767a662ecde33c3979bf02b793d392aca0403162Wink Saville 936767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (userDataCompressed) { 937767a662ecde33c3979bf02b793d392aca0403162Wink Saville Log.w(LOG_TAG, "4 - Unsupported SMS data coding scheme " 938767a662ecde33c3979bf02b793d392aca0403162Wink Saville + "(compression) " + (dataCodingScheme & 0xff)); 939767a662ecde33c3979bf02b793d392aca0403162Wink Saville } else { 940767a662ecde33c3979bf02b793d392aca0403162Wink Saville switch ((dataCodingScheme >> 2) & 0x3) { 941767a662ecde33c3979bf02b793d392aca0403162Wink Saville case 0: // GSM 7 bit default alphabet 942767a662ecde33c3979bf02b793d392aca0403162Wink Saville encodingType = ENCODING_7BIT; 943767a662ecde33c3979bf02b793d392aca0403162Wink Saville break; 944767a662ecde33c3979bf02b793d392aca0403162Wink Saville 945767a662ecde33c3979bf02b793d392aca0403162Wink Saville case 2: // UCS 2 (16bit) 946767a662ecde33c3979bf02b793d392aca0403162Wink Saville encodingType = ENCODING_16BIT; 947767a662ecde33c3979bf02b793d392aca0403162Wink Saville break; 948767a662ecde33c3979bf02b793d392aca0403162Wink Saville 949767a662ecde33c3979bf02b793d392aca0403162Wink Saville case 1: // 8 bit data 950767a662ecde33c3979bf02b793d392aca0403162Wink Saville case 3: // reserved 951767a662ecde33c3979bf02b793d392aca0403162Wink Saville Log.w(LOG_TAG, "1 - Unsupported SMS data coding scheme " 952767a662ecde33c3979bf02b793d392aca0403162Wink Saville + (dataCodingScheme & 0xff)); 953767a662ecde33c3979bf02b793d392aca0403162Wink Saville encodingType = ENCODING_8BIT; 954767a662ecde33c3979bf02b793d392aca0403162Wink Saville break; 955767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 956767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 957767a662ecde33c3979bf02b793d392aca0403162Wink Saville } else if ((dataCodingScheme & 0xf0) == 0xf0) { 958767a662ecde33c3979bf02b793d392aca0403162Wink Saville automaticDeletion = false; 959767a662ecde33c3979bf02b793d392aca0403162Wink Saville hasMessageClass = true; 960767a662ecde33c3979bf02b793d392aca0403162Wink Saville userDataCompressed = false; 961767a662ecde33c3979bf02b793d392aca0403162Wink Saville 962767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (0 == (dataCodingScheme & 0x04)) { 963767a662ecde33c3979bf02b793d392aca0403162Wink Saville // GSM 7 bit default alphabet 964767a662ecde33c3979bf02b793d392aca0403162Wink Saville encodingType = ENCODING_7BIT; 965767a662ecde33c3979bf02b793d392aca0403162Wink Saville } else { 966767a662ecde33c3979bf02b793d392aca0403162Wink Saville // 8 bit data 967767a662ecde33c3979bf02b793d392aca0403162Wink Saville encodingType = ENCODING_8BIT; 968767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 969767a662ecde33c3979bf02b793d392aca0403162Wink Saville } else if ((dataCodingScheme & 0xF0) == 0xC0 970767a662ecde33c3979bf02b793d392aca0403162Wink Saville || (dataCodingScheme & 0xF0) == 0xD0 971767a662ecde33c3979bf02b793d392aca0403162Wink Saville || (dataCodingScheme & 0xF0) == 0xE0) { 972767a662ecde33c3979bf02b793d392aca0403162Wink Saville // 3GPP TS 23.038 V7.0.0 (2006-03) section 4 973767a662ecde33c3979bf02b793d392aca0403162Wink Saville 974767a662ecde33c3979bf02b793d392aca0403162Wink Saville // 0xC0 == 7 bit, don't store 975767a662ecde33c3979bf02b793d392aca0403162Wink Saville // 0xD0 == 7 bit, store 976767a662ecde33c3979bf02b793d392aca0403162Wink Saville // 0xE0 == UCS-2, store 977767a662ecde33c3979bf02b793d392aca0403162Wink Saville 978767a662ecde33c3979bf02b793d392aca0403162Wink Saville if ((dataCodingScheme & 0xF0) == 0xE0) { 979767a662ecde33c3979bf02b793d392aca0403162Wink Saville encodingType = ENCODING_16BIT; 980767a662ecde33c3979bf02b793d392aca0403162Wink Saville } else { 981767a662ecde33c3979bf02b793d392aca0403162Wink Saville encodingType = ENCODING_7BIT; 982767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 983767a662ecde33c3979bf02b793d392aca0403162Wink Saville 984767a662ecde33c3979bf02b793d392aca0403162Wink Saville userDataCompressed = false; 985767a662ecde33c3979bf02b793d392aca0403162Wink Saville boolean active = ((dataCodingScheme & 0x08) == 0x08); 986767a662ecde33c3979bf02b793d392aca0403162Wink Saville 987767a662ecde33c3979bf02b793d392aca0403162Wink Saville // bit 0x04 reserved 988767a662ecde33c3979bf02b793d392aca0403162Wink Saville 989767a662ecde33c3979bf02b793d392aca0403162Wink Saville if ((dataCodingScheme & 0x03) == 0x00) { 990767a662ecde33c3979bf02b793d392aca0403162Wink Saville isMwi = true; 991767a662ecde33c3979bf02b793d392aca0403162Wink Saville mwiSense = active; 992767a662ecde33c3979bf02b793d392aca0403162Wink Saville mwiDontStore = ((dataCodingScheme & 0xF0) == 0xC0); 993767a662ecde33c3979bf02b793d392aca0403162Wink Saville } else { 994767a662ecde33c3979bf02b793d392aca0403162Wink Saville isMwi = false; 995767a662ecde33c3979bf02b793d392aca0403162Wink Saville 996767a662ecde33c3979bf02b793d392aca0403162Wink Saville Log.w(LOG_TAG, "MWI for fax, email, or other " 997767a662ecde33c3979bf02b793d392aca0403162Wink Saville + (dataCodingScheme & 0xff)); 998767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 999767a662ecde33c3979bf02b793d392aca0403162Wink Saville } else { 1000767a662ecde33c3979bf02b793d392aca0403162Wink Saville Log.w(LOG_TAG, "3 - Unsupported SMS data coding scheme " 1001767a662ecde33c3979bf02b793d392aca0403162Wink Saville + (dataCodingScheme & 0xff)); 1002767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 1003767a662ecde33c3979bf02b793d392aca0403162Wink Saville 1004767a662ecde33c3979bf02b793d392aca0403162Wink Saville // set both the user data and the user data header. 1005767a662ecde33c3979bf02b793d392aca0403162Wink Saville int count = p.constructUserData(hasUserDataHeader, 1006767a662ecde33c3979bf02b793d392aca0403162Wink Saville encodingType == ENCODING_7BIT); 1007767a662ecde33c3979bf02b793d392aca0403162Wink Saville this.userData = p.getUserData(); 1008767a662ecde33c3979bf02b793d392aca0403162Wink Saville this.userDataHeader = p.getUserDataHeader(); 1009767a662ecde33c3979bf02b793d392aca0403162Wink Saville 1010767a662ecde33c3979bf02b793d392aca0403162Wink Saville switch (encodingType) { 1011767a662ecde33c3979bf02b793d392aca0403162Wink Saville case ENCODING_UNKNOWN: 1012767a662ecde33c3979bf02b793d392aca0403162Wink Saville case ENCODING_8BIT: 1013767a662ecde33c3979bf02b793d392aca0403162Wink Saville messageBody = null; 1014767a662ecde33c3979bf02b793d392aca0403162Wink Saville break; 1015767a662ecde33c3979bf02b793d392aca0403162Wink Saville 1016767a662ecde33c3979bf02b793d392aca0403162Wink Saville case ENCODING_7BIT: 1017767a662ecde33c3979bf02b793d392aca0403162Wink Saville messageBody = p.getUserDataGSM7Bit(count); 1018767a662ecde33c3979bf02b793d392aca0403162Wink Saville break; 1019767a662ecde33c3979bf02b793d392aca0403162Wink Saville 1020767a662ecde33c3979bf02b793d392aca0403162Wink Saville case ENCODING_16BIT: 1021767a662ecde33c3979bf02b793d392aca0403162Wink Saville messageBody = p.getUserDataUCS2(count); 1022767a662ecde33c3979bf02b793d392aca0403162Wink Saville break; 1023767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 1024767a662ecde33c3979bf02b793d392aca0403162Wink Saville 1025767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (Config.LOGV) Log.v(LOG_TAG, "SMS message body (raw): '" + messageBody + "'"); 1026767a662ecde33c3979bf02b793d392aca0403162Wink Saville 1027767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (messageBody != null) { 1028767a662ecde33c3979bf02b793d392aca0403162Wink Saville parseMessageBody(); 1029767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 1030767a662ecde33c3979bf02b793d392aca0403162Wink Saville 1031767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (!hasMessageClass) { 1032767a662ecde33c3979bf02b793d392aca0403162Wink Saville messageClass = MessageClass.UNKNOWN; 1033767a662ecde33c3979bf02b793d392aca0403162Wink Saville } else { 1034767a662ecde33c3979bf02b793d392aca0403162Wink Saville switch (dataCodingScheme & 0x3) { 1035767a662ecde33c3979bf02b793d392aca0403162Wink Saville case 0: 1036767a662ecde33c3979bf02b793d392aca0403162Wink Saville messageClass = MessageClass.CLASS_0; 1037767a662ecde33c3979bf02b793d392aca0403162Wink Saville break; 1038767a662ecde33c3979bf02b793d392aca0403162Wink Saville case 1: 1039767a662ecde33c3979bf02b793d392aca0403162Wink Saville messageClass = MessageClass.CLASS_1; 1040767a662ecde33c3979bf02b793d392aca0403162Wink Saville break; 1041767a662ecde33c3979bf02b793d392aca0403162Wink Saville case 2: 1042767a662ecde33c3979bf02b793d392aca0403162Wink Saville messageClass = MessageClass.CLASS_2; 1043767a662ecde33c3979bf02b793d392aca0403162Wink Saville break; 1044767a662ecde33c3979bf02b793d392aca0403162Wink Saville case 3: 1045767a662ecde33c3979bf02b793d392aca0403162Wink Saville messageClass = MessageClass.CLASS_3; 1046767a662ecde33c3979bf02b793d392aca0403162Wink Saville break; 1047767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 1048767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 1049767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 1050767a662ecde33c3979bf02b793d392aca0403162Wink Saville 1051767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** 1052767a662ecde33c3979bf02b793d392aca0403162Wink Saville * {@inheritDoc} 1053767a662ecde33c3979bf02b793d392aca0403162Wink Saville */ 1054767a662ecde33c3979bf02b793d392aca0403162Wink Saville public MessageClass getMessageClass() { 1055767a662ecde33c3979bf02b793d392aca0403162Wink Saville return messageClass; 1056767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 1057767a662ecde33c3979bf02b793d392aca0403162Wink Saville 1058767a662ecde33c3979bf02b793d392aca0403162Wink Saville} 1059