1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.internal.telephony; 18 19import com.android.internal.telephony.SmsConstants; 20import com.android.internal.telephony.SmsHeader; 21import java.util.Arrays; 22 23import android.provider.Telephony; 24 25/** 26 * Base class declaring the specific methods and members for SmsMessage. 27 * {@hide} 28 */ 29public abstract class SmsMessageBase { 30 private static final String LOG_TAG = "SMS"; 31 32 /** {@hide} The address of the SMSC. May be null */ 33 protected String scAddress; 34 35 /** {@hide} The address of the sender */ 36 protected SmsAddress originatingAddress; 37 38 /** {@hide} The message body as a string. May be null if the message isn't text */ 39 protected String messageBody; 40 41 /** {@hide} */ 42 protected String pseudoSubject; 43 44 /** {@hide} Non-null if this is an email gateway message */ 45 protected String emailFrom; 46 47 /** {@hide} Non-null if this is an email gateway message */ 48 protected String emailBody; 49 50 /** {@hide} */ 51 protected boolean isEmail; 52 53 /** {@hide} */ 54 protected long scTimeMillis; 55 56 /** {@hide} The raw PDU of the message */ 57 protected byte[] mPdu; 58 59 /** {@hide} The raw bytes for the user data section of the message */ 60 protected byte[] userData; 61 62 /** {@hide} */ 63 protected SmsHeader userDataHeader; 64 65 // "Message Waiting Indication Group" 66 // 23.038 Section 4 67 /** {@hide} */ 68 protected boolean isMwi; 69 70 /** {@hide} */ 71 protected boolean mwiSense; 72 73 /** {@hide} */ 74 protected boolean mwiDontStore; 75 76 /** 77 * Indicates status for messages stored on the ICC. 78 */ 79 protected int statusOnIcc = -1; 80 81 /** 82 * Record index of message in the EF. 83 */ 84 protected int indexOnIcc = -1; 85 86 /** TP-Message-Reference - Message Reference of sent message. @hide */ 87 public int messageRef; 88 89 // TODO(): This class is duplicated in SmsMessage.java. Refactor accordingly. 90 public static abstract class SubmitPduBase { 91 public byte[] encodedScAddress; // Null if not applicable. 92 public byte[] encodedMessage; 93 94 public String toString() { 95 return "SubmitPdu: encodedScAddress = " 96 + Arrays.toString(encodedScAddress) 97 + ", encodedMessage = " 98 + Arrays.toString(encodedMessage); 99 } 100 } 101 102 /** 103 * Returns the address of the SMS service center that relayed this message 104 * or null if there is none. 105 */ 106 public String getServiceCenterAddress() { 107 return scAddress; 108 } 109 110 /** 111 * Returns the originating address (sender) of this SMS message in String 112 * form or null if unavailable 113 */ 114 public String getOriginatingAddress() { 115 if (originatingAddress == null) { 116 return null; 117 } 118 119 return originatingAddress.getAddressString(); 120 } 121 122 /** 123 * Returns the originating address, or email from address if this message 124 * was from an email gateway. Returns null if originating address 125 * unavailable. 126 */ 127 public String getDisplayOriginatingAddress() { 128 if (isEmail) { 129 return emailFrom; 130 } else { 131 return getOriginatingAddress(); 132 } 133 } 134 135 /** 136 * Returns the message body as a String, if it exists and is text based. 137 * @return message body is there is one, otherwise null 138 */ 139 public String getMessageBody() { 140 return messageBody; 141 } 142 143 /** 144 * Returns the class of this message. 145 */ 146 public abstract SmsConstants.MessageClass getMessageClass(); 147 148 /** 149 * Returns the message body, or email message body if this message was from 150 * an email gateway. Returns null if message body unavailable. 151 */ 152 public String getDisplayMessageBody() { 153 if (isEmail) { 154 return emailBody; 155 } else { 156 return getMessageBody(); 157 } 158 } 159 160 /** 161 * Unofficial convention of a subject line enclosed in parens empty string 162 * if not present 163 */ 164 public String getPseudoSubject() { 165 return pseudoSubject == null ? "" : pseudoSubject; 166 } 167 168 /** 169 * Returns the service centre timestamp in currentTimeMillis() format 170 */ 171 public long getTimestampMillis() { 172 return scTimeMillis; 173 } 174 175 /** 176 * Returns true if message is an email. 177 * 178 * @return true if this message came through an email gateway and email 179 * sender / subject / parsed body are available 180 */ 181 public boolean isEmail() { 182 return isEmail; 183 } 184 185 /** 186 * @return if isEmail() is true, body of the email sent through the gateway. 187 * null otherwise 188 */ 189 public String getEmailBody() { 190 return emailBody; 191 } 192 193 /** 194 * @return if isEmail() is true, email from address of email sent through 195 * the gateway. null otherwise 196 */ 197 public String getEmailFrom() { 198 return emailFrom; 199 } 200 201 /** 202 * Get protocol identifier. 203 */ 204 public abstract int getProtocolIdentifier(); 205 206 /** 207 * See TS 23.040 9.2.3.9 returns true if this is a "replace short message" 208 * SMS 209 */ 210 public abstract boolean isReplace(); 211 212 /** 213 * Returns true for CPHS MWI toggle message. 214 * 215 * @return true if this is a CPHS MWI toggle message See CPHS 4.2 section 216 * B.4.2 217 */ 218 public abstract boolean isCphsMwiMessage(); 219 220 /** 221 * returns true if this message is a CPHS voicemail / message waiting 222 * indicator (MWI) clear message 223 */ 224 public abstract boolean isMWIClearMessage(); 225 226 /** 227 * returns true if this message is a CPHS voicemail / message waiting 228 * indicator (MWI) set message 229 */ 230 public abstract boolean isMWISetMessage(); 231 232 /** 233 * returns true if this message is a "Message Waiting Indication Group: 234 * Discard Message" notification and should not be stored. 235 */ 236 public abstract boolean isMwiDontStore(); 237 238 /** 239 * returns the user data section minus the user data header if one was 240 * present. 241 */ 242 public byte[] getUserData() { 243 return userData; 244 } 245 246 /** 247 * Returns an object representing the user data header 248 * 249 * {@hide} 250 */ 251 public SmsHeader getUserDataHeader() { 252 return userDataHeader; 253 } 254 255 /** 256 * TODO(cleanup): The term PDU is used in a seemingly non-unique 257 * manner -- for example, what is the difference between this byte 258 * array and the contents of SubmitPdu objects. Maybe a more 259 * illustrative term would be appropriate. 260 */ 261 262 /** 263 * Returns the raw PDU for the message. 264 */ 265 public byte[] getPdu() { 266 return mPdu; 267 } 268 269 /** 270 * For an SMS-STATUS-REPORT message, this returns the status field from 271 * the status report. This field indicates the status of a previously 272 * submitted SMS, if requested. See TS 23.040, 9.2.3.15 TP-Status for a 273 * description of values. 274 * 275 * @return 0 indicates the previously sent message was received. 276 * See TS 23.040, 9.9.2.3.15 for a description of other possible 277 * values. 278 */ 279 public abstract int getStatus(); 280 281 /** 282 * Return true iff the message is a SMS-STATUS-REPORT message. 283 */ 284 public abstract boolean isStatusReportMessage(); 285 286 /** 287 * Returns true iff the <code>TP-Reply-Path</code> bit is set in 288 * this message. 289 */ 290 public abstract boolean isReplyPathPresent(); 291 292 /** 293 * Returns the status of the message on the ICC (read, unread, sent, unsent). 294 * 295 * @return the status of the message on the ICC. These are: 296 * SmsManager.STATUS_ON_ICC_FREE 297 * SmsManager.STATUS_ON_ICC_READ 298 * SmsManager.STATUS_ON_ICC_UNREAD 299 * SmsManager.STATUS_ON_ICC_SEND 300 * SmsManager.STATUS_ON_ICC_UNSENT 301 */ 302 public int getStatusOnIcc() { 303 return statusOnIcc; 304 } 305 306 /** 307 * Returns the record index of the message on the ICC (1-based index). 308 * @return the record index of the message on the ICC, or -1 if this 309 * SmsMessage was not created from a ICC SMS EF record. 310 */ 311 public int getIndexOnIcc() { 312 return indexOnIcc; 313 } 314 315 protected void parseMessageBody() { 316 // originatingAddress could be null if this message is from a status 317 // report. 318 if (originatingAddress != null && originatingAddress.couldBeEmailGateway()) { 319 extractEmailAddressFromMessageBody(); 320 } 321 } 322 323 /** 324 * Try to parse this message as an email gateway message 325 * There are two ways specified in TS 23.040 Section 3.8 : 326 * - SMS message "may have its TP-PID set for Internet electronic mail - MT 327 * SMS format: [<from-address><space>]<message> - "Depending on the 328 * nature of the gateway, the destination/origination address is either 329 * derived from the content of the SMS TP-OA or TP-DA field, or the 330 * TP-OA/TP-DA field contains a generic gateway address and the to/from 331 * address is added at the beginning as shown above." (which is supported here) 332 * - Multiple addresses separated by commas, no spaces, Subject field delimited 333 * by '()' or '##' and '#' Section 9.2.3.24.11 (which are NOT supported here) 334 */ 335 protected void extractEmailAddressFromMessageBody() { 336 337 /* Some carriers may use " /" delimiter as below 338 * 339 * 1. [x@y][ ]/[subject][ ]/[body] 340 * -or- 341 * 2. [x@y][ ]/[body] 342 */ 343 String[] parts = messageBody.split("( /)|( )", 2); 344 if (parts.length < 2) return; 345 emailFrom = parts[0]; 346 emailBody = parts[1]; 347 isEmail = Telephony.Mms.isEmailAddress(emailFrom); 348 } 349 350} 351