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