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