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