| /* |
| * Copyright (C) 2008 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.telephony; |
| |
| import android.os.Parcel; |
| import android.util.Log; |
| |
| import com.android.internal.telephony.GsmAlphabet; |
| import com.android.internal.telephony.EncodeException; |
| import com.android.internal.telephony.SmsHeader; |
| import com.android.internal.telephony.SmsMessageBase; |
| import com.android.internal.telephony.SmsMessageBase.SubmitPduBase; |
| import com.android.internal.telephony.SmsMessageBase.TextEncodingDetails; |
| |
| import java.lang.Math; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| |
| import static android.telephony.TelephonyManager.PHONE_TYPE_CDMA; |
| |
| |
| /** |
| * A Short Message Service message. |
| */ |
| public class SmsMessage { |
| private static final boolean LOCAL_DEBUG = true; |
| private static final String LOG_TAG = "SMS"; |
| |
| /** |
| * SMS Class enumeration. |
| * See TS 23.038. |
| * |
| */ |
| public enum MessageClass{ |
| UNKNOWN, CLASS_0, CLASS_1, CLASS_2, CLASS_3; |
| } |
| |
| /** User data text encoding code unit size */ |
| public static final int ENCODING_UNKNOWN = 0; |
| public static final int ENCODING_7BIT = 1; |
| public static final int ENCODING_8BIT = 2; |
| public static final int ENCODING_16BIT = 3; |
| |
| /** The maximum number of payload bytes per message */ |
| public static final int MAX_USER_DATA_BYTES = 140; |
| |
| /** |
| * The maximum number of payload bytes per message if a user data header |
| * is present. This assumes the header only contains the |
| * CONCATENATED_8_BIT_REFERENCE element. |
| */ |
| public static final int MAX_USER_DATA_BYTES_WITH_HEADER = 134; |
| |
| /** The maximum number of payload septets per message */ |
| public static final int MAX_USER_DATA_SEPTETS = 160; |
| |
| /** |
| * The maximum number of payload septets per message if a user data header |
| * is present. This assumes the header only contains the |
| * CONCATENATED_8_BIT_REFERENCE element. |
| */ |
| public static final int MAX_USER_DATA_SEPTETS_WITH_HEADER = 153; |
| |
| /** Contains actual SmsMessage. Only public for debugging and for framework layer. |
| * |
| * @hide |
| */ |
| public SmsMessageBase mWrappedSmsMessage; |
| |
| public static class SubmitPdu { |
| |
| public byte[] encodedScAddress; // Null if not applicable. |
| public byte[] encodedMessage; |
| |
| public String toString() { |
| return "SubmitPdu: encodedScAddress = " |
| + Arrays.toString(encodedScAddress) |
| + ", encodedMessage = " |
| + Arrays.toString(encodedMessage); |
| } |
| |
| /** |
| * @hide |
| */ |
| protected SubmitPdu(SubmitPduBase spb) { |
| this.encodedMessage = spb.encodedMessage; |
| this.encodedScAddress = spb.encodedScAddress; |
| } |
| |
| } |
| |
| /** |
| * Constructor |
| * |
| * @hide |
| */ |
| public SmsMessage() { |
| this(getSmsFacility()); |
| } |
| |
| private SmsMessage(SmsMessageBase smb) { |
| mWrappedSmsMessage = smb; |
| } |
| |
| /** |
| * Create an SmsMessage from a raw PDU. |
| */ |
| public static SmsMessage createFromPdu(byte[] pdu) { |
| SmsMessageBase wrappedMessage; |
| int activePhone = TelephonyManager.getDefault().getPhoneType(); |
| |
| if (PHONE_TYPE_CDMA == activePhone) { |
| wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.createFromPdu(pdu); |
| } else { |
| wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.createFromPdu(pdu); |
| } |
| |
| return new SmsMessage(wrappedMessage); |
| } |
| |
| /** |
| * TS 27.005 3.4.1 lines[0] and lines[1] are the two lines read from the |
| * +CMT unsolicited response (PDU mode, of course) |
| * +CMT: [<alpha>],<length><CR><LF><pdu> |
| * |
| * Only public for debugging and for RIL |
| * |
| * {@hide} |
| */ |
| public static SmsMessage newFromCMT(String[] lines){ |
| SmsMessageBase wrappedMessage; |
| int activePhone = TelephonyManager.getDefault().getPhoneType(); |
| |
| if (PHONE_TYPE_CDMA == activePhone) { |
| wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.newFromCMT(lines); |
| } else { |
| wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.newFromCMT(lines); |
| } |
| |
| return new SmsMessage(wrappedMessage); |
| } |
| |
| /** @hide */ |
| protected static SmsMessage newFromCMTI(String line) { |
| SmsMessageBase wrappedMessage; |
| int activePhone = TelephonyManager.getDefault().getPhoneType(); |
| |
| if (PHONE_TYPE_CDMA == activePhone) { |
| wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.newFromCMTI(line); |
| } else { |
| wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.newFromCMTI(line); |
| } |
| |
| return new SmsMessage(wrappedMessage); |
| } |
| |
| /** @hide */ |
| public static SmsMessage newFromCDS(String line) { |
| SmsMessageBase wrappedMessage; |
| int activePhone = TelephonyManager.getDefault().getPhoneType(); |
| |
| if (PHONE_TYPE_CDMA == activePhone) { |
| wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.newFromCDS(line); |
| } else { |
| wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.newFromCDS(line); |
| } |
| |
| return new SmsMessage(wrappedMessage); |
| } |
| |
| /** @hide */ |
| public static SmsMessage newFromParcel(Parcel p) { |
| SmsMessageBase wrappedMessage; |
| int activePhone = TelephonyManager.getDefault().getPhoneType(); |
| |
| if (PHONE_TYPE_CDMA == activePhone) { |
| wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.newFromParcel(p); |
| } else { |
| wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.newFromParcel(p); |
| } |
| |
| return new SmsMessage(wrappedMessage); |
| } |
| |
| /** |
| * Create an SmsMessage from an SMS EF record. |
| * |
| * @param index Index of SMS record. This should be index in ArrayList |
| * returned by SmsManager.getAllMessagesFromSim + 1. |
| * @param data Record data. |
| * @return An SmsMessage representing the record. |
| * |
| * @hide |
| */ |
| public static SmsMessage createFromEfRecord(int index, byte[] data) { |
| SmsMessageBase wrappedMessage; |
| int activePhone = TelephonyManager.getDefault().getPhoneType(); |
| |
| if (PHONE_TYPE_CDMA == activePhone) { |
| wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.createFromEfRecord( |
| index, data); |
| } else { |
| wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.createFromEfRecord( |
| index, data); |
| } |
| |
| return wrappedMessage != null ? new SmsMessage(wrappedMessage) : null; |
| } |
| |
| /** |
| * Get the TP-Layer-Length for the given SMS-SUBMIT PDU Basically, the |
| * length in bytes (not hex chars) less the SMSC header |
| */ |
| public static int getTPLayerLengthForPDU(String pdu) { |
| int activePhone = TelephonyManager.getDefault().getPhoneType(); |
| |
| if (PHONE_TYPE_CDMA == activePhone) { |
| return com.android.internal.telephony.cdma.SmsMessage.getTPLayerLengthForPDU(pdu); |
| } else { |
| return com.android.internal.telephony.gsm.SmsMessage.getTPLayerLengthForPDU(pdu); |
| } |
| } |
| |
| /* |
| * TODO(cleanup): It would make some sense if the result of |
| * preprocessing a message to determine the proper encoding (ie |
| * the resulting datastructure from calculateLength) could be |
| * passed as an argument to the actual final encoding function. |
| * This would better ensure that the logic behind size calculation |
| * actually matched the encoding. |
| */ |
| |
| /** |
| * Calculates the number of SMS's required to encode the message body and |
| * the number of characters remaining until the next message. |
| * |
| * @param msgBody the message to encode |
| * @param use7bitOnly if true, characters that are not part of the |
| * radio-specific 7-bit encoding are counted as single |
| * space chars. If false, and if the messageBody contains |
| * non-7-bit encodable characters, length is calculated |
| * using a 16-bit encoding. |
| * @return an int[4] with int[0] being the number of SMS's |
| * required, int[1] the number of code units used, and |
| * int[2] is the number of code units remaining until the |
| * next message. int[3] is an indicator of the encoding |
| * code unit size (see the ENCODING_* definitions in this |
| * class). |
| */ |
| public static int[] calculateLength(CharSequence msgBody, boolean use7bitOnly) { |
| int activePhone = TelephonyManager.getDefault().getPhoneType(); |
| TextEncodingDetails ted = (PHONE_TYPE_CDMA == activePhone) ? |
| com.android.internal.telephony.cdma.SmsMessage.calculateLength(msgBody, use7bitOnly) : |
| com.android.internal.telephony.gsm.SmsMessage.calculateLength(msgBody, use7bitOnly); |
| int ret[] = new int[4]; |
| ret[0] = ted.msgCount; |
| ret[1] = ted.codeUnitCount; |
| ret[2] = ted.codeUnitsRemaining; |
| ret[3] = ted.codeUnitSize; |
| return ret; |
| } |
| |
| /** |
| * Divide a message text into several fragments, none bigger than |
| * the maximum SMS message text size. |
| * |
| * @param text text, must not be null. |
| * @return an <code>ArrayList</code> of strings that, in order, |
| * comprise the original msg text |
| * |
| * @hide |
| */ |
| public static ArrayList<String> fragmentText(String text) { |
| int activePhone = TelephonyManager.getDefault().getPhoneType(); |
| TextEncodingDetails ted = (PHONE_TYPE_CDMA == activePhone) ? |
| com.android.internal.telephony.cdma.SmsMessage.calculateLength(text, false) : |
| com.android.internal.telephony.gsm.SmsMessage.calculateLength(text, false); |
| |
| // TODO(cleanup): The code here could be rolled into the logic |
| // below cleanly if these MAX_* constants were defined more |
| // flexibly... |
| |
| int limit; |
| if (ted.msgCount > 1) { |
| limit = (ted.codeUnitSize == ENCODING_7BIT) ? |
| MAX_USER_DATA_SEPTETS_WITH_HEADER : MAX_USER_DATA_BYTES_WITH_HEADER; |
| } else { |
| limit = (ted.codeUnitSize == ENCODING_7BIT) ? |
| MAX_USER_DATA_SEPTETS : MAX_USER_DATA_BYTES; |
| } |
| |
| int pos = 0; // Index in code units. |
| int textLen = text.length(); |
| ArrayList<String> result = new ArrayList<String>(ted.msgCount); |
| while (pos < textLen) { |
| int nextPos = 0; // Counts code units. |
| if (ted.codeUnitSize == ENCODING_7BIT) { |
| if (activePhone == PHONE_TYPE_CDMA && ted.msgCount == 1) { |
| // For a singleton CDMA message, the encoding must be ASCII... |
| nextPos = pos + Math.min(limit, textLen - pos); |
| } else { |
| // For multi-segment messages, CDMA 7bit equals GSM 7bit encoding (EMS mode). |
| nextPos = GsmAlphabet.findGsmSeptetLimitIndex(text, pos, limit); |
| } |
| } else { // Assume unicode. |
| nextPos = pos + Math.min(limit / 2, textLen - pos); |
| } |
| if ((nextPos <= pos) || (nextPos > textLen)) { |
| Log.e(LOG_TAG, "fragmentText failed (" + pos + " >= " + nextPos + " or " + |
| nextPos + " >= " + textLen + ")"); |
| break; |
| } |
| result.add(text.substring(pos, nextPos)); |
| pos = nextPos; |
| } |
| return result; |
| } |
| |
| /** |
| * Calculates the number of SMS's required to encode the message body and |
| * the number of characters remaining until the next message, given the |
| * current encoding. |
| * |
| * @param messageBody the message to encode |
| * @param use7bitOnly if true, characters that are not part of the radio |
| * specific (GSM / CDMA) alphabet encoding are converted to as a |
| * single space characters. If false, a messageBody containing |
| * non-GSM or non-CDMA alphabet characters are encoded using |
| * 16-bit encoding. |
| * @return an int[4] with int[0] being the number of SMS's required, int[1] |
| * the number of code units used, and int[2] is the number of code |
| * units remaining until the next message. int[3] is the encoding |
| * type that should be used for the message. |
| */ |
| public static int[] calculateLength(String messageBody, boolean use7bitOnly) { |
| return calculateLength((CharSequence)messageBody, use7bitOnly); |
| } |
| |
| /* |
| * TODO(cleanup): It looks like there is now no useful reason why |
| * apps should generate pdus themselves using these routines, |
| * instead of handing the raw data to SMSDispatcher (and thereby |
| * have the phone process do the encoding). Moreover, CDMA now |
| * has shared state (in the form of the msgId system property) |
| * which can only be modified by the phone process, and hence |
| * makes the output of these routines incorrect. Since they now |
| * serve no purpose, they should probably just return null |
| * directly, and be deprecated. Going further in that direction, |
| * the above parsers of serialized pdu data should probably also |
| * be gotten rid of, hiding all but the necessarily visible |
| * structured data from client apps. A possible concern with |
| * doing this is that apps may be using these routines to generate |
| * pdus that are then sent elsewhere, some network server, for |
| * example, and that always returning null would thereby break |
| * otherwise useful apps. |
| */ |
| |
| /** |
| * Get an SMS-SUBMIT PDU for a destination address and a message |
| * |
| * @param scAddress Service Centre address. Null means use default. |
| * @return a <code>SubmitPdu</code> containing the encoded SC |
| * address, if applicable, and the encoded message. |
| * Returns null on encode error. |
| * @hide |
| */ |
| public static SubmitPdu getSubmitPdu(String scAddress, |
| String destinationAddress, String message, |
| boolean statusReportRequested, byte[] header) { |
| SubmitPduBase spb; |
| int activePhone = TelephonyManager.getDefault().getPhoneType(); |
| |
| if (PHONE_TYPE_CDMA == activePhone) { |
| spb = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(scAddress, |
| destinationAddress, message, statusReportRequested, |
| SmsHeader.fromByteArray(header)); |
| } else { |
| spb = com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(scAddress, |
| destinationAddress, message, statusReportRequested, header); |
| } |
| |
| return new SubmitPdu(spb); |
| } |
| |
| /** |
| * Get an SMS-SUBMIT PDU for a destination address and a message |
| * |
| * @param scAddress Service Centre address. Null means use default. |
| * @return a <code>SubmitPdu</code> containing the encoded SC |
| * address, if applicable, and the encoded message. |
| * Returns null on encode error. |
| */ |
| public static SubmitPdu getSubmitPdu(String scAddress, |
| String destinationAddress, String message, boolean statusReportRequested) { |
| SubmitPduBase spb; |
| int activePhone = TelephonyManager.getDefault().getPhoneType(); |
| |
| if (PHONE_TYPE_CDMA == activePhone) { |
| spb = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(scAddress, |
| destinationAddress, message, statusReportRequested, null); |
| } else { |
| spb = com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(scAddress, |
| destinationAddress, message, statusReportRequested); |
| } |
| |
| return new SubmitPdu(spb); |
| } |
| |
| /** |
| * Get an SMS-SUBMIT PDU for a data message to a destination address & port |
| * |
| * @param scAddress Service Centre address. null == use default |
| * @param destinationAddress the address of the destination for the message |
| * @param destinationPort the port to deliver the message to at the |
| * destination |
| * @param data the dat for the message |
| * @return a <code>SubmitPdu</code> containing the encoded SC |
| * address, if applicable, and the encoded message. |
| * Returns null on encode error. |
| */ |
| public static SubmitPdu getSubmitPdu(String scAddress, |
| String destinationAddress, short destinationPort, byte[] data, |
| boolean statusReportRequested) { |
| SubmitPduBase spb; |
| int activePhone = TelephonyManager.getDefault().getPhoneType(); |
| |
| if (PHONE_TYPE_CDMA == activePhone) { |
| spb = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(scAddress, |
| destinationAddress, destinationPort, data, statusReportRequested); |
| } else { |
| spb = com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(scAddress, |
| destinationAddress, destinationPort, data, statusReportRequested); |
| } |
| |
| return new SubmitPdu(spb); |
| } |
| |
| /** |
| * Returns the address of the SMS service center that relayed this message |
| * or null if there is none. |
| */ |
| public String getServiceCenterAddress() { |
| return mWrappedSmsMessage.getServiceCenterAddress(); |
| } |
| |
| /** |
| * Returns the originating address (sender) of this SMS message in String |
| * form or null if unavailable |
| */ |
| public String getOriginatingAddress() { |
| return mWrappedSmsMessage.getOriginatingAddress(); |
| } |
| |
| /** |
| * Returns the originating address, or email from address if this message |
| * was from an email gateway. Returns null if originating address |
| * unavailable. |
| */ |
| public String getDisplayOriginatingAddress() { |
| return mWrappedSmsMessage.getDisplayOriginatingAddress(); |
| } |
| |
| /** |
| * Returns the message body as a String, if it exists and is text based. |
| * @return message body is there is one, otherwise null |
| */ |
| public String getMessageBody() { |
| return mWrappedSmsMessage.getMessageBody(); |
| } |
| |
| /** |
| * Returns the class of this message. |
| */ |
| public MessageClass getMessageClass() { |
| return mWrappedSmsMessage.getMessageClass(); |
| } |
| |
| /** |
| * Returns the message body, or email message body if this message was from |
| * an email gateway. Returns null if message body unavailable. |
| */ |
| public String getDisplayMessageBody() { |
| return mWrappedSmsMessage.getDisplayMessageBody(); |
| } |
| |
| /** |
| * Unofficial convention of a subject line enclosed in parens empty string |
| * if not present |
| */ |
| public String getPseudoSubject() { |
| return mWrappedSmsMessage.getPseudoSubject(); |
| } |
| |
| /** |
| * Returns the service centre timestamp in currentTimeMillis() format |
| */ |
| public long getTimestampMillis() { |
| return mWrappedSmsMessage.getTimestampMillis(); |
| } |
| |
| /** |
| * Returns true if message is an email. |
| * |
| * @return true if this message came through an email gateway and email |
| * sender / subject / parsed body are available |
| */ |
| public boolean isEmail() { |
| return mWrappedSmsMessage.isEmail(); |
| } |
| |
| /** |
| * @return if isEmail() is true, body of the email sent through the gateway. |
| * null otherwise |
| */ |
| public String getEmailBody() { |
| return mWrappedSmsMessage.getEmailBody(); |
| } |
| |
| /** |
| * @return if isEmail() is true, email from address of email sent through |
| * the gateway. null otherwise |
| */ |
| public String getEmailFrom() { |
| return mWrappedSmsMessage.getEmailFrom(); |
| } |
| |
| /** |
| * Get protocol identifier. |
| */ |
| public int getProtocolIdentifier() { |
| return mWrappedSmsMessage.getProtocolIdentifier(); |
| } |
| |
| /** |
| * See TS 23.040 9.2.3.9 returns true if this is a "replace short message" |
| * SMS |
| */ |
| public boolean isReplace() { |
| return mWrappedSmsMessage.isReplace(); |
| } |
| |
| /** |
| * Returns true for CPHS MWI toggle message. |
| * |
| * @return true if this is a CPHS MWI toggle message See CPHS 4.2 section |
| * B.4.2 |
| */ |
| public boolean isCphsMwiMessage() { |
| return mWrappedSmsMessage.isCphsMwiMessage(); |
| } |
| |
| /** |
| * returns true if this message is a CPHS voicemail / message waiting |
| * indicator (MWI) clear message |
| */ |
| public boolean isMWIClearMessage() { |
| return mWrappedSmsMessage.isMWIClearMessage(); |
| } |
| |
| /** |
| * returns true if this message is a CPHS voicemail / message waiting |
| * indicator (MWI) set message |
| */ |
| public boolean isMWISetMessage() { |
| return mWrappedSmsMessage.isMWISetMessage(); |
| } |
| |
| /** |
| * returns true if this message is a "Message Waiting Indication Group: |
| * Discard Message" notification and should not be stored. |
| */ |
| public boolean isMwiDontStore() { |
| return mWrappedSmsMessage.isMwiDontStore(); |
| } |
| |
| /** |
| * returns the user data section minus the user data header if one was |
| * present. |
| */ |
| public byte[] getUserData() { |
| return mWrappedSmsMessage.getUserData(); |
| } |
| |
| /** |
| * Return the user data header (UDH). |
| * |
| * @hide |
| */ |
| public SmsHeader getUserDataHeader() { |
| return mWrappedSmsMessage.getUserDataHeader(); |
| } |
| |
| /** |
| * Returns the raw PDU for the message. |
| * |
| * @return the raw PDU for the message. |
| */ |
| public byte[] getPdu() { |
| return mWrappedSmsMessage.getPdu(); |
| } |
| |
| /** |
| * Returns the status of the message on the SIM (read, unread, sent, unsent). |
| * |
| * @return the status of the message on the SIM. These are: |
| * SmsManager.STATUS_ON_SIM_FREE |
| * SmsManager.STATUS_ON_SIM_READ |
| * SmsManager.STATUS_ON_SIM_UNREAD |
| * SmsManager.STATUS_ON_SIM_SEND |
| * SmsManager.STATUS_ON_SIM_UNSENT |
| * @deprecated Use getStatusOnIcc instead. |
| */ |
| @Deprecated public int getStatusOnSim() { |
| return mWrappedSmsMessage.getStatusOnIcc(); |
| } |
| |
| /** |
| * Returns the status of the message on the ICC (read, unread, sent, unsent). |
| * |
| * @return the status of the message on the ICC. These are: |
| * SmsManager.STATUS_ON_ICC_FREE |
| * SmsManager.STATUS_ON_ICC_READ |
| * SmsManager.STATUS_ON_ICC_UNREAD |
| * SmsManager.STATUS_ON_ICC_SEND |
| * SmsManager.STATUS_ON_ICC_UNSENT |
| */ |
| public int getStatusOnIcc() { |
| |
| return mWrappedSmsMessage.getStatusOnIcc(); |
| } |
| |
| /** |
| * Returns the record index of the message on the SIM (1-based index). |
| * @return the record index of the message on the SIM, or -1 if this |
| * SmsMessage was not created from a SIM SMS EF record. |
| * @deprecated Use getIndexOnIcc instead. |
| */ |
| @Deprecated public int getIndexOnSim() { |
| return mWrappedSmsMessage.getIndexOnIcc(); |
| } |
| |
| /** |
| * Returns the record index of the message on the ICC (1-based index). |
| * @return the record index of the message on the ICC, or -1 if this |
| * SmsMessage was not created from a ICC SMS EF record. |
| */ |
| public int getIndexOnIcc() { |
| |
| return mWrappedSmsMessage.getIndexOnIcc(); |
| } |
| |
| /** |
| * GSM: |
| * For an SMS-STATUS-REPORT message, this returns the status field from |
| * the status report. This field indicates the status of a previously |
| * submitted SMS, if requested. See TS 23.040, 9.2.3.15 TP-Status for a |
| * description of values. |
| * CDMA: |
| * For not interfering with status codes from GSM, the value is |
| * shifted to the bits 31-16. |
| * The value is composed of an error class (bits 25-24) and a status code (bits 23-16). |
| * Possible codes are described in C.S0015-B, v2.0, 4.5.21. |
| * |
| * @return 0 indicates the previously sent message was received. |
| * See TS 23.040, 9.9.2.3.15 and C.S0015-B, v2.0, 4.5.21 |
| * for a description of other possible values. |
| */ |
| public int getStatus() { |
| return mWrappedSmsMessage.getStatus(); |
| } |
| |
| /** |
| * Return true iff the message is a SMS-STATUS-REPORT message. |
| */ |
| public boolean isStatusReportMessage() { |
| return mWrappedSmsMessage.isStatusReportMessage(); |
| } |
| |
| /** |
| * Returns true iff the <code>TP-Reply-Path</code> bit is set in |
| * this message. |
| */ |
| public boolean isReplyPathPresent() { |
| return mWrappedSmsMessage.isReplyPathPresent(); |
| } |
| |
| /** This method returns the reference to a specific |
| * SmsMessage object, which is used for accessing its static methods. |
| * @return Specific SmsMessage. |
| * |
| * @hide |
| */ |
| private static final SmsMessageBase getSmsFacility(){ |
| int activePhone = TelephonyManager.getDefault().getPhoneType(); |
| if (PHONE_TYPE_CDMA == activePhone) { |
| return new com.android.internal.telephony.cdma.SmsMessage(); |
| } else { |
| return new com.android.internal.telephony.gsm.SmsMessage(); |
| } |
| } |
| } |