blob: 964cf76d17f6e38da04ed663f18b1cb167cee0f6 [file] [log] [blame]
Dan Willemsen4980bf42017-02-14 14:17:12 -08001/*
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
changbettyd5093c712019-11-21 11:07:14 +080019import android.Manifest;
Hongming Jin08496b02019-01-25 13:41:52 -080020import android.annotation.CallbackExecutor;
chen xu9c7fad92019-03-25 10:43:28 -070021import android.annotation.IntDef;
Hongming Jin46edf152019-01-17 12:11:59 -080022import android.annotation.NonNull;
23import android.annotation.Nullable;
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -060024import android.annotation.RequiresPermission;
Jeff Davidsona4a4c8a2018-03-15 17:10:58 -070025import android.annotation.SuppressAutoDoc;
Abhijith Shastry448c12c2017-02-14 13:02:59 -080026import android.annotation.SystemApi;
chen xu9c7fad92019-03-25 10:43:28 -070027import android.annotation.TestApi;
Dan Willemsen4980bf42017-02-14 14:17:12 -080028import android.app.PendingIntent;
Shuo Qian24fded62020-01-14 14:48:27 -080029import android.compat.Compatibility;
30import android.compat.annotation.ChangeId;
31import android.compat.annotation.EnabledAfter;
Artur Satayev74cb7192019-12-10 17:47:56 +000032import android.compat.annotation.UnsupportedAppUsage;
Dan Willemsen4980bf42017-02-14 14:17:12 -080033import android.content.Context;
Hongming Jin08496b02019-01-25 13:41:52 -080034import android.database.CursorWindow;
Dan Willemsen4980bf42017-02-14 14:17:12 -080035import android.net.Uri;
Mathew Inwood55418ea2018-12-20 15:30:45 +000036import android.os.Build;
Dan Willemsen4980bf42017-02-14 14:17:12 -080037import android.os.Bundle;
38import android.os.RemoteException;
Dan Willemsen4980bf42017-02-14 14:17:12 -080039import android.text.TextUtils;
40import android.util.ArrayMap;
41import android.util.Log;
Philip P. Moltmann7ebd5592020-07-16 14:37:30 -070042import android.util.Pair;
Dan Willemsen4980bf42017-02-14 14:17:12 -080043
Philip P. Moltmann7ebd5592020-07-16 14:37:30 -070044import com.android.internal.annotations.GuardedBy;
Brad Ebinger360415a2019-04-30 11:37:27 -070045import com.android.internal.telephony.IIntegerConsumer;
Dan Willemsen4980bf42017-02-14 14:17:12 -080046import com.android.internal.telephony.ISms;
Brad Ebinger360415a2019-04-30 11:37:27 -070047import com.android.internal.telephony.ITelephony;
Dan Willemsen4980bf42017-02-14 14:17:12 -080048import com.android.internal.telephony.SmsRawData;
Nazanindf808782020-08-11 15:42:54 -070049import com.android.telephony.Rlog;
Dan Willemsen4980bf42017-02-14 14:17:12 -080050
chen xu9c7fad92019-03-25 10:43:28 -070051import java.lang.annotation.Retention;
52import java.lang.annotation.RetentionPolicy;
Dan Willemsen4980bf42017-02-14 14:17:12 -080053import java.util.ArrayList;
Dan Willemsen4980bf42017-02-14 14:17:12 -080054import java.util.List;
55import java.util.Map;
Hongming Jin08496b02019-01-25 13:41:52 -080056import java.util.concurrent.Executor;
Dan Willemsen4980bf42017-02-14 14:17:12 -080057
58/*
59 * TODO(code review): Curious question... Why are a lot of these
60 * methods not declared as static, since they do not seem to require
61 * any local object state? Presumably this cannot be changed without
62 * interfering with the API...
63 */
64
65/**
66 * Manages SMS operations such as sending data, text, and pdu SMS messages.
Brad Ebingerfa82ddd2019-04-30 11:34:14 -070067 * Get this object by calling the static method {@link #getDefault()}. To create an instance of
68 * {@link SmsManager} associated with a specific subscription ID, call
69 * {@link #getSmsManagerForSubscriptionId(int)}. This is typically used for devices that support
70 * multiple active subscriptions at once.
Dan Willemsen4980bf42017-02-14 14:17:12 -080071 *
72 * <p>For information about how to behave as the default SMS app on Android 4.4 (API level 19)
73 * and higher, see {@link android.provider.Telephony}.
Brad Ebingerfa82ddd2019-04-30 11:34:14 -070074 *
75 * @see SubscriptionManager#getActiveSubscriptionInfoList()
Dan Willemsen4980bf42017-02-14 14:17:12 -080076 */
77public final class SmsManager {
78 private static final String TAG = "SmsManager";
Vasu Noriaea03912018-09-04 11:19:59 -070079
Dan Willemsen4980bf42017-02-14 14:17:12 -080080 private static final Object sLockObject = new Object();
81
Philip P. Moltmann7ebd5592020-07-16 14:37:30 -070082 @GuardedBy("sLockObject")
83 private static final Map<Pair<Context, Integer>, SmsManager> sSubInstances =
84 new ArrayMap<>();
85
86 /** Singleton object constructed during class initialization. */
87 private static final SmsManager DEFAULT_INSTANCE = getSmsManagerForContextAndSubscriptionId(
88 null, SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
89
Nathan Harolde97d1c62016-12-13 19:03:09 -080090 /** SMS record length from TS 51.011 10.5.3
91 * @hide
92 */
93 public static final int SMS_RECORD_LENGTH = 176;
94
95 /** SMS record length from C.S0023 3.4.27
96 * @hide
97 */
98 public static final int CDMA_SMS_RECORD_LENGTH = 255;
99
Dan Willemsen4980bf42017-02-14 14:17:12 -0800100 /** A concrete subscription id, or the pseudo DEFAULT_SUBSCRIPTION_ID */
Mathew Inwood55418ea2018-12-20 15:30:45 +0000101 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Dan Willemsen4980bf42017-02-14 14:17:12 -0800102 private int mSubId;
103
Philip P. Moltmann7ebd5592020-07-16 14:37:30 -0700104 /**
105 * Context this SmsManager is for. Can be {@code null} in the case the manager was created via
106 * legacy APIs
107 */
108 private final @Nullable Context mContext;
109
Dan Willemsen4980bf42017-02-14 14:17:12 -0800110 /*
111 * Key for the various carrier-dependent configuration values.
112 * Some of the values are used by the system in processing SMS or MMS messages. Others
113 * are provided for the convenience of SMS applications.
114 */
115
116 /**
117 * Whether to append transaction id to MMS WAP Push M-Notification.ind's content location URI
118 * when constructing the download URL of a new MMS (boolean type)
119 */
120 public static final String MMS_CONFIG_APPEND_TRANSACTION_ID =
121 CarrierConfigManager.KEY_MMS_APPEND_TRANSACTION_ID_BOOL;
122 /**
123 * Whether MMS is enabled for the current carrier (boolean type)
124 */
125 public static final String
Brad Ebinger360415a2019-04-30 11:37:27 -0700126 MMS_CONFIG_MMS_ENABLED = CarrierConfigManager.KEY_MMS_MMS_ENABLED_BOOL;
Dan Willemsen4980bf42017-02-14 14:17:12 -0800127 /**
128 * Whether group MMS is enabled for the current carrier (boolean type)
129 */
130 public static final String
131 MMS_CONFIG_GROUP_MMS_ENABLED = CarrierConfigManager.KEY_MMS_GROUP_MMS_ENABLED_BOOL;
132 /**
133 * If this is enabled, M-NotifyResp.ind should be sent to the WAP Push content location instead
134 * of the default MMSC (boolean type)
135 */
136 public static final String MMS_CONFIG_NOTIFY_WAP_MMSC_ENABLED =
137 CarrierConfigManager.KEY_MMS_NOTIFY_WAP_MMSC_ENABLED_BOOL;
138 /**
139 * Whether alias is enabled (boolean type)
140 */
141 public static final String
142 MMS_CONFIG_ALIAS_ENABLED = CarrierConfigManager.KEY_MMS_ALIAS_ENABLED_BOOL;
143 /**
144 * Whether audio is allowed to be attached for MMS messages (boolean type)
145 */
146 public static final String
147 MMS_CONFIG_ALLOW_ATTACH_AUDIO = CarrierConfigManager.KEY_MMS_ALLOW_ATTACH_AUDIO_BOOL;
148 /**
149 * Whether multipart SMS is enabled (boolean type)
150 */
151 public static final String MMS_CONFIG_MULTIPART_SMS_ENABLED =
152 CarrierConfigManager.KEY_MMS_MULTIPART_SMS_ENABLED_BOOL;
153 /**
154 * Whether SMS delivery report is enabled (boolean type)
155 */
156 public static final String MMS_CONFIG_SMS_DELIVERY_REPORT_ENABLED =
157 CarrierConfigManager.KEY_MMS_SMS_DELIVERY_REPORT_ENABLED_BOOL;
158 /**
159 * Whether content-disposition field should be expected in an MMS PDU (boolean type)
160 */
161 public static final String MMS_CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION =
162 CarrierConfigManager.KEY_MMS_SUPPORT_MMS_CONTENT_DISPOSITION_BOOL;
163 /**
164 * Whether multipart SMS should be sent as separate messages
165 */
166 public static final String MMS_CONFIG_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES =
167 CarrierConfigManager.KEY_MMS_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES_BOOL;
168 /**
169 * Whether MMS read report is enabled (boolean type)
170 */
171 public static final String MMS_CONFIG_MMS_READ_REPORT_ENABLED =
172 CarrierConfigManager.KEY_MMS_MMS_READ_REPORT_ENABLED_BOOL;
173 /**
174 * Whether MMS delivery report is enabled (boolean type)
175 */
176 public static final String MMS_CONFIG_MMS_DELIVERY_REPORT_ENABLED =
177 CarrierConfigManager.KEY_MMS_MMS_DELIVERY_REPORT_ENABLED_BOOL;
178 /**
179 * Max MMS message size in bytes (int type)
180 */
181 public static final String
182 MMS_CONFIG_MAX_MESSAGE_SIZE = CarrierConfigManager.KEY_MMS_MAX_MESSAGE_SIZE_INT;
183 /**
184 * Max MMS image width (int type)
185 */
186 public static final String
187 MMS_CONFIG_MAX_IMAGE_WIDTH = CarrierConfigManager.KEY_MMS_MAX_IMAGE_WIDTH_INT;
188 /**
189 * Max MMS image height (int type)
190 */
191 public static final String
192 MMS_CONFIG_MAX_IMAGE_HEIGHT = CarrierConfigManager.KEY_MMS_MAX_IMAGE_HEIGHT_INT;
193 /**
194 * Limit of recipients of MMS messages (int type)
195 */
196 public static final String
197 MMS_CONFIG_RECIPIENT_LIMIT = CarrierConfigManager.KEY_MMS_RECIPIENT_LIMIT_INT;
198 /**
199 * Min alias character count (int type)
200 */
201 public static final String
202 MMS_CONFIG_ALIAS_MIN_CHARS = CarrierConfigManager.KEY_MMS_ALIAS_MIN_CHARS_INT;
203 /**
204 * Max alias character count (int type)
205 */
206 public static final String
207 MMS_CONFIG_ALIAS_MAX_CHARS = CarrierConfigManager.KEY_MMS_ALIAS_MAX_CHARS_INT;
208 /**
209 * When the number of parts of a multipart SMS reaches this threshold, it should be converted
210 * into an MMS (int type)
211 */
212 public static final String MMS_CONFIG_SMS_TO_MMS_TEXT_THRESHOLD =
213 CarrierConfigManager.KEY_MMS_SMS_TO_MMS_TEXT_THRESHOLD_INT;
214 /**
215 * Some carriers require SMS to be converted into MMS when text length reaches this threshold
216 * (int type)
217 */
218 public static final String MMS_CONFIG_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD =
219 CarrierConfigManager.KEY_MMS_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD_INT;
220 /**
221 * Max message text size (int type)
222 */
223 public static final String MMS_CONFIG_MESSAGE_TEXT_MAX_SIZE =
224 CarrierConfigManager.KEY_MMS_MESSAGE_TEXT_MAX_SIZE_INT;
225 /**
226 * Max message subject length (int type)
227 */
228 public static final String
229 MMS_CONFIG_SUBJECT_MAX_LENGTH = CarrierConfigManager.KEY_MMS_SUBJECT_MAX_LENGTH_INT;
230 /**
231 * MMS HTTP socket timeout in milliseconds (int type)
232 */
233 public static final String
234 MMS_CONFIG_HTTP_SOCKET_TIMEOUT = CarrierConfigManager.KEY_MMS_HTTP_SOCKET_TIMEOUT_INT;
235 /**
236 * The name of the UA Prof URL HTTP header for MMS HTTP request (String type)
237 */
238 public static final String
239 MMS_CONFIG_UA_PROF_TAG_NAME = CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING;
240 /**
241 * The User-Agent header value for MMS HTTP request (String type)
242 */
243 public static final String
244 MMS_CONFIG_USER_AGENT = CarrierConfigManager.KEY_MMS_USER_AGENT_STRING;
245 /**
246 * The UA Profile URL header value for MMS HTTP request (String type)
247 */
248 public static final String
249 MMS_CONFIG_UA_PROF_URL = CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING;
250 /**
251 * A list of HTTP headers to add to MMS HTTP request, separated by "|" (String type)
252 */
253 public static final String
254 MMS_CONFIG_HTTP_PARAMS = CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING;
255 /**
256 * Email gateway number (String type)
257 */
258 public static final String MMS_CONFIG_EMAIL_GATEWAY_NUMBER =
259 CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING;
260 /**
261 * The suffix to append to the NAI header value for MMS HTTP request (String type)
262 */
263 public static final String
264 MMS_CONFIG_NAI_SUFFIX = CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING;
265 /**
266 * If true, show the cell broadcast (amber alert) in the SMS settings. Some carriers don't want
267 * this shown. (Boolean type)
268 */
269 public static final String MMS_CONFIG_SHOW_CELL_BROADCAST_APP_LINKS =
270 CarrierConfigManager.KEY_MMS_SHOW_CELL_BROADCAST_APP_LINKS_BOOL;
271 /**
272 * Whether the carrier MMSC supports charset field in Content-Type header. If this is false,
273 * then we don't add "charset" to "Content-Type"
274 */
275 public static final String MMS_CONFIG_SUPPORT_HTTP_CHARSET_HEADER =
276 CarrierConfigManager.KEY_MMS_SUPPORT_HTTP_CHARSET_HEADER_BOOL;
277 /**
278 * If true, add "Connection: close" header to MMS HTTP requests so the connection
279 * is immediately closed (disabling keep-alive). (Boolean type)
280 * @hide
281 */
282 public static final String MMS_CONFIG_CLOSE_CONNECTION =
283 CarrierConfigManager.KEY_MMS_CLOSE_CONNECTION_BOOL;
284
Dan Willemsen4980bf42017-02-14 14:17:12 -0800285 /**
Mengjun Leng353bed12018-07-30 15:28:31 +0800286 * 3gpp2 SMS priority is not specified
287 * @hide
288 */
289 public static final int SMS_MESSAGE_PRIORITY_NOT_SPECIFIED = -1;
290 /**
291 * 3gpp SMS period is not specified
292 * @hide
293 */
294 public static final int SMS_MESSAGE_PERIOD_NOT_SPECIFIED = -1;
295
changbetty9dc2ca02019-12-26 19:57:35 +0800296 /** @hide */
297 @IntDef(prefix = { "PREMIUM_SMS_CONSENT" }, value = {
298 SmsManager.PREMIUM_SMS_CONSENT_UNKNOWN,
299 SmsManager.PREMIUM_SMS_CONSENT_ASK_USER,
300 SmsManager.PREMIUM_SMS_CONSENT_NEVER_ALLOW,
301 SmsManager.PREMIUM_SMS_CONSENT_ALWAYS_ALLOW
302 })
303 @Retention(RetentionPolicy.SOURCE)
304 public @interface PremiumSmsConsent {}
305
306 /** Premium SMS Consent for the package is unknown. This indicates that the user
307 * has not set a permission for this package, because this package has never tried
308 * to send a premium SMS.
309 * @hide
310 */
311 @SystemApi
312 public static final int PREMIUM_SMS_CONSENT_UNKNOWN = 0;
313
314 /** Default premium SMS Consent (ask user for each premium SMS sent).
315 * @hide
316 */
317 @SystemApi
318 public static final int PREMIUM_SMS_CONSENT_ASK_USER = 1;
319
320 /** Premium SMS Consent when the owner has denied the app from sending premium SMS.
321 * @hide
322 */
323 @SystemApi
324 public static final int PREMIUM_SMS_CONSENT_NEVER_ALLOW = 2;
325
326 /** Premium SMS Consent when the owner has allowed the app to send premium SMS.
327 * @hide
328 */
329 @SystemApi
330 public static final int PREMIUM_SMS_CONSENT_ALWAYS_ALLOW = 3;
331
Brad Ebinger360415a2019-04-30 11:37:27 -0700332 // result of asking the user for a subscription to perform an operation.
333 private interface SubscriptionResolverResult {
334 void onSuccess(int subId);
335 void onFailure();
336 }
337
338 /**
Philip P. Moltmann7ebd5592020-07-16 14:37:30 -0700339 * Get {@link Context#getOpPackageName()} if this manager has a context, otherwise a dummy
340 * value.
341 *
342 * @return The package name to be used for app-ops checks
343 */
344 private @Nullable String getOpPackageName() {
345 if (mContext == null) {
346 return null;
347 } else {
348 return mContext.getOpPackageName();
349 }
350 }
351
352 /**
353 * Get {@link Context#getAttributionTag()} ()} if this manager has a context, otherwise get the
354 * default attribution tag.
355 *
356 * @return The attribution tag to be used for app-ops checks
357 */
358 private @Nullable String getAttributionTag() {
359 if (mContext == null) {
360 return null;
361 } else {
362 return mContext.getAttributionTag();
363 }
364 }
365
366 /**
Dan Willemsen4980bf42017-02-14 14:17:12 -0800367 * Send a text based SMS.
368 *
369 * <p class="note"><strong>Note:</strong> Using this method requires that your app has the
370 * {@link android.Manifest.permission#SEND_SMS} permission.</p>
371 *
372 * <p class="note"><strong>Note:</strong> Beginning with Android 4.4 (API level 19), if
373 * <em>and only if</em> an app is not selected as the default SMS app, the system automatically
374 * writes messages sent using this method to the SMS Provider (the default SMS app is always
375 * responsible for writing its sent messages to the SMS Provider). For information about
376 * how to behave as the default SMS app, see {@link android.provider.Telephony}.</p>
377 *
Brad Ebinger360415a2019-04-30 11:37:27 -0700378 * <p class="note"><strong>Note:</strong> If {@link #getDefault()} is used to instantiate this
379 * manager on a multi-SIM device, this operation may fail sending the SMS message because no
380 * suitable default subscription could be found. In this case, if {@code sentIntent} is
381 * non-null, then the {@link PendingIntent} will be sent with an error code
382 * {@code RESULT_ERROR_GENERIC_FAILURE} and an extra string {@code "noDefault"} containing the
383 * boolean value {@code true}. See {@link #getDefault()} for more information on the conditions
384 * where this operation may fail.
385 * </p>
386 *
Dan Willemsen4980bf42017-02-14 14:17:12 -0800387 *
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>
Brad Ebingere6de81f2019-03-06 14:32:28 -0800399 * <code>RESULT_ERROR_NO_SERVICE</code><br>
Tom Taylorf43f4f02019-10-08 16:34:04 -0700400 * <code>RESULT_ERROR_NO_SERVICE</code><br>
401 * <code>RESULT_ERROR_LIMIT_EXCEEDED</code><br>
402 * <code>RESULT_ERROR_FDN_CHECK_FAILURE</code><br>
403 * <code>RESULT_ERROR_SHORT_CODE_NOT_ALLOWED</code><br>
404 * <code>RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED</code><br>
405 * <code>RESULT_RADIO_NOT_AVAILABLE</code><br>
406 * <code>RESULT_NETWORK_REJECT</code><br>
407 * <code>RESULT_INVALID_ARGUMENTS</code><br>
408 * <code>RESULT_INVALID_STATE</code><br>
409 * <code>RESULT_NO_MEMORY</code><br>
410 * <code>RESULT_INVALID_SMS_FORMAT</code><br>
411 * <code>RESULT_SYSTEM_ERROR</code><br>
412 * <code>RESULT_MODEM_ERROR</code><br>
413 * <code>RESULT_NETWORK_ERROR</code><br>
414 * <code>RESULT_ENCODING_ERROR</code><br>
415 * <code>RESULT_INVALID_SMSC_ADDRESS</code><br>
416 * <code>RESULT_OPERATION_NOT_ALLOWED</code><br>
417 * <code>RESULT_INTERNAL_ERROR</code><br>
418 * <code>RESULT_NO_RESOURCES</code><br>
419 * <code>RESULT_CANCELLED</code><br>
420 * <code>RESULT_REQUEST_NOT_SUPPORTED</code><br>
421 * <code>RESULT_NO_BLUETOOTH_SERVICE</code><br>
422 * <code>RESULT_INVALID_BLUETOOTH_ADDRESS</code><br>
423 * <code>RESULT_BLUETOOTH_DISCONNECTED</code><br>
424 * <code>RESULT_UNEXPECTED_EVENT_STOP_SENDING</code><br>
425 * <code>RESULT_SMS_BLOCKED_DURING_EMERGENCY</code><br>
426 * <code>RESULT_SMS_SEND_RETRY_FAILED</code><br>
427 * <code>RESULT_REMOTE_EXCEPTION</code><br>
428 * <code>RESULT_NO_DEFAULT_SMS_APP</code><br>
429 * <code>RESULT_RIL_RADIO_NOT_AVAILABLE</code><br>
430 * <code>RESULT_RIL_SMS_SEND_FAIL_RETRY</code><br>
431 * <code>RESULT_RIL_NETWORK_REJECT</code><br>
432 * <code>RESULT_RIL_INVALID_STATE</code><br>
433 * <code>RESULT_RIL_INVALID_ARGUMENTS</code><br>
434 * <code>RESULT_RIL_NO_MEMORY</code><br>
435 * <code>RESULT_RIL_REQUEST_RATE_LIMITED</code><br>
436 * <code>RESULT_RIL_INVALID_SMS_FORMAT</code><br>
437 * <code>RESULT_RIL_SYSTEM_ERR</code><br>
438 * <code>RESULT_RIL_ENCODING_ERR</code><br>
439 * <code>RESULT_RIL_INVALID_SMSC_ADDRESS</code><br>
440 * <code>RESULT_RIL_MODEM_ERR</code><br>
441 * <code>RESULT_RIL_NETWORK_ERR</code><br>
442 * <code>RESULT_RIL_INTERNAL_ERR</code><br>
443 * <code>RESULT_RIL_REQUEST_NOT_SUPPORTED</code><br>
444 * <code>RESULT_RIL_INVALID_MODEM_STATE</code><br>
445 * <code>RESULT_RIL_NETWORK_NOT_READY</code><br>
446 * <code>RESULT_RIL_OPERATION_NOT_ALLOWED</code><br>
447 * <code>RESULT_RIL_NO_RESOURCES</code><br>
448 * <code>RESULT_RIL_CANCELLED</code><br>
449 * <code>RESULT_RIL_SIM_ABSENT</code><br>
450 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> or any of the RESULT_RIL errors,
451 * the sentIntent may include the extra "errorCode" containing a radio technology specific
452 * value, generally only useful for troubleshooting.<br>
Dan Willemsen4980bf42017-02-14 14:17:12 -0800453 * The per-application based SMS control checks sentIntent. If sentIntent
454 * is NULL the caller will be checked against all unknown applications,
455 * which cause smaller number of SMS to be sent in checking period.
456 * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
457 * broadcast when the message is delivered to the recipient. The
458 * raw pdu of the status report is in the extended data ("pdu").
459 *
460 * @throws IllegalArgumentException if destinationAddress or text are empty
461 */
462 public void sendTextMessage(
463 String destinationAddress, String scAddress, String text,
464 PendingIntent sentIntent, PendingIntent deliveryIntent) {
Abhijith Shastry448c12c2017-02-14 13:02:59 -0800465 sendTextMessageInternal(destinationAddress, scAddress, text, sentIntent, deliveryIntent,
Philip P. Moltmann7ebd5592020-07-16 14:37:30 -0700466 true /* persistMessage*/, getOpPackageName(), getAttributionTag(),
467 0L /* messageId */);
Tom Taylor66afc8f2019-11-20 15:39:12 -0800468 }
469
470
471 /**
472 * Send a text based SMS. Same as {@link #sendTextMessage( String destinationAddress,
473 * String scAddress, String text, PendingIntent sentIntent, PendingIntent deliveryIntent)}, but
474 * adds an optional messageId.
475 * @param messageId An id that uniquely identifies the message requested to be sent.
476 * Used for logging and diagnostics purposes. The id may be 0.
477 *
478 * @throws IllegalArgumentException if destinationAddress or text are empty
479 *
480 */
481 public void sendTextMessage(
482 @NonNull String destinationAddress, @Nullable String scAddress, @NonNull String text,
483 @Nullable PendingIntent sentIntent, @Nullable PendingIntent deliveryIntent,
484 long messageId) {
485 sendTextMessageInternal(destinationAddress, scAddress, text, sentIntent, deliveryIntent,
Philip P. Moltmann7ebd5592020-07-16 14:37:30 -0700486 true /* persistMessage*/, getOpPackageName(), getAttributionTag(),
487 messageId);
Dan Willemsen4980bf42017-02-14 14:17:12 -0800488 }
489
Amit Mahajan24c01a22019-09-20 11:13:05 -0700490 /**
491 * Send a text based SMS with messaging options.
492 *
493 * <p class="note"><strong>Note:</strong> If {@link #getDefault()} is used to instantiate this
494 * manager on a multi-SIM device, this operation may fail sending the SMS message because no
495 * suitable default subscription could be found. In this case, if {@code sentIntent} is
496 * non-null, then the {@link PendingIntent} will be sent with an error code
497 * {@code RESULT_ERROR_GENERIC_FAILURE} and an extra string {@code "noDefault"} containing the
498 * boolean value {@code true}. See {@link #getDefault()} for more information on the conditions
499 * where this operation may fail.
500 * </p>
501 *
502 * @param destinationAddress the address to send the message to
503 * @param scAddress is the service center address or null to use
504 * the current default SMSC
505 * @param text the body of the message to send
506 * @param sentIntent if not NULL this <code>PendingIntent</code> is
507 * broadcast when the message is successfully sent, or failed.
508 * The result code will be <code>Activity.RESULT_OK</code> for success,
509 * or one of these errors:<br>
510 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
511 * <code>RESULT_ERROR_RADIO_OFF</code><br>
512 * <code>RESULT_ERROR_NULL_PDU</code><br>
Tom Taylorf43f4f02019-10-08 16:34:04 -0700513 * <code>RESULT_ERROR_NO_SERVICE</code><br>
514 * <code>RESULT_ERROR_NO_SERVICE</code><br>
515 * <code>RESULT_ERROR_LIMIT_EXCEEDED</code><br>
516 * <code>RESULT_ERROR_FDN_CHECK_FAILURE</code><br>
517 * <code>RESULT_ERROR_SHORT_CODE_NOT_ALLOWED</code><br>
518 * <code>RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED</code><br>
519 * <code>RESULT_RADIO_NOT_AVAILABLE</code><br>
520 * <code>RESULT_NETWORK_REJECT</code><br>
521 * <code>RESULT_INVALID_ARGUMENTS</code><br>
522 * <code>RESULT_INVALID_STATE</code><br>
523 * <code>RESULT_NO_MEMORY</code><br>
524 * <code>RESULT_INVALID_SMS_FORMAT</code><br>
525 * <code>RESULT_SYSTEM_ERROR</code><br>
526 * <code>RESULT_MODEM_ERROR</code><br>
527 * <code>RESULT_NETWORK_ERROR</code><br>
528 * <code>RESULT_ENCODING_ERROR</code><br>
529 * <code>RESULT_INVALID_SMSC_ADDRESS</code><br>
530 * <code>RESULT_OPERATION_NOT_ALLOWED</code><br>
531 * <code>RESULT_INTERNAL_ERROR</code><br>
532 * <code>RESULT_NO_RESOURCES</code><br>
533 * <code>RESULT_CANCELLED</code><br>
534 * <code>RESULT_REQUEST_NOT_SUPPORTED</code><br>
535 * <code>RESULT_NO_BLUETOOTH_SERVICE</code><br>
536 * <code>RESULT_INVALID_BLUETOOTH_ADDRESS</code><br>
537 * <code>RESULT_BLUETOOTH_DISCONNECTED</code><br>
538 * <code>RESULT_UNEXPECTED_EVENT_STOP_SENDING</code><br>
539 * <code>RESULT_SMS_BLOCKED_DURING_EMERGENCY</code><br>
540 * <code>RESULT_SMS_SEND_RETRY_FAILED</code><br>
541 * <code>RESULT_REMOTE_EXCEPTION</code><br>
542 * <code>RESULT_NO_DEFAULT_SMS_APP</code><br>
543 * <code>RESULT_RIL_RADIO_NOT_AVAILABLE</code><br>
544 * <code>RESULT_RIL_SMS_SEND_FAIL_RETRY</code><br>
545 * <code>RESULT_RIL_NETWORK_REJECT</code><br>
546 * <code>RESULT_RIL_INVALID_STATE</code><br>
547 * <code>RESULT_RIL_INVALID_ARGUMENTS</code><br>
548 * <code>RESULT_RIL_NO_MEMORY</code><br>
549 * <code>RESULT_RIL_REQUEST_RATE_LIMITED</code><br>
550 * <code>RESULT_RIL_INVALID_SMS_FORMAT</code><br>
551 * <code>RESULT_RIL_SYSTEM_ERR</code><br>
552 * <code>RESULT_RIL_ENCODING_ERR</code><br>
553 * <code>RESULT_RIL_INVALID_SMSC_ADDRESS</code><br>
554 * <code>RESULT_RIL_MODEM_ERR</code><br>
555 * <code>RESULT_RIL_NETWORK_ERR</code><br>
556 * <code>RESULT_RIL_INTERNAL_ERR</code><br>
557 * <code>RESULT_RIL_REQUEST_NOT_SUPPORTED</code><br>
558 * <code>RESULT_RIL_INVALID_MODEM_STATE</code><br>
559 * <code>RESULT_RIL_NETWORK_NOT_READY</code><br>
560 * <code>RESULT_RIL_OPERATION_NOT_ALLOWED</code><br>
561 * <code>RESULT_RIL_NO_RESOURCES</code><br>
562 * <code>RESULT_RIL_CANCELLED</code><br>
563 * <code>RESULT_RIL_SIM_ABSENT</code><br>
564 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> or any of the RESULT_RIL errors,
565 * the sentIntent may include the extra "errorCode" containing a radio technology specific
566 * value, generally only useful for troubleshooting.<br>
Amit Mahajan24c01a22019-09-20 11:13:05 -0700567 * The per-application based SMS control checks sentIntent. If sentIntent
568 * is NULL the caller will be checked against all unknown applications,
569 * which cause smaller number of SMS to be sent in checking period.
570 * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
571 * broadcast when the message is delivered to the recipient. The
572 * raw pdu of the status report is in the extended data ("pdu").
573 * @param priority Priority level of the message
574 * Refer specification See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1
575 * ---------------------------------
576 * PRIORITY | Level of Priority
577 * ---------------------------------
578 * '00' | Normal
579 * '01' | Interactive
580 * '10' | Urgent
581 * '11' | Emergency
582 * ----------------------------------
583 * Any Other values included Negative considered as Invalid Priority Indicator of the message.
584 * @param expectMore is a boolean to indicate the sending messages through same link or not.
585 * @param validityPeriod Validity Period of the message in mins.
586 * Refer specification 3GPP TS 23.040 V6.8.1 section 9.2.3.12.1.
587 * Validity Period(Minimum) -> 5 mins
588 * Validity Period(Maximum) -> 635040 mins(i.e.63 weeks).
589 * Any Other values included Negative considered as Invalid Validity Period of the message.
590 *
591 * @throws IllegalArgumentException if destinationAddress or text are empty
592 * {@hide}
593 */
Mathew Inwood8e742f92020-10-27 11:47:29 +0000594 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Amit Mahajan24c01a22019-09-20 11:13:05 -0700595 public void sendTextMessage(
596 String destinationAddress, String scAddress, String text,
597 PendingIntent sentIntent, PendingIntent deliveryIntent,
598 int priority, boolean expectMore, int validityPeriod) {
599 sendTextMessageInternal(destinationAddress, scAddress, text, sentIntent, deliveryIntent,
600 true /* persistMessage*/, priority, expectMore, validityPeriod);
601 }
602
Dan Willemsen4980bf42017-02-14 14:17:12 -0800603 private void sendTextMessageInternal(String destinationAddress, String scAddress,
604 String text, PendingIntent sentIntent, PendingIntent deliveryIntent,
Philip P. Moltmann83083302020-03-19 17:27:39 -0700605 boolean persistMessage, String packageName, String attributionTag, long messageId) {
Dan Willemsen4980bf42017-02-14 14:17:12 -0800606 if (TextUtils.isEmpty(destinationAddress)) {
607 throw new IllegalArgumentException("Invalid destinationAddress");
608 }
609
610 if (TextUtils.isEmpty(text)) {
611 throw new IllegalArgumentException("Invalid message body");
612 }
613
Brad Ebinger360415a2019-04-30 11:37:27 -0700614 // We will only show the SMS disambiguation dialog in the case that the message is being
615 // persisted. This is for two reasons:
616 // 1) Messages that are not persisted are sent by carrier/OEM apps for a specific
617 // subscription and require special permissions. These messages are usually not sent by
618 // the device user and should not have an SMS disambiguation dialog associated with them
619 // because the device user did not trigger them.
620 // 2) The SMS disambiguation dialog ONLY checks to make sure that the user has the SEND_SMS
621 // permission. If we call resolveSubscriptionForOperation from a carrier/OEM app that has
622 // the correct MODIFY_PHONE_STATE or carrier permissions, but no SEND_SMS, it will throw
623 // an incorrect SecurityException.
624 if (persistMessage) {
625 resolveSubscriptionForOperation(new SubscriptionResolverResult() {
626 @Override
627 public void onSuccess(int subId) {
628 ISms iSms = getISmsServiceOrThrow();
629 try {
Philip P. Moltmann83083302020-03-19 17:27:39 -0700630 iSms.sendTextForSubscriber(subId, packageName, attributionTag,
Brad Ebinger360415a2019-04-30 11:37:27 -0700631 destinationAddress, scAddress, text, sentIntent, deliveryIntent,
Tom Taylor66afc8f2019-11-20 15:39:12 -0800632 persistMessage, messageId);
Brad Ebinger360415a2019-04-30 11:37:27 -0700633 } catch (RemoteException e) {
634 Log.e(TAG, "sendTextMessageInternal: Couldn't send SMS, exception - "
Tom Taylor66afc8f2019-11-20 15:39:12 -0800635 + e.getMessage() + " id: " + messageId);
Tom Taylorf43f4f02019-10-08 16:34:04 -0700636 notifySmsError(sentIntent, RESULT_REMOTE_EXCEPTION);
Brad Ebinger360415a2019-04-30 11:37:27 -0700637 }
638 }
639
640 @Override
641 public void onFailure() {
Tom Taylorf43f4f02019-10-08 16:34:04 -0700642 notifySmsError(sentIntent, RESULT_NO_DEFAULT_SMS_APP);
Brad Ebinger360415a2019-04-30 11:37:27 -0700643 }
644 });
645 } else {
646 // Not persisting the message, used by sendTextMessageWithoutPersisting() and is not
647 // visible to the user.
Hayden Gomes7a3d8a42019-03-21 18:30:41 -0700648 ISms iSms = getISmsServiceOrThrow();
Brad Ebinger360415a2019-04-30 11:37:27 -0700649 try {
Philip P. Moltmann83083302020-03-19 17:27:39 -0700650 iSms.sendTextForSubscriber(getSubscriptionId(), packageName, attributionTag,
Brad Ebinger360415a2019-04-30 11:37:27 -0700651 destinationAddress, scAddress, text, sentIntent, deliveryIntent,
Tom Taylor66afc8f2019-11-20 15:39:12 -0800652 persistMessage, messageId);
Brad Ebinger360415a2019-04-30 11:37:27 -0700653 } catch (RemoteException e) {
654 Log.e(TAG, "sendTextMessageInternal (no persist): Couldn't send SMS, exception - "
Tom Taylor66afc8f2019-11-20 15:39:12 -0800655 + e.getMessage() + " id: " + messageId);
Tom Taylorf43f4f02019-10-08 16:34:04 -0700656 notifySmsError(sentIntent, RESULT_REMOTE_EXCEPTION);
Brad Ebinger360415a2019-04-30 11:37:27 -0700657 }
Dan Willemsen4980bf42017-02-14 14:17:12 -0800658 }
659 }
660
661 /**
662 * Send a text based SMS without writing it into the SMS Provider.
663 *
goneildcf5c042017-10-24 18:05:19 -0700664 * <p>
665 * The message will be sent directly over the network and will not be visible in SMS
666 * applications. Intended for internal carrier use only.
667 * </p>
668 *
Jeff Davidsona4a4c8a2018-03-15 17:10:58 -0700669 * <p>Requires Permission: Both {@link android.Manifest.permission#SEND_SMS} and
670 * {@link android.Manifest.permission#MODIFY_PHONE_STATE}, or that the calling app has carrier
671 * privileges (see {@link TelephonyManager#hasCarrierPrivileges}), or that the calling app is
672 * the default IMS app (see
673 * {@link CarrierConfigManager#KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING}).
Brad Ebinger360415a2019-04-30 11:37:27 -0700674 * </p>
675 *
676 * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier
677 * applications or the Telephony framework and will never trigger an SMS disambiguation
678 * dialog. If this method is called on a device that has multiple active subscriptions, this
679 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
680 * default subscription is defined, the subscription ID associated with this message will be
681 * INVALID, which will result in the SMS being sent on the subscription associated with logical
682 * slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the SMS is sent on the
683 * correct subscription.
684 * </p>
Dan Willemsen4980bf42017-02-14 14:17:12 -0800685 *
686 * @see #sendTextMessage(String, String, String, PendingIntent, PendingIntent)
Dan Willemsen4980bf42017-02-14 14:17:12 -0800687 */
Jeff Davidsona4a4c8a2018-03-15 17:10:58 -0700688 @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
goneil52f3d192017-12-13 16:20:35 -0800689 @RequiresPermission(allOf = {
690 android.Manifest.permission.MODIFY_PHONE_STATE,
691 android.Manifest.permission.SEND_SMS
692 })
Dan Willemsen4980bf42017-02-14 14:17:12 -0800693 public void sendTextMessageWithoutPersisting(
694 String destinationAddress, String scAddress, String text,
695 PendingIntent sentIntent, PendingIntent deliveryIntent) {
Abhijith Shastry448c12c2017-02-14 13:02:59 -0800696 sendTextMessageInternal(destinationAddress, scAddress, text, sentIntent, deliveryIntent,
Philip P. Moltmann7ebd5592020-07-16 14:37:30 -0700697 false /* persistMessage */, getOpPackageName(),
698 getAttributionTag(), 0L /* messageId */);
Dan Willemsen4980bf42017-02-14 14:17:12 -0800699 }
700
Mengjun Lengb379ce92017-03-13 17:08:26 +0800701 private void sendTextMessageInternal(
702 String destinationAddress, String scAddress, String text,
703 PendingIntent sentIntent, PendingIntent deliveryIntent, boolean persistMessage,
704 int priority, boolean expectMore, int validityPeriod) {
705 if (TextUtils.isEmpty(destinationAddress)) {
706 throw new IllegalArgumentException("Invalid destinationAddress");
707 }
708
709 if (TextUtils.isEmpty(text)) {
710 throw new IllegalArgumentException("Invalid message body");
711 }
712
713 if (priority < 0x00 || priority > 0x03) {
Taesu Lee1ec60182020-05-18 20:08:58 +0900714 Log.e(TAG, "Invalid Priority " + priority);
Mengjun Leng353bed12018-07-30 15:28:31 +0800715 priority = SMS_MESSAGE_PRIORITY_NOT_SPECIFIED;
Mengjun Lengb379ce92017-03-13 17:08:26 +0800716 }
717
718 if (validityPeriod < 0x05 || validityPeriod > 0x09b0a0) {
Taesu Lee1ec60182020-05-18 20:08:58 +0900719 Log.e(TAG, "Invalid Validity Period " + validityPeriod);
Mengjun Leng353bed12018-07-30 15:28:31 +0800720 validityPeriod = SMS_MESSAGE_PERIOD_NOT_SPECIFIED;
Mengjun Lengb379ce92017-03-13 17:08:26 +0800721 }
722
Brad Ebinger360415a2019-04-30 11:37:27 -0700723 final int finalPriority = priority;
724 final int finalValidity = validityPeriod;
Brad Ebinger360415a2019-04-30 11:37:27 -0700725 // We will only show the SMS disambiguation dialog in the case that the message is being
726 // persisted. This is for two reasons:
727 // 1) Messages that are not persisted are sent by carrier/OEM apps for a specific
728 // subscription and require special permissions. These messages are usually not sent by
729 // the device user and should not have an SMS disambiguation dialog associated with them
730 // because the device user did not trigger them.
731 // 2) The SMS disambiguation dialog ONLY checks to make sure that the user has the SEND_SMS
732 // permission. If we call resolveSubscriptionForOperation from a carrier/OEM app that has
733 // the correct MODIFY_PHONE_STATE or carrier permissions, but no SEND_SMS, it will throw
734 // an incorrect SecurityException.
735 if (persistMessage) {
736 resolveSubscriptionForOperation(new SubscriptionResolverResult() {
737 @Override
738 public void onSuccess(int subId) {
739 try {
740 ISms iSms = getISmsServiceOrThrow();
741 if (iSms != null) {
742 iSms.sendTextForSubscriberWithOptions(subId,
Philip P. Moltmannf35af1f2020-03-19 21:37:01 +0000743 null, null, destinationAddress,
Brad Ebinger360415a2019-04-30 11:37:27 -0700744 scAddress,
745 text, sentIntent, deliveryIntent, persistMessage, finalPriority,
746 expectMore, finalValidity);
747 }
748 } catch (RemoteException e) {
749 Log.e(TAG, "sendTextMessageInternal: Couldn't send SMS, exception - "
750 + e.getMessage());
Tom Taylorf43f4f02019-10-08 16:34:04 -0700751 notifySmsError(sentIntent, RESULT_REMOTE_EXCEPTION);
Brad Ebinger360415a2019-04-30 11:37:27 -0700752 }
753 }
754
755 @Override
756 public void onFailure() {
Tom Taylorf43f4f02019-10-08 16:34:04 -0700757 notifySmsError(sentIntent, RESULT_NO_DEFAULT_SMS_APP);
Brad Ebinger360415a2019-04-30 11:37:27 -0700758 }
759 });
760 } else {
761 try {
762 ISms iSms = getISmsServiceOrThrow();
763 if (iSms != null) {
764 iSms.sendTextForSubscriberWithOptions(getSubscriptionId(),
Philip P. Moltmannf35af1f2020-03-19 21:37:01 +0000765 null, null, destinationAddress,
Brad Ebinger360415a2019-04-30 11:37:27 -0700766 scAddress,
767 text, sentIntent, deliveryIntent, persistMessage, finalPriority,
768 expectMore, finalValidity);
769 }
770 } catch (RemoteException e) {
771 Log.e(TAG, "sendTextMessageInternal(no persist): Couldn't send SMS, exception - "
772 + e.getMessage());
Tom Taylorf43f4f02019-10-08 16:34:04 -0700773 notifySmsError(sentIntent, RESULT_REMOTE_EXCEPTION);
Mengjun Lengb379ce92017-03-13 17:08:26 +0800774 }
Mengjun Lengb379ce92017-03-13 17:08:26 +0800775 }
776 }
777
778 /**
779 * Send a text based SMS without writing it into the SMS Provider.
780 *
781 * <p>Requires Permission:
782 * {@link android.Manifest.permission#MODIFY_PHONE_STATE} or the calling app has carrier
783 * privileges.
784 * </p>
785 *
Brad Ebinger360415a2019-04-30 11:37:27 -0700786 * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier
787 * applications or the Telephony framework and will never trigger an SMS disambiguation
788 * dialog. If this method is called on a device that has multiple active subscriptions, this
789 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
790 * default subscription is defined, the subscription ID associated with this message will be
791 * INVALID, which will result in the SMS being sent on the subscription associated with logical
792 * slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the SMS is sent on the
793 * correct subscription.
794 * </p>
795 *
Mengjun Lengb379ce92017-03-13 17:08:26 +0800796 * @see #sendTextMessage(String, String, String, PendingIntent,
797 * PendingIntent, int, boolean, int)
798 * @hide
799 */
Mathew Inwooda8382062018-08-16 17:01:12 +0100800 @UnsupportedAppUsage
Mengjun Lengb379ce92017-03-13 17:08:26 +0800801 public void sendTextMessageWithoutPersisting(
802 String destinationAddress, String scAddress, String text,
803 PendingIntent sentIntent, PendingIntent deliveryIntent, int priority,
804 boolean expectMore, int validityPeriod) {
805 sendTextMessageInternal(destinationAddress, scAddress, text, sentIntent, deliveryIntent,
806 false /* persistMessage */, priority, expectMore, validityPeriod);
807 }
808
809 /**
810 *
Dan Willemsen4980bf42017-02-14 14:17:12 -0800811 * Inject an SMS PDU into the android application framework.
812 *
Abhijith Shastrybc1a6e62017-03-29 10:54:53 -0700813 * <p>Requires permission: {@link android.Manifest.permission#MODIFY_PHONE_STATE} or carrier
Jeff Davidsonbeb90fd2017-10-13 11:23:28 -0700814 * privileges per {@link android.telephony.TelephonyManager#hasCarrierPrivileges}.
Dan Willemsen4980bf42017-02-14 14:17:12 -0800815 *
Brad Ebinger360415a2019-04-30 11:37:27 -0700816 * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier
817 * applications or the Telephony framework and will never trigger an SMS disambiguation
818 * dialog. If this method is called on a device that has multiple active subscriptions, this
819 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
820 * default subscription is defined, the subscription ID associated with this message will be
821 * INVALID, which will result in the SMS being injected on the subscription associated with
822 * logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the SMS is
823 * delivered to the correct subscription.
824 * </p>
825 *
Dan Willemsen4980bf42017-02-14 14:17:12 -0800826 * @param pdu is the byte array of pdu to be injected into android application framework
Jeff Davidsonbeb90fd2017-10-13 11:23:28 -0700827 * @param format is the format of SMS pdu ({@link SmsMessage#FORMAT_3GPP} or
828 * {@link SmsMessage#FORMAT_3GPP2})
Dan Willemsen4980bf42017-02-14 14:17:12 -0800829 * @param receivedIntent if not NULL this <code>PendingIntent</code> is
830 * broadcast when the message is successfully received by the
831 * android application framework, or failed. This intent is broadcasted at
832 * the same time an SMS received from radio is acknowledged back.
Jeff Davidsonbeb90fd2017-10-13 11:23:28 -0700833 * The result code will be {@link android.provider.Telephony.Sms.Intents#RESULT_SMS_HANDLED}
Tom Taylorccc1c3e2019-10-30 10:08:50 -0700834 * for success, or {@link android.provider.Telephony.Sms.Intents#RESULT_SMS_GENERIC_ERROR} or
835 * {@link #RESULT_REMOTE_EXCEPTION} for error.
Dan Willemsen4980bf42017-02-14 14:17:12 -0800836 *
Jeff Davidsonbeb90fd2017-10-13 11:23:28 -0700837 * @throws IllegalArgumentException if the format is invalid.
Dan Willemsen4980bf42017-02-14 14:17:12 -0800838 */
Jeff Davidsonbeb90fd2017-10-13 11:23:28 -0700839 public void injectSmsPdu(
840 byte[] pdu, @SmsMessage.Format String format, PendingIntent receivedIntent) {
Dan Willemsen4980bf42017-02-14 14:17:12 -0800841 if (!format.equals(SmsMessage.FORMAT_3GPP) && !format.equals(SmsMessage.FORMAT_3GPP2)) {
842 // Format must be either 3gpp or 3gpp2.
843 throw new IllegalArgumentException(
844 "Invalid pdu format. format must be either 3gpp or 3gpp2");
845 }
846 try {
Tim Murrayc73a2812019-10-22 11:39:05 -0700847 ISms iSms = TelephonyManager.getSmsService();
Hayden Gomes7a3d8a42019-03-21 18:30:41 -0700848 if (iSms != null) {
849 iSms.injectSmsPduForSubscriber(
Dan Willemsen4980bf42017-02-14 14:17:12 -0800850 getSubscriptionId(), pdu, format, receivedIntent);
851 }
852 } catch (RemoteException ex) {
Brad Ebinger360415a2019-04-30 11:37:27 -0700853 try {
854 if (receivedIntent != null) {
Tom Taylorf43f4f02019-10-08 16:34:04 -0700855 receivedIntent.send(RESULT_REMOTE_EXCEPTION);
Brad Ebinger360415a2019-04-30 11:37:27 -0700856 }
857 } catch (PendingIntent.CanceledException cx) {
858 // Don't worry about it, we do not need to notify the caller if this is the case.
859 }
Dan Willemsen4980bf42017-02-14 14:17:12 -0800860 }
861 }
862
863 /**
Taesu Lee98d41e62018-06-15 15:26:51 +0900864 * Divide a message text into several fragments, none bigger than the maximum SMS message size.
Dan Willemsen4980bf42017-02-14 14:17:12 -0800865 *
Taesu Lee98d41e62018-06-15 15:26:51 +0900866 * @param text the original message. Must not be null.
867 * @return an <code>ArrayList</code> of strings that, in order, comprise the original message.
868 * @throws IllegalArgumentException if text is null.
Dan Willemsen4980bf42017-02-14 14:17:12 -0800869 */
870 public ArrayList<String> divideMessage(String text) {
871 if (null == text) {
872 throw new IllegalArgumentException("text is null");
873 }
Taesu Lee98d41e62018-06-15 15:26:51 +0900874 return SmsMessage.fragmentText(text, getSubscriptionId());
Dan Willemsen4980bf42017-02-14 14:17:12 -0800875 }
876
877 /**
878 * Send a multi-part text based SMS. The callee should have already
879 * divided the message into correctly sized parts by calling
880 * <code>divideMessage</code>.
881 *
882 * <p class="note"><strong>Note:</strong> Using this method requires that your app has the
883 * {@link android.Manifest.permission#SEND_SMS} permission.</p>
884 *
885 * <p class="note"><strong>Note:</strong> Beginning with Android 4.4 (API level 19), if
886 * <em>and only if</em> an app is not selected as the default SMS app, the system automatically
887 * writes messages sent using this method to the SMS Provider (the default SMS app is always
888 * responsible for writing its sent messages to the SMS Provider). For information about
889 * how to behave as the default SMS app, see {@link android.provider.Telephony}.</p>
890 *
Brad Ebinger360415a2019-04-30 11:37:27 -0700891 * <p class="note"><strong>Note:</strong> If {@link #getDefault()} is used to instantiate this
892 * manager on a multi-SIM device, this operation may fail sending the SMS message because no
893 * suitable default subscription could be found. In this case, if {@code sentIntent} is
894 * non-null, then the {@link PendingIntent} will be sent with an error code
895 * {@code RESULT_ERROR_GENERIC_FAILURE} and an extra string {@code "noDefault"} containing the
896 * boolean value {@code true}. See {@link #getDefault()} for more information on the conditions
897 * where this operation may fail.
898 * </p>
899 *
900 *
Dan Willemsen4980bf42017-02-14 14:17:12 -0800901 * @param destinationAddress the address to send the message to
902 * @param scAddress is the service center address or null to use
903 * the current default SMSC
904 * @param parts an <code>ArrayList</code> of strings that, in order,
905 * comprise the original message
906 * @param sentIntents if not null, an <code>ArrayList</code> of
907 * <code>PendingIntent</code>s (one for each message part) that is
908 * broadcast when the corresponding message part has been sent.
909 * The result code will be <code>Activity.RESULT_OK</code> for success,
910 * or one of these errors:<br>
Tom Taylorf43f4f02019-10-08 16:34:04 -0700911 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
912 * <code>RESULT_ERROR_RADIO_OFF</code><br>
913 * <code>RESULT_ERROR_NULL_PDU</code><br>
914 * <code>RESULT_ERROR_NO_SERVICE</code><br>
915 * <code>RESULT_ERROR_NO_SERVICE</code><br>
916 * <code>RESULT_ERROR_LIMIT_EXCEEDED</code><br>
917 * <code>RESULT_ERROR_FDN_CHECK_FAILURE</code><br>
918 * <code>RESULT_ERROR_SHORT_CODE_NOT_ALLOWED</code><br>
919 * <code>RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED</code><br>
920 * <code>RESULT_RADIO_NOT_AVAILABLE</code><br>
921 * <code>RESULT_NETWORK_REJECT</code><br>
922 * <code>RESULT_INVALID_ARGUMENTS</code><br>
923 * <code>RESULT_INVALID_STATE</code><br>
924 * <code>RESULT_NO_MEMORY</code><br>
925 * <code>RESULT_INVALID_SMS_FORMAT</code><br>
926 * <code>RESULT_SYSTEM_ERROR</code><br>
927 * <code>RESULT_MODEM_ERROR</code><br>
928 * <code>RESULT_NETWORK_ERROR</code><br>
929 * <code>RESULT_ENCODING_ERROR</code><br>
930 * <code>RESULT_INVALID_SMSC_ADDRESS</code><br>
931 * <code>RESULT_OPERATION_NOT_ALLOWED</code><br>
932 * <code>RESULT_INTERNAL_ERROR</code><br>
933 * <code>RESULT_NO_RESOURCES</code><br>
934 * <code>RESULT_CANCELLED</code><br>
935 * <code>RESULT_REQUEST_NOT_SUPPORTED</code><br>
936 * <code>RESULT_NO_BLUETOOTH_SERVICE</code><br>
937 * <code>RESULT_INVALID_BLUETOOTH_ADDRESS</code><br>
938 * <code>RESULT_BLUETOOTH_DISCONNECTED</code><br>
939 * <code>RESULT_UNEXPECTED_EVENT_STOP_SENDING</code><br>
940 * <code>RESULT_SMS_BLOCKED_DURING_EMERGENCY</code><br>
941 * <code>RESULT_SMS_SEND_RETRY_FAILED</code><br>
942 * <code>RESULT_REMOTE_EXCEPTION</code><br>
943 * <code>RESULT_NO_DEFAULT_SMS_APP</code><br>
944 * <code>RESULT_RIL_RADIO_NOT_AVAILABLE</code><br>
945 * <code>RESULT_RIL_SMS_SEND_FAIL_RETRY</code><br>
946 * <code>RESULT_RIL_NETWORK_REJECT</code><br>
947 * <code>RESULT_RIL_INVALID_STATE</code><br>
948 * <code>RESULT_RIL_INVALID_ARGUMENTS</code><br>
949 * <code>RESULT_RIL_NO_MEMORY</code><br>
950 * <code>RESULT_RIL_REQUEST_RATE_LIMITED</code><br>
951 * <code>RESULT_RIL_INVALID_SMS_FORMAT</code><br>
952 * <code>RESULT_RIL_SYSTEM_ERR</code><br>
953 * <code>RESULT_RIL_ENCODING_ERR</code><br>
954 * <code>RESULT_RIL_INVALID_SMSC_ADDRESS</code><br>
955 * <code>RESULT_RIL_MODEM_ERR</code><br>
956 * <code>RESULT_RIL_NETWORK_ERR</code><br>
957 * <code>RESULT_RIL_INTERNAL_ERR</code><br>
958 * <code>RESULT_RIL_REQUEST_NOT_SUPPORTED</code><br>
959 * <code>RESULT_RIL_INVALID_MODEM_STATE</code><br>
960 * <code>RESULT_RIL_NETWORK_NOT_READY</code><br>
961 * <code>RESULT_RIL_OPERATION_NOT_ALLOWED</code><br>
962 * <code>RESULT_RIL_NO_RESOURCES</code><br>
963 * <code>RESULT_RIL_CANCELLED</code><br>
964 * <code>RESULT_RIL_SIM_ABSENT</code><br>
965 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> or any of the RESULT_RIL errors,
966 * the sentIntent may include the extra "errorCode" containing a radio technology specific
967 * value, generally only useful for troubleshooting.<br>
Dan Willemsen4980bf42017-02-14 14:17:12 -0800968 * The per-application based SMS control checks sentIntent. If sentIntent
969 * is NULL the caller will be checked against all unknown applications,
970 * which cause smaller number of SMS to be sent in checking period.
971 * @param deliveryIntents if not null, an <code>ArrayList</code> of
972 * <code>PendingIntent</code>s (one for each message part) that is
973 * broadcast when the corresponding message part has been delivered
974 * to the recipient. The raw pdu of the status report is in the
975 * extended data ("pdu").
976 *
977 * @throws IllegalArgumentException if destinationAddress or data are empty
978 */
979 public void sendMultipartTextMessage(
980 String destinationAddress, String scAddress, ArrayList<String> parts,
981 ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) {
Abhijith Shastry448c12c2017-02-14 13:02:59 -0800982 sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents,
Philip P. Moltmann7ebd5592020-07-16 14:37:30 -0700983 deliveryIntents, true /* persistMessage*/, getOpPackageName(),
984 getAttributionTag(), 0L /* messageId */);
Tom Taylor66afc8f2019-11-20 15:39:12 -0800985 }
986
987 /**
988 * Send a multi-part text based SMS. Same as #sendMultipartTextMessage(String, String,
989 * ArrayList, ArrayList, ArrayList), but adds an optional messageId.
990 * @param messageId An id that uniquely identifies the message requested to be sent.
991 * Used for logging and diagnostics purposes. The id may be 0.
992 *
993 * @throws IllegalArgumentException if destinationAddress or data are empty
994 *
995 */
996 public void sendMultipartTextMessage(
997 @NonNull String destinationAddress, @Nullable String scAddress,
998 @NonNull List<String> parts, @Nullable List<PendingIntent> sentIntents,
999 @Nullable List<PendingIntent> deliveryIntents, long messageId) {
1000 sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents,
Philip P. Moltmann7ebd5592020-07-16 14:37:30 -07001001 deliveryIntents, true /* persistMessage*/, getOpPackageName(),
1002 getAttributionTag(), messageId);
Youming Ye35c84882019-04-30 10:35:08 -07001003 }
1004
1005 /**
Youming Ye35c84882019-04-30 10:35:08 -07001006 * Similar method as #sendMultipartTextMessage(String, String, ArrayList, ArrayList, ArrayList)
Brad Ebinger360415a2019-04-30 11:37:27 -07001007 * With an additional argument.
1008 *
1009 * <p class="note"><strong>Note:</strong> This method is intended for internal use the Telephony
1010 * framework and will never trigger an SMS disambiguation dialog. If this method is called on a
1011 * device that has multiple active subscriptions, this {@link SmsManager} instance has been
1012 * created with {@link #getDefault()}, and no user-defined default subscription is defined, the
1013 * subscription ID associated with this message will be INVALID, which will result in the SMS
1014 * being sent on the subscription associated with logical slot 0. Use
1015 * {@link #getSmsManagerForSubscriptionId(int)} to ensure the SMS is sent on the correct
1016 * subscription.
1017 * </p>
1018 *
Shuo Qian24fded62020-01-14 14:48:27 -08001019 * @param packageName serves as the default package name if the package name that is
1020 * associated with the user id is null.
Youming Ye35c84882019-04-30 10:35:08 -07001021 */
Hall Liue2f17aa2019-10-31 15:17:58 -07001022 public void sendMultipartTextMessage(
Tom Taylor66afc8f2019-11-20 15:39:12 -08001023 @NonNull String destinationAddress, @Nullable String scAddress,
Hall Liue2f17aa2019-10-31 15:17:58 -07001024 @NonNull List<String> parts, @Nullable List<PendingIntent> sentIntents,
Philip P. Moltmann83083302020-03-19 17:27:39 -07001025 @Nullable List<PendingIntent> deliveryIntents, @NonNull String packageName,
1026 @Nullable String attributionTag) {
Youming Ye35c84882019-04-30 10:35:08 -07001027 sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents,
Philip P. Moltmann83083302020-03-19 17:27:39 -07001028 deliveryIntents, true /* persistMessage*/, packageName, attributionTag,
1029 0L /* messageId */);
Dan Willemsen4980bf42017-02-14 14:17:12 -08001030 }
1031
1032 private void sendMultipartTextMessageInternal(
Abhijith Shastry448c12c2017-02-14 13:02:59 -08001033 String destinationAddress, String scAddress, List<String> parts,
1034 List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents,
Philip P. Moltmann83083302020-03-19 17:27:39 -07001035 boolean persistMessage, String packageName, @Nullable String attributionTag,
1036 long messageId) {
Dan Willemsen4980bf42017-02-14 14:17:12 -08001037 if (TextUtils.isEmpty(destinationAddress)) {
1038 throw new IllegalArgumentException("Invalid destinationAddress");
1039 }
1040 if (parts == null || parts.size() < 1) {
1041 throw new IllegalArgumentException("Invalid message body");
1042 }
1043
1044 if (parts.size() > 1) {
Brad Ebinger360415a2019-04-30 11:37:27 -07001045 // We will only show the SMS disambiguation dialog in the case that the message is being
1046 // persisted. This is for two reasons:
1047 // 1) Messages that are not persisted are sent by carrier/OEM apps for a specific
1048 // subscription and require special permissions. These messages are usually not sent
1049 // by the device user and should not have an SMS disambiguation dialog associated
1050 // with them because the device user did not trigger them.
1051 // 2) The SMS disambiguation dialog ONLY checks to make sure that the user has the
1052 // SEND_SMS permission. If we call resolveSubscriptionForOperation from a carrier/OEM
1053 // app that has the correct MODIFY_PHONE_STATE or carrier permissions, but no
1054 // SEND_SMS, it will throw an incorrect SecurityException.
1055 if (persistMessage) {
1056 resolveSubscriptionForOperation(new SubscriptionResolverResult() {
1057 @Override
1058 public void onSuccess(int subId) {
1059 try {
1060 ISms iSms = getISmsServiceOrThrow();
Philip P. Moltmann83083302020-03-19 17:27:39 -07001061 iSms.sendMultipartTextForSubscriber(subId, packageName, attributionTag,
Brad Ebinger360415a2019-04-30 11:37:27 -07001062 destinationAddress, scAddress, parts, sentIntents,
Tom Taylor66afc8f2019-11-20 15:39:12 -08001063 deliveryIntents, persistMessage, messageId);
Brad Ebinger360415a2019-04-30 11:37:27 -07001064 } catch (RemoteException e) {
1065 Log.e(TAG, "sendMultipartTextMessageInternal: Couldn't send SMS - "
Tom Taylor66afc8f2019-11-20 15:39:12 -08001066 + e.getMessage() + " id: "
1067 + messageId);
Tom Taylorf43f4f02019-10-08 16:34:04 -07001068 notifySmsError(sentIntents, RESULT_REMOTE_EXCEPTION);
Brad Ebinger360415a2019-04-30 11:37:27 -07001069 }
1070 }
1071
1072 @Override
1073 public void onFailure() {
Tom Taylorf43f4f02019-10-08 16:34:04 -07001074 notifySmsError(sentIntents, RESULT_NO_DEFAULT_SMS_APP);
Brad Ebinger360415a2019-04-30 11:37:27 -07001075 }
1076 });
1077 } else {
1078 // Called by apps that are not user facing, don't show disambiguation dialog.
1079 try {
1080 ISms iSms = getISmsServiceOrThrow();
1081 if (iSms != null) {
1082 iSms.sendMultipartTextForSubscriber(getSubscriptionId(), packageName,
Philip P. Moltmann83083302020-03-19 17:27:39 -07001083 attributionTag, destinationAddress, scAddress, parts, sentIntents,
1084 deliveryIntents, persistMessage, messageId);
Brad Ebinger360415a2019-04-30 11:37:27 -07001085 }
1086 } catch (RemoteException e) {
1087 Log.e(TAG, "sendMultipartTextMessageInternal: Couldn't send SMS - "
Tom Taylor66afc8f2019-11-20 15:39:12 -08001088 + e.getMessage() + " id: " + messageId);
Tom Taylorf43f4f02019-10-08 16:34:04 -07001089 notifySmsError(sentIntents, RESULT_REMOTE_EXCEPTION);
Brad Ebinger360415a2019-04-30 11:37:27 -07001090 }
Dan Willemsen4980bf42017-02-14 14:17:12 -08001091 }
1092 } else {
1093 PendingIntent sentIntent = null;
1094 PendingIntent deliveryIntent = null;
1095 if (sentIntents != null && sentIntents.size() > 0) {
1096 sentIntent = sentIntents.get(0);
1097 }
1098 if (deliveryIntents != null && deliveryIntents.size() > 0) {
1099 deliveryIntent = deliveryIntents.get(0);
1100 }
Youming Ye35c84882019-04-30 10:35:08 -07001101 sendTextMessageInternal(destinationAddress, scAddress, parts.get(0),
Philip P. Moltmann83083302020-03-19 17:27:39 -07001102 sentIntent, deliveryIntent, true, packageName, attributionTag, messageId);
Dan Willemsen4980bf42017-02-14 14:17:12 -08001103 }
1104 }
1105
1106 /**
1107 * Send a multi-part text based SMS without writing it into the SMS Provider.
1108 *
Brad Ebinger360415a2019-04-30 11:37:27 -07001109 * <p>
1110 * If this method is called on a device with multiple active subscriptions, this
1111 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
1112 * default subscription is defined, the subscription ID associated with this message will be
1113 * INVALID, which will result in the SMS sent on the subscription associated with slot
1114 * 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the SMS is sent using the
1115 * correct subscription.
1116 * </p>
1117 *
Abhijith Shastry448c12c2017-02-14 13:02:59 -08001118 * <p>Requires Permission:
1119 * {@link android.Manifest.permission#MODIFY_PHONE_STATE} or the calling app has carrier
1120 * privileges.
1121 * </p>
Dan Willemsen4980bf42017-02-14 14:17:12 -08001122 *
1123 * @see #sendMultipartTextMessage(String, String, ArrayList, ArrayList, ArrayList)
1124 * @hide
1125 **/
Abhijith Shastry448c12c2017-02-14 13:02:59 -08001126 @SystemApi
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -06001127 @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
Dan Willemsen4980bf42017-02-14 14:17:12 -08001128 public void sendMultipartTextMessageWithoutPersisting(
Abhijith Shastry448c12c2017-02-14 13:02:59 -08001129 String destinationAddress, String scAddress, List<String> parts,
1130 List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents) {
1131 sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents,
Philip P. Moltmann7ebd5592020-07-16 14:37:30 -07001132 deliveryIntents, false /* persistMessage*/, getOpPackageName(),
1133 getAttributionTag(), 0L /* messageId */);
Dan Willemsen4980bf42017-02-14 14:17:12 -08001134 }
1135
1136 /**
Mengjun Lengb379ce92017-03-13 17:08:26 +08001137 * Send a multi-part text based SMS with messaging options. The callee should have already
1138 * divided the message into correctly sized parts by calling
1139 * <code>divideMessage</code>.
1140 *
1141 * <p class="note"><strong>Note:</strong> Using this method requires that your app has the
1142 * {@link android.Manifest.permission#SEND_SMS} permission.</p>
1143 *
1144 * <p class="note"><strong>Note:</strong> Beginning with Android 4.4 (API level 19), if
1145 * <em>and only if</em> an app is not selected as the default SMS app, the system automatically
1146 * writes messages sent using this method to the SMS Provider (the default SMS app is always
1147 * responsible for writing its sent messages to the SMS Provider). For information about
1148 * how to behave as the default SMS app, see {@link android.provider.Telephony}.</p>
1149 *
Brad Ebinger360415a2019-04-30 11:37:27 -07001150 * <p class="note"><strong>Note:</strong> If {@link #getDefault()} is used to instantiate this
1151 * manager on a multi-SIM device, this operation may fail sending the SMS message because no
1152 * suitable default subscription could be found. In this case, if {@code sentIntent} is
1153 * non-null, then the {@link PendingIntent} will be sent with an error code
1154 * {@code RESULT_ERROR_GENERIC_FAILURE} and an extra string {@code "noDefault"} containing the
1155 * boolean value {@code true}. See {@link #getDefault()} for more information on the conditions
1156 * where this operation may fail.
1157 * </p>
1158
Mengjun Lengb379ce92017-03-13 17:08:26 +08001159 * @param destinationAddress the address to send the message to
1160 * @param scAddress is the service center address or null to use
1161 * the current default SMSC
1162 * @param parts an <code>ArrayList</code> of strings that, in order,
1163 * comprise the original message
1164 * @param sentIntents if not null, an <code>ArrayList</code> of
1165 * <code>PendingIntent</code>s (one for each message part) that is
1166 * broadcast when the corresponding message part has been sent.
1167 * The result code will be <code>Activity.RESULT_OK</code> for success,
1168 * or one of these errors:<br>
Tom Taylorf43f4f02019-10-08 16:34:04 -07001169 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
1170 * <code>RESULT_ERROR_RADIO_OFF</code><br>
1171 * <code>RESULT_ERROR_NULL_PDU</code><br>
1172 * <code>RESULT_ERROR_NO_SERVICE</code><br>
1173 * <code>RESULT_ERROR_NO_SERVICE</code><br>
1174 * <code>RESULT_ERROR_LIMIT_EXCEEDED</code><br>
1175 * <code>RESULT_ERROR_FDN_CHECK_FAILURE</code><br>
1176 * <code>RESULT_ERROR_SHORT_CODE_NOT_ALLOWED</code><br>
1177 * <code>RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED</code><br>
1178 * <code>RESULT_RADIO_NOT_AVAILABLE</code><br>
1179 * <code>RESULT_NETWORK_REJECT</code><br>
1180 * <code>RESULT_INVALID_ARGUMENTS</code><br>
1181 * <code>RESULT_INVALID_STATE</code><br>
1182 * <code>RESULT_NO_MEMORY</code><br>
1183 * <code>RESULT_INVALID_SMS_FORMAT</code><br>
1184 * <code>RESULT_SYSTEM_ERROR</code><br>
1185 * <code>RESULT_MODEM_ERROR</code><br>
1186 * <code>RESULT_NETWORK_ERROR</code><br>
1187 * <code>RESULT_ENCODING_ERROR</code><br>
1188 * <code>RESULT_INVALID_SMSC_ADDRESS</code><br>
1189 * <code>RESULT_OPERATION_NOT_ALLOWED</code><br>
1190 * <code>RESULT_INTERNAL_ERROR</code><br>
1191 * <code>RESULT_NO_RESOURCES</code><br>
1192 * <code>RESULT_CANCELLED</code><br>
1193 * <code>RESULT_REQUEST_NOT_SUPPORTED</code><br>
1194 * <code>RESULT_NO_BLUETOOTH_SERVICE</code><br>
1195 * <code>RESULT_INVALID_BLUETOOTH_ADDRESS</code><br>
1196 * <code>RESULT_BLUETOOTH_DISCONNECTED</code><br>
1197 * <code>RESULT_UNEXPECTED_EVENT_STOP_SENDING</code><br>
1198 * <code>RESULT_SMS_BLOCKED_DURING_EMERGENCY</code><br>
1199 * <code>RESULT_SMS_SEND_RETRY_FAILED</code><br>
1200 * <code>RESULT_REMOTE_EXCEPTION</code><br>
1201 * <code>RESULT_NO_DEFAULT_SMS_APP</code><br>
1202 * <code>RESULT_RIL_RADIO_NOT_AVAILABLE</code><br>
1203 * <code>RESULT_RIL_SMS_SEND_FAIL_RETRY</code><br>
1204 * <code>RESULT_RIL_NETWORK_REJECT</code><br>
1205 * <code>RESULT_RIL_INVALID_STATE</code><br>
1206 * <code>RESULT_RIL_INVALID_ARGUMENTS</code><br>
1207 * <code>RESULT_RIL_NO_MEMORY</code><br>
1208 * <code>RESULT_RIL_REQUEST_RATE_LIMITED</code><br>
1209 * <code>RESULT_RIL_INVALID_SMS_FORMAT</code><br>
1210 * <code>RESULT_RIL_SYSTEM_ERR</code><br>
1211 * <code>RESULT_RIL_ENCODING_ERR</code><br>
1212 * <code>RESULT_RIL_INVALID_SMSC_ADDRESS</code><br>
1213 * <code>RESULT_RIL_MODEM_ERR</code><br>
1214 * <code>RESULT_RIL_NETWORK_ERR</code><br>
1215 * <code>RESULT_RIL_INTERNAL_ERR</code><br>
1216 * <code>RESULT_RIL_REQUEST_NOT_SUPPORTED</code><br>
1217 * <code>RESULT_RIL_INVALID_MODEM_STATE</code><br>
1218 * <code>RESULT_RIL_NETWORK_NOT_READY</code><br>
1219 * <code>RESULT_RIL_OPERATION_NOT_ALLOWED</code><br>
1220 * <code>RESULT_RIL_NO_RESOURCES</code><br>
1221 * <code>RESULT_RIL_CANCELLED</code><br>
1222 * <code>RESULT_RIL_SIM_ABSENT</code><br>
1223 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> or any of the RESULT_RIL errors,
1224 * the sentIntent may include the extra "errorCode" containing a radio technology specific
1225 * value, generally only useful for troubleshooting.<br>
Mengjun Lengb379ce92017-03-13 17:08:26 +08001226 * The per-application based SMS control checks sentIntent. If sentIntent
1227 * is NULL the caller will be checked against all unknown applications,
1228 * which cause smaller number of SMS to be sent in checking period.
1229 * @param deliveryIntents if not null, an <code>ArrayList</code> of
1230 * <code>PendingIntent</code>s (one for each message part) that is
1231 * broadcast when the corresponding message part has been delivered
1232 * to the recipient. The raw pdu of the status report is in the
1233 * extended data ("pdu").
1234 * @param priority Priority level of the message
1235 * Refer specification See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1
1236 * ---------------------------------
1237 * PRIORITY | Level of Priority
1238 * ---------------------------------
1239 * '00' | Normal
1240 * '01' | Interactive
1241 * '10' | Urgent
1242 * '11' | Emergency
1243 * ----------------------------------
1244 * Any Other values included Negative considered as Invalid Priority Indicator of the message.
1245 * @param expectMore is a boolean to indicate the sending messages through same link or not.
1246 * @param validityPeriod Validity Period of the message in mins.
1247 * Refer specification 3GPP TS 23.040 V6.8.1 section 9.2.3.12.1.
1248 * Validity Period(Minimum) -> 5 mins
1249 * Validity Period(Maximum) -> 635040 mins(i.e.63 weeks).
1250 * Any Other values included Negative considered as Invalid Validity Period of the message.
1251 *
1252 * @throws IllegalArgumentException if destinationAddress or data are empty
1253 * {@hide}
1254 */
Mathew Inwooda8382062018-08-16 17:01:12 +01001255 @UnsupportedAppUsage
Mengjun Lengb379ce92017-03-13 17:08:26 +08001256 public void sendMultipartTextMessage(
1257 String destinationAddress, String scAddress, ArrayList<String> parts,
1258 ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents,
1259 int priority, boolean expectMore, int validityPeriod) {
1260 sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents,
Mengjun Leng353bed12018-07-30 15:28:31 +08001261 deliveryIntents, true /* persistMessage*/, priority, expectMore,
1262 validityPeriod);
Mengjun Lengb379ce92017-03-13 17:08:26 +08001263 }
1264
1265 private void sendMultipartTextMessageInternal(
1266 String destinationAddress, String scAddress, List<String> parts,
1267 List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents,
1268 boolean persistMessage, int priority, boolean expectMore, int validityPeriod) {
1269 if (TextUtils.isEmpty(destinationAddress)) {
1270 throw new IllegalArgumentException("Invalid destinationAddress");
1271 }
1272 if (parts == null || parts.size() < 1) {
1273 throw new IllegalArgumentException("Invalid message body");
1274 }
1275
1276 if (priority < 0x00 || priority > 0x03) {
Taesu Lee1ec60182020-05-18 20:08:58 +09001277 Log.e(TAG, "Invalid Priority " + priority);
Brad Ebinger360415a2019-04-30 11:37:27 -07001278 priority = SMS_MESSAGE_PRIORITY_NOT_SPECIFIED;
Mengjun Lengb379ce92017-03-13 17:08:26 +08001279 }
1280
1281 if (validityPeriod < 0x05 || validityPeriod > 0x09b0a0) {
Taesu Lee1ec60182020-05-18 20:08:58 +09001282 Log.e(TAG, "Invalid Validity Period " + validityPeriod);
Brad Ebinger360415a2019-04-30 11:37:27 -07001283 validityPeriod = SMS_MESSAGE_PERIOD_NOT_SPECIFIED;
Mengjun Lengb379ce92017-03-13 17:08:26 +08001284 }
1285
1286 if (parts.size() > 1) {
Brad Ebinger360415a2019-04-30 11:37:27 -07001287 final int finalPriority = priority;
1288 final int finalValidity = validityPeriod;
Brad Ebinger360415a2019-04-30 11:37:27 -07001289 if (persistMessage) {
1290 resolveSubscriptionForOperation(new SubscriptionResolverResult() {
1291 @Override
1292 public void onSuccess(int subId) {
1293 try {
1294 ISms iSms = getISmsServiceOrThrow();
1295 if (iSms != null) {
1296 iSms.sendMultipartTextForSubscriberWithOptions(subId,
Philip P. Moltmann83083302020-03-19 17:27:39 -07001297 null, null, destinationAddress,
Brad Ebinger360415a2019-04-30 11:37:27 -07001298 scAddress, parts, sentIntents, deliveryIntents,
1299 persistMessage, finalPriority, expectMore, finalValidity);
1300 }
1301 } catch (RemoteException e) {
1302 Log.e(TAG, "sendMultipartTextMessageInternal: Couldn't send SMS - "
1303 + e.getMessage());
Tom Taylorf43f4f02019-10-08 16:34:04 -07001304 notifySmsError(sentIntents, RESULT_REMOTE_EXCEPTION);
Brad Ebinger360415a2019-04-30 11:37:27 -07001305 }
1306 }
1307
1308 @Override
1309 public void onFailure() {
Tom Taylorf43f4f02019-10-08 16:34:04 -07001310 notifySmsError(sentIntents, RESULT_NO_DEFAULT_SMS_APP);
Brad Ebinger360415a2019-04-30 11:37:27 -07001311 }
1312 });
1313 } else {
1314 // Sent by apps that are not user visible, so don't show SIM disambiguation dialog.
1315 try {
1316 ISms iSms = getISmsServiceOrThrow();
1317 if (iSms != null) {
1318 iSms.sendMultipartTextForSubscriberWithOptions(getSubscriptionId(),
Philip P. Moltmann83083302020-03-19 17:27:39 -07001319 null, null, destinationAddress,
Brad Ebinger360415a2019-04-30 11:37:27 -07001320 scAddress, parts, sentIntents, deliveryIntents,
1321 persistMessage, finalPriority, expectMore, finalValidity);
1322 }
1323 } catch (RemoteException e) {
1324 Log.e(TAG, "sendMultipartTextMessageInternal (no persist): Couldn't send SMS - "
1325 + e.getMessage());
Tom Taylorf43f4f02019-10-08 16:34:04 -07001326 notifySmsError(sentIntents, RESULT_REMOTE_EXCEPTION);
Mengjun Lengb379ce92017-03-13 17:08:26 +08001327 }
Mengjun Lengb379ce92017-03-13 17:08:26 +08001328 }
1329 } else {
1330 PendingIntent sentIntent = null;
1331 PendingIntent deliveryIntent = null;
1332 if (sentIntents != null && sentIntents.size() > 0) {
1333 sentIntent = sentIntents.get(0);
1334 }
1335 if (deliveryIntents != null && deliveryIntents.size() > 0) {
1336 deliveryIntent = deliveryIntents.get(0);
1337 }
1338 sendTextMessageInternal(destinationAddress, scAddress, parts.get(0),
1339 sentIntent, deliveryIntent, persistMessage, priority, expectMore,
1340 validityPeriod);
1341 }
1342 }
1343
1344 /**
Dan Willemsen4980bf42017-02-14 14:17:12 -08001345 * Send a data based SMS to a specific application port.
1346 *
1347 * <p class="note"><strong>Note:</strong> Using this method requires that your app has the
1348 * {@link android.Manifest.permission#SEND_SMS} permission.</p>
1349 *
Brad Ebinger360415a2019-04-30 11:37:27 -07001350 * <p class="note"><strong>Note:</strong> If {@link #getDefault()} is used to instantiate this
1351 * manager on a multi-SIM device, this operation may fail sending the SMS message because no
1352 * suitable default subscription could be found. In this case, if {@code sentIntent} is
1353 * non-null, then the {@link PendingIntent} will be sent with an error code
1354 * {@code RESULT_ERROR_GENERIC_FAILURE} and an extra string {@code "noDefault"} containing the
1355 * boolean value {@code true}. See {@link #getDefault()} for more information on the conditions
1356 * where this operation may fail.
1357 * </p>
1358 *
Dan Willemsen4980bf42017-02-14 14:17:12 -08001359 * @param destinationAddress the address to send the message to
1360 * @param scAddress is the service center address or null to use
1361 * the current default SMSC
1362 * @param destinationPort the port to deliver the message to
1363 * @param data the body of the message to send
1364 * @param sentIntent if not NULL this <code>PendingIntent</code> is
1365 * broadcast when the message is successfully sent, or failed.
1366 * The result code will be <code>Activity.RESULT_OK</code> for success,
1367 * or one of these errors:<br>
1368 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
1369 * <code>RESULT_ERROR_RADIO_OFF</code><br>
1370 * <code>RESULT_ERROR_NULL_PDU</code><br>
Tom Taylorf43f4f02019-10-08 16:34:04 -07001371 * <code>RESULT_ERROR_NO_SERVICE</code><br>
1372 * <code>RESULT_ERROR_NO_SERVICE</code><br>
1373 * <code>RESULT_ERROR_LIMIT_EXCEEDED</code><br>
1374 * <code>RESULT_ERROR_FDN_CHECK_FAILURE</code><br>
1375 * <code>RESULT_ERROR_SHORT_CODE_NOT_ALLOWED</code><br>
1376 * <code>RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED</code><br>
1377 * <code>RESULT_RADIO_NOT_AVAILABLE</code><br>
1378 * <code>RESULT_NETWORK_REJECT</code><br>
1379 * <code>RESULT_INVALID_ARGUMENTS</code><br>
1380 * <code>RESULT_INVALID_STATE</code><br>
1381 * <code>RESULT_NO_MEMORY</code><br>
1382 * <code>RESULT_INVALID_SMS_FORMAT</code><br>
1383 * <code>RESULT_SYSTEM_ERROR</code><br>
1384 * <code>RESULT_MODEM_ERROR</code><br>
1385 * <code>RESULT_NETWORK_ERROR</code><br>
1386 * <code>RESULT_ENCODING_ERROR</code><br>
1387 * <code>RESULT_INVALID_SMSC_ADDRESS</code><br>
1388 * <code>RESULT_OPERATION_NOT_ALLOWED</code><br>
1389 * <code>RESULT_INTERNAL_ERROR</code><br>
1390 * <code>RESULT_NO_RESOURCES</code><br>
1391 * <code>RESULT_CANCELLED</code><br>
1392 * <code>RESULT_REQUEST_NOT_SUPPORTED</code><br>
1393 * <code>RESULT_NO_BLUETOOTH_SERVICE</code><br>
1394 * <code>RESULT_INVALID_BLUETOOTH_ADDRESS</code><br>
1395 * <code>RESULT_BLUETOOTH_DISCONNECTED</code><br>
1396 * <code>RESULT_UNEXPECTED_EVENT_STOP_SENDING</code><br>
1397 * <code>RESULT_SMS_BLOCKED_DURING_EMERGENCY</code><br>
1398 * <code>RESULT_SMS_SEND_RETRY_FAILED</code><br>
1399 * <code>RESULT_REMOTE_EXCEPTION</code><br>
1400 * <code>RESULT_NO_DEFAULT_SMS_APP</code><br>
1401 * <code>RESULT_RIL_RADIO_NOT_AVAILABLE</code><br>
1402 * <code>RESULT_RIL_SMS_SEND_FAIL_RETRY</code><br>
1403 * <code>RESULT_RIL_NETWORK_REJECT</code><br>
1404 * <code>RESULT_RIL_INVALID_STATE</code><br>
1405 * <code>RESULT_RIL_INVALID_ARGUMENTS</code><br>
1406 * <code>RESULT_RIL_NO_MEMORY</code><br>
1407 * <code>RESULT_RIL_REQUEST_RATE_LIMITED</code><br>
1408 * <code>RESULT_RIL_INVALID_SMS_FORMAT</code><br>
1409 * <code>RESULT_RIL_SYSTEM_ERR</code><br>
1410 * <code>RESULT_RIL_ENCODING_ERR</code><br>
1411 * <code>RESULT_RIL_INVALID_SMSC_ADDRESS</code><br>
1412 * <code>RESULT_RIL_MODEM_ERR</code><br>
1413 * <code>RESULT_RIL_NETWORK_ERR</code><br>
1414 * <code>RESULT_RIL_INTERNAL_ERR</code><br>
1415 * <code>RESULT_RIL_REQUEST_NOT_SUPPORTED</code><br>
1416 * <code>RESULT_RIL_INVALID_MODEM_STATE</code><br>
1417 * <code>RESULT_RIL_NETWORK_NOT_READY</code><br>
1418 * <code>RESULT_RIL_OPERATION_NOT_ALLOWED</code><br>
1419 * <code>RESULT_RIL_NO_RESOURCES</code><br>
1420 * <code>RESULT_RIL_CANCELLED</code><br>
1421 * <code>RESULT_RIL_SIM_ABSENT</code><br>
1422 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> or any of the RESULT_RIL errors,
1423 * the sentIntent may include the extra "errorCode" containing a radio technology specific
1424 * value, generally only useful for troubleshooting.<br>
Dan Willemsen4980bf42017-02-14 14:17:12 -08001425 * The per-application based SMS control checks sentIntent. If sentIntent
1426 * is NULL the caller will be checked against all unknown applications,
1427 * which cause smaller number of SMS to be sent in checking period.
1428 * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
1429 * broadcast when the message is delivered to the recipient. The
1430 * raw pdu of the status report is in the extended data ("pdu").
1431 *
1432 * @throws IllegalArgumentException if destinationAddress or data are empty
1433 */
1434 public void sendDataMessage(
1435 String destinationAddress, String scAddress, short destinationPort,
1436 byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
1437 if (TextUtils.isEmpty(destinationAddress)) {
1438 throw new IllegalArgumentException("Invalid destinationAddress");
1439 }
1440
1441 if (data == null || data.length == 0) {
1442 throw new IllegalArgumentException("Invalid message data");
1443 }
1444
Brad Ebinger360415a2019-04-30 11:37:27 -07001445 resolveSubscriptionForOperation(new SubscriptionResolverResult() {
1446 @Override
1447 public void onSuccess(int subId) {
1448 try {
1449 ISms iSms = getISmsServiceOrThrow();
Philip P. Moltmann83083302020-03-19 17:27:39 -07001450 iSms.sendDataForSubscriber(subId, null, null, destinationAddress, scAddress,
1451 destinationPort & 0xFFFF, data, sentIntent, deliveryIntent);
Brad Ebinger360415a2019-04-30 11:37:27 -07001452 } catch (RemoteException e) {
1453 Log.e(TAG, "sendDataMessage: Couldn't send SMS - Exception: " + e.getMessage());
Tom Taylorf43f4f02019-10-08 16:34:04 -07001454 notifySmsError(sentIntent, RESULT_REMOTE_EXCEPTION);
Brad Ebinger360415a2019-04-30 11:37:27 -07001455 }
1456 }
1457 @Override
1458 public void onFailure() {
Tom Taylorf43f4f02019-10-08 16:34:04 -07001459 notifySmsError(sentIntent, RESULT_NO_DEFAULT_SMS_APP);
Brad Ebinger360415a2019-04-30 11:37:27 -07001460 }
1461 });
Dan Willemsen4980bf42017-02-14 14:17:12 -08001462 }
1463
1464 /**
Dan Willemsen4980bf42017-02-14 14:17:12 -08001465 * Get the SmsManager associated with the default subscription id. The instance will always be
Brad Ebingerfa82ddd2019-04-30 11:34:14 -07001466 * associated with the default subscription id, even if the default subscription id changes.
Dan Willemsen4980bf42017-02-14 14:17:12 -08001467 *
Brad Ebinger360415a2019-04-30 11:37:27 -07001468 * <p class="note"><strong>Note:</strong> For devices that support multiple active subscriptions
1469 * at a time, SmsManager will track the subscription set by the user as the default SMS
1470 * subscription. If the user has not set a default, {@link SmsManager} may
1471 * start an activity to kick off a subscription disambiguation dialog. Most operations will not
1472 * complete until the user has chosen the subscription that will be associated with the
1473 * operation. If the user cancels the dialog without choosing a subscription, one of the
1474 * following will happen, depending on the target SDK version of the application. For
1475 * compatibility purposes, if the target SDK level is <= 28, telephony will still send the SMS
1476 * over the first available subscription. If the target SDK level is > 28, the operation will
1477 * fail to complete.
1478 * </p>
1479 *
1480 * <p class="note"><strong>Note:</strong> If this method is used to perform an operation on a
1481 * device that has multiple active subscriptions, the user has not set a default SMS
1482 * subscription, and the operation is being performed while the application is not in the
1483 * foreground, the SMS disambiguation dialog will not be shown. The result of the operation will
1484 * conclude as if the user cancelled the disambiguation dialog and the operation will finish as
1485 * outlined above, depending on the target SDK version of the calling application. It is safer
1486 * to use {@link #getSmsManagerForSubscriptionId(int)} if the application will perform the
1487 * operation while in the background because this can cause unpredictable results, such as the
1488 * operation being sent over the wrong subscription or failing completely, depending on the
1489 * user's default SMS subscription setting.
1490 * </p>
1491 *
1492 * @return the {@link SmsManager} associated with the default subscription id.
1493 *
1494 * @see SubscriptionManager#getDefaultSmsSubscriptionId()
Philip P. Moltmann7ebd5592020-07-16 14:37:30 -07001495 *
1496 * @deprecated Use {@link Context#getSystemService Context.getSystemService(SmsManager.class)}
1497 * instead
Dan Willemsen4980bf42017-02-14 14:17:12 -08001498 */
Philip P. Moltmann7ebd5592020-07-16 14:37:30 -07001499 @Deprecated
Dan Willemsen4980bf42017-02-14 14:17:12 -08001500 public static SmsManager getDefault() {
Philip P. Moltmann7ebd5592020-07-16 14:37:30 -07001501 return DEFAULT_INSTANCE;
1502 }
1503
1504 /**
1505 * Get the instance of the SmsManager associated with a particular context and subscription ID.
1506 *
1507 * @param context The context the manager belongs to
1508 * @param subId an SMS subscription ID, typically accessed using {@link SubscriptionManager}
1509 *
1510 * @return the instance of the SmsManager associated with subscription
1511 *
1512 * @hide
1513 */
1514 public static @NonNull SmsManager getSmsManagerForContextAndSubscriptionId(
1515 @Nullable Context context, int subId) {
1516 synchronized(sLockObject) {
1517 Pair<Context, Integer> key = new Pair<>(context, subId);
1518
1519 SmsManager smsManager = sSubInstances.get(key);
1520 if (smsManager == null) {
1521 smsManager = new SmsManager(context, subId);
1522 sSubInstances.put(key, smsManager);
1523 }
1524 return smsManager;
1525 }
1526 }
1527
1528 /**
1529 * Get the instance of the SmsManager associated with a particular subscription ID.
1530 *
1531 * <p class="note"><strong>Note:</strong> Constructing an {@link SmsManager} in this manner will
1532 * never cause an SMS disambiguation dialog to appear, unlike {@link #getDefault()}.
1533 * </p>
1534 *
1535 * @param subId an SMS subscription ID, typically accessed using {@link SubscriptionManager}
1536 * @return the instance of the SmsManager associated with subscription
1537 *
1538 * @see SubscriptionManager#getActiveSubscriptionInfoList()
1539 * @see SubscriptionManager#getDefaultSmsSubscriptionId()
1540 * @deprecated Use {@link Context#getSystemService Context.getSystemService(SmsManager.class)}
1541 * .{@link #createForSubscriptionId createForSubscriptionId(subId)} instead
1542 */
1543 @Deprecated
1544 public static SmsManager getSmsManagerForSubscriptionId(int subId) {
1545 return getSmsManagerForContextAndSubscriptionId(null, subId);
Dan Willemsen4980bf42017-02-14 14:17:12 -08001546 }
1547
1548 /**
Brad Ebinger360415a2019-04-30 11:37:27 -07001549 * Get the instance of the SmsManager associated with a particular subscription ID.
Dan Willemsen4980bf42017-02-14 14:17:12 -08001550 *
Brad Ebinger360415a2019-04-30 11:37:27 -07001551 * <p class="note"><strong>Note:</strong> Constructing an {@link SmsManager} in this manner will
1552 * never cause an SMS disambiguation dialog to appear, unlike {@link #getDefault()}.
1553 * </p>
Brad Ebingerfa82ddd2019-04-30 11:34:14 -07001554 *
1555 * @param subId an SMS subscription ID, typically accessed using {@link SubscriptionManager}
1556 * @return the instance of the SmsManager associated with subscription
1557 *
1558 * @see SubscriptionManager#getActiveSubscriptionInfoList()
1559 * @see SubscriptionManager#getDefaultSmsSubscriptionId()
Dan Willemsen4980bf42017-02-14 14:17:12 -08001560 */
Philip P. Moltmann7ebd5592020-07-16 14:37:30 -07001561 public @NonNull SmsManager createForSubscriptionId(int subId) {
1562 return getSmsManagerForContextAndSubscriptionId(mContext, subId);
Dan Willemsen4980bf42017-02-14 14:17:12 -08001563 }
1564
Philip P. Moltmann7ebd5592020-07-16 14:37:30 -07001565 private SmsManager(@Nullable Context context, int subId) {
1566 mContext = context;
Dan Willemsen4980bf42017-02-14 14:17:12 -08001567 mSubId = subId;
1568 }
1569
1570 /**
1571 * Get the associated subscription id. If the instance was returned by {@link #getDefault()},
1572 * then this method may return different values at different points in time (if the user
Brad Ebingerfa82ddd2019-04-30 11:34:14 -07001573 * changes the default subscription id).
Dan Willemsen4980bf42017-02-14 14:17:12 -08001574 *
Brad Ebinger360415a2019-04-30 11:37:27 -07001575 * <p class="note"><strong>Note:</strong> This method used to display a disambiguation dialog to
1576 * the user asking them to choose a default subscription to send SMS messages over if they
1577 * haven't chosen yet. Starting in API level 29, we allow the user to not have a default set as
1578 * a valid option for the default SMS subscription on multi-SIM devices. We no longer show the
1579 * disambiguation dialog and return {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} if the
1580 * device has multiple active subscriptions and no default is set.
1581 * </p>
Dan Willemsen4980bf42017-02-14 14:17:12 -08001582 *
Brad Ebingerfa82ddd2019-04-30 11:34:14 -07001583 * @return associated subscription ID or {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} if
Brad Ebinger360415a2019-04-30 11:37:27 -07001584 * the default subscription id cannot be determined or the device has multiple active
Brad Ebingerfa82ddd2019-04-30 11:34:14 -07001585 * subscriptions and and no default is set ("ask every time") by the user.
Dan Willemsen4980bf42017-02-14 14:17:12 -08001586 */
1587 public int getSubscriptionId() {
Brad Ebinger360415a2019-04-30 11:37:27 -07001588 try {
1589 return (mSubId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)
1590 ? getISmsServiceOrThrow().getPreferredSmsSubscription() : mSubId;
1591 } catch (RemoteException e) {
1592 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1593 }
1594 }
1595
1596 /**
1597 * Resolves the subscription id to use for the associated operation if
1598 * {@link #getSubscriptionId()} returns {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID}.
1599 *
1600 * If app targets API level 28 or below and they are either sending the SMS from the background
1601 * or the device has more than one active subscription available and no default is set, we will
1602 * use the first logical slot to send the SMS and possibly fail later in the SMS sending
1603 * process.
1604 *
1605 * Regardless of the API level, if the app is the foreground app, then we will show the SMS
1606 * disambiguation dialog. If the app is in the background and tries to perform an operation, we
1607 * will not show the disambiguation dialog.
1608 *
1609 * See {@link #getDefault()} for a detailed explanation of how this method operates.
1610 *
1611 * @param resolverResult The callback that will be called when the subscription is resolved or
1612 * fails to be resolved.
1613 */
1614 private void resolveSubscriptionForOperation(SubscriptionResolverResult resolverResult) {
1615 int subId = getSubscriptionId();
1616 boolean isSmsSimPickActivityNeeded = false;
Brad Ebinger360415a2019-04-30 11:37:27 -07001617 try {
1618 ISms iSms = getISmsService();
1619 if (iSms != null) {
1620 // Determines if the SMS SIM pick activity should be shown. This is only shown if:
1621 // 1) The device has multiple active subscriptions and an SMS default subscription
1622 // hasn't been set, and
1623 // 2) SmsManager is being called from the foreground app.
1624 // Android does not allow background activity starts, so we need to block this.
1625 // if Q+, do not perform requested operation if these two operations are not set. If
1626 // <P, perform these operations on phone 0 (for compatibility purposes, since we
1627 // used to not wait for the result of this activity).
1628 isSmsSimPickActivityNeeded = iSms.isSmsSimPickActivityNeeded(subId);
1629 }
1630 } catch (RemoteException ex) {
1631 Log.e(TAG, "resolveSubscriptionForOperation", ex);
1632 }
1633 if (!isSmsSimPickActivityNeeded) {
1634 sendResolverResult(resolverResult, subId, false /*pickActivityShown*/);
1635 return;
1636 }
1637 // We need to ask the user pick an appropriate subid for the operation.
Shuo Qian24fded62020-01-14 14:48:27 -08001638 Log.d(TAG, "resolveSubscriptionForOperation isSmsSimPickActivityNeeded is true for calling"
1639 + " package. ");
Brad Ebinger360415a2019-04-30 11:37:27 -07001640 try {
1641 // Create the SMS pick activity and call back once the activity is complete. Can't do
1642 // it here because we do not have access to the activity context that is performing this
1643 // operation.
1644 // Requires that the calling process has the SEND_SMS permission.
Philip P. Moltmann83083302020-03-19 17:27:39 -07001645 getITelephony().enqueueSmsPickResult(null, null,
Brad Ebinger360415a2019-04-30 11:37:27 -07001646 new IIntegerConsumer.Stub() {
1647 @Override
1648 public void accept(int subId) {
1649 // Runs on binder thread attached to this app's process.
1650 sendResolverResult(resolverResult, subId, true /*pickActivityShown*/);
1651 }
1652 });
1653 } catch (RemoteException ex) {
1654 Log.e(TAG, "Unable to launch activity", ex);
1655 // pickActivityShown is true here because we want to call sendResolverResult and always
1656 // have this operation fail. This is because we received a RemoteException here, which
1657 // means that telephony is not available and the next operation to Telephony will fail
1658 // as well anyways, so we might as well shortcut fail here first.
1659 sendResolverResult(resolverResult, subId, true /*pickActivityShown*/);
1660 }
1661 }
1662
Shuo Qian24fded62020-01-14 14:48:27 -08001663 /**
1664 * To check the SDK version for SmsManager.sendResolverResult method.
1665 */
1666 @ChangeId
1667 @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.P)
1668 private static final long GET_TARGET_SDK_VERSION_CODE_CHANGE = 145147528L;
1669
Brad Ebinger360415a2019-04-30 11:37:27 -07001670 private void sendResolverResult(SubscriptionResolverResult resolverResult, int subId,
1671 boolean pickActivityShown) {
1672 if (SubscriptionManager.isValidSubscriptionId(subId)) {
1673 resolverResult.onSuccess(subId);
1674 return;
1675 }
1676
Shuo Qian24fded62020-01-14 14:48:27 -08001677 if (!Compatibility.isChangeEnabled(GET_TARGET_SDK_VERSION_CODE_CHANGE)
1678 && !pickActivityShown) {
Brad Ebinger360415a2019-04-30 11:37:27 -07001679 // Do not fail, return a success with an INVALID subid for apps targeting P or below
1680 // that tried to perform an operation and the SMS disambiguation dialog was never shown,
1681 // as these applications may not have been written to handle the failure case properly.
1682 // This will resolve to performing the operation on phone 0 in telephony.
1683 resolverResult.onSuccess(subId);
1684 } else {
1685 // Fail if the app targets Q or above or it targets P and below and the disambiguation
1686 // dialog was shown and the user clicked out of it.
1687 resolverResult.onFailure();
1688 }
1689 }
1690
Brad Ebinger360415a2019-04-30 11:37:27 -07001691 private static ITelephony getITelephony() {
1692 ITelephony binder = ITelephony.Stub.asInterface(
Peter Wangd9eebca2019-12-30 16:14:01 -08001693 TelephonyFrameworkInitializer
1694 .getTelephonyServiceManager()
1695 .getTelephonyServiceRegisterer()
1696 .get());
Brad Ebinger360415a2019-04-30 11:37:27 -07001697 if (binder == null) {
1698 throw new RuntimeException("Could not find Telephony Service.");
1699 }
1700 return binder;
1701 }
1702
Tom Taylorf43f4f02019-10-08 16:34:04 -07001703 private static void notifySmsError(PendingIntent pendingIntent, int error) {
Brad Ebinger360415a2019-04-30 11:37:27 -07001704 if (pendingIntent != null) {
Brad Ebinger360415a2019-04-30 11:37:27 -07001705 try {
Tom Taylorf43f4f02019-10-08 16:34:04 -07001706 pendingIntent.send(error);
Brad Ebinger360415a2019-04-30 11:37:27 -07001707 } catch (PendingIntent.CanceledException e) {
1708 // Don't worry about it, we do not need to notify the caller if this is the case.
1709 }
1710 }
1711 }
1712
Tom Taylorf43f4f02019-10-08 16:34:04 -07001713 private static void notifySmsError(List<PendingIntent> pendingIntents, int error) {
Brad Ebinger360415a2019-04-30 11:37:27 -07001714 if (pendingIntents != null) {
1715 for (PendingIntent pendingIntent : pendingIntents) {
Tom Taylorf43f4f02019-10-08 16:34:04 -07001716 notifySmsError(pendingIntent, error);
Brad Ebinger360415a2019-04-30 11:37:27 -07001717 }
1718 }
Brad Ebinger099d9852019-03-28 15:46:50 -07001719 }
1720
1721 /**
Dan Willemsen4980bf42017-02-14 14:17:12 -08001722 * Returns the ISms service, or throws an UnsupportedOperationException if
1723 * the service does not exist.
1724 */
1725 private static ISms getISmsServiceOrThrow() {
Tim Murrayc73a2812019-10-22 11:39:05 -07001726 ISms iSms = TelephonyManager.getSmsService();
Hayden Gomes7a3d8a42019-03-21 18:30:41 -07001727 if (iSms == null) {
Dan Willemsen4980bf42017-02-14 14:17:12 -08001728 throw new UnsupportedOperationException("Sms is not supported");
1729 }
Hayden Gomes7a3d8a42019-03-21 18:30:41 -07001730 return iSms;
Dan Willemsen4980bf42017-02-14 14:17:12 -08001731 }
1732
1733 private static ISms getISmsService() {
Tim Murrayc73a2812019-10-22 11:39:05 -07001734 return TelephonyManager.getSmsService();
Dan Willemsen4980bf42017-02-14 14:17:12 -08001735 }
1736
1737 /**
Taesu Lee27e67c22019-12-11 10:10:49 +09001738 * Copies a raw SMS PDU to the ICC.
Dan Willemsen4980bf42017-02-14 14:17:12 -08001739 * ICC (Integrated Circuit Card) is the card of the device.
1740 * For example, this can be the SIM or USIM for GSM.
1741 *
Brad Ebinger360415a2019-04-30 11:37:27 -07001742 * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier
1743 * applications or the Telephony framework and will never trigger an SMS disambiguation
1744 * dialog. If this method is called on a device that has multiple active subscriptions, this
1745 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
1746 * default subscription is defined, the subscription ID associated with this message will be
1747 * INVALID, which will result in the operation being completed on the subscription associated
1748 * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the
1749 * operation is performed on the correct subscription.
1750 * </p>
1751 *
Taesu Lee27e67c22019-12-11 10:10:49 +09001752 * @param smsc the SMSC for this messag or null for the default SMSC.
1753 * @param pdu the raw PDU to store.
1754 * @param status message status. One of these status:
1755 * <code>STATUS_ON_ICC_READ</code>
1756 * <code>STATUS_ON_ICC_UNREAD</code>
1757 * <code>STATUS_ON_ICC_SENT</code>
1758 * <code>STATUS_ON_ICC_UNSENT</code>
1759 * @return true for success. Otherwise false.
Dan Willemsen4980bf42017-02-14 14:17:12 -08001760 *
Taesu Lee27e67c22019-12-11 10:10:49 +09001761 * @throws IllegalArgumentException if pdu is null.
1762 * @hide
Dan Willemsen4980bf42017-02-14 14:17:12 -08001763 */
Taesu Lee27e67c22019-12-11 10:10:49 +09001764 @RequiresPermission(Manifest.permission.ACCESS_MESSAGES_ON_ICC)
1765 public boolean copyMessageToIcc(
1766 @Nullable byte[] smsc, @NonNull byte[] pdu, @StatusOnIcc int status) {
Dan Willemsen4980bf42017-02-14 14:17:12 -08001767 boolean success = false;
1768
Taesu Lee27e67c22019-12-11 10:10:49 +09001769 if (pdu == null) {
1770 throw new IllegalArgumentException("pdu is null");
Dan Willemsen4980bf42017-02-14 14:17:12 -08001771 }
1772 try {
Hayden Gomes7a3d8a42019-03-21 18:30:41 -07001773 ISms iSms = getISmsService();
1774 if (iSms != null) {
1775 success = iSms.copyMessageToIccEfForSubscriber(getSubscriptionId(),
Shuo Qian24fded62020-01-14 14:48:27 -08001776 null,
Dan Willemsen4980bf42017-02-14 14:17:12 -08001777 status, pdu, smsc);
1778 }
1779 } catch (RemoteException ex) {
1780 // ignore it
1781 }
1782
1783 return success;
1784 }
1785
1786 /**
Taesu Leeade283c2019-12-03 17:29:20 +09001787 * Deletes the specified message from the ICC.
Dan Willemsen4980bf42017-02-14 14:17:12 -08001788 * ICC (Integrated Circuit Card) is the card of the device.
1789 * For example, this can be the SIM or USIM for GSM.
1790 *
Brad Ebinger360415a2019-04-30 11:37:27 -07001791 * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier
1792 * applications or the Telephony framework and will never trigger an SMS disambiguation
1793 * dialog. If this method is called on a device that has multiple active subscriptions, this
1794 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
1795 * default subscription is defined, the subscription ID associated with this message will be
1796 * INVALID, which will result in the operation being completed on the subscription associated
1797 * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the
1798 * operation is performed on the correct subscription.
1799 * </p>
1800 *
Taesu Lee24115e82020-07-17 12:18:11 +09001801 * @param messageIndex the message index of the message in the ICC (1-based index).
changbettyd5093c712019-11-21 11:07:14 +08001802 * @return true for success, false if the operation fails. Failure can be due to IPC failure,
1803 * RIL/modem error which results in SMS failed to be deleted on SIM
Dan Willemsen4980bf42017-02-14 14:17:12 -08001804 *
1805 * {@hide}
1806 */
Amit Mahajan1530a592020-10-21 12:32:59 -07001807 @UnsupportedAppUsage
changbettyd5093c712019-11-21 11:07:14 +08001808 @RequiresPermission(Manifest.permission.ACCESS_MESSAGES_ON_ICC)
1809 public boolean deleteMessageFromIcc(int messageIndex) {
Dan Willemsen4980bf42017-02-14 14:17:12 -08001810 boolean success = false;
Dan Willemsen4980bf42017-02-14 14:17:12 -08001811
1812 try {
Hayden Gomes7a3d8a42019-03-21 18:30:41 -07001813 ISms iSms = getISmsService();
1814 if (iSms != null) {
1815 success = iSms.updateMessageOnIccEfForSubscriber(getSubscriptionId(),
Shuo Qian24fded62020-01-14 14:48:27 -08001816 null,
Taesu Lee265dc5b2019-07-15 12:27:08 +09001817 messageIndex, STATUS_ON_ICC_FREE, null /* pdu */);
Dan Willemsen4980bf42017-02-14 14:17:12 -08001818 }
1819 } catch (RemoteException ex) {
1820 // ignore it
1821 }
1822
1823 return success;
1824 }
1825
1826 /**
1827 * Update the specified message on the ICC.
1828 * ICC (Integrated Circuit Card) is the card of the device.
1829 * For example, this can be the SIM or USIM for GSM.
1830 *
Brad Ebinger360415a2019-04-30 11:37:27 -07001831 * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier
1832 * applications or the Telephony framework and will never trigger an SMS disambiguation
1833 * dialog. If this method is called on a device that has multiple active subscriptions, this
1834 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
1835 * default subscription is defined, the subscription ID associated with this message will be
1836 * INVALID, which will result in the operation being completed on the subscription associated
1837 * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the
1838 * operation is performed on the correct subscription.
1839 * </p>
1840 *
Dan Willemsen4980bf42017-02-14 14:17:12 -08001841 * @param messageIndex record index of message to update
1842 * @param newStatus new message status (STATUS_ON_ICC_READ,
1843 * STATUS_ON_ICC_UNREAD, STATUS_ON_ICC_SENT,
1844 * STATUS_ON_ICC_UNSENT, STATUS_ON_ICC_FREE)
1845 * @param pdu the raw PDU to store
1846 * @return true for success
1847 *
1848 * {@hide}
1849 */
Mathew Inwooda8382062018-08-16 17:01:12 +01001850 @UnsupportedAppUsage
changbettyd5093c712019-11-21 11:07:14 +08001851 @RequiresPermission(Manifest.permission.ACCESS_MESSAGES_ON_ICC)
Dan Willemsen4980bf42017-02-14 14:17:12 -08001852 public boolean updateMessageOnIcc(int messageIndex, int newStatus, byte[] pdu) {
1853 boolean success = false;
1854
1855 try {
Hayden Gomes7a3d8a42019-03-21 18:30:41 -07001856 ISms iSms = getISmsService();
1857 if (iSms != null) {
1858 success = iSms.updateMessageOnIccEfForSubscriber(getSubscriptionId(),
Shuo Qian24fded62020-01-14 14:48:27 -08001859 null,
Dan Willemsen4980bf42017-02-14 14:17:12 -08001860 messageIndex, newStatus, pdu);
1861 }
1862 } catch (RemoteException ex) {
1863 // ignore it
1864 }
1865
1866 return success;
1867 }
1868
1869 /**
Taesu Leeade283c2019-12-03 17:29:20 +09001870 * Retrieves all messages currently stored on the ICC.
Dan Willemsen4980bf42017-02-14 14:17:12 -08001871 * ICC (Integrated Circuit Card) is the card of the device.
1872 * For example, this can be the SIM or USIM for GSM.
1873 *
Brad Ebinger360415a2019-04-30 11:37:27 -07001874 * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier
1875 * applications or the Telephony framework and will never trigger an SMS disambiguation
1876 * dialog. If this method is called on a device that has multiple active subscriptions, this
1877 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
1878 * default subscription is defined, the subscription ID associated with this message will be
1879 * INVALID, which will result in the operation being completed on the subscription associated
1880 * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the
1881 * operation is performed on the correct subscription.
1882 * </p>
1883 *
Taesu Lee24115e82020-07-17 12:18:11 +09001884 * @return <code>List</code> of <code>SmsMessage</code> objects for valid records only.
changbettyd5093c712019-11-21 11:07:14 +08001885 *
1886 * {@hide}
1887 */
changbettyd5093c712019-11-21 11:07:14 +08001888 @RequiresPermission(Manifest.permission.ACCESS_MESSAGES_ON_ICC)
1889 public @NonNull List<SmsMessage> getMessagesFromIcc() {
1890 return getAllMessagesFromIcc();
1891 }
1892
1893 /**
Dan Willemsen4980bf42017-02-14 14:17:12 -08001894 * @return <code>ArrayList</code> of <code>SmsMessage</code> objects
1895 *
changbettyd5093c712019-11-21 11:07:14 +08001896 * This is similar to {@link #getMessagesFromIcc} except that it will return ArrayList.
1897 * Suggested to use {@link #getMessagesFromIcc} instead.
1898 *
Dan Willemsen4980bf42017-02-14 14:17:12 -08001899 * {@hide}
1900 */
Mathew Inwooda8382062018-08-16 17:01:12 +01001901 @UnsupportedAppUsage
Dan Willemsen4980bf42017-02-14 14:17:12 -08001902 public ArrayList<SmsMessage> getAllMessagesFromIcc() {
1903 List<SmsRawData> records = null;
1904
1905 try {
Hayden Gomes7a3d8a42019-03-21 18:30:41 -07001906 ISms iSms = getISmsService();
1907 if (iSms != null) {
1908 records = iSms.getAllMessagesFromIccEfForSubscriber(
Dan Willemsen4980bf42017-02-14 14:17:12 -08001909 getSubscriptionId(),
Shuo Qian24fded62020-01-14 14:48:27 -08001910 null);
Dan Willemsen4980bf42017-02-14 14:17:12 -08001911 }
1912 } catch (RemoteException ex) {
1913 // ignore it
1914 }
1915
1916 return createMessageListFromRawRecords(records);
1917 }
1918
1919 /**
1920 * Enable reception of cell broadcast (SMS-CB) messages with the given
Jordan Liu657ef5a2019-08-16 14:07:03 -07001921 * message identifier range and RAN type. The RAN type specifies if this message ID
1922 * belongs to 3GPP (GSM) or 3GPP2(CDMA). Note that if two different clients enable
Dan Willemsen4980bf42017-02-14 14:17:12 -08001923 * the same message identifier, they must both disable it for the device to stop
1924 * receiving those messages. All received messages will be broadcast in an
1925 * intent with the action "android.provider.Telephony.SMS_CB_RECEIVED".
1926 * Note: This call is blocking, callers may want to avoid calling it from
1927 * the main thread of an application.
1928 *
Brad Ebinger360415a2019-04-30 11:37:27 -07001929 * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier
1930 * applications or the Telephony framework and will never trigger an SMS disambiguation
1931 * dialog. If this method is called on a device that has multiple active subscriptions, this
1932 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
1933 * default subscription is defined, the subscription ID associated with this message will be
Jordan Liu657ef5a2019-08-16 14:07:03 -07001934 * {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID}, which will result in the operation
1935 * being completed on the subscription associated with logical slot 0. Use
1936 * {@link #getSmsManagerForSubscriptionId(int)} to ensure the operation is performed on the
1937 * correct subscription.
Brad Ebinger360415a2019-04-30 11:37:27 -07001938 * </p>
1939 *
Jordan Liu657ef5a2019-08-16 14:07:03 -07001940 * <p>Requires {@link android.Manifest.permission#RECEIVE_EMERGENCY_BROADCAST}</p>
1941 *
Dan Willemsen4980bf42017-02-14 14:17:12 -08001942 * @param startMessageId first message identifier as specified in TS 23.041 (3GPP)
1943 * or C.R1001-G (3GPP2)
1944 * @param endMessageId last message identifier as specified in TS 23.041 (3GPP)
1945 * or C.R1001-G (3GPP2)
Jordan Liu657ef5a2019-08-16 14:07:03 -07001946 * @param ranType the message format as defined in {@link SmsCbMessage}
1947 * @return true if successful, false if the modem reports a failure (e.g. the given range or
1948 * RAN type is invalid).
Dan Willemsen4980bf42017-02-14 14:17:12 -08001949 * @see #disableCellBroadcastRange(int, int, int)
1950 *
1951 * @throws IllegalArgumentException if endMessageId < startMessageId
1952 * {@hide}
1953 */
Jordan Liu657ef5a2019-08-16 14:07:03 -07001954 @SystemApi
1955 public boolean enableCellBroadcastRange(int startMessageId, int endMessageId,
1956 @android.telephony.SmsCbMessage.MessageFormat int ranType) {
Dan Willemsen4980bf42017-02-14 14:17:12 -08001957 boolean success = false;
Dan Willemsen4980bf42017-02-14 14:17:12 -08001958 if (endMessageId < startMessageId) {
1959 throw new IllegalArgumentException("endMessageId < startMessageId");
1960 }
1961 try {
Hayden Gomes7a3d8a42019-03-21 18:30:41 -07001962 ISms iSms = getISmsService();
1963 if (iSms != null) {
Brad Ebingerfa82ddd2019-04-30 11:34:14 -07001964 // If getSubscriptionId() returns INVALID or an inactive subscription, we will use
1965 // the default phone internally.
Nazanindf808782020-08-11 15:42:54 -07001966 int subId = getSubscriptionId();
1967 success = iSms.enableCellBroadcastRangeForSubscriber(subId,
Dan Willemsen4980bf42017-02-14 14:17:12 -08001968 startMessageId, endMessageId, ranType);
Nazanindf808782020-08-11 15:42:54 -07001969 Rlog.d(TAG, "enableCellBroadcastRange: " + (success ? "succeeded" : "failed")
1970 + " at calling enableCellBroadcastRangeForSubscriber. subId = " + subId);
Dan Willemsen4980bf42017-02-14 14:17:12 -08001971 }
1972 } catch (RemoteException ex) {
Nazanindf808782020-08-11 15:42:54 -07001973 Rlog.d(TAG, "enableCellBroadcastRange: " + ex.getStackTrace());
Dan Willemsen4980bf42017-02-14 14:17:12 -08001974 // ignore it
1975 }
1976
1977 return success;
1978 }
1979
1980 /**
1981 * Disable reception of cell broadcast (SMS-CB) messages with the given
1982 * message identifier range and RAN type. The RAN type specify this message
1983 * ID range belong to 3GPP (GSM) or 3GPP2(CDMA). Note that if two different
1984 * clients enable the same message identifier, they must both disable it for
1985 * the device to stop receiving those messages.
1986 * Note: This call is blocking, callers may want to avoid calling it from
1987 * the main thread of an application.
1988 *
Brad Ebinger360415a2019-04-30 11:37:27 -07001989 * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier
1990 * applications or the Telephony framework and will never trigger an SMS disambiguation
1991 * dialog. If this method is called on a device that has multiple active subscriptions, this
1992 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
1993 * default subscription is defined, the subscription ID associated with this message will be
1994 * INVALID, which will result in the operation being completed on the subscription associated
1995 * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the
1996 * operation is performed on the correct subscription.
1997 * </p>
1998 *
Jordan Liu657ef5a2019-08-16 14:07:03 -07001999 * <p>Requires {@link android.Manifest.permission#RECEIVE_EMERGENCY_BROADCAST}</p>
2000 *
Dan Willemsen4980bf42017-02-14 14:17:12 -08002001 * @param startMessageId first message identifier as specified in TS 23.041 (3GPP)
2002 * or C.R1001-G (3GPP2)
2003 * @param endMessageId last message identifier as specified in TS 23.041 (3GPP)
2004 * or C.R1001-G (3GPP2)
Jordan Liu657ef5a2019-08-16 14:07:03 -07002005 * @param ranType the message format as defined in {@link SmsCbMessage}
2006 * @return true if successful, false if the modem reports a failure (e.g. the given range or
2007 * RAN type is invalid).
Dan Willemsen4980bf42017-02-14 14:17:12 -08002008 *
2009 * @see #enableCellBroadcastRange(int, int, int)
2010 *
2011 * @throws IllegalArgumentException if endMessageId < startMessageId
2012 * {@hide}
2013 */
Jordan Liu657ef5a2019-08-16 14:07:03 -07002014 @SystemApi
2015 public boolean disableCellBroadcastRange(int startMessageId, int endMessageId,
2016 @android.telephony.SmsCbMessage.MessageFormat int ranType) {
Dan Willemsen4980bf42017-02-14 14:17:12 -08002017 boolean success = false;
2018
2019 if (endMessageId < startMessageId) {
2020 throw new IllegalArgumentException("endMessageId < startMessageId");
2021 }
2022 try {
Hayden Gomes7a3d8a42019-03-21 18:30:41 -07002023 ISms iSms = getISmsService();
2024 if (iSms != null) {
Brad Ebingerfa82ddd2019-04-30 11:34:14 -07002025 // If getSubscriptionId() returns INVALID or an inactive subscription, we will use
2026 // the default phone internally.
Nazanindf808782020-08-11 15:42:54 -07002027 int subId = getSubscriptionId();
2028 success = iSms.disableCellBroadcastRangeForSubscriber(subId,
Dan Willemsen4980bf42017-02-14 14:17:12 -08002029 startMessageId, endMessageId, ranType);
Nazanindf808782020-08-11 15:42:54 -07002030 Rlog.d(TAG, "disableCellBroadcastRange: " + (success ? "succeeded" : "failed")
2031 + " at calling disableCellBroadcastRangeForSubscriber. subId = " + subId);
Dan Willemsen4980bf42017-02-14 14:17:12 -08002032 }
2033 } catch (RemoteException ex) {
Nazanindf808782020-08-11 15:42:54 -07002034 Rlog.d(TAG, "disableCellBroadcastRange: " + ex.getStackTrace());
Dan Willemsen4980bf42017-02-14 14:17:12 -08002035 // ignore it
2036 }
2037
2038 return success;
2039 }
2040
2041 /**
Taesu Leeade283c2019-12-03 17:29:20 +09002042 * Creates a list of <code>SmsMessage</code>s from a list of SmsRawData records.
Dan Willemsen4980bf42017-02-14 14:17:12 -08002043 *
Brad Ebinger360415a2019-04-30 11:37:27 -07002044 * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier
2045 * applications or the Telephony framework and will never trigger an SMS disambiguation
2046 * dialog. If this method is called on a device that has multiple active subscriptions, this
2047 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
2048 * default subscription is defined, the subscription ID associated with this message will be
2049 * INVALID, which will result in the operation being completed on the subscription associated
2050 * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the
2051 * operation is performed on the correct subscription.
2052 * </p>
2053 *
Taesu Leeade283c2019-12-03 17:29:20 +09002054 * @param records SMS EF records.
Dan Willemsen4980bf42017-02-14 14:17:12 -08002055 * @return <code>ArrayList</code> of <code>SmsMessage</code> objects.
2056 */
Mengjun Lengb379ce92017-03-13 17:08:26 +08002057 private ArrayList<SmsMessage> createMessageListFromRawRecords(List<SmsRawData> records) {
Dan Willemsen4980bf42017-02-14 14:17:12 -08002058 ArrayList<SmsMessage> messages = new ArrayList<SmsMessage>();
2059 if (records != null) {
2060 int count = records.size();
2061 for (int i = 0; i < count; i++) {
2062 SmsRawData data = records.get(i);
2063 // List contains all records, including "free" records (null)
2064 if (data != null) {
Taesu Leeade283c2019-12-03 17:29:20 +09002065 SmsMessage sms = SmsMessage.createFromEfRecord(i + 1, data.getBytes(),
Mengjun Lengb379ce92017-03-13 17:08:26 +08002066 getSubscriptionId());
Dan Willemsen4980bf42017-02-14 14:17:12 -08002067 if (sms != null) {
2068 messages.add(sms);
2069 }
2070 }
2071 }
2072 }
2073 return messages;
2074 }
2075
2076 /**
2077 * SMS over IMS is supported if IMS is registered and SMS is supported
2078 * on IMS.
2079 *
Brad Ebinger360415a2019-04-30 11:37:27 -07002080 * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier
2081 * applications or the Telephony framework and will never trigger an SMS disambiguation
2082 * dialog. If this method is called on a device that has multiple active subscriptions, this
2083 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
2084 * default subscription is defined, the subscription ID associated with this message will be
2085 * INVALID, which will result in the operation being completed on the subscription associated
2086 * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the
2087 * operation is performed on the correct subscription.
2088 * </p>
2089 *
Dan Willemsen4980bf42017-02-14 14:17:12 -08002090 * @return true if SMS over IMS is supported, false otherwise
2091 *
2092 * @see #getImsSmsFormat()
2093 *
2094 * @hide
2095 */
2096 public boolean isImsSmsSupported() {
2097 boolean boSupported = false;
2098 try {
Hayden Gomes7a3d8a42019-03-21 18:30:41 -07002099 ISms iSms = getISmsService();
2100 if (iSms != null) {
2101 boSupported = iSms.isImsSmsSupportedForSubscriber(getSubscriptionId());
Dan Willemsen4980bf42017-02-14 14:17:12 -08002102 }
2103 } catch (RemoteException ex) {
2104 // ignore it
2105 }
2106 return boSupported;
2107 }
2108
2109 /**
Brad Ebinger360415a2019-04-30 11:37:27 -07002110 * Gets SMS format supported on IMS. SMS over IMS format is either 3GPP or 3GPP2.
2111 *
2112 * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier
2113 * applications or the Telephony framework and will never trigger an SMS disambiguation
2114 * dialog. If this method is called on a device that has multiple active subscriptions, this
2115 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
2116 * default subscription is defined, the subscription ID associated with this message will be
2117 * INVALID, which will result in the operation being completed on the subscription associated
2118 * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the
2119 * operation is performed on the correct subscription.
2120 * </p>
Dan Willemsen4980bf42017-02-14 14:17:12 -08002121 *
2122 * @return SmsMessage.FORMAT_3GPP,
2123 * SmsMessage.FORMAT_3GPP2
2124 * or SmsMessage.FORMAT_UNKNOWN
2125 *
2126 * @see #isImsSmsSupported()
2127 *
2128 * @hide
2129 */
2130 public String getImsSmsFormat() {
2131 String format = com.android.internal.telephony.SmsConstants.FORMAT_UNKNOWN;
2132 try {
Hayden Gomes7a3d8a42019-03-21 18:30:41 -07002133 ISms iSms = getISmsService();
2134 if (iSms != null) {
2135 format = iSms.getImsSmsFormatForSubscriber(getSubscriptionId());
Dan Willemsen4980bf42017-02-14 14:17:12 -08002136 }
2137 } catch (RemoteException ex) {
2138 // ignore it
2139 }
2140 return format;
2141 }
2142
2143 /**
Amit Mahajan1c0a7a12019-05-17 10:48:00 -07002144 * Get default sms subscription id.
Dan Willemsen4980bf42017-02-14 14:17:12 -08002145 *
Amit Mahajan1c0a7a12019-05-17 10:48:00 -07002146 * <p class="note"><strong>Note:</strong>This returns a value different from
2147 * {@link SubscriptionManager#getDefaultSmsSubscriptionId} if the user has not chosen a default.
2148 * In this case it returns the active subscription id if there's only one active subscription
2149 * available.
2150 *
2151 * @return the user-defined default SMS subscription id, or the active subscription id if
2152 * there's only one active subscription available, otherwise
2153 * {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID}.
Dan Willemsen4980bf42017-02-14 14:17:12 -08002154 */
2155 public static int getDefaultSmsSubscriptionId() {
Dan Willemsen4980bf42017-02-14 14:17:12 -08002156 try {
Amit Mahajan900aad92019-06-07 10:40:09 -07002157 return getISmsService().getPreferredSmsSubscription();
Amit Mahajan1c0a7a12019-05-17 10:48:00 -07002158 } catch (RemoteException e) {
2159 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
Amit Mahajan900aad92019-06-07 10:40:09 -07002160 } catch (NullPointerException e) {
2161 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
Dan Willemsen4980bf42017-02-14 14:17:12 -08002162 }
2163 }
2164
2165 /**
2166 * Get SMS prompt property, enabled or not
2167 *
2168 * @return true if enabled, false otherwise
2169 * @hide
2170 */
Mathew Inwooda8382062018-08-16 17:01:12 +01002171 @UnsupportedAppUsage
Dan Willemsen4980bf42017-02-14 14:17:12 -08002172 public boolean isSMSPromptEnabled() {
Hayden Gomes7a3d8a42019-03-21 18:30:41 -07002173 ISms iSms = null;
Dan Willemsen4980bf42017-02-14 14:17:12 -08002174 try {
Tim Murrayc73a2812019-10-22 11:39:05 -07002175 iSms = TelephonyManager.getSmsService();
Hayden Gomes7a3d8a42019-03-21 18:30:41 -07002176 return iSms.isSMSPromptEnabled();
Dan Willemsen4980bf42017-02-14 14:17:12 -08002177 } catch (RemoteException ex) {
2178 return false;
2179 } catch (NullPointerException ex) {
2180 return false;
2181 }
2182 }
2183
Mengjun Lengdb152712019-11-21 10:38:03 +08002184 /**
Taesu Leed2ed15e2020-04-24 15:11:08 +09002185 * Gets the total capacity of SMS storage on the SIM card.
Mengjun Lengdb152712019-11-21 10:38:03 +08002186 *
Taesu Leed2ed15e2020-04-24 15:11:08 +09002187 * <p>
2188 * This is the number of 176 byte EF-SMS records which can be stored on the SIM card.
2189 * See 3GPP TS 31.102 - 4.2.25 - EF-SMS for more information.
2190 * </p>
2191 *
2192 * <p class="note"><strong>Note:</strong> This method will never trigger an SMS disambiguation
2193 * dialog. If this method is called on a device that has multiple active subscriptions, this
2194 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
2195 * default subscription is defined, the subscription ID associated with this method will be
2196 * INVALID, which will result in the operation being completed on the subscription associated
2197 * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the operation
2198 * is performed on the correct subscription.
2199 * </p>
2200 *
2201 * @return the total number of SMS records which can be stored on the SIM card.
Mengjun Lengdb152712019-11-21 10:38:03 +08002202 */
Taesu Leed2ed15e2020-04-24 15:11:08 +09002203 @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
Mengjun Lengdb152712019-11-21 10:38:03 +08002204 public int getSmsCapacityOnIcc() {
2205 int ret = 0;
2206 try {
2207 ISms iccISms = getISmsService();
2208 if (iccISms != null) {
2209 ret = iccISms.getSmsCapacityOnIccForSubscriber(getSubscriptionId());
2210 }
2211 } catch (RemoteException ex) {
Taesu Leed2ed15e2020-04-24 15:11:08 +09002212 throw new RuntimeException(ex);
Mengjun Lengdb152712019-11-21 10:38:03 +08002213 }
2214 return ret;
2215 }
2216
Taesu Lee27e67c22019-12-11 10:10:49 +09002217 /** @hide */
2218 @IntDef(prefix = { "STATUS_ON_ICC_" }, value = {
2219 STATUS_ON_ICC_FREE,
2220 STATUS_ON_ICC_READ,
2221 STATUS_ON_ICC_UNREAD,
2222 STATUS_ON_ICC_SENT,
2223 STATUS_ON_ICC_UNSENT
2224 })
2225 @Retention(RetentionPolicy.SOURCE)
2226 public @interface StatusOnIcc {}
2227
Dan Willemsen4980bf42017-02-14 14:17:12 -08002228 // see SmsMessage.getStatusOnIcc
2229
2230 /** Free space (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */
Tom Taylorf43f4f02019-10-08 16:34:04 -07002231 public static final int STATUS_ON_ICC_FREE = 0;
Dan Willemsen4980bf42017-02-14 14:17:12 -08002232
2233 /** Received and read (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */
Tom Taylorf43f4f02019-10-08 16:34:04 -07002234 public static final int STATUS_ON_ICC_READ = 1;
Dan Willemsen4980bf42017-02-14 14:17:12 -08002235
2236 /** Received and unread (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */
Tom Taylorf43f4f02019-10-08 16:34:04 -07002237 public static final int STATUS_ON_ICC_UNREAD = 3;
Dan Willemsen4980bf42017-02-14 14:17:12 -08002238
2239 /** Stored and sent (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */
Tom Taylorf43f4f02019-10-08 16:34:04 -07002240 public static final int STATUS_ON_ICC_SENT = 5;
Dan Willemsen4980bf42017-02-14 14:17:12 -08002241
2242 /** Stored and unsent (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */
Tom Taylorf43f4f02019-10-08 16:34:04 -07002243 public static final int STATUS_ON_ICC_UNSENT = 7;
Dan Willemsen4980bf42017-02-14 14:17:12 -08002244
2245 // SMS send failure result codes
2246
Brad Ebinger50c7b1b2019-09-24 18:11:02 -07002247 /** @hide */
2248 @IntDef(prefix = { "RESULT" }, value = {
2249 RESULT_ERROR_NONE,
2250 RESULT_ERROR_GENERIC_FAILURE,
2251 RESULT_ERROR_RADIO_OFF,
2252 RESULT_ERROR_NULL_PDU,
2253 RESULT_ERROR_NO_SERVICE,
2254 RESULT_ERROR_LIMIT_EXCEEDED,
2255 RESULT_ERROR_FDN_CHECK_FAILURE,
2256 RESULT_ERROR_SHORT_CODE_NOT_ALLOWED,
2257 RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED,
2258 RESULT_RADIO_NOT_AVAILABLE,
2259 RESULT_NETWORK_REJECT,
2260 RESULT_INVALID_ARGUMENTS,
2261 RESULT_INVALID_STATE,
2262 RESULT_NO_MEMORY,
2263 RESULT_INVALID_SMS_FORMAT,
2264 RESULT_SYSTEM_ERROR,
2265 RESULT_MODEM_ERROR,
2266 RESULT_NETWORK_ERROR,
2267 RESULT_INVALID_SMSC_ADDRESS,
2268 RESULT_OPERATION_NOT_ALLOWED,
2269 RESULT_INTERNAL_ERROR,
2270 RESULT_NO_RESOURCES,
2271 RESULT_CANCELLED,
Tom Taylorccc1c3e2019-10-30 10:08:50 -07002272 RESULT_REQUEST_NOT_SUPPORTED,
2273 RESULT_NO_BLUETOOTH_SERVICE,
2274 RESULT_INVALID_BLUETOOTH_ADDRESS,
2275 RESULT_BLUETOOTH_DISCONNECTED,
2276 RESULT_UNEXPECTED_EVENT_STOP_SENDING,
2277 RESULT_SMS_BLOCKED_DURING_EMERGENCY,
2278 RESULT_SMS_SEND_RETRY_FAILED,
2279 RESULT_REMOTE_EXCEPTION,
2280 RESULT_NO_DEFAULT_SMS_APP,
2281 RESULT_RIL_RADIO_NOT_AVAILABLE,
2282 RESULT_RIL_SMS_SEND_FAIL_RETRY,
2283 RESULT_RIL_NETWORK_REJECT,
2284 RESULT_RIL_INVALID_STATE,
2285 RESULT_RIL_INVALID_ARGUMENTS,
2286 RESULT_RIL_NO_MEMORY,
2287 RESULT_RIL_REQUEST_RATE_LIMITED,
2288 RESULT_RIL_INVALID_SMS_FORMAT,
2289 RESULT_RIL_SYSTEM_ERR,
2290 RESULT_RIL_ENCODING_ERR,
2291 RESULT_RIL_INVALID_SMSC_ADDRESS,
2292 RESULT_RIL_MODEM_ERR,
2293 RESULT_RIL_NETWORK_ERR,
2294 RESULT_RIL_INTERNAL_ERR,
2295 RESULT_RIL_REQUEST_NOT_SUPPORTED,
2296 RESULT_RIL_INVALID_MODEM_STATE,
2297 RESULT_RIL_NETWORK_NOT_READY,
2298 RESULT_RIL_OPERATION_NOT_ALLOWED,
2299 RESULT_RIL_NO_RESOURCES,
2300 RESULT_RIL_CANCELLED,
2301 RESULT_RIL_SIM_ABSENT
Brad Ebinger50c7b1b2019-09-24 18:11:02 -07002302 })
2303 @Retention(RetentionPolicy.SOURCE)
2304 public @interface Result {}
2305
Mohamed Abdalkader9cb476b2018-01-23 09:56:31 -08002306 /**
2307 * No error.
Mohamed Abdalkader9cb476b2018-01-23 09:56:31 -08002308 */
Tom Taylorf43f4f02019-10-08 16:34:04 -07002309 public static final int RESULT_ERROR_NONE = 0;
2310
Dan Willemsen4980bf42017-02-14 14:17:12 -08002311 /** Generic failure cause */
Tom Taylorf43f4f02019-10-08 16:34:04 -07002312 public static final int RESULT_ERROR_GENERIC_FAILURE = 1;
2313
Dan Willemsen4980bf42017-02-14 14:17:12 -08002314 /** Failed because radio was explicitly turned off */
Tom Taylorf43f4f02019-10-08 16:34:04 -07002315 public static final int RESULT_ERROR_RADIO_OFF = 2;
2316
Dan Willemsen4980bf42017-02-14 14:17:12 -08002317 /** Failed because no pdu provided */
Tom Taylorf43f4f02019-10-08 16:34:04 -07002318 public static final int RESULT_ERROR_NULL_PDU = 3;
2319
Dan Willemsen4980bf42017-02-14 14:17:12 -08002320 /** Failed because service is currently unavailable */
Tom Taylorf43f4f02019-10-08 16:34:04 -07002321 public static final int RESULT_ERROR_NO_SERVICE = 4;
2322
sqian724f6212017-08-09 15:28:41 -07002323 /** Failed because we reached the sending queue limit. */
Tom Taylorf43f4f02019-10-08 16:34:04 -07002324 public static final int RESULT_ERROR_LIMIT_EXCEEDED = 5;
2325
Mohamed Abdalkader9cb476b2018-01-23 09:56:31 -08002326 /**
2327 * Failed because FDN is enabled.
Mohamed Abdalkader9cb476b2018-01-23 09:56:31 -08002328 */
Tom Taylorf43f4f02019-10-08 16:34:04 -07002329 public static final int RESULT_ERROR_FDN_CHECK_FAILURE = 6;
2330
sqian724f6212017-08-09 15:28:41 -07002331 /** Failed because user denied the sending of this short code. */
Tom Taylorf43f4f02019-10-08 16:34:04 -07002332 public static final int RESULT_ERROR_SHORT_CODE_NOT_ALLOWED = 7;
2333
sqian724f6212017-08-09 15:28:41 -07002334 /** Failed because the user has denied this app ever send premium short codes. */
Tom Taylorf43f4f02019-10-08 16:34:04 -07002335 public static final int RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED = 8;
2336
Mohamed Abdalkader9cb476b2018-01-23 09:56:31 -08002337 /**
2338 * Failed because the radio was not available
Mohamed Abdalkader9cb476b2018-01-23 09:56:31 -08002339 */
Tom Taylorf43f4f02019-10-08 16:34:04 -07002340 public static final int RESULT_RADIO_NOT_AVAILABLE = 9;
2341
Mohamed Abdalkader9cb476b2018-01-23 09:56:31 -08002342 /**
2343 * Failed because of network rejection
Mohamed Abdalkader9cb476b2018-01-23 09:56:31 -08002344 */
Tom Taylorf43f4f02019-10-08 16:34:04 -07002345 public static final int RESULT_NETWORK_REJECT = 10;
2346
Mohamed Abdalkader9cb476b2018-01-23 09:56:31 -08002347 /**
2348 * Failed because of invalid arguments
Mohamed Abdalkader9cb476b2018-01-23 09:56:31 -08002349 */
Tom Taylorf43f4f02019-10-08 16:34:04 -07002350 public static final int RESULT_INVALID_ARGUMENTS = 11;
2351
Mohamed Abdalkader9cb476b2018-01-23 09:56:31 -08002352 /**
2353 * Failed because of an invalid state
Mohamed Abdalkader9cb476b2018-01-23 09:56:31 -08002354 */
Tom Taylorf43f4f02019-10-08 16:34:04 -07002355 public static final int RESULT_INVALID_STATE = 12;
2356
Mohamed Abdalkader9cb476b2018-01-23 09:56:31 -08002357 /**
2358 * Failed because there is no memory
Mohamed Abdalkader9cb476b2018-01-23 09:56:31 -08002359 */
Tom Taylorf43f4f02019-10-08 16:34:04 -07002360 public static final int RESULT_NO_MEMORY = 13;
2361
Mohamed Abdalkader9cb476b2018-01-23 09:56:31 -08002362 /**
2363 * Failed because the sms format is not valid
Mohamed Abdalkader9cb476b2018-01-23 09:56:31 -08002364 */
Tom Taylorf43f4f02019-10-08 16:34:04 -07002365 public static final int RESULT_INVALID_SMS_FORMAT = 14;
2366
Mohamed Abdalkader9cb476b2018-01-23 09:56:31 -08002367 /**
2368 * Failed because of a system error
Mohamed Abdalkader9cb476b2018-01-23 09:56:31 -08002369 */
Tom Taylorf43f4f02019-10-08 16:34:04 -07002370 public static final int RESULT_SYSTEM_ERROR = 15;
2371
Mohamed Abdalkader9cb476b2018-01-23 09:56:31 -08002372 /**
2373 * Failed because of a modem error
Mohamed Abdalkader9cb476b2018-01-23 09:56:31 -08002374 */
Tom Taylorf43f4f02019-10-08 16:34:04 -07002375 public static final int RESULT_MODEM_ERROR = 16;
2376
Mohamed Abdalkader9cb476b2018-01-23 09:56:31 -08002377 /**
2378 * Failed because of a network error
Mohamed Abdalkader9cb476b2018-01-23 09:56:31 -08002379 */
Tom Taylorf43f4f02019-10-08 16:34:04 -07002380 public static final int RESULT_NETWORK_ERROR = 17;
2381
Mohamed Abdalkader9cb476b2018-01-23 09:56:31 -08002382 /**
2383 * Failed because of an encoding error
Mohamed Abdalkader9cb476b2018-01-23 09:56:31 -08002384 */
Tom Taylorf43f4f02019-10-08 16:34:04 -07002385 public static final int RESULT_ENCODING_ERROR = 18;
2386
Mohamed Abdalkader9cb476b2018-01-23 09:56:31 -08002387 /**
2388 * Failed because of an invalid smsc address
Mohamed Abdalkader9cb476b2018-01-23 09:56:31 -08002389 */
Tom Taylorf43f4f02019-10-08 16:34:04 -07002390 public static final int RESULT_INVALID_SMSC_ADDRESS = 19;
2391
Mohamed Abdalkader9cb476b2018-01-23 09:56:31 -08002392 /**
2393 * Failed because the operation is not allowed
Mohamed Abdalkader9cb476b2018-01-23 09:56:31 -08002394 */
Tom Taylorf43f4f02019-10-08 16:34:04 -07002395 public static final int RESULT_OPERATION_NOT_ALLOWED = 20;
2396
Mohamed Abdalkader9cb476b2018-01-23 09:56:31 -08002397 /**
2398 * Failed because of an internal error
Mohamed Abdalkader9cb476b2018-01-23 09:56:31 -08002399 */
Tom Taylorf43f4f02019-10-08 16:34:04 -07002400 public static final int RESULT_INTERNAL_ERROR = 21;
2401
Mohamed Abdalkader9cb476b2018-01-23 09:56:31 -08002402 /**
2403 * Failed because there are no resources
Mohamed Abdalkader9cb476b2018-01-23 09:56:31 -08002404 */
Tom Taylorf43f4f02019-10-08 16:34:04 -07002405 public static final int RESULT_NO_RESOURCES = 22;
2406
Mohamed Abdalkader9cb476b2018-01-23 09:56:31 -08002407 /**
2408 * Failed because the operation was cancelled
Mohamed Abdalkader9cb476b2018-01-23 09:56:31 -08002409 */
Tom Taylorf43f4f02019-10-08 16:34:04 -07002410 public static final int RESULT_CANCELLED = 23;
2411
Mohamed Abdalkader9cb476b2018-01-23 09:56:31 -08002412 /**
2413 * Failed because the request is not supported
Mohamed Abdalkader9cb476b2018-01-23 09:56:31 -08002414 */
Tom Taylorf43f4f02019-10-08 16:34:04 -07002415 public static final int RESULT_REQUEST_NOT_SUPPORTED = 24;
2416
2417 /**
2418 * Failed sending via bluetooth because the bluetooth service is not available
2419 */
2420 public static final int RESULT_NO_BLUETOOTH_SERVICE = 25;
2421
2422 /**
2423 * Failed sending via bluetooth because the bluetooth device address is invalid
2424 */
2425 public static final int RESULT_INVALID_BLUETOOTH_ADDRESS = 26;
2426
2427 /**
2428 * Failed sending via bluetooth because bluetooth disconnected
2429 */
2430 public static final int RESULT_BLUETOOTH_DISCONNECTED = 27;
2431
2432 /**
2433 * Failed sending because the user denied or canceled the dialog displayed for a premium
2434 * shortcode sms or rate-limited sms.
2435 */
2436 public static final int RESULT_UNEXPECTED_EVENT_STOP_SENDING = 28;
2437
2438 /**
2439 * Failed sending during an emergency call
2440 */
2441 public static final int RESULT_SMS_BLOCKED_DURING_EMERGENCY = 29;
2442
2443 /**
2444 * Failed to send an sms retry
2445 */
2446 public static final int RESULT_SMS_SEND_RETRY_FAILED = 30;
2447
2448 /**
2449 * Set by BroadcastReceiver to indicate a remote exception while handling a message.
2450 */
2451 public static final int RESULT_REMOTE_EXCEPTION = 31;
2452
2453 /**
2454 * Set by BroadcastReceiver to indicate there's no default sms app.
2455 */
2456 public static final int RESULT_NO_DEFAULT_SMS_APP = 32;
2457
2458 // Radio Error results
2459
2460 /**
2461 * The radio did not start or is resetting.
2462 */
2463 public static final int RESULT_RIL_RADIO_NOT_AVAILABLE = 100;
2464
2465 /**
2466 * The radio failed to send the sms and needs to retry.
2467 */
2468 public static final int RESULT_RIL_SMS_SEND_FAIL_RETRY = 101;
2469
2470 /**
2471 * The sms request was rejected by the network.
2472 */
2473 public static final int RESULT_RIL_NETWORK_REJECT = 102;
2474
2475 /**
2476 * The radio returned an unexpected request for the current state.
2477 */
2478 public static final int RESULT_RIL_INVALID_STATE = 103;
2479
2480 /**
2481 * The radio received invalid arguments in the request.
2482 */
2483 public static final int RESULT_RIL_INVALID_ARGUMENTS = 104;
2484
2485 /**
2486 * The radio didn't have sufficient memory to process the request.
2487 */
2488 public static final int RESULT_RIL_NO_MEMORY = 105;
2489
2490 /**
2491 * The radio denied the operation due to overly-frequent requests.
2492 */
2493 public static final int RESULT_RIL_REQUEST_RATE_LIMITED = 106;
2494
2495 /**
2496 * The radio returned an error indicating invalid sms format.
2497 */
2498 public static final int RESULT_RIL_INVALID_SMS_FORMAT = 107;
2499
2500 /**
2501 * The radio encountered a platform or system error.
2502 */
2503 public static final int RESULT_RIL_SYSTEM_ERR = 108;
2504
2505 /**
2506 * The SMS message was not encoded properly.
2507 */
2508 public static final int RESULT_RIL_ENCODING_ERR = 109;
2509
2510 /**
2511 * The specified SMSC address was invalid.
2512 */
2513 public static final int RESULT_RIL_INVALID_SMSC_ADDRESS = 110;
2514
2515 /**
2516 * The vendor RIL received an unexpected or incorrect response.
2517 */
2518 public static final int RESULT_RIL_MODEM_ERR = 111;
2519
2520 /**
2521 * The radio received an error from the network.
2522 */
2523 public static final int RESULT_RIL_NETWORK_ERR = 112;
2524
2525 /**
2526 * The modem encountered an unexpected error scenario while handling the request.
2527 */
2528 public static final int RESULT_RIL_INTERNAL_ERR = 113;
2529
2530 /**
2531 * The request was not supported by the radio.
2532 */
2533 public static final int RESULT_RIL_REQUEST_NOT_SUPPORTED = 114;
2534
2535 /**
2536 * The radio cannot process the request in the current modem state.
2537 */
2538 public static final int RESULT_RIL_INVALID_MODEM_STATE = 115;
2539
2540 /**
2541 * The network is not ready to perform the request.
2542 */
2543 public static final int RESULT_RIL_NETWORK_NOT_READY = 116;
2544
2545 /**
2546 * The radio reports the request is not allowed.
2547 */
2548 public static final int RESULT_RIL_OPERATION_NOT_ALLOWED = 117;
2549
2550 /**
Tom Taylorccc1c3e2019-10-30 10:08:50 -07002551 * There are insufficient resources to process the request.
Tom Taylorf43f4f02019-10-08 16:34:04 -07002552 */
2553 public static final int RESULT_RIL_NO_RESOURCES = 118;
2554
2555 /**
2556 * The request has been cancelled.
2557 */
2558 public static final int RESULT_RIL_CANCELLED = 119;
2559
2560 /**
2561 * The radio failed to set the location where the CDMA subscription
2562 * can be retrieved because the SIM or RUIM is absent.
2563 */
2564 public static final int RESULT_RIL_SIM_ABSENT = 120;
Mohamed Abdalkader9cb476b2018-01-23 09:56:31 -08002565
Tom Taylorccc1c3e2019-10-30 10:08:50 -07002566 // SMS receiving results sent as a "result" extra in {@link Intents.SMS_REJECTED_ACTION}
2567
2568 /**
2569 * SMS receive dispatch failure.
2570 */
2571 public static final int RESULT_RECEIVE_DISPATCH_FAILURE = 500;
2572
2573 /**
2574 * SMS receive injected null PDU.
2575 */
2576 public static final int RESULT_RECEIVE_INJECTED_NULL_PDU = 501;
2577
2578 /**
2579 * SMS receive encountered runtime exception.
2580 */
2581 public static final int RESULT_RECEIVE_RUNTIME_EXCEPTION = 502;
2582
2583 /**
2584 * SMS received null message from the radio interface layer.
2585 */
2586 public static final int RESULT_RECEIVE_NULL_MESSAGE_FROM_RIL = 503;
2587
2588 /**
2589 * SMS short code received while the phone is in encrypted state.
2590 */
2591 public static final int RESULT_RECEIVE_WHILE_ENCRYPTED = 504;
2592
2593 /**
2594 * SMS receive encountered an SQL exception.
2595 */
2596 public static final int RESULT_RECEIVE_SQL_EXCEPTION = 505;
2597
2598 /**
2599 * SMS receive an exception parsing a uri.
2600 */
2601 public static final int RESULT_RECEIVE_URI_EXCEPTION = 506;
2602
2603
2604
Dan Willemsen4980bf42017-02-14 14:17:12 -08002605 /**
2606 * Send an MMS message
2607 *
Taesu Lee16bd38d2020-10-12 16:45:55 +09002608 * <p class="note"><strong>Note:</strong> If {@link #getDefault()} is used to instantiate this
2609 * manager on a multi-SIM device, this operation may fail sending the MMS message because no
2610 * suitable default subscription could be found. In this case, if {@code sentIntent} is
2611 * non-null, then the {@link PendingIntent} will be sent with an error code
2612 * {@code RESULT_NO_DEFAULT_SMS_APP}. See {@link #getDefault()} for more information on the
2613 * conditions where this operation may fail.
Brad Ebinger360415a2019-04-30 11:37:27 -07002614 * </p>
2615 *
Dan Willemsen4980bf42017-02-14 14:17:12 -08002616 * @param context application context
2617 * @param contentUri the content Uri from which the message pdu will be read
2618 * @param locationUrl the optional location url where message should be sent to
2619 * @param configOverrides the carrier-specific messaging configuration values to override for
2620 * sending the message.
2621 * @param sentIntent if not NULL this <code>PendingIntent</code> is
2622 * broadcast when the message is successfully sent, or failed
2623 * @throws IllegalArgumentException if contentUri is empty
2624 */
2625 public void sendMultimediaMessage(Context context, Uri contentUri, String locationUrl,
2626 Bundle configOverrides, PendingIntent sentIntent) {
2627 if (contentUri == null) {
2628 throw new IllegalArgumentException("Uri contentUri null");
2629 }
Sarah Chin4affb512020-01-10 16:09:11 -08002630 MmsManager m = (MmsManager) context.getSystemService(Context.MMS_SERVICE);
2631 if (m != null) {
Taesu Lee16bd38d2020-10-12 16:45:55 +09002632 resolveSubscriptionForOperation(new SubscriptionResolverResult() {
2633 @Override
2634 public void onSuccess(int subId) {
2635 m.sendMultimediaMessage(subId, contentUri, locationUrl, configOverrides,
2636 sentIntent, 0L /* messageId */);
2637 }
2638
2639 @Override
2640 public void onFailure() {
2641 notifySmsError(sentIntent, RESULT_NO_DEFAULT_SMS_APP);
2642 }
2643 });
Sarah Chin4affb512020-01-10 16:09:11 -08002644 }
Dan Willemsen4980bf42017-02-14 14:17:12 -08002645 }
2646
2647 /**
2648 * Download an MMS message from carrier by a given location URL
2649 *
Taesu Lee16bd38d2020-10-12 16:45:55 +09002650 * <p class="note"><strong>Note:</strong> If {@link #getDefault()} is used to instantiate this
2651 * manager on a multi-SIM device, this operation may fail downloading the MMS message because no
2652 * suitable default subscription could be found. In this case, if {@code downloadedIntent} is
2653 * non-null, then the {@link PendingIntent} will be sent with an error code
2654 * {@code RESULT_NO_DEFAULT_SMS_APP}. See {@link #getDefault()} for more information on the
2655 * conditions where this operation may fail.
Brad Ebinger360415a2019-04-30 11:37:27 -07002656 * </p>
2657 *
Dan Willemsen4980bf42017-02-14 14:17:12 -08002658 * @param context application context
2659 * @param locationUrl the location URL of the MMS message to be downloaded, usually obtained
2660 * from the MMS WAP push notification
2661 * @param contentUri the content uri to which the downloaded pdu will be written
2662 * @param configOverrides the carrier-specific messaging configuration values to override for
2663 * downloading the message.
2664 * @param downloadedIntent if not NULL this <code>PendingIntent</code> is
2665 * broadcast when the message is downloaded, or the download is failed
2666 * @throws IllegalArgumentException if locationUrl or contentUri is empty
2667 */
2668 public void downloadMultimediaMessage(Context context, String locationUrl, Uri contentUri,
2669 Bundle configOverrides, PendingIntent downloadedIntent) {
2670 if (TextUtils.isEmpty(locationUrl)) {
2671 throw new IllegalArgumentException("Empty MMS location URL");
2672 }
2673 if (contentUri == null) {
2674 throw new IllegalArgumentException("Uri contentUri null");
2675 }
Sarah Chin4affb512020-01-10 16:09:11 -08002676 MmsManager m = (MmsManager) context.getSystemService(Context.MMS_SERVICE);
2677 if (m != null) {
Taesu Lee16bd38d2020-10-12 16:45:55 +09002678 resolveSubscriptionForOperation(new SubscriptionResolverResult() {
2679 @Override
2680 public void onSuccess(int subId) {
2681 m.downloadMultimediaMessage(subId, locationUrl, contentUri, configOverrides,
2682 downloadedIntent, 0L /* messageId */);
2683 }
2684
2685 @Override
2686 public void onFailure() {
2687 notifySmsError(downloadedIntent, RESULT_NO_DEFAULT_SMS_APP);
2688 }
2689 });
Sarah Chin4affb512020-01-10 16:09:11 -08002690 }
Dan Willemsen4980bf42017-02-14 14:17:12 -08002691 }
2692
2693 // MMS send/download failure result codes
2694 public static final int MMS_ERROR_UNSPECIFIED = 1;
2695 public static final int MMS_ERROR_INVALID_APN = 2;
2696 public static final int MMS_ERROR_UNABLE_CONNECT_MMS = 3;
2697 public static final int MMS_ERROR_HTTP_FAILURE = 4;
2698 public static final int MMS_ERROR_IO_ERROR = 5;
2699 public static final int MMS_ERROR_RETRY = 6;
2700 public static final int MMS_ERROR_CONFIGURATION_ERROR = 7;
2701 public static final int MMS_ERROR_NO_DATA_NETWORK = 8;
2702
2703 /** Intent extra name for MMS sending result data in byte array type */
2704 public static final String EXTRA_MMS_DATA = "android.telephony.extra.MMS_DATA";
2705 /** Intent extra name for HTTP status code for MMS HTTP failure in integer type */
2706 public static final String EXTRA_MMS_HTTP_STATUS = "android.telephony.extra.MMS_HTTP_STATUS";
2707
Dan Willemsen4980bf42017-02-14 14:17:12 -08002708 /**
Taesu Lee44fb1902019-11-15 16:16:08 +09002709 * Get carrier-dependent MMS configuration values.
Dan Willemsen4980bf42017-02-14 14:17:12 -08002710 *
Brad Ebinger360415a2019-04-30 11:37:27 -07002711 * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier
Taesu Lee44fb1902019-11-15 16:16:08 +09002712 * applications or the Telephony framework and will never trigger an SMS disambiguation dialog.
2713 * If this method is called on a device that has multiple active subscriptions, this {@link
2714 * SmsManager} instance has been created with {@link #getDefault()}, and no user-defined default
2715 * subscription is defined, the subscription ID associated with this message will be INVALID,
2716 * which will result in the operation being completed on the subscription associated with
2717 * logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the operation is
2718 * performed on the correct subscription.
Brad Ebinger360415a2019-04-30 11:37:27 -07002719 * </p>
2720 *
Taesu Lee44fb1902019-11-15 16:16:08 +09002721 * @return the bundle key/values pairs that contains MMS configuration values
Sarah Chin4affb512020-01-10 16:09:11 -08002722 * or an empty Bundle if they cannot be found.
Dan Willemsen4980bf42017-02-14 14:17:12 -08002723 */
Sarah Chin4affb512020-01-10 16:09:11 -08002724 @NonNull public Bundle getCarrierConfigValues() {
Taesu Lee44fb1902019-11-15 16:16:08 +09002725 try {
2726 ISms iSms = getISmsService();
2727 if (iSms != null) {
2728 return iSms.getCarrierConfigValuesForSubscriber(getSubscriptionId());
2729 }
2730 } catch (RemoteException ex) {
2731 // ignore it
2732 }
Sarah Chin4affb512020-01-10 16:09:11 -08002733 return new Bundle();
Dan Willemsen4980bf42017-02-14 14:17:12 -08002734 }
2735
2736 /**
Brad Ebinger360415a2019-04-30 11:37:27 -07002737 * Create a single use app specific incoming SMS request for the calling package.
Dan Willemsen4980bf42017-02-14 14:17:12 -08002738 *
2739 * This method returns a token that if included in a subsequent incoming SMS message will cause
2740 * {@code intent} to be sent with the SMS data.
2741 *
2742 * The token is only good for one use, after an SMS has been received containing the token all
2743 * subsequent SMS messages with the token will be routed as normal.
2744 *
2745 * An app can only have one request at a time, if the app already has a request pending it will
2746 * be replaced with a new request.
2747 *
Brad Ebinger360415a2019-04-30 11:37:27 -07002748 * <p class="note"><strong>Note:</strong> This method will never trigger an SMS disambiguation
2749 * dialog. If this method is called on a device that has multiple active subscriptions, this
2750 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
2751 * default subscription is defined, the subscription ID associated with this message will be
2752 * INVALID, which will result in the operation being completed on the subscription associated
2753 * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the
2754 * operation is performed on the correct subscription.
2755 * </p>
2756 *
Dan Willemsen4980bf42017-02-14 14:17:12 -08002757 * @return Token to include in an SMS message. The token will be 11 characters long.
2758 * @see android.provider.Telephony.Sms.Intents#getMessagesFromIntent
2759 */
2760 public String createAppSpecificSmsToken(PendingIntent intent) {
2761 try {
2762 ISms iccSms = getISmsServiceOrThrow();
2763 return iccSms.createAppSpecificSmsToken(getSubscriptionId(),
Shuo Qian24fded62020-01-14 14:48:27 -08002764 null, intent);
Dan Willemsen4980bf42017-02-14 14:17:12 -08002765
2766 } catch (RemoteException ex) {
2767 ex.rethrowFromSystemServer();
2768 return null;
2769 }
2770 }
2771
Chen Xud6b26732019-09-29 19:55:06 -07002772 /**
2773 * callback for providing asynchronous sms messages for financial app.
2774 */
Hongming Jin08496b02019-01-25 13:41:52 -08002775 public abstract static class FinancialSmsCallback {
2776 /**
2777 * Callback to send sms messages back to financial app asynchronously.
2778 *
2779 * @param msgs SMS messages.
2780 */
2781 public abstract void onFinancialSmsMessages(CursorWindow msgs);
2782 };
2783
2784 /**
2785 * Get SMS messages for the calling financial app.
2786 * The result will be delivered asynchronously in the passing in callback interface.
2787 *
Brad Ebinger360415a2019-04-30 11:37:27 -07002788 * <p class="note"><strong>Note:</strong> This method will never trigger an SMS disambiguation
2789 * dialog. If this method is called on a device that has multiple active subscriptions, this
2790 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
2791 * default subscription is defined, the subscription ID associated with this message will be
2792 * INVALID, which will result in the operation being completed on the subscription associated
2793 * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the
2794 * operation is performed on the correct subscription.
2795 * </p>
2796 *
Hongming Jin08496b02019-01-25 13:41:52 -08002797 * @param params the parameters to filter SMS messages returned.
2798 * @param executor the executor on which callback will be invoked.
2799 * @param callback a callback to receive CursorWindow with SMS messages.
Chen Xud6b26732019-09-29 19:55:06 -07002800 *
Hongming Jin08496b02019-01-25 13:41:52 -08002801 */
2802 @RequiresPermission(android.Manifest.permission.SMS_FINANCIAL_TRANSACTIONS)
2803 public void getSmsMessagesForFinancialApp(
2804 Bundle params,
2805 @NonNull @CallbackExecutor Executor executor,
2806 @NonNull FinancialSmsCallback callback) {
Chen Xud6b26732019-09-29 19:55:06 -07002807 // This API is not functional and thus removed to avoid future confusion.
Hongming Jin08496b02019-01-25 13:41:52 -08002808 }
2809
Dan Willemsen4980bf42017-02-14 14:17:12 -08002810 /**
Amit Mahajan24c01a22019-09-20 11:13:05 -07002811 * @see #createAppSpecificSmsTokenWithPackageInfo(String, PendingIntent).
Hongming Jin46edf152019-01-17 12:11:59 -08002812 * The prefixes is a list of prefix {@code String} separated by this delimiter.
2813 * @hide
2814 */
2815 public static final String REGEX_PREFIX_DELIMITER = ",";
2816 /**
Amit Mahajan24c01a22019-09-20 11:13:05 -07002817 * @see #createAppSpecificSmsTokenWithPackageInfo(String, PendingIntent).
Hongming Jin46edf152019-01-17 12:11:59 -08002818 * The success status to be added into the intent to be sent to the calling package.
2819 * @hide
2820 */
2821 public static final int RESULT_STATUS_SUCCESS = 0;
2822 /**
Amit Mahajan24c01a22019-09-20 11:13:05 -07002823 * @see #createAppSpecificSmsTokenWithPackageInfo(String, PendingIntent).
Hongming Jin46edf152019-01-17 12:11:59 -08002824 * The timeout status to be added into the intent to be sent to the calling package.
2825 * @hide
2826 */
2827 public static final int RESULT_STATUS_TIMEOUT = 1;
2828 /**
Amit Mahajan24c01a22019-09-20 11:13:05 -07002829 * @see #createAppSpecificSmsTokenWithPackageInfo(String, PendingIntent).
Hongming Jin46edf152019-01-17 12:11:59 -08002830 * Intent extra key of the retrieved SMS message as a {@code String}.
2831 * @hide
2832 */
2833 public static final String EXTRA_SMS_MESSAGE = "android.telephony.extra.SMS_MESSAGE";
2834 /**
Amit Mahajan24c01a22019-09-20 11:13:05 -07002835 * @see #createAppSpecificSmsTokenWithPackageInfo(String, PendingIntent).
Hongming Jin46edf152019-01-17 12:11:59 -08002836 * Intent extra key of SMS retriever status, which indicates whether the request for the
2837 * coming SMS message is SUCCESS or TIMEOUT
2838 * @hide
2839 */
2840 public static final String EXTRA_STATUS = "android.telephony.extra.STATUS";
2841 /**
Amit Mahajan24c01a22019-09-20 11:13:05 -07002842 * @see #createAppSpecificSmsTokenWithPackageInfo(String, PendingIntent).
Hongming Jin46edf152019-01-17 12:11:59 -08002843 * [Optional] Intent extra key of the retrieved Sim card subscription Id if any. {@code int}
2844 * @hide
2845 */
2846 public static final String EXTRA_SIM_SUBSCRIPTION_ID =
2847 "android.telephony.extra.SIM_SUBSCRIPTION_ID";
2848
2849 /**
2850 * Create a single use app specific incoming SMS request for the calling package.
2851 *
2852 * This method returns a token that if included in a subsequent incoming SMS message, and the
2853 * SMS message has a prefix from the given prefixes list, the provided {@code intent} will be
2854 * sent with the SMS data to the calling package.
2855 *
2856 * The token is only good for one use within a reasonable amount of time. After an SMS has been
2857 * received containing the token all subsequent SMS messages with the token will be routed as
2858 * normal.
2859 *
2860 * An app can only have one request at a time, if the app already has a request pending it will
2861 * be replaced with a new request.
2862 *
Brad Ebinger360415a2019-04-30 11:37:27 -07002863 * <p class="note"><strong>Note:</strong> This method will never trigger an SMS disambiguation
2864 * dialog. If this method is called on a device that has multiple active subscriptions, this
2865 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
2866 * default subscription is defined, the subscription ID associated with this message will be
2867 * INVALID, which will result in the operation being completed on the subscription associated
2868 * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the
2869 * operation is performed on the correct subscription.
2870 * </p>
2871 *
Hongming Jin46edf152019-01-17 12:11:59 -08002872 * @param prefixes this is a list of prefixes string separated by REGEX_PREFIX_DELIMITER. The
2873 * matching SMS message should have at least one of the prefixes in the beginning of the
2874 * message.
2875 * @param intent this intent is sent when the matching SMS message is received.
2876 * @return Token to include in an SMS message.
2877 */
2878 @Nullable
2879 public String createAppSpecificSmsTokenWithPackageInfo(
2880 @Nullable String prefixes, @NonNull PendingIntent intent) {
2881 try {
2882 ISms iccSms = getISmsServiceOrThrow();
2883 return iccSms.createAppSpecificSmsTokenWithPackageInfo(getSubscriptionId(),
Shuo Qian24fded62020-01-14 14:48:27 -08002884 null, prefixes, intent);
Hongming Jin46edf152019-01-17 12:11:59 -08002885
2886 } catch (RemoteException ex) {
2887 ex.rethrowFromSystemServer();
2888 return null;
2889 }
2890 }
2891
chen xu9c7fad92019-03-25 10:43:28 -07002892 /** @hide */
2893 @Retention(RetentionPolicy.SOURCE)
2894 @IntDef(prefix = {"SMS_CATEGORY_"},
2895 value = {
2896 SmsManager.SMS_CATEGORY_NOT_SHORT_CODE,
2897 SmsManager.SMS_CATEGORY_FREE_SHORT_CODE,
2898 SmsManager.SMS_CATEGORY_STANDARD_SHORT_CODE,
2899 SmsManager.SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE,
2900 SmsManager.SMS_CATEGORY_PREMIUM_SHORT_CODE})
2901 public @interface SmsShortCodeCategory {}
2902
2903 /**
2904 * Return value from {@link #checkSmsShortCodeDestination(String, String)} ()} for regular
2905 * phone numbers.
2906 * @hide
2907 */
2908 @TestApi
2909 public static final int SMS_CATEGORY_NOT_SHORT_CODE = 0;
2910 /**
2911 * Return value from {@link #checkSmsShortCodeDestination(String, String)} ()} for free
2912 * (no cost) short codes.
2913 * @hide
2914 */
2915 @TestApi
2916 public static final int SMS_CATEGORY_FREE_SHORT_CODE = 1;
2917 /**
2918 * Return value from {@link #checkSmsShortCodeDestination(String, String)} ()} for
2919 * standard rate (non-premium)
2920 * short codes.
2921 * @hide
2922 */
2923 @TestApi
2924 public static final int SMS_CATEGORY_STANDARD_SHORT_CODE = 2;
2925 /**
2926 * Return value from {@link #checkSmsShortCodeDestination(String, String)} ()} for possible
2927 * premium short codes.
2928 * @hide
2929 */
2930 @TestApi
2931 public static final int SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE = 3;
2932 /**
2933 * Return value from {@link #checkSmsShortCodeDestination(String, String)} ()} for
2934 * premium short codes.
2935 * @hide
2936 */
2937 @TestApi
2938 public static final int SMS_CATEGORY_PREMIUM_SHORT_CODE = 4;
2939
2940 /**
2941 * Check if the destination address is a possible premium short code.
2942 * NOTE: the caller is expected to strip non-digits from the destination number with
2943 * {@link PhoneNumberUtils#extractNetworkPortion} before calling this method.
2944 *
Brad Ebinger360415a2019-04-30 11:37:27 -07002945 * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier
2946 * applications or the Telephony framework and will never trigger an SMS disambiguation
2947 * dialog. If this method is called on a device that has multiple active subscriptions, this
2948 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
2949 * default subscription is defined, the subscription ID associated with this message will be
2950 * INVALID, which will result in the operation being completed on the subscription associated
2951 * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the
2952 * operation is performed on the correct subscription.
2953 * </p>
2954 *
chen xu9c7fad92019-03-25 10:43:28 -07002955 * @param destAddress the destination address to test for possible short code
2956 * @param countryIso the ISO country code
2957 *
2958 * @return
2959 * {@link SmsManager#SMS_CATEGORY_NOT_SHORT_CODE},
2960 * {@link SmsManager#SMS_CATEGORY_FREE_SHORT_CODE},
2961 * {@link SmsManager#SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE},
2962 * {@link SmsManager#SMS_CATEGORY_PREMIUM_SHORT_CODE}, or
2963 * {@link SmsManager#SMS_CATEGORY_STANDARD_SHORT_CODE}
2964 *
2965 * @hide
2966 */
2967 @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
2968 @TestApi
2969 public @SmsShortCodeCategory int checkSmsShortCodeDestination(
2970 String destAddress, String countryIso) {
2971 try {
2972 ISms iccISms = getISmsServiceOrThrow();
2973 if (iccISms != null) {
2974 return iccISms.checkSmsShortCodeDestination(getSubscriptionId(),
Shuo Qian24fded62020-01-14 14:48:27 -08002975 null, null, destAddress, countryIso);
chen xu9c7fad92019-03-25 10:43:28 -07002976 }
2977 } catch (RemoteException e) {
2978 Log.e(TAG, "checkSmsShortCodeDestination() RemoteException", e);
2979 }
2980 return SmsManager.SMS_CATEGORY_NOT_SHORT_CODE;
2981 }
Taesu Leef7488d02019-07-16 14:13:05 +09002982
2983 /**
2984 * Gets the SMSC address from (U)SIM.
2985 *
2986 * <p class="note"><strong>Note:</strong> Using this method requires that your app is the
2987 * default SMS application, or READ_PRIVILEGED_PHONE_STATE permission, or has the carrier
2988 * privileges.</p>
2989 *
2990 * <p class="note"><strong>Note:</strong> This method will never trigger an SMS disambiguation
2991 * dialog. If this method is called on a device that has multiple active subscriptions, this
2992 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
2993 * default subscription is defined, the subscription ID associated with this method will be
2994 * INVALID, which will result in the operation being completed on the subscription associated
2995 * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the operation
2996 * is performed on the correct subscription.
2997 * </p>
2998 *
2999 * @return the SMSC address string, null if failed.
3000 */
3001 @SuppressAutoDoc // for carrier privileges and default SMS application.
3002 @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
3003 @Nullable
3004 public String getSmscAddress() {
3005 String smsc = null;
3006
3007 try {
3008 ISms iSms = getISmsService();
3009 if (iSms != null) {
3010 smsc = iSms.getSmscAddressFromIccEfForSubscriber(
Shuo Qian24fded62020-01-14 14:48:27 -08003011 getSubscriptionId(), null);
Taesu Leef7488d02019-07-16 14:13:05 +09003012 }
3013 } catch (RemoteException ex) {
Amit Mahajand42340b2020-03-03 15:49:58 -08003014 throw new RuntimeException(ex);
Taesu Leef7488d02019-07-16 14:13:05 +09003015 }
3016 return smsc;
3017 }
3018
3019 /**
3020 * Sets the SMSC address on (U)SIM.
3021 *
3022 * <p class="note"><strong>Note:</strong> Using this method requires that your app is the
3023 * default SMS application, or has {@link android.Manifest.permission#MODIFY_PHONE_STATE}
3024 * permission, or has the carrier privileges.</p>
3025 *
3026 * <p class="note"><strong>Note:</strong> This method will never trigger an SMS disambiguation
3027 * dialog. If this method is called on a device that has multiple active subscriptions, this
3028 * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
3029 * default subscription is defined, the subscription ID associated with this method will be
3030 * INVALID, which will result in the operation being completed on the subscription associated
3031 * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the operation
3032 * is performed on the correct subscription.
3033 * </p>
3034 *
3035 * @param smsc the SMSC address string.
Amit Mahajand42340b2020-03-03 15:49:58 -08003036 * @return true for success, false otherwise. Failure can be due modem returning an error.
Taesu Leef7488d02019-07-16 14:13:05 +09003037 */
3038 @SuppressAutoDoc // for carrier privileges and default SMS application.
3039 @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
3040 public boolean setSmscAddress(@NonNull String smsc) {
3041 try {
3042 ISms iSms = getISmsService();
3043 if (iSms != null) {
3044 return iSms.setSmscAddressOnIccEfForSubscriber(
Shuo Qian24fded62020-01-14 14:48:27 -08003045 smsc, getSubscriptionId(), null);
Taesu Leef7488d02019-07-16 14:13:05 +09003046 }
3047 } catch (RemoteException ex) {
Amit Mahajand42340b2020-03-03 15:49:58 -08003048 throw new RuntimeException(ex);
Taesu Leef7488d02019-07-16 14:13:05 +09003049 }
3050 return false;
3051 }
changbetty9dc2ca02019-12-26 19:57:35 +08003052
3053 /**
3054 * Gets the premium SMS permission for the specified package. If the package has never
changbettya3357582020-03-06 16:46:25 +08003055 * been seen before, the default {@link SmsManager#PREMIUM_SMS_CONSENT_UNKNOWN}
changbetty9dc2ca02019-12-26 19:57:35 +08003056 * will be returned.
3057 * @param packageName the name of the package to query permission
3058 * @return one of {@link SmsManager#PREMIUM_SMS_CONSENT_UNKNOWN},
3059 * {@link SmsManager#PREMIUM_SMS_CONSENT_ASK_USER},
3060 * {@link SmsManager#PREMIUM_SMS_CONSENT_NEVER_ALLOW}, or
3061 * {@link SmsManager#PREMIUM_SMS_CONSENT_ALWAYS_ALLOW}
3062 * @hide
3063 */
3064 @SystemApi
3065 @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
3066 public @PremiumSmsConsent int getPremiumSmsConsent(@NonNull String packageName) {
3067 int permission = 0;
3068 try {
3069 ISms iSms = getISmsService();
3070 if (iSms != null) {
3071 permission = iSms.getPremiumSmsPermission(packageName);
3072 }
3073 } catch (RemoteException e) {
3074 Log.e(TAG, "getPremiumSmsPermission() RemoteException", e);
3075 }
3076 return permission;
3077 }
3078
3079 /**
3080 * Sets the premium SMS permission for the specified package and save the value asynchronously
3081 * to persistent storage.
3082 * @param packageName the name of the package to set permission
3083 * @param permission one of {@link SmsManager#PREMIUM_SMS_CONSENT_ASK_USER},
3084 * {@link SmsManager#PREMIUM_SMS_CONSENT_NEVER_ALLOW}, or
3085 * {@link SmsManager#PREMIUM_SMS_CONSENT_ALWAYS_ALLOW}
3086 * @hide
3087 */
3088 @SystemApi
3089 @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
3090 public void setPremiumSmsConsent(
3091 @NonNull String packageName, @PremiumSmsConsent int permission) {
3092 try {
3093 ISms iSms = getISmsService();
3094 if (iSms != null) {
3095 iSms.setPremiumSmsPermission(packageName, permission);
3096 }
3097 } catch (RemoteException e) {
3098 Log.e(TAG, "setPremiumSmsPermission() RemoteException", e);
3099 }
3100 }
Jack Yue9c44272020-06-17 10:35:21 -07003101
3102 /**
3103 * Reset all cell broadcast ranges. Previously enabled ranges will become invalid after this.
3104 *
3105 * @return {@code true} if succeeded, otherwise {@code false}.
3106 *
3107 * // TODO: Unhide the API in S.
3108 * @hide
3109 */
3110 public boolean resetAllCellBroadcastRanges() {
3111 boolean success = false;
3112
3113 try {
3114 ISms iSms = getISmsService();
3115 if (iSms != null) {
3116 // If getSubscriptionId() returns INVALID or an inactive subscription, we will use
3117 // the default phone internally.
3118 success = iSms.resetAllCellBroadcastRanges(getSubscriptionId());
3119 }
3120 } catch (RemoteException ex) {
3121 // ignore it
3122 }
3123
3124 return success;
3125 }
Dan Willemsen4980bf42017-02-14 14:17:12 -08003126}