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