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