Home | History | Annotate | Download | only in telephony
      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