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