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