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 android.telephony;
     18 
     19 import android.app.ActivityThread;
     20 import android.app.PendingIntent;
     21 import android.content.ActivityNotFoundException;
     22 import android.content.ContentValues;
     23 import android.content.Context;
     24 import android.content.Intent;
     25 import android.net.Uri;
     26 import android.os.BaseBundle;
     27 import android.os.Bundle;
     28 import android.os.RemoteException;
     29 import android.os.ServiceManager;
     30 import android.text.TextUtils;
     31 import android.util.ArrayMap;
     32 import android.util.Log;
     33 
     34 import com.android.internal.telephony.ISms;
     35 import com.android.internal.telephony.SmsRawData;
     36 import com.android.internal.telephony.IMms;
     37 import com.android.internal.telephony.uicc.IccConstants;
     38 
     39 import java.util.ArrayList;
     40 import java.util.Arrays;
     41 import java.util.List;
     42 import java.util.Map;
     43 
     44 /*
     45  * TODO(code review): Curious question... Why are a lot of these
     46  * methods not declared as static, since they do not seem to require
     47  * any local object state?  Presumably this cannot be changed without
     48  * interfering with the API...
     49  */
     50 
     51 /**
     52  * Manages SMS operations such as sending data, text, and pdu SMS messages.
     53  * Get this object by calling the static method {@link #getDefault()}.
     54  *
     55  * <p>For information about how to behave as the default SMS app on Android 4.4 (API level 19)
     56  * and higher, see {@link android.provider.Telephony}.
     57  */
     58 public final class SmsManager {
     59     private static final String TAG = "SmsManager";
     60     /**
     61      * A psuedo-subId that represents the default subId at any given time. The actual subId it
     62      * represents changes as the default subId is changed.
     63      */
     64     private static final int DEFAULT_SUBSCRIPTION_ID = -1002;
     65 
     66     /** Singleton object constructed during class initialization. */
     67     private static final SmsManager sInstance = new SmsManager(DEFAULT_SUBSCRIPTION_ID);
     68     private static final Object sLockObject = new Object();
     69 
     70     /** @hide */
     71     public static final int CELL_BROADCAST_RAN_TYPE_GSM = 0;
     72     /** @hide */
     73     public static final int CELL_BROADCAST_RAN_TYPE_CDMA = 1;
     74 
     75     private static final Map<Integer, SmsManager> sSubInstances =
     76             new ArrayMap<Integer, SmsManager>();
     77 
     78     /** A concrete subscription id, or the pseudo DEFAULT_SUBSCRIPTION_ID */
     79     private int mSubId;
     80 
     81     /*
     82      * Key for the various carrier-dependent configuration values.
     83      * Some of the values are used by the system in processing SMS or MMS messages. Others
     84      * are provided for the convenience of SMS applications.
     85      */
     86 
     87     /**
     88      * Whether to append transaction id to MMS WAP Push M-Notification.ind's content location URI
     89      * when constructing the download URL of a new MMS (boolean type)
     90      */
     91     public static final String MMS_CONFIG_APPEND_TRANSACTION_ID =
     92             CarrierConfigManager.KEY_MMS_APPEND_TRANSACTION_ID_BOOL;
     93     /**
     94      * Whether MMS is enabled for the current carrier (boolean type)
     95      */
     96     public static final String
     97         MMS_CONFIG_MMS_ENABLED = CarrierConfigManager.KEY_MMS_MMS_ENABLED_BOOL;
     98     /**
     99      * Whether group MMS is enabled for the current carrier (boolean type)
    100      */
    101     public static final String
    102             MMS_CONFIG_GROUP_MMS_ENABLED = CarrierConfigManager.KEY_MMS_GROUP_MMS_ENABLED_BOOL;
    103     /**
    104      * If this is enabled, M-NotifyResp.ind should be sent to the WAP Push content location instead
    105      * of the default MMSC (boolean type)
    106      */
    107     public static final String MMS_CONFIG_NOTIFY_WAP_MMSC_ENABLED =
    108             CarrierConfigManager.KEY_MMS_NOTIFY_WAP_MMSC_ENABLED_BOOL;
    109     /**
    110      * Whether alias is enabled (boolean type)
    111      */
    112     public static final String
    113             MMS_CONFIG_ALIAS_ENABLED = CarrierConfigManager.KEY_MMS_ALIAS_ENABLED_BOOL;
    114     /**
    115      * Whether audio is allowed to be attached for MMS messages (boolean type)
    116      */
    117     public static final String
    118             MMS_CONFIG_ALLOW_ATTACH_AUDIO = CarrierConfigManager.KEY_MMS_ALLOW_ATTACH_AUDIO_BOOL;
    119     /**
    120      * Whether multipart SMS is enabled (boolean type)
    121      */
    122     public static final String MMS_CONFIG_MULTIPART_SMS_ENABLED =
    123             CarrierConfigManager.KEY_MMS_MULTIPART_SMS_ENABLED_BOOL;
    124     /**
    125      * Whether SMS delivery report is enabled (boolean type)
    126      */
    127     public static final String MMS_CONFIG_SMS_DELIVERY_REPORT_ENABLED =
    128             CarrierConfigManager.KEY_MMS_SMS_DELIVERY_REPORT_ENABLED_BOOL;
    129     /**
    130      * Whether content-disposition field should be expected in an MMS PDU (boolean type)
    131      */
    132     public static final String MMS_CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION =
    133             CarrierConfigManager.KEY_MMS_SUPPORT_MMS_CONTENT_DISPOSITION_BOOL;
    134     /**
    135      * Whether multipart SMS should be sent as separate messages
    136      */
    137     public static final String MMS_CONFIG_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES =
    138             CarrierConfigManager.KEY_MMS_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES_BOOL;
    139     /**
    140      * Whether MMS read report is enabled (boolean type)
    141      */
    142     public static final String MMS_CONFIG_MMS_READ_REPORT_ENABLED =
    143             CarrierConfigManager.KEY_MMS_MMS_READ_REPORT_ENABLED_BOOL;
    144     /**
    145      * Whether MMS delivery report is enabled (boolean type)
    146      */
    147     public static final String MMS_CONFIG_MMS_DELIVERY_REPORT_ENABLED =
    148             CarrierConfigManager.KEY_MMS_MMS_DELIVERY_REPORT_ENABLED_BOOL;
    149     /**
    150      * Max MMS message size in bytes (int type)
    151      */
    152     public static final String
    153             MMS_CONFIG_MAX_MESSAGE_SIZE = CarrierConfigManager.KEY_MMS_MAX_MESSAGE_SIZE_INT;
    154     /**
    155      * Max MMS image width (int type)
    156      */
    157     public static final String
    158             MMS_CONFIG_MAX_IMAGE_WIDTH = CarrierConfigManager.KEY_MMS_MAX_IMAGE_WIDTH_INT;
    159     /**
    160      * Max MMS image height (int type)
    161      */
    162     public static final String
    163             MMS_CONFIG_MAX_IMAGE_HEIGHT = CarrierConfigManager.KEY_MMS_MAX_IMAGE_HEIGHT_INT;
    164     /**
    165      * Limit of recipients of MMS messages (int type)
    166      */
    167     public static final String
    168             MMS_CONFIG_RECIPIENT_LIMIT = CarrierConfigManager.KEY_MMS_RECIPIENT_LIMIT_INT;
    169     /**
    170      * Min alias character count (int type)
    171      */
    172     public static final String
    173             MMS_CONFIG_ALIAS_MIN_CHARS = CarrierConfigManager.KEY_MMS_ALIAS_MIN_CHARS_INT;
    174     /**
    175      * Max alias character count (int type)
    176      */
    177     public static final String
    178             MMS_CONFIG_ALIAS_MAX_CHARS = CarrierConfigManager.KEY_MMS_ALIAS_MAX_CHARS_INT;
    179     /**
    180      * When the number of parts of a multipart SMS reaches this threshold, it should be converted
    181      * into an MMS (int type)
    182      */
    183     public static final String MMS_CONFIG_SMS_TO_MMS_TEXT_THRESHOLD =
    184             CarrierConfigManager.KEY_MMS_SMS_TO_MMS_TEXT_THRESHOLD_INT;
    185     /**
    186      * Some carriers require SMS to be converted into MMS when text length reaches this threshold
    187      * (int type)
    188      */
    189     public static final String MMS_CONFIG_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD =
    190             CarrierConfigManager.KEY_MMS_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD_INT;
    191     /**
    192      * Max message text size (int type)
    193      */
    194     public static final String MMS_CONFIG_MESSAGE_TEXT_MAX_SIZE =
    195             CarrierConfigManager.KEY_MMS_MESSAGE_TEXT_MAX_SIZE_INT;
    196     /**
    197      * Max message subject length (int type)
    198      */
    199     public static final String
    200             MMS_CONFIG_SUBJECT_MAX_LENGTH = CarrierConfigManager.KEY_MMS_SUBJECT_MAX_LENGTH_INT;
    201     /**
    202      * MMS HTTP socket timeout in milliseconds (int type)
    203      */
    204     public static final String
    205             MMS_CONFIG_HTTP_SOCKET_TIMEOUT = CarrierConfigManager.KEY_MMS_HTTP_SOCKET_TIMEOUT_INT;
    206     /**
    207      * The name of the UA Prof URL HTTP header for MMS HTTP request (String type)
    208      */
    209     public static final String
    210             MMS_CONFIG_UA_PROF_TAG_NAME = CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING;
    211     /**
    212      * The User-Agent header value for MMS HTTP request (String type)
    213      */
    214     public static final String
    215             MMS_CONFIG_USER_AGENT = CarrierConfigManager.KEY_MMS_USER_AGENT_STRING;
    216     /**
    217      * The UA Profile URL header value for MMS HTTP request (String type)
    218      */
    219     public static final String
    220             MMS_CONFIG_UA_PROF_URL = CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING;
    221     /**
    222      * A list of HTTP headers to add to MMS HTTP request, separated by "|" (String type)
    223      */
    224     public static final String
    225             MMS_CONFIG_HTTP_PARAMS = CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING;
    226     /**
    227      * Email gateway number (String type)
    228      */
    229     public static final String MMS_CONFIG_EMAIL_GATEWAY_NUMBER =
    230             CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING;
    231     /**
    232      * The suffix to append to the NAI header value for MMS HTTP request (String type)
    233      */
    234     public static final String
    235             MMS_CONFIG_NAI_SUFFIX = CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING;
    236     /**
    237      * If true, show the cell broadcast (amber alert) in the SMS settings. Some carriers don't want
    238      * this shown. (Boolean type)
    239      */
    240     public static final String MMS_CONFIG_SHOW_CELL_BROADCAST_APP_LINKS =
    241             CarrierConfigManager.KEY_MMS_SHOW_CELL_BROADCAST_APP_LINKS_BOOL;
    242     /**
    243      * Whether the carrier MMSC supports charset field in Content-Type header. If this is false,
    244      * then we don't add "charset" to "Content-Type"
    245      */
    246     public static final String MMS_CONFIG_SUPPORT_HTTP_CHARSET_HEADER =
    247             CarrierConfigManager.KEY_MMS_SUPPORT_HTTP_CHARSET_HEADER_BOOL;
    248     /*
    249      * Forwarded constants from SimDialogActivity.
    250      */
    251     private static String DIALOG_TYPE_KEY = "dialog_type";
    252     private static final int SMS_PICK = 2;
    253 
    254     /**
    255      * Send a text based SMS.
    256      *
    257      * <p class="note"><strong>Note:</strong> Using this method requires that your app has the
    258      * {@link android.Manifest.permission#SEND_SMS} permission.</p>
    259      *
    260      * <p class="note"><strong>Note:</strong> Beginning with Android 4.4 (API level 19), if
    261      * <em>and only if</em> an app is not selected as the default SMS app, the system automatically
    262      * writes messages sent using this method to the SMS Provider (the default SMS app is always
    263      * responsible for writing its sent messages to the SMS Provider). For information about
    264      * how to behave as the default SMS app, see {@link android.provider.Telephony}.</p>
    265      *
    266      *
    267      * @param destinationAddress the address to send the message to
    268      * @param scAddress is the service center address or null to use
    269      *  the current default SMSC
    270      * @param text the body of the message to send
    271      * @param sentIntent if not NULL this <code>PendingIntent</code> is
    272      *  broadcast when the message is successfully sent, or failed.
    273      *  The result code will be <code>Activity.RESULT_OK</code> for success,
    274      *  or one of these errors:<br>
    275      *  <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
    276      *  <code>RESULT_ERROR_RADIO_OFF</code><br>
    277      *  <code>RESULT_ERROR_NULL_PDU</code><br>
    278      *  For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
    279      *  the extra "errorCode" containing a radio technology specific value,
    280      *  generally only useful for troubleshooting.<br>
    281      *  The per-application based SMS control checks sentIntent. If sentIntent
    282      *  is NULL the caller will be checked against all unknown applications,
    283      *  which cause smaller number of SMS to be sent in checking period.
    284      * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
    285      *  broadcast when the message is delivered to the recipient.  The
    286      *  raw pdu of the status report is in the extended data ("pdu").
    287      *
    288      * @throws IllegalArgumentException if destinationAddress or text are empty
    289      */
    290     public void sendTextMessage(
    291             String destinationAddress, String scAddress, String text,
    292             PendingIntent sentIntent, PendingIntent deliveryIntent) {
    293         sendTextMessageInternal(destinationAddress, scAddress, text,
    294             sentIntent, deliveryIntent, true /* persistMessageForCarrierApp*/);
    295     }
    296 
    297     private void sendTextMessageInternal(String destinationAddress, String scAddress,
    298             String text, PendingIntent sentIntent, PendingIntent deliveryIntent,
    299             boolean persistMessageForCarrierApp) {
    300         if (TextUtils.isEmpty(destinationAddress)) {
    301             throw new IllegalArgumentException("Invalid destinationAddress");
    302         }
    303 
    304         if (TextUtils.isEmpty(text)) {
    305             throw new IllegalArgumentException("Invalid message body");
    306         }
    307 
    308         try {
    309             ISms iccISms = getISmsServiceOrThrow();
    310             iccISms.sendTextForSubscriber(getSubscriptionId(), ActivityThread.currentPackageName(),
    311                     destinationAddress,
    312                     scAddress, text, sentIntent, deliveryIntent,
    313                     persistMessageForCarrierApp);
    314         } catch (RemoteException ex) {
    315             // ignore it
    316         }
    317     }
    318 
    319     /**
    320      * Send a text based SMS without writing it into the SMS Provider.
    321      *
    322      * <p>Only the carrier app can call this method.</p>
    323      *
    324      * @see #sendTextMessage(String, String, String, PendingIntent, PendingIntent)
    325      * @hide
    326      */
    327     public void sendTextMessageWithoutPersisting(
    328             String destinationAddress, String scAddress, String text,
    329             PendingIntent sentIntent, PendingIntent deliveryIntent) {
    330         sendTextMessageInternal(destinationAddress, scAddress, text,
    331             sentIntent, deliveryIntent, false /* persistMessageForCarrierApp*/);
    332     }
    333 
    334     /**
    335      * A variant of {@link SmsManager#sendTextMessage} that allows self to be the caller. This is
    336      * for internal use only.
    337      *
    338      * @hide
    339      */
    340     public void sendTextMessageWithSelfPermissions(
    341             String destinationAddress, String scAddress, String text,
    342             PendingIntent sentIntent, PendingIntent deliveryIntent) {
    343         if (TextUtils.isEmpty(destinationAddress)) {
    344             throw new IllegalArgumentException("Invalid destinationAddress");
    345         }
    346 
    347         if (TextUtils.isEmpty(text)) {
    348             throw new IllegalArgumentException("Invalid message body");
    349         }
    350 
    351         try {
    352             ISms iccISms = getISmsServiceOrThrow();
    353             iccISms.sendTextForSubscriberWithSelfPermissions(getSubscriptionId(),
    354                     ActivityThread.currentPackageName(),
    355                     destinationAddress,
    356                     scAddress, text, sentIntent, deliveryIntent);
    357         } catch (RemoteException ex) {
    358             // ignore it
    359         }
    360     }
    361 
    362     /**
    363      * Inject an SMS PDU into the android application framework.
    364      *
    365      * The caller should have carrier privileges.
    366      * @see android.telephony.TelephonyManager#hasCarrierPrivileges
    367      *
    368      * @param pdu is the byte array of pdu to be injected into android application framework
    369      * @param format is the format of SMS pdu (3gpp or 3gpp2)
    370      * @param receivedIntent if not NULL this <code>PendingIntent</code> is
    371      *  broadcast when the message is successfully received by the
    372      *  android application framework, or failed. This intent is broadcasted at
    373      *  the same time an SMS received from radio is acknowledged back.
    374      *  The result code will be <code>RESULT_SMS_HANDLED</code> for success, or
    375      *  <code>RESULT_SMS_GENERIC_ERROR</code> for error.
    376      *
    377      * @throws IllegalArgumentException if format is not one of 3gpp and 3gpp2.
    378      */
    379     public void injectSmsPdu(byte[] pdu, String format, PendingIntent receivedIntent) {
    380         if (!format.equals(SmsMessage.FORMAT_3GPP) && !format.equals(SmsMessage.FORMAT_3GPP2)) {
    381             // Format must be either 3gpp or 3gpp2.
    382             throw new IllegalArgumentException(
    383                     "Invalid pdu format. format must be either 3gpp or 3gpp2");
    384         }
    385         try {
    386             ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
    387             if (iccISms != null) {
    388                 iccISms.injectSmsPduForSubscriber(
    389                         getSubscriptionId(), pdu, format, receivedIntent);
    390             }
    391         } catch (RemoteException ex) {
    392           // ignore it
    393         }
    394     }
    395 
    396     /**
    397      * Divide a message text into several fragments, none bigger than
    398      * the maximum SMS message size.
    399      *
    400      * @param text the original message.  Must not be null.
    401      * @return an <code>ArrayList</code> of strings that, in order,
    402      *   comprise the original message
    403      *
    404      * @throws IllegalArgumentException if text is null
    405      */
    406     public ArrayList<String> divideMessage(String text) {
    407         if (null == text) {
    408             throw new IllegalArgumentException("text is null");
    409         }
    410         return SmsMessage.fragmentText(text);
    411     }
    412 
    413     /**
    414      * Send a multi-part text based SMS.  The callee should have already
    415      * divided the message into correctly sized parts by calling
    416      * <code>divideMessage</code>.
    417      *
    418      * <p class="note"><strong>Note:</strong> Using this method requires that your app has the
    419      * {@link android.Manifest.permission#SEND_SMS} permission.</p>
    420      *
    421      * <p class="note"><strong>Note:</strong> Beginning with Android 4.4 (API level 19), if
    422      * <em>and only if</em> an app is not selected as the default SMS app, the system automatically
    423      * writes messages sent using this method to the SMS Provider (the default SMS app is always
    424      * responsible for writing its sent messages to the SMS Provider). For information about
    425      * how to behave as the default SMS app, see {@link android.provider.Telephony}.</p>
    426      *
    427      * @param destinationAddress the address to send the message to
    428      * @param scAddress is the service center address or null to use
    429      *   the current default SMSC
    430      * @param parts an <code>ArrayList</code> of strings that, in order,
    431      *   comprise the original message
    432      * @param sentIntents if not null, an <code>ArrayList</code> of
    433      *   <code>PendingIntent</code>s (one for each message part) that is
    434      *   broadcast when the corresponding message part has been sent.
    435      *   The result code will be <code>Activity.RESULT_OK</code> for success,
    436      *   or one of these errors:<br>
    437      *   <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
    438      *   <code>RESULT_ERROR_RADIO_OFF</code><br>
    439      *   <code>RESULT_ERROR_NULL_PDU</code><br>
    440      *   For <code>RESULT_ERROR_GENERIC_FAILURE</code> each sentIntent may include
    441      *   the extra "errorCode" containing a radio technology specific value,
    442      *   generally only useful for troubleshooting.<br>
    443      *   The per-application based SMS control checks sentIntent. If sentIntent
    444      *   is NULL the caller will be checked against all unknown applications,
    445      *   which cause smaller number of SMS to be sent in checking period.
    446      * @param deliveryIntents if not null, an <code>ArrayList</code> of
    447      *   <code>PendingIntent</code>s (one for each message part) that is
    448      *   broadcast when the corresponding message part has been delivered
    449      *   to the recipient.  The raw pdu of the status report is in the
    450      *   extended data ("pdu").
    451      *
    452      * @throws IllegalArgumentException if destinationAddress or data are empty
    453      */
    454     public void sendMultipartTextMessage(
    455             String destinationAddress, String scAddress, ArrayList<String> parts,
    456             ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) {
    457         sendMultipartTextMessageInternal(destinationAddress, scAddress, parts,
    458               sentIntents, deliveryIntents, true /* persistMessageForCarrierApp*/);
    459     }
    460 
    461     private void sendMultipartTextMessageInternal(
    462             String destinationAddress, String scAddress, ArrayList<String> parts,
    463             ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents,
    464             boolean persistMessageForCarrierApp) {
    465         if (TextUtils.isEmpty(destinationAddress)) {
    466             throw new IllegalArgumentException("Invalid destinationAddress");
    467         }
    468         if (parts == null || parts.size() < 1) {
    469             throw new IllegalArgumentException("Invalid message body");
    470         }
    471 
    472         if (parts.size() > 1) {
    473             try {
    474                 ISms iccISms = getISmsServiceOrThrow();
    475                 iccISms.sendMultipartTextForSubscriber(getSubscriptionId(),
    476                         ActivityThread.currentPackageName(),
    477                         destinationAddress, scAddress, parts,
    478                         sentIntents, deliveryIntents, persistMessageForCarrierApp);
    479             } catch (RemoteException ex) {
    480                 // ignore it
    481             }
    482         } else {
    483             PendingIntent sentIntent = null;
    484             PendingIntent deliveryIntent = null;
    485             if (sentIntents != null && sentIntents.size() > 0) {
    486                 sentIntent = sentIntents.get(0);
    487             }
    488             if (deliveryIntents != null && deliveryIntents.size() > 0) {
    489                 deliveryIntent = deliveryIntents.get(0);
    490             }
    491             sendTextMessage(destinationAddress, scAddress, parts.get(0),
    492                     sentIntent, deliveryIntent);
    493         }
    494     }
    495 
    496     /**
    497      * Send a multi-part text based SMS without writing it into the SMS Provider.
    498      *
    499      * <p>Only the carrier app can call this method.</p>
    500      *
    501      * @see #sendMultipartTextMessage(String, String, ArrayList, ArrayList, ArrayList)
    502      * @hide
    503      **/
    504     public void sendMultipartTextMessageWithoutPersisting(
    505             String destinationAddress, String scAddress, ArrayList<String> parts,
    506             ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) {
    507         sendMultipartTextMessageInternal(destinationAddress, scAddress, parts,
    508             sentIntents, deliveryIntents, false /* persistMessageForCarrierApp*/);
    509     }
    510 
    511     /**
    512      * Send a data based SMS to a specific application port.
    513      *
    514      * <p class="note"><strong>Note:</strong> Using this method requires that your app has the
    515      * {@link android.Manifest.permission#SEND_SMS} permission.</p>
    516      *
    517      * @param destinationAddress the address to send the message to
    518      * @param scAddress is the service center address or null to use
    519      *  the current default SMSC
    520      * @param destinationPort the port to deliver the message to
    521      * @param data the body of the message to send
    522      * @param sentIntent if not NULL this <code>PendingIntent</code> is
    523      *  broadcast when the message is successfully sent, or failed.
    524      *  The result code will be <code>Activity.RESULT_OK</code> for success,
    525      *  or one of these errors:<br>
    526      *  <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
    527      *  <code>RESULT_ERROR_RADIO_OFF</code><br>
    528      *  <code>RESULT_ERROR_NULL_PDU</code><br>
    529      *  For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
    530      *  the extra "errorCode" containing a radio technology specific value,
    531      *  generally only useful for troubleshooting.<br>
    532      *  The per-application based SMS control checks sentIntent. If sentIntent
    533      *  is NULL the caller will be checked against all unknown applications,
    534      *  which cause smaller number of SMS to be sent in checking period.
    535      * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
    536      *  broadcast when the message is delivered to the recipient.  The
    537      *  raw pdu of the status report is in the extended data ("pdu").
    538      *
    539      * @throws IllegalArgumentException if destinationAddress or data are empty
    540      */
    541     public void sendDataMessage(
    542             String destinationAddress, String scAddress, short destinationPort,
    543             byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
    544         if (TextUtils.isEmpty(destinationAddress)) {
    545             throw new IllegalArgumentException("Invalid destinationAddress");
    546         }
    547 
    548         if (data == null || data.length == 0) {
    549             throw new IllegalArgumentException("Invalid message data");
    550         }
    551 
    552         try {
    553             ISms iccISms = getISmsServiceOrThrow();
    554             iccISms.sendDataForSubscriber(getSubscriptionId(), ActivityThread.currentPackageName(),
    555                     destinationAddress, scAddress, destinationPort & 0xFFFF,
    556                     data, sentIntent, deliveryIntent);
    557         } catch (RemoteException ex) {
    558             // ignore it
    559         }
    560     }
    561 
    562     /**
    563      * A variant of {@link SmsManager#sendDataMessage} that allows self to be the caller. This is
    564      * for internal use only.
    565      *
    566      * @hide
    567      */
    568     public void sendDataMessageWithSelfPermissions(
    569             String destinationAddress, String scAddress, short destinationPort,
    570             byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
    571         if (TextUtils.isEmpty(destinationAddress)) {
    572             throw new IllegalArgumentException("Invalid destinationAddress");
    573         }
    574 
    575         if (data == null || data.length == 0) {
    576             throw new IllegalArgumentException("Invalid message data");
    577         }
    578 
    579         try {
    580             ISms iccISms = getISmsServiceOrThrow();
    581             iccISms.sendDataForSubscriberWithSelfPermissions(getSubscriptionId(),
    582                     ActivityThread.currentPackageName(), destinationAddress, scAddress,
    583                     destinationPort & 0xFFFF, data, sentIntent, deliveryIntent);
    584         } catch (RemoteException ex) {
    585             // ignore it
    586         }
    587     }
    588 
    589 
    590 
    591     /**
    592      * Get the SmsManager associated with the default subscription id. The instance will always be
    593      * associated with the default subscription id, even if the default subscription id is changed.
    594      *
    595      * @return the SmsManager associated with the default subscription id
    596      */
    597     public static SmsManager getDefault() {
    598         return sInstance;
    599     }
    600 
    601     /**
    602      * Get the the instance of the SmsManager associated with a particular subscription id
    603      *
    604      * @param subId an SMS subscription id, typically accessed using
    605      *   {@link android.telephony.SubscriptionManager}
    606      * @return the instance of the SmsManager associated with subId
    607      */
    608     public static SmsManager getSmsManagerForSubscriptionId(int subId) {
    609         // TODO(shri): Add javadoc link once SubscriptionManager is made public api
    610         synchronized(sLockObject) {
    611             SmsManager smsManager = sSubInstances.get(subId);
    612             if (smsManager == null) {
    613                 smsManager = new SmsManager(subId);
    614                 sSubInstances.put(subId, smsManager);
    615             }
    616             return smsManager;
    617         }
    618     }
    619 
    620     private SmsManager(int subId) {
    621         mSubId = subId;
    622     }
    623 
    624     /**
    625      * Get the associated subscription id. If the instance was returned by {@link #getDefault()},
    626      * then this method may return different values at different points in time (if the user
    627      * changes the default subscription id). It will return < 0 if the default subscription id
    628      * cannot be determined.
    629      *
    630      * Additionally, to support legacy applications that are not multi-SIM aware,
    631      * if the following are true:
    632      *     - We are using a multi-SIM device
    633      *     - A default SMS SIM has not been selected
    634      *     - At least one SIM subscription is available
    635      * then ask the user to set the default SMS SIM.
    636      *
    637      * @return associated subscription id
    638      */
    639     public int getSubscriptionId() {
    640         final int subId = (mSubId == DEFAULT_SUBSCRIPTION_ID)
    641                 ? getDefaultSmsSubscriptionId() : mSubId;
    642         boolean isSmsSimPickActivityNeeded = false;
    643         final Context context = ActivityThread.currentApplication().getApplicationContext();
    644         try {
    645             ISms iccISms = getISmsService();
    646             if (iccISms != null) {
    647                 isSmsSimPickActivityNeeded = iccISms.isSmsSimPickActivityNeeded(subId);
    648             }
    649         } catch (RemoteException ex) {
    650             Log.e(TAG, "Exception in getSubscriptionId");
    651         }
    652 
    653         if (isSmsSimPickActivityNeeded) {
    654             Log.d(TAG, "getSubscriptionId isSmsSimPickActivityNeeded is true");
    655             // ask the user for a default SMS SIM.
    656             Intent intent = new Intent();
    657             intent.setClassName("com.android.settings",
    658                     "com.android.settings.sim.SimDialogActivity");
    659             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    660             intent.putExtra(DIALOG_TYPE_KEY, SMS_PICK);
    661             try {
    662                 context.startActivity(intent);
    663             } catch (ActivityNotFoundException anfe) {
    664                 // If Settings is not installed, only log the error as we do not want to break
    665                 // legacy applications.
    666                 Log.e(TAG, "Unable to launch Settings application.");
    667             }
    668         }
    669 
    670         return subId;
    671     }
    672 
    673     /**
    674      * Returns the ISms service, or throws an UnsupportedOperationException if
    675      * the service does not exist.
    676      */
    677     private static ISms getISmsServiceOrThrow() {
    678         ISms iccISms = getISmsService();
    679         if (iccISms == null) {
    680             throw new UnsupportedOperationException("Sms is not supported");
    681         }
    682         return iccISms;
    683     }
    684 
    685     private static ISms getISmsService() {
    686         return ISms.Stub.asInterface(ServiceManager.getService("isms"));
    687     }
    688 
    689     /**
    690      * Copy a raw SMS PDU to the ICC.
    691      * ICC (Integrated Circuit Card) is the card of the device.
    692      * For example, this can be the SIM or USIM for GSM.
    693      *
    694      * @param smsc the SMSC for this message, or NULL for the default SMSC
    695      * @param pdu the raw PDU to store
    696      * @param status message status (STATUS_ON_ICC_READ, STATUS_ON_ICC_UNREAD,
    697      *               STATUS_ON_ICC_SENT, STATUS_ON_ICC_UNSENT)
    698      * @return true for success
    699      *
    700      * @throws IllegalArgumentException if pdu is NULL
    701      * {@hide}
    702      */
    703     public boolean copyMessageToIcc(byte[] smsc, byte[] pdu,int status) {
    704         boolean success = false;
    705 
    706         if (null == pdu) {
    707             throw new IllegalArgumentException("pdu is NULL");
    708         }
    709         try {
    710             ISms iccISms = getISmsService();
    711             if (iccISms != null) {
    712                 success = iccISms.copyMessageToIccEfForSubscriber(getSubscriptionId(),
    713                         ActivityThread.currentPackageName(),
    714                         status, pdu, smsc);
    715             }
    716         } catch (RemoteException ex) {
    717             // ignore it
    718         }
    719 
    720         return success;
    721     }
    722 
    723     /**
    724      * Delete the specified message from the ICC.
    725      * ICC (Integrated Circuit Card) is the card of the device.
    726      * For example, this can be the SIM or USIM for GSM.
    727      *
    728      * @param messageIndex is the record index of the message on ICC
    729      * @return true for success
    730      *
    731      * {@hide}
    732      */
    733     public boolean
    734     deleteMessageFromIcc(int messageIndex) {
    735         boolean success = false;
    736         byte[] pdu = new byte[IccConstants.SMS_RECORD_LENGTH-1];
    737         Arrays.fill(pdu, (byte)0xff);
    738 
    739         try {
    740             ISms iccISms = getISmsService();
    741             if (iccISms != null) {
    742                 success = iccISms.updateMessageOnIccEfForSubscriber(getSubscriptionId(),
    743                         ActivityThread.currentPackageName(),
    744                         messageIndex, STATUS_ON_ICC_FREE, pdu);
    745             }
    746         } catch (RemoteException ex) {
    747             // ignore it
    748         }
    749 
    750         return success;
    751     }
    752 
    753     /**
    754      * Update the specified message on the ICC.
    755      * ICC (Integrated Circuit Card) is the card of the device.
    756      * For example, this can be the SIM or USIM for GSM.
    757      *
    758      * @param messageIndex record index of message to update
    759      * @param newStatus new message status (STATUS_ON_ICC_READ,
    760      *                  STATUS_ON_ICC_UNREAD, STATUS_ON_ICC_SENT,
    761      *                  STATUS_ON_ICC_UNSENT, STATUS_ON_ICC_FREE)
    762      * @param pdu the raw PDU to store
    763      * @return true for success
    764      *
    765      * {@hide}
    766      */
    767     public boolean updateMessageOnIcc(int messageIndex, int newStatus, byte[] pdu) {
    768         boolean success = false;
    769 
    770         try {
    771             ISms iccISms = getISmsService();
    772             if (iccISms != null) {
    773                 success = iccISms.updateMessageOnIccEfForSubscriber(getSubscriptionId(),
    774                         ActivityThread.currentPackageName(),
    775                         messageIndex, newStatus, pdu);
    776             }
    777         } catch (RemoteException ex) {
    778             // ignore it
    779         }
    780 
    781         return success;
    782     }
    783 
    784     /**
    785      * Retrieves all messages currently stored on ICC.
    786      * ICC (Integrated Circuit Card) is the card of the device.
    787      * For example, this can be the SIM or USIM for GSM.
    788      *
    789      * @return <code>ArrayList</code> of <code>SmsMessage</code> objects
    790      *
    791      * {@hide}
    792      */
    793     public ArrayList<SmsMessage> getAllMessagesFromIcc() {
    794         List<SmsRawData> records = null;
    795 
    796         try {
    797             ISms iccISms = getISmsService();
    798             if (iccISms != null) {
    799                 records = iccISms.getAllMessagesFromIccEfForSubscriber(
    800                         getSubscriptionId(),
    801                         ActivityThread.currentPackageName());
    802             }
    803         } catch (RemoteException ex) {
    804             // ignore it
    805         }
    806 
    807         return createMessageListFromRawRecords(records);
    808     }
    809 
    810     /**
    811      * Enable reception of cell broadcast (SMS-CB) messages with the given
    812      * message identifier and RAN type. The RAN type specify this message ID
    813      * belong to 3GPP (GSM) or 3GPP2(CDMA).Note that if two different clients
    814      * enable the same message identifier, they must both disable it for the device to stop
    815      * receiving those messages. All received messages will be broadcast in an
    816      * intent with the action "android.provider.Telephony.SMS_CB_RECEIVED".
    817      * Note: This call is blocking, callers may want to avoid calling it from
    818      * the main thread of an application.
    819      *
    820      * @param messageIdentifier Message identifier as specified in TS 23.041 (3GPP)
    821      * or C.R1001-G (3GPP2)
    822      * @param ranType as defined in class SmsManager, the value can be one of these:
    823      *    android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_GSM
    824      *    android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_CDMA
    825      * @return true if successful, false otherwise
    826      * @see #disableCellBroadcast(int, int)
    827      *
    828      * {@hide}
    829      */
    830     public boolean enableCellBroadcast(int messageIdentifier, int ranType) {
    831         boolean success = false;
    832 
    833         try {
    834             ISms iccISms = getISmsService();
    835             if (iccISms != null) {
    836                 success = iccISms.enableCellBroadcastForSubscriber(
    837                         getSubscriptionId(), messageIdentifier, ranType);
    838             }
    839         } catch (RemoteException ex) {
    840             // ignore it
    841         }
    842 
    843         return success;
    844     }
    845 
    846     /**
    847      * Disable reception of cell broadcast (SMS-CB) messages with the given
    848      * message identifier and RAN type. The RAN type specify this message ID
    849      * belong to 3GPP (GSM) or 3GPP2(CDMA). Note that if two different clients
    850      * enable the same message identifier, they must both disable it for the
    851      * device to stop receiving those messages.
    852      * Note: This call is blocking, callers may want to avoid calling it from
    853      * the main thread of an application.
    854      *
    855      * @param messageIdentifier Message identifier as specified in TS 23.041 (3GPP)
    856      * or C.R1001-G (3GPP2)
    857      * @param ranType as defined in class SmsManager, the value can be one of these:
    858      *    android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_GSM
    859      *    android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_CDMA
    860      * @return true if successful, false otherwise
    861      *
    862      * @see #enableCellBroadcast(int, int)
    863      *
    864      * {@hide}
    865      */
    866     public boolean disableCellBroadcast(int messageIdentifier, int ranType) {
    867         boolean success = false;
    868 
    869         try {
    870             ISms iccISms = getISmsService();
    871             if (iccISms != null) {
    872                 success = iccISms.disableCellBroadcastForSubscriber(
    873                         getSubscriptionId(), messageIdentifier, ranType);
    874             }
    875         } catch (RemoteException ex) {
    876             // ignore it
    877         }
    878 
    879         return success;
    880     }
    881 
    882     /**
    883      * Enable reception of cell broadcast (SMS-CB) messages with the given
    884      * message identifier range and RAN type. The RAN type specify this message ID
    885      * belong to 3GPP (GSM) or 3GPP2(CDMA). Note that if two different clients enable
    886      * the same message identifier, they must both disable it for the device to stop
    887      * receiving those messages. All received messages will be broadcast in an
    888      * intent with the action "android.provider.Telephony.SMS_CB_RECEIVED".
    889      * Note: This call is blocking, callers may want to avoid calling it from
    890      * the main thread of an application.
    891      *
    892      * @param startMessageId first message identifier as specified in TS 23.041 (3GPP)
    893      * or C.R1001-G (3GPP2)
    894      * @param endMessageId last message identifier as specified in TS 23.041 (3GPP)
    895      * or C.R1001-G (3GPP2)
    896      * @param ranType as defined in class SmsManager, the value can be one of these:
    897      *    android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_GSM
    898      *    android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_CDMA
    899      * @return true if successful, false otherwise
    900      * @see #disableCellBroadcastRange(int, int, int)
    901      *
    902      * @throws IllegalArgumentException if endMessageId < startMessageId
    903      * {@hide}
    904      */
    905     public boolean enableCellBroadcastRange(int startMessageId, int endMessageId, int ranType) {
    906         boolean success = false;
    907 
    908         if (endMessageId < startMessageId) {
    909             throw new IllegalArgumentException("endMessageId < startMessageId");
    910         }
    911         try {
    912             ISms iccISms = getISmsService();
    913             if (iccISms != null) {
    914                 success = iccISms.enableCellBroadcastRangeForSubscriber(getSubscriptionId(),
    915                         startMessageId, endMessageId, ranType);
    916             }
    917         } catch (RemoteException ex) {
    918             // ignore it
    919         }
    920 
    921         return success;
    922     }
    923 
    924     /**
    925      * Disable reception of cell broadcast (SMS-CB) messages with the given
    926      * message identifier range and RAN type. The RAN type specify this message
    927      * ID range belong to 3GPP (GSM) or 3GPP2(CDMA). Note that if two different
    928      * clients enable the same message identifier, they must both disable it for
    929      * the device to stop receiving those messages.
    930      * Note: This call is blocking, callers may want to avoid calling it from
    931      * the main thread of an application.
    932      *
    933      * @param startMessageId first message identifier as specified in TS 23.041 (3GPP)
    934      * or C.R1001-G (3GPP2)
    935      * @param endMessageId last message identifier as specified in TS 23.041 (3GPP)
    936      * or C.R1001-G (3GPP2)
    937      * @param ranType as defined in class SmsManager, the value can be one of these:
    938      *    android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_GSM
    939      *    android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_CDMA
    940      * @return true if successful, false otherwise
    941      *
    942      * @see #enableCellBroadcastRange(int, int, int)
    943      *
    944      * @throws IllegalArgumentException if endMessageId < startMessageId
    945      * {@hide}
    946      */
    947     public boolean disableCellBroadcastRange(int startMessageId, int endMessageId, int ranType) {
    948         boolean success = false;
    949 
    950         if (endMessageId < startMessageId) {
    951             throw new IllegalArgumentException("endMessageId < startMessageId");
    952         }
    953         try {
    954             ISms iccISms = getISmsService();
    955             if (iccISms != null) {
    956                 success = iccISms.disableCellBroadcastRangeForSubscriber(getSubscriptionId(),
    957                         startMessageId, endMessageId, ranType);
    958             }
    959         } catch (RemoteException ex) {
    960             // ignore it
    961         }
    962 
    963         return success;
    964     }
    965 
    966     /**
    967      * Create a list of <code>SmsMessage</code>s from a list of RawSmsData
    968      * records returned by <code>getAllMessagesFromIcc()</code>
    969      *
    970      * @param records SMS EF records, returned by
    971      *   <code>getAllMessagesFromIcc</code>
    972      * @return <code>ArrayList</code> of <code>SmsMessage</code> objects.
    973      */
    974     private static ArrayList<SmsMessage> createMessageListFromRawRecords(List<SmsRawData> records) {
    975         ArrayList<SmsMessage> messages = new ArrayList<SmsMessage>();
    976         if (records != null) {
    977             int count = records.size();
    978             for (int i = 0; i < count; i++) {
    979                 SmsRawData data = records.get(i);
    980                 // List contains all records, including "free" records (null)
    981                 if (data != null) {
    982                     SmsMessage sms = SmsMessage.createFromEfRecord(i+1, data.getBytes());
    983                     if (sms != null) {
    984                         messages.add(sms);
    985                     }
    986                 }
    987             }
    988         }
    989         return messages;
    990     }
    991 
    992     /**
    993      * SMS over IMS is supported if IMS is registered and SMS is supported
    994      * on IMS.
    995      *
    996      * @return true if SMS over IMS is supported, false otherwise
    997      *
    998      * @see #getImsSmsFormat()
    999      *
   1000      * @hide
   1001      */
   1002     public boolean isImsSmsSupported() {
   1003         boolean boSupported = false;
   1004         try {
   1005             ISms iccISms = getISmsService();
   1006             if (iccISms != null) {
   1007                 boSupported = iccISms.isImsSmsSupportedForSubscriber(getSubscriptionId());
   1008             }
   1009         } catch (RemoteException ex) {
   1010             // ignore it
   1011         }
   1012         return boSupported;
   1013     }
   1014 
   1015     /**
   1016      * Gets SMS format supported on IMS.  SMS over IMS format is
   1017      * either 3GPP or 3GPP2.
   1018      *
   1019      * @return SmsMessage.FORMAT_3GPP,
   1020      *         SmsMessage.FORMAT_3GPP2
   1021      *      or SmsMessage.FORMAT_UNKNOWN
   1022      *
   1023      * @see #isImsSmsSupported()
   1024      *
   1025      * @hide
   1026      */
   1027     public String getImsSmsFormat() {
   1028         String format = com.android.internal.telephony.SmsConstants.FORMAT_UNKNOWN;
   1029         try {
   1030             ISms iccISms = getISmsService();
   1031             if (iccISms != null) {
   1032                 format = iccISms.getImsSmsFormatForSubscriber(getSubscriptionId());
   1033             }
   1034         } catch (RemoteException ex) {
   1035             // ignore it
   1036         }
   1037         return format;
   1038     }
   1039 
   1040     /**
   1041      * Get default sms subscription id
   1042      *
   1043      * @return the default SMS subscription id
   1044      */
   1045     public static int getDefaultSmsSubscriptionId() {
   1046         ISms iccISms = null;
   1047         try {
   1048             iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
   1049             return iccISms.getPreferredSmsSubscription();
   1050         } catch (RemoteException ex) {
   1051             return -1;
   1052         } catch (NullPointerException ex) {
   1053             return -1;
   1054         }
   1055     }
   1056 
   1057     /**
   1058      * Get SMS prompt property,  enabled or not
   1059      *
   1060      * @return true if enabled, false otherwise
   1061      * @hide
   1062      */
   1063     public boolean isSMSPromptEnabled() {
   1064         ISms iccISms = null;
   1065         try {
   1066             iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
   1067             return iccISms.isSMSPromptEnabled();
   1068         } catch (RemoteException ex) {
   1069             return false;
   1070         } catch (NullPointerException ex) {
   1071             return false;
   1072         }
   1073     }
   1074 
   1075     // see SmsMessage.getStatusOnIcc
   1076 
   1077     /** Free space (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */
   1078     static public final int STATUS_ON_ICC_FREE      = 0;
   1079 
   1080     /** Received and read (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */
   1081     static public final int STATUS_ON_ICC_READ      = 1;
   1082 
   1083     /** Received and unread (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */
   1084     static public final int STATUS_ON_ICC_UNREAD    = 3;
   1085 
   1086     /** Stored and sent (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */
   1087     static public final int STATUS_ON_ICC_SENT      = 5;
   1088 
   1089     /** Stored and unsent (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */
   1090     static public final int STATUS_ON_ICC_UNSENT    = 7;
   1091 
   1092     // SMS send failure result codes
   1093 
   1094     /** Generic failure cause */
   1095     static public final int RESULT_ERROR_GENERIC_FAILURE    = 1;
   1096     /** Failed because radio was explicitly turned off */
   1097     static public final int RESULT_ERROR_RADIO_OFF          = 2;
   1098     /** Failed because no pdu provided */
   1099     static public final int RESULT_ERROR_NULL_PDU           = 3;
   1100     /** Failed because service is currently unavailable */
   1101     static public final int RESULT_ERROR_NO_SERVICE         = 4;
   1102     /** Failed because we reached the sending queue limit.  {@hide} */
   1103     static public final int RESULT_ERROR_LIMIT_EXCEEDED     = 5;
   1104     /** Failed because FDN is enabled. {@hide} */
   1105     static public final int RESULT_ERROR_FDN_CHECK_FAILURE  = 6;
   1106 
   1107     static private final String PHONE_PACKAGE_NAME = "com.android.phone";
   1108 
   1109     /**
   1110      * Send an MMS message
   1111      *
   1112      * @param context application context
   1113      * @param contentUri the content Uri from which the message pdu will be read
   1114      * @param locationUrl the optional location url where message should be sent to
   1115      * @param configOverrides the carrier-specific messaging configuration values to override for
   1116      *  sending the message.
   1117      * @param sentIntent if not NULL this <code>PendingIntent</code> is
   1118      *  broadcast when the message is successfully sent, or failed
   1119      * @throws IllegalArgumentException if contentUri is empty
   1120      */
   1121     public void sendMultimediaMessage(Context context, Uri contentUri, String locationUrl,
   1122             Bundle configOverrides, PendingIntent sentIntent) {
   1123         if (contentUri == null) {
   1124             throw new IllegalArgumentException("Uri contentUri null");
   1125         }
   1126         try {
   1127             final IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms"));
   1128             if (iMms == null) {
   1129                 return;
   1130             }
   1131 
   1132             iMms.sendMessage(getSubscriptionId(), ActivityThread.currentPackageName(), contentUri,
   1133                     locationUrl, configOverrides, sentIntent);
   1134         } catch (RemoteException e) {
   1135             // Ignore it
   1136         }
   1137     }
   1138 
   1139     /**
   1140      * Download an MMS message from carrier by a given location URL
   1141      *
   1142      * @param context application context
   1143      * @param locationUrl the location URL of the MMS message to be downloaded, usually obtained
   1144      *  from the MMS WAP push notification
   1145      * @param contentUri the content uri to which the downloaded pdu will be written
   1146      * @param configOverrides the carrier-specific messaging configuration values to override for
   1147      *  downloading the message.
   1148      * @param downloadedIntent if not NULL this <code>PendingIntent</code> is
   1149      *  broadcast when the message is downloaded, or the download is failed
   1150      * @throws IllegalArgumentException if locationUrl or contentUri is empty
   1151      */
   1152     public void downloadMultimediaMessage(Context context, String locationUrl, Uri contentUri,
   1153             Bundle configOverrides, PendingIntent downloadedIntent) {
   1154         if (TextUtils.isEmpty(locationUrl)) {
   1155             throw new IllegalArgumentException("Empty MMS location URL");
   1156         }
   1157         if (contentUri == null) {
   1158             throw new IllegalArgumentException("Uri contentUri null");
   1159         }
   1160         try {
   1161             final IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms"));
   1162             if (iMms == null) {
   1163                 return;
   1164             }
   1165             iMms.downloadMessage(
   1166                     getSubscriptionId(), ActivityThread.currentPackageName(), locationUrl,
   1167                     contentUri, configOverrides, downloadedIntent);
   1168         } catch (RemoteException e) {
   1169             // Ignore it
   1170         }
   1171     }
   1172 
   1173     // MMS send/download failure result codes
   1174     public static final int MMS_ERROR_UNSPECIFIED = 1;
   1175     public static final int MMS_ERROR_INVALID_APN = 2;
   1176     public static final int MMS_ERROR_UNABLE_CONNECT_MMS = 3;
   1177     public static final int MMS_ERROR_HTTP_FAILURE = 4;
   1178     public static final int MMS_ERROR_IO_ERROR = 5;
   1179     public static final int MMS_ERROR_RETRY = 6;
   1180     public static final int MMS_ERROR_CONFIGURATION_ERROR = 7;
   1181     public static final int MMS_ERROR_NO_DATA_NETWORK = 8;
   1182 
   1183     /** Intent extra name for MMS sending result data in byte array type */
   1184     public static final String EXTRA_MMS_DATA = "android.telephony.extra.MMS_DATA";
   1185     /** Intent extra name for HTTP status code for MMS HTTP failure in integer type */
   1186     public static final String EXTRA_MMS_HTTP_STATUS = "android.telephony.extra.MMS_HTTP_STATUS";
   1187 
   1188     /**
   1189      * Import a text message into system's SMS store
   1190      *
   1191      * Only default SMS apps can import SMS
   1192      *
   1193      * @param address the destination(source) address of the sent(received) message
   1194      * @param type the type of the message
   1195      * @param text the message text
   1196      * @param timestampMillis the message timestamp in milliseconds
   1197      * @param seen if the message is seen
   1198      * @param read if the message is read
   1199      * @return the message URI, null if failed
   1200      * @hide
   1201      */
   1202     public Uri importTextMessage(String address, int type, String text, long timestampMillis,
   1203             boolean seen, boolean read) {
   1204         try {
   1205             IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms"));
   1206             if (iMms != null) {
   1207                 return iMms.importTextMessage(ActivityThread.currentPackageName(),
   1208                         address, type, text, timestampMillis, seen, read);
   1209             }
   1210         } catch (RemoteException ex) {
   1211             // ignore it
   1212         }
   1213         return null;
   1214     }
   1215 
   1216     /** Represents the received SMS message for importing {@hide} */
   1217     public static final int SMS_TYPE_INCOMING = 0;
   1218     /** Represents the sent SMS message for importing {@hide} */
   1219     public static final int SMS_TYPE_OUTGOING = 1;
   1220 
   1221     /**
   1222      * Import a multimedia message into system's MMS store. Only the following PDU type is
   1223      * supported: Retrieve.conf, Send.req, Notification.ind, Delivery.ind, Read-Orig.ind
   1224      *
   1225      * Only default SMS apps can import MMS
   1226      *
   1227      * @param contentUri the content uri from which to read the PDU of the message to import
   1228      * @param messageId the optional message id. Use null if not specifying
   1229      * @param timestampSecs the optional message timestamp. Use -1 if not specifying
   1230      * @param seen if the message is seen
   1231      * @param read if the message is read
   1232      * @return the message URI, null if failed
   1233      * @throws IllegalArgumentException if pdu is empty
   1234      * {@hide}
   1235      */
   1236     public Uri importMultimediaMessage(Uri contentUri, String messageId, long timestampSecs,
   1237             boolean seen, boolean read) {
   1238         if (contentUri == null) {
   1239             throw new IllegalArgumentException("Uri contentUri null");
   1240         }
   1241         try {
   1242             IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms"));
   1243             if (iMms != null) {
   1244                 return iMms.importMultimediaMessage(ActivityThread.currentPackageName(),
   1245                         contentUri, messageId, timestampSecs, seen, read);
   1246             }
   1247         } catch (RemoteException ex) {
   1248             // ignore it
   1249         }
   1250         return null;
   1251     }
   1252 
   1253     /**
   1254      * Delete a system stored SMS or MMS message
   1255      *
   1256      * Only default SMS apps can delete system stored SMS and MMS messages
   1257      *
   1258      * @param messageUri the URI of the stored message
   1259      * @return true if deletion is successful, false otherwise
   1260      * @throws IllegalArgumentException if messageUri is empty
   1261      * {@hide}
   1262      */
   1263     public boolean deleteStoredMessage(Uri messageUri) {
   1264         if (messageUri == null) {
   1265             throw new IllegalArgumentException("Empty message URI");
   1266         }
   1267         try {
   1268             IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms"));
   1269             if (iMms != null) {
   1270                 return iMms.deleteStoredMessage(ActivityThread.currentPackageName(), messageUri);
   1271             }
   1272         } catch (RemoteException ex) {
   1273             // ignore it
   1274         }
   1275         return false;
   1276     }
   1277 
   1278     /**
   1279      * Delete a system stored SMS or MMS thread
   1280      *
   1281      * Only default SMS apps can delete system stored SMS and MMS conversations
   1282      *
   1283      * @param conversationId the ID of the message conversation
   1284      * @return true if deletion is successful, false otherwise
   1285      * {@hide}
   1286      */
   1287     public boolean deleteStoredConversation(long conversationId) {
   1288         try {
   1289             IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms"));
   1290             if (iMms != null) {
   1291                 return iMms.deleteStoredConversation(
   1292                         ActivityThread.currentPackageName(), conversationId);
   1293             }
   1294         } catch (RemoteException ex) {
   1295             // ignore it
   1296         }
   1297         return false;
   1298     }
   1299 
   1300     /**
   1301      * Update the status properties of a system stored SMS or MMS message, e.g.
   1302      * the read status of a message, etc.
   1303      *
   1304      * @param messageUri the URI of the stored message
   1305      * @param statusValues a list of status properties in key-value pairs to update
   1306      * @return true if update is successful, false otherwise
   1307      * @throws IllegalArgumentException if messageUri is empty
   1308      * {@hide}
   1309      */
   1310     public boolean updateStoredMessageStatus(Uri messageUri, ContentValues statusValues) {
   1311         if (messageUri == null) {
   1312             throw new IllegalArgumentException("Empty message URI");
   1313         }
   1314         try {
   1315             IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms"));
   1316             if (iMms != null) {
   1317                 return iMms.updateStoredMessageStatus(ActivityThread.currentPackageName(),
   1318                         messageUri, statusValues);
   1319             }
   1320         } catch (RemoteException ex) {
   1321             // ignore it
   1322         }
   1323         return false;
   1324     }
   1325 
   1326     /** Message status property: whether the message has been seen. 1 means seen, 0 not {@hide} */
   1327     public static final String MESSAGE_STATUS_SEEN = "seen";
   1328     /** Message status property: whether the message has been read. 1 means read, 0 not {@hide} */
   1329     public static final String MESSAGE_STATUS_READ = "read";
   1330 
   1331     /**
   1332      * Archive or unarchive a stored conversation
   1333      *
   1334      * @param conversationId the ID of the message conversation
   1335      * @param archived true to archive the conversation, false to unarchive
   1336      * @return true if update is successful, false otherwise
   1337      * {@hide}
   1338      */
   1339     public boolean archiveStoredConversation(long conversationId, boolean archived) {
   1340         try {
   1341             IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms"));
   1342             if (iMms != null) {
   1343                 return iMms.archiveStoredConversation(ActivityThread.currentPackageName(),
   1344                         conversationId, archived);
   1345             }
   1346         } catch (RemoteException ex) {
   1347             // ignore it
   1348         }
   1349         return false;
   1350     }
   1351 
   1352     /**
   1353      * Add a text message draft to system SMS store
   1354      *
   1355      * Only default SMS apps can add SMS draft
   1356      *
   1357      * @param address the destination address of message
   1358      * @param text the body of the message to send
   1359      * @return the URI of the stored draft message
   1360      * {@hide}
   1361      */
   1362     public Uri addTextMessageDraft(String address, String text) {
   1363         try {
   1364             IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms"));
   1365             if (iMms != null) {
   1366                 return iMms.addTextMessageDraft(ActivityThread.currentPackageName(), address, text);
   1367             }
   1368         } catch (RemoteException ex) {
   1369             // ignore it
   1370         }
   1371         return null;
   1372     }
   1373 
   1374     /**
   1375      * Add a multimedia message draft to system MMS store
   1376      *
   1377      * Only default SMS apps can add MMS draft
   1378      *
   1379      * @param contentUri the content uri from which to read the PDU data of the draft MMS
   1380      * @return the URI of the stored draft message
   1381      * @throws IllegalArgumentException if pdu is empty
   1382      * {@hide}
   1383      */
   1384     public Uri addMultimediaMessageDraft(Uri contentUri) {
   1385         if (contentUri == null) {
   1386             throw new IllegalArgumentException("Uri contentUri null");
   1387         }
   1388         try {
   1389             IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms"));
   1390             if (iMms != null) {
   1391                 return iMms.addMultimediaMessageDraft(ActivityThread.currentPackageName(),
   1392                         contentUri);
   1393             }
   1394         } catch (RemoteException ex) {
   1395             // ignore it
   1396         }
   1397         return null;
   1398     }
   1399 
   1400     /**
   1401      * Send a system stored text message.
   1402      *
   1403      * You can only send a failed text message or a draft text message.
   1404      *
   1405      * @param messageUri the URI of the stored message
   1406      * @param scAddress is the service center address or null to use the current default SMSC
   1407      * @param sentIntent if not NULL this <code>PendingIntent</code> is
   1408      *  broadcast when the message is successfully sent, or failed.
   1409      *  The result code will be <code>Activity.RESULT_OK</code> for success,
   1410      *  or one of these errors:<br>
   1411      *  <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
   1412      *  <code>RESULT_ERROR_RADIO_OFF</code><br>
   1413      *  <code>RESULT_ERROR_NULL_PDU</code><br>
   1414      *  For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
   1415      *  the extra "errorCode" containing a radio technology specific value,
   1416      *  generally only useful for troubleshooting.<br>
   1417      *  The per-application based SMS control checks sentIntent. If sentIntent
   1418      *  is NULL the caller will be checked against all unknown applications,
   1419      *  which cause smaller number of SMS to be sent in checking period.
   1420      * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
   1421      *  broadcast when the message is delivered to the recipient.  The
   1422      *  raw pdu of the status report is in the extended data ("pdu").
   1423      *
   1424      * @throws IllegalArgumentException if messageUri is empty
   1425      * {@hide}
   1426      */
   1427     public void sendStoredTextMessage(Uri messageUri, String scAddress, PendingIntent sentIntent,
   1428             PendingIntent deliveryIntent) {
   1429         if (messageUri == null) {
   1430             throw new IllegalArgumentException("Empty message URI");
   1431         }
   1432         try {
   1433             ISms iccISms = getISmsServiceOrThrow();
   1434             iccISms.sendStoredText(
   1435                     getSubscriptionId(), ActivityThread.currentPackageName(), messageUri,
   1436                     scAddress, sentIntent, deliveryIntent);
   1437         } catch (RemoteException ex) {
   1438             // ignore it
   1439         }
   1440     }
   1441 
   1442     /**
   1443      * Send a system stored multi-part text message.
   1444      *
   1445      * You can only send a failed text message or a draft text message.
   1446      * The provided <code>PendingIntent</code> lists should match the part number of the
   1447      * divided text of the stored message by using <code>divideMessage</code>
   1448      *
   1449      * @param messageUri the URI of the stored message
   1450      * @param scAddress is the service center address or null to use
   1451      *   the current default SMSC
   1452      * @param sentIntents if not null, an <code>ArrayList</code> of
   1453      *   <code>PendingIntent</code>s (one for each message part) that is
   1454      *   broadcast when the corresponding message part has been sent.
   1455      *   The result code will be <code>Activity.RESULT_OK</code> for success,
   1456      *   or one of these errors:<br>
   1457      *   <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
   1458      *   <code>RESULT_ERROR_RADIO_OFF</code><br>
   1459      *   <code>RESULT_ERROR_NULL_PDU</code><br>
   1460      *   For <code>RESULT_ERROR_GENERIC_FAILURE</code> each sentIntent may include
   1461      *   the extra "errorCode" containing a radio technology specific value,
   1462      *   generally only useful for troubleshooting.<br>
   1463      *   The per-application based SMS control checks sentIntent. If sentIntent
   1464      *   is NULL the caller will be checked against all unknown applications,
   1465      *   which cause smaller number of SMS to be sent in checking period.
   1466      * @param deliveryIntents if not null, an <code>ArrayList</code> of
   1467      *   <code>PendingIntent</code>s (one for each message part) that is
   1468      *   broadcast when the corresponding message part has been delivered
   1469      *   to the recipient.  The raw pdu of the status report is in the
   1470      *   extended data ("pdu").
   1471      *
   1472      * @throws IllegalArgumentException if messageUri is empty
   1473      * {@hide}
   1474      */
   1475     public void sendStoredMultipartTextMessage(Uri messageUri, String scAddress,
   1476             ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) {
   1477         if (messageUri == null) {
   1478             throw new IllegalArgumentException("Empty message URI");
   1479         }
   1480         try {
   1481             ISms iccISms = getISmsServiceOrThrow();
   1482             iccISms.sendStoredMultipartText(
   1483                     getSubscriptionId(), ActivityThread.currentPackageName(), messageUri,
   1484                     scAddress, sentIntents, deliveryIntents);
   1485         } catch (RemoteException ex) {
   1486             // ignore it
   1487         }
   1488     }
   1489 
   1490     /**
   1491      * Send a system stored MMS message
   1492      *
   1493      * This is used for sending a previously sent, but failed-to-send, message or
   1494      * for sending a text message that has been stored as a draft.
   1495      *
   1496      * @param messageUri the URI of the stored message
   1497      * @param configOverrides the carrier-specific messaging configuration values to override for
   1498      *  sending the message.
   1499      * @param sentIntent if not NULL this <code>PendingIntent</code> is
   1500      *  broadcast when the message is successfully sent, or failed
   1501      * @throws IllegalArgumentException if messageUri is empty
   1502      * {@hide}
   1503      */
   1504     public void sendStoredMultimediaMessage(Uri messageUri, Bundle configOverrides,
   1505             PendingIntent sentIntent) {
   1506         if (messageUri == null) {
   1507             throw new IllegalArgumentException("Empty message URI");
   1508         }
   1509         try {
   1510             IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms"));
   1511             if (iMms != null) {
   1512                 iMms.sendStoredMessage(
   1513                         getSubscriptionId(), ActivityThread.currentPackageName(), messageUri,
   1514                         configOverrides, sentIntent);
   1515             }
   1516         } catch (RemoteException ex) {
   1517             // ignore it
   1518         }
   1519     }
   1520 
   1521     /**
   1522      * Turns on/off the flag to automatically write sent/received SMS/MMS messages into system
   1523      *
   1524      * When this flag is on, all SMS/MMS sent/received are stored by system automatically
   1525      * When this flag is off, only SMS/MMS sent by non-default SMS apps are stored by system
   1526      * automatically
   1527      *
   1528      * This flag can only be changed by default SMS apps
   1529      *
   1530      * @param enabled Whether to enable message auto persisting
   1531      * {@hide}
   1532      */
   1533     public void setAutoPersisting(boolean enabled) {
   1534         try {
   1535             IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms"));
   1536             if (iMms != null) {
   1537                 iMms.setAutoPersisting(ActivityThread.currentPackageName(), enabled);
   1538             }
   1539         } catch (RemoteException ex) {
   1540             // ignore it
   1541         }
   1542     }
   1543 
   1544     /**
   1545      * Get the value of the flag to automatically write sent/received SMS/MMS messages into system
   1546      *
   1547      * When this flag is on, all SMS/MMS sent/received are stored by system automatically
   1548      * When this flag is off, only SMS/MMS sent by non-default SMS apps are stored by system
   1549      * automatically
   1550      *
   1551      * @return the current value of the auto persist flag
   1552      * {@hide}
   1553      */
   1554     public boolean getAutoPersisting() {
   1555         try {
   1556             IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms"));
   1557             if (iMms != null) {
   1558                 return iMms.getAutoPersisting();
   1559             }
   1560         } catch (RemoteException ex) {
   1561             // ignore it
   1562         }
   1563         return false;
   1564     }
   1565 
   1566     /**
   1567      * Get carrier-dependent configuration values.
   1568      *
   1569      * @return bundle key/values pairs of configuration values
   1570      */
   1571     public Bundle getCarrierConfigValues() {
   1572         try {
   1573             IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms"));
   1574             if (iMms != null) {
   1575                 return iMms.getCarrierConfigValues(getSubscriptionId());
   1576             }
   1577         } catch (RemoteException ex) {
   1578             // ignore it
   1579         }
   1580         return null;
   1581     }
   1582 
   1583     /**
   1584      * Filters a bundle to only contain MMS config variables.
   1585      *
   1586      * This is for use with bundles returned by {@link CarrierConfigManager} which contain MMS
   1587      * config and unrelated config. It is assumed that all MMS_CONFIG_* keys are present in the
   1588      * supplied bundle.
   1589      *
   1590      * @param config a Bundle that contains MMS config variables and possibly more.
   1591      * @return a new Bundle that only contains the MMS_CONFIG_* keys defined above.
   1592      * @hide
   1593      */
   1594     public static Bundle getMmsConfig(BaseBundle config) {
   1595         Bundle filtered = new Bundle();
   1596         filtered.putBoolean(MMS_CONFIG_APPEND_TRANSACTION_ID,
   1597                 config.getBoolean(MMS_CONFIG_APPEND_TRANSACTION_ID));
   1598         filtered.putBoolean(MMS_CONFIG_MMS_ENABLED, config.getBoolean(MMS_CONFIG_MMS_ENABLED));
   1599         filtered.putBoolean(MMS_CONFIG_GROUP_MMS_ENABLED,
   1600                 config.getBoolean(MMS_CONFIG_GROUP_MMS_ENABLED));
   1601         filtered.putBoolean(MMS_CONFIG_NOTIFY_WAP_MMSC_ENABLED,
   1602                 config.getBoolean(MMS_CONFIG_NOTIFY_WAP_MMSC_ENABLED));
   1603         filtered.putBoolean(MMS_CONFIG_ALIAS_ENABLED, config.getBoolean(MMS_CONFIG_ALIAS_ENABLED));
   1604         filtered.putBoolean(MMS_CONFIG_ALLOW_ATTACH_AUDIO,
   1605                 config.getBoolean(MMS_CONFIG_ALLOW_ATTACH_AUDIO));
   1606         filtered.putBoolean(MMS_CONFIG_MULTIPART_SMS_ENABLED,
   1607                 config.getBoolean(MMS_CONFIG_MULTIPART_SMS_ENABLED));
   1608         filtered.putBoolean(MMS_CONFIG_SMS_DELIVERY_REPORT_ENABLED,
   1609                 config.getBoolean(MMS_CONFIG_SMS_DELIVERY_REPORT_ENABLED));
   1610         filtered.putBoolean(MMS_CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION,
   1611                 config.getBoolean(MMS_CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION));
   1612         filtered.putBoolean(MMS_CONFIG_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES,
   1613                 config.getBoolean(MMS_CONFIG_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES));
   1614         filtered.putBoolean(MMS_CONFIG_MMS_READ_REPORT_ENABLED,
   1615                 config.getBoolean(MMS_CONFIG_MMS_READ_REPORT_ENABLED));
   1616         filtered.putBoolean(MMS_CONFIG_MMS_DELIVERY_REPORT_ENABLED,
   1617                 config.getBoolean(MMS_CONFIG_MMS_DELIVERY_REPORT_ENABLED));
   1618         filtered.putInt(MMS_CONFIG_MAX_MESSAGE_SIZE, config.getInt(MMS_CONFIG_MAX_MESSAGE_SIZE));
   1619         filtered.putInt(MMS_CONFIG_MAX_IMAGE_WIDTH, config.getInt(MMS_CONFIG_MAX_IMAGE_WIDTH));
   1620         filtered.putInt(MMS_CONFIG_MAX_IMAGE_HEIGHT, config.getInt(MMS_CONFIG_MAX_IMAGE_HEIGHT));
   1621         filtered.putInt(MMS_CONFIG_RECIPIENT_LIMIT, config.getInt(MMS_CONFIG_RECIPIENT_LIMIT));
   1622         filtered.putInt(MMS_CONFIG_ALIAS_MIN_CHARS, config.getInt(MMS_CONFIG_ALIAS_MIN_CHARS));
   1623         filtered.putInt(MMS_CONFIG_ALIAS_MAX_CHARS, config.getInt(MMS_CONFIG_ALIAS_MAX_CHARS));
   1624         filtered.putInt(MMS_CONFIG_SMS_TO_MMS_TEXT_THRESHOLD,
   1625                 config.getInt(MMS_CONFIG_SMS_TO_MMS_TEXT_THRESHOLD));
   1626         filtered.putInt(MMS_CONFIG_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD,
   1627                 config.getInt(MMS_CONFIG_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD));
   1628         filtered.putInt(MMS_CONFIG_MESSAGE_TEXT_MAX_SIZE,
   1629                 config.getInt(MMS_CONFIG_MESSAGE_TEXT_MAX_SIZE));
   1630         filtered.putInt(MMS_CONFIG_SUBJECT_MAX_LENGTH,
   1631                 config.getInt(MMS_CONFIG_SUBJECT_MAX_LENGTH));
   1632         filtered.putInt(MMS_CONFIG_HTTP_SOCKET_TIMEOUT,
   1633                 config.getInt(MMS_CONFIG_HTTP_SOCKET_TIMEOUT));
   1634         filtered.putString(MMS_CONFIG_UA_PROF_TAG_NAME,
   1635                 config.getString(MMS_CONFIG_UA_PROF_TAG_NAME));
   1636         filtered.putString(MMS_CONFIG_USER_AGENT, config.getString(MMS_CONFIG_USER_AGENT));
   1637         filtered.putString(MMS_CONFIG_UA_PROF_URL, config.getString(MMS_CONFIG_UA_PROF_URL));
   1638         filtered.putString(MMS_CONFIG_HTTP_PARAMS, config.getString(MMS_CONFIG_HTTP_PARAMS));
   1639         filtered.putString(MMS_CONFIG_EMAIL_GATEWAY_NUMBER,
   1640                 config.getString(MMS_CONFIG_EMAIL_GATEWAY_NUMBER));
   1641         filtered.putString(MMS_CONFIG_NAI_SUFFIX, config.getString(MMS_CONFIG_NAI_SUFFIX));
   1642         filtered.putBoolean(MMS_CONFIG_SHOW_CELL_BROADCAST_APP_LINKS,
   1643                 config.getBoolean(MMS_CONFIG_SHOW_CELL_BROADCAST_APP_LINKS));
   1644         filtered.putBoolean(MMS_CONFIG_SUPPORT_HTTP_CHARSET_HEADER,
   1645                 config.getBoolean(MMS_CONFIG_SUPPORT_HTTP_CHARSET_HEADER));
   1646         return filtered;
   1647     }
   1648 
   1649 }
   1650