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.Manifest; 20 import android.annotation.CallbackExecutor; 21 import android.annotation.IntDef; 22 import android.annotation.IntRange; 23 import android.annotation.NonNull; 24 import android.annotation.Nullable; 25 import android.annotation.RequiresPermission; 26 import android.annotation.SuppressAutoDoc; 27 import android.annotation.SystemApi; 28 import android.annotation.TestApi; 29 import android.app.PendingIntent; 30 import android.compat.Compatibility; 31 import android.compat.annotation.ChangeId; 32 import android.compat.annotation.EnabledAfter; 33 import android.compat.annotation.UnsupportedAppUsage; 34 import android.content.Context; 35 import android.database.CursorWindow; 36 import android.net.Uri; 37 import android.os.Build; 38 import android.os.Bundle; 39 import android.os.RemoteException; 40 import android.text.TextUtils; 41 import android.util.ArrayMap; 42 import android.util.Log; 43 import android.util.Pair; 44 45 import com.android.internal.annotations.GuardedBy; 46 import com.android.internal.telephony.IIntegerConsumer; 47 import com.android.internal.telephony.ISms; 48 import com.android.internal.telephony.ITelephony; 49 import com.android.internal.telephony.SmsRawData; 50 import com.android.telephony.Rlog; 51 52 import java.lang.annotation.Retention; 53 import java.lang.annotation.RetentionPolicy; 54 import java.util.ArrayList; 55 import java.util.List; 56 import java.util.Map; 57 import java.util.concurrent.Executor; 58 59 /* 60 * TODO(code review): Curious question... Why are a lot of these 61 * methods not declared as static, since they do not seem to require 62 * any local object state? Presumably this cannot be changed without 63 * interfering with the API... 64 */ 65 66 /** 67 * Manages SMS operations such as sending data, text, and pdu SMS messages. 68 * Get this object by calling the static method {@link #getDefault()}. To create an instance of 69 * {@link SmsManager} associated with a specific subscription ID, call 70 * {@link #getSmsManagerForSubscriptionId(int)}. This is typically used for devices that support 71 * multiple active subscriptions at once. 72 * 73 * <p>For information about how to behave as the default SMS app on Android 4.4 (API level 19) 74 * and higher, see {@link android.provider.Telephony}. 75 * 76 * @see SubscriptionManager#getActiveSubscriptionInfoList() 77 */ 78 public final class SmsManager { 79 private static final String TAG = "SmsManager"; 80 81 private static final Object sLockObject = new Object(); 82 83 @GuardedBy("sLockObject") 84 private static final Map<Pair<Context, Integer>, SmsManager> sSubInstances = 85 new ArrayMap<>(); 86 87 /** Singleton object constructed during class initialization. */ 88 private static final SmsManager DEFAULT_INSTANCE = getSmsManagerForContextAndSubscriptionId( 89 null, SubscriptionManager.DEFAULT_SUBSCRIPTION_ID); 90 91 /** SMS record length from TS 51.011 10.5.3 92 * @hide 93 */ 94 public static final int SMS_RECORD_LENGTH = 176; 95 96 /** SMS record length from C.S0023 3.4.27 97 * @hide 98 */ 99 public static final int CDMA_SMS_RECORD_LENGTH = 255; 100 101 /** A concrete subscription id, or the pseudo DEFAULT_SUBSCRIPTION_ID */ 102 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 103 private int mSubId; 104 105 /** 106 * Context this SmsManager is for. Can be {@code null} in the case the manager was created via 107 * legacy APIs 108 */ 109 private final @Nullable Context mContext; 110 111 /* 112 * Key for the various carrier-dependent configuration values. 113 * Some of the values are used by the system in processing SMS or MMS messages. Others 114 * are provided for the convenience of SMS applications. 115 */ 116 117 /** 118 * Whether to append transaction id to MMS WAP Push M-Notification.ind's content location URI 119 * when constructing the download URL of a new MMS (boolean type) 120 */ 121 public static final String MMS_CONFIG_APPEND_TRANSACTION_ID = 122 CarrierConfigManager.KEY_MMS_APPEND_TRANSACTION_ID_BOOL; 123 /** 124 * Whether MMS is enabled for the current carrier (boolean type) 125 */ 126 public static final String 127 MMS_CONFIG_MMS_ENABLED = CarrierConfigManager.KEY_MMS_MMS_ENABLED_BOOL; 128 /** 129 * Whether group MMS is enabled for the current carrier (boolean type) 130 */ 131 public static final String 132 MMS_CONFIG_GROUP_MMS_ENABLED = CarrierConfigManager.KEY_MMS_GROUP_MMS_ENABLED_BOOL; 133 /** 134 * If this is enabled, M-NotifyResp.ind should be sent to the WAP Push content location instead 135 * of the default MMSC (boolean type) 136 */ 137 public static final String MMS_CONFIG_NOTIFY_WAP_MMSC_ENABLED = 138 CarrierConfigManager.KEY_MMS_NOTIFY_WAP_MMSC_ENABLED_BOOL; 139 /** 140 * Whether alias is enabled (boolean type) 141 */ 142 public static final String 143 MMS_CONFIG_ALIAS_ENABLED = CarrierConfigManager.KEY_MMS_ALIAS_ENABLED_BOOL; 144 /** 145 * Whether audio is allowed to be attached for MMS messages (boolean type) 146 */ 147 public static final String 148 MMS_CONFIG_ALLOW_ATTACH_AUDIO = CarrierConfigManager.KEY_MMS_ALLOW_ATTACH_AUDIO_BOOL; 149 /** 150 * Whether multipart SMS is enabled (boolean type) 151 */ 152 public static final String MMS_CONFIG_MULTIPART_SMS_ENABLED = 153 CarrierConfigManager.KEY_MMS_MULTIPART_SMS_ENABLED_BOOL; 154 /** 155 * Whether SMS delivery report is enabled (boolean type) 156 */ 157 public static final String MMS_CONFIG_SMS_DELIVERY_REPORT_ENABLED = 158 CarrierConfigManager.KEY_MMS_SMS_DELIVERY_REPORT_ENABLED_BOOL; 159 /** 160 * Whether content-disposition field should be expected in an MMS PDU (boolean type) 161 */ 162 public static final String MMS_CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION = 163 CarrierConfigManager.KEY_MMS_SUPPORT_MMS_CONTENT_DISPOSITION_BOOL; 164 /** 165 * Whether multipart SMS should be sent as separate messages 166 */ 167 public static final String MMS_CONFIG_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES = 168 CarrierConfigManager.KEY_MMS_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES_BOOL; 169 /** 170 * Whether MMS read report is enabled (boolean type) 171 */ 172 public static final String MMS_CONFIG_MMS_READ_REPORT_ENABLED = 173 CarrierConfigManager.KEY_MMS_MMS_READ_REPORT_ENABLED_BOOL; 174 /** 175 * Whether MMS delivery report is enabled (boolean type) 176 */ 177 public static final String MMS_CONFIG_MMS_DELIVERY_REPORT_ENABLED = 178 CarrierConfigManager.KEY_MMS_MMS_DELIVERY_REPORT_ENABLED_BOOL; 179 /** 180 * Max MMS message size in bytes (int type) 181 */ 182 public static final String 183 MMS_CONFIG_MAX_MESSAGE_SIZE = CarrierConfigManager.KEY_MMS_MAX_MESSAGE_SIZE_INT; 184 /** 185 * Max MMS image width (int type) 186 */ 187 public static final String 188 MMS_CONFIG_MAX_IMAGE_WIDTH = CarrierConfigManager.KEY_MMS_MAX_IMAGE_WIDTH_INT; 189 /** 190 * Max MMS image height (int type) 191 */ 192 public static final String 193 MMS_CONFIG_MAX_IMAGE_HEIGHT = CarrierConfigManager.KEY_MMS_MAX_IMAGE_HEIGHT_INT; 194 /** 195 * Limit of recipients of MMS messages (int type) 196 */ 197 public static final String 198 MMS_CONFIG_RECIPIENT_LIMIT = CarrierConfigManager.KEY_MMS_RECIPIENT_LIMIT_INT; 199 /** 200 * Min alias character count (int type) 201 */ 202 public static final String 203 MMS_CONFIG_ALIAS_MIN_CHARS = CarrierConfigManager.KEY_MMS_ALIAS_MIN_CHARS_INT; 204 /** 205 * Max alias character count (int type) 206 */ 207 public static final String 208 MMS_CONFIG_ALIAS_MAX_CHARS = CarrierConfigManager.KEY_MMS_ALIAS_MAX_CHARS_INT; 209 /** 210 * When the number of parts of a multipart SMS reaches this threshold, it should be converted 211 * into an MMS (int type) 212 */ 213 public static final String MMS_CONFIG_SMS_TO_MMS_TEXT_THRESHOLD = 214 CarrierConfigManager.KEY_MMS_SMS_TO_MMS_TEXT_THRESHOLD_INT; 215 /** 216 * Some carriers require SMS to be converted into MMS when text length reaches this threshold 217 * (int type) 218 */ 219 public static final String MMS_CONFIG_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD = 220 CarrierConfigManager.KEY_MMS_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD_INT; 221 /** 222 * Max message text size (int type) 223 */ 224 public static final String MMS_CONFIG_MESSAGE_TEXT_MAX_SIZE = 225 CarrierConfigManager.KEY_MMS_MESSAGE_TEXT_MAX_SIZE_INT; 226 /** 227 * Max message subject length (int type) 228 */ 229 public static final String 230 MMS_CONFIG_SUBJECT_MAX_LENGTH = CarrierConfigManager.KEY_MMS_SUBJECT_MAX_LENGTH_INT; 231 /** 232 * MMS HTTP socket timeout in milliseconds (int type) 233 */ 234 public static final String 235 MMS_CONFIG_HTTP_SOCKET_TIMEOUT = CarrierConfigManager.KEY_MMS_HTTP_SOCKET_TIMEOUT_INT; 236 /** 237 * The name of the UA Prof URL HTTP header for MMS HTTP request (String type) 238 */ 239 public static final String 240 MMS_CONFIG_UA_PROF_TAG_NAME = CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING; 241 /** 242 * The User-Agent header value for MMS HTTP request (String type) 243 */ 244 public static final String 245 MMS_CONFIG_USER_AGENT = CarrierConfigManager.KEY_MMS_USER_AGENT_STRING; 246 /** 247 * The UA Profile URL header value for MMS HTTP request (String type) 248 */ 249 public static final String 250 MMS_CONFIG_UA_PROF_URL = CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING; 251 /** 252 * A list of HTTP headers to add to MMS HTTP request, separated by "|" (String type) 253 */ 254 public static final String 255 MMS_CONFIG_HTTP_PARAMS = CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING; 256 /** 257 * Email gateway number (String type) 258 */ 259 public static final String MMS_CONFIG_EMAIL_GATEWAY_NUMBER = 260 CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING; 261 /** 262 * The suffix to append to the NAI header value for MMS HTTP request (String type) 263 */ 264 public static final String 265 MMS_CONFIG_NAI_SUFFIX = CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING; 266 /** 267 * If true, show the cell broadcast (amber alert) in the SMS settings. Some carriers don't want 268 * this shown. (Boolean type) 269 */ 270 public static final String MMS_CONFIG_SHOW_CELL_BROADCAST_APP_LINKS = 271 CarrierConfigManager.KEY_MMS_SHOW_CELL_BROADCAST_APP_LINKS_BOOL; 272 /** 273 * Whether the carrier MMSC supports charset field in Content-Type header. If this is false, 274 * then we don't add "charset" to "Content-Type" 275 */ 276 public static final String MMS_CONFIG_SUPPORT_HTTP_CHARSET_HEADER = 277 CarrierConfigManager.KEY_MMS_SUPPORT_HTTP_CHARSET_HEADER_BOOL; 278 /** 279 * If true, add "Connection: close" header to MMS HTTP requests so the connection 280 * is immediately closed (disabling keep-alive). (Boolean type) 281 * @hide 282 */ 283 public static final String MMS_CONFIG_CLOSE_CONNECTION = 284 CarrierConfigManager.KEY_MMS_CLOSE_CONNECTION_BOOL; 285 286 /** 287 * 3gpp2 SMS priority is not specified 288 * @hide 289 */ 290 public static final int SMS_MESSAGE_PRIORITY_NOT_SPECIFIED = -1; 291 /** 292 * 3gpp SMS period is not specified 293 * @hide 294 */ 295 public static final int SMS_MESSAGE_PERIOD_NOT_SPECIFIED = -1; 296 297 /** @hide */ 298 @IntDef(prefix = { "PREMIUM_SMS_CONSENT" }, value = { 299 SmsManager.PREMIUM_SMS_CONSENT_UNKNOWN, 300 SmsManager.PREMIUM_SMS_CONSENT_ASK_USER, 301 SmsManager.PREMIUM_SMS_CONSENT_NEVER_ALLOW, 302 SmsManager.PREMIUM_SMS_CONSENT_ALWAYS_ALLOW 303 }) 304 @Retention(RetentionPolicy.SOURCE) 305 public @interface PremiumSmsConsent {} 306 307 /** Premium SMS Consent for the package is unknown. This indicates that the user 308 * has not set a permission for this package, because this package has never tried 309 * to send a premium SMS. 310 * @hide 311 */ 312 @SystemApi 313 public static final int PREMIUM_SMS_CONSENT_UNKNOWN = 0; 314 315 /** Default premium SMS Consent (ask user for each premium SMS sent). 316 * @hide 317 */ 318 @SystemApi 319 public static final int PREMIUM_SMS_CONSENT_ASK_USER = 1; 320 321 /** Premium SMS Consent when the owner has denied the app from sending premium SMS. 322 * @hide 323 */ 324 @SystemApi 325 public static final int PREMIUM_SMS_CONSENT_NEVER_ALLOW = 2; 326 327 /** Premium SMS Consent when the owner has allowed the app to send premium SMS. 328 * @hide 329 */ 330 @SystemApi 331 public static final int PREMIUM_SMS_CONSENT_ALWAYS_ALLOW = 3; 332 333 // result of asking the user for a subscription to perform an operation. 334 private interface SubscriptionResolverResult { onSuccess(int subId)335 void onSuccess(int subId); onFailure()336 void onFailure(); 337 } 338 339 /** 340 * Get {@link Context#getOpPackageName()} if this manager has a context, otherwise a dummy 341 * value. 342 * 343 * @return The package name to be used for app-ops checks 344 */ getOpPackageName()345 private @Nullable String getOpPackageName() { 346 if (mContext == null) { 347 return null; 348 } else { 349 return mContext.getOpPackageName(); 350 } 351 } 352 353 /** 354 * Get {@link Context#getAttributionTag()} ()} if this manager has a context, otherwise get the 355 * default attribution tag. 356 * 357 * @return The attribution tag to be used for app-ops checks 358 */ getAttributionTag()359 private @Nullable String getAttributionTag() { 360 if (mContext == null) { 361 return null; 362 } else { 363 return mContext.getAttributionTag(); 364 } 365 } 366 367 /** 368 * Send a text based SMS. 369 * 370 * <p class="note"><strong>Note:</strong> Using this method requires that your app has the 371 * {@link android.Manifest.permission#SEND_SMS} permission.</p> 372 * 373 * <p class="note"><strong>Note:</strong> Beginning with Android 4.4 (API level 19), if 374 * <em>and only if</em> an app is not selected as the default SMS app, the system automatically 375 * writes messages sent using this method to the SMS Provider (the default SMS app is always 376 * responsible for writing its sent messages to the SMS Provider). For information about 377 * how to behave as the default SMS app, see {@link android.provider.Telephony}.</p> 378 * 379 * <p class="note"><strong>Note:</strong> If {@link #getDefault()} is used to instantiate this 380 * manager on a multi-SIM device, this operation may fail sending the SMS message because no 381 * suitable default subscription could be found. In this case, if {@code sentIntent} is 382 * non-null, then the {@link PendingIntent} will be sent with an error code 383 * {@code RESULT_ERROR_GENERIC_FAILURE} and an extra string {@code "noDefault"} containing the 384 * boolean value {@code true}. See {@link #getDefault()} for more information on the conditions 385 * where this operation may fail. 386 * </p> 387 * 388 * @param destinationAddress the address to send the message to 389 * @param scAddress is the service center address or null to use 390 * the current default SMSC 391 * @param text the body of the message to send 392 * @param sentIntent if not NULL this <code>PendingIntent</code> is 393 * broadcast when the message is successfully sent, or failed. 394 * The result code will be <code>Activity.RESULT_OK</code> for success, 395 * or one of these errors:<br> 396 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 397 * <code>RESULT_ERROR_RADIO_OFF</code><br> 398 * <code>RESULT_ERROR_NULL_PDU</code><br> 399 * <code>RESULT_ERROR_NO_SERVICE</code><br> 400 * <code>RESULT_ERROR_LIMIT_EXCEEDED</code><br> 401 * <code>RESULT_ERROR_FDN_CHECK_FAILURE</code><br> 402 * <code>RESULT_ERROR_SHORT_CODE_NOT_ALLOWED</code><br> 403 * <code>RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED</code><br> 404 * <code>RESULT_RADIO_NOT_AVAILABLE</code><br> 405 * <code>RESULT_NETWORK_REJECT</code><br> 406 * <code>RESULT_INVALID_ARGUMENTS</code><br> 407 * <code>RESULT_INVALID_STATE</code><br> 408 * <code>RESULT_NO_MEMORY</code><br> 409 * <code>RESULT_INVALID_SMS_FORMAT</code><br> 410 * <code>RESULT_SYSTEM_ERROR</code><br> 411 * <code>RESULT_MODEM_ERROR</code><br> 412 * <code>RESULT_NETWORK_ERROR</code><br> 413 * <code>RESULT_ENCODING_ERROR</code><br> 414 * <code>RESULT_INVALID_SMSC_ADDRESS</code><br> 415 * <code>RESULT_OPERATION_NOT_ALLOWED</code><br> 416 * <code>RESULT_INTERNAL_ERROR</code><br> 417 * <code>RESULT_NO_RESOURCES</code><br> 418 * <code>RESULT_CANCELLED</code><br> 419 * <code>RESULT_REQUEST_NOT_SUPPORTED</code><br> 420 * <code>RESULT_NO_BLUETOOTH_SERVICE</code><br> 421 * <code>RESULT_INVALID_BLUETOOTH_ADDRESS</code><br> 422 * <code>RESULT_BLUETOOTH_DISCONNECTED</code><br> 423 * <code>RESULT_UNEXPECTED_EVENT_STOP_SENDING</code><br> 424 * <code>RESULT_SMS_BLOCKED_DURING_EMERGENCY</code><br> 425 * <code>RESULT_SMS_SEND_RETRY_FAILED</code><br> 426 * <code>RESULT_REMOTE_EXCEPTION</code><br> 427 * <code>RESULT_NO_DEFAULT_SMS_APP</code><br> 428 * <code>RESULT_RIL_RADIO_NOT_AVAILABLE</code><br> 429 * <code>RESULT_RIL_SMS_SEND_FAIL_RETRY</code><br> 430 * <code>RESULT_RIL_NETWORK_REJECT</code><br> 431 * <code>RESULT_RIL_INVALID_STATE</code><br> 432 * <code>RESULT_RIL_INVALID_ARGUMENTS</code><br> 433 * <code>RESULT_RIL_NO_MEMORY</code><br> 434 * <code>RESULT_RIL_REQUEST_RATE_LIMITED</code><br> 435 * <code>RESULT_RIL_INVALID_SMS_FORMAT</code><br> 436 * <code>RESULT_RIL_SYSTEM_ERR</code><br> 437 * <code>RESULT_RIL_ENCODING_ERR</code><br> 438 * <code>RESULT_RIL_INVALID_SMSC_ADDRESS</code><br> 439 * <code>RESULT_RIL_MODEM_ERR</code><br> 440 * <code>RESULT_RIL_NETWORK_ERR</code><br> 441 * <code>RESULT_RIL_INTERNAL_ERR</code><br> 442 * <code>RESULT_RIL_REQUEST_NOT_SUPPORTED</code><br> 443 * <code>RESULT_RIL_INVALID_MODEM_STATE</code><br> 444 * <code>RESULT_RIL_NETWORK_NOT_READY</code><br> 445 * <code>RESULT_RIL_OPERATION_NOT_ALLOWED</code><br> 446 * <code>RESULT_RIL_NO_RESOURCES</code><br> 447 * <code>RESULT_RIL_CANCELLED</code><br> 448 * <code>RESULT_RIL_SIM_ABSENT</code><br> 449 * <code>RESULT_RIL_SIMULTANEOUS_SMS_AND_CALL_NOT_ALLOWED</code><br> 450 * <code>RESULT_RIL_ACCESS_BARRED</code><br> 451 * <code>RESULT_RIL_BLOCKED_DUE_TO_CALL</code><br> 452 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> or any of the RESULT_RIL errors, 453 * the sentIntent may include the extra "errorCode" containing a radio technology specific 454 * value, generally only useful for troubleshooting.<br> 455 * @param deliveryIntent if not NULL this <code>PendingIntent</code> is 456 * broadcast when the message is delivered to the recipient. The 457 * raw pdu of the status report is in the extended data ("pdu"). 458 * 459 * @throws IllegalArgumentException if destinationAddress or text are empty 460 */ sendTextMessage( String destinationAddress, String scAddress, String text, PendingIntent sentIntent, PendingIntent deliveryIntent)461 public void sendTextMessage( 462 String destinationAddress, String scAddress, String text, 463 PendingIntent sentIntent, PendingIntent deliveryIntent) { 464 sendTextMessageInternal(destinationAddress, scAddress, text, sentIntent, deliveryIntent, 465 true /* persistMessage*/, getOpPackageName(), getAttributionTag(), 466 0L /* messageId */); 467 } 468 469 470 /** 471 * Send a text based SMS. Same as {@link #sendTextMessage( String destinationAddress, 472 * String scAddress, String text, PendingIntent sentIntent, PendingIntent deliveryIntent)}, but 473 * adds an optional messageId. 474 * @param messageId An id that uniquely identifies the message requested to be sent. 475 * Used for logging and diagnostics purposes. The id may be 0. 476 * 477 * @throws IllegalArgumentException if destinationAddress or text are empty 478 * 479 */ sendTextMessage( @onNull String destinationAddress, @Nullable String scAddress, @NonNull String text, @Nullable PendingIntent sentIntent, @Nullable PendingIntent deliveryIntent, long messageId)480 public void sendTextMessage( 481 @NonNull String destinationAddress, @Nullable String scAddress, @NonNull String text, 482 @Nullable PendingIntent sentIntent, @Nullable PendingIntent deliveryIntent, 483 long messageId) { 484 sendTextMessageInternal(destinationAddress, scAddress, text, sentIntent, deliveryIntent, 485 true /* persistMessage*/, getOpPackageName(), getAttributionTag(), 486 messageId); 487 } 488 489 /** 490 * Send a text based SMS with messaging options. 491 * 492 * <p class="note"><strong>Note:</strong> If {@link #getDefault()} is used to instantiate this 493 * manager on a multi-SIM device, this operation may fail sending the SMS message because no 494 * suitable default subscription could be found. In this case, if {@code sentIntent} is 495 * non-null, then the {@link PendingIntent} will be sent with an error code 496 * {@code RESULT_ERROR_GENERIC_FAILURE} and an extra string {@code "noDefault"} containing the 497 * boolean value {@code true}. See {@link #getDefault()} for more information on the conditions 498 * where this operation may fail. 499 * </p> 500 * 501 * @param destinationAddress the address to send the message to 502 * @param scAddress is the service center address or null to use 503 * the current default SMSC 504 * @param text the body of the message to send 505 * @param sentIntent if not NULL this <code>PendingIntent</code> is 506 * broadcast when the message is successfully sent, or failed. 507 * The result code will be <code>Activity.RESULT_OK</code> for success, 508 * or one of these errors:<br> 509 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 510 * <code>RESULT_ERROR_RADIO_OFF</code><br> 511 * <code>RESULT_ERROR_NULL_PDU</code><br> 512 * <code>RESULT_ERROR_NO_SERVICE</code><br> 513 * <code>RESULT_ERROR_LIMIT_EXCEEDED</code><br> 514 * <code>RESULT_ERROR_FDN_CHECK_FAILURE</code><br> 515 * <code>RESULT_ERROR_SHORT_CODE_NOT_ALLOWED</code><br> 516 * <code>RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED</code><br> 517 * <code>RESULT_RADIO_NOT_AVAILABLE</code><br> 518 * <code>RESULT_NETWORK_REJECT</code><br> 519 * <code>RESULT_INVALID_ARGUMENTS</code><br> 520 * <code>RESULT_INVALID_STATE</code><br> 521 * <code>RESULT_NO_MEMORY</code><br> 522 * <code>RESULT_INVALID_SMS_FORMAT</code><br> 523 * <code>RESULT_SYSTEM_ERROR</code><br> 524 * <code>RESULT_MODEM_ERROR</code><br> 525 * <code>RESULT_NETWORK_ERROR</code><br> 526 * <code>RESULT_ENCODING_ERROR</code><br> 527 * <code>RESULT_INVALID_SMSC_ADDRESS</code><br> 528 * <code>RESULT_OPERATION_NOT_ALLOWED</code><br> 529 * <code>RESULT_INTERNAL_ERROR</code><br> 530 * <code>RESULT_NO_RESOURCES</code><br> 531 * <code>RESULT_CANCELLED</code><br> 532 * <code>RESULT_REQUEST_NOT_SUPPORTED</code><br> 533 * <code>RESULT_NO_BLUETOOTH_SERVICE</code><br> 534 * <code>RESULT_INVALID_BLUETOOTH_ADDRESS</code><br> 535 * <code>RESULT_BLUETOOTH_DISCONNECTED</code><br> 536 * <code>RESULT_UNEXPECTED_EVENT_STOP_SENDING</code><br> 537 * <code>RESULT_SMS_BLOCKED_DURING_EMERGENCY</code><br> 538 * <code>RESULT_SMS_SEND_RETRY_FAILED</code><br> 539 * <code>RESULT_REMOTE_EXCEPTION</code><br> 540 * <code>RESULT_NO_DEFAULT_SMS_APP</code><br> 541 * <code>RESULT_RIL_RADIO_NOT_AVAILABLE</code><br> 542 * <code>RESULT_RIL_SMS_SEND_FAIL_RETRY</code><br> 543 * <code>RESULT_RIL_NETWORK_REJECT</code><br> 544 * <code>RESULT_RIL_INVALID_STATE</code><br> 545 * <code>RESULT_RIL_INVALID_ARGUMENTS</code><br> 546 * <code>RESULT_RIL_NO_MEMORY</code><br> 547 * <code>RESULT_RIL_REQUEST_RATE_LIMITED</code><br> 548 * <code>RESULT_RIL_INVALID_SMS_FORMAT</code><br> 549 * <code>RESULT_RIL_SYSTEM_ERR</code><br> 550 * <code>RESULT_RIL_ENCODING_ERR</code><br> 551 * <code>RESULT_RIL_INVALID_SMSC_ADDRESS</code><br> 552 * <code>RESULT_RIL_MODEM_ERR</code><br> 553 * <code>RESULT_RIL_NETWORK_ERR</code><br> 554 * <code>RESULT_RIL_INTERNAL_ERR</code><br> 555 * <code>RESULT_RIL_REQUEST_NOT_SUPPORTED</code><br> 556 * <code>RESULT_RIL_INVALID_MODEM_STATE</code><br> 557 * <code>RESULT_RIL_NETWORK_NOT_READY</code><br> 558 * <code>RESULT_RIL_OPERATION_NOT_ALLOWED</code><br> 559 * <code>RESULT_RIL_NO_RESOURCES</code><br> 560 * <code>RESULT_RIL_CANCELLED</code><br> 561 * <code>RESULT_RIL_SIM_ABSENT</code><br> 562 * <code>RESULT_RIL_SIMULTANEOUS_SMS_AND_CALL_NOT_ALLOWED</code><br> 563 * <code>RESULT_RIL_ACCESS_BARRED</code><br> 564 * <code>RESULT_RIL_BLOCKED_DUE_TO_CALL</code><br> 565 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> or any of the RESULT_RIL errors, 566 * the sentIntent may include the extra "errorCode" containing a radio technology specific 567 * value, generally only useful for troubleshooting.<br> 568 * @param deliveryIntent if not NULL this <code>PendingIntent</code> is 569 * broadcast when the message is delivered to the recipient. The 570 * raw pdu of the status report is in the extended data ("pdu"). 571 * @param priority Priority level of the message 572 * Refer specification See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1 573 * --------------------------------- 574 * PRIORITY | Level of Priority 575 * --------------------------------- 576 * '00' | Normal 577 * '01' | Interactive 578 * '10' | Urgent 579 * '11' | Emergency 580 * ---------------------------------- 581 * Any Other values included Negative considered as Invalid Priority Indicator of the message. 582 * @param expectMore is a boolean to indicate the sending messages through same link or not. 583 * @param validityPeriod Validity Period of the message in mins. 584 * Refer specification 3GPP TS 23.040 V6.8.1 section 9.2.3.12.1. 585 * Validity Period(Minimum) -> 5 mins 586 * Validity Period(Maximum) -> 635040 mins(i.e.63 weeks). 587 * Any Other values included Negative considered as Invalid Validity Period of the message. 588 * 589 * @throws IllegalArgumentException if destinationAddress or text are empty 590 * {@hide} 591 */ 592 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) sendTextMessage( String destinationAddress, String scAddress, String text, PendingIntent sentIntent, PendingIntent deliveryIntent, int priority, boolean expectMore, int validityPeriod)593 public void sendTextMessage( 594 String destinationAddress, String scAddress, String text, 595 PendingIntent sentIntent, PendingIntent deliveryIntent, 596 int priority, boolean expectMore, int validityPeriod) { 597 sendTextMessageInternal(destinationAddress, scAddress, text, sentIntent, deliveryIntent, 598 true /* persistMessage*/, priority, expectMore, validityPeriod); 599 } 600 sendTextMessageInternal(String destinationAddress, String scAddress, String text, PendingIntent sentIntent, PendingIntent deliveryIntent, boolean persistMessage, String packageName, String attributionTag, long messageId)601 private void sendTextMessageInternal(String destinationAddress, String scAddress, 602 String text, PendingIntent sentIntent, PendingIntent deliveryIntent, 603 boolean persistMessage, String packageName, String attributionTag, long messageId) { 604 if (TextUtils.isEmpty(destinationAddress)) { 605 throw new IllegalArgumentException("Invalid destinationAddress"); 606 } 607 608 if (TextUtils.isEmpty(text)) { 609 throw new IllegalArgumentException("Invalid message body"); 610 } 611 612 // We will only show the SMS disambiguation dialog in the case that the message is being 613 // persisted. This is for two reasons: 614 // 1) Messages that are not persisted are sent by carrier/OEM apps for a specific 615 // subscription and require special permissions. These messages are usually not sent by 616 // the device user and should not have an SMS disambiguation dialog associated with them 617 // because the device user did not trigger them. 618 // 2) The SMS disambiguation dialog ONLY checks to make sure that the user has the SEND_SMS 619 // permission. If we call resolveSubscriptionForOperation from a carrier/OEM app that has 620 // the correct MODIFY_PHONE_STATE or carrier permissions, but no SEND_SMS, it will throw 621 // an incorrect SecurityException. 622 if (persistMessage) { 623 resolveSubscriptionForOperation(new SubscriptionResolverResult() { 624 @Override 625 public void onSuccess(int subId) { 626 ISms iSms = getISmsServiceOrThrow(); 627 try { 628 iSms.sendTextForSubscriber(subId, packageName, attributionTag, 629 destinationAddress, scAddress, text, sentIntent, deliveryIntent, 630 persistMessage, messageId); 631 } catch (RemoteException e) { 632 Log.e(TAG, "sendTextMessageInternal: Couldn't send SMS, exception - " 633 + e.getMessage() + " " + formatCrossStackMessageId(messageId)); 634 notifySmsError(sentIntent, RESULT_REMOTE_EXCEPTION); 635 } 636 } 637 638 @Override 639 public void onFailure() { 640 notifySmsError(sentIntent, RESULT_NO_DEFAULT_SMS_APP); 641 } 642 }); 643 } else { 644 // Not persisting the message, used by sendTextMessageWithoutPersisting() and is not 645 // visible to the user. 646 ISms iSms = getISmsServiceOrThrow(); 647 try { 648 iSms.sendTextForSubscriber(getSubscriptionId(), packageName, attributionTag, 649 destinationAddress, scAddress, text, sentIntent, deliveryIntent, 650 persistMessage, messageId); 651 } catch (RemoteException e) { 652 Log.e(TAG, "sendTextMessageInternal (no persist): Couldn't send SMS, exception - " 653 + e.getMessage() + " " + formatCrossStackMessageId(messageId)); 654 notifySmsError(sentIntent, RESULT_REMOTE_EXCEPTION); 655 } 656 } 657 } 658 659 /** 660 * Send a text based SMS without writing it into the SMS Provider. 661 * 662 * <p> 663 * The message will be sent directly over the network and will not be visible in SMS 664 * applications. Intended for internal carrier use only. 665 * </p> 666 * 667 * <p>Requires Permission: Both {@link android.Manifest.permission#SEND_SMS} and 668 * {@link android.Manifest.permission#MODIFY_PHONE_STATE}, or that the calling app has carrier 669 * privileges (see {@link TelephonyManager#hasCarrierPrivileges}), or that the calling app is 670 * the default IMS app (see 671 * {@link CarrierConfigManager#KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING}). 672 * </p> 673 * 674 * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier 675 * applications or the Telephony framework and will never trigger an SMS disambiguation 676 * dialog. If this method is called on a device that has multiple active subscriptions, this 677 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined 678 * default subscription is defined, the subscription ID associated with this message will be 679 * INVALID, which will result in the SMS being sent on the subscription associated with logical 680 * slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the SMS is sent on the 681 * correct subscription. 682 * </p> 683 * 684 * @see #sendTextMessage(String, String, String, PendingIntent, PendingIntent) 685 */ 686 @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges 687 @RequiresPermission(allOf = { 688 android.Manifest.permission.MODIFY_PHONE_STATE, 689 android.Manifest.permission.SEND_SMS 690 }) sendTextMessageWithoutPersisting( String destinationAddress, String scAddress, String text, PendingIntent sentIntent, PendingIntent deliveryIntent)691 public void sendTextMessageWithoutPersisting( 692 String destinationAddress, String scAddress, String text, 693 PendingIntent sentIntent, PendingIntent deliveryIntent) { 694 sendTextMessageInternal(destinationAddress, scAddress, text, sentIntent, deliveryIntent, 695 false /* persistMessage */, getOpPackageName(), 696 getAttributionTag(), 0L /* messageId */); 697 } 698 sendTextMessageInternal( String destinationAddress, String scAddress, String text, PendingIntent sentIntent, PendingIntent deliveryIntent, boolean persistMessage, int priority, boolean expectMore, int validityPeriod)699 private void sendTextMessageInternal( 700 String destinationAddress, String scAddress, String text, 701 PendingIntent sentIntent, PendingIntent deliveryIntent, boolean persistMessage, 702 int priority, boolean expectMore, int validityPeriod) { 703 if (TextUtils.isEmpty(destinationAddress)) { 704 throw new IllegalArgumentException("Invalid destinationAddress"); 705 } 706 707 if (TextUtils.isEmpty(text)) { 708 throw new IllegalArgumentException("Invalid message body"); 709 } 710 711 if (priority < 0x00 || priority > 0x03) { 712 Log.e(TAG, "Invalid Priority " + priority); 713 priority = SMS_MESSAGE_PRIORITY_NOT_SPECIFIED; 714 } 715 716 if (validityPeriod < 0x05 || validityPeriod > 0x09b0a0) { 717 Log.e(TAG, "Invalid Validity Period " + validityPeriod); 718 validityPeriod = SMS_MESSAGE_PERIOD_NOT_SPECIFIED; 719 } 720 721 final int finalPriority = priority; 722 final int finalValidity = validityPeriod; 723 // We will only show the SMS disambiguation dialog in the case that the message is being 724 // persisted. This is for two reasons: 725 // 1) Messages that are not persisted are sent by carrier/OEM apps for a specific 726 // subscription and require special permissions. These messages are usually not sent by 727 // the device user and should not have an SMS disambiguation dialog associated with them 728 // because the device user did not trigger them. 729 // 2) The SMS disambiguation dialog ONLY checks to make sure that the user has the SEND_SMS 730 // permission. If we call resolveSubscriptionForOperation from a carrier/OEM app that has 731 // the correct MODIFY_PHONE_STATE or carrier permissions, but no SEND_SMS, it will throw 732 // an incorrect SecurityException. 733 if (persistMessage) { 734 resolveSubscriptionForOperation(new SubscriptionResolverResult() { 735 @Override 736 public void onSuccess(int subId) { 737 try { 738 ISms iSms = getISmsServiceOrThrow(); 739 if (iSms != null) { 740 iSms.sendTextForSubscriberWithOptions(subId, 741 null, null, destinationAddress, 742 scAddress, 743 text, sentIntent, deliveryIntent, persistMessage, finalPriority, 744 expectMore, finalValidity); 745 } 746 } catch (RemoteException e) { 747 Log.e(TAG, "sendTextMessageInternal: Couldn't send SMS, exception - " 748 + e.getMessage()); 749 notifySmsError(sentIntent, RESULT_REMOTE_EXCEPTION); 750 } 751 } 752 753 @Override 754 public void onFailure() { 755 notifySmsError(sentIntent, RESULT_NO_DEFAULT_SMS_APP); 756 } 757 }); 758 } else { 759 try { 760 ISms iSms = getISmsServiceOrThrow(); 761 if (iSms != null) { 762 iSms.sendTextForSubscriberWithOptions(getSubscriptionId(), 763 null, null, destinationAddress, 764 scAddress, 765 text, sentIntent, deliveryIntent, persistMessage, finalPriority, 766 expectMore, finalValidity); 767 } 768 } catch (RemoteException e) { 769 Log.e(TAG, "sendTextMessageInternal(no persist): Couldn't send SMS, exception - " 770 + e.getMessage()); 771 notifySmsError(sentIntent, RESULT_REMOTE_EXCEPTION); 772 } 773 } 774 } 775 776 /** 777 * Send a text based SMS without writing it into the SMS Provider. 778 * 779 * <p>Requires Permission: 780 * {@link android.Manifest.permission#MODIFY_PHONE_STATE} or the calling app has carrier 781 * privileges. 782 * </p> 783 * 784 * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier 785 * applications or the Telephony framework and will never trigger an SMS disambiguation 786 * dialog. If this method is called on a device that has multiple active subscriptions, this 787 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined 788 * default subscription is defined, the subscription ID associated with this message will be 789 * INVALID, which will result in the SMS being sent on the subscription associated with logical 790 * slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the SMS is sent on the 791 * correct subscription. 792 * </p> 793 * 794 * @see #sendTextMessage(String, String, String, PendingIntent, 795 * PendingIntent, int, boolean, int) 796 * @hide 797 */ 798 @UnsupportedAppUsage sendTextMessageWithoutPersisting( String destinationAddress, String scAddress, String text, PendingIntent sentIntent, PendingIntent deliveryIntent, int priority, boolean expectMore, int validityPeriod)799 public void sendTextMessageWithoutPersisting( 800 String destinationAddress, String scAddress, String text, 801 PendingIntent sentIntent, PendingIntent deliveryIntent, int priority, 802 boolean expectMore, int validityPeriod) { 803 sendTextMessageInternal(destinationAddress, scAddress, text, sentIntent, deliveryIntent, 804 false /* persistMessage */, priority, expectMore, validityPeriod); 805 } 806 807 /** 808 * 809 * Inject an SMS PDU into the android application framework. 810 * 811 * <p>Requires permission: {@link android.Manifest.permission#MODIFY_PHONE_STATE} or carrier 812 * privileges per {@link android.telephony.TelephonyManager#hasCarrierPrivileges}. 813 * 814 * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier 815 * applications or the Telephony framework and will never trigger an SMS disambiguation 816 * dialog. If this method is called on a device that has multiple active subscriptions, this 817 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined 818 * default subscription is defined, the subscription ID associated with this message will be 819 * INVALID, which will result in the SMS being injected on the subscription associated with 820 * logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the SMS is 821 * delivered to the correct subscription. 822 * </p> 823 * 824 * @param pdu is the byte array of pdu to be injected into android application framework 825 * @param format is the format of SMS pdu ({@link SmsMessage#FORMAT_3GPP} or 826 * {@link SmsMessage#FORMAT_3GPP2}) 827 * @param receivedIntent if not NULL this <code>PendingIntent</code> is 828 * broadcast when the message is successfully received by the 829 * android application framework, or failed. This intent is broadcasted at 830 * the same time an SMS received from radio is acknowledged back. 831 * The result code will be {@link android.provider.Telephony.Sms.Intents#RESULT_SMS_HANDLED} 832 * for success, or {@link android.provider.Telephony.Sms.Intents#RESULT_SMS_GENERIC_ERROR} or 833 * {@link #RESULT_REMOTE_EXCEPTION} for error. 834 * 835 * @throws IllegalArgumentException if the format is invalid. 836 */ injectSmsPdu( byte[] pdu, @SmsMessage.Format String format, PendingIntent receivedIntent)837 public void injectSmsPdu( 838 byte[] pdu, @SmsMessage.Format String format, PendingIntent receivedIntent) { 839 if (!format.equals(SmsMessage.FORMAT_3GPP) && !format.equals(SmsMessage.FORMAT_3GPP2)) { 840 // Format must be either 3gpp or 3gpp2. 841 throw new IllegalArgumentException( 842 "Invalid pdu format. format must be either 3gpp or 3gpp2"); 843 } 844 try { 845 ISms iSms = TelephonyManager.getSmsService(); 846 if (iSms != null) { 847 iSms.injectSmsPduForSubscriber( 848 getSubscriptionId(), pdu, format, receivedIntent); 849 } 850 } catch (RemoteException ex) { 851 try { 852 if (receivedIntent != null) { 853 receivedIntent.send(RESULT_REMOTE_EXCEPTION); 854 } 855 } catch (PendingIntent.CanceledException cx) { 856 // Don't worry about it, we do not need to notify the caller if this is the case. 857 } 858 } 859 } 860 861 /** 862 * Divide a message text into several fragments, none bigger than the maximum SMS message size. 863 * 864 * @param text the original message. Must not be null. 865 * @return an <code>ArrayList</code> of strings that, in order, comprise the original message. 866 * @throws IllegalArgumentException if text is null. 867 */ divideMessage(String text)868 public ArrayList<String> divideMessage(String text) { 869 if (null == text) { 870 throw new IllegalArgumentException("text is null"); 871 } 872 return SmsMessage.fragmentText(text, getSubscriptionId()); 873 } 874 875 /** 876 * Send a multi-part text based SMS. The callee should have already 877 * divided the message into correctly sized parts by calling 878 * <code>divideMessage</code>. 879 * 880 * <p class="note"><strong>Note:</strong> Using this method requires that your app has the 881 * {@link android.Manifest.permission#SEND_SMS} permission.</p> 882 * 883 * <p class="note"><strong>Note:</strong> Beginning with Android 4.4 (API level 19), if 884 * <em>and only if</em> an app is not selected as the default SMS app, the system automatically 885 * writes messages sent using this method to the SMS Provider (the default SMS app is always 886 * responsible for writing its sent messages to the SMS Provider). For information about 887 * how to behave as the default SMS app, see {@link android.provider.Telephony}.</p> 888 * 889 * <p class="note"><strong>Note:</strong> If {@link #getDefault()} is used to instantiate this 890 * manager on a multi-SIM device, this operation may fail sending the SMS message because no 891 * suitable default subscription could be found. In this case, if {@code sentIntent} is 892 * non-null, then the {@link PendingIntent} will be sent with an error code 893 * {@code RESULT_ERROR_GENERIC_FAILURE} and an extra string {@code "noDefault"} containing the 894 * boolean value {@code true}. See {@link #getDefault()} for more information on the conditions 895 * where this operation may fail. 896 * </p> 897 * 898 * @param destinationAddress the address to send the message to 899 * @param scAddress is the service center address or null to use 900 * the current default SMSC 901 * @param parts an <code>ArrayList</code> of strings that, in order, 902 * comprise the original message 903 * @param sentIntents if not null, an <code>ArrayList</code> of 904 * <code>PendingIntent</code>s (one for each message part) that is 905 * broadcast when the corresponding message part has been sent. 906 * The result code will be <code>Activity.RESULT_OK</code> for success, 907 * or one of these errors:<br> 908 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 909 * <code>RESULT_ERROR_RADIO_OFF</code><br> 910 * <code>RESULT_ERROR_NULL_PDU</code><br> 911 * <code>RESULT_ERROR_NO_SERVICE</code><br> 912 * <code>RESULT_ERROR_LIMIT_EXCEEDED</code><br> 913 * <code>RESULT_ERROR_FDN_CHECK_FAILURE</code><br> 914 * <code>RESULT_ERROR_SHORT_CODE_NOT_ALLOWED</code><br> 915 * <code>RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED</code><br> 916 * <code>RESULT_RADIO_NOT_AVAILABLE</code><br> 917 * <code>RESULT_NETWORK_REJECT</code><br> 918 * <code>RESULT_INVALID_ARGUMENTS</code><br> 919 * <code>RESULT_INVALID_STATE</code><br> 920 * <code>RESULT_NO_MEMORY</code><br> 921 * <code>RESULT_INVALID_SMS_FORMAT</code><br> 922 * <code>RESULT_SYSTEM_ERROR</code><br> 923 * <code>RESULT_MODEM_ERROR</code><br> 924 * <code>RESULT_NETWORK_ERROR</code><br> 925 * <code>RESULT_ENCODING_ERROR</code><br> 926 * <code>RESULT_INVALID_SMSC_ADDRESS</code><br> 927 * <code>RESULT_OPERATION_NOT_ALLOWED</code><br> 928 * <code>RESULT_INTERNAL_ERROR</code><br> 929 * <code>RESULT_NO_RESOURCES</code><br> 930 * <code>RESULT_CANCELLED</code><br> 931 * <code>RESULT_REQUEST_NOT_SUPPORTED</code><br> 932 * <code>RESULT_NO_BLUETOOTH_SERVICE</code><br> 933 * <code>RESULT_INVALID_BLUETOOTH_ADDRESS</code><br> 934 * <code>RESULT_BLUETOOTH_DISCONNECTED</code><br> 935 * <code>RESULT_UNEXPECTED_EVENT_STOP_SENDING</code><br> 936 * <code>RESULT_SMS_BLOCKED_DURING_EMERGENCY</code><br> 937 * <code>RESULT_SMS_SEND_RETRY_FAILED</code><br> 938 * <code>RESULT_REMOTE_EXCEPTION</code><br> 939 * <code>RESULT_NO_DEFAULT_SMS_APP</code><br> 940 * <code>RESULT_RIL_RADIO_NOT_AVAILABLE</code><br> 941 * <code>RESULT_RIL_SMS_SEND_FAIL_RETRY</code><br> 942 * <code>RESULT_RIL_NETWORK_REJECT</code><br> 943 * <code>RESULT_RIL_INVALID_STATE</code><br> 944 * <code>RESULT_RIL_INVALID_ARGUMENTS</code><br> 945 * <code>RESULT_RIL_NO_MEMORY</code><br> 946 * <code>RESULT_RIL_REQUEST_RATE_LIMITED</code><br> 947 * <code>RESULT_RIL_INVALID_SMS_FORMAT</code><br> 948 * <code>RESULT_RIL_SYSTEM_ERR</code><br> 949 * <code>RESULT_RIL_ENCODING_ERR</code><br> 950 * <code>RESULT_RIL_INVALID_SMSC_ADDRESS</code><br> 951 * <code>RESULT_RIL_MODEM_ERR</code><br> 952 * <code>RESULT_RIL_NETWORK_ERR</code><br> 953 * <code>RESULT_RIL_INTERNAL_ERR</code><br> 954 * <code>RESULT_RIL_REQUEST_NOT_SUPPORTED</code><br> 955 * <code>RESULT_RIL_INVALID_MODEM_STATE</code><br> 956 * <code>RESULT_RIL_NETWORK_NOT_READY</code><br> 957 * <code>RESULT_RIL_OPERATION_NOT_ALLOWED</code><br> 958 * <code>RESULT_RIL_NO_RESOURCES</code><br> 959 * <code>RESULT_RIL_CANCELLED</code><br> 960 * <code>RESULT_RIL_SIM_ABSENT</code><br> 961 * <code>RESULT_RIL_SIMULTANEOUS_SMS_AND_CALL_NOT_ALLOWED</code><br> 962 * <code>RESULT_RIL_ACCESS_BARRED</code><br> 963 * <code>RESULT_RIL_BLOCKED_DUE_TO_CALL</code><br> 964 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> or any of the RESULT_RIL errors, 965 * the sentIntent may include the extra "errorCode" containing a radio technology specific 966 * value, generally only useful for troubleshooting.<br> 967 * @param deliveryIntents if not null, an <code>ArrayList</code> of 968 * <code>PendingIntent</code>s (one for each message part) that is 969 * broadcast when the corresponding message part has been delivered 970 * to the recipient. The raw pdu of the status report is in the 971 * extended data ("pdu"). 972 * 973 * @throws IllegalArgumentException if destinationAddress or data are empty 974 */ sendMultipartTextMessage( String destinationAddress, String scAddress, ArrayList<String> parts, ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents)975 public void sendMultipartTextMessage( 976 String destinationAddress, String scAddress, ArrayList<String> parts, 977 ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) { 978 sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents, 979 deliveryIntents, true /* persistMessage*/, getOpPackageName(), 980 getAttributionTag(), 0L /* messageId */); 981 } 982 983 /** 984 * Send a multi-part text based SMS. Same as #sendMultipartTextMessage(String, String, 985 * ArrayList, ArrayList, ArrayList), but adds an optional messageId. 986 * @param messageId An id that uniquely identifies the message requested to be sent. 987 * Used for logging and diagnostics purposes. The id may be 0. 988 * 989 * @throws IllegalArgumentException if destinationAddress or data are empty 990 * 991 */ sendMultipartTextMessage( @onNull String destinationAddress, @Nullable String scAddress, @NonNull List<String> parts, @Nullable List<PendingIntent> sentIntents, @Nullable List<PendingIntent> deliveryIntents, long messageId)992 public void sendMultipartTextMessage( 993 @NonNull String destinationAddress, @Nullable String scAddress, 994 @NonNull List<String> parts, @Nullable List<PendingIntent> sentIntents, 995 @Nullable List<PendingIntent> deliveryIntents, long messageId) { 996 sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents, 997 deliveryIntents, true /* persistMessage*/, getOpPackageName(), 998 getAttributionTag(), messageId); 999 } 1000 1001 /** 1002 * Similar method as #sendMultipartTextMessage(String, String, ArrayList, ArrayList, ArrayList) 1003 * With an additional argument. 1004 * 1005 * <p class="note"><strong>Note:</strong> This method is intended for internal use the Telephony 1006 * framework and will never trigger an SMS disambiguation dialog. If this method is called on a 1007 * device that has multiple active subscriptions, this {@link SmsManager} instance has been 1008 * created with {@link #getDefault()}, and no user-defined default subscription is defined, the 1009 * subscription ID associated with this message will be INVALID, which will result in the SMS 1010 * being sent on the subscription associated with logical slot 0. Use 1011 * {@link #getSmsManagerForSubscriptionId(int)} to ensure the SMS is sent on the correct 1012 * subscription. 1013 * </p> 1014 * 1015 * @param packageName serves as the default package name if the package name that is 1016 * associated with the user id is null. 1017 */ sendMultipartTextMessage( @onNull String destinationAddress, @Nullable String scAddress, @NonNull List<String> parts, @Nullable List<PendingIntent> sentIntents, @Nullable List<PendingIntent> deliveryIntents, @NonNull String packageName, @Nullable String attributionTag)1018 public void sendMultipartTextMessage( 1019 @NonNull String destinationAddress, @Nullable String scAddress, 1020 @NonNull List<String> parts, @Nullable List<PendingIntent> sentIntents, 1021 @Nullable List<PendingIntent> deliveryIntents, @NonNull String packageName, 1022 @Nullable String attributionTag) { 1023 sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents, 1024 deliveryIntents, true /* persistMessage*/, packageName, attributionTag, 1025 0L /* messageId */); 1026 } 1027 sendMultipartTextMessageInternal( String destinationAddress, String scAddress, List<String> parts, List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents, boolean persistMessage, String packageName, @Nullable String attributionTag, long messageId)1028 private void sendMultipartTextMessageInternal( 1029 String destinationAddress, String scAddress, List<String> parts, 1030 List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents, 1031 boolean persistMessage, String packageName, @Nullable String attributionTag, 1032 long messageId) { 1033 if (TextUtils.isEmpty(destinationAddress)) { 1034 throw new IllegalArgumentException("Invalid destinationAddress"); 1035 } 1036 if (parts == null || parts.size() < 1) { 1037 throw new IllegalArgumentException("Invalid message body"); 1038 } 1039 1040 if (parts.size() > 1) { 1041 // We will only show the SMS disambiguation dialog in the case that the message is being 1042 // persisted. This is for two reasons: 1043 // 1) Messages that are not persisted are sent by carrier/OEM apps for a specific 1044 // subscription and require special permissions. These messages are usually not sent 1045 // by the device user and should not have an SMS disambiguation dialog associated 1046 // with them because the device user did not trigger them. 1047 // 2) The SMS disambiguation dialog ONLY checks to make sure that the user has the 1048 // SEND_SMS permission. If we call resolveSubscriptionForOperation from a carrier/OEM 1049 // app that has the correct MODIFY_PHONE_STATE or carrier permissions, but no 1050 // SEND_SMS, it will throw an incorrect SecurityException. 1051 if (persistMessage) { 1052 resolveSubscriptionForOperation(new SubscriptionResolverResult() { 1053 @Override 1054 public void onSuccess(int subId) { 1055 try { 1056 ISms iSms = getISmsServiceOrThrow(); 1057 iSms.sendMultipartTextForSubscriber(subId, packageName, attributionTag, 1058 destinationAddress, scAddress, parts, sentIntents, 1059 deliveryIntents, persistMessage, messageId); 1060 } catch (RemoteException e) { 1061 Log.e(TAG, "sendMultipartTextMessageInternal: Couldn't send SMS - " 1062 + e.getMessage() + " " + formatCrossStackMessageId(messageId)); 1063 notifySmsError(sentIntents, RESULT_REMOTE_EXCEPTION); 1064 } 1065 } 1066 1067 @Override 1068 public void onFailure() { 1069 notifySmsError(sentIntents, RESULT_NO_DEFAULT_SMS_APP); 1070 } 1071 }); 1072 } else { 1073 // Called by apps that are not user facing, don't show disambiguation dialog. 1074 try { 1075 ISms iSms = getISmsServiceOrThrow(); 1076 if (iSms != null) { 1077 iSms.sendMultipartTextForSubscriber(getSubscriptionId(), packageName, 1078 attributionTag, destinationAddress, scAddress, parts, sentIntents, 1079 deliveryIntents, persistMessage, messageId); 1080 } 1081 } catch (RemoteException e) { 1082 Log.e(TAG, "sendMultipartTextMessageInternal: Couldn't send SMS - " 1083 + e.getMessage() + " " + formatCrossStackMessageId(messageId)); 1084 notifySmsError(sentIntents, RESULT_REMOTE_EXCEPTION); 1085 } 1086 } 1087 } else { 1088 PendingIntent sentIntent = null; 1089 PendingIntent deliveryIntent = null; 1090 if (sentIntents != null && sentIntents.size() > 0) { 1091 sentIntent = sentIntents.get(0); 1092 } 1093 if (deliveryIntents != null && deliveryIntents.size() > 0) { 1094 deliveryIntent = deliveryIntents.get(0); 1095 } 1096 sendTextMessageInternal(destinationAddress, scAddress, parts.get(0), 1097 sentIntent, deliveryIntent, true, packageName, attributionTag, messageId); 1098 } 1099 } 1100 1101 /** 1102 * Send a multi-part text based SMS without writing it into the SMS Provider. 1103 * 1104 * <p> 1105 * If this method is called on a device with multiple active subscriptions, this 1106 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined 1107 * default subscription is defined, the subscription ID associated with this message will be 1108 * INVALID, which will result in the SMS sent on the subscription associated with slot 1109 * 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the SMS is sent using the 1110 * correct subscription. 1111 * </p> 1112 * 1113 * <p>Requires Permission: 1114 * {@link android.Manifest.permission#MODIFY_PHONE_STATE} or the calling app has carrier 1115 * privileges. 1116 * </p> 1117 * 1118 * @see #sendMultipartTextMessage(String, String, ArrayList, ArrayList, ArrayList) 1119 * @hide 1120 **/ 1121 @SystemApi 1122 @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) sendMultipartTextMessageWithoutPersisting( String destinationAddress, String scAddress, List<String> parts, List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents)1123 public void sendMultipartTextMessageWithoutPersisting( 1124 String destinationAddress, String scAddress, List<String> parts, 1125 List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents) { 1126 sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents, 1127 deliveryIntents, false /* persistMessage*/, getOpPackageName(), 1128 getAttributionTag(), 0L /* messageId */); 1129 } 1130 1131 /** 1132 * Send a multi-part text based SMS with messaging options. The callee should have already 1133 * divided the message into correctly sized parts by calling 1134 * <code>divideMessage</code>. 1135 * 1136 * <p class="note"><strong>Note:</strong> Using this method requires that your app has the 1137 * {@link android.Manifest.permission#SEND_SMS} permission.</p> 1138 * 1139 * <p class="note"><strong>Note:</strong> Beginning with Android 4.4 (API level 19), if 1140 * <em>and only if</em> an app is not selected as the default SMS app, the system automatically 1141 * writes messages sent using this method to the SMS Provider (the default SMS app is always 1142 * responsible for writing its sent messages to the SMS Provider). For information about 1143 * how to behave as the default SMS app, see {@link android.provider.Telephony}.</p> 1144 * 1145 * <p class="note"><strong>Note:</strong> If {@link #getDefault()} is used to instantiate this 1146 * manager on a multi-SIM device, this operation may fail sending the SMS message because no 1147 * suitable default subscription could be found. In this case, if {@code sentIntent} is 1148 * non-null, then the {@link PendingIntent} will be sent with an error code 1149 * {@code RESULT_ERROR_GENERIC_FAILURE} and an extra string {@code "noDefault"} containing the 1150 * boolean value {@code true}. See {@link #getDefault()} for more information on the conditions 1151 * where this operation may fail. 1152 * </p> 1153 * 1154 * @param destinationAddress the address to send the message to 1155 * @param scAddress is the service center address or null to use 1156 * the current default SMSC 1157 * @param parts an <code>ArrayList</code> of strings that, in order, 1158 * comprise the original message 1159 * @param sentIntents if not null, an <code>ArrayList</code> of 1160 * <code>PendingIntent</code>s (one for each message part) that is 1161 * broadcast when the corresponding message part has been sent. 1162 * The result code will be <code>Activity.RESULT_OK</code> for success, 1163 * or one of these errors:<br> 1164 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 1165 * <code>RESULT_ERROR_RADIO_OFF</code><br> 1166 * <code>RESULT_ERROR_NULL_PDU</code><br> 1167 * <code>RESULT_ERROR_NO_SERVICE</code><br> 1168 * <code>RESULT_ERROR_LIMIT_EXCEEDED</code><br> 1169 * <code>RESULT_ERROR_FDN_CHECK_FAILURE</code><br> 1170 * <code>RESULT_ERROR_SHORT_CODE_NOT_ALLOWED</code><br> 1171 * <code>RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED</code><br> 1172 * <code>RESULT_RADIO_NOT_AVAILABLE</code><br> 1173 * <code>RESULT_NETWORK_REJECT</code><br> 1174 * <code>RESULT_INVALID_ARGUMENTS</code><br> 1175 * <code>RESULT_INVALID_STATE</code><br> 1176 * <code>RESULT_NO_MEMORY</code><br> 1177 * <code>RESULT_INVALID_SMS_FORMAT</code><br> 1178 * <code>RESULT_SYSTEM_ERROR</code><br> 1179 * <code>RESULT_MODEM_ERROR</code><br> 1180 * <code>RESULT_NETWORK_ERROR</code><br> 1181 * <code>RESULT_ENCODING_ERROR</code><br> 1182 * <code>RESULT_INVALID_SMSC_ADDRESS</code><br> 1183 * <code>RESULT_OPERATION_NOT_ALLOWED</code><br> 1184 * <code>RESULT_INTERNAL_ERROR</code><br> 1185 * <code>RESULT_NO_RESOURCES</code><br> 1186 * <code>RESULT_CANCELLED</code><br> 1187 * <code>RESULT_REQUEST_NOT_SUPPORTED</code><br> 1188 * <code>RESULT_NO_BLUETOOTH_SERVICE</code><br> 1189 * <code>RESULT_INVALID_BLUETOOTH_ADDRESS</code><br> 1190 * <code>RESULT_BLUETOOTH_DISCONNECTED</code><br> 1191 * <code>RESULT_UNEXPECTED_EVENT_STOP_SENDING</code><br> 1192 * <code>RESULT_SMS_BLOCKED_DURING_EMERGENCY</code><br> 1193 * <code>RESULT_SMS_SEND_RETRY_FAILED</code><br> 1194 * <code>RESULT_REMOTE_EXCEPTION</code><br> 1195 * <code>RESULT_NO_DEFAULT_SMS_APP</code><br> 1196 * <code>RESULT_RIL_RADIO_NOT_AVAILABLE</code><br> 1197 * <code>RESULT_RIL_SMS_SEND_FAIL_RETRY</code><br> 1198 * <code>RESULT_RIL_NETWORK_REJECT</code><br> 1199 * <code>RESULT_RIL_INVALID_STATE</code><br> 1200 * <code>RESULT_RIL_INVALID_ARGUMENTS</code><br> 1201 * <code>RESULT_RIL_NO_MEMORY</code><br> 1202 * <code>RESULT_RIL_REQUEST_RATE_LIMITED</code><br> 1203 * <code>RESULT_RIL_INVALID_SMS_FORMAT</code><br> 1204 * <code>RESULT_RIL_SYSTEM_ERR</code><br> 1205 * <code>RESULT_RIL_ENCODING_ERR</code><br> 1206 * <code>RESULT_RIL_INVALID_SMSC_ADDRESS</code><br> 1207 * <code>RESULT_RIL_MODEM_ERR</code><br> 1208 * <code>RESULT_RIL_NETWORK_ERR</code><br> 1209 * <code>RESULT_RIL_INTERNAL_ERR</code><br> 1210 * <code>RESULT_RIL_REQUEST_NOT_SUPPORTED</code><br> 1211 * <code>RESULT_RIL_INVALID_MODEM_STATE</code><br> 1212 * <code>RESULT_RIL_NETWORK_NOT_READY</code><br> 1213 * <code>RESULT_RIL_OPERATION_NOT_ALLOWED</code><br> 1214 * <code>RESULT_RIL_NO_RESOURCES</code><br> 1215 * <code>RESULT_RIL_CANCELLED</code><br> 1216 * <code>RESULT_RIL_SIM_ABSENT</code><br> 1217 * <code>RESULT_RIL_SIMULTANEOUS_SMS_AND_CALL_NOT_ALLOWED</code><br> 1218 * <code>RESULT_RIL_ACCESS_BARRED</code><br> 1219 * <code>RESULT_RIL_BLOCKED_DUE_TO_CALL</code><br> 1220 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> or any of the RESULT_RIL errors, 1221 * the sentIntent may include the extra "errorCode" containing a radio technology specific 1222 * value, generally only useful for troubleshooting.<br> 1223 * @param deliveryIntents if not null, an <code>ArrayList</code> of 1224 * <code>PendingIntent</code>s (one for each message part) that is 1225 * broadcast when the corresponding message part has been delivered 1226 * to the recipient. The raw pdu of the status report is in the 1227 * extended data ("pdu"). 1228 * @param priority Priority level of the message 1229 * Refer specification See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1 1230 * --------------------------------- 1231 * PRIORITY | Level of Priority 1232 * --------------------------------- 1233 * '00' | Normal 1234 * '01' | Interactive 1235 * '10' | Urgent 1236 * '11' | Emergency 1237 * ---------------------------------- 1238 * Any Other values included Negative considered as Invalid Priority Indicator of the message. 1239 * @param expectMore is a boolean to indicate the sending messages through same link or not. 1240 * @param validityPeriod Validity Period of the message in mins. 1241 * Refer specification 3GPP TS 23.040 V6.8.1 section 9.2.3.12.1. 1242 * Validity Period(Minimum) -> 5 mins 1243 * Validity Period(Maximum) -> 635040 mins(i.e.63 weeks). 1244 * Any Other values included Negative considered as Invalid Validity Period of the message. 1245 * 1246 * @throws IllegalArgumentException if destinationAddress or data are empty 1247 * {@hide} 1248 */ 1249 @UnsupportedAppUsage sendMultipartTextMessage( String destinationAddress, String scAddress, ArrayList<String> parts, ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents, int priority, boolean expectMore, int validityPeriod)1250 public void sendMultipartTextMessage( 1251 String destinationAddress, String scAddress, ArrayList<String> parts, 1252 ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents, 1253 int priority, boolean expectMore, int validityPeriod) { 1254 sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents, 1255 deliveryIntents, true /* persistMessage*/, priority, expectMore, 1256 validityPeriod); 1257 } 1258 sendMultipartTextMessageInternal( String destinationAddress, String scAddress, List<String> parts, List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents, boolean persistMessage, int priority, boolean expectMore, int validityPeriod)1259 private void sendMultipartTextMessageInternal( 1260 String destinationAddress, String scAddress, List<String> parts, 1261 List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents, 1262 boolean persistMessage, int priority, boolean expectMore, int validityPeriod) { 1263 if (TextUtils.isEmpty(destinationAddress)) { 1264 throw new IllegalArgumentException("Invalid destinationAddress"); 1265 } 1266 if (parts == null || parts.size() < 1) { 1267 throw new IllegalArgumentException("Invalid message body"); 1268 } 1269 1270 if (priority < 0x00 || priority > 0x03) { 1271 Log.e(TAG, "Invalid Priority " + priority); 1272 priority = SMS_MESSAGE_PRIORITY_NOT_SPECIFIED; 1273 } 1274 1275 if (validityPeriod < 0x05 || validityPeriod > 0x09b0a0) { 1276 Log.e(TAG, "Invalid Validity Period " + validityPeriod); 1277 validityPeriod = SMS_MESSAGE_PERIOD_NOT_SPECIFIED; 1278 } 1279 1280 if (parts.size() > 1) { 1281 final int finalPriority = priority; 1282 final int finalValidity = validityPeriod; 1283 if (persistMessage) { 1284 resolveSubscriptionForOperation(new SubscriptionResolverResult() { 1285 @Override 1286 public void onSuccess(int subId) { 1287 try { 1288 ISms iSms = getISmsServiceOrThrow(); 1289 if (iSms != null) { 1290 iSms.sendMultipartTextForSubscriberWithOptions(subId, 1291 null, null, destinationAddress, 1292 scAddress, parts, sentIntents, deliveryIntents, 1293 persistMessage, finalPriority, expectMore, finalValidity); 1294 } 1295 } catch (RemoteException e) { 1296 Log.e(TAG, "sendMultipartTextMessageInternal: Couldn't send SMS - " 1297 + e.getMessage()); 1298 notifySmsError(sentIntents, RESULT_REMOTE_EXCEPTION); 1299 } 1300 } 1301 1302 @Override 1303 public void onFailure() { 1304 notifySmsError(sentIntents, RESULT_NO_DEFAULT_SMS_APP); 1305 } 1306 }); 1307 } else { 1308 // Sent by apps that are not user visible, so don't show SIM disambiguation dialog. 1309 try { 1310 ISms iSms = getISmsServiceOrThrow(); 1311 if (iSms != null) { 1312 iSms.sendMultipartTextForSubscriberWithOptions(getSubscriptionId(), 1313 null, null, destinationAddress, 1314 scAddress, parts, sentIntents, deliveryIntents, 1315 persistMessage, finalPriority, expectMore, finalValidity); 1316 } 1317 } catch (RemoteException e) { 1318 Log.e(TAG, "sendMultipartTextMessageInternal (no persist): Couldn't send SMS - " 1319 + e.getMessage()); 1320 notifySmsError(sentIntents, RESULT_REMOTE_EXCEPTION); 1321 } 1322 } 1323 } else { 1324 PendingIntent sentIntent = null; 1325 PendingIntent deliveryIntent = null; 1326 if (sentIntents != null && sentIntents.size() > 0) { 1327 sentIntent = sentIntents.get(0); 1328 } 1329 if (deliveryIntents != null && deliveryIntents.size() > 0) { 1330 deliveryIntent = deliveryIntents.get(0); 1331 } 1332 sendTextMessageInternal(destinationAddress, scAddress, parts.get(0), 1333 sentIntent, deliveryIntent, persistMessage, priority, expectMore, 1334 validityPeriod); 1335 } 1336 } 1337 1338 /** 1339 * Send a data based SMS to a specific application port. 1340 * 1341 * <p class="note"><strong>Note:</strong> Using this method requires that your app has the 1342 * {@link android.Manifest.permission#SEND_SMS} permission.</p> 1343 * 1344 * <p class="note"><strong>Note:</strong> If {@link #getDefault()} is used to instantiate this 1345 * manager on a multi-SIM device, this operation may fail sending the SMS message because no 1346 * suitable default subscription could be found. In this case, if {@code sentIntent} is 1347 * non-null, then the {@link PendingIntent} will be sent with an error code 1348 * {@code RESULT_ERROR_GENERIC_FAILURE} and an extra string {@code "noDefault"} containing the 1349 * boolean value {@code true}. See {@link #getDefault()} for more information on the conditions 1350 * where this operation may fail. 1351 * </p> 1352 * 1353 * @param destinationAddress the address to send the message to 1354 * @param scAddress is the service center address or null to use 1355 * the current default SMSC 1356 * @param destinationPort the port to deliver the message to 1357 * @param data the body of the message to send 1358 * @param sentIntent if not NULL this <code>PendingIntent</code> is 1359 * broadcast when the message is successfully sent, or failed. 1360 * The result code will be <code>Activity.RESULT_OK</code> for success, 1361 * or one of these errors:<br> 1362 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 1363 * <code>RESULT_ERROR_RADIO_OFF</code><br> 1364 * <code>RESULT_ERROR_NULL_PDU</code><br> 1365 * <code>RESULT_ERROR_NO_SERVICE</code><br> 1366 * <code>RESULT_ERROR_LIMIT_EXCEEDED</code><br> 1367 * <code>RESULT_ERROR_FDN_CHECK_FAILURE</code><br> 1368 * <code>RESULT_ERROR_SHORT_CODE_NOT_ALLOWED</code><br> 1369 * <code>RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED</code><br> 1370 * <code>RESULT_RADIO_NOT_AVAILABLE</code><br> 1371 * <code>RESULT_NETWORK_REJECT</code><br> 1372 * <code>RESULT_INVALID_ARGUMENTS</code><br> 1373 * <code>RESULT_INVALID_STATE</code><br> 1374 * <code>RESULT_NO_MEMORY</code><br> 1375 * <code>RESULT_INVALID_SMS_FORMAT</code><br> 1376 * <code>RESULT_SYSTEM_ERROR</code><br> 1377 * <code>RESULT_MODEM_ERROR</code><br> 1378 * <code>RESULT_NETWORK_ERROR</code><br> 1379 * <code>RESULT_ENCODING_ERROR</code><br> 1380 * <code>RESULT_INVALID_SMSC_ADDRESS</code><br> 1381 * <code>RESULT_OPERATION_NOT_ALLOWED</code><br> 1382 * <code>RESULT_INTERNAL_ERROR</code><br> 1383 * <code>RESULT_NO_RESOURCES</code><br> 1384 * <code>RESULT_CANCELLED</code><br> 1385 * <code>RESULT_REQUEST_NOT_SUPPORTED</code><br> 1386 * <code>RESULT_NO_BLUETOOTH_SERVICE</code><br> 1387 * <code>RESULT_INVALID_BLUETOOTH_ADDRESS</code><br> 1388 * <code>RESULT_BLUETOOTH_DISCONNECTED</code><br> 1389 * <code>RESULT_UNEXPECTED_EVENT_STOP_SENDING</code><br> 1390 * <code>RESULT_SMS_BLOCKED_DURING_EMERGENCY</code><br> 1391 * <code>RESULT_SMS_SEND_RETRY_FAILED</code><br> 1392 * <code>RESULT_REMOTE_EXCEPTION</code><br> 1393 * <code>RESULT_NO_DEFAULT_SMS_APP</code><br> 1394 * <code>RESULT_RIL_RADIO_NOT_AVAILABLE</code><br> 1395 * <code>RESULT_RIL_SMS_SEND_FAIL_RETRY</code><br> 1396 * <code>RESULT_RIL_NETWORK_REJECT</code><br> 1397 * <code>RESULT_RIL_INVALID_STATE</code><br> 1398 * <code>RESULT_RIL_INVALID_ARGUMENTS</code><br> 1399 * <code>RESULT_RIL_NO_MEMORY</code><br> 1400 * <code>RESULT_RIL_REQUEST_RATE_LIMITED</code><br> 1401 * <code>RESULT_RIL_INVALID_SMS_FORMAT</code><br> 1402 * <code>RESULT_RIL_SYSTEM_ERR</code><br> 1403 * <code>RESULT_RIL_ENCODING_ERR</code><br> 1404 * <code>RESULT_RIL_INVALID_SMSC_ADDRESS</code><br> 1405 * <code>RESULT_RIL_MODEM_ERR</code><br> 1406 * <code>RESULT_RIL_NETWORK_ERR</code><br> 1407 * <code>RESULT_RIL_INTERNAL_ERR</code><br> 1408 * <code>RESULT_RIL_REQUEST_NOT_SUPPORTED</code><br> 1409 * <code>RESULT_RIL_INVALID_MODEM_STATE</code><br> 1410 * <code>RESULT_RIL_NETWORK_NOT_READY</code><br> 1411 * <code>RESULT_RIL_OPERATION_NOT_ALLOWED</code><br> 1412 * <code>RESULT_RIL_NO_RESOURCES</code><br> 1413 * <code>RESULT_RIL_CANCELLED</code><br> 1414 * <code>RESULT_RIL_SIM_ABSENT</code><br> 1415 * <code>RESULT_RIL_SIMULTANEOUS_SMS_AND_CALL_NOT_ALLOWED</code><br> 1416 * <code>RESULT_RIL_ACCESS_BARRED</code><br> 1417 * <code>RESULT_RIL_BLOCKED_DUE_TO_CALL</code><br> 1418 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> or any of the RESULT_RIL errors, 1419 * the sentIntent may include the extra "errorCode" containing a radio technology specific 1420 * value, generally only useful for troubleshooting.<br> 1421 * @param deliveryIntent if not NULL this <code>PendingIntent</code> is 1422 * broadcast when the message is delivered to the recipient. The 1423 * raw pdu of the status report is in the extended data ("pdu"). 1424 * 1425 * @throws IllegalArgumentException if destinationAddress or data are empty 1426 */ sendDataMessage( String destinationAddress, String scAddress, short destinationPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent)1427 public void sendDataMessage( 1428 String destinationAddress, String scAddress, short destinationPort, 1429 byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) { 1430 if (TextUtils.isEmpty(destinationAddress)) { 1431 throw new IllegalArgumentException("Invalid destinationAddress"); 1432 } 1433 1434 if (data == null || data.length == 0) { 1435 throw new IllegalArgumentException("Invalid message data"); 1436 } 1437 1438 resolveSubscriptionForOperation(new SubscriptionResolverResult() { 1439 @Override 1440 public void onSuccess(int subId) { 1441 try { 1442 ISms iSms = getISmsServiceOrThrow(); 1443 iSms.sendDataForSubscriber(subId, null, null, destinationAddress, scAddress, 1444 destinationPort & 0xFFFF, data, sentIntent, deliveryIntent); 1445 } catch (RemoteException e) { 1446 Log.e(TAG, "sendDataMessage: Couldn't send SMS - Exception: " + e.getMessage()); 1447 notifySmsError(sentIntent, RESULT_REMOTE_EXCEPTION); 1448 } 1449 } 1450 @Override 1451 public void onFailure() { 1452 notifySmsError(sentIntent, RESULT_NO_DEFAULT_SMS_APP); 1453 } 1454 }); 1455 } 1456 1457 /** 1458 * Get the SmsManager associated with the default subscription id. The instance will always be 1459 * associated with the default subscription id, even if the default subscription id changes. 1460 * 1461 * <p class="note"><strong>Note:</strong> For devices that support multiple active subscriptions 1462 * at a time, SmsManager will track the subscription set by the user as the default SMS 1463 * subscription. If the user has not set a default, {@link SmsManager} may 1464 * start an activity to kick off a subscription disambiguation dialog. Most operations will not 1465 * complete until the user has chosen the subscription that will be associated with the 1466 * operation. If the user cancels the dialog without choosing a subscription, one of the 1467 * following will happen, depending on the target SDK version of the application. For 1468 * compatibility purposes, if the target SDK level is <= 28, telephony will still send the SMS 1469 * over the first available subscription. If the target SDK level is > 28, the operation will 1470 * fail to complete. 1471 * </p> 1472 * 1473 * <p class="note"><strong>Note:</strong> If this method is used to perform an operation on a 1474 * device that has multiple active subscriptions, the user has not set a default SMS 1475 * subscription, and the operation is being performed while the application is not in the 1476 * foreground, the SMS disambiguation dialog will not be shown. The result of the operation will 1477 * conclude as if the user cancelled the disambiguation dialog and the operation will finish as 1478 * outlined above, depending on the target SDK version of the calling application. It is safer 1479 * to use {@link #getSmsManagerForSubscriptionId(int)} if the application will perform the 1480 * operation while in the background because this can cause unpredictable results, such as the 1481 * operation being sent over the wrong subscription or failing completely, depending on the 1482 * user's default SMS subscription setting. 1483 * </p> 1484 * 1485 * @return the {@link SmsManager} associated with the default subscription id. 1486 * 1487 * @see SubscriptionManager#getDefaultSmsSubscriptionId() 1488 * 1489 * @deprecated Use {@link Context#getSystemService Context.getSystemService(SmsManager.class)} 1490 * instead 1491 */ 1492 @Deprecated getDefault()1493 public static SmsManager getDefault() { 1494 return DEFAULT_INSTANCE; 1495 } 1496 1497 /** 1498 * Get the instance of the SmsManager associated with a particular context and subscription ID. 1499 * 1500 * @param context The context the manager belongs to 1501 * @param subId an SMS subscription ID, typically accessed using {@link SubscriptionManager} 1502 * 1503 * @return the instance of the SmsManager associated with subscription 1504 * 1505 * @hide 1506 */ getSmsManagerForContextAndSubscriptionId( @ullable Context context, int subId)1507 public static @NonNull SmsManager getSmsManagerForContextAndSubscriptionId( 1508 @Nullable Context context, int subId) { 1509 synchronized(sLockObject) { 1510 Pair<Context, Integer> key = new Pair<>(context, subId); 1511 1512 SmsManager smsManager = sSubInstances.get(key); 1513 if (smsManager == null) { 1514 smsManager = new SmsManager(context, subId); 1515 sSubInstances.put(key, smsManager); 1516 } 1517 return smsManager; 1518 } 1519 } 1520 1521 /** 1522 * Get the instance of the SmsManager associated with a particular subscription ID. 1523 * 1524 * <p class="note"><strong>Note:</strong> Constructing an {@link SmsManager} in this manner will 1525 * never cause an SMS disambiguation dialog to appear, unlike {@link #getDefault()}. 1526 * </p> 1527 * 1528 * @param subId an SMS subscription ID, typically accessed using {@link SubscriptionManager} 1529 * @return the instance of the SmsManager associated with subscription 1530 * 1531 * @see SubscriptionManager#getActiveSubscriptionInfoList() 1532 * @see SubscriptionManager#getDefaultSmsSubscriptionId() 1533 * @deprecated Use {@link Context#getSystemService Context.getSystemService(SmsManager.class)} 1534 * .{@link #createForSubscriptionId createForSubscriptionId(subId)} instead 1535 */ 1536 @Deprecated getSmsManagerForSubscriptionId(int subId)1537 public static SmsManager getSmsManagerForSubscriptionId(int subId) { 1538 return getSmsManagerForContextAndSubscriptionId(null, subId); 1539 } 1540 1541 /** 1542 * Get the instance of the SmsManager associated with a particular subscription ID. 1543 * 1544 * <p class="note"><strong>Note:</strong> Constructing an {@link SmsManager} in this manner will 1545 * never cause an SMS disambiguation dialog to appear, unlike {@link #getDefault()}. 1546 * </p> 1547 * 1548 * @param subId an SMS subscription ID, typically accessed using {@link SubscriptionManager} 1549 * @return the instance of the SmsManager associated with subscription 1550 * 1551 * @see SubscriptionManager#getActiveSubscriptionInfoList() 1552 * @see SubscriptionManager#getDefaultSmsSubscriptionId() 1553 */ createForSubscriptionId(int subId)1554 public @NonNull SmsManager createForSubscriptionId(int subId) { 1555 return getSmsManagerForContextAndSubscriptionId(mContext, subId); 1556 } 1557 SmsManager(@ullable Context context, int subId)1558 private SmsManager(@Nullable Context context, int subId) { 1559 mContext = context; 1560 mSubId = subId; 1561 } 1562 1563 /** 1564 * Get the associated subscription id. If the instance was returned by {@link #getDefault()}, 1565 * then this method may return different values at different points in time (if the user 1566 * changes the default subscription id). 1567 * 1568 * <p class="note"><strong>Note:</strong> This method used to display a disambiguation dialog to 1569 * the user asking them to choose a default subscription to send SMS messages over if they 1570 * haven't chosen yet. Starting in API level 29, we allow the user to not have a default set as 1571 * a valid option for the default SMS subscription on multi-SIM devices. We no longer show the 1572 * disambiguation dialog and return {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} if the 1573 * device has multiple active subscriptions and no default is set. 1574 * </p> 1575 * 1576 * @return associated subscription ID or {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} if 1577 * the default subscription id cannot be determined or the device has multiple active 1578 * subscriptions and and no default is set ("ask every time") by the user. 1579 */ getSubscriptionId()1580 public int getSubscriptionId() { 1581 try { 1582 return (mSubId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) 1583 ? getISmsServiceOrThrow().getPreferredSmsSubscription() : mSubId; 1584 } catch (RemoteException e) { 1585 return SubscriptionManager.INVALID_SUBSCRIPTION_ID; 1586 } 1587 } 1588 1589 /** 1590 * Resolves the subscription id to use for the associated operation if 1591 * {@link #getSubscriptionId()} returns {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID}. 1592 * 1593 * If app targets API level 28 or below and they are either sending the SMS from the background 1594 * or the device has more than one active subscription available and no default is set, we will 1595 * use the first logical slot to send the SMS and possibly fail later in the SMS sending 1596 * process. 1597 * 1598 * Regardless of the API level, if the app is the foreground app, then we will show the SMS 1599 * disambiguation dialog. If the app is in the background and tries to perform an operation, we 1600 * will not show the disambiguation dialog. 1601 * 1602 * See {@link #getDefault()} for a detailed explanation of how this method operates. 1603 * 1604 * @param resolverResult The callback that will be called when the subscription is resolved or 1605 * fails to be resolved. 1606 */ resolveSubscriptionForOperation(SubscriptionResolverResult resolverResult)1607 private void resolveSubscriptionForOperation(SubscriptionResolverResult resolverResult) { 1608 int subId = getSubscriptionId(); 1609 boolean isSmsSimPickActivityNeeded = false; 1610 try { 1611 ISms iSms = getISmsService(); 1612 if (iSms != null) { 1613 // Determines if the SMS SIM pick activity should be shown. This is only shown if: 1614 // 1) The device has multiple active subscriptions and an SMS default subscription 1615 // hasn't been set, and 1616 // 2) SmsManager is being called from the foreground app. 1617 // Android does not allow background activity starts, so we need to block this. 1618 // if Q+, do not perform requested operation if these two operations are not set. If 1619 // <P, perform these operations on phone 0 (for compatibility purposes, since we 1620 // used to not wait for the result of this activity). 1621 isSmsSimPickActivityNeeded = iSms.isSmsSimPickActivityNeeded(subId); 1622 } 1623 } catch (RemoteException ex) { 1624 Log.e(TAG, "resolveSubscriptionForOperation", ex); 1625 } 1626 if (!isSmsSimPickActivityNeeded) { 1627 sendResolverResult(resolverResult, subId, false /*pickActivityShown*/); 1628 return; 1629 } 1630 // We need to ask the user pick an appropriate subid for the operation. 1631 Log.d(TAG, "resolveSubscriptionForOperation isSmsSimPickActivityNeeded is true for calling" 1632 + " package. "); 1633 try { 1634 // Create the SMS pick activity and call back once the activity is complete. Can't do 1635 // it here because we do not have access to the activity context that is performing this 1636 // operation. 1637 // Requires that the calling process has the SEND_SMS permission. 1638 getITelephony().enqueueSmsPickResult(null, null, 1639 new IIntegerConsumer.Stub() { 1640 @Override 1641 public void accept(int subId) { 1642 // Runs on binder thread attached to this app's process. 1643 sendResolverResult(resolverResult, subId, true /*pickActivityShown*/); 1644 } 1645 }); 1646 } catch (RemoteException ex) { 1647 Log.e(TAG, "Unable to launch activity", ex); 1648 // pickActivityShown is true here because we want to call sendResolverResult and always 1649 // have this operation fail. This is because we received a RemoteException here, which 1650 // means that telephony is not available and the next operation to Telephony will fail 1651 // as well anyways, so we might as well shortcut fail here first. 1652 sendResolverResult(resolverResult, subId, true /*pickActivityShown*/); 1653 } 1654 } 1655 1656 /** 1657 * To check the SDK version for SmsManager.sendResolverResult method. 1658 */ 1659 @ChangeId 1660 @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.P) 1661 private static final long GET_TARGET_SDK_VERSION_CODE_CHANGE = 145147528L; 1662 sendResolverResult(SubscriptionResolverResult resolverResult, int subId, boolean pickActivityShown)1663 private void sendResolverResult(SubscriptionResolverResult resolverResult, int subId, 1664 boolean pickActivityShown) { 1665 if (SubscriptionManager.isValidSubscriptionId(subId)) { 1666 resolverResult.onSuccess(subId); 1667 return; 1668 } 1669 1670 if (!Compatibility.isChangeEnabled(GET_TARGET_SDK_VERSION_CODE_CHANGE) 1671 && !pickActivityShown) { 1672 // Do not fail, return a success with an INVALID subid for apps targeting P or below 1673 // that tried to perform an operation and the SMS disambiguation dialog was never shown, 1674 // as these applications may not have been written to handle the failure case properly. 1675 // This will resolve to performing the operation on phone 0 in telephony. 1676 resolverResult.onSuccess(subId); 1677 } else { 1678 // Fail if the app targets Q or above or it targets P and below and the disambiguation 1679 // dialog was shown and the user clicked out of it. 1680 resolverResult.onFailure(); 1681 } 1682 } 1683 getITelephony()1684 private static ITelephony getITelephony() { 1685 ITelephony binder = ITelephony.Stub.asInterface( 1686 TelephonyFrameworkInitializer 1687 .getTelephonyServiceManager() 1688 .getTelephonyServiceRegisterer() 1689 .get()); 1690 if (binder == null) { 1691 throw new RuntimeException("Could not find Telephony Service."); 1692 } 1693 return binder; 1694 } 1695 notifySmsError(PendingIntent pendingIntent, int error)1696 private static void notifySmsError(PendingIntent pendingIntent, int error) { 1697 if (pendingIntent != null) { 1698 try { 1699 pendingIntent.send(error); 1700 } catch (PendingIntent.CanceledException e) { 1701 // Don't worry about it, we do not need to notify the caller if this is the case. 1702 } 1703 } 1704 } 1705 notifySmsError(List<PendingIntent> pendingIntents, int error)1706 private static void notifySmsError(List<PendingIntent> pendingIntents, int error) { 1707 if (pendingIntents != null) { 1708 for (PendingIntent pendingIntent : pendingIntents) { 1709 notifySmsError(pendingIntent, error); 1710 } 1711 } 1712 } 1713 1714 /** 1715 * Returns the ISms service, or throws an UnsupportedOperationException if 1716 * the service does not exist. 1717 */ getISmsServiceOrThrow()1718 private static ISms getISmsServiceOrThrow() { 1719 ISms iSms = TelephonyManager.getSmsService(); 1720 if (iSms == null) { 1721 throw new UnsupportedOperationException("Sms is not supported"); 1722 } 1723 return iSms; 1724 } 1725 getISmsService()1726 private static ISms getISmsService() { 1727 return TelephonyManager.getSmsService(); 1728 } 1729 1730 /** 1731 * Copies a raw SMS PDU to the ICC. 1732 * ICC (Integrated Circuit Card) is the card of the device. 1733 * For example, this can be the SIM or USIM for GSM. 1734 * 1735 * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier 1736 * applications or the Telephony framework and will never trigger an SMS disambiguation 1737 * dialog. If this method is called on a device that has multiple active subscriptions, this 1738 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined 1739 * default subscription is defined, the subscription ID associated with this message will be 1740 * INVALID, which will result in the operation being completed on the subscription associated 1741 * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the 1742 * operation is performed on the correct subscription. 1743 * </p> 1744 * 1745 * @param smsc the SMSC for this messag or null for the default SMSC. 1746 * @param pdu the raw PDU to store. 1747 * @param status message status. One of these status: 1748 * <code>STATUS_ON_ICC_READ</code> 1749 * <code>STATUS_ON_ICC_UNREAD</code> 1750 * <code>STATUS_ON_ICC_SENT</code> 1751 * <code>STATUS_ON_ICC_UNSENT</code> 1752 * @return true for success. Otherwise false. 1753 * 1754 * @throws IllegalArgumentException if pdu is null. 1755 * @hide 1756 */ 1757 @RequiresPermission(Manifest.permission.ACCESS_MESSAGES_ON_ICC) copyMessageToIcc( @ullable byte[] smsc, @NonNull byte[] pdu, @StatusOnIcc int status)1758 public boolean copyMessageToIcc( 1759 @Nullable byte[] smsc, @NonNull byte[] pdu, @StatusOnIcc int status) { 1760 boolean success = false; 1761 1762 if (pdu == null) { 1763 throw new IllegalArgumentException("pdu is null"); 1764 } 1765 try { 1766 ISms iSms = getISmsService(); 1767 if (iSms != null) { 1768 success = iSms.copyMessageToIccEfForSubscriber(getSubscriptionId(), 1769 null, 1770 status, pdu, smsc); 1771 } 1772 } catch (RemoteException ex) { 1773 // ignore it 1774 } 1775 1776 return success; 1777 } 1778 1779 /** 1780 * Deletes the specified message from the ICC. 1781 * ICC (Integrated Circuit Card) is the card of the device. 1782 * For example, this can be the SIM or USIM for GSM. 1783 * 1784 * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier 1785 * applications or the Telephony framework and will never trigger an SMS disambiguation 1786 * dialog. If this method is called on a device that has multiple active subscriptions, this 1787 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined 1788 * default subscription is defined, the subscription ID associated with this message will be 1789 * INVALID, which will result in the operation being completed on the subscription associated 1790 * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the 1791 * operation is performed on the correct subscription. 1792 * </p> 1793 * 1794 * @param messageIndex the message index of the message in the ICC (1-based index). 1795 * @return true for success, false if the operation fails. Failure can be due to IPC failure, 1796 * RIL/modem error which results in SMS failed to be deleted on SIM 1797 * 1798 * {@hide} 1799 */ 1800 @UnsupportedAppUsage 1801 @RequiresPermission(Manifest.permission.ACCESS_MESSAGES_ON_ICC) deleteMessageFromIcc(int messageIndex)1802 public boolean deleteMessageFromIcc(int messageIndex) { 1803 boolean success = false; 1804 1805 try { 1806 ISms iSms = getISmsService(); 1807 if (iSms != null) { 1808 success = iSms.updateMessageOnIccEfForSubscriber(getSubscriptionId(), 1809 null, 1810 messageIndex, STATUS_ON_ICC_FREE, null /* pdu */); 1811 } 1812 } catch (RemoteException ex) { 1813 // ignore it 1814 } 1815 1816 return success; 1817 } 1818 1819 /** 1820 * Update the specified message on the ICC. 1821 * ICC (Integrated Circuit Card) is the card of the device. 1822 * For example, this can be the SIM or USIM for GSM. 1823 * 1824 * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier 1825 * applications or the Telephony framework and will never trigger an SMS disambiguation 1826 * dialog. If this method is called on a device that has multiple active subscriptions, this 1827 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined 1828 * default subscription is defined, the subscription ID associated with this message will be 1829 * INVALID, which will result in the operation being completed on the subscription associated 1830 * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the 1831 * operation is performed on the correct subscription. 1832 * </p> 1833 * 1834 * @param messageIndex record index of message to update 1835 * @param newStatus new message status (STATUS_ON_ICC_READ, 1836 * STATUS_ON_ICC_UNREAD, STATUS_ON_ICC_SENT, 1837 * STATUS_ON_ICC_UNSENT, STATUS_ON_ICC_FREE) 1838 * @param pdu the raw PDU to store 1839 * @return true for success 1840 * 1841 * {@hide} 1842 */ 1843 @UnsupportedAppUsage 1844 @RequiresPermission(Manifest.permission.ACCESS_MESSAGES_ON_ICC) updateMessageOnIcc(int messageIndex, int newStatus, byte[] pdu)1845 public boolean updateMessageOnIcc(int messageIndex, int newStatus, byte[] pdu) { 1846 boolean success = false; 1847 1848 try { 1849 ISms iSms = getISmsService(); 1850 if (iSms != null) { 1851 success = iSms.updateMessageOnIccEfForSubscriber(getSubscriptionId(), 1852 null, 1853 messageIndex, newStatus, pdu); 1854 } 1855 } catch (RemoteException ex) { 1856 // ignore it 1857 } 1858 1859 return success; 1860 } 1861 1862 /** 1863 * Retrieves all messages currently stored on the ICC. 1864 * ICC (Integrated Circuit Card) is the card of the device. 1865 * For example, this can be the SIM or USIM for GSM. 1866 * 1867 * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier 1868 * applications or the Telephony framework and will never trigger an SMS disambiguation 1869 * dialog. If this method is called on a device that has multiple active subscriptions, this 1870 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined 1871 * default subscription is defined, the subscription ID associated with this message will be 1872 * INVALID, which will result in the operation being completed on the subscription associated 1873 * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the 1874 * operation is performed on the correct subscription. 1875 * </p> 1876 * 1877 * @return <code>List</code> of <code>SmsMessage</code> objects for valid records only. 1878 * 1879 * {@hide} 1880 */ 1881 @RequiresPermission(Manifest.permission.ACCESS_MESSAGES_ON_ICC) getMessagesFromIcc()1882 public @NonNull List<SmsMessage> getMessagesFromIcc() { 1883 return getAllMessagesFromIcc(); 1884 } 1885 1886 /** 1887 * @return <code>ArrayList</code> of <code>SmsMessage</code> objects 1888 * 1889 * This is similar to {@link #getMessagesFromIcc} except that it will return ArrayList. 1890 * Suggested to use {@link #getMessagesFromIcc} instead. 1891 * 1892 * {@hide} 1893 */ 1894 @UnsupportedAppUsage getAllMessagesFromIcc()1895 public ArrayList<SmsMessage> getAllMessagesFromIcc() { 1896 List<SmsRawData> records = null; 1897 1898 try { 1899 ISms iSms = getISmsService(); 1900 if (iSms != null) { 1901 records = iSms.getAllMessagesFromIccEfForSubscriber( 1902 getSubscriptionId(), 1903 null); 1904 } 1905 } catch (RemoteException ex) { 1906 // ignore it 1907 } 1908 1909 return createMessageListFromRawRecords(records); 1910 } 1911 1912 /** 1913 * Enable reception of cell broadcast (SMS-CB) messages with the given 1914 * message identifier range and RAN type. The RAN type specifies if this message ID 1915 * belongs to 3GPP (GSM) or 3GPP2(CDMA). Note that if two different clients enable 1916 * the same message identifier, they must both disable it for the device to stop 1917 * receiving those messages. All received messages will be broadcast in an 1918 * intent with the action "android.provider.Telephony.SMS_CB_RECEIVED". 1919 * Note: This call is blocking, callers may want to avoid calling it from 1920 * the main thread of an application. 1921 * 1922 * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier 1923 * applications or the Telephony framework and will never trigger an SMS disambiguation 1924 * dialog. If this method is called on a device that has multiple active subscriptions, this 1925 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined 1926 * default subscription is defined, the subscription ID associated with this message will be 1927 * {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID}, which will result in the operation 1928 * being completed on the subscription associated with logical slot 0. Use 1929 * {@link #getSmsManagerForSubscriptionId(int)} to ensure the operation is performed on the 1930 * correct subscription. 1931 * </p> 1932 * 1933 * <p>Requires {@link android.Manifest.permission#RECEIVE_EMERGENCY_BROADCAST}</p> 1934 * 1935 * @param startMessageId first message identifier as specified in TS 23.041 (3GPP) 1936 * or C.R1001-G (3GPP2) 1937 * @param endMessageId last message identifier as specified in TS 23.041 (3GPP) 1938 * or C.R1001-G (3GPP2) 1939 * @param ranType the message format as defined in {@link SmsCbMessage} 1940 * @return true if successful, false if the modem reports a failure (e.g. the given range or 1941 * RAN type is invalid). 1942 * @see #disableCellBroadcastRange(int, int, int) 1943 * 1944 * @throws IllegalArgumentException if endMessageId < startMessageId 1945 * {@hide} 1946 */ 1947 @SystemApi enableCellBroadcastRange(int startMessageId, int endMessageId, @android.telephony.SmsCbMessage.MessageFormat int ranType)1948 public boolean enableCellBroadcastRange(int startMessageId, int endMessageId, 1949 @android.telephony.SmsCbMessage.MessageFormat int ranType) { 1950 boolean success = false; 1951 if (endMessageId < startMessageId) { 1952 throw new IllegalArgumentException("endMessageId < startMessageId"); 1953 } 1954 try { 1955 ISms iSms = getISmsService(); 1956 if (iSms != null) { 1957 // If getSubscriptionId() returns INVALID or an inactive subscription, we will use 1958 // the default phone internally. 1959 int subId = getSubscriptionId(); 1960 success = iSms.enableCellBroadcastRangeForSubscriber(subId, 1961 startMessageId, endMessageId, ranType); 1962 Rlog.d(TAG, "enableCellBroadcastRange: " + (success ? "succeeded" : "failed") 1963 + " at calling enableCellBroadcastRangeForSubscriber. subId = " + subId); 1964 } 1965 } catch (RemoteException ex) { 1966 Rlog.d(TAG, "enableCellBroadcastRange: " + ex.getStackTrace()); 1967 // ignore it 1968 } 1969 1970 return success; 1971 } 1972 1973 /** 1974 * Disable reception of cell broadcast (SMS-CB) messages with the given 1975 * message identifier range and RAN type. The RAN type specify this message 1976 * ID range belong to 3GPP (GSM) or 3GPP2(CDMA). Note that if two different 1977 * clients enable the same message identifier, they must both disable it for 1978 * the device to stop receiving those messages. 1979 * Note: This call is blocking, callers may want to avoid calling it from 1980 * the main thread of an application. 1981 * 1982 * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier 1983 * applications or the Telephony framework and will never trigger an SMS disambiguation 1984 * dialog. If this method is called on a device that has multiple active subscriptions, this 1985 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined 1986 * default subscription is defined, the subscription ID associated with this message will be 1987 * INVALID, which will result in the operation being completed on the subscription associated 1988 * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the 1989 * operation is performed on the correct subscription. 1990 * </p> 1991 * 1992 * <p>Requires {@link android.Manifest.permission#RECEIVE_EMERGENCY_BROADCAST}</p> 1993 * 1994 * @param startMessageId first message identifier as specified in TS 23.041 (3GPP) 1995 * or C.R1001-G (3GPP2) 1996 * @param endMessageId last message identifier as specified in TS 23.041 (3GPP) 1997 * or C.R1001-G (3GPP2) 1998 * @param ranType the message format as defined in {@link SmsCbMessage} 1999 * @return true if successful, false if the modem reports a failure (e.g. the given range or 2000 * RAN type is invalid). 2001 * 2002 * @see #enableCellBroadcastRange(int, int, int) 2003 * 2004 * @throws IllegalArgumentException if endMessageId < startMessageId 2005 * {@hide} 2006 */ 2007 @SystemApi disableCellBroadcastRange(int startMessageId, int endMessageId, @android.telephony.SmsCbMessage.MessageFormat int ranType)2008 public boolean disableCellBroadcastRange(int startMessageId, int endMessageId, 2009 @android.telephony.SmsCbMessage.MessageFormat int ranType) { 2010 boolean success = false; 2011 2012 if (endMessageId < startMessageId) { 2013 throw new IllegalArgumentException("endMessageId < startMessageId"); 2014 } 2015 try { 2016 ISms iSms = getISmsService(); 2017 if (iSms != null) { 2018 // If getSubscriptionId() returns INVALID or an inactive subscription, we will use 2019 // the default phone internally. 2020 int subId = getSubscriptionId(); 2021 success = iSms.disableCellBroadcastRangeForSubscriber(subId, 2022 startMessageId, endMessageId, ranType); 2023 Rlog.d(TAG, "disableCellBroadcastRange: " + (success ? "succeeded" : "failed") 2024 + " at calling disableCellBroadcastRangeForSubscriber. subId = " + subId); 2025 } 2026 } catch (RemoteException ex) { 2027 Rlog.d(TAG, "disableCellBroadcastRange: " + ex.getStackTrace()); 2028 // ignore it 2029 } 2030 2031 return success; 2032 } 2033 2034 /** 2035 * Creates a list of <code>SmsMessage</code>s from a list of SmsRawData records. 2036 * 2037 * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier 2038 * applications or the Telephony framework and will never trigger an SMS disambiguation 2039 * dialog. If this method is called on a device that has multiple active subscriptions, this 2040 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined 2041 * default subscription is defined, the subscription ID associated with this message will be 2042 * INVALID, which will result in the operation being completed on the subscription associated 2043 * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the 2044 * operation is performed on the correct subscription. 2045 * </p> 2046 * 2047 * @param records SMS EF records. 2048 * @return <code>ArrayList</code> of <code>SmsMessage</code> objects. 2049 */ createMessageListFromRawRecords(List<SmsRawData> records)2050 private ArrayList<SmsMessage> createMessageListFromRawRecords(List<SmsRawData> records) { 2051 ArrayList<SmsMessage> messages = new ArrayList<SmsMessage>(); 2052 if (records != null) { 2053 int count = records.size(); 2054 for (int i = 0; i < count; i++) { 2055 SmsRawData data = records.get(i); 2056 // List contains all records, including "free" records (null) 2057 if (data != null) { 2058 SmsMessage sms = SmsMessage.createFromEfRecord(i + 1, data.getBytes(), 2059 getSubscriptionId()); 2060 if (sms != null) { 2061 messages.add(sms); 2062 } 2063 } 2064 } 2065 } 2066 return messages; 2067 } 2068 2069 /** 2070 * SMS over IMS is supported if IMS is registered and SMS is supported 2071 * on IMS. 2072 * 2073 * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier 2074 * applications or the Telephony framework and will never trigger an SMS disambiguation 2075 * dialog. If this method is called on a device that has multiple active subscriptions, this 2076 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined 2077 * default subscription is defined, the subscription ID associated with this message will be 2078 * INVALID, which will result in the operation being completed on the subscription associated 2079 * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the 2080 * operation is performed on the correct subscription. 2081 * </p> 2082 * 2083 * @return true if SMS over IMS is supported, false otherwise 2084 * 2085 * @see #getImsSmsFormat() 2086 * 2087 * @hide 2088 */ isImsSmsSupported()2089 public boolean isImsSmsSupported() { 2090 boolean boSupported = false; 2091 try { 2092 ISms iSms = getISmsService(); 2093 if (iSms != null) { 2094 boSupported = iSms.isImsSmsSupportedForSubscriber(getSubscriptionId()); 2095 } 2096 } catch (RemoteException ex) { 2097 // ignore it 2098 } 2099 return boSupported; 2100 } 2101 2102 /** 2103 * Gets SMS format supported on IMS. SMS over IMS format is either 3GPP or 3GPP2. 2104 * 2105 * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier 2106 * applications or the Telephony framework and will never trigger an SMS disambiguation 2107 * dialog. If this method is called on a device that has multiple active subscriptions, this 2108 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined 2109 * default subscription is defined, the subscription ID associated with this message will be 2110 * INVALID, which will result in the operation being completed on the subscription associated 2111 * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the 2112 * operation is performed on the correct subscription. 2113 * </p> 2114 * 2115 * @return SmsMessage.FORMAT_3GPP, 2116 * SmsMessage.FORMAT_3GPP2 2117 * or SmsMessage.FORMAT_UNKNOWN 2118 * 2119 * @see #isImsSmsSupported() 2120 * 2121 * @hide 2122 */ getImsSmsFormat()2123 public String getImsSmsFormat() { 2124 String format = com.android.internal.telephony.SmsConstants.FORMAT_UNKNOWN; 2125 try { 2126 ISms iSms = getISmsService(); 2127 if (iSms != null) { 2128 format = iSms.getImsSmsFormatForSubscriber(getSubscriptionId()); 2129 } 2130 } catch (RemoteException ex) { 2131 // ignore it 2132 } 2133 return format; 2134 } 2135 2136 /** 2137 * Get default sms subscription id. 2138 * 2139 * <p class="note"><strong>Note:</strong>This returns a value different from 2140 * {@link SubscriptionManager#getDefaultSmsSubscriptionId} if the user has not chosen a default. 2141 * In this case it returns the active subscription id if there's only one active subscription 2142 * available. 2143 * 2144 * @return the user-defined default SMS subscription id, or the active subscription id if 2145 * there's only one active subscription available, otherwise 2146 * {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID}. 2147 */ getDefaultSmsSubscriptionId()2148 public static int getDefaultSmsSubscriptionId() { 2149 try { 2150 return getISmsService().getPreferredSmsSubscription(); 2151 } catch (RemoteException e) { 2152 return SubscriptionManager.INVALID_SUBSCRIPTION_ID; 2153 } catch (NullPointerException e) { 2154 return SubscriptionManager.INVALID_SUBSCRIPTION_ID; 2155 } 2156 } 2157 2158 /** 2159 * Get SMS prompt property, enabled or not 2160 * 2161 * @return true if enabled, false otherwise 2162 * @hide 2163 */ 2164 @UnsupportedAppUsage isSMSPromptEnabled()2165 public boolean isSMSPromptEnabled() { 2166 ISms iSms = null; 2167 try { 2168 iSms = TelephonyManager.getSmsService(); 2169 return iSms.isSMSPromptEnabled(); 2170 } catch (RemoteException ex) { 2171 return false; 2172 } catch (NullPointerException ex) { 2173 return false; 2174 } 2175 } 2176 2177 /** 2178 * Gets the total capacity of SMS storage on the SIM card. 2179 * 2180 * <p> 2181 * This is the number of 176 byte EF-SMS records which can be stored on the SIM card. 2182 * See 3GPP TS 31.102 - 4.2.25 - EF-SMS for more information. 2183 * </p> 2184 * 2185 * <p class="note"><strong>Note:</strong> This method will never trigger an SMS disambiguation 2186 * dialog. If this method is called on a device that has multiple active subscriptions, this 2187 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined 2188 * default subscription is defined, the subscription ID associated with this method will be 2189 * INVALID, which will result in the operation being completed on the subscription associated 2190 * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the operation 2191 * is performed on the correct subscription. 2192 * </p> 2193 * 2194 * @return the total number of SMS records which can be stored on the SIM card. 2195 */ 2196 @RequiresPermission(anyOf = {android.Manifest.permission.READ_PHONE_STATE, 2197 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE}) 2198 @IntRange(from = 0) getSmsCapacityOnIcc()2199 public int getSmsCapacityOnIcc() { 2200 int ret = 0; 2201 try { 2202 ISms iccISms = getISmsService(); 2203 if (iccISms != null) { 2204 ret = iccISms.getSmsCapacityOnIccForSubscriber(getSubscriptionId()); 2205 } 2206 } catch (RemoteException ex) { 2207 Log.e(TAG, "getSmsCapacityOnIcc() RemoteException", ex); 2208 } 2209 return ret; 2210 } 2211 2212 /** @hide */ 2213 @IntDef(prefix = { "STATUS_ON_ICC_" }, value = { 2214 STATUS_ON_ICC_FREE, 2215 STATUS_ON_ICC_READ, 2216 STATUS_ON_ICC_UNREAD, 2217 STATUS_ON_ICC_SENT, 2218 STATUS_ON_ICC_UNSENT 2219 }) 2220 @Retention(RetentionPolicy.SOURCE) 2221 public @interface StatusOnIcc {} 2222 2223 // see SmsMessage.getStatusOnIcc 2224 2225 /** Free space (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ 2226 public static final int STATUS_ON_ICC_FREE = 0; 2227 2228 /** Received and read (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ 2229 public static final int STATUS_ON_ICC_READ = 1; 2230 2231 /** Received and unread (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ 2232 public static final int STATUS_ON_ICC_UNREAD = 3; 2233 2234 /** Stored and sent (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ 2235 public static final int STATUS_ON_ICC_SENT = 5; 2236 2237 /** Stored and unsent (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ 2238 public static final int STATUS_ON_ICC_UNSENT = 7; 2239 2240 // SMS send failure result codes 2241 2242 /** @hide */ 2243 @IntDef(prefix = { "RESULT" }, value = { 2244 RESULT_ERROR_NONE, 2245 RESULT_ERROR_GENERIC_FAILURE, 2246 RESULT_ERROR_RADIO_OFF, 2247 RESULT_ERROR_NULL_PDU, 2248 RESULT_ERROR_NO_SERVICE, 2249 RESULT_ERROR_LIMIT_EXCEEDED, 2250 RESULT_ERROR_FDN_CHECK_FAILURE, 2251 RESULT_ERROR_SHORT_CODE_NOT_ALLOWED, 2252 RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED, 2253 RESULT_RADIO_NOT_AVAILABLE, 2254 RESULT_NETWORK_REJECT, 2255 RESULT_INVALID_ARGUMENTS, 2256 RESULT_INVALID_STATE, 2257 RESULT_NO_MEMORY, 2258 RESULT_INVALID_SMS_FORMAT, 2259 RESULT_SYSTEM_ERROR, 2260 RESULT_MODEM_ERROR, 2261 RESULT_NETWORK_ERROR, 2262 RESULT_INVALID_SMSC_ADDRESS, 2263 RESULT_OPERATION_NOT_ALLOWED, 2264 RESULT_INTERNAL_ERROR, 2265 RESULT_NO_RESOURCES, 2266 RESULT_CANCELLED, 2267 RESULT_REQUEST_NOT_SUPPORTED, 2268 RESULT_NO_BLUETOOTH_SERVICE, 2269 RESULT_INVALID_BLUETOOTH_ADDRESS, 2270 RESULT_BLUETOOTH_DISCONNECTED, 2271 RESULT_UNEXPECTED_EVENT_STOP_SENDING, 2272 RESULT_SMS_BLOCKED_DURING_EMERGENCY, 2273 RESULT_SMS_SEND_RETRY_FAILED, 2274 RESULT_REMOTE_EXCEPTION, 2275 RESULT_NO_DEFAULT_SMS_APP, 2276 RESULT_RIL_RADIO_NOT_AVAILABLE, 2277 RESULT_RIL_SMS_SEND_FAIL_RETRY, 2278 RESULT_RIL_NETWORK_REJECT, 2279 RESULT_RIL_INVALID_STATE, 2280 RESULT_RIL_INVALID_ARGUMENTS, 2281 RESULT_RIL_NO_MEMORY, 2282 RESULT_RIL_REQUEST_RATE_LIMITED, 2283 RESULT_RIL_INVALID_SMS_FORMAT, 2284 RESULT_RIL_SYSTEM_ERR, 2285 RESULT_RIL_ENCODING_ERR, 2286 RESULT_RIL_INVALID_SMSC_ADDRESS, 2287 RESULT_RIL_MODEM_ERR, 2288 RESULT_RIL_NETWORK_ERR, 2289 RESULT_RIL_INTERNAL_ERR, 2290 RESULT_RIL_REQUEST_NOT_SUPPORTED, 2291 RESULT_RIL_INVALID_MODEM_STATE, 2292 RESULT_RIL_NETWORK_NOT_READY, 2293 RESULT_RIL_OPERATION_NOT_ALLOWED, 2294 RESULT_RIL_NO_RESOURCES, 2295 RESULT_RIL_CANCELLED, 2296 RESULT_RIL_SIM_ABSENT, 2297 RESULT_RIL_SIMULTANEOUS_SMS_AND_CALL_NOT_ALLOWED, 2298 RESULT_RIL_ACCESS_BARRED, 2299 RESULT_RIL_BLOCKED_DUE_TO_CALL 2300 }) 2301 @Retention(RetentionPolicy.SOURCE) 2302 public @interface Result {} 2303 2304 /** 2305 * No error. 2306 */ 2307 public static final int RESULT_ERROR_NONE = 0; 2308 2309 /** Generic failure cause */ 2310 public static final int RESULT_ERROR_GENERIC_FAILURE = 1; 2311 2312 /** Failed because radio was explicitly turned off */ 2313 public static final int RESULT_ERROR_RADIO_OFF = 2; 2314 2315 /** Failed because no pdu provided */ 2316 public static final int RESULT_ERROR_NULL_PDU = 3; 2317 2318 /** Failed because service is currently unavailable */ 2319 public static final int RESULT_ERROR_NO_SERVICE = 4; 2320 2321 /** Failed because we reached the sending queue limit. */ 2322 public static final int RESULT_ERROR_LIMIT_EXCEEDED = 5; 2323 2324 /** 2325 * Failed because FDN is enabled. 2326 */ 2327 public static final int RESULT_ERROR_FDN_CHECK_FAILURE = 6; 2328 2329 /** Failed because user denied the sending of this short code. */ 2330 public static final int RESULT_ERROR_SHORT_CODE_NOT_ALLOWED = 7; 2331 2332 /** Failed because the user has denied this app ever send premium short codes. */ 2333 public static final int RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED = 8; 2334 2335 /** 2336 * Failed because the radio was not available 2337 */ 2338 public static final int RESULT_RADIO_NOT_AVAILABLE = 9; 2339 2340 /** 2341 * Failed because of network rejection 2342 */ 2343 public static final int RESULT_NETWORK_REJECT = 10; 2344 2345 /** 2346 * Failed because of invalid arguments 2347 */ 2348 public static final int RESULT_INVALID_ARGUMENTS = 11; 2349 2350 /** 2351 * Failed because of an invalid state 2352 */ 2353 public static final int RESULT_INVALID_STATE = 12; 2354 2355 /** 2356 * Failed because there is no memory 2357 */ 2358 public static final int RESULT_NO_MEMORY = 13; 2359 2360 /** 2361 * Failed because the sms format is not valid 2362 */ 2363 public static final int RESULT_INVALID_SMS_FORMAT = 14; 2364 2365 /** 2366 * Failed because of a system error 2367 */ 2368 public static final int RESULT_SYSTEM_ERROR = 15; 2369 2370 /** 2371 * Failed because of a modem error 2372 */ 2373 public static final int RESULT_MODEM_ERROR = 16; 2374 2375 /** 2376 * Failed because of a network error 2377 */ 2378 public static final int RESULT_NETWORK_ERROR = 17; 2379 2380 /** 2381 * Failed because of an encoding error 2382 */ 2383 public static final int RESULT_ENCODING_ERROR = 18; 2384 2385 /** 2386 * Failed because of an invalid smsc address 2387 */ 2388 public static final int RESULT_INVALID_SMSC_ADDRESS = 19; 2389 2390 /** 2391 * Failed because the operation is not allowed 2392 */ 2393 public static final int RESULT_OPERATION_NOT_ALLOWED = 20; 2394 2395 /** 2396 * Failed because of an internal error 2397 */ 2398 public static final int RESULT_INTERNAL_ERROR = 21; 2399 2400 /** 2401 * Failed because there are no resources 2402 */ 2403 public static final int RESULT_NO_RESOURCES = 22; 2404 2405 /** 2406 * Failed because the operation was cancelled 2407 */ 2408 public static final int RESULT_CANCELLED = 23; 2409 2410 /** 2411 * Failed because the request is not supported 2412 */ 2413 public static final int RESULT_REQUEST_NOT_SUPPORTED = 24; 2414 2415 /** 2416 * Failed sending via bluetooth because the bluetooth service is not available 2417 */ 2418 public static final int RESULT_NO_BLUETOOTH_SERVICE = 25; 2419 2420 /** 2421 * Failed sending via bluetooth because the bluetooth device address is invalid 2422 */ 2423 public static final int RESULT_INVALID_BLUETOOTH_ADDRESS = 26; 2424 2425 /** 2426 * Failed sending via bluetooth because bluetooth disconnected 2427 */ 2428 public static final int RESULT_BLUETOOTH_DISCONNECTED = 27; 2429 2430 /** 2431 * Failed sending because the user denied or canceled the dialog displayed for a premium 2432 * shortcode sms or rate-limited sms. 2433 */ 2434 public static final int RESULT_UNEXPECTED_EVENT_STOP_SENDING = 28; 2435 2436 /** 2437 * Failed sending during an emergency call 2438 */ 2439 public static final int RESULT_SMS_BLOCKED_DURING_EMERGENCY = 29; 2440 2441 /** 2442 * Failed to send an sms retry 2443 */ 2444 public static final int RESULT_SMS_SEND_RETRY_FAILED = 30; 2445 2446 /** 2447 * Set by BroadcastReceiver to indicate a remote exception while handling a message. 2448 */ 2449 public static final int RESULT_REMOTE_EXCEPTION = 31; 2450 2451 /** 2452 * Set by BroadcastReceiver to indicate there's no default sms app. 2453 */ 2454 public static final int RESULT_NO_DEFAULT_SMS_APP = 32; 2455 2456 // Radio Error results 2457 2458 /** 2459 * The radio did not start or is resetting. 2460 */ 2461 public static final int RESULT_RIL_RADIO_NOT_AVAILABLE = 100; 2462 2463 /** 2464 * The radio failed to send the sms and needs to retry. 2465 */ 2466 public static final int RESULT_RIL_SMS_SEND_FAIL_RETRY = 101; 2467 2468 /** 2469 * The sms request was rejected by the network. 2470 */ 2471 public static final int RESULT_RIL_NETWORK_REJECT = 102; 2472 2473 /** 2474 * The radio returned an unexpected request for the current state. 2475 */ 2476 public static final int RESULT_RIL_INVALID_STATE = 103; 2477 2478 /** 2479 * The radio received invalid arguments in the request. 2480 */ 2481 public static final int RESULT_RIL_INVALID_ARGUMENTS = 104; 2482 2483 /** 2484 * The radio didn't have sufficient memory to process the request. 2485 */ 2486 public static final int RESULT_RIL_NO_MEMORY = 105; 2487 2488 /** 2489 * The radio denied the operation due to overly-frequent requests. 2490 */ 2491 public static final int RESULT_RIL_REQUEST_RATE_LIMITED = 106; 2492 2493 /** 2494 * The radio returned an error indicating invalid sms format. 2495 */ 2496 public static final int RESULT_RIL_INVALID_SMS_FORMAT = 107; 2497 2498 /** 2499 * The radio encountered a platform or system error. 2500 */ 2501 public static final int RESULT_RIL_SYSTEM_ERR = 108; 2502 2503 /** 2504 * The SMS message was not encoded properly. 2505 */ 2506 public static final int RESULT_RIL_ENCODING_ERR = 109; 2507 2508 /** 2509 * The specified SMSC address was invalid. 2510 */ 2511 public static final int RESULT_RIL_INVALID_SMSC_ADDRESS = 110; 2512 2513 /** 2514 * The vendor RIL received an unexpected or incorrect response. 2515 */ 2516 public static final int RESULT_RIL_MODEM_ERR = 111; 2517 2518 /** 2519 * The radio received an error from the network. 2520 */ 2521 public static final int RESULT_RIL_NETWORK_ERR = 112; 2522 2523 /** 2524 * The modem encountered an unexpected error scenario while handling the request. 2525 */ 2526 public static final int RESULT_RIL_INTERNAL_ERR = 113; 2527 2528 /** 2529 * The request was not supported by the radio. 2530 */ 2531 public static final int RESULT_RIL_REQUEST_NOT_SUPPORTED = 114; 2532 2533 /** 2534 * The radio cannot process the request in the current modem state. 2535 */ 2536 public static final int RESULT_RIL_INVALID_MODEM_STATE = 115; 2537 2538 /** 2539 * The network is not ready to perform the request. 2540 */ 2541 public static final int RESULT_RIL_NETWORK_NOT_READY = 116; 2542 2543 /** 2544 * The radio reports the request is not allowed. 2545 */ 2546 public static final int RESULT_RIL_OPERATION_NOT_ALLOWED = 117; 2547 2548 /** 2549 * There are insufficient resources to process the request. 2550 */ 2551 public static final int RESULT_RIL_NO_RESOURCES = 118; 2552 2553 /** 2554 * The request has been cancelled. 2555 */ 2556 public static final int RESULT_RIL_CANCELLED = 119; 2557 2558 /** 2559 * The radio failed to set the location where the CDMA subscription 2560 * can be retrieved because the SIM or RUIM is absent. 2561 */ 2562 public static final int RESULT_RIL_SIM_ABSENT = 120; 2563 2564 /** 2565 * 1X voice and SMS are not allowed simulteneously. 2566 */ 2567 public static final int RESULT_RIL_SIMULTANEOUS_SMS_AND_CALL_NOT_ALLOWED = 121; 2568 2569 /** 2570 * Access is barred. 2571 */ 2572 public static final int RESULT_RIL_ACCESS_BARRED = 122; 2573 2574 /** 2575 * SMS is blocked due to call control, e.g., resource unavailable in the SMR entity. 2576 */ 2577 public static final int RESULT_RIL_BLOCKED_DUE_TO_CALL = 123; 2578 2579 // SMS receiving results sent as a "result" extra in {@link Intents.SMS_REJECTED_ACTION} 2580 2581 /** 2582 * SMS receive dispatch failure. 2583 */ 2584 public static final int RESULT_RECEIVE_DISPATCH_FAILURE = 500; 2585 2586 /** 2587 * SMS receive injected null PDU. 2588 */ 2589 public static final int RESULT_RECEIVE_INJECTED_NULL_PDU = 501; 2590 2591 /** 2592 * SMS receive encountered runtime exception. 2593 */ 2594 public static final int RESULT_RECEIVE_RUNTIME_EXCEPTION = 502; 2595 2596 /** 2597 * SMS received null message from the radio interface layer. 2598 */ 2599 public static final int RESULT_RECEIVE_NULL_MESSAGE_FROM_RIL = 503; 2600 2601 /** 2602 * SMS short code received while the phone is in encrypted state. 2603 */ 2604 public static final int RESULT_RECEIVE_WHILE_ENCRYPTED = 504; 2605 2606 /** 2607 * SMS receive encountered an SQL exception. 2608 */ 2609 public static final int RESULT_RECEIVE_SQL_EXCEPTION = 505; 2610 2611 /** 2612 * SMS receive an exception parsing a uri. 2613 */ 2614 public static final int RESULT_RECEIVE_URI_EXCEPTION = 506; 2615 2616 2617 2618 /** 2619 * Send an MMS message 2620 * 2621 * <p class="note"><strong>Note:</strong> If {@link #getDefault()} is used to instantiate this 2622 * manager on a multi-SIM device, this operation may fail sending the MMS message because no 2623 * suitable default subscription could be found. In this case, if {@code sentIntent} is 2624 * non-null, then the {@link PendingIntent} will be sent with an error code 2625 * {@code RESULT_NO_DEFAULT_SMS_APP}. See {@link #getDefault()} for more information on the 2626 * conditions where this operation may fail. 2627 * </p> 2628 * 2629 * @param context application context 2630 * @param contentUri the content Uri from which the message pdu will be read 2631 * @param locationUrl the optional location url where message should be sent to 2632 * @param configOverrides the carrier-specific messaging configuration values to override for 2633 * sending the message. 2634 * @param sentIntent if not NULL this <code>PendingIntent</code> is 2635 * broadcast when the message is successfully sent, or failed 2636 * @throws IllegalArgumentException if contentUri is empty 2637 */ sendMultimediaMessage(Context context, Uri contentUri, String locationUrl, Bundle configOverrides, PendingIntent sentIntent)2638 public void sendMultimediaMessage(Context context, Uri contentUri, String locationUrl, 2639 Bundle configOverrides, PendingIntent sentIntent) { 2640 sendMultimediaMessage(context, contentUri, locationUrl, configOverrides, sentIntent, 2641 0L /* messageId */); 2642 } 2643 2644 /** 2645 * Send an MMS message 2646 * 2647 * Same as {@link #sendMultimediaMessage(Context context, Uri contentUri, String locationUrl, 2648 * Bundle configOverrides, PendingIntent sentIntent)}, but adds an optional messageId. 2649 * <p class="note"><strong>Note:</strong> If {@link #getDefault()} is used to instantiate this 2650 * manager on a multi-SIM device, this operation may fail sending the MMS message because no 2651 * suitable default subscription could be found. In this case, if {@code sentIntent} is 2652 * non-null, then the {@link PendingIntent} will be sent with an error code 2653 * {@code RESULT_NO_DEFAULT_SMS_APP}. See {@link #getDefault()} for more information on the 2654 * conditions where this operation may fail. 2655 * </p> 2656 * 2657 * @param context application context 2658 * @param contentUri the content Uri from which the message pdu will be read 2659 * @param locationUrl the optional location url where message should be sent to 2660 * @param configOverrides the carrier-specific messaging configuration values to override for 2661 * sending the message. 2662 * @param sentIntent if not NULL this <code>PendingIntent</code> is 2663 * broadcast when the message is successfully sent, or failed 2664 * @param messageId an id that uniquely identifies the message requested to be sent. 2665 * Used for logging and diagnostics purposes. The id may be 0. 2666 * @throws IllegalArgumentException if contentUri is empty 2667 */ sendMultimediaMessage(@onNull Context context, @NonNull Uri contentUri, @Nullable String locationUrl, @Nullable Bundle configOverrides, @Nullable PendingIntent sentIntent, long messageId)2668 public void sendMultimediaMessage(@NonNull Context context, @NonNull Uri contentUri, 2669 @Nullable String locationUrl, @Nullable Bundle configOverrides, 2670 @Nullable PendingIntent sentIntent, long messageId) { 2671 if (contentUri == null) { 2672 throw new IllegalArgumentException("Uri contentUri null"); 2673 } 2674 MmsManager m = (MmsManager) context.getSystemService(Context.MMS_SERVICE); 2675 if (m != null) { 2676 resolveSubscriptionForOperation(new SubscriptionResolverResult() { 2677 @Override 2678 public void onSuccess(int subId) { 2679 m.sendMultimediaMessage(subId, contentUri, locationUrl, configOverrides, 2680 sentIntent, messageId); 2681 } 2682 2683 @Override 2684 public void onFailure() { 2685 notifySmsError(sentIntent, RESULT_NO_DEFAULT_SMS_APP); 2686 } 2687 }); 2688 } 2689 } 2690 2691 /** 2692 * Download an MMS message from carrier by a given location URL 2693 * 2694 * <p class="note"><strong>Note:</strong> If {@link #getDefault()} is used to instantiate this 2695 * manager on a multi-SIM device, this operation may fail downloading the MMS message because no 2696 * suitable default subscription could be found. In this case, if {@code downloadedIntent} is 2697 * non-null, then the {@link PendingIntent} will be sent with an error code 2698 * {@code RESULT_NO_DEFAULT_SMS_APP}. See {@link #getDefault()} for more information on the 2699 * conditions where this operation may fail. 2700 * </p> 2701 * 2702 * @param context application context 2703 * @param locationUrl the location URL of the MMS message to be downloaded, usually obtained 2704 * from the MMS WAP push notification 2705 * @param contentUri the content uri to which the downloaded pdu will be written 2706 * @param configOverrides the carrier-specific messaging configuration values to override for 2707 * downloading the message. 2708 * @param downloadedIntent if not NULL this <code>PendingIntent</code> is 2709 * broadcast when the message is downloaded, or the download is failed 2710 * @throws IllegalArgumentException if locationUrl or contentUri is empty 2711 */ downloadMultimediaMessage(Context context, String locationUrl, Uri contentUri, Bundle configOverrides, PendingIntent downloadedIntent)2712 public void downloadMultimediaMessage(Context context, String locationUrl, Uri contentUri, 2713 Bundle configOverrides, PendingIntent downloadedIntent) { 2714 downloadMultimediaMessage(context, locationUrl, contentUri, configOverrides, 2715 downloadedIntent, 0L /* messageId */); 2716 } 2717 2718 /** 2719 * Download an MMS message from carrier by a given location URL 2720 * 2721 * Same as {@link #downloadMultimediaMessage(Context context, String locationUrl, 2722 * Uri contentUri, Bundle configOverrides, PendingIntent downloadedIntent)}, 2723 * but adds an optional messageId. 2724 * <p class="note"><strong>Note:</strong> If {@link #getDefault()} is used to instantiate this 2725 * manager on a multi-SIM device, this operation may fail downloading the MMS message because no 2726 * suitable default subscription could be found. In this case, if {@code downloadedIntent} is 2727 * non-null, then the {@link PendingIntent} will be sent with an error code 2728 * {@code RESULT_NO_DEFAULT_SMS_APP}. See {@link #getDefault()} for more information on the 2729 * conditions where this operation may fail. 2730 * </p> 2731 * 2732 * @param context application context 2733 * @param locationUrl the location URL of the MMS message to be downloaded, usually obtained 2734 * from the MMS WAP push notification 2735 * @param contentUri the content uri to which the downloaded pdu will be written 2736 * @param configOverrides the carrier-specific messaging configuration values to override for 2737 * downloading the message. 2738 * @param downloadedIntent if not NULL this <code>PendingIntent</code> is 2739 * broadcast when the message is downloaded, or the download is failed 2740 * @param messageId an id that uniquely identifies the message requested to be downloaded. 2741 * Used for logging and diagnostics purposes. The id may be 0. 2742 * @throws IllegalArgumentException if locationUrl or contentUri is empty 2743 */ downloadMultimediaMessage(@onNull Context context, @NonNull String locationUrl, @NonNull Uri contentUri, @Nullable Bundle configOverrides, @Nullable PendingIntent downloadedIntent, long messageId)2744 public void downloadMultimediaMessage(@NonNull Context context, @NonNull String locationUrl, 2745 @NonNull Uri contentUri, @Nullable Bundle configOverrides, 2746 @Nullable PendingIntent downloadedIntent, long messageId) { 2747 if (TextUtils.isEmpty(locationUrl)) { 2748 throw new IllegalArgumentException("Empty MMS location URL"); 2749 } 2750 if (contentUri == null) { 2751 throw new IllegalArgumentException("Uri contentUri null"); 2752 } 2753 MmsManager m = (MmsManager) context.getSystemService(Context.MMS_SERVICE); 2754 if (m != null) { 2755 resolveSubscriptionForOperation(new SubscriptionResolverResult() { 2756 @Override 2757 public void onSuccess(int subId) { 2758 m.downloadMultimediaMessage(subId, locationUrl, contentUri, configOverrides, 2759 downloadedIntent, messageId); 2760 } 2761 2762 @Override 2763 public void onFailure() { 2764 notifySmsError(downloadedIntent, RESULT_NO_DEFAULT_SMS_APP); 2765 } 2766 }); 2767 } 2768 } 2769 2770 // MMS send/download failure result codes 2771 public static final int MMS_ERROR_UNSPECIFIED = 1; 2772 public static final int MMS_ERROR_INVALID_APN = 2; 2773 public static final int MMS_ERROR_UNABLE_CONNECT_MMS = 3; 2774 public static final int MMS_ERROR_HTTP_FAILURE = 4; 2775 public static final int MMS_ERROR_IO_ERROR = 5; 2776 public static final int MMS_ERROR_RETRY = 6; 2777 public static final int MMS_ERROR_CONFIGURATION_ERROR = 7; 2778 public static final int MMS_ERROR_NO_DATA_NETWORK = 8; 2779 2780 /** Intent extra name for MMS sending result data in byte array type */ 2781 public static final String EXTRA_MMS_DATA = "android.telephony.extra.MMS_DATA"; 2782 /** Intent extra name for HTTP status code for MMS HTTP failure in integer type */ 2783 public static final String EXTRA_MMS_HTTP_STATUS = "android.telephony.extra.MMS_HTTP_STATUS"; 2784 2785 /** 2786 * Get carrier-dependent MMS configuration values. 2787 * 2788 * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier 2789 * applications or the Telephony framework and will never trigger an SMS disambiguation dialog. 2790 * If this method is called on a device that has multiple active subscriptions, this {@link 2791 * SmsManager} instance has been created with {@link #getDefault()}, and no user-defined default 2792 * subscription is defined, the subscription ID associated with this message will be INVALID, 2793 * which will result in the operation being completed on the subscription associated with 2794 * logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the operation is 2795 * performed on the correct subscription. 2796 * </p> 2797 * 2798 * @return the bundle key/values pairs that contains MMS configuration values 2799 * or an empty Bundle if they cannot be found. 2800 */ getCarrierConfigValues()2801 @NonNull public Bundle getCarrierConfigValues() { 2802 try { 2803 ISms iSms = getISmsService(); 2804 if (iSms != null) { 2805 return iSms.getCarrierConfigValuesForSubscriber(getSubscriptionId()); 2806 } 2807 } catch (RemoteException ex) { 2808 // ignore it 2809 } 2810 return new Bundle(); 2811 } 2812 2813 /** 2814 * Create a single use app specific incoming SMS request for the calling package. 2815 * 2816 * This method returns a token that if included in a subsequent incoming SMS message will cause 2817 * {@code intent} to be sent with the SMS data. 2818 * 2819 * The token is only good for one use, after an SMS has been received containing the token all 2820 * subsequent SMS messages with the token will be routed as normal. 2821 * 2822 * An app can only have one request at a time, if the app already has a request pending it will 2823 * be replaced with a new request. 2824 * 2825 * <p class="note"><strong>Note:</strong> This method will never trigger an SMS disambiguation 2826 * dialog. If this method is called on a device that has multiple active subscriptions, this 2827 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined 2828 * default subscription is defined, the subscription ID associated with this message will be 2829 * INVALID, which will result in the operation being completed on the subscription associated 2830 * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the 2831 * operation is performed on the correct subscription. 2832 * </p> 2833 * 2834 * @return Token to include in an SMS message. The token will be 11 characters long. 2835 * @see android.provider.Telephony.Sms.Intents#getMessagesFromIntent 2836 */ createAppSpecificSmsToken(PendingIntent intent)2837 public String createAppSpecificSmsToken(PendingIntent intent) { 2838 try { 2839 ISms iccSms = getISmsServiceOrThrow(); 2840 return iccSms.createAppSpecificSmsToken(getSubscriptionId(), 2841 null, intent); 2842 2843 } catch (RemoteException ex) { 2844 ex.rethrowFromSystemServer(); 2845 return null; 2846 } 2847 } 2848 2849 /** 2850 * callback for providing asynchronous sms messages for financial app. 2851 */ 2852 public abstract static class FinancialSmsCallback { 2853 /** 2854 * Callback to send sms messages back to financial app asynchronously. 2855 * 2856 * @param msgs SMS messages. 2857 */ onFinancialSmsMessages(CursorWindow msgs)2858 public abstract void onFinancialSmsMessages(CursorWindow msgs); 2859 }; 2860 2861 /** 2862 * Get SMS messages for the calling financial app. 2863 * The result will be delivered asynchronously in the passing in callback interface. 2864 * 2865 * <p class="note"><strong>Note:</strong> This method will never trigger an SMS disambiguation 2866 * dialog. If this method is called on a device that has multiple active subscriptions, this 2867 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined 2868 * default subscription is defined, the subscription ID associated with this message will be 2869 * INVALID, which will result in the operation being completed on the subscription associated 2870 * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the 2871 * operation is performed on the correct subscription. 2872 * </p> 2873 * 2874 * @param params the parameters to filter SMS messages returned. 2875 * @param executor the executor on which callback will be invoked. 2876 * @param callback a callback to receive CursorWindow with SMS messages. 2877 * 2878 */ 2879 @RequiresPermission(android.Manifest.permission.SMS_FINANCIAL_TRANSACTIONS) getSmsMessagesForFinancialApp( Bundle params, @NonNull @CallbackExecutor Executor executor, @NonNull FinancialSmsCallback callback)2880 public void getSmsMessagesForFinancialApp( 2881 Bundle params, 2882 @NonNull @CallbackExecutor Executor executor, 2883 @NonNull FinancialSmsCallback callback) { 2884 // This API is not functional and thus removed to avoid future confusion. 2885 } 2886 2887 /** 2888 * @see #createAppSpecificSmsTokenWithPackageInfo(String, PendingIntent). 2889 * The prefixes is a list of prefix {@code String} separated by this delimiter. 2890 * @hide 2891 */ 2892 public static final String REGEX_PREFIX_DELIMITER = ","; 2893 /** 2894 * @see #createAppSpecificSmsTokenWithPackageInfo(String, PendingIntent). 2895 * The success status to be added into the intent to be sent to the calling package. 2896 * @hide 2897 */ 2898 public static final int RESULT_STATUS_SUCCESS = 0; 2899 /** 2900 * @see #createAppSpecificSmsTokenWithPackageInfo(String, PendingIntent). 2901 * The timeout status to be added into the intent to be sent to the calling package. 2902 * @hide 2903 */ 2904 public static final int RESULT_STATUS_TIMEOUT = 1; 2905 /** 2906 * @see #createAppSpecificSmsTokenWithPackageInfo(String, PendingIntent). 2907 * Intent extra key of the retrieved SMS message as a {@code String}. 2908 * @hide 2909 */ 2910 public static final String EXTRA_SMS_MESSAGE = "android.telephony.extra.SMS_MESSAGE"; 2911 /** 2912 * @see #createAppSpecificSmsTokenWithPackageInfo(String, PendingIntent). 2913 * Intent extra key of SMS retriever status, which indicates whether the request for the 2914 * coming SMS message is SUCCESS or TIMEOUT 2915 * @hide 2916 */ 2917 public static final String EXTRA_STATUS = "android.telephony.extra.STATUS"; 2918 /** 2919 * @see #createAppSpecificSmsTokenWithPackageInfo(String, PendingIntent). 2920 * [Optional] Intent extra key of the retrieved Sim card subscription Id if any. {@code int} 2921 * @hide 2922 */ 2923 public static final String EXTRA_SIM_SUBSCRIPTION_ID = 2924 "android.telephony.extra.SIM_SUBSCRIPTION_ID"; 2925 2926 /** 2927 * Create a single use app specific incoming SMS request for the calling package. 2928 * 2929 * This method returns a token that if included in a subsequent incoming SMS message, and the 2930 * SMS message has a prefix from the given prefixes list, the provided {@code intent} will be 2931 * sent with the SMS data to the calling package. 2932 * 2933 * The token is only good for one use within a reasonable amount of time. After an SMS has been 2934 * received containing the token all subsequent SMS messages with the token will be routed as 2935 * normal. 2936 * 2937 * An app can only have one request at a time, if the app already has a request pending it will 2938 * be replaced with a new request. 2939 * 2940 * <p class="note"><strong>Note:</strong> This method will never trigger an SMS disambiguation 2941 * dialog. If this method is called on a device that has multiple active subscriptions, this 2942 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined 2943 * default subscription is defined, the subscription ID associated with this message will be 2944 * INVALID, which will result in the operation being completed on the subscription associated 2945 * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the 2946 * operation is performed on the correct subscription. 2947 * </p> 2948 * 2949 * @param prefixes this is a list of prefixes string separated by REGEX_PREFIX_DELIMITER. The 2950 * matching SMS message should have at least one of the prefixes in the beginning of the 2951 * message. 2952 * @param intent this intent is sent when the matching SMS message is received. 2953 * @return Token to include in an SMS message. 2954 */ 2955 @Nullable createAppSpecificSmsTokenWithPackageInfo( @ullable String prefixes, @NonNull PendingIntent intent)2956 public String createAppSpecificSmsTokenWithPackageInfo( 2957 @Nullable String prefixes, @NonNull PendingIntent intent) { 2958 try { 2959 ISms iccSms = getISmsServiceOrThrow(); 2960 return iccSms.createAppSpecificSmsTokenWithPackageInfo(getSubscriptionId(), 2961 null, prefixes, intent); 2962 2963 } catch (RemoteException ex) { 2964 ex.rethrowFromSystemServer(); 2965 return null; 2966 } 2967 } 2968 2969 /** @hide */ 2970 @Retention(RetentionPolicy.SOURCE) 2971 @IntDef(prefix = {"SMS_CATEGORY_"}, 2972 value = { 2973 SmsManager.SMS_CATEGORY_NOT_SHORT_CODE, 2974 SmsManager.SMS_CATEGORY_FREE_SHORT_CODE, 2975 SmsManager.SMS_CATEGORY_STANDARD_SHORT_CODE, 2976 SmsManager.SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE, 2977 SmsManager.SMS_CATEGORY_PREMIUM_SHORT_CODE}) 2978 public @interface SmsShortCodeCategory {} 2979 2980 /** 2981 * Return value from {@link #checkSmsShortCodeDestination(String, String)} ()} for regular 2982 * phone numbers. 2983 * @hide 2984 */ 2985 @TestApi 2986 public static final int SMS_CATEGORY_NOT_SHORT_CODE = 0; 2987 /** 2988 * Return value from {@link #checkSmsShortCodeDestination(String, String)} ()} for free 2989 * (no cost) short codes. 2990 * @hide 2991 */ 2992 @TestApi 2993 public static final int SMS_CATEGORY_FREE_SHORT_CODE = 1; 2994 /** 2995 * Return value from {@link #checkSmsShortCodeDestination(String, String)} ()} for 2996 * standard rate (non-premium) 2997 * short codes. 2998 * @hide 2999 */ 3000 @TestApi 3001 public static final int SMS_CATEGORY_STANDARD_SHORT_CODE = 2; 3002 /** 3003 * Return value from {@link #checkSmsShortCodeDestination(String, String)} ()} for possible 3004 * premium short codes. 3005 * @hide 3006 */ 3007 @TestApi 3008 public static final int SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE = 3; 3009 /** 3010 * Return value from {@link #checkSmsShortCodeDestination(String, String)} ()} for 3011 * premium short codes. 3012 * @hide 3013 */ 3014 @TestApi 3015 public static final int SMS_CATEGORY_PREMIUM_SHORT_CODE = 4; 3016 3017 /** 3018 * Check if the destination address is a possible premium short code. 3019 * NOTE: the caller is expected to strip non-digits from the destination number with 3020 * {@link PhoneNumberUtils#extractNetworkPortion} before calling this method. 3021 * 3022 * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier 3023 * applications or the Telephony framework and will never trigger an SMS disambiguation 3024 * dialog. If this method is called on a device that has multiple active subscriptions, this 3025 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined 3026 * default subscription is defined, the subscription ID associated with this message will be 3027 * INVALID, which will result in the operation being completed on the subscription associated 3028 * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the 3029 * operation is performed on the correct subscription. 3030 * </p> 3031 * 3032 * @param destAddress the destination address to test for possible short code 3033 * @param countryIso the ISO country code 3034 * 3035 * @return 3036 * {@link SmsManager#SMS_CATEGORY_NOT_SHORT_CODE}, 3037 * {@link SmsManager#SMS_CATEGORY_FREE_SHORT_CODE}, 3038 * {@link SmsManager#SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE}, 3039 * {@link SmsManager#SMS_CATEGORY_PREMIUM_SHORT_CODE}, or 3040 * {@link SmsManager#SMS_CATEGORY_STANDARD_SHORT_CODE} 3041 * 3042 * @hide 3043 */ 3044 @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) 3045 @TestApi checkSmsShortCodeDestination( String destAddress, String countryIso)3046 public @SmsShortCodeCategory int checkSmsShortCodeDestination( 3047 String destAddress, String countryIso) { 3048 try { 3049 ISms iccISms = getISmsServiceOrThrow(); 3050 if (iccISms != null) { 3051 return iccISms.checkSmsShortCodeDestination(getSubscriptionId(), 3052 null, null, destAddress, countryIso); 3053 } 3054 } catch (RemoteException e) { 3055 Log.e(TAG, "checkSmsShortCodeDestination() RemoteException", e); 3056 } 3057 return SmsManager.SMS_CATEGORY_NOT_SHORT_CODE; 3058 } 3059 3060 /** 3061 * Gets the SMSC address from (U)SIM. 3062 * 3063 * <p class="note"><strong>Note:</strong> Using this method requires that your app is the 3064 * default SMS application, or READ_PRIVILEGED_PHONE_STATE permission, or has the carrier 3065 * privileges.</p> 3066 * 3067 * <p class="note"><strong>Note:</strong> This method will never trigger an SMS disambiguation 3068 * dialog. If this method is called on a device that has multiple active subscriptions, this 3069 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined 3070 * default subscription is defined, the subscription ID associated with this method will be 3071 * INVALID, which will result in the operation being completed on the subscription associated 3072 * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the operation 3073 * is performed on the correct subscription. 3074 * </p> 3075 * 3076 * @return the SMSC address string, null if failed. 3077 */ 3078 @SuppressAutoDoc // for carrier privileges and default SMS application. 3079 @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) 3080 @Nullable getSmscAddress()3081 public String getSmscAddress() { 3082 String smsc = null; 3083 3084 try { 3085 ISms iSms = getISmsService(); 3086 if (iSms != null) { 3087 smsc = iSms.getSmscAddressFromIccEfForSubscriber( 3088 getSubscriptionId(), null); 3089 } 3090 } catch (RemoteException ex) { 3091 throw new RuntimeException(ex); 3092 } 3093 return smsc; 3094 } 3095 3096 /** 3097 * Sets the SMSC address on (U)SIM. 3098 * 3099 * <p class="note"><strong>Note:</strong> Using this method requires that your app is the 3100 * default SMS application, or has {@link android.Manifest.permission#MODIFY_PHONE_STATE} 3101 * permission, or has the carrier privileges.</p> 3102 * 3103 * <p class="note"><strong>Note:</strong> This method will never trigger an SMS disambiguation 3104 * dialog. If this method is called on a device that has multiple active subscriptions, this 3105 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined 3106 * default subscription is defined, the subscription ID associated with this method will be 3107 * INVALID, which will result in the operation being completed on the subscription associated 3108 * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the operation 3109 * is performed on the correct subscription. 3110 * </p> 3111 * 3112 * @param smsc the SMSC address string. 3113 * @return true for success, false otherwise. Failure can be due modem returning an error. 3114 */ 3115 @SuppressAutoDoc // for carrier privileges and default SMS application. 3116 @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) setSmscAddress(@onNull String smsc)3117 public boolean setSmscAddress(@NonNull String smsc) { 3118 try { 3119 ISms iSms = getISmsService(); 3120 if (iSms != null) { 3121 return iSms.setSmscAddressOnIccEfForSubscriber( 3122 smsc, getSubscriptionId(), null); 3123 } 3124 } catch (RemoteException ex) { 3125 throw new RuntimeException(ex); 3126 } 3127 return false; 3128 } 3129 3130 /** 3131 * Gets the premium SMS permission for the specified package. If the package has never 3132 * been seen before, the default {@link SmsManager#PREMIUM_SMS_CONSENT_UNKNOWN} 3133 * will be returned. 3134 * @param packageName the name of the package to query permission 3135 * @return one of {@link SmsManager#PREMIUM_SMS_CONSENT_UNKNOWN}, 3136 * {@link SmsManager#PREMIUM_SMS_CONSENT_ASK_USER}, 3137 * {@link SmsManager#PREMIUM_SMS_CONSENT_NEVER_ALLOW}, or 3138 * {@link SmsManager#PREMIUM_SMS_CONSENT_ALWAYS_ALLOW} 3139 * @hide 3140 */ 3141 @SystemApi 3142 @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) getPremiumSmsConsent(@onNull String packageName)3143 public @PremiumSmsConsent int getPremiumSmsConsent(@NonNull String packageName) { 3144 int permission = 0; 3145 try { 3146 ISms iSms = getISmsService(); 3147 if (iSms != null) { 3148 permission = iSms.getPremiumSmsPermission(packageName); 3149 } 3150 } catch (RemoteException e) { 3151 Log.e(TAG, "getPremiumSmsPermission() RemoteException", e); 3152 } 3153 return permission; 3154 } 3155 3156 /** 3157 * Sets the premium SMS permission for the specified package and save the value asynchronously 3158 * to persistent storage. 3159 * @param packageName the name of the package to set permission 3160 * @param permission one of {@link SmsManager#PREMIUM_SMS_CONSENT_ASK_USER}, 3161 * {@link SmsManager#PREMIUM_SMS_CONSENT_NEVER_ALLOW}, or 3162 * {@link SmsManager#PREMIUM_SMS_CONSENT_ALWAYS_ALLOW} 3163 * @hide 3164 */ 3165 @SystemApi 3166 @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) setPremiumSmsConsent( @onNull String packageName, @PremiumSmsConsent int permission)3167 public void setPremiumSmsConsent( 3168 @NonNull String packageName, @PremiumSmsConsent int permission) { 3169 try { 3170 ISms iSms = getISmsService(); 3171 if (iSms != null) { 3172 iSms.setPremiumSmsPermission(packageName, permission); 3173 } 3174 } catch (RemoteException e) { 3175 Log.e(TAG, "setPremiumSmsPermission() RemoteException", e); 3176 } 3177 } 3178 3179 /** 3180 * Reset all cell broadcast ranges. Previously enabled ranges will become invalid after this. 3181 * @hide 3182 */ 3183 @SystemApi 3184 @RequiresPermission(android.Manifest.permission.MODIFY_CELL_BROADCASTS) resetAllCellBroadcastRanges()3185 public void resetAllCellBroadcastRanges() { 3186 try { 3187 ISms iSms = getISmsService(); 3188 if (iSms != null) { 3189 // If getSubscriptionId() returns INVALID or an inactive subscription, we will use 3190 // the default phone internally. 3191 iSms.resetAllCellBroadcastRanges(getSubscriptionId()); 3192 } 3193 } catch (RemoteException ex) { 3194 ex.rethrowFromSystemServer(); 3195 } 3196 } 3197 formatCrossStackMessageId(long id)3198 private static String formatCrossStackMessageId(long id) { 3199 return "{x-message-id:" + id + "}"; 3200 } 3201 } 3202