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