blob: 5171cf9dcea76a1a6fd83915a41ff6f7913631b5 [file] [log] [blame]
Aurimas Liutikas93554f22022-04-19 16:51:35 -07001/*
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
17package android.telephony;
18
19import android.Manifest;
20import android.annotation.CallbackExecutor;
21import android.annotation.IntDef;
22import android.annotation.IntRange;
23import android.annotation.NonNull;
24import android.annotation.Nullable;
25import android.annotation.RequiresPermission;
26import android.annotation.SuppressAutoDoc;
27import android.annotation.SystemApi;
28import android.annotation.TestApi;
29import android.app.PendingIntent;
30import android.compat.Compatibility;
31import android.compat.annotation.ChangeId;
32import android.compat.annotation.EnabledAfter;
33import android.compat.annotation.UnsupportedAppUsage;
34import android.content.Context;
35import android.database.CursorWindow;
36import android.net.Uri;
37import android.os.Build;
38import android.os.Bundle;
39import android.os.RemoteException;
40import android.text.TextUtils;
41import android.util.ArrayMap;
42import android.util.Log;
43import android.util.Pair;
44
45import com.android.internal.annotations.GuardedBy;
46import com.android.internal.telephony.IIntegerConsumer;
47import com.android.internal.telephony.ISms;
48import com.android.internal.telephony.ITelephony;
49import com.android.internal.telephony.SmsRawData;
50import com.android.telephony.Rlog;
51
52import java.lang.annotation.Retention;
53import java.lang.annotation.RetentionPolicy;
54import java.util.ArrayList;
55import java.util.List;
56import java.util.Map;
57import 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 */
78public 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 {
335 void onSuccess(int subId);
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 */
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 */
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 */
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 */
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)
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
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 })
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
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
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 */
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 */
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 */
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 */
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 */
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
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)
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
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
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 */
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
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 */
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
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 */
1554 public @NonNull SmsManager createForSubscriptionId(int subId) {
1555 return getSmsManagerForContextAndSubscriptionId(mContext, subId);
1556 }
1557
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 */
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 */
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
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
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
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
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 */
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
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)
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)
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)
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)
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
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
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
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 */
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 */
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 */
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 */
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
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)
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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)
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
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
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
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)
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)
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)
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)
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
3198 private static String formatCrossStackMessageId(long id) {
3199 return "{x-message-id:" + id + "}";
3200 }
3201}