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