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