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