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