1 /*
2  * Copyright (C) 2014 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 static android.net.NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_CONGESTED;
20 import static android.net.NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_UNMETERED;
21 
22 import android.Manifest;
23 import android.annotation.CallbackExecutor;
24 import android.annotation.DurationMillisLong;
25 import android.annotation.IntDef;
26 import android.annotation.NonNull;
27 import android.annotation.Nullable;
28 import android.annotation.RequiresPermission;
29 import android.annotation.SdkConstant;
30 import android.annotation.SdkConstant.SdkConstantType;
31 import android.annotation.SuppressAutoDoc;
32 import android.annotation.SystemApi;
33 import android.annotation.SystemService;
34 import android.annotation.TestApi;
35 import android.app.BroadcastOptions;
36 import android.app.PendingIntent;
37 import android.compat.annotation.UnsupportedAppUsage;
38 import android.content.Context;
39 import android.content.Intent;
40 import android.content.pm.PackageInfo;
41 import android.content.pm.PackageManager;
42 import android.content.res.Configuration;
43 import android.content.res.Resources;
44 import android.database.ContentObserver;
45 import android.net.INetworkPolicyManager;
46 import android.net.NetworkCapabilities;
47 import android.net.NetworkPolicyManager;
48 import android.net.Uri;
49 import android.os.Binder;
50 import android.os.Build;
51 import android.os.Handler;
52 import android.os.Looper;
53 import android.os.ParcelUuid;
54 import android.os.Process;
55 import android.os.RemoteException;
56 import android.os.ServiceManager;
57 import android.provider.Telephony.SimInfo;
58 import android.telephony.euicc.EuiccManager;
59 import android.telephony.ims.ImsMmTelManager;
60 import android.util.Log;
61 import android.util.Pair;
62 
63 import com.android.internal.telephony.ISetOpportunisticDataCallback;
64 import com.android.internal.telephony.ISub;
65 import com.android.internal.telephony.PhoneConstants;
66 import com.android.internal.telephony.util.HandlerExecutor;
67 import com.android.internal.util.Preconditions;
68 import com.android.telephony.Rlog;
69 
70 import java.lang.annotation.Retention;
71 import java.lang.annotation.RetentionPolicy;
72 import java.util.ArrayList;
73 import java.util.Arrays;
74 import java.util.Collections;
75 import java.util.HashMap;
76 import java.util.List;
77 import java.util.Locale;
78 import java.util.Map;
79 import java.util.concurrent.ConcurrentHashMap;
80 import java.util.concurrent.Executor;
81 import java.util.concurrent.TimeUnit;
82 import java.util.function.Consumer;
83 import java.util.stream.Collectors;
84 
85 /**
86  * SubscriptionManager is the application interface to SubscriptionController
87  * and provides information about the current Telephony Subscriptions.
88  */
89 @SystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE)
90 public class SubscriptionManager {
91     private static final String LOG_TAG = "SubscriptionManager";
92     private static final boolean DBG = false;
93     private static final boolean VDBG = false;
94 
95     /** An invalid subscription identifier */
96     public static final int INVALID_SUBSCRIPTION_ID = -1;
97 
98     /** Base value for placeholder SUBSCRIPTION_ID's. */
99     /** @hide */
100     public static final int PLACEHOLDER_SUBSCRIPTION_ID_BASE = INVALID_SUBSCRIPTION_ID - 1;
101 
102     /** An invalid phone identifier */
103     /** @hide */
104     public static final int INVALID_PHONE_INDEX = -1;
105 
106     /** Indicates invalid sim slot. This can be returned by {@link #getSlotIndex(int)}. */
107     public static final int INVALID_SIM_SLOT_INDEX = -1;
108 
109     /** Indicates the default subscription ID in Telephony. */
110     public static final int DEFAULT_SUBSCRIPTION_ID = Integer.MAX_VALUE;
111 
112     /**
113      * Indicates the caller wants the default phone id.
114      * Used in SubscriptionController and Phone but do we really need it???
115      * @hide
116      */
117     public static final int DEFAULT_PHONE_INDEX = Integer.MAX_VALUE;
118 
119     /** Indicates the caller wants the default slot id. NOT used remove? */
120     /** @hide */
121     public static final int DEFAULT_SIM_SLOT_INDEX = Integer.MAX_VALUE;
122 
123     /** Minimum possible subid that represents a subscription */
124     /** @hide */
125     public static final int MIN_SUBSCRIPTION_ID_VALUE = 0;
126 
127     /** Maximum possible subid that represents a subscription */
128     /** @hide */
129     public static final int MAX_SUBSCRIPTION_ID_VALUE = DEFAULT_SUBSCRIPTION_ID - 1;
130 
131     /** @hide */
132     @UnsupportedAppUsage
133     public static final Uri CONTENT_URI = SimInfo.CONTENT_URI;
134 
135     /**
136      * Generates a content {@link Uri} used to receive updates on simInfo change
137      * on the given subscriptionId
138      * @param subscriptionId the subscriptionId to receive updates on
139      * @return the Uri used to observe carrier identity changes
140      * @hide
141      */
getUriForSubscriptionId(int subscriptionId)142     public static Uri getUriForSubscriptionId(int subscriptionId) {
143         return Uri.withAppendedPath(CONTENT_URI, String.valueOf(subscriptionId));
144     }
145 
146     /**
147      * A content {@link Uri} used to receive updates on wfc enabled user setting.
148      * <p>
149      * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
150      * subscription wfc enabled {@link ImsMmTelManager#isVoWiFiSettingEnabled()}
151      * while your app is running. You can also use a {@link android.app.job.JobService}
152      * to ensure your app
153      * is notified of changes to the {@link Uri} even when it is not running.
154      * Note, however, that using a {@link android.app.job.JobService} does not guarantee timely
155      * delivery of updates to the {@link Uri}.
156      * To be notified of changes to a specific subId, append subId to the URI
157      * {@link Uri#withAppendedPath(Uri, String)}.
158      * @hide
159      */
160     @NonNull
161     @SystemApi
162     @TestApi
163     public static final Uri WFC_ENABLED_CONTENT_URI = Uri.withAppendedPath(CONTENT_URI, "wfc");
164 
165     /**
166      * A content {@link Uri} used to receive updates on advanced calling user setting
167      * @see ImsMmTelManager#isAdvancedCallingSettingEnabled().
168      * <p>
169      * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
170      * subscription advanced calling enabled
171      * {@link ImsMmTelManager#isAdvancedCallingSettingEnabled()} while your app is running.
172      * You can also use a {@link android.app.job.JobService} to ensure your app is notified of
173      * changes to the {@link Uri} even when it is not running.
174      * Note, however, that using a {@link android.app.job.JobService} does not guarantee timely
175      * delivery of updates to the {@link Uri}.
176      * To be notified of changes to a specific subId, append subId to the URI
177      * {@link Uri#withAppendedPath(Uri, String)}.
178      * @hide
179      */
180     @NonNull
181     @SystemApi
182     @TestApi
183     public static final Uri ADVANCED_CALLING_ENABLED_CONTENT_URI = Uri.withAppendedPath(
184             CONTENT_URI, "advanced_calling");
185 
186     /**
187      * A content {@link Uri} used to receive updates on wfc mode setting.
188      * <p>
189      * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
190      * subscription wfc mode {@link ImsMmTelManager#getVoWiFiModeSetting()}
191      * while your app is running. You can also use a {@link android.app.job.JobService} to ensure
192      * your app is notified of changes to the {@link Uri} even when it is not running.
193      * Note, however, that using a {@link android.app.job.JobService} does not guarantee timely
194      * delivery of updates to the {@link Uri}.
195      * To be notified of changes to a specific subId, append subId to the URI
196      * {@link Uri#withAppendedPath(Uri, String)}.
197      * @hide
198      */
199     @NonNull
200     @SystemApi
201     @TestApi
202     public static final Uri WFC_MODE_CONTENT_URI = Uri.withAppendedPath(CONTENT_URI, "wfc_mode");
203 
204     /**
205      * A content {@link Uri} used to receive updates on wfc roaming mode setting.
206      * <p>
207      * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
208      * subscription wfc roaming mode {@link ImsMmTelManager#getVoWiFiRoamingModeSetting()}
209      * while your app is running. You can also use a {@link android.app.job.JobService}
210      * to ensure your app is notified of changes to the {@link Uri} even when it is not running.
211      * Note, however, that using a {@link android.app.job.JobService} does not guarantee timely
212      * delivery of updates to the {@link Uri}.
213      * To be notified of changes to a specific subId, append subId to the URI
214      * {@link Uri#withAppendedPath(Uri, String)}.
215      * @hide
216      */
217     @NonNull
218     @SystemApi
219     @TestApi
220     public static final Uri WFC_ROAMING_MODE_CONTENT_URI = Uri.withAppendedPath(
221             CONTENT_URI, "wfc_roaming_mode");
222 
223     /**
224      * A content {@link Uri} used to receive updates on vt(video telephony over IMS) enabled
225      * setting.
226      * <p>
227      * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
228      * subscription vt enabled {@link ImsMmTelManager#isVtSettingEnabled()}
229      * while your app is running. You can also use a {@link android.app.job.JobService} to ensure
230      * your app is notified of changes to the {@link Uri} even when it is not running.
231      * Note, however, that using a {@link android.app.job.JobService} does not guarantee timely
232      * delivery of updates to the {@link Uri}.
233      * To be notified of changes to a specific subId, append subId to the URI
234      * {@link Uri#withAppendedPath(Uri, String)}.
235      * @hide
236      */
237     @NonNull
238     @SystemApi
239     @TestApi
240     public static final Uri VT_ENABLED_CONTENT_URI = Uri.withAppendedPath(
241             CONTENT_URI, "vt_enabled");
242 
243     /**
244      * A content {@link Uri} used to receive updates on wfc roaming enabled setting.
245      * <p>
246      * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
247      * subscription wfc roaming enabled {@link ImsMmTelManager#isVoWiFiRoamingSettingEnabled()}
248      * while your app is running. You can also use a {@link android.app.job.JobService} to ensure
249      * your app is notified of changes to the {@link Uri} even when it is not running.
250      * Note, however, that using a {@link android.app.job.JobService} does not guarantee timely
251      * delivery of updates to the {@link Uri}.
252      * To be notified of changes to a specific subId, append subId to the URI
253      * {@link Uri#withAppendedPath(Uri, String)}.
254      * @hide
255      */
256     @NonNull
257     @SystemApi
258     @TestApi
259     public static final Uri WFC_ROAMING_ENABLED_CONTENT_URI = Uri.withAppendedPath(
260             CONTENT_URI, "wfc_roaming_enabled");
261 
262     /**
263      * TelephonyProvider unique key column name is the subscription id.
264      * <P>Type: TEXT (String)</P>
265      */
266     /** @hide */
267     public static final String UNIQUE_KEY_SUBSCRIPTION_ID =
268             SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID;
269 
270     /**
271      * TelephonyProvider column name for a unique identifier for the subscription within the
272      * specific subscription type. For example, it contains SIM ICC Identifier subscriptions
273      * on Local SIMs. and Mac-address for Remote-SIM Subscriptions for Bluetooth devices.
274      * <P>Type: TEXT (String)</P>
275      */
276     /** @hide */
277     public static final String ICC_ID = SimInfo.COLUMN_ICC_ID;
278 
279     /**
280      * TelephonyProvider column name for user SIM_SlOT_INDEX
281      * <P>Type: INTEGER (int)</P>
282      */
283     /** @hide */
284     public static final String SIM_SLOT_INDEX = SimInfo.COLUMN_SIM_SLOT_INDEX;
285 
286     /** SIM is not inserted */
287     /** @hide */
288     public static final int SIM_NOT_INSERTED = SimInfo.SIM_NOT_INSERTED;
289 
290     /**
291      * The slot-index for Bluetooth Remote-SIM subscriptions
292      * @hide
293      */
294     public static final int SLOT_INDEX_FOR_REMOTE_SIM_SUB = INVALID_SIM_SLOT_INDEX;
295 
296     /**
297      * TelephonyProvider column name Subscription-type.
298      * <P>Type: INTEGER (int)</P> {@link #SUBSCRIPTION_TYPE_LOCAL_SIM} for Local-SIM Subscriptions,
299      * {@link #SUBSCRIPTION_TYPE_REMOTE_SIM} for Remote-SIM Subscriptions.
300      * Default value is 0.
301      */
302     /** @hide */
303     public static final String SUBSCRIPTION_TYPE = SimInfo.COLUMN_SUBSCRIPTION_TYPE;
304 
305     /**
306      * TelephonyProvider column name data_enabled_override_rules.
307      * It's a list of rules for overriding data enabled settings. The syntax is
308      * For example, "mms=nonDefault" indicates enabling data for mms in non-default subscription.
309      * "default=nonDefault&inVoiceCall" indicates enabling data for internet in non-default
310      * subscription and while is in voice call.
311      *
312      * Default value is empty string.
313      *
314      * @hide
315      */
316     public static final String DATA_ENABLED_OVERRIDE_RULES =
317             SimInfo.COLUMN_DATA_ENABLED_OVERRIDE_RULES;
318 
319     /** @hide */
320     @Retention(RetentionPolicy.SOURCE)
321     @IntDef(prefix = {"SUBSCRIPTION_TYPE_"},
322         value = {
323             SUBSCRIPTION_TYPE_LOCAL_SIM,
324             SUBSCRIPTION_TYPE_REMOTE_SIM})
325     public @interface SubscriptionType {}
326 
327     /**
328      * This constant is to designate a subscription as a Local-SIM Subscription.
329      * <p> A Local-SIM can be a physical SIM inserted into a sim-slot in the device, or eSIM on the
330      * device.
331      * </p>
332      */
333     public static final int SUBSCRIPTION_TYPE_LOCAL_SIM = SimInfo.SUBSCRIPTION_TYPE_LOCAL_SIM;
334 
335     /**
336      * This constant is to designate a subscription as a Remote-SIM Subscription.
337      * <p>
338      * A Remote-SIM subscription is for a SIM on a phone connected to this device via some
339      * connectivity mechanism, for example bluetooth. Similar to Local SIM, this subscription can
340      * be used for SMS, Voice and data by proxying data through the connected device.
341      * Certain data of the SIM, such as IMEI, are not accessible for Remote SIMs.
342      * </p>
343      *
344      * <p>
345      * A Remote-SIM is available only as long the phone stays connected to this device.
346      * When the phone disconnects, Remote-SIM subscription is removed from this device and is
347      * no longer known. All data associated with the subscription, such as stored SMS, call logs,
348      * contacts etc, are removed from this device.
349      * </p>
350      *
351      * <p>
352      * If the phone re-connects to this device, a new Remote-SIM subscription is created for
353      * the phone. The Subscription Id associated with the new subscription is different from
354      * the Subscription Id of the previous Remote-SIM subscription created (and removed) for the
355      * phone; i.e., new Remote-SIM subscription treats the reconnected phone as a Remote-SIM that
356      * was never seen before.
357      * </p>
358      */
359     public static final int SUBSCRIPTION_TYPE_REMOTE_SIM = SimInfo.SUBSCRIPTION_TYPE_REMOTE_SIM;
360 
361     /**
362      * TelephonyProvider column name for user displayed name.
363      * <P>Type: TEXT (String)</P>
364      */
365     /** @hide */
366     public static final String DISPLAY_NAME = SimInfo.COLUMN_DISPLAY_NAME;
367 
368     /**
369      * TelephonyProvider column name for the service provider name for the SIM.
370      * <P>Type: TEXT (String)</P>
371      */
372     /** @hide */
373     public static final String CARRIER_NAME = SimInfo.COLUMN_CARRIER_NAME;
374 
375     /**
376      * Default name resource
377      * @hide
378      */
379     public static final int DEFAULT_NAME_RES = com.android.internal.R.string.unknownName;
380 
381     /**
382      * TelephonyProvider column name for source of the user displayed name.
383      * <P>Type: INT (int)</P> with one of the NAME_SOURCE_XXXX values below
384      *
385      * @hide
386      */
387     public static final String NAME_SOURCE = SimInfo.COLUMN_NAME_SOURCE;
388 
389     /**
390      * The name_source is from the carrier id.
391      * @hide
392      */
393     public static final int NAME_SOURCE_CARRIER_ID = SimInfo.NAME_SOURCE_CARRIER_ID;
394 
395     /**
396      * The name_source is from SIM EF_SPN.
397      * @hide
398      */
399     public static final int NAME_SOURCE_SIM_SPN = SimInfo.NAME_SOURCE_SIM_SPN;
400 
401     /**
402      * The name_source is from user input
403      * @hide
404      */
405     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
406     public static final int NAME_SOURCE_USER_INPUT = SimInfo.NAME_SOURCE_USER_INPUT;
407 
408     /**
409      * The name_source is carrier (carrier app, carrier config, etc.)
410      * @hide
411      */
412     public static final int NAME_SOURCE_CARRIER = SimInfo.NAME_SOURCE_CARRIER;
413 
414     /**
415      * The name_source is from SIM EF_PNN.
416      * @hide
417      */
418     public static final int NAME_SOURCE_SIM_PNN = SimInfo.NAME_SOURCE_SIM_PNN;
419 
420     /** @hide */
421     @Retention(RetentionPolicy.SOURCE)
422     @IntDef(prefix = {"NAME_SOURCE_"},
423             value = {
424                     NAME_SOURCE_CARRIER_ID,
425                     NAME_SOURCE_SIM_SPN,
426                     NAME_SOURCE_USER_INPUT,
427                     NAME_SOURCE_CARRIER,
428                     NAME_SOURCE_SIM_PNN
429             })
430     public @interface SimDisplayNameSource {}
431 
432     /**
433      * TelephonyProvider column name for the color of a SIM.
434      * <P>Type: INTEGER (int)</P>
435      */
436     /** @hide */
437     public static final String HUE = SimInfo.COLUMN_COLOR;
438 
439     /**
440      * TelephonyProvider column name for the phone number of a SIM.
441      * <P>Type: TEXT (String)</P>
442      */
443     /** @hide */
444     public static final String NUMBER = SimInfo.COLUMN_NUMBER;
445 
446     /**
447      * TelephonyProvider column name for whether data roaming is enabled.
448      * <P>Type: INTEGER (int)</P>
449      */
450     /** @hide */
451     public static final String DATA_ROAMING = SimInfo.COLUMN_DATA_ROAMING;
452 
453     /** Indicates that data roaming is enabled for a subscription */
454     public static final int DATA_ROAMING_ENABLE = SimInfo.DATA_ROAMING_ENABLE;
455 
456     /** Indicates that data roaming is disabled for a subscription */
457     public static final int DATA_ROAMING_DISABLE = SimInfo.DATA_ROAMING_DISABLE;
458 
459     /**
460      * TelephonyProvider column name for subscription carrier id.
461      * @see TelephonyManager#getSimCarrierId()
462      * <p>Type: INTEGER (int) </p>
463      * @hide
464      */
465     public static final String CARRIER_ID = SimInfo.COLUMN_CARRIER_ID;
466 
467     /**
468      * @hide A comma-separated list of EHPLMNs associated with the subscription
469      * <P>Type: TEXT (String)</P>
470      */
471     public static final String EHPLMNS = SimInfo.COLUMN_EHPLMNS;
472 
473     /**
474      * @hide A comma-separated list of HPLMNs associated with the subscription
475      * <P>Type: TEXT (String)</P>
476      */
477     public static final String HPLMNS = SimInfo.COLUMN_HPLMNS;
478 
479     /**
480      * TelephonyProvider column name for the MCC associated with a SIM, stored as a string.
481      * <P>Type: TEXT (String)</P>
482      * @hide
483      */
484     public static final String MCC_STRING = SimInfo.COLUMN_MCC_STRING;
485 
486     /**
487      * TelephonyProvider column name for the MNC associated with a SIM, stored as a string.
488      * <P>Type: TEXT (String)</P>
489      * @hide
490      */
491     public static final String MNC_STRING = SimInfo.COLUMN_MNC_STRING;
492 
493     /**
494      * TelephonyProvider column name for the MCC associated with a SIM.
495      * <P>Type: INTEGER (int)</P>
496      * @hide
497      */
498     public static final String MCC = SimInfo.COLUMN_MCC;
499 
500     /**
501      * TelephonyProvider column name for the MNC associated with a SIM.
502      * <P>Type: INTEGER (int)</P>
503      * @hide
504      */
505     public static final String MNC = SimInfo.COLUMN_MNC;
506 
507     /**
508      * TelephonyProvider column name for the iso country code associated with a SIM.
509      * <P>Type: TEXT (String)</P>
510      * @hide
511      */
512     public static final String ISO_COUNTRY_CODE = SimInfo.COLUMN_ISO_COUNTRY_CODE;
513 
514     /**
515      * TelephonyProvider column name for whether a subscription is embedded (that is, present on an
516      * eSIM).
517      * <p>Type: INTEGER (int), 1 for embedded or 0 for non-embedded.
518      * @hide
519      */
520     public static final String IS_EMBEDDED = SimInfo.COLUMN_IS_EMBEDDED;
521 
522     /**
523      * TelephonyProvider column name for SIM card identifier. For UICC card it is the ICCID of the
524      * current enabled profile on the card, while for eUICC card it is the EID of the card.
525      * <P>Type: TEXT (String)</P>
526      * @hide
527      */
528     public static final String CARD_ID = SimInfo.COLUMN_CARD_ID;
529 
530     /**
531      * TelephonyProvider column name for the encoded {@link UiccAccessRule}s from
532      * {@link UiccAccessRule#encodeRules}. Only present if {@link #IS_EMBEDDED} is 1.
533      * <p>TYPE: BLOB
534      * @hide
535      */
536     public static final String ACCESS_RULES = SimInfo.COLUMN_ACCESS_RULES;
537 
538     /**
539      * TelephonyProvider column name for the encoded {@link UiccAccessRule}s from
540      * {@link UiccAccessRule#encodeRules} but for the rules that come from CarrierConfigs.
541      * Only present if there are access rules in CarrierConfigs
542      * <p>TYPE: BLOB
543      * @hide
544      */
545     public static final String ACCESS_RULES_FROM_CARRIER_CONFIGS =
546             SimInfo.COLUMN_ACCESS_RULES_FROM_CARRIER_CONFIGS;
547 
548     /**
549      * TelephonyProvider column name identifying whether an embedded subscription is on a removable
550      * card. Such subscriptions are marked inaccessible as soon as the current card is removed.
551      * Otherwise, they will remain accessible unless explicitly deleted. Only present if
552      * {@link #IS_EMBEDDED} is 1.
553      * <p>TYPE: INTEGER (int), 1 for removable or 0 for non-removable.
554      * @hide
555      */
556     public static final String IS_REMOVABLE = SimInfo.COLUMN_IS_REMOVABLE;
557 
558     /**
559      *  TelephonyProvider column name for extreme threat in CB settings
560      * @hide
561      */
562     public static final String CB_EXTREME_THREAT_ALERT =
563             SimInfo.COLUMN_CB_EXTREME_THREAT_ALERT;
564 
565     /**
566      * TelephonyProvider column name for severe threat in CB settings
567      *@hide
568      */
569     public static final String CB_SEVERE_THREAT_ALERT = SimInfo.COLUMN_CB_SEVERE_THREAT_ALERT;
570 
571     /**
572      * TelephonyProvider column name for amber alert in CB settings
573      *@hide
574      */
575     public static final String CB_AMBER_ALERT = SimInfo.COLUMN_CB_AMBER_ALERT;
576 
577     /**
578      * TelephonyProvider column name for emergency alert in CB settings
579      *@hide
580      */
581     public static final String CB_EMERGENCY_ALERT = SimInfo.COLUMN_CB_EMERGENCY_ALERT;
582 
583     /**
584      * TelephonyProvider column name for alert sound duration in CB settings
585      *@hide
586      */
587     public static final String CB_ALERT_SOUND_DURATION =
588             SimInfo.COLUMN_CB_ALERT_SOUND_DURATION;
589 
590     /**
591      * TelephonyProvider column name for alert reminder interval in CB settings
592      *@hide
593      */
594     public static final String CB_ALERT_REMINDER_INTERVAL =
595             SimInfo.COLUMN_CB_ALERT_REMINDER_INTERVAL;
596 
597     /**
598      * TelephonyProvider column name for enabling vibrate in CB settings
599      *@hide
600      */
601     public static final String CB_ALERT_VIBRATE = SimInfo.COLUMN_CB_ALERT_VIBRATE;
602 
603     /**
604      * TelephonyProvider column name for enabling alert speech in CB settings
605      *@hide
606      */
607     public static final String CB_ALERT_SPEECH = SimInfo.COLUMN_CB_ALERT_SPEECH;
608 
609     /**
610      * TelephonyProvider column name for ETWS test alert in CB settings
611      *@hide
612      */
613     public static final String CB_ETWS_TEST_ALERT = SimInfo.COLUMN_CB_ETWS_TEST_ALERT;
614 
615     /**
616      * TelephonyProvider column name for enable channel50 alert in CB settings
617      *@hide
618      */
619     public static final String CB_CHANNEL_50_ALERT = SimInfo.COLUMN_CB_CHANNEL_50_ALERT;
620 
621     /**
622      * TelephonyProvider column name for CMAS test alert in CB settings
623      *@hide
624      */
625     public static final String CB_CMAS_TEST_ALERT = SimInfo.COLUMN_CB_CMAS_TEST_ALERT;
626 
627     /**
628      * TelephonyProvider column name for Opt out dialog in CB settings
629      *@hide
630      */
631     public static final String CB_OPT_OUT_DIALOG = SimInfo.COLUMN_CB_OPT_OUT_DIALOG;
632 
633     /**
634      * TelephonyProvider column name for enable Volte.
635      *
636      * If this setting is not initialized (set to -1)  then we use the Carrier Config value
637      * {@link CarrierConfigManager#KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL}.
638      *@hide
639      */
640     public static final String ENHANCED_4G_MODE_ENABLED =
641             SimInfo.COLUMN_ENHANCED_4G_MODE_ENABLED;
642 
643     /**
644      * TelephonyProvider column name for enable VT (Video Telephony over IMS)
645      *@hide
646      */
647     public static final String VT_IMS_ENABLED = SimInfo.COLUMN_VT_IMS_ENABLED;
648 
649     /**
650      * TelephonyProvider column name for enable Wifi calling
651      *@hide
652      */
653     public static final String WFC_IMS_ENABLED = SimInfo.COLUMN_WFC_IMS_ENABLED;
654 
655     /**
656      * TelephonyProvider column name for Wifi calling mode
657      *@hide
658      */
659     public static final String WFC_IMS_MODE = SimInfo.COLUMN_WFC_IMS_MODE;
660 
661     /**
662      * TelephonyProvider column name for Wifi calling mode in roaming
663      *@hide
664      */
665     public static final String WFC_IMS_ROAMING_MODE = SimInfo.COLUMN_WFC_IMS_ROAMING_MODE;
666 
667     /**
668      * TelephonyProvider column name for enable Wifi calling in roaming
669      *@hide
670      */
671     public static final String WFC_IMS_ROAMING_ENABLED = SimInfo.COLUMN_WFC_IMS_ROAMING_ENABLED;
672 
673     /**
674      * Determines if the user has enabled IMS RCS User Capability Exchange (UCE) for this
675      * subscription.
676      * @hide
677      */
678     public static final String IMS_RCS_UCE_ENABLED = SimInfo.COLUMN_IMS_RCS_UCE_ENABLED;
679 
680     /**
681      * TelephonyProvider column name for whether a subscription is opportunistic, that is,
682      * whether the network it connects to is limited in functionality or coverage.
683      * For example, CBRS.
684      * <p>Type: INTEGER (int), 1 for opportunistic or 0 for non-opportunistic.
685      * @hide
686      */
687     public static final String IS_OPPORTUNISTIC = SimInfo.COLUMN_IS_OPPORTUNISTIC;
688 
689     /**
690      * TelephonyProvider column name for group ID. Subscriptions with same group ID
691      * are considered bundled together, and should behave as a single subscription at
692      * certain scenarios.
693      *
694      * @hide
695      */
696     public static final String GROUP_UUID = SimInfo.COLUMN_GROUP_UUID;
697 
698     /**
699      * TelephonyProvider column name for group owner. It's the package name who created
700      * the subscription group.
701      *
702      * @hide
703      */
704     public static final String GROUP_OWNER = SimInfo.COLUMN_GROUP_OWNER;
705 
706     /**
707      * TelephonyProvider column name for the profile class of a subscription
708      * Only present if {@link #IS_EMBEDDED} is 1.
709      * <P>Type: INTEGER (int)</P>
710      * @hide
711      */
712     public static final String PROFILE_CLASS = SimInfo.COLUMN_PROFILE_CLASS;
713 
714     /**
715      * Profile class of the subscription
716      * @hide
717      */
718     @Retention(RetentionPolicy.SOURCE)
719     @IntDef(prefix = { "PROFILE_CLASS_" }, value = {
720             SimInfo.PROFILE_CLASS_TESTING,
721             SimInfo.PROFILE_CLASS_PROVISIONING,
722             SimInfo.PROFILE_CLASS_OPERATIONAL,
723             SimInfo.PROFILE_CLASS_UNSET,
724     })
725     public @interface ProfileClass {}
726 
727     /**
728      * A testing profile can be pre-loaded or downloaded onto
729      * the eUICC and provides connectivity to test equipment
730      * for the purpose of testing the device and the eUICC. It
731      * is not intended to store any operator credentials.
732      * @hide
733      */
734     @SystemApi
735     public static final int PROFILE_CLASS_TESTING = SimInfo.PROFILE_CLASS_TESTING;
736 
737     /**
738      * A provisioning profile is pre-loaded onto the eUICC and
739      * provides connectivity to a mobile network solely for the
740      * purpose of provisioning profiles.
741      * @hide
742      */
743     @SystemApi
744     public static final int PROFILE_CLASS_PROVISIONING = SimInfo.PROFILE_CLASS_PROVISIONING;
745 
746     /**
747      * An operational profile can be pre-loaded or downloaded
748      * onto the eUICC and provides services provided by the
749      * operator.
750      * @hide
751      */
752     @SystemApi
753     public static final int PROFILE_CLASS_OPERATIONAL = SimInfo.PROFILE_CLASS_OPERATIONAL;
754 
755     /**
756      * The profile class is unset. This occurs when profile class
757      * info is not available. The subscription either has no profile
758      * metadata or the profile metadata did not encode profile class.
759      * @hide
760      */
761     @SystemApi
762     public static final int PROFILE_CLASS_UNSET = SimInfo.PROFILE_CLASS_UNSET;
763 
764     /**
765      * Default profile class
766      * @hide
767      */
768     @SystemApi
769     @Deprecated
770     public static final int PROFILE_CLASS_DEFAULT = SimInfo.PROFILE_CLASS_UNSET;
771 
772     /**
773      * IMSI (International Mobile Subscriber Identity).
774      * <P>Type: TEXT </P>
775      * @hide
776      */
777     //TODO: add @SystemApi
778     public static final String IMSI = SimInfo.COLUMN_IMSI;
779 
780     /**
781      * Whether uicc applications is set to be enabled or disabled. By default it's enabled.
782      * @hide
783      */
784     public static final String UICC_APPLICATIONS_ENABLED = SimInfo.COLUMN_UICC_APPLICATIONS_ENABLED;
785 
786     /**
787      * Indicate which network type is allowed. By default it's enabled.
788      * @hide
789      */
790     public static final String ALLOWED_NETWORK_TYPES = SimInfo.COLUMN_ALLOWED_NETWORK_TYPES;
791 
792     /**
793      * Broadcast Action: The user has changed one of the default subs related to
794      * data, phone calls, or sms</p>
795      *
796      * TODO: Change to a listener
797      * @hide
798      */
799     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
800     public static final String SUB_DEFAULT_CHANGED_ACTION =
801             "android.intent.action.SUB_DEFAULT_CHANGED";
802 
803     /**
804      * Broadcast Action: The default subscription has changed.  This has the following
805      * extra values:</p>
806      * The {@link #EXTRA_SUBSCRIPTION_INDEX} extra indicates the current default subscription index
807      */
808     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
809     public static final String ACTION_DEFAULT_SUBSCRIPTION_CHANGED
810             = "android.telephony.action.DEFAULT_SUBSCRIPTION_CHANGED";
811 
812     /**
813      * Broadcast Action: The default sms subscription has changed.  This has the following
814      * extra values:</p>
815      * {@link #EXTRA_SUBSCRIPTION_INDEX} extra indicates the current default sms
816      * subscription index
817      */
818     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
819     public static final String ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED
820             = "android.telephony.action.DEFAULT_SMS_SUBSCRIPTION_CHANGED";
821 
822     /**
823      * Activity Action: Display UI for managing the billing relationship plans
824      * between a carrier and a specific subscriber.
825      * <p>
826      * Carrier apps are encouraged to implement this activity, and the OS will
827      * provide an affordance to quickly enter this activity, typically via
828      * Settings. This affordance will only be shown when the carrier app is
829      * actively providing subscription plan information via
830      * {@link #setSubscriptionPlans(int, List)}.
831      * <p>
832      * Contains {@link #EXTRA_SUBSCRIPTION_INDEX} to indicate which subscription
833      * the user is interested in.
834      */
835     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
836     public static final String ACTION_MANAGE_SUBSCRIPTION_PLANS
837             = "android.telephony.action.MANAGE_SUBSCRIPTION_PLANS";
838 
839     /**
840      * Broadcast Action: Request a refresh of the billing relationship plans
841      * between a carrier and a specific subscriber.
842      * <p>
843      * Carrier apps are encouraged to implement this receiver, and the OS will
844      * provide an affordance to request a refresh. This affordance will only be
845      * shown when the carrier app is actively providing subscription plan
846      * information via {@link #setSubscriptionPlans(int, List)}.
847      * <p>
848      * Contains {@link #EXTRA_SUBSCRIPTION_INDEX} to indicate which subscription
849      * the user is interested in.
850      * <p>
851      * Receivers should protect themselves by checking that the sender holds the
852      * {@code android.permission.MANAGE_SUBSCRIPTION_PLANS} permission.
853      */
854     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
855     public static final String ACTION_REFRESH_SUBSCRIPTION_PLANS
856             = "android.telephony.action.REFRESH_SUBSCRIPTION_PLANS";
857 
858     /**
859      * Broadcast Action: The billing relationship plans between a carrier and a
860      * specific subscriber has changed.
861      * <p>
862      * Contains {@link #EXTRA_SUBSCRIPTION_INDEX} to indicate which subscription
863      * changed.
864      * @hide
865      */
866     @SystemApi
867     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
868     @RequiresPermission(android.Manifest.permission.MANAGE_SUBSCRIPTION_PLANS)
869     public static final String ACTION_SUBSCRIPTION_PLANS_CHANGED
870             = "android.telephony.action.SUBSCRIPTION_PLANS_CHANGED";
871 
872     /**
873      * Integer extra used with {@link #ACTION_DEFAULT_SUBSCRIPTION_CHANGED} and
874      * {@link #ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED} to indicate the subscription
875      * which has changed.
876      */
877     public static final String EXTRA_SUBSCRIPTION_INDEX = "android.telephony.extra.SUBSCRIPTION_INDEX";
878 
879     /**
880      * Integer extra to specify SIM slot index.
881      */
882     public static final String EXTRA_SLOT_INDEX = "android.telephony.extra.SLOT_INDEX";
883 
884     private final Context mContext;
885     private volatile INetworkPolicyManager mNetworkPolicy;
886 
887     // Cache of Resource that has been created in getResourcesForSubId. Key is a Pair containing
888     // the Context and subId.
889     private static final Map<Pair<Context, Integer>, Resources> sResourcesCache =
890             new ConcurrentHashMap<>();
891 
892     /**
893      * A listener class for monitoring changes to {@link SubscriptionInfo} records.
894      * <p>
895      * Override the onSubscriptionsChanged method in the object that extends this
896      * class and pass it to {@link #addOnSubscriptionsChangedListener(OnSubscriptionsChangedListener)}
897      * to register your listener and to unregister invoke
898      * {@link #removeOnSubscriptionsChangedListener(OnSubscriptionsChangedListener)}
899      * <p>
900      * Permissions android.Manifest.permission.READ_PHONE_STATE is required
901      * for #onSubscriptionsChanged to be invoked.
902      */
903     public static class OnSubscriptionsChangedListener {
904         private class OnSubscriptionsChangedListenerHandler extends Handler {
OnSubscriptionsChangedListenerHandler()905             OnSubscriptionsChangedListenerHandler() {
906                 super();
907             }
908 
OnSubscriptionsChangedListenerHandler(Looper looper)909             OnSubscriptionsChangedListenerHandler(Looper looper) {
910                 super(looper);
911             }
912         }
913 
914         /**
915          * Posted executor callback on the handler associated with a given looper.
916          * The looper can be the calling thread's looper or the looper passed from the
917          * constructor {@link #OnSubscriptionsChangedListener(Looper)}.
918          */
919         private final HandlerExecutor mExecutor;
920 
921         /**
922          * @hide
923          */
getHandlerExecutor()924         public HandlerExecutor getHandlerExecutor() {
925             return mExecutor;
926         }
927 
OnSubscriptionsChangedListener()928         public OnSubscriptionsChangedListener() {
929             mExecutor = new HandlerExecutor(new OnSubscriptionsChangedListenerHandler());
930         }
931 
932         /**
933          * Allow a listener to be created with a custom looper
934          * @param looper the looper that the underlining handler should run on
935          * @hide
936          */
OnSubscriptionsChangedListener(Looper looper)937         public OnSubscriptionsChangedListener(Looper looper) {
938             mExecutor = new HandlerExecutor(new OnSubscriptionsChangedListenerHandler(looper));
939         }
940 
941         /**
942          * Callback invoked when there is any change to any SubscriptionInfo, as well as once on
943          * registering for changes with {@link #addOnSubscriptionsChangedListener}. Typically
944          * this method would invoke {@link #getActiveSubscriptionInfoList}
945          */
onSubscriptionsChanged()946         public void onSubscriptionsChanged() {
947             if (DBG) log("onSubscriptionsChanged: NOT OVERRIDDEN");
948         }
949 
950         /**
951          * Callback invoked when {@link SubscriptionManager#addOnSubscriptionsChangedListener(
952          * Executor, OnSubscriptionsChangedListener)} or
953          * {@link SubscriptionManager#addOnSubscriptionsChangedListener(
954          * OnSubscriptionsChangedListener)} fails to complete due to the
955          * {@link Context#TELEPHONY_REGISTRY_SERVICE} being unavailable.
956          * @hide
957          */
onAddListenerFailed()958         public void onAddListenerFailed() {
959             Rlog.w(LOG_TAG, "onAddListenerFailed not overridden");
960         }
961 
log(String s)962         private void log(String s) {
963             Rlog.d(LOG_TAG, s);
964         }
965     }
966 
967     /** @hide */
968     @UnsupportedAppUsage
SubscriptionManager(Context context)969     public SubscriptionManager(Context context) {
970         if (DBG) logd("SubscriptionManager created");
971         mContext = context;
972     }
973 
getNetworkPolicyManager()974     private NetworkPolicyManager getNetworkPolicyManager() {
975         return (NetworkPolicyManager) mContext
976                 .getSystemService(Context.NETWORK_POLICY_SERVICE);
977     }
978 
979     /**
980      * @deprecated developers should always obtain references directly from
981      *             {@link Context#getSystemService(Class)}.
982      */
983     @Deprecated
from(Context context)984     public static SubscriptionManager from(Context context) {
985         return (SubscriptionManager) context
986                 .getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
987     }
988 
getINetworkPolicyManager()989     private INetworkPolicyManager getINetworkPolicyManager() {
990         if (mNetworkPolicy == null) {
991             mNetworkPolicy = INetworkPolicyManager.Stub
992                     .asInterface(ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
993         }
994         return mNetworkPolicy;
995     }
996 
997     /**
998      * Register for changes to the list of active {@link SubscriptionInfo} records or to the
999      * individual records themselves. When a change occurs the onSubscriptionsChanged method of
1000      * the listener will be invoked immediately if there has been a notification. The
1001      * onSubscriptionChanged method will also be triggered once initially when calling this
1002      * function. The callback will be invoked on the looper specified in the listener's constructor.
1003      *
1004      * @param listener an instance of {@link OnSubscriptionsChangedListener} with
1005      *                 onSubscriptionsChanged overridden.
1006      *
1007      * @deprecated Will get exception if the parameter listener is not initialized with a Looper.
1008      * Use {@link #addOnSubscriptionsChangedListener(Executor, OnSubscriptionsChangedListener)}.
1009      */
1010     @Deprecated
addOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener)1011     public void addOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener) {
1012         if (listener == null) return;
1013         addOnSubscriptionsChangedListener(listener.mExecutor, listener);
1014     }
1015 
1016     /**
1017      * Register for changes to the list of active {@link SubscriptionInfo} records or to the
1018      * individual records themselves. When a change occurs the onSubscriptionsChanged method of
1019      * the listener will be invoked immediately if there has been a notification. The
1020      * onSubscriptionChanged method will also be triggered once initially when calling this
1021      * function.
1022      *
1023      * @param listener an instance of {@link OnSubscriptionsChangedListener} with
1024      *                 onSubscriptionsChanged overridden.
1025      * @param executor the executor that will execute callbacks.
1026      */
addOnSubscriptionsChangedListener( @onNull @allbackExecutor Executor executor, @NonNull OnSubscriptionsChangedListener listener)1027     public void addOnSubscriptionsChangedListener(
1028             @NonNull @CallbackExecutor Executor executor,
1029             @NonNull OnSubscriptionsChangedListener listener) {
1030         String pkgName = mContext != null ? mContext.getOpPackageName() : "<unknown>";
1031         if (DBG) {
1032             logd("register OnSubscriptionsChangedListener pkgName=" + pkgName
1033                     + " listener=" + listener);
1034         }
1035         // We use the TelephonyRegistry as it runs in the system and thus is always
1036         // available. Where as SubscriptionController could crash and not be available
1037         TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager)
1038                 mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
1039         if (telephonyRegistryManager != null) {
1040             telephonyRegistryManager.addOnSubscriptionsChangedListener(listener,
1041                     executor);
1042         } else {
1043             // If the telephony registry isn't available, we will inform the caller on their
1044             // listener that it failed so they can try to re-register.
1045             loge("addOnSubscriptionsChangedListener: pkgname=" + pkgName + " failed to be added "
1046                     + " due to TELEPHONY_REGISTRY_SERVICE being unavailable.");
1047             executor.execute(() -> listener.onAddListenerFailed());
1048         }
1049     }
1050 
1051     /**
1052      * Unregister the {@link OnSubscriptionsChangedListener}. This is not strictly necessary
1053      * as the listener will automatically be unregistered if an attempt to invoke the listener
1054      * fails.
1055      *
1056      * @param listener that is to be unregistered.
1057      */
removeOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener)1058     public void removeOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener) {
1059         if (listener == null) return;
1060         String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
1061         if (DBG) {
1062             logd("unregister OnSubscriptionsChangedListener pkgForDebug=" + pkgForDebug
1063                     + " listener=" + listener);
1064         }
1065         // We use the TelephonyRegistry as it runs in the system and thus is always
1066         // available where as SubscriptionController could crash and not be available
1067         TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager)
1068                 mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
1069         if (telephonyRegistryManager != null) {
1070             telephonyRegistryManager.removeOnSubscriptionsChangedListener(listener);
1071         }
1072     }
1073 
1074     /**
1075      * A listener class for monitoring changes to {@link SubscriptionInfo} records of opportunistic
1076      * subscriptions.
1077      * <p>
1078      * Override the onOpportunisticSubscriptionsChanged method in the object that extends this
1079      * or {@link #addOnOpportunisticSubscriptionsChangedListener(
1080      * Executor, OnOpportunisticSubscriptionsChangedListener)}
1081      * to register your listener and to unregister invoke
1082      * {@link #removeOnOpportunisticSubscriptionsChangedListener(
1083      * OnOpportunisticSubscriptionsChangedListener)}
1084      * <p>
1085      * Permissions android.Manifest.permission.READ_PHONE_STATE is required
1086      * for #onOpportunisticSubscriptionsChanged to be invoked.
1087      */
1088     public static class OnOpportunisticSubscriptionsChangedListener {
1089         /**
1090          * Callback invoked when there is any change to any SubscriptionInfo. Typically
1091          * this method would invoke {@link #getActiveSubscriptionInfoList}
1092          */
onOpportunisticSubscriptionsChanged()1093         public void onOpportunisticSubscriptionsChanged() {
1094             if (DBG) log("onOpportunisticSubscriptionsChanged: NOT OVERRIDDEN");
1095         }
1096 
log(String s)1097         private void log(String s) {
1098             Rlog.d(LOG_TAG, s);
1099         }
1100     }
1101 
1102     /**
1103      * Register for changes to the list of opportunistic subscription records or to the
1104      * individual records themselves. When a change occurs the onOpportunisticSubscriptionsChanged
1105      * method of the listener will be invoked immediately if there has been a notification.
1106      *
1107      * @param listener an instance of {@link OnOpportunisticSubscriptionsChangedListener} with
1108      *                 onOpportunisticSubscriptionsChanged overridden.
1109      */
addOnOpportunisticSubscriptionsChangedListener( @onNull @allbackExecutor Executor executor, @NonNull OnOpportunisticSubscriptionsChangedListener listener)1110     public void addOnOpportunisticSubscriptionsChangedListener(
1111             @NonNull @CallbackExecutor Executor executor,
1112             @NonNull OnOpportunisticSubscriptionsChangedListener listener) {
1113         if (executor == null || listener == null) {
1114             return;
1115         }
1116 
1117         String pkgName = mContext != null ? mContext.getOpPackageName() : "<unknown>";
1118         if (DBG) {
1119             logd("register addOnOpportunisticSubscriptionsChangedListener pkgName=" + pkgName
1120                     + " listener=" + listener);
1121         }
1122 
1123         // We use the TelephonyRegistry as it runs in the system and thus is always
1124         // available where as SubscriptionController could crash and not be available
1125         TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager)
1126                 mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
1127         if (telephonyRegistryManager != null) {
1128             telephonyRegistryManager.addOnOpportunisticSubscriptionsChangedListener(
1129                     listener, executor);
1130         }
1131     }
1132 
1133     /**
1134      * Unregister the {@link OnOpportunisticSubscriptionsChangedListener} that is currently
1135      * listening opportunistic subscriptions change. This is not strictly necessary
1136      * as the listener will automatically be unregistered if an attempt to invoke the listener
1137      * fails.
1138      *
1139      * @param listener that is to be unregistered.
1140      */
removeOnOpportunisticSubscriptionsChangedListener( @onNull OnOpportunisticSubscriptionsChangedListener listener)1141     public void removeOnOpportunisticSubscriptionsChangedListener(
1142             @NonNull OnOpportunisticSubscriptionsChangedListener listener) {
1143         Preconditions.checkNotNull(listener, "listener cannot be null");
1144         String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
1145         if (DBG) {
1146             logd("unregister OnOpportunisticSubscriptionsChangedListener pkgForDebug="
1147                     + pkgForDebug + " listener=" + listener);
1148         }
1149         TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager)
1150                 mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
1151         if (telephonyRegistryManager != null) {
1152             telephonyRegistryManager.removeOnOpportunisticSubscriptionsChangedListener(listener);
1153         }
1154     }
1155 
1156     /**
1157      * Get the active SubscriptionInfo with the input subId.
1158      *
1159      * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
1160      * or that the calling app has carrier privileges (see
1161      * {@link TelephonyManager#hasCarrierPrivileges}).
1162      *
1163      * @param subId The unique SubscriptionInfo key in database.
1164      * @return SubscriptionInfo, maybe null if its not active.
1165      */
1166     @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
1167     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
getActiveSubscriptionInfo(int subId)1168     public SubscriptionInfo getActiveSubscriptionInfo(int subId) {
1169         if (VDBG) logd("[getActiveSubscriptionInfo]+ subId=" + subId);
1170         if (!isValidSubscriptionId(subId)) {
1171             if (DBG) {
1172                 logd("[getActiveSubscriptionInfo]- invalid subId");
1173             }
1174             return null;
1175         }
1176 
1177         SubscriptionInfo subInfo = null;
1178 
1179         try {
1180             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
1181             if (iSub != null) {
1182                 subInfo = iSub.getActiveSubscriptionInfo(subId, mContext.getOpPackageName(),
1183                         null);
1184             }
1185         } catch (RemoteException ex) {
1186             // ignore it
1187         }
1188 
1189         return subInfo;
1190 
1191     }
1192 
1193     /**
1194      * Gets an active SubscriptionInfo {@link SubscriptionInfo} associated with the Sim IccId.
1195      *
1196      * @param iccId the IccId of SIM card
1197      * @return SubscriptionInfo, maybe null if its not active
1198      *
1199      * @hide
1200      */
1201     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
1202     @Nullable
1203     @SystemApi
getActiveSubscriptionInfoForIcc(@onNull String iccId)1204     public SubscriptionInfo getActiveSubscriptionInfoForIcc(@NonNull String iccId) {
1205         if (VDBG) logd("[getActiveSubscriptionInfoForIccIndex]+ iccId=" + iccId);
1206         if (iccId == null) {
1207             logd("[getActiveSubscriptionInfoForIccIndex]- null iccid");
1208             return null;
1209         }
1210 
1211         SubscriptionInfo result = null;
1212 
1213         try {
1214             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
1215             if (iSub != null) {
1216                 result = iSub.getActiveSubscriptionInfoForIccId(iccId, mContext.getOpPackageName(),
1217                         null);
1218             }
1219         } catch (RemoteException ex) {
1220             // ignore it
1221         }
1222 
1223         return result;
1224     }
1225 
1226     /**
1227      * Get the active SubscriptionInfo associated with the slotIndex
1228      *
1229      * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
1230      * or that the calling app has carrier privileges (see
1231      * {@link TelephonyManager#hasCarrierPrivileges}).
1232      *
1233      * @param slotIndex the slot which the subscription is inserted
1234      * @return SubscriptionInfo, maybe null if its not active
1235      */
1236     @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
1237     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
getActiveSubscriptionInfoForSimSlotIndex(int slotIndex)1238     public SubscriptionInfo getActiveSubscriptionInfoForSimSlotIndex(int slotIndex) {
1239         if (VDBG) logd("[getActiveSubscriptionInfoForSimSlotIndex]+ slotIndex=" + slotIndex);
1240         if (!isValidSlotIndex(slotIndex)) {
1241             logd("[getActiveSubscriptionInfoForSimSlotIndex]- invalid slotIndex");
1242             return null;
1243         }
1244 
1245         SubscriptionInfo result = null;
1246 
1247         try {
1248             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
1249             if (iSub != null) {
1250                 result = iSub.getActiveSubscriptionInfoForSimSlotIndex(slotIndex,
1251                         mContext.getOpPackageName(), null);
1252             }
1253         } catch (RemoteException ex) {
1254             // ignore it
1255         }
1256 
1257         return result;
1258     }
1259 
1260     /**
1261      * @return List of all SubscriptionInfo records in database,
1262      * include those that were inserted before, maybe empty but not null.
1263      * @hide
1264      */
1265     @UnsupportedAppUsage
getAllSubscriptionInfoList()1266     public List<SubscriptionInfo> getAllSubscriptionInfoList() {
1267         if (VDBG) logd("[getAllSubscriptionInfoList]+");
1268 
1269         List<SubscriptionInfo> result = null;
1270 
1271         try {
1272             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
1273             if (iSub != null) {
1274                 result = iSub.getAllSubInfoList(mContext.getOpPackageName(),
1275                         null);
1276             }
1277         } catch (RemoteException ex) {
1278             // ignore it
1279         }
1280 
1281         if (result == null) {
1282             result = new ArrayList<>();
1283         }
1284         return result;
1285     }
1286 
1287     /**
1288      * Get the SubscriptionInfo(s) of the currently active SIM(s). The records will be sorted
1289      * by {@link SubscriptionInfo#getSimSlotIndex} then by {@link SubscriptionInfo#getSubscriptionId}.
1290      *
1291      * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
1292      * or that the calling app has carrier privileges (see
1293      * {@link TelephonyManager#hasCarrierPrivileges}). In the latter case, only records accessible
1294      * to the calling app are returned.
1295      *
1296      * @return Sorted list of the currently {@link SubscriptionInfo} records available on the device.
1297      * <ul>
1298      * <li>
1299      * If null is returned the current state is unknown but if a {@link OnSubscriptionsChangedListener}
1300      * has been registered {@link OnSubscriptionsChangedListener#onSubscriptionsChanged} will be
1301      * invoked in the future.
1302      * </li>
1303      * <li>
1304      * If the list is empty then there are no {@link SubscriptionInfo} records currently available.
1305      * </li>
1306      * <li>
1307      * if the list is non-empty the list is sorted by {@link SubscriptionInfo#getSimSlotIndex}
1308      * then by {@link SubscriptionInfo#getSubscriptionId}.
1309      * </li>
1310      * </ul>
1311      */
1312     @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
1313     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
getActiveSubscriptionInfoList()1314     public List<SubscriptionInfo> getActiveSubscriptionInfoList() {
1315         return getActiveSubscriptionInfoList(/* userVisibleonly */true);
1316     }
1317 
1318     /**
1319      * Get both hidden and visible SubscriptionInfo(s) of the currently active SIM(s).
1320      * The records will be sorted by {@link SubscriptionInfo#getSimSlotIndex}
1321      * then by {@link SubscriptionInfo#getSubscriptionId}.
1322      *
1323      * Hidden subscriptions refer to those are not meant visible to the users.
1324      * For example, an opportunistic subscription that is grouped with other
1325      * subscriptions should remain invisible to users as they are only functionally
1326      * supplementary to primary ones.
1327      *
1328      * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
1329      * or that the calling app has carrier privileges (see
1330      * {@link TelephonyManager#hasCarrierPrivileges}). In the latter case, only records accessible
1331      * to the calling app are returned.
1332      *
1333      * @return Sorted list of the currently available {@link SubscriptionInfo}
1334      * records on the device.
1335      * This is similar to {@link #getActiveSubscriptionInfoList} except that it will return
1336      * both active and hidden SubscriptionInfos.
1337      *
1338      */
getActiveAndHiddenSubscriptionInfoList()1339     public @Nullable List<SubscriptionInfo> getActiveAndHiddenSubscriptionInfoList() {
1340         return getActiveSubscriptionInfoList(/* userVisibleonly */false);
1341     }
1342 
1343     /**
1344     * This is similar to {@link #getActiveSubscriptionInfoList()}, but if userVisibleOnly
1345     * is true, it will filter out the hidden subscriptions.
1346     *
1347     * @hide
1348     */
getActiveSubscriptionInfoList(boolean userVisibleOnly)1349     public @Nullable List<SubscriptionInfo> getActiveSubscriptionInfoList(boolean userVisibleOnly) {
1350         List<SubscriptionInfo> activeList = null;
1351 
1352         try {
1353             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
1354             if (iSub != null) {
1355                 activeList = iSub.getActiveSubscriptionInfoList(mContext.getOpPackageName(),
1356                         null);
1357             }
1358         } catch (RemoteException ex) {
1359             // ignore it
1360         }
1361 
1362         if (!userVisibleOnly || activeList == null) {
1363             return activeList;
1364         } else {
1365             return activeList.stream().filter(subInfo -> isSubscriptionVisible(subInfo))
1366                     .collect(Collectors.toList());
1367         }
1368     }
1369 
1370     /**
1371      * Gets the SubscriptionInfo(s) of all available subscriptions, if any.
1372      *
1373      * <p>Available subscriptions include active ones (those with a non-negative
1374      * {@link SubscriptionInfo#getSimSlotIndex()}) as well as inactive but installed embedded
1375      * subscriptions.
1376      *
1377      * <p>The records will be sorted by {@link SubscriptionInfo#getSimSlotIndex} then by
1378      * {@link SubscriptionInfo#getSubscriptionId}.
1379      *
1380      * @return Sorted list of the current {@link SubscriptionInfo} records available on the
1381      * device.
1382      * <ul>
1383      * <li>
1384      * If null is returned the current state is unknown but if a
1385      * {@link OnSubscriptionsChangedListener} has been registered
1386      * {@link OnSubscriptionsChangedListener#onSubscriptionsChanged} will be invoked in the future.
1387      * <li>
1388      * If the list is empty then there are no {@link SubscriptionInfo} records currently available.
1389      * <li>
1390      * if the list is non-empty the list is sorted by {@link SubscriptionInfo#getSimSlotIndex}
1391      * then by {@link SubscriptionInfo#getSubscriptionId}.
1392      * </ul>
1393      *
1394      * <p>
1395      * Permissions android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE is required
1396      * for #getAvailableSubscriptionInfoList to be invoked.
1397      * @hide
1398      */
1399     @SystemApi
getAvailableSubscriptionInfoList()1400     public List<SubscriptionInfo> getAvailableSubscriptionInfoList() {
1401         List<SubscriptionInfo> result = null;
1402 
1403         try {
1404             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
1405             if (iSub != null) {
1406                 result = iSub.getAvailableSubscriptionInfoList(mContext.getOpPackageName(),
1407                         null);
1408             }
1409         } catch (RemoteException ex) {
1410             // ignore it
1411         }
1412         return result;
1413     }
1414 
1415     /**
1416      * Gets the SubscriptionInfo(s) of all embedded subscriptions accessible to the calling app, if
1417      * any.
1418      *
1419      * <p>Only those subscriptions for which the calling app has carrier privileges per the
1420      * subscription metadata, if any, will be included in the returned list.
1421      *
1422      * <p>The records will be sorted by {@link SubscriptionInfo#getSimSlotIndex} then by
1423      * {@link SubscriptionInfo#getSubscriptionId}.
1424      *
1425      * @return Sorted list of the current embedded {@link SubscriptionInfo} records available on the
1426      * device which are accessible to the caller.
1427      * <ul>
1428      * <li>
1429      * If null is returned the current state is unknown but if a
1430      * {@link OnSubscriptionsChangedListener} has been registered
1431      * {@link OnSubscriptionsChangedListener#onSubscriptionsChanged} will be invoked in the future.
1432      * <li>
1433      * If the list is empty then there are no {@link SubscriptionInfo} records currently available.
1434      * <li>
1435      * if the list is non-empty the list is sorted by {@link SubscriptionInfo#getSimSlotIndex}
1436      * then by {@link SubscriptionInfo#getSubscriptionId}.
1437      * </ul>
1438      */
getAccessibleSubscriptionInfoList()1439     public List<SubscriptionInfo> getAccessibleSubscriptionInfoList() {
1440         List<SubscriptionInfo> result = null;
1441 
1442         try {
1443             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
1444             if (iSub != null) {
1445                 result = iSub.getAccessibleSubscriptionInfoList(mContext.getOpPackageName());
1446             }
1447         } catch (RemoteException ex) {
1448             // ignore it
1449         }
1450         return result;
1451     }
1452 
1453     /**
1454      * Request a refresh of the platform cache of profile information for the eUICC which
1455      * corresponds to the card ID returned by {@link TelephonyManager#getCardIdForDefaultEuicc()}.
1456      *
1457      * <p>Should be called by the EuiccService implementation whenever this information changes due
1458      * to an operation done outside the scope of a request initiated by the platform to the
1459      * EuiccService. There is no need to refresh for downloads, deletes, or other operations that
1460      * were made through the EuiccService.
1461      *
1462      * <p>Requires the {@link android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission.
1463      *
1464      * @see {@link TelephonyManager#getCardIdForDefaultEuicc()} for more information on the card ID.
1465      *
1466      * @hide
1467      */
1468     @SystemApi
requestEmbeddedSubscriptionInfoListRefresh()1469     public void requestEmbeddedSubscriptionInfoListRefresh() {
1470         int cardId = TelephonyManager.from(mContext).getCardIdForDefaultEuicc();
1471         try {
1472             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
1473             if (iSub != null) {
1474                 iSub.requestEmbeddedSubscriptionInfoListRefresh(cardId);
1475             }
1476         } catch (RemoteException ex) {
1477             logd("requestEmbeddedSubscriptionInfoListFresh for card = " + cardId + " failed.");
1478         }
1479     }
1480 
1481     /**
1482      * Request a refresh of the platform cache of profile information for the eUICC with the given
1483      * {@code cardId}.
1484      *
1485      * <p>Should be called by the EuiccService implementation whenever this information changes due
1486      * to an operation done outside the scope of a request initiated by the platform to the
1487      * EuiccService. There is no need to refresh for downloads, deletes, or other operations that
1488      * were made through the EuiccService.
1489      *
1490      * <p>Requires the {@link android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission.
1491      *
1492      * @param cardId the card ID of the eUICC.
1493      *
1494      * @see {@link TelephonyManager#getCardIdForDefaultEuicc()} for more information on the card ID.
1495      *
1496      * @hide
1497      */
1498     @SystemApi
requestEmbeddedSubscriptionInfoListRefresh(int cardId)1499     public void requestEmbeddedSubscriptionInfoListRefresh(int cardId) {
1500         try {
1501             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
1502             if (iSub != null) {
1503                 iSub.requestEmbeddedSubscriptionInfoListRefresh(cardId);
1504             }
1505         } catch (RemoteException ex) {
1506             logd("requestEmbeddedSubscriptionInfoListFresh for card = " + cardId + " failed.");
1507         }
1508     }
1509 
1510     /**
1511      * @return the count of all subscriptions in the database, this includes
1512      * all subscriptions that have been seen.
1513      * @hide
1514      */
1515     @UnsupportedAppUsage
getAllSubscriptionInfoCount()1516     public int getAllSubscriptionInfoCount() {
1517         if (VDBG) logd("[getAllSubscriptionInfoCount]+");
1518 
1519         int result = 0;
1520 
1521         try {
1522             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
1523             if (iSub != null) {
1524                 result = iSub.getAllSubInfoCount(mContext.getOpPackageName(),
1525                         null);
1526             }
1527         } catch (RemoteException ex) {
1528             // ignore it
1529         }
1530 
1531         return result;
1532     }
1533 
1534     /**
1535      *
1536      * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
1537      * or that the calling app has carrier privileges (see
1538      * {@link TelephonyManager#hasCarrierPrivileges}). In the latter case, the count will include
1539      * only those subscriptions accessible to the caller.
1540      *
1541      * @return the current number of active subscriptions. There is no guarantee the value
1542      * returned by this method will be the same as the length of the list returned by
1543      * {@link #getActiveSubscriptionInfoList}.
1544      */
1545     @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
1546     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
getActiveSubscriptionInfoCount()1547     public int getActiveSubscriptionInfoCount() {
1548         int result = 0;
1549 
1550         try {
1551             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
1552             if (iSub != null) {
1553                 result = iSub.getActiveSubInfoCount(mContext.getOpPackageName(),
1554                         null);
1555             }
1556         } catch (RemoteException ex) {
1557             // ignore it
1558         }
1559 
1560         return result;
1561     }
1562 
1563     /**
1564      * @return the maximum number of active subscriptions that will be returned by
1565      * {@link #getActiveSubscriptionInfoList} and the value returned by
1566      * {@link #getActiveSubscriptionInfoCount}.
1567      */
getActiveSubscriptionInfoCountMax()1568     public int getActiveSubscriptionInfoCountMax() {
1569         int result = 0;
1570 
1571         try {
1572             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
1573             if (iSub != null) {
1574                 result = iSub.getActiveSubInfoCountMax();
1575             }
1576         } catch (RemoteException ex) {
1577             // ignore it
1578         }
1579 
1580         return result;
1581     }
1582 
1583     /**
1584      * Add a new SubscriptionInfo to SubscriptionInfo database if needed
1585      * @param iccId the IccId of the SIM card
1586      * @param slotIndex the slot which the SIM is inserted
1587      * @return the URL of the newly created row or the updated row
1588      * @hide
1589      */
addSubscriptionInfoRecord(String iccId, int slotIndex)1590     public Uri addSubscriptionInfoRecord(String iccId, int slotIndex) {
1591         if (VDBG) logd("[addSubscriptionInfoRecord]+ iccId:" + iccId + " slotIndex:" + slotIndex);
1592         if (iccId == null) {
1593             logd("[addSubscriptionInfoRecord]- null iccId");
1594         }
1595         if (!isValidSlotIndex(slotIndex)) {
1596             logd("[addSubscriptionInfoRecord]- invalid slotIndex");
1597         }
1598 
1599         addSubscriptionInfoRecord(iccId, null, slotIndex, SUBSCRIPTION_TYPE_LOCAL_SIM);
1600 
1601         // FIXME: Always returns null?
1602         return null;
1603 
1604     }
1605 
1606     /**
1607      * Add a new SubscriptionInfo to SubscriptionInfo database if needed
1608      * @param uniqueId This is the unique identifier for the subscription within the
1609      *                 specific subscription type.
1610      * @param displayName human-readable name of the device the subscription corresponds to.
1611      * @param slotIndex the slot assigned to this subscription. It is ignored for subscriptionType
1612      *                  of {@link #SUBSCRIPTION_TYPE_REMOTE_SIM}.
1613      * @param subscriptionType the {@link #SUBSCRIPTION_TYPE}
1614      * @hide
1615      */
addSubscriptionInfoRecord(String uniqueId, String displayName, int slotIndex, int subscriptionType)1616     public void addSubscriptionInfoRecord(String uniqueId, String displayName, int slotIndex,
1617             int subscriptionType) {
1618         if (VDBG) {
1619             logd("[addSubscriptionInfoRecord]+ uniqueId:" + uniqueId
1620                     + ", displayName:" + displayName + ", slotIndex:" + slotIndex
1621                     + ", subscriptionType: " + subscriptionType);
1622         }
1623         if (uniqueId == null) {
1624             Log.e(LOG_TAG, "[addSubscriptionInfoRecord]- uniqueId is null");
1625             return;
1626         }
1627 
1628         try {
1629             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
1630             if (iSub == null) {
1631                 Log.e(LOG_TAG, "[addSubscriptionInfoRecord]- ISub service is null");
1632                 return;
1633             }
1634             int result = iSub.addSubInfo(uniqueId, displayName, slotIndex, subscriptionType);
1635             if (result < 0) {
1636                 Log.e(LOG_TAG, "Adding of subscription didn't succeed: error = " + result);
1637             } else {
1638                 logd("successfully added new subscription");
1639             }
1640         } catch (RemoteException ex) {
1641             // ignore it
1642         }
1643     }
1644 
1645     /**
1646      * Remove SubscriptionInfo record from the SubscriptionInfo database
1647      * @param uniqueId This is the unique identifier for the subscription within the specific
1648      *                 subscription type.
1649      * @param subscriptionType the {@link #SUBSCRIPTION_TYPE}
1650      * @hide
1651      */
removeSubscriptionInfoRecord(String uniqueId, int subscriptionType)1652     public void removeSubscriptionInfoRecord(String uniqueId, int subscriptionType) {
1653         if (VDBG) {
1654             logd("[removeSubscriptionInfoRecord]+ uniqueId:" + uniqueId
1655                     + ", subscriptionType: " + subscriptionType);
1656         }
1657         if (uniqueId == null) {
1658             Log.e(LOG_TAG, "[addSubscriptionInfoRecord]- uniqueId is null");
1659             return;
1660         }
1661 
1662         try {
1663             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
1664             if (iSub == null) {
1665                 Log.e(LOG_TAG, "[removeSubscriptionInfoRecord]- ISub service is null");
1666                 return;
1667             }
1668             int result = iSub.removeSubInfo(uniqueId, subscriptionType);
1669             if (result < 0) {
1670                 Log.e(LOG_TAG, "Removal of subscription didn't succeed: error = " + result);
1671             } else {
1672                 logd("successfully removed subscription");
1673             }
1674         } catch (RemoteException ex) {
1675             // ignore it
1676         }
1677     }
1678 
1679     /**
1680      * Set SIM icon tint color by simInfo index
1681      * @param tint the RGB value of icon tint color of the SIM
1682      * @param subId the unique SubInfoRecord index in database
1683      * @return the number of records updated
1684      * @hide
1685      */
1686     @UnsupportedAppUsage
setIconTint(int tint, int subId)1687     public int setIconTint(int tint, int subId) {
1688         if (VDBG) logd("[setIconTint]+ tint:" + tint + " subId:" + subId);
1689         return setSubscriptionPropertyHelper(subId, "setIconTint",
1690                 (iSub)-> iSub.setIconTint(tint, subId)
1691         );
1692     }
1693 
1694     /**
1695      * Set display name by simInfo index with name source
1696      * @param displayName the display name of SIM card
1697      * @param subId the unique SubscriptionInfo index in database
1698      * @param nameSource SIM display name source
1699      * @return the number of records updated or < 0 if invalid subId
1700      * @hide
1701      */
1702     @UnsupportedAppUsage
setDisplayName(String displayName, int subId, @SimDisplayNameSource int nameSource)1703     public int setDisplayName(String displayName, int subId, @SimDisplayNameSource int nameSource) {
1704         if (VDBG) {
1705             logd("[setDisplayName]+  displayName:" + displayName + " subId:" + subId
1706                     + " nameSource:" + nameSource);
1707         }
1708         return setSubscriptionPropertyHelper(subId, "setDisplayName",
1709                 (iSub)-> iSub.setDisplayNameUsingSrc(displayName, subId, nameSource)
1710         );
1711     }
1712 
1713     /**
1714      * Set phone number by subId
1715      * @param number the phone number of the SIM
1716      * @param subId the unique SubscriptionInfo index in database
1717      * @return the number of records updated
1718      * @hide
1719      */
1720     @UnsupportedAppUsage
setDisplayNumber(String number, int subId)1721     public int setDisplayNumber(String number, int subId) {
1722         if (number == null) {
1723             logd("[setDisplayNumber]- fail");
1724             return -1;
1725         }
1726         return setSubscriptionPropertyHelper(subId, "setDisplayNumber",
1727                 (iSub)-> iSub.setDisplayNumber(number, subId)
1728         );
1729     }
1730 
1731     /**
1732      * Set data roaming by simInfo index
1733      * @param roaming 0:Don't allow data when roaming, 1:Allow data when roaming
1734      * @param subId the unique SubscriptionInfo index in database
1735      * @return the number of records updated
1736      * @hide
1737      */
1738     @UnsupportedAppUsage
setDataRoaming(int roaming, int subId)1739     public int setDataRoaming(int roaming, int subId) {
1740         if (VDBG) logd("[setDataRoaming]+ roaming:" + roaming + " subId:" + subId);
1741         return setSubscriptionPropertyHelper(subId, "setDataRoaming",
1742                 (iSub)->iSub.setDataRoaming(roaming, subId)
1743         );
1744     }
1745 
1746     /**
1747      * Get slotIndex associated with the subscription.
1748      *
1749      * @param subscriptionId the unique SubscriptionInfo index in database
1750      * @return slotIndex as a positive integer or {@link #INVALID_SIM_SLOT_INDEX} if the supplied
1751      * subscriptionId doesn't have an associated slot index.
1752      */
getSlotIndex(int subscriptionId)1753     public static int getSlotIndex(int subscriptionId) {
1754         if (!isValidSubscriptionId(subscriptionId)) {
1755             if (DBG) {
1756                 logd("[getSlotIndex]- supplied subscriptionId is invalid.");
1757             }
1758         }
1759 
1760         int result = INVALID_SIM_SLOT_INDEX;
1761 
1762         try {
1763             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
1764             if (iSub != null) {
1765                 result = iSub.getSlotIndex(subscriptionId);
1766             }
1767         } catch (RemoteException ex) {
1768             // ignore it
1769         }
1770 
1771         return result;
1772 
1773     }
1774 
1775     /**
1776      * Get an array of Subscription Ids for specified slot Index.
1777      * @param slotIndex the slot index.
1778      * @return subscription Ids or null if the given slot Index is not valid or there are no active
1779      * subscriptions in the slot.
1780      */
1781     @Nullable
getSubscriptionIds(int slotIndex)1782     public int[] getSubscriptionIds(int slotIndex) {
1783         return getSubId(slotIndex);
1784     }
1785 
1786     /** @hide */
1787     @UnsupportedAppUsage
getSubId(int slotIndex)1788     public static int[] getSubId(int slotIndex) {
1789         if (!isValidSlotIndex(slotIndex)) {
1790             logd("[getSubId]- fail");
1791             return null;
1792         }
1793 
1794         int[] subId = null;
1795 
1796         try {
1797             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
1798             if (iSub != null) {
1799                 subId = iSub.getSubId(slotIndex);
1800             }
1801         } catch (RemoteException ex) {
1802             // ignore it
1803         }
1804 
1805         return subId;
1806     }
1807 
1808     /** @hide */
1809     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
getPhoneId(int subId)1810     public static int getPhoneId(int subId) {
1811         if (!isValidSubscriptionId(subId)) {
1812             if (DBG) {
1813                 logd("[getPhoneId]- fail");
1814             }
1815             return INVALID_PHONE_INDEX;
1816         }
1817 
1818         int result = INVALID_PHONE_INDEX;
1819 
1820         try {
1821             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
1822             if (iSub != null) {
1823                 result = iSub.getPhoneId(subId);
1824             }
1825         } catch (RemoteException ex) {
1826             // ignore it
1827         }
1828 
1829         if (VDBG) logd("[getPhoneId]- phoneId=" + result);
1830         return result;
1831 
1832     }
1833 
logd(String msg)1834     private static void logd(String msg) {
1835         Rlog.d(LOG_TAG, msg);
1836     }
1837 
loge(String msg)1838     private static void loge(String msg) {
1839         Rlog.e(LOG_TAG, msg);
1840     }
1841 
1842     /**
1843      * Returns the system's default subscription id.
1844      *
1845      * For a voice capable device, it will return getDefaultVoiceSubscriptionId.
1846      * For a data only device, it will return the getDefaultDataSubscriptionId.
1847      * May return an INVALID_SUBSCRIPTION_ID on error.
1848      *
1849      * @return the "system" default subscription id.
1850      */
getDefaultSubscriptionId()1851     public static int getDefaultSubscriptionId() {
1852         int subId = INVALID_SUBSCRIPTION_ID;
1853 
1854         try {
1855             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
1856             if (iSub != null) {
1857                 subId = iSub.getDefaultSubId();
1858             }
1859         } catch (RemoteException ex) {
1860             // ignore it
1861         }
1862 
1863         if (VDBG) logd("getDefaultSubId=" + subId);
1864         return subId;
1865     }
1866 
1867     /**
1868      * Returns the system's default voice subscription id.
1869      *
1870      * On a data only device or on error, will return INVALID_SUBSCRIPTION_ID.
1871      *
1872      * @return the default voice subscription Id.
1873      */
getDefaultVoiceSubscriptionId()1874     public static int getDefaultVoiceSubscriptionId() {
1875         int subId = INVALID_SUBSCRIPTION_ID;
1876 
1877         try {
1878             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
1879             if (iSub != null) {
1880                 subId = iSub.getDefaultVoiceSubId();
1881             }
1882         } catch (RemoteException ex) {
1883             // ignore it
1884         }
1885 
1886         if (VDBG) logd("getDefaultVoiceSubscriptionId, sub id = " + subId);
1887         return subId;
1888     }
1889 
1890     /**
1891      * Sets the system's default voice subscription id.
1892      *
1893      * On a data-only device, this is a no-op.
1894      *
1895      * May throw a {@link RuntimeException} if the provided subscription id is equal to
1896      * {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID}
1897      *
1898      * @param subscriptionId A valid subscription ID to set as the system default, or
1899      *                       {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID}
1900      * @hide
1901      */
1902     @SystemApi
1903     @TestApi
1904     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
setDefaultVoiceSubscriptionId(int subscriptionId)1905     public void setDefaultVoiceSubscriptionId(int subscriptionId) {
1906         if (VDBG) logd("setDefaultVoiceSubId sub id = " + subscriptionId);
1907         try {
1908             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
1909             if (iSub != null) {
1910                 iSub.setDefaultVoiceSubId(subscriptionId);
1911             }
1912         } catch (RemoteException ex) {
1913             // ignore it
1914         }
1915     }
1916 
1917     /**
1918      * Same as {@link #setDefaultVoiceSubscriptionId(int)}, but preserved for backwards
1919      * compatibility.
1920      * @hide
1921      */
setDefaultVoiceSubId(int subId)1922     public void setDefaultVoiceSubId(int subId) {
1923         setDefaultVoiceSubscriptionId(subId);
1924     }
1925 
1926     /**
1927      * Return the SubscriptionInfo for default voice subscription.
1928      *
1929      * Will return null on data only devices, or on error.
1930      *
1931      * @return the SubscriptionInfo for the default voice subscription.
1932      * @hide
1933      */
1934     @UnsupportedAppUsage
getDefaultVoiceSubscriptionInfo()1935     public SubscriptionInfo getDefaultVoiceSubscriptionInfo() {
1936         return getActiveSubscriptionInfo(getDefaultVoiceSubscriptionId());
1937     }
1938 
1939     /** @hide */
1940     @UnsupportedAppUsage
getDefaultVoicePhoneId()1941     public static int getDefaultVoicePhoneId() {
1942         return getPhoneId(getDefaultVoiceSubscriptionId());
1943     }
1944 
1945     /**
1946      * Returns the system's default SMS subscription id.
1947      *
1948      * On a data only device or on error, will return INVALID_SUBSCRIPTION_ID.
1949      *
1950      * @return the default SMS subscription Id.
1951      */
getDefaultSmsSubscriptionId()1952     public static int getDefaultSmsSubscriptionId() {
1953         int subId = INVALID_SUBSCRIPTION_ID;
1954 
1955         try {
1956             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
1957             if (iSub != null) {
1958                 subId = iSub.getDefaultSmsSubId();
1959             }
1960         } catch (RemoteException ex) {
1961             // ignore it
1962         }
1963 
1964         if (VDBG) logd("getDefaultSmsSubscriptionId, sub id = " + subId);
1965         return subId;
1966     }
1967 
1968     /**
1969      * Set the subscription which will be used by default for SMS, with the subscription which
1970      * the supplied subscription ID corresponds to; or throw a RuntimeException if the supplied
1971      * subscription ID is not usable (check with {@link #isUsableSubscriptionId(int)}).
1972      *
1973      * @param subscriptionId the supplied subscription ID
1974      *
1975      * @hide
1976      */
1977     @SystemApi
1978     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
setDefaultSmsSubId(int subscriptionId)1979     public void setDefaultSmsSubId(int subscriptionId) {
1980         if (VDBG) logd("setDefaultSmsSubId sub id = " + subscriptionId);
1981         try {
1982             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
1983             if (iSub != null) {
1984                 iSub.setDefaultSmsSubId(subscriptionId);
1985             }
1986         } catch (RemoteException ex) {
1987             ex.rethrowFromSystemServer();
1988         }
1989     }
1990 
1991     /**
1992      * Return the SubscriptionInfo for default voice subscription.
1993      *
1994      * Will return null on data only devices, or on error.
1995      *
1996      * @return the SubscriptionInfo for the default SMS subscription.
1997      * @hide
1998      */
getDefaultSmsSubscriptionInfo()1999     public SubscriptionInfo getDefaultSmsSubscriptionInfo() {
2000         return getActiveSubscriptionInfo(getDefaultSmsSubscriptionId());
2001     }
2002 
2003     /** @hide */
2004     @UnsupportedAppUsage
getDefaultSmsPhoneId()2005     public int getDefaultSmsPhoneId() {
2006         return getPhoneId(getDefaultSmsSubscriptionId());
2007     }
2008 
2009     /**
2010      * Returns the system's default data subscription id.
2011      *
2012      * On a voice only device or on error, will return INVALID_SUBSCRIPTION_ID.
2013      *
2014      * @return the default data subscription Id.
2015      */
getDefaultDataSubscriptionId()2016     public static int getDefaultDataSubscriptionId() {
2017         int subId = INVALID_SUBSCRIPTION_ID;
2018 
2019         try {
2020             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
2021             if (iSub != null) {
2022                 subId = iSub.getDefaultDataSubId();
2023             }
2024         } catch (RemoteException ex) {
2025             // ignore it
2026         }
2027 
2028         if (VDBG) logd("getDefaultDataSubscriptionId, sub id = " + subId);
2029         return subId;
2030     }
2031 
2032     /**
2033      * Set the subscription which will be used by default for data, with the subscription which
2034      * the supplied subscription ID corresponds to; or throw a RuntimeException if the supplied
2035      * subscription ID is not usable (check with {@link #isUsableSubscriptionId(int)}).
2036      *
2037      * @param subscriptionId the supplied subscription ID
2038      *
2039      * @hide
2040      */
2041     @SystemApi
2042     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
setDefaultDataSubId(int subscriptionId)2043     public void setDefaultDataSubId(int subscriptionId) {
2044         if (VDBG) logd("setDataSubscription sub id = " + subscriptionId);
2045         try {
2046             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
2047             if (iSub != null) {
2048                 iSub.setDefaultDataSubId(subscriptionId);
2049             }
2050         } catch (RemoteException ex) {
2051             // ignore it
2052         }
2053     }
2054 
2055     /**
2056      * Return the SubscriptionInfo for default data subscription.
2057      *
2058      * Will return null on voice only devices, or on error.
2059      *
2060      * @return the SubscriptionInfo for the default data subscription.
2061      * @hide
2062      */
2063     @UnsupportedAppUsage
getDefaultDataSubscriptionInfo()2064     public SubscriptionInfo getDefaultDataSubscriptionInfo() {
2065         return getActiveSubscriptionInfo(getDefaultDataSubscriptionId());
2066     }
2067 
2068     /** @hide */
2069     @UnsupportedAppUsage
getDefaultDataPhoneId()2070     public int getDefaultDataPhoneId() {
2071         return getPhoneId(getDefaultDataSubscriptionId());
2072     }
2073 
2074     /** @hide */
clearSubscriptionInfo()2075     public void clearSubscriptionInfo() {
2076         try {
2077             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
2078             if (iSub != null) {
2079                 iSub.clearSubInfo();
2080             }
2081         } catch (RemoteException ex) {
2082             // ignore it
2083         }
2084 
2085         return;
2086     }
2087 
2088     //FIXME this is vulnerable to race conditions
2089     /** @hide */
allDefaultsSelected()2090     public boolean allDefaultsSelected() {
2091         if (!isValidSubscriptionId(getDefaultDataSubscriptionId())) {
2092             return false;
2093         }
2094         if (!isValidSubscriptionId(getDefaultSmsSubscriptionId())) {
2095             return false;
2096         }
2097         if (!isValidSubscriptionId(getDefaultVoiceSubscriptionId())) {
2098             return false;
2099         }
2100         return true;
2101     }
2102 
2103     /**
2104      * Check if the supplied subscription ID is valid.
2105      *
2106      * <p>A valid subscription ID is not necessarily an active subscription ID
2107      * (see {@link #isActiveSubscriptionId(int)}) or an usable subscription ID
2108      * (see {@link #isUsableSubscriptionId(int)}). Unless specifically noted, subscription
2109      * APIs work with a valid subscription ID.
2110      *
2111      * @param subscriptionId The subscription ID.
2112      * @return {@code true} if the supplied subscriptionId is valid; {@code false} otherwise.
2113      */
isValidSubscriptionId(int subscriptionId)2114     public static boolean isValidSubscriptionId(int subscriptionId) {
2115         return subscriptionId > INVALID_SUBSCRIPTION_ID;
2116     }
2117 
2118     /**
2119      * Check if the supplied subscription ID is usable.
2120      *
2121      * <p>A usable subscription ID is a valid subscription ID, but not necessarily an active
2122      * subscription ID (see {@link #isActiveSubscriptionId(int)}). Some subscription APIs
2123      * require a usable subscription ID, and this is noted in their documentation; otherwise, a
2124      * subscription ID does not need to be usable for subscription functions, only valid.
2125      *
2126      * @param subscriptionId the subscription ID
2127      * @return {@code true} if the subscription ID is usable; {@code false} otherwise.
2128      */
isUsableSubscriptionId(int subscriptionId)2129     public static boolean isUsableSubscriptionId(int subscriptionId) {
2130         return isUsableSubIdValue(subscriptionId);
2131     }
2132 
2133     /**
2134      * @return true if subId is an usable subId value else false. A
2135      * usable subId means its neither a INVALID_SUBSCRIPTION_ID nor a DEFAULT_SUB_ID.
2136      * @hide
2137      */
2138     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
isUsableSubIdValue(int subId)2139     public static boolean isUsableSubIdValue(int subId) {
2140         return subId >= MIN_SUBSCRIPTION_ID_VALUE && subId <= MAX_SUBSCRIPTION_ID_VALUE;
2141     }
2142 
2143     /** @hide */
2144     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
isValidSlotIndex(int slotIndex)2145     public static boolean isValidSlotIndex(int slotIndex) {
2146         return slotIndex >= 0 && slotIndex < TelephonyManager.getDefault().getActiveModemCount();
2147     }
2148 
2149     /** @hide */
2150     @UnsupportedAppUsage
isValidPhoneId(int phoneId)2151     public static boolean isValidPhoneId(int phoneId) {
2152         return phoneId >= 0 && phoneId < TelephonyManager.getDefault().getActiveModemCount();
2153     }
2154 
2155     /** @hide */
2156     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
putPhoneIdAndSubIdExtra(Intent intent, int phoneId)2157     public static void putPhoneIdAndSubIdExtra(Intent intent, int phoneId) {
2158         int[] subIds = SubscriptionManager.getSubId(phoneId);
2159         if (subIds != null && subIds.length > 0) {
2160             putPhoneIdAndSubIdExtra(intent, phoneId, subIds[0]);
2161         } else {
2162             logd("putPhoneIdAndSubIdExtra: no valid subs");
2163             intent.putExtra(PhoneConstants.PHONE_KEY, phoneId);
2164             intent.putExtra(EXTRA_SLOT_INDEX, phoneId);
2165         }
2166     }
2167 
2168     /** @hide */
2169     @UnsupportedAppUsage
putPhoneIdAndSubIdExtra(Intent intent, int phoneId, int subId)2170     public static void putPhoneIdAndSubIdExtra(Intent intent, int phoneId, int subId) {
2171         if (VDBG) logd("putPhoneIdAndSubIdExtra: phoneId=" + phoneId + " subId=" + subId);
2172         intent.putExtra(EXTRA_SLOT_INDEX, phoneId);
2173         intent.putExtra(PhoneConstants.PHONE_KEY, phoneId);
2174         putSubscriptionIdExtra(intent, subId);
2175     }
2176 
2177     /**
2178      * Get visible subscription Id(s) of the currently active SIM(s).
2179      *
2180      * @return the list of subId's that are active,
2181      *         is never null but the length may be 0.
2182      * @hide
2183      */
2184     @SystemApi
2185     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
getActiveSubscriptionIdList()2186     public @NonNull int[] getActiveSubscriptionIdList() {
2187         return getActiveSubscriptionIdList(/* visibleOnly */ true);
2188     }
2189 
2190     /**
2191      * Get both hidden and visible subscription Id(s) of the currently active SIM(s).
2192      *
2193      * Hidden subscriptions refer to those are not meant visible to the users.
2194      * For example, an opportunistic subscription that is grouped with other
2195      * subscriptions should remain invisible to users as they are only functionally
2196      * supplementary to primary ones.
2197      *
2198      * @return the list of subId's that are active,
2199      *         is never null but the length may be 0.
2200      * @hide
2201      */
2202     @SystemApi
2203     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
getCompleteActiveSubscriptionIdList()2204     public @NonNull int[] getCompleteActiveSubscriptionIdList() {
2205         return getActiveSubscriptionIdList(/* visibleOnly */false);
2206     }
2207 
2208     /**
2209      * @return a non-null list of subId's that are active.
2210      *
2211      * @hide
2212      */
getActiveSubscriptionIdList(boolean visibleOnly)2213     public @NonNull int[] getActiveSubscriptionIdList(boolean visibleOnly) {
2214         try {
2215             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
2216             if (iSub != null) {
2217                 int[] subId = iSub.getActiveSubIdList(visibleOnly);
2218                 if (subId != null) return subId;
2219             }
2220         } catch (RemoteException ex) {
2221             // ignore it
2222         }
2223 
2224         return new int[0];
2225     }
2226 
2227     /**
2228      * Returns true if the device is considered roaming on the current
2229      * network for a subscription.
2230      * <p>
2231      * Availability: Only when user registered to a network.
2232      *
2233      * @param subId The subscription ID
2234      * @return true if the network for the subscription is roaming, false otherwise
2235      */
isNetworkRoaming(int subId)2236     public boolean isNetworkRoaming(int subId) {
2237         final int phoneId = getPhoneId(subId);
2238         if (phoneId < 0) {
2239             // What else can we do?
2240             return false;
2241         }
2242         return TelephonyManager.getDefault().isNetworkRoaming(subId);
2243     }
2244 
2245     /**
2246      * Returns a constant indicating the state of sim for the slot index.
2247      *
2248      * @param slotIndex
2249      *
2250      * {@See TelephonyManager#SIM_STATE_UNKNOWN}
2251      * {@See TelephonyManager#SIM_STATE_ABSENT}
2252      * {@See TelephonyManager#SIM_STATE_PIN_REQUIRED}
2253      * {@See TelephonyManager#SIM_STATE_PUK_REQUIRED}
2254      * {@See TelephonyManager#SIM_STATE_NETWORK_LOCKED}
2255      * {@See TelephonyManager#SIM_STATE_READY}
2256      * {@See TelephonyManager#SIM_STATE_NOT_READY}
2257      * {@See TelephonyManager#SIM_STATE_PERM_DISABLED}
2258      * {@See TelephonyManager#SIM_STATE_CARD_IO_ERROR}
2259      *
2260      * {@hide}
2261      */
getSimStateForSlotIndex(int slotIndex)2262     public static int getSimStateForSlotIndex(int slotIndex) {
2263         int simState = TelephonyManager.SIM_STATE_UNKNOWN;
2264 
2265         try {
2266             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
2267             if (iSub != null) {
2268                 simState = iSub.getSimStateForSlotIndex(slotIndex);
2269             }
2270         } catch (RemoteException ex) {
2271         }
2272 
2273         return simState;
2274     }
2275 
2276     /**
2277      * Store properties associated with SubscriptionInfo in database
2278      * @param subId Subscription Id of Subscription
2279      * @param propKey Column name in database associated with SubscriptionInfo
2280      * @param propValue Value to store in DB for particular subId & column name
2281      * @hide
2282      */
setSubscriptionProperty(int subId, String propKey, String propValue)2283     public static void setSubscriptionProperty(int subId, String propKey, String propValue) {
2284         try {
2285             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
2286             if (iSub != null) {
2287                 iSub.setSubscriptionProperty(subId, propKey, propValue);
2288             }
2289         } catch (RemoteException ex) {
2290             // ignore it
2291         }
2292     }
2293 
2294     /**
2295      * Store properties associated with SubscriptionInfo in database
2296      * @param subId Subscription Id of Subscription
2297      * @param propKey Column name in SubscriptionInfo database
2298      * @return Value associated with subId and propKey column in database
2299      * @hide
2300      */
getSubscriptionProperty(int subId, String propKey, Context context)2301     private static String getSubscriptionProperty(int subId, String propKey,
2302             Context context) {
2303         String resultValue = null;
2304         try {
2305             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
2306             if (iSub != null) {
2307                 resultValue = iSub.getSubscriptionProperty(subId, propKey,
2308                         context.getOpPackageName(), null);
2309             }
2310         } catch (RemoteException ex) {
2311             // ignore it
2312         }
2313         return resultValue;
2314     }
2315 
2316     /**
2317      * Returns boolean value corresponding to query result.
2318      * @param subId Subscription Id of Subscription
2319      * @param propKey Column name in SubscriptionInfo database
2320      * @param defValue Default boolean value to be returned
2321      * @return boolean result value to be returned
2322      * @hide
2323      */
getBooleanSubscriptionProperty(int subId, String propKey, boolean defValue, Context context)2324     public static boolean getBooleanSubscriptionProperty(int subId, String propKey,
2325             boolean defValue, Context context) {
2326         String result = getSubscriptionProperty(subId, propKey, context);
2327         if (result != null) {
2328             try {
2329                 return Integer.parseInt(result) == 1;
2330             } catch (NumberFormatException err) {
2331                 logd("getBooleanSubscriptionProperty NumberFormat exception");
2332             }
2333         }
2334         return defValue;
2335     }
2336 
2337     /**
2338      * Returns integer value corresponding to query result.
2339      * @param subId Subscription Id of Subscription
2340      * @param propKey Column name in SubscriptionInfo database
2341      * @param defValue Default integer value to be returned
2342      * @return integer result value to be returned
2343      * @hide
2344      */
getIntegerSubscriptionProperty(int subId, String propKey, int defValue, Context context)2345     public static int getIntegerSubscriptionProperty(int subId, String propKey, int defValue,
2346             Context context) {
2347         String result = getSubscriptionProperty(subId, propKey, context);
2348         if (result != null) {
2349             try {
2350                 return Integer.parseInt(result);
2351             } catch (NumberFormatException err) {
2352                 logd("getIntegerSubscriptionProperty NumberFormat exception");
2353             }
2354         }
2355         return defValue;
2356     }
2357 
2358     /**
2359      * Returns long value corresponding to query result.
2360      * @param subId Subscription Id of Subscription
2361      * @param propKey Column name in SubscriptionInfo database
2362      * @param defValue Default long value to be returned
2363      * @return long result value to be returned
2364      * @hide
2365      */
getLongSubscriptionProperty(int subId, String propKey, long defValue, Context context)2366     public static long getLongSubscriptionProperty(int subId, String propKey, long defValue,
2367                                                      Context context) {
2368         String result = getSubscriptionProperty(subId, propKey, context);
2369         if (result != null) {
2370             try {
2371                 return Long.parseLong(result);
2372             } catch (NumberFormatException err) {
2373                 logd("getLongSubscriptionProperty NumberFormat exception");
2374             }
2375         }
2376         return defValue;
2377     }
2378 
2379     /**
2380      * Returns the {@link Resources} from the given {@link Context} for the MCC/MNC associated with
2381      * the subscription. If the subscription ID is invalid, the base resources are returned instead.
2382      *
2383      * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
2384      *
2385      * @param context Context object
2386      * @param subId Subscription Id of Subscription whose resources are required
2387      * @return Resources associated with Subscription.
2388      * @hide
2389      */
2390     @NonNull
2391     @SystemApi
getResourcesForSubId(@onNull Context context, int subId)2392     public static Resources getResourcesForSubId(@NonNull Context context, int subId) {
2393         return getResourcesForSubId(context, subId, false);
2394     }
2395 
2396     /**
2397      * Returns the resources associated with Subscription.
2398      * @param context Context object
2399      * @param subId Subscription Id of Subscription who's resources are required
2400      * @param useRootLocale if root locale should be used. Localized locale is used if false.
2401      * @return Resources associated with Subscription.
2402      * @hide
2403      */
2404     @NonNull
getResourcesForSubId(Context context, int subId, boolean useRootLocale)2405     public static Resources getResourcesForSubId(Context context, int subId,
2406             boolean useRootLocale) {
2407         // Check if resources for this context and subId already exist in the resource cache.
2408         // Resources that use the root locale are not cached.
2409         Pair<Context, Integer> cacheKey = null;
2410         if (isValidSubscriptionId(subId) && !useRootLocale) {
2411             cacheKey = Pair.create(context, subId);
2412             if (sResourcesCache.containsKey(cacheKey)) {
2413                 // Cache hit. Use cached Resources.
2414                 return sResourcesCache.get(cacheKey);
2415             }
2416         }
2417 
2418         final SubscriptionInfo subInfo =
2419                 SubscriptionManager.from(context).getActiveSubscriptionInfo(subId);
2420 
2421         Configuration overrideConfig = new Configuration();
2422         if (subInfo != null) {
2423             overrideConfig.mcc = subInfo.getMcc();
2424             overrideConfig.mnc = subInfo.getMnc();
2425             if (overrideConfig.mnc == 0) overrideConfig.mnc = Configuration.MNC_ZERO;
2426         }
2427 
2428         if (useRootLocale) {
2429             overrideConfig.setLocale(Locale.ROOT);
2430         }
2431 
2432         // Create new context with new configuration so that we can avoid modifying the passed in
2433         // context.
2434         // Note that if the original context configuration changes, the resources here will also
2435         // change for all values except those overridden by newConfig (e.g. if the device has an
2436         // orientation change).
2437         Context newContext = context.createConfigurationContext(overrideConfig);
2438         Resources res = newContext.getResources();
2439 
2440         if (cacheKey != null) {
2441             // Save the newly created Resources in the resource cache.
2442             sResourcesCache.put(cacheKey, res);
2443         }
2444         return res;
2445     }
2446 
2447     /**
2448      * Checks if the supplied subscription ID corresponds to a subscription which is actively in
2449      * use on the device. An active subscription ID is a valid and usable subscription ID.
2450      *
2451      * @param subscriptionId the subscription ID.
2452      * @return {@code true} if the supplied subscription ID corresponds to an active subscription;
2453      * {@code false} if it does not correspond to an active subscription; or throw a
2454      * SecurityException if the caller hasn't got the right permission.
2455      */
2456     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
isActiveSubscriptionId(int subscriptionId)2457     public boolean isActiveSubscriptionId(int subscriptionId) {
2458         return isActiveSubId(subscriptionId);
2459     }
2460 
2461     /**
2462      * @return true if the sub ID is active. i.e. The sub ID corresponds to a known subscription
2463      * and the SIM providing the subscription is present in a slot and in "LOADED" state.
2464      * @hide
2465      */
2466     @UnsupportedAppUsage
isActiveSubId(int subId)2467     public boolean isActiveSubId(int subId) {
2468         try {
2469             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
2470             if (iSub != null) {
2471                 return iSub.isActiveSubId(subId, mContext.getOpPackageName(),
2472                         null);
2473             }
2474         } catch (RemoteException ex) {
2475         }
2476         return false;
2477     }
2478 
2479     /**
2480      * Get the description of the billing relationship plan between a carrier
2481      * and a specific subscriber.
2482      * <p>
2483      * This method is only accessible to the following narrow set of apps:
2484      * <ul>
2485      * <li>The carrier app for this subscriberId, as determined by
2486      * {@link TelephonyManager#hasCarrierPrivileges()}.
2487      * <li>The carrier app explicitly delegated access through
2488      * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}.
2489      * </ul>
2490      *
2491      * @param subId the subscriber this relationship applies to
2492      * @throws SecurityException if the caller doesn't meet the requirements
2493      *             outlined above.
2494      */
getSubscriptionPlans(int subId)2495     public @NonNull List<SubscriptionPlan> getSubscriptionPlans(int subId) {
2496         SubscriptionPlan[] subscriptionPlans =
2497                 getNetworkPolicyManager().getSubscriptionPlans(subId, mContext.getOpPackageName());
2498         return subscriptionPlans == null
2499                 ? Collections.emptyList() : Arrays.asList(subscriptionPlans);
2500     }
2501 
2502     /**
2503      * Set the description of the billing relationship plan between a carrier
2504      * and a specific subscriber.
2505      * <p>
2506      * This method is only accessible to the following narrow set of apps:
2507      * <ul>
2508      * <li>The carrier app for this subscriberId, as determined by
2509      * {@link TelephonyManager#hasCarrierPrivileges()}.
2510      * <li>The carrier app explicitly delegated access through
2511      * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}.
2512      * </ul>
2513      *
2514      * @param subId the subscriber this relationship applies to. An empty list
2515      *            may be sent to clear any existing plans.
2516      * @param plans the list of plans. The first plan is always the primary and
2517      *            most important plan. Any additional plans are secondary and
2518      *            may not be displayed or used by decision making logic.
2519      * @throws SecurityException if the caller doesn't meet the requirements
2520      *             outlined above.
2521      * @throws IllegalArgumentException if plans don't meet the requirements
2522      *             defined in {@link SubscriptionPlan}.
2523      */
setSubscriptionPlans(int subId, @NonNull List<SubscriptionPlan> plans)2524     public void setSubscriptionPlans(int subId, @NonNull List<SubscriptionPlan> plans) {
2525         getNetworkPolicyManager().setSubscriptionPlans(subId,
2526                 plans.toArray(new SubscriptionPlan[plans.size()]), mContext.getOpPackageName());
2527     }
2528 
2529     /** @hide */
getSubscriptionPlansOwner(int subId)2530     private String getSubscriptionPlansOwner(int subId) {
2531         try {
2532             return getINetworkPolicyManager().getSubscriptionPlansOwner(subId);
2533         } catch (RemoteException e) {
2534             throw e.rethrowFromSystemServer();
2535         }
2536     }
2537 
2538     /**
2539      * Temporarily override the billing relationship plan between a carrier and
2540      * a specific subscriber to be considered unmetered. This will be reflected
2541      * to apps via {@link NetworkCapabilities#NET_CAPABILITY_NOT_METERED}.
2542      * <p>
2543      * This method is only accessible to the following narrow set of apps:
2544      * <ul>
2545      * <li>The carrier app for this subscriberId, as determined by
2546      * {@link TelephonyManager#hasCarrierPrivileges()}.
2547      * <li>The carrier app explicitly delegated access through
2548      * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}.
2549      * </ul>
2550      *
2551      * @param subId the subscriber this override applies to.
2552      * @param overrideUnmetered set if the billing relationship should be
2553      *            considered unmetered.
2554      * @param timeoutMillis the timeout after which the requested override will
2555      *            be automatically cleared, or {@code 0} to leave in the
2556      *            requested state until explicitly cleared, or the next reboot,
2557      *            whichever happens first.
2558      * @throws SecurityException if the caller doesn't meet the requirements
2559      *             outlined above.
2560      */
setSubscriptionOverrideUnmetered(int subId, boolean overrideUnmetered, @DurationMillisLong long timeoutMillis)2561     public void setSubscriptionOverrideUnmetered(int subId, boolean overrideUnmetered,
2562             @DurationMillisLong long timeoutMillis) {
2563 
2564         final int overrideValue = overrideUnmetered ? SUBSCRIPTION_OVERRIDE_UNMETERED : 0;
2565         getNetworkPolicyManager().setSubscriptionOverride(subId, SUBSCRIPTION_OVERRIDE_UNMETERED,
2566                 overrideValue, timeoutMillis, mContext.getOpPackageName());
2567     }
2568 
2569     /**
2570      * Temporarily override the billing relationship plan between a carrier and
2571      * a specific subscriber to be considered congested. This will cause the
2572      * device to delay certain network requests when possible, such as developer
2573      * jobs that are willing to run in a flexible time window.
2574      * <p>
2575      * This method is only accessible to the following narrow set of apps:
2576      * <ul>
2577      * <li>The carrier app for this subscriberId, as determined by
2578      * {@link TelephonyManager#hasCarrierPrivileges()}.
2579      * <li>The carrier app explicitly delegated access through
2580      * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}.
2581      * </ul>
2582      *
2583      * @param subId the subscriber this override applies to.
2584      * @param overrideCongested set if the subscription should be considered
2585      *            congested.
2586      * @param timeoutMillis the timeout after which the requested override will
2587      *            be automatically cleared, or {@code 0} to leave in the
2588      *            requested state until explicitly cleared, or the next reboot,
2589      *            whichever happens first.
2590      * @throws SecurityException if the caller doesn't meet the requirements
2591      *             outlined above.
2592      */
setSubscriptionOverrideCongested(int subId, boolean overrideCongested, @DurationMillisLong long timeoutMillis)2593     public void setSubscriptionOverrideCongested(int subId, boolean overrideCongested,
2594             @DurationMillisLong long timeoutMillis) {
2595         final int overrideValue = overrideCongested ? SUBSCRIPTION_OVERRIDE_CONGESTED : 0;
2596         getNetworkPolicyManager().setSubscriptionOverride(subId, SUBSCRIPTION_OVERRIDE_CONGESTED,
2597                 overrideValue, timeoutMillis, mContext.getOpPackageName());
2598     }
2599 
2600     /**
2601      * Create an {@link Intent} that can be launched towards the carrier app
2602      * that is currently defining the billing relationship plan through
2603      * {@link #setSubscriptionPlans(int, List)}.
2604      *
2605      * @return ready to launch Intent targeted towards the carrier app, or
2606      *         {@code null} if no carrier app is defined, or if the defined
2607      *         carrier app provides no management activity.
2608      * @hide
2609      */
createManageSubscriptionIntent(int subId)2610     public @Nullable Intent createManageSubscriptionIntent(int subId) {
2611         // Bail if no owner
2612         final String owner = getSubscriptionPlansOwner(subId);
2613         if (owner == null) return null;
2614 
2615         // Bail if no plans
2616         final List<SubscriptionPlan> plans = getSubscriptionPlans(subId);
2617         if (plans.isEmpty()) return null;
2618 
2619         final Intent intent = new Intent(ACTION_MANAGE_SUBSCRIPTION_PLANS);
2620         intent.setPackage(owner);
2621         intent.putExtra(EXTRA_SUBSCRIPTION_INDEX, subId);
2622 
2623         // Bail if not implemented
2624         if (mContext.getPackageManager().queryIntentActivities(intent,
2625                 PackageManager.MATCH_DEFAULT_ONLY).isEmpty()) {
2626             return null;
2627         }
2628 
2629         return intent;
2630     }
2631 
2632     /** @hide */
createRefreshSubscriptionIntent(int subId)2633     private @Nullable Intent createRefreshSubscriptionIntent(int subId) {
2634         // Bail if no owner
2635         final String owner = getSubscriptionPlansOwner(subId);
2636         if (owner == null) return null;
2637 
2638         // Bail if no plans
2639         final List<SubscriptionPlan> plans = getSubscriptionPlans(subId);
2640         if (plans.isEmpty()) return null;
2641 
2642         final Intent intent = new Intent(ACTION_REFRESH_SUBSCRIPTION_PLANS);
2643         intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
2644         intent.setPackage(owner);
2645         intent.putExtra(EXTRA_SUBSCRIPTION_INDEX, subId);
2646 
2647         // Bail if not implemented
2648         if (mContext.getPackageManager().queryBroadcastReceivers(intent, 0).isEmpty()) {
2649             return null;
2650         }
2651 
2652         return intent;
2653     }
2654 
2655     /**
2656      * Check if there is a carrier app that is currently defining the billing
2657      * relationship plan through {@link #setSubscriptionPlans(int, List)} that
2658      * supports refreshing of subscription plans.
2659      *
2660      * @hide
2661      */
isSubscriptionPlansRefreshSupported(int subId)2662     public boolean isSubscriptionPlansRefreshSupported(int subId) {
2663         return createRefreshSubscriptionIntent(subId) != null;
2664     }
2665 
2666     /**
2667      * Request that the carrier app that is currently defining the billing
2668      * relationship plan through {@link #setSubscriptionPlans(int, List)}
2669      * refresh its subscription plans.
2670      * <p>
2671      * If the app is able to successfully update the plans, you'll expect to
2672      * receive the {@link #ACTION_SUBSCRIPTION_PLANS_CHANGED} broadcast.
2673      *
2674      * @hide
2675      */
requestSubscriptionPlansRefresh(int subId)2676     public void requestSubscriptionPlansRefresh(int subId) {
2677         final Intent intent = createRefreshSubscriptionIntent(subId);
2678         final BroadcastOptions options = BroadcastOptions.makeBasic();
2679         options.setTemporaryAppWhitelistDuration(TimeUnit.MINUTES.toMillis(1));
2680         mContext.sendBroadcast(intent, null, options.toBundle());
2681     }
2682 
2683     /**
2684      * Checks whether the app with the given context is authorized to manage the given subscription
2685      * according to its metadata.
2686      *
2687      * @param info The subscription to check.
2688      * @return whether the app is authorized to manage this subscription per its metadata.
2689      */
canManageSubscription(SubscriptionInfo info)2690     public boolean canManageSubscription(SubscriptionInfo info) {
2691         return canManageSubscription(info, mContext.getPackageName());
2692     }
2693 
2694     /**
2695      * Checks whether the given app is authorized to manage the given subscription. An app can only
2696      * be authorized if it is included in the {@link android.telephony.UiccAccessRule} of the
2697      * {@link android.telephony.SubscriptionInfo} with the access status.
2698      *
2699      * @param info The subscription to check.
2700      * @param packageName Package name of the app to check.
2701      * @return whether the app is authorized to manage this subscription per its access rules.
2702      * @hide
2703      */
2704     @SystemApi
canManageSubscription(@onNull SubscriptionInfo info, @NonNull String packageName)2705     public boolean canManageSubscription(@NonNull SubscriptionInfo info,
2706             @NonNull String packageName) {
2707         if (info == null || info.getAllAccessRules() == null || packageName == null) {
2708             return false;
2709         }
2710         PackageManager packageManager = mContext.getPackageManager();
2711         PackageInfo packageInfo;
2712         try {
2713             packageInfo = packageManager.getPackageInfo(packageName,
2714                 PackageManager.GET_SIGNING_CERTIFICATES);
2715         } catch (PackageManager.NameNotFoundException e) {
2716             logd("Unknown package: " + packageName);
2717             return false;
2718         }
2719         for (UiccAccessRule rule : info.getAllAccessRules()) {
2720             if (rule.getCarrierPrivilegeStatus(packageInfo)
2721                     == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
2722                 return true;
2723             }
2724         }
2725         return false;
2726     }
2727 
2728     /**
2729      * Set which subscription is preferred for cellular data.
2730      * It's also usually the subscription we set up internet connection on.
2731      *
2732      * PreferredData overwrites user setting of default data subscription. And it's used
2733      * by AlternativeNetworkService or carrier apps to switch primary and CBRS
2734      * subscription dynamically in multi-SIM devices.
2735      *
2736      * @param subId which subscription is preferred to for cellular data. If it's
2737      *              {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID}, it means
2738      *              it's unset and {@link SubscriptionManager#getDefaultDataSubscriptionId()}
2739      *              is used to determine which modem is preferred.
2740      * @param needValidation whether Telephony will wait until the network is validated by
2741      *              connectivity service before switching data to it. More details see
2742      *              {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED}.
2743      * @param executor The executor of where the callback will execute.
2744      * @param callback Callback will be triggered once it succeeds or failed.
2745      *                 Pass null if don't care about the result.
2746      *
2747      * @hide
2748      *
2749      */
2750     @SystemApi
2751     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
setPreferredDataSubscriptionId(int subId, boolean needValidation, @Nullable @CallbackExecutor Executor executor, @Nullable @TelephonyManager.SetOpportunisticSubscriptionResult Consumer<Integer> callback)2752     public void setPreferredDataSubscriptionId(int subId, boolean needValidation,
2753             @Nullable @CallbackExecutor Executor executor, @Nullable
2754             @TelephonyManager.SetOpportunisticSubscriptionResult Consumer<Integer> callback) {
2755         if (VDBG) logd("[setPreferredDataSubscriptionId]+ subId:" + subId);
2756         try {
2757             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
2758             if (iSub == null) return;
2759 
2760             ISetOpportunisticDataCallback callbackStub = new ISetOpportunisticDataCallback.Stub() {
2761                 @Override
2762                 public void onComplete(int result) {
2763                     if (executor == null || callback == null) {
2764                         return;
2765                     }
2766                     final long identity = Binder.clearCallingIdentity();
2767                     try {
2768                         executor.execute(() -> {
2769                             callback.accept(result);
2770                         });
2771                     } finally {
2772                         Binder.restoreCallingIdentity(identity);
2773                     }
2774                 }
2775             };
2776             iSub.setPreferredDataSubscriptionId(subId, needValidation, callbackStub);
2777         } catch (RemoteException ex) {
2778             // ignore it
2779         }
2780     }
2781 
2782     /**
2783      * Get which subscription is preferred for cellular data.
2784      * It's also usually the subscription we set up internet connection on.
2785      *
2786      * PreferredData overwrites user setting of default data subscription. And it's used
2787      * by AlternativeNetworkService or carrier apps to switch primary and CBRS
2788      * subscription dynamically in multi-SIM devices.
2789      *
2790      * @return preferred subscription id for cellular data. {@link DEFAULT_SUBSCRIPTION_ID} if
2791      * there's no prefered subscription.
2792      *
2793      * @hide
2794      *
2795      */
2796     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
getPreferredDataSubscriptionId()2797     public int getPreferredDataSubscriptionId() {
2798         int preferredSubId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
2799         try {
2800             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
2801             if (iSub != null) {
2802                 preferredSubId = iSub.getPreferredDataSubscriptionId();
2803             }
2804         } catch (RemoteException ex) {
2805             // ignore it
2806         }
2807 
2808         return preferredSubId;
2809     }
2810 
2811     /**
2812      * Return opportunistic subscriptions that can be visible to the caller.
2813      * Opportunistic subscriptions are for opportunistic networks, which are cellular
2814      * networks with limited capabilities and coverage, for example, CBRS.
2815      *
2816      * <p>Requires Permission:
2817      * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
2818      * or that the calling app has carrier privileges (see
2819      * {@link TelephonyManager#hasCarrierPrivileges}).
2820      *
2821      * @return the list of opportunistic subscription info. If none exists, an empty list.
2822      */
2823     @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
2824     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
getOpportunisticSubscriptions()2825     public @NonNull List<SubscriptionInfo> getOpportunisticSubscriptions() {
2826         String contextPkg = mContext != null ? mContext.getOpPackageName() : "<unknown>";
2827         String contextFeature = null;
2828         List<SubscriptionInfo> subInfoList = null;
2829 
2830         try {
2831             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
2832             if (iSub != null) {
2833                 subInfoList = iSub.getOpportunisticSubscriptions(contextPkg, contextFeature);
2834             }
2835         } catch (RemoteException ex) {
2836             // ignore it
2837         }
2838 
2839         if (subInfoList == null) {
2840             subInfoList = new ArrayList<>();
2841         }
2842 
2843         return subInfoList;
2844     }
2845 
2846     /**
2847      * Switch to a certain subscription
2848      *
2849      *  @param subId sub id
2850      *  @param callbackIntent pending intent that will be sent after operation is done.
2851      */
2852     @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
switchToSubscription(int subId, @NonNull PendingIntent callbackIntent)2853     public void switchToSubscription(int subId, @NonNull PendingIntent callbackIntent) {
2854         Preconditions.checkNotNull(callbackIntent, "callbackIntent cannot be null");
2855         EuiccManager euiccManager = new EuiccManager(mContext);
2856         euiccManager.switchToSubscription(subId, callbackIntent);
2857     }
2858 
2859     /**
2860      * Set whether a subscription is opportunistic, that is, whether the network it connects
2861      * to has limited coverage. For example, CBRS. Setting a subscription opportunistic has
2862      * following impacts:
2863      *  1) Even if it's active, it will be dormant most of the time. The modem will not try
2864      *     to scan or camp until it knows an available network is nearby to save power.
2865      *  2) Telephony relies on system app or carrier input to notify nearby available networks.
2866      *     See {@link TelephonyManager#updateAvailableNetworks(List, Executor, Consumer)}
2867      *     for more information.
2868      *  3) In multi-SIM devices, when the network is nearby and camped, system may automatically
2869      *     switch internet data between it and default data subscription, based on carrier
2870      *     recommendation and its signal strength and metered-ness, etc.
2871      *
2872      *
2873      * Caller will either have {@link android.Manifest.permission#MODIFY_PHONE_STATE} or carrier
2874      * privilege permission of the subscription.
2875      *
2876      * @param opportunistic whether it’s opportunistic subscription.
2877      * @param subId the unique SubscriptionInfo index in database
2878      * @return {@code true} if the operation is succeed, {@code false} otherwise.
2879      */
2880     @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
2881     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
setOpportunistic(boolean opportunistic, int subId)2882     public boolean setOpportunistic(boolean opportunistic, int subId) {
2883         if (VDBG) logd("[setOpportunistic]+ opportunistic:" + opportunistic + " subId:" + subId);
2884         return setSubscriptionPropertyHelper(subId, "setOpportunistic",
2885                 (iSub)-> iSub.setOpportunistic(
2886                         opportunistic, subId, mContext.getOpPackageName())) == 1;
2887     }
2888 
2889     /**
2890      * Inform SubscriptionManager that subscriptions in the list are bundled
2891      * as a group. It can be multiple primary (non-opportunistic) subscriptions,
2892      * or one or more primary plus one or more opportunistic subscriptions.
2893      *
2894      * This API will always create a new immutable group and assign group UUID to all the
2895      * subscriptions, regardless whether they are in a group already or not.
2896      *
2897      * Grouped subscriptions will have below behaviors:
2898      * 1) They will share the same user settings.
2899      * 2) The opportunistic subscriptions in the group is considered invisible and will not
2900      *    return from {@link #getActiveSubscriptionInfoList()}, unless caller has carrier
2901      *    privilege permission of the subscriptions.
2902      * 3) The opportunistic subscriptions in the group can't be active by itself. If all other
2903      *    non-opportunistic ones are deactivated (unplugged or disabled in Settings),
2904      *    the opportunistic ones will be deactivated automatically.
2905      *
2906      * Caller will either have {@link android.Manifest.permission#MODIFY_PHONE_STATE}
2907      * permission or had carrier privilege permission on the subscriptions:
2908      * {@link TelephonyManager#hasCarrierPrivileges()} or
2909      * {@link #canManageSubscription(SubscriptionInfo)}
2910      *
2911      * @throws SecurityException if the caller doesn't meet the requirements
2912      *             outlined above.
2913      * @throws IllegalArgumentException if any of the subscriptions in the list doesn't exist.
2914      * @throws IllegalStateException if Telephony service is in bad state.
2915      *
2916      * @param subIdList list of subId that will be in the same group
2917      * @return groupUUID a UUID assigned to the subscription group.
2918      *
2919      */
2920     @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
2921     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
createSubscriptionGroup(@onNull List<Integer> subIdList)2922     public @NonNull ParcelUuid createSubscriptionGroup(@NonNull List<Integer> subIdList) {
2923         Preconditions.checkNotNull(subIdList, "can't create group for null subId list");
2924         String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
2925         if (VDBG) {
2926             logd("[createSubscriptionGroup]");
2927         }
2928 
2929         ParcelUuid groupUuid = null;
2930         int[] subIdArray = subIdList.stream().mapToInt(i->i).toArray();
2931         try {
2932             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
2933             if (iSub != null) {
2934                 groupUuid = iSub.createSubscriptionGroup(subIdArray, pkgForDebug);
2935             } else {
2936                 if (!isSystemProcess()) {
2937                     throw new IllegalStateException("telephony service is null.");
2938                 }
2939             }
2940         } catch (RemoteException ex) {
2941             loge("createSubscriptionGroup RemoteException " + ex);
2942             if (!isSystemProcess()) {
2943                 ex.rethrowAsRuntimeException();
2944             }
2945         }
2946 
2947         return groupUuid;
2948     }
2949 
2950     /**
2951      * Add a list of subscriptions into a group.
2952      * See {@link #createSubscriptionGroup(List)} for more details.
2953      *
2954      * Caller will either have {@link android.Manifest.permission#MODIFY_PHONE_STATE}
2955      * permission or had carrier privilege permission on the subscriptions:
2956      * {@link TelephonyManager#hasCarrierPrivileges()} or
2957      * {@link #canManageSubscription(SubscriptionInfo)}
2958      *
2959      * @throws SecurityException if the caller doesn't meet the requirements
2960      *             outlined above.
2961      * @throws IllegalArgumentException if the some subscriptions in the list doesn't exist.
2962      * @throws IllegalStateException if Telephony service is in bad state.
2963      *
2964      * @param subIdList list of subId that need adding into the group
2965      * @param groupUuid the groupUuid the subscriptions are being added to.
2966      *
2967      */
2968     @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
2969     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
addSubscriptionsIntoGroup(@onNull List<Integer> subIdList, @NonNull ParcelUuid groupUuid)2970     public void addSubscriptionsIntoGroup(@NonNull List<Integer> subIdList,
2971             @NonNull ParcelUuid groupUuid) {
2972         Preconditions.checkNotNull(subIdList, "subIdList can't be null.");
2973         Preconditions.checkNotNull(groupUuid, "groupUuid can't be null.");
2974         String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
2975         if (VDBG) {
2976             logd("[addSubscriptionsIntoGroup]");
2977         }
2978 
2979         int[] subIdArray = subIdList.stream().mapToInt(i->i).toArray();
2980 
2981         try {
2982             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
2983             if (iSub != null) {
2984                 iSub.addSubscriptionsIntoGroup(subIdArray, groupUuid, pkgForDebug);
2985             } else {
2986                 if (!isSystemProcess()) {
2987                     throw new IllegalStateException("telephony service is null.");
2988                 }
2989             }
2990         } catch (RemoteException ex) {
2991             loge("addSubscriptionsIntoGroup RemoteException " + ex);
2992             if (!isSystemProcess()) {
2993                 ex.rethrowAsRuntimeException();
2994             }
2995         }
2996     }
2997 
isSystemProcess()2998     private boolean isSystemProcess() {
2999         return Process.myUid() == Process.SYSTEM_UID;
3000     }
3001 
3002     /**
3003      * Remove a list of subscriptions from their subscription group.
3004      * See {@link #createSubscriptionGroup(List)} for more details.
3005      *
3006      * Caller will either have {@link android.Manifest.permission#MODIFY_PHONE_STATE}
3007      * permission or had carrier privilege permission on the subscriptions:
3008      * {@link TelephonyManager#hasCarrierPrivileges()} or
3009      * {@link #canManageSubscription(SubscriptionInfo)}
3010      *
3011      * @throws SecurityException if the caller doesn't meet the requirements
3012      *             outlined above.
3013      * @throws IllegalArgumentException if the some subscriptions in the list doesn't belong
3014      *             the specified group.
3015      * @throws IllegalStateException if Telephony service is in bad state.
3016      *
3017      * @param subIdList list of subId that need removing from their groups.
3018      *
3019      */
3020     @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
3021     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
removeSubscriptionsFromGroup(@onNull List<Integer> subIdList, @NonNull ParcelUuid groupUuid)3022     public void removeSubscriptionsFromGroup(@NonNull List<Integer> subIdList,
3023             @NonNull ParcelUuid groupUuid) {
3024         Preconditions.checkNotNull(subIdList, "subIdList can't be null.");
3025         Preconditions.checkNotNull(groupUuid, "groupUuid can't be null.");
3026         String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
3027         if (VDBG) {
3028             logd("[removeSubscriptionsFromGroup]");
3029         }
3030 
3031         int[] subIdArray = subIdList.stream().mapToInt(i->i).toArray();
3032 
3033         try {
3034             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
3035             if (iSub != null) {
3036                 iSub.removeSubscriptionsFromGroup(subIdArray, groupUuid, pkgForDebug);
3037             } else {
3038                 if (!isSystemProcess()) {
3039                     throw new IllegalStateException("telephony service is null.");
3040                 }
3041             }
3042         } catch (RemoteException ex) {
3043             loge("removeSubscriptionsFromGroup RemoteException " + ex);
3044             if (!isSystemProcess()) {
3045                 ex.rethrowAsRuntimeException();
3046             }
3047         }
3048     }
3049 
3050     /**
3051      * Get subscriptionInfo list of subscriptions that are in the same group of given subId.
3052      * See {@link #createSubscriptionGroup(List)} for more details.
3053      *
3054      * Caller will either have {@link android.Manifest.permission#READ_PHONE_STATE}
3055      * permission or had carrier privilege permission on the subscription.
3056      * {@link TelephonyManager#hasCarrierPrivileges()}
3057      *
3058      * @throws IllegalStateException if Telephony service is in bad state.
3059      * @throws SecurityException if the caller doesn't meet the requirements
3060      *             outlined above.
3061      *
3062      * @param groupUuid of which list of subInfo will be returned.
3063      * @return list of subscriptionInfo that belong to the same group, including the given
3064      * subscription itself. It will return an empty list if no subscription belongs to the group.
3065      *
3066      */
3067     @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
3068     @RequiresPermission(Manifest.permission.READ_PHONE_STATE)
getSubscriptionsInGroup(@onNull ParcelUuid groupUuid)3069     public @NonNull List<SubscriptionInfo> getSubscriptionsInGroup(@NonNull ParcelUuid groupUuid) {
3070         Preconditions.checkNotNull(groupUuid, "groupUuid can't be null");
3071         String contextPkg = mContext != null ? mContext.getOpPackageName() : "<unknown>";
3072         String contextFeature = null;
3073         if (VDBG) {
3074             logd("[getSubscriptionsInGroup]+ groupUuid:" + groupUuid);
3075         }
3076 
3077         List<SubscriptionInfo> result = null;
3078         try {
3079             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
3080             if (iSub != null) {
3081                 result = iSub.getSubscriptionsInGroup(groupUuid, contextPkg, contextFeature);
3082             } else {
3083                 if (!isSystemProcess()) {
3084                     throw new IllegalStateException("telephony service is null.");
3085                 }
3086             }
3087         } catch (RemoteException ex) {
3088             loge("removeSubscriptionsFromGroup RemoteException " + ex);
3089             if (!isSystemProcess()) {
3090                 ex.rethrowAsRuntimeException();
3091             }
3092         }
3093 
3094         return result;
3095     }
3096 
3097     /**
3098      * Whether a subscription is visible to API caller. If it's a bundled opportunistic
3099      * subscription, it should be hidden anywhere in Settings, dialer, status bar etc.
3100      * Exception is if caller owns carrier privilege, in which case they will
3101      * want to see their own hidden subscriptions.
3102      *
3103      * @param info the subscriptionInfo to check against.
3104      * @return true if this subscription should be visible to the API caller.
3105      *
3106      * @hide
3107      */
isSubscriptionVisible(SubscriptionInfo info)3108     public boolean isSubscriptionVisible(SubscriptionInfo info) {
3109         if (info == null) return false;
3110         // If subscription is NOT grouped opportunistic subscription, it's visible.
3111         if (info.getGroupUuid() == null || !info.isOpportunistic()) return true;
3112 
3113         // If the caller is the carrier app and owns the subscription, it should be visible
3114         // to the caller.
3115         boolean hasCarrierPrivilegePermission = TelephonyManager.from(mContext)
3116                 .hasCarrierPrivileges(info.getSubscriptionId())
3117                 || canManageSubscription(info);
3118         return hasCarrierPrivilegePermission;
3119     }
3120 
3121     /**
3122      * Return a list of subscriptions that are available and visible to the user.
3123      * Used by Settings app to show a list of subscriptions for user to pick.
3124      *
3125      * <p>
3126      * Permissions android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE is required
3127      * for getSelectableSubscriptionInfoList to be invoked.
3128      * @return list of user selectable subscriptions.
3129      *
3130      * @hide
3131      */
getSelectableSubscriptionInfoList()3132     public @Nullable List<SubscriptionInfo> getSelectableSubscriptionInfoList() {
3133         List<SubscriptionInfo> availableList = getAvailableSubscriptionInfoList();
3134         if (availableList == null) {
3135             return null;
3136         } else {
3137             // Multiple subscriptions in a group should only have one representative.
3138             // It should be the current active primary subscription if any, or any
3139             // primary subscription.
3140             List<SubscriptionInfo> selectableList = new ArrayList<>();
3141             Map<ParcelUuid, SubscriptionInfo> groupMap = new HashMap<>();
3142 
3143             for (SubscriptionInfo info : availableList) {
3144                 // Opportunistic subscriptions are considered invisible
3145                 // to users so they should never be returned.
3146                 if (!isSubscriptionVisible(info)) continue;
3147 
3148                 ParcelUuid groupUuid = info.getGroupUuid();
3149                 if (groupUuid == null) {
3150                     // Doesn't belong to any group. Add in the list.
3151                     selectableList.add(info);
3152                 } else if (!groupMap.containsKey(groupUuid)
3153                         || (groupMap.get(groupUuid).getSimSlotIndex() == INVALID_SIM_SLOT_INDEX
3154                         && info.getSimSlotIndex() != INVALID_SIM_SLOT_INDEX)) {
3155                     // If it belongs to a group that has never been recorded or it's the current
3156                     // active subscription, add it in the list.
3157                     selectableList.remove(groupMap.get(groupUuid));
3158                     selectableList.add(info);
3159                     groupMap.put(groupUuid, info);
3160                 }
3161 
3162             }
3163             return selectableList;
3164         }
3165     }
3166 
3167     /**
3168      * Enables or disables a subscription. This is currently used in the settings page. It will
3169      * fail and return false if operation is not supported or failed.
3170      *
3171      * To disable an active subscription on a physical (non-Euicc) SIM,
3172      * {@link #canDisablePhysicalSubscription} needs to be true.
3173      *
3174      * <p>
3175      * Permissions android.Manifest.permission.MODIFY_PHONE_STATE is required
3176      *
3177      * @param enable whether user is turning it on or off.
3178      * @param subscriptionId Subscription to be enabled or disabled.
3179      *                       It could be a eSIM or pSIM subscription.
3180      *
3181      * @return whether the operation is successful.
3182      *
3183      * @hide
3184      */
3185     @SystemApi
3186     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
setSubscriptionEnabled(int subscriptionId, boolean enable)3187     public boolean setSubscriptionEnabled(int subscriptionId, boolean enable) {
3188         if (VDBG) {
3189             logd("setSubscriptionActivated subId= " + subscriptionId + " enable " + enable);
3190         }
3191         try {
3192             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
3193             if (iSub != null) {
3194                 return iSub.setSubscriptionEnabled(enable, subscriptionId);
3195             }
3196         } catch (RemoteException ex) {
3197             // ignore it
3198         }
3199 
3200         return false;
3201     }
3202 
3203     /**
3204      * Set uicc applications being enabled or disabled.
3205      * The value will be remembered on the subscription and will be applied whenever it's present.
3206      * If the subscription in currently present, it will also apply the setting to modem
3207      * immediately.
3208      *
3209      * Permissions android.Manifest.permission.MODIFY_PHONE_STATE is required
3210      *
3211      * @param subscriptionId which subscription to operate on.
3212      * @param enabled whether uicc applications are enabled or disabled.
3213      * @hide
3214      */
3215     @SystemApi
3216     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
setUiccApplicationsEnabled(int subscriptionId, boolean enabled)3217     public void setUiccApplicationsEnabled(int subscriptionId, boolean enabled) {
3218         if (VDBG) {
3219             logd("setUiccApplicationsEnabled subId= " + subscriptionId + " enable " + enabled);
3220         }
3221         try {
3222             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
3223             if (iSub != null) {
3224                 iSub.setUiccApplicationsEnabled(enabled, subscriptionId);
3225             }
3226         } catch (RemoteException ex) {
3227             // ignore it
3228         }
3229     }
3230 
3231     /**
3232      * Whether it's supported to disable / re-enable a subscription on a physical (non-euicc) SIM.
3233      *
3234      * Physical SIM refers non-euicc, or aka non-programmable SIM.
3235      *
3236      * It provides whether a physical SIM card can be disabled without taking it out, which is done
3237      * via {@link #setSubscriptionEnabled(int, boolean)} API.
3238      *
3239      * Requires Permission: READ_PRIVILEGED_PHONE_STATE.
3240      *
3241      * @return whether can disable subscriptions on physical SIMs.
3242      *
3243      * @hide
3244      */
3245     @SystemApi
3246     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
canDisablePhysicalSubscription()3247     public boolean canDisablePhysicalSubscription() {
3248         if (VDBG) {
3249             logd("canDisablePhysicalSubscription");
3250         }
3251         try {
3252             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
3253             if (iSub != null) {
3254                 return iSub.canDisablePhysicalSubscription();
3255             }
3256         } catch (RemoteException ex) {
3257             // ignore it
3258         }
3259 
3260         return false;
3261     }
3262 
3263     /**
3264      * DO NOT USE.
3265      * This API is designed for features that are not finished at this point. Do not call this API.
3266      * @hide
3267      * TODO b/135547512: further clean up
3268      */
3269     @SystemApi
3270     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
isSubscriptionEnabled(int subscriptionId)3271     public boolean isSubscriptionEnabled(int subscriptionId) {
3272         try {
3273             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
3274             if (iSub != null) {
3275                 return iSub.isSubscriptionEnabled(subscriptionId);
3276             }
3277         } catch (RemoteException ex) {
3278             // ignore it
3279         }
3280 
3281         return false;
3282     }
3283 
3284     /**
3285      * DO NOT USE.
3286      * This API is designed for features that are not finished at this point. Do not call this API.
3287      * @hide
3288      * TODO b/135547512: further clean up
3289      */
3290     @SystemApi
3291     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
getEnabledSubscriptionId(int slotIndex)3292     public int getEnabledSubscriptionId(int slotIndex) {
3293         int subId = INVALID_SUBSCRIPTION_ID;
3294 
3295         try {
3296             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
3297             if (iSub != null) {
3298                 subId = iSub.getEnabledSubscriptionId(slotIndex);
3299             }
3300         } catch (RemoteException ex) {
3301             // ignore it
3302         }
3303 
3304         if (VDBG) logd("getEnabledSubscriptionId, subId = " + subId);
3305         return subId;
3306     }
3307 
3308     private interface CallISubMethodHelper {
callMethod(ISub iSub)3309         int callMethod(ISub iSub) throws RemoteException;
3310     }
3311 
setSubscriptionPropertyHelper(int subId, String methodName, CallISubMethodHelper helper)3312     private int setSubscriptionPropertyHelper(int subId, String methodName,
3313             CallISubMethodHelper helper) {
3314         if (!isValidSubscriptionId(subId)) {
3315             logd("[" + methodName + "]" + "- fail");
3316             return -1;
3317         }
3318 
3319         int result = 0;
3320 
3321         try {
3322             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
3323             if (iSub != null) {
3324                 result = helper.callMethod(iSub);
3325             }
3326         } catch (RemoteException ex) {
3327             // ignore it
3328         }
3329 
3330         return result;
3331     }
3332 
3333     /**
3334      * Get active data subscription id. Active data subscription refers to the subscription
3335      * currently chosen to provide cellular internet connection to the user. This may be
3336      * different from getDefaultDataSubscriptionId(). Eg. Opportunistics data
3337      *
3338      * See {@link PhoneStateListener#onActiveDataSubscriptionIdChanged(int)} for the details.
3339      *
3340      * @return Active data subscription id if any is chosen, or
3341      * SubscriptionManager.INVALID_SUBSCRIPTION_ID if not.
3342      */
getActiveDataSubscriptionId()3343     public static int getActiveDataSubscriptionId() {
3344         try {
3345             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
3346             if (iSub != null) {
3347                 return iSub.getActiveDataSubscriptionId();
3348             }
3349         } catch (RemoteException ex) {
3350         }
3351         return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
3352     }
3353 
3354     /**
3355      * Helper method that puts a subscription id on an intent with the constants:
3356      * PhoneConstant.SUBSCRIPTION_KEY and SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX.
3357      * Both constants are used to support backwards compatibility.  Once we know we got all places,
3358      * we can remove PhoneConstants.SUBSCRIPTION_KEY.
3359      * @param intent Intent to put sub id on.
3360      * @param subId SubscriptionId to put on intent.
3361      *
3362      * @hide
3363      */
putSubscriptionIdExtra(Intent intent, int subId)3364     public static void putSubscriptionIdExtra(Intent intent, int subId) {
3365         intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
3366         intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
3367     }
3368 }
3369