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