1 /*
2  * Copyright 2022 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 com.android.internal.telephony.subscription;
18 
19 import static android.content.pm.PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION;
20 import static android.telephony.TelephonyManager.ENABLE_FEATURE_MAPPING;
21 
22 import android.Manifest;
23 import android.annotation.CallbackExecutor;
24 import android.annotation.ColorInt;
25 import android.annotation.EnforcePermission;
26 import android.annotation.NonNull;
27 import android.annotation.Nullable;
28 import android.annotation.RequiresPermission;
29 import android.annotation.UserIdInt;
30 import android.app.AppOpsManager;
31 import android.app.PendingIntent;
32 import android.app.compat.CompatChanges;
33 import android.compat.annotation.ChangeId;
34 import android.compat.annotation.EnabledSince;
35 import android.content.BroadcastReceiver;
36 import android.content.Context;
37 import android.content.Intent;
38 import android.content.IntentFilter;
39 import android.content.pm.PackageManager;
40 import android.content.res.Resources;
41 import android.net.Uri;
42 import android.os.Binder;
43 import android.os.Build;
44 import android.os.Bundle;
45 import android.os.CountDownTimer;
46 import android.os.Handler;
47 import android.os.HandlerThread;
48 import android.os.Looper;
49 import android.os.ParcelUuid;
50 import android.os.PersistableBundle;
51 import android.os.Process;
52 import android.os.RemoteException;
53 import android.os.SystemProperties;
54 import android.os.TelephonyServiceManager;
55 import android.os.UserHandle;
56 import android.os.UserManager;
57 import android.provider.DeviceConfig;
58 import android.provider.Settings;
59 import android.provider.Telephony.SimInfo;
60 import android.service.carrier.CarrierIdentifier;
61 import android.service.euicc.EuiccProfileInfo;
62 import android.service.euicc.EuiccService;
63 import android.service.euicc.GetEuiccProfileInfoListResult;
64 import android.telecom.PhoneAccountHandle;
65 import android.telecom.TelecomManager;
66 import android.telephony.AnomalyReporter;
67 import android.telephony.CarrierConfigManager;
68 import android.telephony.RadioAccessFamily;
69 import android.telephony.SubscriptionInfo;
70 import android.telephony.SubscriptionManager;
71 import android.telephony.SubscriptionManager.DataRoamingMode;
72 import android.telephony.SubscriptionManager.DeviceToDeviceStatusSharingPreference;
73 import android.telephony.SubscriptionManager.PhoneNumberSource;
74 import android.telephony.SubscriptionManager.SimDisplayNameSource;
75 import android.telephony.SubscriptionManager.SubscriptionType;
76 import android.telephony.SubscriptionManager.UsageSetting;
77 import android.telephony.TelephonyFrameworkInitializer;
78 import android.telephony.TelephonyManager;
79 import android.telephony.TelephonyManager.SimState;
80 import android.telephony.TelephonyRegistryManager;
81 import android.telephony.UiccAccessRule;
82 import android.telephony.euicc.EuiccManager;
83 import android.text.TextUtils;
84 import android.util.ArraySet;
85 import android.util.Base64;
86 import android.util.EventLog;
87 import android.util.IndentingPrintWriter;
88 import android.util.LocalLog;
89 
90 import com.android.internal.R;
91 import com.android.internal.annotations.VisibleForTesting;
92 import com.android.internal.telephony.CarrierResolver;
93 import com.android.internal.telephony.ISetOpportunisticDataCallback;
94 import com.android.internal.telephony.ISub;
95 import com.android.internal.telephony.IccCard;
96 import com.android.internal.telephony.MccTable;
97 import com.android.internal.telephony.MultiSimSettingController;
98 import com.android.internal.telephony.Phone;
99 import com.android.internal.telephony.PhoneFactory;
100 import com.android.internal.telephony.ProxyController;
101 import com.android.internal.telephony.RILConstants;
102 import com.android.internal.telephony.TelephonyIntents;
103 import com.android.internal.telephony.TelephonyPermissions;
104 import com.android.internal.telephony.data.PhoneSwitcher;
105 import com.android.internal.telephony.euicc.EuiccController;
106 import com.android.internal.telephony.flags.FeatureFlags;
107 import com.android.internal.telephony.flags.Flags;
108 import com.android.internal.telephony.satellite.SatelliteController;
109 import com.android.internal.telephony.subscription.SubscriptionDatabaseManager.SubscriptionDatabaseManagerCallback;
110 import com.android.internal.telephony.uicc.IccRecords;
111 import com.android.internal.telephony.uicc.IccUtils;
112 import com.android.internal.telephony.uicc.UiccCard;
113 import com.android.internal.telephony.uicc.UiccController;
114 import com.android.internal.telephony.uicc.UiccPort;
115 import com.android.internal.telephony.uicc.UiccSlot;
116 import com.android.internal.telephony.util.ArrayUtils;
117 import com.android.internal.telephony.util.TelephonyUtils;
118 import com.android.telephony.Rlog;
119 
120 import java.io.FileDescriptor;
121 import java.io.PrintWriter;
122 import java.util.ArrayList;
123 import java.util.Arrays;
124 import java.util.Collections;
125 import java.util.Comparator;
126 import java.util.List;
127 import java.util.Map;
128 import java.util.Objects;
129 import java.util.Optional;
130 import java.util.Random;
131 import java.util.Set;
132 import java.util.UUID;
133 import java.util.concurrent.ConcurrentHashMap;
134 import java.util.concurrent.Executor;
135 import java.util.stream.Collectors;
136 import java.util.stream.IntStream;
137 import java.util.stream.Stream;
138 
139 /**
140  * The subscription manager service is the backend service of {@link SubscriptionManager}.
141  * The service handles all SIM subscription related requests from clients.
142  */
143 public class SubscriptionManagerService extends ISub.Stub {
144     private static final String LOG_TAG = "SMSVC";
145     private static final String ALLOW_MOCK_MODEM_PROPERTY = "persist.radio.allow_mock_modem";
146     private static final String BOOT_ALLOW_MOCK_MODEM_PROPERTY = "ro.boot.radio.allow_mock_modem";
147 
148     private static final int CHECK_BOOTSTRAP_TIMER_IN_MS = 20 * 60 * 1000; // 20 minutes
149     private static CountDownTimer bootstrapProvisioningTimer;
150 
151     /** Whether enabling verbose debugging message or not. */
152     private static final boolean VDBG = false;
153 
154     /**
155      * The columns in {@link SimInfo} table that can be directly accessed through
156      * {@link #getSubscriptionProperty(int, String, String, String)} or
157      * {@link #setSubscriptionProperty(int, String, String)}. Usually those fields are not
158      * sensitive. Mostly they are related to user settings, for example, wifi calling
159      * user settings, cross sim calling user settings, etc...Those fields are protected with
160      * {@link Manifest.permission#READ_PHONE_STATE} permission only.
161      *
162      * For sensitive fields, they usually requires special methods to access. For example,
163      * {@link #getSubscriptionUserHandle(int)} or {@link #getPhoneNumber(int, int, String, String)}
164      * that requires higher permission to access.
165      */
166     private static final Set<String> DIRECT_ACCESS_SUBSCRIPTION_COLUMNS = Set.of(
167             SimInfo.COLUMN_CB_EXTREME_THREAT_ALERT,
168             SimInfo.COLUMN_CB_SEVERE_THREAT_ALERT,
169             SimInfo.COLUMN_CB_AMBER_ALERT,
170             SimInfo.COLUMN_CB_EMERGENCY_ALERT,
171             SimInfo.COLUMN_CB_ALERT_SOUND_DURATION,
172             SimInfo.COLUMN_CB_ALERT_REMINDER_INTERVAL,
173             SimInfo.COLUMN_CB_ALERT_VIBRATE,
174             SimInfo.COLUMN_CB_ALERT_SPEECH,
175             SimInfo.COLUMN_CB_ETWS_TEST_ALERT,
176             SimInfo.COLUMN_CB_CHANNEL_50_ALERT,
177             SimInfo.COLUMN_CB_CMAS_TEST_ALERT,
178             SimInfo.COLUMN_CB_OPT_OUT_DIALOG,
179             SimInfo.COLUMN_ENHANCED_4G_MODE_ENABLED,
180             SimInfo.COLUMN_VT_IMS_ENABLED,
181             SimInfo.COLUMN_WFC_IMS_ENABLED,
182             SimInfo.COLUMN_WFC_IMS_MODE,
183             SimInfo.COLUMN_WFC_IMS_ROAMING_MODE,
184             SimInfo.COLUMN_WFC_IMS_ROAMING_ENABLED,
185             SimInfo.COLUMN_ENABLED_MOBILE_DATA_POLICIES,
186             SimInfo.COLUMN_IMS_RCS_UCE_ENABLED,
187             SimInfo.COLUMN_CROSS_SIM_CALLING_ENABLED,
188             SimInfo.COLUMN_RCS_CONFIG,
189             SimInfo.COLUMN_ALLOWED_NETWORK_TYPES_FOR_REASONS,
190             SimInfo.COLUMN_D2D_STATUS_SHARING,
191             SimInfo.COLUMN_VOIMS_OPT_IN_STATUS,
192             SimInfo.COLUMN_D2D_STATUS_SHARING_SELECTED_CONTACTS,
193             SimInfo.COLUMN_NR_ADVANCED_CALLING_ENABLED,
194             SimInfo.COLUMN_SATELLITE_ENABLED,
195             SimInfo.COLUMN_SATELLITE_ATTACH_ENABLED_FOR_CARRIER,
196             SimInfo.COLUMN_IS_NTN,
197             SimInfo.COLUMN_SATELLITE_ENTITLEMENT_STATUS,
198             SimInfo.COLUMN_SATELLITE_ENTITLEMENT_PLMNS
199     );
200 
201     /**
202      * Apps targeting on Android T and beyond will get exception if there is no access to device
203      * identifiers nor has carrier privileges when calling
204      * {@link SubscriptionManager#getSubscriptionsInGroup}.
205      */
206     @ChangeId
207     @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
208     public static final long REQUIRE_DEVICE_IDENTIFIERS_FOR_GROUP_UUID = 213902861L;
209 
210     /**
211      * Apps targeting on Android V and beyond can only see subscriptions accessible by them
212      * according to its user Id.
213      */
214     @ChangeId
215     @EnabledSince(targetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM)
216     public static final long FILTER_ACCESSIBLE_SUBS_BY_USER = 296076674L;
217 
218     /** Wrap Binder methods for testing. */
219     @NonNull
220     private static final BinderWrapper BINDER_WRAPPER = new BinderWrapper();
221 
222     /** Instance of subscription manager service. */
223     @NonNull
224     private static SubscriptionManagerService sInstance;
225 
226     /** The context */
227     @NonNull
228     private final Context mContext;
229 
230     /** Feature flags */
231     @NonNull
232     private final FeatureFlags mFeatureFlags;
233 
234     /** App Ops manager instance. */
235     @NonNull
236     private final AppOpsManager mAppOpsManager;
237 
238     /** Telephony manager instance. */
239     @NonNull
240     private final TelephonyManager mTelephonyManager;
241 
242     /** Subscription manager instance. */
243     @NonNull
244     private final SubscriptionManager mSubscriptionManager;
245 
246     /**
247      * Euicc manager instance. Will be null if the device does not support
248      * {@link PackageManager#FEATURE_TELEPHONY_EUICC}.
249      */
250     @Nullable
251     private final EuiccManager mEuiccManager;
252 
253     /** Uicc controller instance. */
254     @NonNull
255     private final UiccController mUiccController;
256 
257     /**
258      * Euicc controller instance. Will be null if the device does not support
259      * {@link PackageManager#FEATURE_TELEPHONY_EUICC}.
260      */
261     @Nullable
262     private EuiccController mEuiccController;
263 
264     /** Package manager instance. */
265     @NonNull
266     private final PackageManager mPackageManager;
267 
268     /**
269      * The main handler of subscription manager service. This is running on phone process's main
270      * thread.
271      */
272     @NonNull
273     private final Handler mHandler;
274 
275     /**
276      * The background handler. This is running on a separate thread.
277      */
278     @NonNull
279     private final Handler mBackgroundHandler;
280 
281     /** Local log for most important debug messages. */
282     @NonNull
283     private final LocalLog mLocalLog = new LocalLog(256);
284 
285     /** The subscription database manager. */
286     @NonNull
287     private final SubscriptionDatabaseManager mSubscriptionDatabaseManager;
288 
289     /** The slot index subscription id map. Key is the slot index, and the value is sub id. */
290     @NonNull
291     private final SubscriptionMap<Integer, Integer> mSlotIndexToSubId = new SubscriptionMap<>();
292 
293     /** Subscription manager service callbacks. */
294     @NonNull
295     private final Set<SubscriptionManagerServiceCallback> mSubscriptionManagerServiceCallbacks =
296             new ArraySet<>();
297 
298     /**
299      * Default sub id. Derived from {@link #mDefaultVoiceSubId} and {@link #mDefaultDataSubId},
300      * depending on device capability.
301      */
302     @NonNull
303     private final WatchedInt mDefaultSubId;
304 
305     /** Default voice subscription id. */
306     @NonNull
307     private final WatchedInt mDefaultVoiceSubId;
308 
309     /** Default data subscription id. */
310     @NonNull
311     private final WatchedInt mDefaultDataSubId;
312 
313     /** Default sms subscription id. */
314     @NonNull
315     private final WatchedInt mDefaultSmsSubId;
316 
317     /** Sim state per logical SIM slot index. */
318     @NonNull
319     private final int[] mSimState;
320 
321     /** Vendor API level from system property. */
322     private final int mVendorApiLevel;
323 
324     /**
325      * {@code true} if a user profile can only see the SIMs associated with it, unless it possesses
326      * no SIMs on the device.
327      */
328     private Map<Integer, List<Integer>> mUserIdToAvailableSubs = new ConcurrentHashMap<>();
329 
330     /**
331      * Slot index/subscription map that automatically invalidate cache in
332      * {@link SubscriptionManager}.
333      *
334      * @param <K> The type of the key.
335      * @param <V> The type of the value.
336      */
337     @VisibleForTesting
338     public static class SubscriptionMap<K, V> extends ConcurrentHashMap<K, V> {
339         @Override
clear()340         public void clear() {
341             super.clear();
342             SubscriptionManager.invalidateSubscriptionManagerServiceCaches();
343         }
344 
345         @Override
put(K key, V value)346         public V put(K key, V value) {
347             V oldValue = super.put(key, value);
348             if (!Objects.equals(oldValue, value)) {
349                 SubscriptionManager.invalidateSubscriptionManagerServiceCaches();
350             }
351             return oldValue;
352         }
353 
354         @Override
remove(Object key)355         public V remove(Object key) {
356             V oldValue = super.remove(key);
357             if (oldValue != null) {
358                 SubscriptionManager.invalidateSubscriptionManagerServiceCaches();
359             }
360             return oldValue;
361         }
362     }
363 
364     /**
365      * Watched integer.
366      */
367     public static class WatchedInt {
368         protected int mValue;
369 
370         /**
371          * Constructor.
372          *
373          * @param initialValue The initial value.
374          */
WatchedInt(int initialValue)375         public WatchedInt(int initialValue) {
376             mValue = initialValue;
377         }
378 
379         /**
380          * @return The value.
381          */
get()382         public int get() {
383             return mValue;
384         }
385 
386         /**
387          * Set the value.
388          *
389          * @param newValue The new value.
390          *
391          * @return {@code true} if {@code newValue} is different from the existing value.
392          */
set(int newValue)393         public boolean set(int newValue) {
394             if (mValue != newValue) {
395                 mValue = newValue;
396                 SubscriptionManager.invalidateSubscriptionManagerServiceCaches();
397                 return true;
398             }
399             return false;
400         }
401     }
402 
403     /** Binder Wrapper for test mocking. */
404     @VisibleForTesting
405     public static class BinderWrapper {
getCallingUserHandle()406         @NonNull public UserHandle getCallingUserHandle() {
407             return Binder.getCallingUserHandle();
408         }
409     }
410 
411     /**
412      * This is the callback used for listening events from {@link SubscriptionManagerService}.
413      */
414     public static class SubscriptionManagerServiceCallback {
415         /** The executor of the callback. */
416         @NonNull
417         private final Executor mExecutor;
418 
419         /**
420          * Constructor
421          *
422          * @param executor The executor of the callback.
423          */
SubscriptionManagerServiceCallback(@onNull @allbackExecutor Executor executor)424         public SubscriptionManagerServiceCallback(@NonNull @CallbackExecutor Executor executor) {
425             mExecutor = executor;
426         }
427 
428         /**
429          * @return The executor of the callback.
430          */
431         @NonNull
432         @VisibleForTesting
getExecutor()433         public Executor getExecutor() {
434             return mExecutor;
435         }
436 
437         /**
438          * Invoke the callback from executor.
439          *
440          * @param runnable The callback method to invoke.
441          */
invokeFromExecutor(@onNull Runnable runnable)442         public void invokeFromExecutor(@NonNull Runnable runnable) {
443             mExecutor.execute(runnable);
444         }
445 
446         /**
447          * Called when subscription changed.
448          *
449          * @param subId The subscription id.
450          */
onSubscriptionChanged(int subId)451         public void onSubscriptionChanged(int subId) {}
452 
453         /**
454          * Called when {@link SubscriptionInfoInternal#areUiccApplicationsEnabled()} changed.
455          *
456          * @param subId The subscription id.
457          */
onUiccApplicationsEnabledChanged(int subId)458         public void onUiccApplicationsEnabledChanged(int subId) {}
459     }
460 
461     /**
462      * The constructor
463      *
464      * @param context The context
465      * @param looper The looper for the handler.
466      */
SubscriptionManagerService(@onNull Context context, @NonNull Looper looper, @NonNull FeatureFlags featureFlags)467     public SubscriptionManagerService(@NonNull Context context, @NonNull Looper looper,
468             @NonNull FeatureFlags featureFlags) {
469         logl("Created SubscriptionManagerService");
470         sInstance = this;
471         mContext = context;
472         mFeatureFlags = featureFlags;
473         mTelephonyManager = context.getSystemService(TelephonyManager.class);
474         mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
475         mEuiccManager = context.getSystemService(EuiccManager.class);
476         mAppOpsManager = context.getSystemService(AppOpsManager.class);
477         mPackageManager = context.getPackageManager();
478         mVendorApiLevel = SystemProperties.getInt(
479                 "ro.vendor.api_level", Build.VERSION.DEVICE_INITIAL_SDK_INT);
480 
481         mUiccController = UiccController.getInstance();
482         mHandler = new Handler(looper);
483 
484         HandlerThread backgroundThread = new HandlerThread(LOG_TAG);
485         backgroundThread.start();
486 
487         mBackgroundHandler = new Handler(backgroundThread.getLooper());
488 
489         mDefaultVoiceSubId = new WatchedInt(Settings.Global.getInt(mContext.getContentResolver(),
490                 Settings.Global.MULTI_SIM_VOICE_CALL_SUBSCRIPTION,
491                 SubscriptionManager.INVALID_SUBSCRIPTION_ID)) {
492             @Override
493             public boolean set(int newValue) {
494                 int oldValue = mValue;
495                 if (super.set(newValue)) {
496                     logl("Default voice subId changed from " + oldValue + " to " + newValue);
497                     Settings.Global.putInt(mContext.getContentResolver(),
498                             Settings.Global.MULTI_SIM_VOICE_CALL_SUBSCRIPTION, newValue);
499                     return true;
500                 }
501                 return false;
502             }
503         };
504 
505         mDefaultDataSubId = new WatchedInt(Settings.Global.getInt(mContext.getContentResolver(),
506                 Settings.Global.MULTI_SIM_DATA_CALL_SUBSCRIPTION,
507                 SubscriptionManager.INVALID_SUBSCRIPTION_ID)) {
508             @Override
509             public boolean set(int newValue) {
510                 int oldValue = mValue;
511                 if (super.set(newValue)) {
512                     logl("Default data subId changed from " + oldValue + " to " + newValue);
513                     Settings.Global.putInt(mContext.getContentResolver(),
514                             Settings.Global.MULTI_SIM_DATA_CALL_SUBSCRIPTION, newValue);
515                     return true;
516                 }
517                 return false;
518             }
519         };
520 
521         mDefaultSmsSubId = new WatchedInt(Settings.Global.getInt(mContext.getContentResolver(),
522                 Settings.Global.MULTI_SIM_SMS_SUBSCRIPTION,
523                 SubscriptionManager.INVALID_SUBSCRIPTION_ID)) {
524             @Override
525             public boolean set(int newValue) {
526                 int oldValue = mValue;
527                 if (super.set(newValue)) {
528                     logl("Default SMS subId changed from " + oldValue + " to " + newValue);
529                     Settings.Global.putInt(mContext.getContentResolver(),
530                             Settings.Global.MULTI_SIM_SMS_SUBSCRIPTION, newValue);
531                     return true;
532                 }
533                 return false;
534             }
535         };
536 
537         mDefaultSubId = new WatchedInt(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
538 
539         mSimState = new int[mTelephonyManager.getSupportedModemCount()];
540         Arrays.fill(mSimState, TelephonyManager.SIM_STATE_UNKNOWN);
541 
542         // Create a separate thread for subscription database manager. The database will be updated
543         // from a different thread.
544         HandlerThread handlerThread = new HandlerThread(LOG_TAG);
545         handlerThread.start();
546         mSubscriptionDatabaseManager = new SubscriptionDatabaseManager(context,
547                 handlerThread.getLooper(), mFeatureFlags,
548                 new SubscriptionDatabaseManagerCallback(mHandler::post) {
549                     /**
550                      * Called when database has been loaded into the cache.
551                      */
552                     @Override
553                     public void onInitialized() {
554                         log("Subscription database has been initialized.");
555                         for (int phoneId = 0; phoneId < mTelephonyManager.getSupportedModemCount()
556                                 ; phoneId++) {
557                             markSubscriptionsInactive(phoneId);
558                         }
559                     }
560 
561                     /**
562                      * Called when subscription changed.
563                      *
564                      * @param subId The subscription id.
565                      */
566                     @Override
567                     public void onSubscriptionChanged(int subId) {
568                         updateUserIdToAvailableSubs();
569 
570                         mSubscriptionManagerServiceCallbacks.forEach(
571                                 callback -> callback.invokeFromExecutor(
572                                         () -> callback.onSubscriptionChanged(subId)));
573 
574                         MultiSimSettingController.getInstance().notifySubscriptionInfoChanged();
575 
576                         TelephonyRegistryManager telephonyRegistryManager =
577                                 mContext.getSystemService(TelephonyRegistryManager.class);
578                         if (telephonyRegistryManager != null) {
579                             telephonyRegistryManager.notifySubscriptionInfoChanged();
580                         }
581 
582                         SubscriptionInfoInternal subInfo =
583                                 mSubscriptionDatabaseManager.getSubscriptionInfoInternal(subId);
584                         if (subInfo != null && subInfo.isOpportunistic()
585                                 && telephonyRegistryManager != null) {
586                             telephonyRegistryManager.notifyOpportunisticSubscriptionInfoChanged();
587                         }
588                     }
589                 });
590 
591         // Broadcast sub Id on service initialized.
592         broadcastSubId(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED,
593                 getDefaultDataSubId());
594         broadcastSubId(TelephonyIntents.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED,
595                 getDefaultVoiceSubId());
596         broadcastSubId(SubscriptionManager.ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED,
597                 getDefaultSmsSubId());
598         updateDefaultSubId();
599 
600         TelephonyServiceManager.ServiceRegisterer subscriptionServiceRegisterer =
601                 TelephonyFrameworkInitializer
602                         .getTelephonyServiceManager()
603                         .getSubscriptionServiceRegisterer();
604         if (subscriptionServiceRegisterer.get() == null) {
605             subscriptionServiceRegisterer.register(this);
606         }
607 
608         mHandler.post(() -> {
609             // EuiccController is created after SubscriptionManagerService. So we need to get
610             // the instance later in the handler.
611             if (mContext.getPackageManager().hasSystemFeature(
612                     PackageManager.FEATURE_TELEPHONY_EUICC)) {
613                 mEuiccController = EuiccController.get();
614             }
615         });
616 
617         SubscriptionManager.invalidateSubscriptionManagerServiceCaches();
618 
619         mContext.registerReceiver(new BroadcastReceiver() {
620             @Override
621             public void onReceive(Context context, Intent intent) {
622                 updateEmbeddedSubscriptions();
623             }
624         }, new IntentFilter(Intent.ACTION_USER_UNLOCKED));
625         logl("Registered iSub service");
626     }
627 
628     /**
629      * @return The singleton instance of {@link SubscriptionManagerService}.
630      */
631     @NonNull
getInstance()632     public static SubscriptionManagerService getInstance() {
633         return sInstance;
634     }
635 
636     /**
637      * Check if the calling package can manage the subscription group.
638      *
639      * @param groupUuid a UUID assigned to the subscription group.
640      * @param callingPackage the package making the IPC.
641      *
642      * @return {@code true} if calling package is the owner of or has carrier privileges for all
643      * subscriptions in the group.
644      */
canPackageManageGroup(@onNull ParcelUuid groupUuid, @NonNull String callingPackage)645     private boolean canPackageManageGroup(@NonNull ParcelUuid groupUuid,
646             @NonNull String callingPackage) {
647         if (groupUuid == null) {
648             throw new IllegalArgumentException("Invalid groupUuid");
649         }
650 
651         if (TextUtils.isEmpty(callingPackage)) {
652             throw new IllegalArgumentException("Empty callingPackage");
653         }
654 
655         List<SubscriptionInfo> infoList;
656 
657         // Getting all subscriptions in the group.
658         infoList = mSubscriptionDatabaseManager.getAllSubscriptions().stream()
659                 .filter(subInfo -> subInfo.getGroupUuid().equals(groupUuid.toString()))
660                 .map(SubscriptionInfoInternal::toSubscriptionInfo)
661                 .collect(Collectors.toList());
662 
663         // If the group does not exist, then by default the UUID is up for grabs so no need to
664         // restrict management of a group (that someone may be attempting to create).
665         if (ArrayUtils.isEmpty(infoList)) {
666             return true;
667         }
668 
669         // If the calling package is the group owner, skip carrier permission check and return
670         // true as it was done before.
671         if (callingPackage.equals(infoList.get(0).getGroupOwner())) return true;
672 
673         // Check carrier privilege for all subscriptions in the group.
674         return (checkCarrierPrivilegeOnSubList(infoList.stream()
675                 .mapToInt(SubscriptionInfo::getSubscriptionId).toArray(), callingPackage));
676     }
677 
678     /**
679      * Helper function to check if the caller has carrier privilege permissions on a list of subId.
680      * The check can either be processed against access rules on currently active SIM cards, or
681      * the access rules we keep in our database for currently inactive SIMs.
682      *
683      * @param subIdList List of subscription ids.
684      * @param callingPackage The package making the call.
685      *
686      * @throws IllegalArgumentException if the some subId is invalid or doesn't exist.
687      *
688      * @return {@code true} if checking passes on all subId, {@code false} otherwise.
689      */
checkCarrierPrivilegeOnSubList(@onNull int[] subIdList, @NonNull String callingPackage)690     private boolean checkCarrierPrivilegeOnSubList(@NonNull int[] subIdList,
691             @NonNull String callingPackage) {
692         for (int subId : subIdList) {
693             SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager
694                     .getSubscriptionInfoInternal(subId);
695             if (subInfo == null) {
696                 loge("checkCarrierPrivilegeOnSubList: subId " + subId + " does not exist.");
697                 return false;
698             }
699 
700             if (subInfo.isActive()) {
701                 if (!mTelephonyManager.hasCarrierPrivileges(subId)) {
702                     loge("checkCarrierPrivilegeOnSubList: Does not have carrier privilege on sub "
703                             + subId);
704                     return false;
705                 }
706             } else {
707                 if (!mSubscriptionManager.canManageSubscription(subInfo.toSubscriptionInfo(),
708                         callingPackage)) {
709                     loge("checkCarrierPrivilegeOnSubList: cannot manage sub " + subId);
710                     return false;
711                 }
712             }
713         }
714 
715         return true;
716     }
717 
718     /**
719      * Sync the settings from specified subscription to all grouped subscriptions.
720      *
721      * @param subId The subscription id of the referenced subscription.
722      */
syncGroupedSetting(int subId)723     public void syncGroupedSetting(int subId) {
724         mHandler.post(() -> {
725             SubscriptionInfoInternal reference = mSubscriptionDatabaseManager
726                     .getSubscriptionInfoInternal(subId);
727             if (reference == null) {
728                 loge("syncSettings: Can't find subscription info for sub " + subId);
729                 return;
730             }
731 
732             mSubscriptionDatabaseManager.syncToGroup(subId);
733         });
734     }
735 
736     /**
737      * Check whether the {@code callingPackage} has access to the phone number on the specified
738      * {@code subId} or not.
739      *
740      * @param subId The subscription id.
741      * @param callingPackage The package making the call.
742      * @param callingFeatureId The feature in the package.
743      * @param message Message to include in the exception or NoteOp.
744      *
745      * @return {@code true} if the caller has phone number access.
746      */
hasPhoneNumberAccess(int subId, @NonNull String callingPackage, @Nullable String callingFeatureId, @Nullable String message)747     private boolean hasPhoneNumberAccess(int subId, @NonNull String callingPackage,
748             @Nullable String callingFeatureId, @Nullable String message) {
749         try {
750             return TelephonyPermissions.checkCallingOrSelfReadPhoneNumber(mContext, subId,
751                     callingPackage, callingFeatureId, message);
752         } catch (SecurityException e) {
753             return false;
754         }
755     }
756 
757     /**
758      * Check whether the {@code callingPackage} has access to subscriber identifiers on the
759      * specified {@code subId} or not.
760      *
761      * @param subId The subscription id.
762      * @param callingPackage The package making the call.
763      * @param callingFeatureId The feature in the package.
764      * @param message Message to include in the exception or NoteOp.
765      * @param reportFailure Indicates if failure should be reported.
766      *
767      * @return {@code true} if the caller has identifier access.
768      */
hasSubscriberIdentifierAccess(int subId, @NonNull String callingPackage, @Nullable String callingFeatureId, @Nullable String message, boolean reportFailure)769     private boolean hasSubscriberIdentifierAccess(int subId, @NonNull String callingPackage,
770             @Nullable String callingFeatureId, @Nullable String message, boolean reportFailure) {
771         try {
772             return TelephonyPermissions.checkCallingOrSelfReadSubscriberIdentifiers(mContext, subId,
773                     callingPackage, callingFeatureId, message, reportFailure);
774         } catch (SecurityException e) {
775             // A SecurityException indicates that the calling package is targeting at least the
776             // minimum level that enforces identifier access restrictions and the new access
777             // requirements are not met.
778             return false;
779         }
780     }
781 
782     /**
783      * Conditionally removes identifiers from the provided {@link SubscriptionInfo} if the {@code
784      * callingPackage} does not meet the access requirements for identifiers and returns the
785      * potentially modified object.
786      *
787      * <p>
788      * If the caller does not have {@link Manifest.permission#READ_PHONE_NUMBERS} permission,
789      * {@link SubscriptionInfo#getNumber()} will return empty string.
790      * If the caller does not have {@link Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER},
791      * {@link SubscriptionInfo#getIccId()} and {@link SubscriptionInfo#getCardString()} will return
792      * empty string, and {@link SubscriptionInfo#getGroupUuid()} will return {@code null}.
793      *
794      * @param subInfo The subscription info.
795      * @param callingPackage The package making the call.
796      * @param callingFeatureId The feature in the package.
797      * @param message Message to include in the exception or NoteOp.
798      *
799      * @return The modified {@link SubscriptionInfo} depending on caller's permission.
800      */
801     @NonNull
conditionallyRemoveIdentifiers(@onNull SubscriptionInfo subInfo, @NonNull String callingPackage, @Nullable String callingFeatureId, @Nullable String message)802     private SubscriptionInfo conditionallyRemoveIdentifiers(@NonNull SubscriptionInfo subInfo,
803             @NonNull String callingPackage, @Nullable String callingFeatureId,
804             @Nullable String message) {
805         int subId = subInfo.getSubscriptionId();
806         boolean hasIdentifierAccess = hasSubscriberIdentifierAccess(subId, callingPackage,
807                 callingFeatureId, message, true);
808         boolean hasPhoneNumberAccess = hasPhoneNumberAccess(subId, callingPackage,
809                 callingFeatureId, message);
810 
811         if (hasIdentifierAccess && hasPhoneNumberAccess) {
812             return subInfo;
813         }
814 
815         SubscriptionInfo.Builder result = new SubscriptionInfo.Builder(subInfo);
816         if (!hasIdentifierAccess) {
817             result.setIccId(null);
818             result.setCardString(null);
819             result.setGroupUuid(null);
820         }
821 
822         if (!hasPhoneNumberAccess) {
823             result.setNumber(null);
824         }
825         return result.build();
826     }
827 
828     /**
829      * @return The list of ICCIDs from the inserted physical SIMs.
830      */
831     @NonNull
getIccIdsOfInsertedPhysicalSims()832     private List<String> getIccIdsOfInsertedPhysicalSims() {
833         List<String> iccidList = new ArrayList<>();
834         UiccSlot[] uiccSlots = mUiccController.getUiccSlots();
835         if (uiccSlots == null) return iccidList;
836 
837         for (UiccSlot uiccSlot : uiccSlots) {
838             if (uiccSlot != null && uiccSlot.getCardState() != null
839                     && uiccSlot.getCardState().isCardPresent() && !uiccSlot.isEuicc()) {
840                 // Non euicc slots will have single port, so use default port index.
841                 String iccId = uiccSlot.getIccId(TelephonyManager.DEFAULT_PORT_INDEX);
842                 if (!TextUtils.isEmpty(iccId)) {
843                     iccidList.add(IccUtils.stripTrailingFs(iccId));
844                 }
845             }
846         }
847 
848         return iccidList;
849     }
850 
851     /**
852      * Set the subscription carrier id.
853      *
854      * @param subId Subscription id.
855      * @param carrierId The carrier id.
856      *
857      * @throws IllegalArgumentException if {@code subId} is invalid or the subscription does not
858      * exist.
859      *
860      * @see TelephonyManager#getSimCarrierId()
861      */
setCarrierId(int subId, int carrierId)862     public void setCarrierId(int subId, int carrierId) {
863         // This can throw IllegalArgumentException if the subscription does not exist.
864         try {
865             mSubscriptionDatabaseManager.setCarrierId(subId, carrierId);
866         } catch (IllegalArgumentException e) {
867             loge("setCarrierId: invalid subId=" + subId);
868         }
869     }
870 
871     /**
872      * Set MCC/MNC by subscription id.
873      *
874      * @param mccMnc MCC/MNC associated with the subscription.
875      * @param subId The subscription id.
876      */
setMccMnc(int subId, @NonNull String mccMnc)877     public void setMccMnc(int subId, @NonNull String mccMnc) {
878         // This can throw IllegalArgumentException if the subscription does not exist.
879         try {
880             mSubscriptionDatabaseManager.setMcc(subId, mccMnc.substring(0, 3));
881             mSubscriptionDatabaseManager.setMnc(subId, mccMnc.substring(3));
882         } catch (IllegalArgumentException e) {
883             loge("setMccMnc: invalid subId=" + subId);
884         }
885     }
886 
887     /**
888      * Set whether the subscription ID supports oem satellite or not.
889      *
890      * @param subId The subscription ID.
891      * @param isNtn {@code true} Requested subscription ID supports oem satellite service,
892      * {@code false} otherwise.
893      */
setNtn(int subId, boolean isNtn)894     public void setNtn(int subId, boolean isNtn) {
895         if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
896             return;
897         }
898 
899         // This can throw IllegalArgumentException if the subscription does not exist.
900         try {
901             mSubscriptionDatabaseManager.setNtn(subId, (isNtn ? 1 : 0));
902         } catch (IllegalArgumentException e) {
903             loge("setOnlyNonTerrestrialNetwork: invalid subId=" + subId);
904         }
905     }
906 
907     /**
908      * Set ISO country code by subscription id.
909      *
910      * @param iso ISO country code associated with the subscription.
911      * @param subId The subscription id.
912      */
setCountryIso(int subId, @NonNull String iso)913     public void setCountryIso(int subId, @NonNull String iso) {
914         // This can throw IllegalArgumentException if the subscription does not exist.
915         try {
916             mSubscriptionDatabaseManager.setCountryIso(subId, iso);
917         } catch (IllegalArgumentException e) {
918             loge("setCountryIso: invalid subId=" + subId);
919         }
920     }
921 
922     /**
923      * Set the name displayed to the user that identifies subscription provider name. This name
924      * is the SPN displayed in status bar and many other places. Can't be renamed by the user.
925      *
926      * @param subId Subscription id.
927      * @param carrierName The carrier name.
928      */
setCarrierName(int subId, @NonNull String carrierName)929     public void setCarrierName(int subId, @NonNull String carrierName) {
930         // This can throw IllegalArgumentException if the subscription does not exist.
931         try {
932             mSubscriptionDatabaseManager.setCarrierName(subId, carrierName);
933         } catch (IllegalArgumentException e) {
934             loge("setCarrierName: invalid subId=" + subId);
935         }
936     }
937 
938     /**
939      * Set the group owner on the subscription
940      *
941      * <p> Note: This only sets the group owner field and doesn't update other relevant fields.
942      * Prefer to call {@link #addSubscriptionsIntoGroup}.
943      *
944      * @param subId Subscription id.
945      * @param groupOwner The group owner to assign to the subscription
946      *
947      * @throws SecurityException if the caller does not have required permissions.
948      */
949     @Override
950     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
setGroupOwner(int subId, @NonNull String groupOwner)951     public void setGroupOwner(int subId, @NonNull String groupOwner) {
952         enforcePermissions("setGroupOwner", Manifest.permission.MODIFY_PHONE_STATE);
953         try {
954             mSubscriptionDatabaseManager.setGroupOwner(
955                     subId,
956                     groupOwner);
957         } catch (IllegalArgumentException e) {
958             loge("setManaged: invalid subId=" + subId);
959         }
960     }
961 
962     /**
963      * Set last used TP message reference.
964      *
965      * @param subId Subscription id.
966      * @param lastUsedTPMessageReference Last used TP message reference.
967      */
setLastUsedTPMessageReference(int subId, int lastUsedTPMessageReference)968     public void setLastUsedTPMessageReference(int subId, int lastUsedTPMessageReference) {
969         // This can throw IllegalArgumentException if the subscription does not exist.
970         try {
971             mSubscriptionDatabaseManager.setLastUsedTPMessageReference(
972                     subId, lastUsedTPMessageReference);
973         } catch (IllegalArgumentException e) {
974             loge("setLastUsedTPMessageReference: invalid subId=" + subId);
975         }
976     }
977 
978     /**
979      * Set the enabled mobile data policies.
980      *
981      * @param subId Subscription id.
982      * @param enabledMobileDataPolicies The enabled mobile data policies.
983      */
setEnabledMobileDataPolicies(int subId, @NonNull String enabledMobileDataPolicies)984     public void setEnabledMobileDataPolicies(int subId, @NonNull String enabledMobileDataPolicies) {
985         // This can throw IllegalArgumentException if the subscription does not exist.
986         try {
987             mSubscriptionDatabaseManager.setEnabledMobileDataPolicies(
988                     subId, enabledMobileDataPolicies);
989         } catch (IllegalArgumentException e) {
990             loge("setEnabledMobileDataPolicies: invalid subId=" + subId);
991         }
992     }
993 
994     /**
995      * Set the phone number retrieved from IMS.
996      *
997      * @param subId Subscription id.
998      * @param numberFromIms The phone number retrieved from IMS.
999      */
setNumberFromIms(int subId, @NonNull String numberFromIms)1000     public void setNumberFromIms(int subId, @NonNull String numberFromIms) {
1001         // This can throw IllegalArgumentException if the subscription does not exist.
1002         try {
1003             mSubscriptionDatabaseManager.setNumberFromIms(subId, numberFromIms);
1004         } catch (IllegalArgumentException e) {
1005             loge("setNumberFromIms: invalid subId=" + subId);
1006         }
1007     }
1008 
1009     /**
1010      * Mark all subscriptions on this SIM slot index inactive.
1011      *
1012      * @param simSlotIndex The logical SIM slot index (i.e. phone id).
1013      */
markSubscriptionsInactive(int simSlotIndex)1014     public void markSubscriptionsInactive(int simSlotIndex) {
1015         logl("markSubscriptionsInactive: slot " + simSlotIndex);
1016         mSlotIndexToSubId.remove(simSlotIndex);
1017         mSubscriptionDatabaseManager.getAllSubscriptions().stream()
1018                 .filter(subInfo -> subInfo.getSimSlotIndex() == simSlotIndex)
1019                 .forEach(subInfo -> {
1020                     mSubscriptionDatabaseManager.setSimSlotIndex(subInfo.getSubscriptionId(),
1021                             SubscriptionManager.INVALID_SIM_SLOT_INDEX);
1022                     // Sometime even though slot-port is inactive, proper iccid will be present,
1023                     // hence retry the port index from UiccSlot. (Pre-U behavior)
1024                     mSubscriptionDatabaseManager.setPortIndex(subInfo.getSubscriptionId(),
1025                             getPortIndex(subInfo.getIccId()));
1026                 });
1027         updateGroupDisabled();
1028         logl("markSubscriptionsInactive: current mapping " + slotMappingToString());
1029     }
1030 
1031     /**
1032      * This is only for internal use and the returned priority is arbitrary. The idea is to give a
1033      * higher value to name source that has higher priority to override other name sources.
1034      *
1035      * @param nameSource Source of display name.
1036      *
1037      * @return The priority. Higher value means higher priority.
1038      */
getNameSourcePriority(@imDisplayNameSource int nameSource)1039     private static int getNameSourcePriority(@SimDisplayNameSource int nameSource) {
1040         int index = Arrays.asList(
1041                 SubscriptionManager.NAME_SOURCE_UNKNOWN,
1042                 SubscriptionManager.NAME_SOURCE_CARRIER_ID,
1043                 SubscriptionManager.NAME_SOURCE_SIM_PNN,
1044                 SubscriptionManager.NAME_SOURCE_SIM_SPN,
1045                 SubscriptionManager.NAME_SOURCE_CARRIER,
1046                 SubscriptionManager.NAME_SOURCE_USER_INPUT // user has highest priority.
1047         ).indexOf(nameSource);
1048         return Math.max(0, index);
1049     }
1050 
1051     /**
1052      * Randomly pick a color from {@link R.array#sim_colors}.
1053      *
1054      * @return The selected color for the subscription.
1055      */
getColor()1056     private int getColor() {
1057         int[] colors = mContext.getResources().getIntArray(com.android.internal.R.array.sim_colors);
1058         if (colors.length == 0) return 0xFFFFFFFF; // white
1059         Random rand = new Random();
1060         return colors[rand.nextInt(colors.length)];
1061     }
1062 
1063     /**
1064      * Get the port index by ICCID.
1065      *
1066      * @param iccId The ICCID.
1067      * @return The port index.
1068      */
getPortIndex(@onNull String iccId)1069     private int getPortIndex(@NonNull String iccId) {
1070         UiccSlot[] slots = mUiccController.getUiccSlots();
1071         for (UiccSlot slot : slots) {
1072             if (slot != null) {
1073                 int portIndex = slot.getPortIndexFromIccId(iccId);
1074                 if (portIndex != TelephonyManager.INVALID_PORT_INDEX) {
1075                     return portIndex;
1076                 }
1077             }
1078         }
1079         return TelephonyManager.INVALID_PORT_INDEX;
1080     }
1081 
1082     /**
1083      * Insert a new subscription into the database.
1084      *
1085      * @param iccId The ICCID.
1086      * @param slotIndex The logical SIM slot index (i.e. phone id).
1087      * @param displayName The display name.
1088      * @param subscriptionType The subscription type.
1089      *
1090      * @return The subscription id.
1091      */
insertSubscriptionInfo(@onNull String iccId, int slotIndex, @Nullable String displayName, @SubscriptionType int subscriptionType)1092     private int insertSubscriptionInfo(@NonNull String iccId, int slotIndex,
1093             @Nullable String displayName, @SubscriptionType int subscriptionType) {
1094         String defaultAllowNetworkTypes = Phone.convertAllowedNetworkTypeMapIndexToDbName(
1095                 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER) + "="
1096                 + RadioAccessFamily.getRafFromNetworkType(RILConstants.PREFERRED_NETWORK_MODE);
1097         SubscriptionInfoInternal.Builder builder = new SubscriptionInfoInternal.Builder()
1098                 .setIccId(iccId)
1099                 .setCardString(iccId)
1100                 .setSimSlotIndex(slotIndex)
1101                 .setType(subscriptionType)
1102                 .setIconTint(getColor())
1103                 .setAllowedNetworkTypesForReasons(defaultAllowNetworkTypes);
1104         if (displayName != null) {
1105             builder.setDisplayName(displayName);
1106         }
1107 
1108         int subId = mSubscriptionDatabaseManager.insertSubscriptionInfo(builder.build());
1109         logl("insertSubscriptionInfo: Inserted a new subscription. subId=" + subId
1110                 + ", slotIndex=" + slotIndex + ", iccId=" + SubscriptionInfo.getPrintableId(iccId)
1111                 + ", displayName=" + displayName + ", type="
1112                 + SubscriptionManager.subscriptionTypeToString(subscriptionType));
1113         return subId;
1114     }
1115 
1116     /**
1117      * Pull the embedded subscription from {@link EuiccController} for the eUICC with the given list
1118      * of card IDs {@code cardIds}.
1119      *
1120      * @param cardIds The card ids of the embedded subscriptions.
1121      * @param callback Callback to be called upon completion.
1122      */
updateEmbeddedSubscriptions(@onNull List<Integer> cardIds, @Nullable Runnable callback)1123     public void updateEmbeddedSubscriptions(@NonNull List<Integer> cardIds,
1124             @Nullable Runnable callback) {
1125         // Run this on a background thread.
1126         mBackgroundHandler.post(() -> {
1127             // Do nothing if eUICCs are disabled. (Previous entries may remain in the cache, but
1128             // they are filtered out of list calls as long as EuiccManager.isEnabled returns false).
1129             if (mEuiccManager == null || !mEuiccManager.isEnabled() || mEuiccController == null) {
1130                 loge("updateEmbeddedSubscriptions: eUICC not enabled");
1131                 if (callback != null) {
1132                     callback.run();
1133                 }
1134                 return;
1135             }
1136 
1137             Set<Integer> embeddedSubs = new ArraySet<>();
1138             log("updateEmbeddedSubscriptions: start to get euicc profiles.");
1139 
1140             for (UiccSlot slot : mUiccController.getUiccSlots()) {
1141                 if (slot != null) {
1142                     log("  " + slot);
1143                 }
1144             }
1145 
1146             // The flag indicating getting successful result from EuiccController.
1147             boolean isProfileUpdateSuccessful = false;
1148 
1149             for (int cardId : cardIds) {
1150                 GetEuiccProfileInfoListResult result = mEuiccController
1151                         .blockingGetEuiccProfileInfoList(cardId);
1152                 logl("updateEmbeddedSubscriptions: cardId=" + cardId + ", result=" + result);
1153                 if (result == null) {
1154                     //TODO: Add back-off retry in the future if needed.
1155                     loge("Failed to get euicc profiles.");
1156                     continue;
1157                 }
1158 
1159                 if (result.getResult() != EuiccService.RESULT_OK) {
1160                     loge("Failed to get euicc profile info. result="
1161                             + EuiccService.resultToString(result.getResult()));
1162                     continue;
1163                 }
1164 
1165                 isProfileUpdateSuccessful = true;
1166 
1167                 if (result.getProfiles() == null || result.getProfiles().isEmpty()) {
1168                     loge("No profiles returned.");
1169                     continue;
1170                 }
1171 
1172                 final boolean isRemovable = result.getIsRemovable();
1173 
1174                 for (EuiccProfileInfo embeddedProfile : result.getProfiles()) {
1175                     SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager
1176                             .getSubscriptionInfoInternalByIccId(embeddedProfile.getIccid());
1177 
1178                     // The subscription does not exist in the database. Insert a new one here.
1179                     if (subInfo == null) {
1180                         int subId = insertSubscriptionInfo(embeddedProfile.getIccid(),
1181                                 SubscriptionManager.INVALID_SIM_SLOT_INDEX,
1182                                 null, SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM);
1183                         mSubscriptionDatabaseManager.setDisplayName(subId, mContext.getResources()
1184                                 .getString(R.string.default_card_name, getCardNumber(subId)));
1185                         subInfo = mSubscriptionDatabaseManager.getSubscriptionInfoInternal(subId);
1186                     }
1187 
1188                     int nameSource = subInfo.getDisplayNameSource();
1189                     int carrierId = subInfo.getCarrierId();
1190 
1191                     SubscriptionInfoInternal.Builder builder = new SubscriptionInfoInternal
1192                             .Builder(subInfo);
1193 
1194                     builder.setEmbedded(1);
1195 
1196                     List<UiccAccessRule> ruleList = embeddedProfile.getUiccAccessRules();
1197                     if (ruleList != null && !ruleList.isEmpty()) {
1198                         builder.setNativeAccessRules(embeddedProfile.getUiccAccessRules());
1199                     }
1200                     builder.setRemovableEmbedded(isRemovable);
1201 
1202                     // override DISPLAY_NAME if the priority of existing nameSource is <= carrier
1203                     String nickName = embeddedProfile.getNickname();
1204                     if (nickName != null
1205                             && getNameSourcePriority(nameSource) <= getNameSourcePriority(
1206                                     SubscriptionManager.NAME_SOURCE_CARRIER)) {
1207                         builder.setDisplayName(nickName);
1208                         builder.setDisplayNameSource(SubscriptionManager.NAME_SOURCE_CARRIER);
1209                     }
1210 
1211                     boolean isSatelliteSpn = false;
1212                     if (mFeatureFlags.oemEnabledSatelliteFlag() ) {
1213                         if (isSatelliteSpn(embeddedProfile.getServiceProviderName())) {
1214                             isSatelliteSpn = true;
1215                             builder.setOnlyNonTerrestrialNetwork(1);
1216                         }
1217                     } else {
1218                         log("updateEmupdateEmbeddedSubscriptions: oemEnabledSatelliteFlag is "
1219                                 + "disabled");
1220                     }
1221 
1222                     if (android.os.Build.isDebuggable() &&
1223                             SystemProperties.getInt("telephony.test.bootstrap_cid", -2)
1224                                 == carrierId) {
1225                         // Force set as provisioning profile for test purpose
1226                         log("Hardcording as bootstrap subscription for cid=" + carrierId);
1227                         builder.setProfileClass(SimInfo.PROFILE_CLASS_PROVISIONING);
1228                     } else {
1229                         builder.setProfileClass(embeddedProfile.getProfileClass());
1230                     }
1231                     builder.setPortIndex(getPortIndex(embeddedProfile.getIccid()));
1232 
1233                     CarrierIdentifier cid = embeddedProfile.getCarrierIdentifier();
1234                     if (cid != null) {
1235                         // Due to the limited subscription information, carrier id identified here
1236                         // might not be accurate compared with CarrierResolver. Only update carrier
1237                         // id if there is no valid carrier id present.
1238                         if (carrierId == TelephonyManager.UNKNOWN_CARRIER_ID) {
1239                             builder.setCarrierId(CarrierResolver
1240                                     .getCarrierIdFromIdentifier(mContext, cid));
1241                         }
1242                         String mcc = cid.getMcc();
1243                         String mnc = cid.getMnc();
1244                         builder.setMcc(mcc);
1245                         builder.setMnc(mnc);
1246                         if (mFeatureFlags.oemEnabledSatelliteFlag() && !isSatelliteSpn) {
1247                             builder.setOnlyNonTerrestrialNetwork(
1248                                     isSatellitePlmn(mcc + mnc) ? 1 : 0);
1249                         }
1250                     }
1251                     // If cardId = unsupported or un-initialized, we have no reason to update DB.
1252                     // Additionally, if the device does not support cardId for default eUICC, the
1253                     // CARD_ID field should not contain the EID
1254                     if (cardId >= 0 && mUiccController.getCardIdForDefaultEuicc()
1255                             != TelephonyManager.UNSUPPORTED_CARD_ID) {
1256                         builder.setCardId(cardId);
1257                         builder.setCardString(mUiccController.convertToCardString(cardId));
1258                     }
1259 
1260                     if (mFeatureFlags.supportPsimToEsimConversion()) {
1261                         builder.setTransferStatus(subInfo.getTransferStatus());
1262                     }
1263                     embeddedSubs.add(subInfo.getSubscriptionId());
1264 
1265                     subInfo = builder.build();
1266                     log("updateEmbeddedSubscriptions: update subscription " + subInfo);
1267                     mSubscriptionDatabaseManager.updateSubscription(subInfo);
1268                 }
1269             }
1270 
1271             // Marked the previous embedded subscriptions non-embedded if the latest profiles do
1272             // not include them anymore.
1273             if (isProfileUpdateSuccessful) {
1274                 // embeddedSubs contains all the existing embedded subs queried from EuiccManager,
1275                 // including active or inactive. If there are any embedded subscription in the
1276                 // database that is not in embeddedSubs, mark them as non-embedded. These were
1277                 // deleted embedded subscriptions, so we treated them as non-embedded (pre-U
1278                 // behavior) and they don't show up in Settings SIM page.
1279                 mSubscriptionDatabaseManager.getAllSubscriptions().stream()
1280                         .filter(SubscriptionInfoInternal::isEmbedded)
1281                         .filter(subInfo -> !embeddedSubs.contains(subInfo.getSubscriptionId()))
1282                         .forEach(subInfo -> {
1283                             logl("updateEmbeddedSubscriptions: Mark the deleted sub "
1284                                     + subInfo.getSubscriptionId() + " as non-embedded.");
1285                             mSubscriptionDatabaseManager.setEmbedded(
1286                                     subInfo.getSubscriptionId(), false);
1287                         });
1288                 if (mSubscriptionDatabaseManager.getAllSubscriptions().stream()
1289                         .anyMatch(subInfo -> subInfo.isEmbedded()
1290                                 && subInfo.isActive()
1291                                 && subInfo.getPortIndex()
1292                                 == TelephonyManager.INVALID_PORT_INDEX
1293                                 && mSimState[subInfo.getSimSlotIndex()]
1294                                 == TelephonyManager.SIM_STATE_LOADED)) {
1295                     //Report Anomaly if invalid portIndex is updated in Active subscriptions
1296                     AnomalyReporter.reportAnomaly(
1297                             UUID.fromString("38fdf63c-3bd9-4fc2-ad33-a20246a32fa7"),
1298                             "SubscriptionManagerService: Found Invalid portIndex"
1299                                     + " in active subscriptions");
1300                 }
1301             } else {
1302                 loge("The eSIM profiles update was not successful.");
1303             }
1304             log("updateEmbeddedSubscriptions: Finished embedded subscription update.");
1305             // The runnable will be executed in the main thread. Pre Android-U behavior.
1306             mHandler.post(() -> {
1307                 if (callback != null) {
1308                     callback.run();
1309                 }
1310             });
1311         });
1312     }
1313 
1314     /**
1315      * Update embedded subscriptions from {@link EuiccController}.
1316      */
updateEmbeddedSubscriptions()1317     private void updateEmbeddedSubscriptions() {
1318         UiccSlot[] uiccSlots = mUiccController.getUiccSlots();
1319         if (uiccSlots != null) {
1320             List<Integer> cardIds = new ArrayList<>();
1321             for (UiccSlot uiccSlot : uiccSlots) {
1322                 if (uiccSlot != null && uiccSlot.isEuicc() && uiccSlot.getUiccCard() != null) {
1323                     int cardId = mUiccController.convertToPublicCardId(
1324                             uiccSlot.getUiccCard().getCardId());
1325                     cardIds.add(cardId);
1326                 }
1327             }
1328             if (!cardIds.isEmpty()) {
1329                 updateEmbeddedSubscriptions(cardIds, null);
1330             }
1331         }
1332     }
1333 
1334     /**
1335      * Check if the SIM application is enabled on the card or not.
1336      *
1337      * @param phoneId The phone id.
1338      *
1339      * @return {@code true} if the application is enabled.
1340      */
areUiccAppsEnabledOnCard(int phoneId)1341     public boolean areUiccAppsEnabledOnCard(int phoneId) {
1342         // When uicc apps are disabled(supported in IRadio 1.5), we will still get IccId from
1343         // cardStatus (since IRadio 1.2). And upon cardStatus change we'll receive another
1344         // handleSimNotReady so this will be evaluated again.
1345         UiccSlot slot = mUiccController.getUiccSlotForPhone(phoneId);
1346         if (slot == null) return false;
1347         UiccPort port = mUiccController.getUiccPort(phoneId);
1348         String iccId = (port == null) ? null : port.getIccId();
1349         if (iccId == null) {
1350             return false;
1351         }
1352 
1353         SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager
1354                 .getSubscriptionInfoInternalByIccId(IccUtils.stripTrailingFs(iccId));
1355         return subInfo != null && subInfo.areUiccApplicationsEnabled();
1356     }
1357 
1358     /**
1359      * Get ICCID by phone id.
1360      *
1361      * @param phoneId The phone id (i.e. Logical SIM slot index.)
1362      *
1363      * @return The ICCID. Empty string if not available.
1364      */
1365     @NonNull
getIccId(int phoneId)1366     private String getIccId(int phoneId) {
1367         UiccPort port = mUiccController.getUiccPort(phoneId);
1368         return (port == null) ? "" : TextUtils.emptyIfNull(
1369                 IccUtils.stripTrailingFs(port.getIccId()));
1370     }
1371 
1372     /**
1373      * @return {@code true} if all the need-to-be-loaded subscriptions from SIM slots are already
1374      * loaded. {@code false} if more than one are still being loaded.
1375      */
areAllSubscriptionsLoaded()1376     private boolean areAllSubscriptionsLoaded() {
1377         for (int phoneId = 0; phoneId < mTelephonyManager.getActiveModemCount(); phoneId++) {
1378             UiccSlot slot = mUiccController.getUiccSlotForPhone(phoneId);
1379             if (slot == null) {
1380                 log("areAllSubscriptionsLoaded: slot is null. phoneId=" + phoneId);
1381                 return false;
1382             }
1383             if (!slot.isActive()) {
1384                 log("areAllSubscriptionsLoaded: slot is inactive. phoneId=" + phoneId);
1385                 return false;
1386             }
1387             if (slot.isEuicc() && mUiccController.getUiccPort(phoneId) == null) {
1388                 log("Wait for port corresponding to phone " + phoneId + " to be active, portIndex "
1389                         + "is " + slot.getPortIndexFromPhoneId(phoneId));
1390                 return false;
1391             }
1392 
1393             if (mSimState[phoneId] == TelephonyManager.SIM_STATE_NOT_READY) {
1394                 // Check if this is the final state.
1395                 IccCard iccCard = PhoneFactory.getPhone(phoneId).getIccCard();
1396                 if (!iccCard.isEmptyProfile() && areUiccAppsEnabledOnCard(phoneId)) {
1397                     log("areAllSubscriptionsLoaded: NOT_READY is not a final state.");
1398                     return false;
1399                 }
1400             }
1401 
1402             if (mSimState[phoneId] == TelephonyManager.SIM_STATE_UNKNOWN) {
1403                 log("areAllSubscriptionsLoaded: SIM " + phoneId + " state is still unknown.");
1404                 return false;
1405             }
1406         }
1407 
1408         return true;
1409     }
1410 
1411     /**
1412      * Update the subscription on the logical SIM slot index (i.e. phone id).
1413      *
1414      * @param phoneId The phone id (i.e. Logical SIM slot index)
1415      */
updateSubscription(int phoneId)1416     private void updateSubscription(int phoneId) {
1417         int simState = mSimState[phoneId];
1418         log("updateSubscription: phoneId=" + phoneId + ", simState="
1419                 + TelephonyManager.simStateToString(simState));
1420         for (UiccSlot slot : mUiccController.getUiccSlots()) {
1421             if (slot != null) {
1422                 log("  " + slot);
1423             }
1424         }
1425 
1426         if (simState == TelephonyManager.SIM_STATE_ABSENT) {
1427             SatelliteController satelliteController = SatelliteController.getInstance();
1428             boolean isSatelliteEnabledOrBeingEnabled = false;
1429             if (satelliteController != null) {
1430                 isSatelliteEnabledOrBeingEnabled = satelliteController.isSatelliteEnabled()
1431                         || satelliteController.isSatelliteBeingEnabled();
1432             }
1433 
1434             if (!isSatelliteEnabledOrBeingEnabled) {
1435                 // Re-enable the pSIM when it's removed, so it will be in enabled state when it gets
1436                 // re-inserted again. (pre-U behavior)
1437                 List<String> iccIds = getIccIdsOfInsertedPhysicalSims();
1438                 mSubscriptionDatabaseManager.getAllSubscriptions().stream()
1439                         .filter(subInfo -> !iccIds.contains(subInfo.getIccId())
1440                                 && !subInfo.isEmbedded())
1441                         .forEach(subInfo -> {
1442                             int subId = subInfo.getSubscriptionId();
1443                             log("updateSubscription: Re-enable Uicc application on sub " + subId);
1444                             mSubscriptionDatabaseManager.setUiccApplicationsEnabled(subId, true);
1445                             // When sim is absent, set the port index to invalid port index.
1446                             // (pre-U behavior)
1447                             mSubscriptionDatabaseManager.setPortIndex(subId,
1448                                     TelephonyManager.INVALID_PORT_INDEX);
1449                         });
1450             }
1451 
1452             if (mSlotIndexToSubId.containsKey(phoneId)) {
1453                 markSubscriptionsInactive(phoneId);
1454             }
1455 
1456             if (Flags.clearCachedImsPhoneNumberWhenDeviceLostImsRegistration()) {
1457                 // Clear the cached Ims phone number
1458                 setNumberFromIms(getSubId(phoneId), new String(""));
1459             }
1460         } else if (simState == TelephonyManager.SIM_STATE_NOT_READY) {
1461             // Check if this is the final state. Only update the subscription if NOT_READY is a
1462             // final state.
1463             IccCard iccCard = PhoneFactory.getPhone(phoneId).getIccCard();
1464             if (iccCard.isEmptyProfile()) log("updateSubscription: iccCard has empty profile.");
1465             if (!iccCard.isEmptyProfile() && areUiccAppsEnabledOnCard(phoneId)) {
1466                 log("updateSubscription: SIM_STATE_NOT_READY is not a final state. Will update "
1467                         + "subscription later.");
1468                 return;
1469             } else {
1470                 logl("updateSubscription: UICC app disabled on slot " + phoneId);
1471                 markSubscriptionsInactive(phoneId);
1472 
1473                 if (Flags.clearCachedImsPhoneNumberWhenDeviceLostImsRegistration()) {
1474                     // Clear the cached Ims phone number
1475                     setNumberFromIms(getSubId(phoneId), new String(""));
1476                 }
1477             }
1478         } else {
1479             String iccId = getIccId(phoneId);
1480             log("updateSubscription: Found iccId=" + SubscriptionInfo.getPrintableId(iccId)
1481                     + " on phone " + phoneId);
1482 
1483             // For eSIM switching, SIM absent will not happen. Below is to exam if we find ICCID
1484             // mismatch on the SIM slot. If that's the case, we need to mark all subscriptions on
1485             // that logical slot invalid first. The correct subscription will be assigned the
1486             // correct slot later.
1487             SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager.getAllSubscriptions()
1488                     .stream()
1489                     .filter(sub -> sub.getSimSlotIndex() == phoneId && !iccId.equals(
1490                             sub.getIccId()))
1491                     .findFirst()
1492                     .orElse(null);
1493             if (subInfo != null) {
1494                 log("updateSubscription: Found previous active sub " + subInfo.getSubscriptionId()
1495                         + " that doesn't match current iccid on slot " + phoneId + ".");
1496                 markSubscriptionsInactive(phoneId);
1497             }
1498 
1499             if (!TextUtils.isEmpty(iccId)) {
1500                 // Check if the subscription already existed.
1501                 subInfo = mSubscriptionDatabaseManager.getSubscriptionInfoInternalByIccId(iccId);
1502                 int subId;
1503                 if (subInfo == null) {
1504                     // This is a new SIM card. Insert a new record.
1505                     subId = insertSubscriptionInfo(iccId, phoneId, null,
1506                             SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM);
1507                     mSubscriptionDatabaseManager.setDisplayName(subId,
1508                             mContext.getResources().getString(R.string.default_card_name,
1509                                     getCardNumber(subId)));
1510                 } else {
1511                     subId = subInfo.getSubscriptionId();
1512                     log("updateSubscription: Found existing subscription. subId= " + subId
1513                             + ", phoneId=" + phoneId);
1514                 }
1515 
1516                 subInfo = mSubscriptionDatabaseManager.getSubscriptionInfoInternal(subId);
1517                 if (subInfo != null && subInfo.areUiccApplicationsEnabled()) {
1518                     mSlotIndexToSubId.put(phoneId, subId);
1519                     // Update the SIM slot index. This will make the subscription active.
1520                     mSubscriptionDatabaseManager.setSimSlotIndex(subId, phoneId);
1521                     logl("updateSubscription: current mapping " + slotMappingToString());
1522                 }
1523 
1524                 // Update the card id.
1525                 UiccCard card = mUiccController.getUiccCardForPhone(phoneId);
1526                 if (card != null) {
1527                     String cardId = card.getCardId();
1528                     if (cardId != null) {
1529                         mSubscriptionDatabaseManager.setCardString(subId, cardId);
1530                     }
1531                 }
1532 
1533                 // Update the port index.
1534                 mSubscriptionDatabaseManager.setPortIndex(subId, getPortIndex(iccId));
1535 
1536                 if (simState == TelephonyManager.SIM_STATE_LOADED) {
1537                     String mccMnc = mTelephonyManager.getSimOperatorNumeric(subId);
1538                     if (!TextUtils.isEmpty(mccMnc)) {
1539                         if (subId == getDefaultSubId()) {
1540                             MccTable.updateMccMncConfiguration(mContext, mccMnc);
1541                         }
1542                         setMccMnc(subId, mccMnc);
1543                     } else {
1544                         loge("updateSubscription: mcc/mnc is empty");
1545                     }
1546 
1547                     String iso = TelephonyManager.getSimCountryIsoForPhone(phoneId);
1548 
1549                     if (!TextUtils.isEmpty(iso)) {
1550                         setCountryIso(subId, iso);
1551                     } else {
1552                         loge("updateSubscription: sim country iso is null");
1553                     }
1554 
1555                     String msisdn = PhoneFactory.getPhone(phoneId).getLine1Number();
1556                     if (!TextUtils.isEmpty(msisdn)) {
1557                         setDisplayNumber(msisdn, subId);
1558                     }
1559 
1560                     String imsi = mTelephonyManager.createForSubscriptionId(
1561                             subId).getSubscriberId();
1562                     if (imsi != null) {
1563                         mSubscriptionDatabaseManager.setImsi(subId, imsi);
1564                     }
1565 
1566                     IccCard iccCard = PhoneFactory.getPhone(phoneId).getIccCard();
1567                     if (iccCard != null) {
1568                         IccRecords records = iccCard.getIccRecords();
1569                         if (records != null) {
1570                             String[] ehplmns = records.getEhplmns();
1571                             if (ehplmns != null) {
1572                                 mSubscriptionDatabaseManager.setEhplmns(subId, ehplmns);
1573                             }
1574                             String[] hplmns = records.getPlmnsFromHplmnActRecord();
1575                             if (hplmns != null) {
1576                                 mSubscriptionDatabaseManager.setHplmns(subId, hplmns);
1577                             }
1578                         } else {
1579                             loge("updateSubscription: ICC records are not available.");
1580                         }
1581                     } else {
1582                         loge("updateSubscription: ICC card is not available.");
1583                     }
1584 
1585                     // Attempt to restore SIM specific settings when SIM is loaded.
1586                     Bundle result = mContext.getContentResolver().call(
1587                             SubscriptionManager.SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI,
1588                             SubscriptionManager.RESTORE_SIM_SPECIFIC_SETTINGS_METHOD_NAME,
1589                             iccId, null);
1590                     if (result != null && result.getBoolean(
1591                             SubscriptionManager.RESTORE_SIM_SPECIFIC_SETTINGS_DATABASE_UPDATED)) {
1592                         logl("Sim specific settings changed the database.");
1593                         mSubscriptionDatabaseManager.reloadDatabaseSync();
1594                         if (mFeatureFlags.backupAndRestoreForEnable2g()) {
1595                             PhoneFactory.getPhone(phoneId)
1596                                     .loadAllowedNetworksFromSubscriptionDatabase();
1597                         }
1598                     }
1599                 }
1600 
1601                 log("updateSubscription: " + mSubscriptionDatabaseManager
1602                         .getSubscriptionInfoInternal(subId));
1603             } else {
1604                 log("updateSubscription: No ICCID available for phone " + phoneId);
1605                 mSlotIndexToSubId.remove(phoneId);
1606                 logl("updateSubscription: current mapping " + slotMappingToString());
1607             }
1608         }
1609 
1610         if (areAllSubscriptionsLoaded()) {
1611             log("Notify all subscriptions loaded.");
1612             MultiSimSettingController.getInstance().notifyAllSubscriptionLoaded();
1613         }
1614 
1615         updateGroupDisabled();
1616         updateDefaultSubId();
1617 
1618         if (mSlotIndexToSubId.containsKey(phoneId) &&
1619                 isEsimBootStrapProvisioningActiveForSubId(mSlotIndexToSubId.get(phoneId))) {
1620             startEsimBootstrapTimer();
1621         } else {
1622             cancelEsimBootstrapTimer();
1623         }
1624     }
1625 
cancelEsimBootstrapTimer()1626     private void cancelEsimBootstrapTimer() {
1627         if (bootstrapProvisioningTimer != null) {
1628             bootstrapProvisioningTimer.cancel();
1629             bootstrapProvisioningTimer = null;
1630             log("bootstrapProvisioningTimer timer cancelled.");
1631         }
1632     }
1633 
startEsimBootstrapTimer()1634     private void startEsimBootstrapTimer() {
1635         if (bootstrapProvisioningTimer == null) {
1636             bootstrapProvisioningTimer = new CountDownTimer(CHECK_BOOTSTRAP_TIMER_IN_MS,
1637                     CHECK_BOOTSTRAP_TIMER_IN_MS) {
1638                 @Override
1639                 public void onTick(long millisUntilFinished) {
1640                     // Do nothing
1641                 }
1642 
1643                 @Override
1644                 public void onFinish() {
1645                     AnomalyReporter.reportAnomaly(UUID.fromString("40587b0f-27c9-4b39-b94d"
1646                                     + "-71fc9771f354"), "eSim bootstrap has been active for too "
1647                             + "long.");
1648                     log("bootstrapProvisioningTimer: timer finished esim was not disabled.");
1649                     cancelEsimBootstrapTimer();
1650                 }
1651             }.start();
1652             log("bootstrapProvisioningTimer timer started.");
1653         }
1654     }
1655 
1656     /**
1657      * Calculate the usage setting based on the carrier request.
1658      *
1659      * @param currentUsageSetting the current setting in the subscription DB.
1660      * @param preferredUsageSetting provided by the carrier config.
1661      *
1662      * @return the calculated usage setting.
1663      */
1664     @VisibleForTesting
calculateUsageSetting(@sageSetting int currentUsageSetting, @UsageSetting int preferredUsageSetting)1665     @UsageSetting public int calculateUsageSetting(@UsageSetting int currentUsageSetting,
1666             @UsageSetting int preferredUsageSetting) {
1667         int[] supportedUsageSettings;
1668 
1669         //  Load the resources to provide the device capability
1670         try {
1671             supportedUsageSettings = mContext.getResources().getIntArray(
1672                     com.android.internal.R.array.config_supported_cellular_usage_settings);
1673             // If usage settings are not supported, return the default setting, which is UNKNOWN.
1674             if (supportedUsageSettings == null
1675                     || supportedUsageSettings.length < 1) return currentUsageSetting;
1676         } catch (Resources.NotFoundException nfe) {
1677             loge("calculateUsageSetting: Failed to load usage setting resources!");
1678             return currentUsageSetting;
1679         }
1680 
1681         // If the current setting is invalid, including the first time the value is set,
1682         // update it to default (this will trigger a change in the DB).
1683         if (currentUsageSetting < SubscriptionManager.USAGE_SETTING_DEFAULT
1684                 || currentUsageSetting > SubscriptionManager.USAGE_SETTING_DATA_CENTRIC) {
1685             log("calculateUsageSetting: Updating usage setting for current subscription");
1686             currentUsageSetting = SubscriptionManager.USAGE_SETTING_DEFAULT;
1687         }
1688 
1689         // Range check the inputs, and on failure, make no changes
1690         if (preferredUsageSetting < SubscriptionManager.USAGE_SETTING_DEFAULT
1691                 || preferredUsageSetting > SubscriptionManager.USAGE_SETTING_DATA_CENTRIC) {
1692             loge("calculateUsageSetting: Invalid usage setting!" + preferredUsageSetting);
1693             return currentUsageSetting;
1694         }
1695 
1696         // Default is always allowed
1697         if (preferredUsageSetting == SubscriptionManager.USAGE_SETTING_DEFAULT) {
1698             return preferredUsageSetting;
1699         }
1700 
1701         // Forced setting must be explicitly supported
1702         for (int supportedUsageSetting : supportedUsageSettings) {
1703             if (preferredUsageSetting == supportedUsageSetting) return preferredUsageSetting;
1704         }
1705 
1706         // If the preferred setting is not possible, just keep the current setting.
1707         return currentUsageSetting;
1708     }
1709 
1710     /**
1711      * Called by CarrierConfigLoader to update the subscription before sending a broadcast.
1712      */
updateSubscriptionByCarrierConfig(int phoneId, @NonNull String configPackageName, @NonNull PersistableBundle config, @NonNull Runnable callback)1713     public void updateSubscriptionByCarrierConfig(int phoneId, @NonNull String configPackageName,
1714             @NonNull PersistableBundle config, @NonNull Runnable callback) {
1715         mHandler.post(() -> {
1716             updateSubscriptionByCarrierConfigInternal(phoneId, configPackageName, config);
1717             callback.run();
1718         });
1719     }
1720 
updateSubscriptionByCarrierConfigInternal(int phoneId, @NonNull String configPackageName, @NonNull PersistableBundle config)1721     private void updateSubscriptionByCarrierConfigInternal(int phoneId,
1722             @NonNull String configPackageName, @NonNull PersistableBundle config) {
1723         log("updateSubscriptionByCarrierConfig: phoneId=" + phoneId + ", configPackageName="
1724                 + configPackageName);
1725         if (!SubscriptionManager.isValidPhoneId(phoneId)
1726                 || TextUtils.isEmpty(configPackageName) || config == null) {
1727             loge("updateSubscriptionByCarrierConfig: Failed to update the subscription. phoneId="
1728                     + phoneId + " configPackageName=" + configPackageName + " config="
1729                         + ((config == null) ? "null" : config.hashCode()));
1730             return;
1731         }
1732 
1733         if (!mSlotIndexToSubId.containsKey(phoneId)) {
1734             log("updateSubscriptionByCarrierConfig: No subscription is active for phone being "
1735                     + "updated.");
1736             return;
1737         }
1738 
1739         int subId = mSlotIndexToSubId.get(phoneId);
1740 
1741         SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager
1742                 .getSubscriptionInfoInternal(subId);
1743         if (subInfo == null) {
1744             loge("updateSubscriptionByCarrierConfig: Couldn't retrieve subscription info for "
1745                     + "current subscription. subId=" + subId);
1746             return;
1747         }
1748 
1749         ParcelUuid groupUuid;
1750 
1751         // carrier certificates are not subscription-specific, so we want to load them even if
1752         // this current package is not a CarrierServicePackage
1753         String[] certs = config.getStringArray(
1754                 CarrierConfigManager.KEY_CARRIER_CERTIFICATE_STRING_ARRAY);
1755         UiccAccessRule[] carrierConfigAccessRules = UiccAccessRule.decodeRulesFromCarrierConfig(
1756                 certs);
1757         if (carrierConfigAccessRules != null) {
1758             mSubscriptionDatabaseManager.setCarrierConfigAccessRules(
1759                     subId, carrierConfigAccessRules);
1760         }
1761 
1762         boolean isOpportunistic = config.getBoolean(
1763                 CarrierConfigManager.KEY_IS_OPPORTUNISTIC_SUBSCRIPTION_BOOL,
1764                 subInfo.isOpportunistic());
1765         mSubscriptionDatabaseManager.setOpportunistic(subId, isOpportunistic);
1766 
1767         String groupUuidString = config.getString(
1768                 CarrierConfigManager.KEY_SUBSCRIPTION_GROUP_UUID_STRING, "");
1769         String oldGroupUuidString = subInfo.getGroupUuid();
1770         if (!TextUtils.isEmpty(groupUuidString)) {
1771             try {
1772                 // Update via a UUID Structure to ensure consistent formatting
1773                 groupUuid = ParcelUuid.fromString(groupUuidString);
1774                 if (groupUuidString.equals(CarrierConfigManager.REMOVE_GROUP_UUID_STRING)) {
1775                     // Remove the group UUID.
1776                     mSubscriptionDatabaseManager.setGroupUuid(subId, "");
1777                 } else if (canPackageManageGroup(groupUuid, configPackageName)) {
1778                     mSubscriptionDatabaseManager.setGroupUuid(subId, groupUuidString);
1779                     mSubscriptionDatabaseManager.setGroupOwner(subId, configPackageName);
1780                     log("updateSubscriptionByCarrierConfig: Group added for sub " + subId);
1781                 } else {
1782                     loge("updateSubscriptionByCarrierConfig: configPackageName "
1783                             + configPackageName + " doesn't own groupUuid " + groupUuid);
1784                 }
1785 
1786                 if (!groupUuidString.equals(oldGroupUuidString)) {
1787                     MultiSimSettingController.getInstance()
1788                             .notifySubscriptionGroupChanged(groupUuid);
1789                 }
1790             } catch (IllegalArgumentException e) {
1791                 loge("updateSubscriptionByCarrierConfig: Invalid Group UUID="
1792                         + groupUuidString);
1793             }
1794         }
1795 
1796         updateGroupDisabled();
1797 
1798         final int preferredUsageSetting = config.getInt(
1799                 CarrierConfigManager.KEY_CELLULAR_USAGE_SETTING_INT,
1800                 SubscriptionManager.USAGE_SETTING_UNKNOWN);
1801 
1802         int newUsageSetting = calculateUsageSetting(
1803                 subInfo.getUsageSetting(), preferredUsageSetting);
1804 
1805         if (newUsageSetting != subInfo.getUsageSetting()) {
1806             mSubscriptionDatabaseManager.setUsageSetting(subId, newUsageSetting);
1807             log("updateSubscriptionByCarrierConfig: UsageSetting changed,"
1808                     + " oldSetting=" + SubscriptionManager.usageSettingToString(
1809                             subInfo.getUsageSetting())
1810                     + " preferredSetting=" + SubscriptionManager.usageSettingToString(
1811                             preferredUsageSetting)
1812                     + " newSetting=" + SubscriptionManager.usageSettingToString(newUsageSetting));
1813         }
1814 
1815         if (mFeatureFlags.dataOnlyCellularService()) {
1816             final int[] servicesFromCarrierConfig =
1817                     config.getIntArray(
1818                             CarrierConfigManager.KEY_CELLULAR_SERVICE_CAPABILITIES_INT_ARRAY);
1819             int serviceBitmasks = 0;
1820             boolean allServicesAreValid = true;
1821             // Check if all services from carrier config are valid before setting to db
1822             if (servicesFromCarrierConfig == null) {
1823                 allServicesAreValid = false;
1824             } else {
1825                 for (int service : servicesFromCarrierConfig) {
1826                     if (service < SubscriptionManager.SERVICE_CAPABILITY_VOICE
1827                             || service > SubscriptionManager.SERVICE_CAPABILITY_MAX) {
1828                         allServicesAreValid = false;
1829                         break;
1830                     } else {
1831                         serviceBitmasks |= SubscriptionManager.serviceCapabilityToBitmask(service);
1832                     }
1833                 }
1834             }
1835             // In case we get invalid service override, fall back to default value.
1836             // DO NOT throw exception which will crash phone process.
1837             if (!allServicesAreValid) {
1838                 serviceBitmasks = SubscriptionManager.getAllServiceCapabilityBitmasks();
1839             }
1840 
1841             if (serviceBitmasks != subInfo.getServiceCapabilities()) {
1842                 log("updateSubscriptionByCarrierConfig: serviceCapabilities updated from "
1843                         + subInfo.getServiceCapabilities() + " to " + serviceBitmasks);
1844                 mSubscriptionDatabaseManager.setServiceCapabilities(subId, serviceBitmasks);
1845             }
1846         }
1847     }
1848 
1849     /**
1850      * Get all subscription info records from SIMs visible to the calling user that are inserted now
1851      * or previously inserted.
1852      *
1853      * <p>
1854      * If the caller does not have {@link Manifest.permission#READ_PHONE_NUMBERS} permission,
1855      * {@link SubscriptionInfo#getNumber()} will return empty string.
1856      * If the caller does not have {@link Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER},
1857      * {@link SubscriptionInfo#getIccId()} and {@link SubscriptionInfo#getCardString()} will return
1858      * empty string, and {@link SubscriptionInfo#getGroupUuid()} will return {@code null}.
1859      *
1860      * <p>
1861      * The carrier app will only get the list of subscriptions that it has carrier privilege on,
1862      * but will have non-stripped {@link SubscriptionInfo} in the list.
1863      *
1864      * @param callingPackage The package making the call.
1865      * @param callingFeatureId The feature in the package.
1866      *
1867      * @return List of all {@link SubscriptionInfo} records from SIMs that are inserted or
1868      * previously inserted. Sorted by {@link SubscriptionInfo#getSimSlotIndex()}, then
1869      * {@link SubscriptionInfo#getSubscriptionId()}.
1870      *
1871      * @throws SecurityException if callers do not hold the required permission.
1872      */
1873     @Override
1874     @NonNull
1875     @RequiresPermission(anyOf = {
1876             Manifest.permission.READ_PHONE_STATE,
1877             Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
1878             "carrier privileges",
1879     })
getAllSubInfoList(@onNull String callingPackage, @Nullable String callingFeatureId)1880     public List<SubscriptionInfo> getAllSubInfoList(@NonNull String callingPackage,
1881             @Nullable String callingFeatureId) {
1882         // Check if the caller has READ_PHONE_STATE, READ_PRIVILEGED_PHONE_STATE, or carrier
1883         // privilege on any active subscription. The carrier app will get full subscription infos
1884         // on the subs it has carrier privilege.
1885         if (!TelephonyPermissions.checkReadPhoneStateOnAnyActiveSub(mContext,
1886                 Binder.getCallingPid(), Binder.getCallingUid(), callingPackage, callingFeatureId,
1887                 "getAllSubInfoList")) {
1888             throw new SecurityException("Need READ_PHONE_STATE, READ_PRIVILEGED_PHONE_STATE, or "
1889                     + "carrier privilege");
1890         }
1891 
1892         enforceTelephonyFeatureWithException(callingPackage, "getAllSubInfoList");
1893 
1894         return getSubscriptionInfoStreamAsUser(BINDER_WRAPPER.getCallingUserHandle())
1895                 // callers have READ_PHONE_STATE or READ_PRIVILEGED_PHONE_STATE can get a full
1896                 // list. Carrier apps can only get the subscriptions they have privileged.
1897                 .filter(subInfo -> TelephonyPermissions.checkCallingOrSelfReadPhoneStateNoThrow(
1898                         mContext, subInfo.getSubscriptionId(), callingPackage, callingFeatureId,
1899                         "getAllSubInfoList"))
1900                 // Remove the identifier if the caller does not have sufficient permission.
1901                 // carrier apps will get full subscription info on the subscriptions associated
1902                 // to them.
1903                 .map(subInfo -> conditionallyRemoveIdentifiers(subInfo.toSubscriptionInfo(),
1904                         callingPackage, callingFeatureId, "getAllSubInfoList"))
1905                 .sorted(Comparator.comparing(SubscriptionInfo::getSimSlotIndex)
1906                         .thenComparing(SubscriptionInfo::getSubscriptionId))
1907                 .collect(Collectors.toList());
1908     }
1909 
1910     /**
1911      * Get the active {@link SubscriptionInfo} with the subscription id key.
1912      *
1913      * @param subId The unique {@link SubscriptionInfo} key in database
1914      * @param callingPackage The package making the call.
1915      * @param callingFeatureId The feature in the package.
1916      *
1917      * @return The subscription info.
1918      *
1919      * @throws SecurityException if the caller does not have required permissions.
1920      */
1921     @Override
1922     @Nullable
1923     @RequiresPermission(anyOf = {
1924             Manifest.permission.READ_PHONE_STATE,
1925             Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
1926             "carrier privileges",
1927     })
getActiveSubscriptionInfo(int subId, @NonNull String callingPackage, @Nullable String callingFeatureId)1928     public SubscriptionInfo getActiveSubscriptionInfo(int subId, @NonNull String callingPackage,
1929             @Nullable String callingFeatureId) {
1930         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mContext, subId, callingPackage,
1931                 callingFeatureId, "getActiveSubscriptionInfo")) {
1932             throw new SecurityException("Need READ_PHONE_STATE, READ_PRIVILEGED_PHONE_STATE, or "
1933                     + "carrier privilege");
1934         }
1935 
1936         enforceTelephonyFeatureWithException(callingPackage, "getActiveSubscriptionInfo");
1937 
1938         SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager
1939                 .getSubscriptionInfoInternal(subId);
1940         if (subInfo != null && subInfo.isActive()) {
1941             return conditionallyRemoveIdentifiers(subInfo.toSubscriptionInfo(), callingPackage,
1942                     callingFeatureId, "getActiveSubscriptionInfo");
1943         }
1944         return null;
1945     }
1946 
1947     /**
1948      * Get the active {@link SubscriptionInfo} associated with the iccId.
1949      *
1950      * @param iccId the IccId of SIM card
1951      * @param callingPackage The package making the call.
1952      * @param callingFeatureId The feature in the package.
1953      *
1954      * @return The subscription info.
1955      *
1956      * @throws SecurityException if the caller does not have required permissions.
1957      */
1958     @Override
1959     @Nullable
1960     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
getActiveSubscriptionInfoForIccId(@onNull String iccId, @NonNull String callingPackage, @Nullable String callingFeatureId)1961     public SubscriptionInfo getActiveSubscriptionInfoForIccId(@NonNull String iccId,
1962             @NonNull String callingPackage, @Nullable String callingFeatureId) {
1963         enforcePermissions("getActiveSubscriptionInfoForIccId",
1964                 Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
1965 
1966         enforceTelephonyFeatureWithException(callingPackage, "getActiveSubscriptionInfoForIccId");
1967 
1968         final long identity = Binder.clearCallingIdentity();
1969         try {
1970             iccId = IccUtils.stripTrailingFs(iccId);
1971             SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager
1972                     .getSubscriptionInfoInternalByIccId(iccId);
1973 
1974             return (subInfo != null && subInfo.isActive()) ? subInfo.toSubscriptionInfo() : null;
1975 
1976         } finally {
1977             Binder.restoreCallingIdentity(identity);
1978         }
1979     }
1980 
1981     /**
1982      * Get the active {@link SubscriptionInfo} associated with the logical SIM slot index.
1983      *
1984      * @param slotIndex the logical SIM slot index which the subscription is inserted.
1985      * @param callingPackage The package making the call.
1986      * @param callingFeatureId The feature in the package.
1987      *
1988      * @return {@link SubscriptionInfo}, null for Remote-SIMs or non-active logical SIM slot index.
1989      *
1990      * @throws SecurityException if the caller does not have required permissions.
1991      */
1992     @Override
1993     @Nullable
1994     @RequiresPermission(anyOf = {
1995             Manifest.permission.READ_PHONE_STATE,
1996             Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
1997             "carrier privileges",
1998     })
getActiveSubscriptionInfoForSimSlotIndex(int slotIndex, @NonNull String callingPackage, @Nullable String callingFeatureId)1999     public SubscriptionInfo getActiveSubscriptionInfoForSimSlotIndex(int slotIndex,
2000             @NonNull String callingPackage, @Nullable String callingFeatureId) {
2001         int subId = mSlotIndexToSubId.getOrDefault(slotIndex,
2002                 SubscriptionManager.INVALID_SUBSCRIPTION_ID);
2003 
2004         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mContext, subId,
2005                 callingPackage, callingFeatureId,
2006                 "getActiveSubscriptionInfoForSimSlotIndex")) {
2007             throw new SecurityException("Need READ_PHONE_STATE, READ_PRIVILEGED_PHONE_STATE, or "
2008                     + "carrier privilege");
2009 
2010         }
2011 
2012         enforceTelephonyFeatureWithException(callingPackage,
2013                 "getActiveSubscriptionInfoForSimSlotIndex");
2014 
2015         if (!SubscriptionManager.isValidSlotIndex(slotIndex)) {
2016             throw new IllegalArgumentException("Invalid slot index " + slotIndex);
2017         }
2018 
2019         SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager
2020                 .getSubscriptionInfoInternal(subId);
2021         if (subInfo != null && subInfo.isActive()) {
2022             return conditionallyRemoveIdentifiers(subInfo.toSubscriptionInfo(), callingPackage,
2023                     callingFeatureId, "getActiveSubscriptionInfoForSimSlotIndex");
2024         }
2025 
2026         return null;
2027     }
2028 
2029     /**
2030      * Get the SubscriptionInfo(s) of the active subscriptions for calling user. The records will be
2031      * sorted by {@link SubscriptionInfo#getSimSlotIndex} then by
2032      * {@link SubscriptionInfo#getSubscriptionId}.
2033      *
2034      * @param callingPackage The package making the call.
2035      * @param callingFeatureId The feature in the package.
2036      * @param isForAllProfiles whether the caller intends to see all subscriptions regardless
2037      *                      association.
2038      *
2039      * @return Sorted list of the currently {@link SubscriptionInfo} records available on the
2040      * device.
2041      */
2042     @Override
2043     @NonNull
2044     @RequiresPermission(anyOf = {
2045             Manifest.permission.READ_PHONE_STATE,
2046             Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
2047             "carrier privileges",
2048     })
getActiveSubscriptionInfoList(@onNull String callingPackage, @Nullable String callingFeatureId, boolean isForAllProfiles)2049     public List<SubscriptionInfo> getActiveSubscriptionInfoList(@NonNull String callingPackage,
2050             @Nullable String callingFeatureId, boolean isForAllProfiles) {
2051         // Check if the caller has READ_PHONE_STATE, READ_PRIVILEGED_PHONE_STATE, or carrier
2052         // privilege on any active subscription. The carrier app will get full subscription infos
2053         // on the subs it has carrier privilege.
2054         if (!TelephonyPermissions.checkReadPhoneStateOnAnyActiveSub(mContext,
2055                 Binder.getCallingPid(), Binder.getCallingUid(), callingPackage, callingFeatureId,
2056                 "getActiveSubscriptionInfoList")) {
2057             // Ideally we should avoid silent failure, but since this API has already been used by
2058             // many apps and they do not expect the security exception, we return an empty list
2059             // here so it's consistent with pre-U behavior.
2060             loge("getActiveSubscriptionInfoList: " + callingPackage + " does not have enough "
2061                     + "permission. Returning empty list here.");
2062             return Collections.emptyList();
2063         }
2064 
2065         enforceTelephonyFeatureWithException(callingPackage, "getActiveSubscriptionInfoList");
2066 
2067         if (isForAllProfiles) {
2068             enforcePermissionAccessAllUserProfiles();
2069         }
2070         return getSubscriptionInfoStreamAsUser(isForAllProfiles
2071                 ? UserHandle.ALL : BINDER_WRAPPER.getCallingUserHandle())
2072                 .filter(SubscriptionInfoInternal::isActive)
2073                 // Remove the identifier if the caller does not have sufficient permission.
2074                 // carrier apps will get full subscription info on the subscriptions associated
2075                 // to them.
2076                 .map(subInfo -> conditionallyRemoveIdentifiers(subInfo.toSubscriptionInfo(),
2077                         callingPackage, callingFeatureId, "getActiveSubscriptionInfoList"))
2078                 .sorted(Comparator.comparing(SubscriptionInfo::getSimSlotIndex)
2079                         .thenComparing(SubscriptionInfo::getSubscriptionId))
2080                 .collect(Collectors.toList());
2081     }
2082 
2083     /**
2084      * Get the number of active {@link SubscriptionInfo}.
2085      *
2086      * @param callingPackage The package making the call.
2087      * @param callingFeatureId The feature in the package.
2088      * @param isForAllProfiles whether the caller intends to see all subscriptions regardless
2089      *                        association.
2090      *
2091      * @return the number of active subscriptions.
2092      *
2093      * @throws SecurityException if the caller does not have required permissions.
2094      */
2095     @Override
2096     @RequiresPermission(anyOf = {
2097             Manifest.permission.READ_PHONE_STATE,
2098             Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
2099             "carrier privileges",
2100     })
getActiveSubInfoCount(@onNull String callingPackage, @Nullable String callingFeatureId, boolean isForAllProfiles)2101     public int getActiveSubInfoCount(@NonNull String callingPackage,
2102             @Nullable String callingFeatureId, boolean isForAllProfiles) {
2103         if (!TelephonyPermissions.checkReadPhoneStateOnAnyActiveSub(mContext,
2104                 Binder.getCallingPid(), Binder.getCallingUid(), callingPackage, callingFeatureId,
2105                 "getAllSubInfoList")) {
2106             throw new SecurityException("Need READ_PHONE_STATE, READ_PRIVILEGED_PHONE_STATE, or "
2107                     + "carrier privilege");
2108         }
2109         if (isForAllProfiles) {
2110             enforcePermissionAccessAllUserProfiles();
2111         }
2112 
2113         enforceTelephonyFeatureWithException(callingPackage, "getActiveSubInfoCount");
2114 
2115         return getActiveSubIdListAsUser(false, isForAllProfiles
2116                 ? UserHandle.ALL : BINDER_WRAPPER.getCallingUserHandle()).length;
2117     }
2118 
2119     /** @throws SecurityException if caller doesn't have one of the requested permissions. */
enforcePermissionAccessAllUserProfiles()2120     private void enforcePermissionAccessAllUserProfiles() {
2121         if (!mFeatureFlags.enforceSubscriptionUserFilter()) return;
2122         enforcePermissions("To access across profiles",
2123                 Manifest.permission.INTERACT_ACROSS_USERS,
2124                 Manifest.permission.INTERACT_ACROSS_USERS_FULL,
2125                 Manifest.permission.INTERACT_ACROSS_PROFILES);
2126     }
2127 
2128     /**
2129      * @return the maximum number of subscriptions this device will support at any one time.
2130      */
2131     @Override
getActiveSubInfoCountMax()2132     public int getActiveSubInfoCountMax() {
2133         return mTelephonyManager.getActiveModemCount();
2134     }
2135 
2136     /**
2137      * Gets the SubscriptionInfo(s) of all available subscriptions, if any.
2138      *
2139      * Available subscriptions include active ones (those with a non-negative
2140      * {@link SubscriptionInfo#getSimSlotIndex()}) as well as inactive but installed embedded
2141      * subscriptions.
2142      *
2143      * @param callingPackage The package making the call.
2144      * @param callingFeatureId The feature in the package.
2145      *
2146      * @return The available subscription info.
2147      *
2148      * @throws SecurityException if the caller does not have required permissions.
2149      */
2150     @Override
2151     @NonNull
getAvailableSubscriptionInfoList(@onNull String callingPackage, @Nullable String callingFeatureId)2152     public List<SubscriptionInfo> getAvailableSubscriptionInfoList(@NonNull String callingPackage,
2153             @Nullable String callingFeatureId) {
2154         enforcePermissions("getAvailableSubscriptionInfoList",
2155                 Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
2156 
2157         enforceTelephonyFeatureWithException(callingPackage, "getAvailableSubscriptionInfoList");
2158 
2159         return getAvailableSubscriptionsInternalStream()
2160                 .sorted(Comparator.comparing(SubscriptionInfoInternal::getSimSlotIndex)
2161                         .thenComparing(SubscriptionInfoInternal::getSubscriptionId))
2162                 .map(SubscriptionInfoInternal::toSubscriptionInfo)
2163                 .collect(Collectors.toList());
2164 
2165     }
2166 
2167     /**
2168      * @return all the subscriptions visible to user on the device.
2169      */
getAvailableSubscriptionsInternalStream()2170     private Stream<SubscriptionInfoInternal> getAvailableSubscriptionsInternalStream() {
2171         // Available eSIM profiles are reported by EuiccManager. However for physical SIMs if
2172         // they are in inactive slot or programmatically disabled, they are still considered
2173         // available. In this case we get their iccid from slot info and include their
2174         // subscriptionInfos.
2175         List<String> iccIds = getIccIdsOfInsertedPhysicalSims();
2176 
2177         return mSubscriptionDatabaseManager.getAllSubscriptions().stream()
2178                 .filter(subInfo -> subInfo.isActive() || iccIds.contains(subInfo.getIccId())
2179                         || (mEuiccManager != null && mEuiccManager.isEnabled()
2180                         && subInfo.isEmbedded()));
2181     }
2182 
2183     /**
2184      * Tracks for each user Id, a list of subscriptions associated with it.
2185      * A profile is barred from seeing unassociated subscriptions if it has its own subscription
2186      * which is available to choose from the device.
2187      */
updateUserIdToAvailableSubs()2188     private void updateUserIdToAvailableSubs() {
2189         mUserIdToAvailableSubs = getAvailableSubscriptionsInternalStream()
2190                 .collect(Collectors.groupingBy(
2191                         SubscriptionInfoInternal::getUserId,
2192                         Collectors.mapping(SubscriptionInfoInternal::getSubscriptionId,
2193                                 Collectors.toList())));
2194         log("updateUserIdToAvailableSubs: " + mUserIdToAvailableSubs);
2195     }
2196 
2197     /**
2198      * Gets the SubscriptionInfo(s) of all embedded subscriptions accessible to the calling app, if
2199      * any.
2200      *
2201      * <p>Only those subscriptions for which the calling app has carrier privileges per the
2202      * subscription metadata, if any, will be included in the returned list.
2203      *
2204      * <p>The records will be sorted by {@link SubscriptionInfo#getSimSlotIndex} then by
2205      * {@link SubscriptionInfo#getSubscriptionId}.
2206      *
2207      * @return Sorted list of the current embedded {@link SubscriptionInfo} records available on the
2208      * device which are accessible to the caller.
2209      * <ul>
2210      * <li>
2211      *
2212      * if the list is non-empty the list is sorted by {@link SubscriptionInfo#getSimSlotIndex}
2213      * then by {@link SubscriptionInfo#getSubscriptionId}.
2214      * </ul>
2215      *
2216      * @param callingPackage The package making the call.
2217      *
2218      * @throws SecurityException if the caller does not have required permissions.
2219      */
2220     @Override
getAccessibleSubscriptionInfoList( @onNull String callingPackage)2221     public List<SubscriptionInfo> getAccessibleSubscriptionInfoList(
2222             @NonNull String callingPackage) {
2223         if (!mEuiccManager.isEnabled()) {
2224             return null;
2225         }
2226 
2227         // Verify that the callingPackage belongs to the calling UID
2228         mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage);
2229         return getSubscriptionInfoStreamAsUser(BINDER_WRAPPER.getCallingUserHandle())
2230                 .map(SubscriptionInfoInternal::toSubscriptionInfo)
2231                 .filter(subInfo -> subInfo.isEmbedded()
2232                         && mSubscriptionManager.canManageSubscription(subInfo, callingPackage))
2233                 .sorted(Comparator.comparing(SubscriptionInfo::getSimSlotIndex)
2234                         .thenComparing(SubscriptionInfo::getSubscriptionId))
2235                 .collect(Collectors.toList());
2236     }
2237 
2238     /**
2239      * @see SubscriptionManager#requestEmbeddedSubscriptionInfoListRefresh
2240      */
2241     @Override
requestEmbeddedSubscriptionInfoListRefresh(int cardId)2242     public void requestEmbeddedSubscriptionInfoListRefresh(int cardId) {
2243         enforcePermissions("requestEmbeddedSubscriptionInfoListRefresh",
2244                 Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS);
2245         updateEmbeddedSubscriptions(List.of(cardId), null);
2246     }
2247 
2248     /**
2249      * Add a new subscription info record, if needed. This should be only used for remote SIM.
2250      *
2251      * @param iccId ICCID of the SIM card.
2252      * @param displayName human-readable name of the device the subscription corresponds to.
2253      * @param slotIndex the logical SIM slot index assigned to this device.
2254      * @param subscriptionType the type of subscription to be added
2255      *
2256      * @return 0 if success, < 0 on error
2257      *
2258      * @throws SecurityException if the caller does not have required permissions.
2259      * @throws IllegalArgumentException if {@code slotIndex} is invalid.
2260      */
2261     @Override
2262     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
addSubInfo(@onNull String iccId, @NonNull String displayName, int slotIndex, @SubscriptionType int subscriptionType)2263     public int addSubInfo(@NonNull String iccId, @NonNull String displayName, int slotIndex,
2264             @SubscriptionType int subscriptionType) {
2265         enforcePermissions("addSubInfo", Manifest.permission.MODIFY_PHONE_STATE);
2266         logl("addSubInfo: iccId=" + SubscriptionInfo.getPrintableId(iccId) + ", slotIndex="
2267                 + slotIndex + ", displayName=" + displayName + ", type="
2268                 + SubscriptionManager.subscriptionTypeToString(subscriptionType) + ", "
2269                 + getCallingPackage());
2270 
2271         enforceTelephonyFeatureWithException(getCurrentPackageName(), "addSubInfo");
2272 
2273         if (!SubscriptionManager.isValidSlotIndex(slotIndex)
2274                 && slotIndex != SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
2275             throw new IllegalArgumentException("Invalid slotIndex " + slotIndex);
2276         }
2277 
2278         // Now that all security checks passes, perform the operation as ourselves.
2279         final long identity = Binder.clearCallingIdentity();
2280         try {
2281             if (TextUtils.isEmpty(iccId)) {
2282                 loge("addSubInfo: null or empty iccId");
2283                 return -1;
2284             }
2285 
2286             iccId = IccUtils.stripTrailingFs(iccId);
2287             SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager
2288                     .getSubscriptionInfoInternalByIccId(iccId);
2289 
2290             // Check if the record exists or not.
2291             if (subInfo == null) {
2292                 // Record does not exist.
2293                 if (mSlotIndexToSubId.containsKey(slotIndex)) {
2294                     loge("Already a subscription on slot " + slotIndex);
2295                     return -1;
2296                 }
2297 
2298                 int subId = insertSubscriptionInfo(iccId, slotIndex, displayName, subscriptionType);
2299                 updateGroupDisabled();
2300                 mSlotIndexToSubId.put(slotIndex, subId);
2301                 logl("addSubInfo: current mapping " + slotMappingToString());
2302             } else {
2303                 // Record already exists.
2304                 loge("Subscription record already existed.");
2305                 return -1;
2306             }
2307         } finally {
2308             Binder.restoreCallingIdentity(identity);
2309         }
2310         return 0;
2311     }
2312 
2313     /**
2314      * Remove subscription info record from the subscription database.
2315      *
2316      * @param uniqueId This is the unique identifier for the subscription within the specific
2317      * subscription type.
2318      * @param subscriptionType the type of subscription to be removed.
2319      *
2320      * @return {@code true} if succeeded, otherwise {@code false}.
2321      *
2322      * @throws NullPointerException if {@code uniqueId} is {@code null}.
2323      * @throws SecurityException if callers do not hold the required permission.
2324      */
2325     @Override
2326     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
removeSubInfo(@onNull String uniqueId, int subscriptionType)2327     public boolean removeSubInfo(@NonNull String uniqueId, int subscriptionType) {
2328         enforcePermissions("removeSubInfo", Manifest.permission.MODIFY_PHONE_STATE);
2329 
2330         logl("removeSubInfo: uniqueId=" + SubscriptionInfo.getPrintableId(uniqueId) + ", "
2331                 + SubscriptionManager.subscriptionTypeToString(subscriptionType) + ", "
2332                 + getCallingPackage());
2333 
2334         enforceTelephonyFeatureWithException(getCurrentPackageName(), "removeSubInfo");
2335 
2336         final long identity = Binder.clearCallingIdentity();
2337         try {
2338             SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager
2339                     .getSubscriptionInfoInternalByIccId(uniqueId);
2340             if (subInfo == null) {
2341                 loge("Cannot find subscription with uniqueId " + uniqueId);
2342                 return false;
2343             }
2344             if (subInfo.getSubscriptionType() != subscriptionType) {
2345                 loge("The subscription type does not match.");
2346                 return false;
2347             }
2348             mSlotIndexToSubId.remove(subInfo.getSimSlotIndex());
2349             mSubscriptionDatabaseManager.removeSubscriptionInfo(subInfo.getSubscriptionId());
2350             return true;
2351         } finally {
2352             Binder.restoreCallingIdentity(identity);
2353         }
2354     }
2355 
2356     /**
2357      * Set SIM icon tint color by simInfo index.
2358      *
2359      * @param subId the unique subscription index in database
2360      * @param tint the icon tint color of the SIM
2361      *
2362      * @return the number of records updated
2363      *
2364      * @throws IllegalArgumentException if {@code subId} is invalid or the subscription does not
2365      * exist.
2366      * @throws SecurityException if callers do not hold the required permission.
2367      */
2368     @Override
2369     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
setIconTint(int subId, @ColorInt int tint)2370     public int setIconTint(int subId, @ColorInt int tint) {
2371         enforcePermissions("setIconTint", Manifest.permission.MODIFY_PHONE_STATE);
2372 
2373         final long identity = Binder.clearCallingIdentity();
2374         try {
2375             if (!SubscriptionManager.isValidSubscriptionId(subId)) {
2376                 throw new IllegalArgumentException("Invalid sub id passed as parameter");
2377             }
2378 
2379             mSubscriptionDatabaseManager.setIconTint(subId, tint);
2380             return 1;
2381         } finally {
2382             Binder.restoreCallingIdentity(identity);
2383         }
2384     }
2385 
2386     /**
2387      * Set display name of a subscription.
2388      *
2389      * @param displayName The display name of SIM card.
2390      * @param subId The subscription id.
2391      * @param nameSource The display name source.
2392      *
2393      * @return the number of records updated
2394      *
2395      * @throws IllegalArgumentException if {@code nameSource} is invalid, or {@code subId} is
2396      * invalid.
2397      * @throws NullPointerException if {@code displayName} is {@code null}.
2398      * @throws SecurityException if callers do not hold the required permission.
2399      */
2400     @Override
2401     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
setDisplayNameUsingSrc(@onNull String displayName, int subId, @SimDisplayNameSource int nameSource)2402     public int setDisplayNameUsingSrc(@NonNull String displayName, int subId,
2403             @SimDisplayNameSource int nameSource) {
2404         enforcePermissions("setDisplayNameUsingSrc", Manifest.permission.MODIFY_PHONE_STATE);
2405 
2406         String callingPackage = getCallingPackage();
2407         final long identity = Binder.clearCallingIdentity();
2408         try {
2409             Objects.requireNonNull(displayName, "setDisplayNameUsingSrc");
2410 
2411             if (nameSource < SubscriptionManager.NAME_SOURCE_CARRIER_ID
2412                     || nameSource > SubscriptionManager.NAME_SOURCE_SIM_PNN) {
2413                 throw new IllegalArgumentException("illegal name source " + nameSource);
2414             }
2415 
2416             SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager
2417                     .getSubscriptionInfoInternal(subId);
2418 
2419             if (subInfo == null) {
2420                 throw new IllegalArgumentException("Cannot find subscription info with sub id "
2421                         + subId);
2422             }
2423 
2424             if (getNameSourcePriority(subInfo.getDisplayNameSource())
2425                     > getNameSourcePriority(nameSource)
2426                     || (getNameSourcePriority(subInfo.getDisplayNameSource())
2427                     == getNameSourcePriority(nameSource))
2428                     && (TextUtils.equals(displayName, subInfo.getDisplayName()))) {
2429                 log("No need to update the display name. nameSource="
2430                         + SubscriptionManager.displayNameSourceToString(nameSource)
2431                         + ", existing name=" + subInfo.getDisplayName() + ", source="
2432                         + SubscriptionManager.displayNameSourceToString(
2433                                 subInfo.getDisplayNameSource()));
2434                 return 0;
2435             }
2436 
2437             String nameToSet;
2438             if (TextUtils.isEmpty(displayName) || displayName.trim().length() == 0) {
2439                 nameToSet = mTelephonyManager.getSimOperatorName(subId);
2440                 if (TextUtils.isEmpty(nameToSet)) {
2441                     if (nameSource == SubscriptionManager.NAME_SOURCE_USER_INPUT
2442                             && SubscriptionManager.isValidSlotIndex(getSlotIndex(subId))) {
2443                         Resources r = Resources.getSystem();
2444                         nameToSet = r.getString(R.string.default_card_name,
2445                                 (getSlotIndex(subId) + 1));
2446                     } else {
2447                         nameToSet = mContext.getString(SubscriptionManager.DEFAULT_NAME_RES);
2448                     }
2449                 }
2450             } else {
2451                 nameToSet = displayName;
2452             }
2453 
2454             logl("setDisplayNameUsingSrc: subId=" + subId + ", name=" + nameToSet
2455                     + ", nameSource=" + SubscriptionManager.displayNameSourceToString(nameSource)
2456                     + ", calling package=" + callingPackage);
2457             mSubscriptionDatabaseManager.setDisplayName(subId, nameToSet);
2458             mSubscriptionDatabaseManager.setDisplayNameSource(subId, nameSource);
2459 
2460             // Update the nickname on the eUICC chip if it's an embedded subscription.
2461             SubscriptionInfo sub = getSubscriptionInfo(subId);
2462             if (sub != null && sub.isEmbedded()) {
2463                 int cardId = sub.getCardId();
2464                 log("Updating embedded sub nickname on cardId: " + cardId);
2465                 mEuiccManager.updateSubscriptionNickname(subId, nameToSet,
2466                         // This PendingIntent simply fulfills the requirement to pass in a callback;
2467                         // we don't care about the result (hence 0 requestCode and no action
2468                         // specified on the intent).
2469                         PendingIntent.getService(mContext, 0 /* requestCode */, new Intent(),
2470                                 PendingIntent.FLAG_IMMUTABLE /* flags */));
2471             }
2472 
2473             return 1;
2474         } finally {
2475             Binder.restoreCallingIdentity(identity);
2476         }
2477     }
2478 
2479     /**
2480      * Set phone number by subscription id.
2481      *
2482      * @param number the phone number of the SIM.
2483      * @param subId the unique SubscriptionInfo index in database.
2484      *
2485      * @return the number of records updated.
2486      *
2487      * @throws SecurityException if callers do not hold the required permission.
2488      * @throws NullPointerException if {@code number} is {@code null}.
2489      */
2490     @Override
2491     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
setDisplayNumber(@onNull String number, int subId)2492     public int setDisplayNumber(@NonNull String number, int subId) {
2493         enforcePermissions("setDisplayNumber", Manifest.permission.MODIFY_PHONE_STATE);
2494         logl("setDisplayNumber: subId=" + subId + ", number="
2495                 + Rlog.pii(TelephonyUtils.IS_DEBUGGABLE, number)
2496                 + ", calling package=" + getCallingPackage());
2497         // Now that all security checks passes, perform the operation as ourselves.
2498         final long identity = Binder.clearCallingIdentity();
2499         try {
2500             mSubscriptionDatabaseManager.setNumber(subId, number);
2501             return 1;
2502         } finally {
2503             Binder.restoreCallingIdentity(identity);
2504         }
2505     }
2506 
2507     /**
2508      * Set data roaming by simInfo index
2509      *
2510      * @param roaming 0:Don't allow data when roaming, 1:Allow data when roaming
2511      * @param subId the unique SubscriptionInfo index in database
2512      *
2513      * @return the number of records updated
2514      *
2515      * @throws IllegalArgumentException if {@code subId} or {@code roaming} is not valid.
2516      * @throws SecurityException if callers do not hold the required permission.
2517      */
2518     @Override
2519     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
setDataRoaming(@ataRoamingMode int roaming, int subId)2520     public int setDataRoaming(@DataRoamingMode int roaming, int subId) {
2521         enforcePermissions("setDataRoaming", Manifest.permission.MODIFY_PHONE_STATE);
2522 
2523         // Now that all security checks passes, perform the operation as ourselves.
2524         final long identity = Binder.clearCallingIdentity();
2525         try {
2526             if (roaming < 0) {
2527                 throw new IllegalArgumentException("Invalid roaming value " + roaming);
2528             }
2529 
2530             mSubscriptionDatabaseManager.setDataRoaming(subId, roaming);
2531             return 1;
2532         } finally {
2533             Binder.restoreCallingIdentity(identity);
2534         }
2535     }
2536 
2537     /**
2538      * Switch to a certain subscription.
2539      *
2540      * @param opportunistic whether it’s opportunistic subscription
2541      * @param subId the unique SubscriptionInfo index in database
2542      * @param callingPackage The package making the call
2543      *
2544      * @return the number of records updated
2545      *
2546      * @throws IllegalArgumentException if {@code subId} is invalid.
2547      * @throws SecurityException if callers do not hold the required permission.
2548      */
2549     @Override
2550     @RequiresPermission(anyOf = {
2551             Manifest.permission.MODIFY_PHONE_STATE,
2552             "carrier privileges",
2553     })
setOpportunistic(boolean opportunistic, int subId, @NonNull String callingPackage)2554     public int setOpportunistic(boolean opportunistic, int subId, @NonNull String callingPackage) {
2555         TelephonyPermissions.enforceAnyPermissionGrantedOrCarrierPrivileges(
2556                 mContext, subId, Binder.getCallingUid(), true, "setOpportunistic",
2557                 Manifest.permission.MODIFY_PHONE_STATE);
2558 
2559         enforceTelephonyFeatureWithException(callingPackage, "setOpportunistic");
2560 
2561         long token = Binder.clearCallingIdentity();
2562         try {
2563             mSubscriptionDatabaseManager.setOpportunistic(subId, opportunistic);
2564             return 1;
2565         } finally {
2566             Binder.restoreCallingIdentity(token);
2567         }
2568     }
2569 
2570     /**
2571      * Inform SubscriptionManager that subscriptions in the list are bundled as a group. Typically
2572      * it's a primary subscription and an opportunistic subscription. It should only affect
2573      * multi-SIM scenarios where primary and opportunistic subscriptions can be activated together.
2574      *
2575      * Being in the same group means they might be activated or deactivated together, some of them
2576      * may be invisible to the users, etc.
2577      *
2578      * Caller will either have {@link Manifest.permission#MODIFY_PHONE_STATE} permission or
2579      * can manage all subscriptions in the list, according to their access rules.
2580      *
2581      * @param subIdList list of subId that will be in the same group.
2582      * @param callingPackage The package making the call.
2583      *
2584      * @return groupUUID a UUID assigned to the subscription group. It returns null if fails.
2585      *
2586      * @throws IllegalArgumentException if {@code subId} is invalid.
2587      * @throws SecurityException if callers do not hold the required permission.
2588      */
2589     @Override
2590     @RequiresPermission(anyOf = {
2591             Manifest.permission.MODIFY_PHONE_STATE,
2592             "carrier privileges",
2593     })
createSubscriptionGroup(@onNull int[] subIdList, @NonNull String callingPackage)2594     public ParcelUuid createSubscriptionGroup(@NonNull int[] subIdList,
2595             @NonNull String callingPackage) {
2596         // Verify that the callingPackage belongs to the calling UID
2597         mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage);
2598 
2599         Objects.requireNonNull(subIdList, "createSubscriptionGroup");
2600         if (subIdList.length == 0) {
2601             throw new IllegalArgumentException("Invalid subIdList " + Arrays.toString(subIdList));
2602         }
2603 
2604         // If it doesn't have modify phone state permission, or carrier privilege permission,
2605         // a SecurityException will be thrown.
2606         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
2607                 != PackageManager.PERMISSION_GRANTED && !checkCarrierPrivilegeOnSubList(
2608                         subIdList, callingPackage)) {
2609             throw new SecurityException("CreateSubscriptionGroup needs MODIFY_PHONE_STATE or"
2610                     + " carrier privilege permission on all specified subscriptions");
2611         }
2612 
2613         enforceTelephonyFeatureWithException(callingPackage, "createSubscriptionGroup");
2614 
2615         long identity = Binder.clearCallingIdentity();
2616 
2617         try {
2618             // Generate a UUID.
2619             ParcelUuid groupUUID = new ParcelUuid(UUID.randomUUID());
2620             String uuidString = groupUUID.toString();
2621 
2622             for (int subId : subIdList) {
2623                 mSubscriptionDatabaseManager.setGroupUuid(subId, uuidString);
2624                 mSubscriptionDatabaseManager.setGroupOwner(subId, callingPackage);
2625             }
2626             updateGroupDisabled();
2627 
2628             MultiSimSettingController.getInstance().notifySubscriptionGroupChanged(groupUUID);
2629             return groupUUID;
2630         } finally {
2631             Binder.restoreCallingIdentity(identity);
2632         }
2633     }
2634 
2635     /**
2636      * Set which subscription is preferred for cellular data. It's designed to overwrite default
2637      * data subscription temporarily.
2638      *
2639      * @param subId which subscription is preferred to for cellular data
2640      * @param needValidation whether validation is needed before switching
2641      * @param callback callback upon request completion
2642      *
2643      * @throws SecurityException if callers do not hold the required permission.
2644      */
2645     @Override
2646     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
setPreferredDataSubscriptionId(int subId, boolean needValidation, @Nullable ISetOpportunisticDataCallback callback)2647     public void setPreferredDataSubscriptionId(int subId, boolean needValidation,
2648             @Nullable ISetOpportunisticDataCallback callback) {
2649         enforcePermissions("setPreferredDataSubscriptionId",
2650                 Manifest.permission.MODIFY_PHONE_STATE);
2651 
2652         enforceTelephonyFeatureWithException(getCurrentPackageName(),
2653                 "setPreferredDataSubscriptionId");
2654 
2655         final long token = Binder.clearCallingIdentity();
2656 
2657         try {
2658             PhoneSwitcher phoneSwitcher = PhoneSwitcher.getInstance();
2659             if (phoneSwitcher == null) {
2660                 loge("Set preferred data sub: phoneSwitcher is null.");
2661                 if (callback != null) {
2662                     try {
2663                         callback.onComplete(
2664                                 TelephonyManager.SET_OPPORTUNISTIC_SUB_REMOTE_SERVICE_EXCEPTION);
2665                     } catch (RemoteException exception) {
2666                         loge("RemoteException " + exception);
2667                     }
2668                 }
2669                 return;
2670             }
2671 
2672             phoneSwitcher.trySetOpportunisticDataSubscription(subId, needValidation, callback);
2673         } finally {
2674             Binder.restoreCallingIdentity(token);
2675         }
2676     }
2677 
2678     /**
2679      * @return The subscription id of preferred subscription for cellular data. This reflects
2680      * the active modem which can serve large amount of cellular data.
2681      *
2682      * @throws SecurityException if callers do not hold the required permission.
2683      */
2684     @Override
2685     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
getPreferredDataSubscriptionId()2686     public int getPreferredDataSubscriptionId() {
2687         enforcePermissions("getPreferredDataSubscriptionId",
2688                 Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
2689         final long token = Binder.clearCallingIdentity();
2690 
2691         try {
2692             PhoneSwitcher phoneSwitcher = PhoneSwitcher.getInstance();
2693             if (phoneSwitcher == null) {
2694                 loge("getPreferredDataSubscriptionId: PhoneSwitcher not available. Return the "
2695                         + "default data sub " + getDefaultDataSubId());
2696                 return getDefaultDataSubId();
2697             }
2698 
2699             return phoneSwitcher.getAutoSelectedDataSubId();
2700         } finally {
2701             Binder.restoreCallingIdentity(token);
2702         }
2703     }
2704 
2705     /**
2706      * Get the opportunistic subscriptions.
2707      *
2708      * Callers with {@link Manifest.permission#READ_PHONE_STATE} or
2709      * {@link Manifest.permission#READ_PRIVILEGED_PHONE_STATE} will have a full list of
2710      * opportunistic subscriptions. Subscriptions that the carrier app has no privilege will be
2711      * excluded from the list.
2712      *
2713      * @param callingPackage The package making the call.
2714      * @param callingFeatureId The feature in the package.
2715      *
2716      * @return The list of opportunistic subscription info that can be accessed by the callers.
2717      */
2718     @Override
2719     @NonNull
2720     @RequiresPermission(anyOf = {
2721             Manifest.permission.READ_PHONE_STATE,
2722             Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
2723             "carrier privileges",
2724     })
getOpportunisticSubscriptions(@onNull String callingPackage, @Nullable String callingFeatureId)2725     public List<SubscriptionInfo> getOpportunisticSubscriptions(@NonNull String callingPackage,
2726             @Nullable String callingFeatureId) {
2727         // Check if the caller has READ_PHONE_STATE, READ_PRIVILEGED_PHONE_STATE, or carrier
2728         // privilege on any active subscription. The carrier app will get full subscription infos
2729         // on the subs it has carrier privilege.
2730         if (!TelephonyPermissions.checkReadPhoneStateOnAnyActiveSub(mContext,
2731                 Binder.getCallingPid(), Binder.getCallingUid(), callingPackage, callingFeatureId,
2732                 "getOpportunisticSubscriptions")) {
2733             // Ideally we should avoid silent failure, but since this API has already been used by
2734             // many apps and they do not expect the security exception, we return an empty list
2735             // here so it's consistent with pre-U behavior.
2736             loge("getOpportunisticSubscriptions: " + callingPackage + " does not have enough "
2737                     + "permission. Returning empty list here.");
2738             return Collections.emptyList();
2739         }
2740 
2741         enforceTelephonyFeatureWithException(callingPackage, "getOpportunisticSubscriptions");
2742 
2743         return mSubscriptionDatabaseManager.getAllSubscriptions().stream()
2744                 // callers have READ_PHONE_STATE or READ_PRIVILEGED_PHONE_STATE can get a full
2745                 // list. Carrier apps can only get the subscriptions they have privileged.
2746                 .filter(subInfo -> subInfo.isOpportunistic()
2747                         && TelephonyPermissions.checkCallingOrSelfReadPhoneStateNoThrow(
2748                         mContext, subInfo.getSubscriptionId(), callingPackage,
2749                         callingFeatureId, "getOpportunisticSubscriptions"))
2750                 // Remove the identifier if the caller does not have sufficient permission.
2751                 // carrier apps will get full subscription info on the subscriptions associated
2752                 // to them.
2753                 .map(subInfo -> conditionallyRemoveIdentifiers(subInfo.toSubscriptionInfo(),
2754                         callingPackage, callingFeatureId, "getOpportunisticSubscriptions"))
2755                 .sorted(Comparator.comparing(SubscriptionInfo::getSimSlotIndex)
2756                         .thenComparing(SubscriptionInfo::getSubscriptionId))
2757                 .collect(Collectors.toList());
2758     }
2759 
2760     /**
2761      * Remove a list of subscriptions from their subscription group.
2762      *
2763      * @param subIdList list of subId that need removing from their groups.
2764      * @param groupUuid The UUID of the subscription group.
2765      * @param callingPackage The package making the call.
2766      *
2767      * @throws SecurityException if the caller doesn't meet the requirements outlined above.
2768      * @throws IllegalArgumentException if the some subscriptions in the list doesn't belong the
2769      * specified group.
2770      *
2771      * @see SubscriptionManager#createSubscriptionGroup(List)
2772      */
2773     @Override
2774     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
removeSubscriptionsFromGroup(@onNull int[] subIdList, @NonNull ParcelUuid groupUuid, @NonNull String callingPackage)2775     public void removeSubscriptionsFromGroup(@NonNull int[] subIdList,
2776             @NonNull ParcelUuid groupUuid, @NonNull String callingPackage) {
2777         // If it doesn't have modify phone state permission, or carrier privilege permission,
2778         // a SecurityException will be thrown. If it's due to invalid parameter or internal state,
2779         // it will return null.
2780         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
2781                 != PackageManager.PERMISSION_GRANTED
2782                 && !(checkCarrierPrivilegeOnSubList(subIdList, callingPackage)
2783                 && canPackageManageGroup(groupUuid, callingPackage))) {
2784             throw new SecurityException("removeSubscriptionsFromGroup needs MODIFY_PHONE_STATE or"
2785                     + " carrier privilege permission on all specified subscriptions.");
2786         }
2787 
2788         Objects.requireNonNull(subIdList);
2789         Objects.requireNonNull(groupUuid);
2790 
2791         if (subIdList.length == 0) {
2792             throw new IllegalArgumentException("subIdList is empty.");
2793         }
2794 
2795         enforceTelephonyFeatureWithException(callingPackage, "removeSubscriptionsFromGroup");
2796 
2797         long identity = Binder.clearCallingIdentity();
2798 
2799         try {
2800             for (int subId : subIdList) {
2801                 SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager
2802                         .getSubscriptionInfoInternal(subId);
2803                 if (subInfo == null) {
2804                     throw new IllegalArgumentException("The provided sub id " + subId
2805                             + " is not valid.");
2806                 }
2807                 if (!groupUuid.toString().equals(subInfo.getGroupUuid())) {
2808                     throw new IllegalArgumentException("Subscription " + subInfo.getSubscriptionId()
2809                             + " doesn't belong to group " + groupUuid);
2810                 }
2811             }
2812 
2813             for (SubscriptionInfoInternal subInfo :
2814                     mSubscriptionDatabaseManager.getAllSubscriptions()) {
2815                 if (IntStream.of(subIdList).anyMatch(
2816                         subId -> subId == subInfo.getSubscriptionId())) {
2817                     mSubscriptionDatabaseManager.setGroupUuid(subInfo.getSubscriptionId(), "");
2818                     mSubscriptionDatabaseManager.setGroupOwner(subInfo.getSubscriptionId(), "");
2819                 } else if (subInfo.getGroupUuid().equals(groupUuid.toString())) {
2820                     // Pre-T behavior. If there are still subscriptions having the same UUID, update
2821                     // to the new owner.
2822                     mSubscriptionDatabaseManager.setGroupOwner(
2823                             subInfo.getSubscriptionId(), callingPackage);
2824                 }
2825             }
2826 
2827             updateGroupDisabled();
2828         } finally {
2829             Binder.restoreCallingIdentity(identity);
2830         }
2831     }
2832 
2833     /**
2834      * Add a list of subscriptions into a group.
2835      *
2836      * Caller should either have {@link android.Manifest.permission#MODIFY_PHONE_STATE}
2837      * permission or had carrier privilege permission on the subscriptions.
2838      *
2839      * @param subIdList list of subId that need adding into the group
2840      * @param groupUuid the groupUuid the subscriptions are being added to.
2841      * @param callingPackage The package making the call.
2842      *
2843      * @throws SecurityException if the caller doesn't meet the requirements outlined above.
2844      * @throws IllegalArgumentException if the some subscriptions in the list doesn't exist.
2845      *
2846      * @see SubscriptionManager#createSubscriptionGroup(List)
2847      */
2848     @Override
2849     @RequiresPermission(anyOf = {
2850             Manifest.permission.MODIFY_PHONE_STATE,
2851             "carrier privileges",
2852     })
addSubscriptionsIntoGroup(@onNull int[] subIdList, @NonNull ParcelUuid groupUuid, @NonNull String callingPackage)2853     public void addSubscriptionsIntoGroup(@NonNull int[] subIdList, @NonNull ParcelUuid groupUuid,
2854             @NonNull String callingPackage) {
2855         Objects.requireNonNull(subIdList, "subIdList");
2856         if (subIdList.length == 0) {
2857             throw new IllegalArgumentException("Invalid subId list");
2858         }
2859 
2860         Objects.requireNonNull(groupUuid, "groupUuid");
2861         String groupUuidString = groupUuid.toString();
2862         if (groupUuidString.equals(CarrierConfigManager.REMOVE_GROUP_UUID_STRING)) {
2863             throw new IllegalArgumentException("Invalid groupUuid");
2864         }
2865 
2866         // Verify that the callingPackage belongs to the calling UID
2867         mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage);
2868 
2869         // If it doesn't have modify phone state permission, or carrier privilege permission,
2870         // a SecurityException will be thrown.
2871         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
2872                 != PackageManager.PERMISSION_GRANTED
2873                 && !(checkCarrierPrivilegeOnSubList(subIdList, callingPackage)
2874                 && canPackageManageGroup(groupUuid, callingPackage))) {
2875             throw new SecurityException("Requires MODIFY_PHONE_STATE or carrier privilege"
2876                     + " permissions on subscriptions and the group.");
2877         }
2878 
2879         enforceTelephonyFeatureWithException(callingPackage, "addSubscriptionsIntoGroup");
2880 
2881         long identity = Binder.clearCallingIdentity();
2882 
2883         try {
2884             for (int subId : subIdList) {
2885                 mSubscriptionDatabaseManager.setGroupUuid(subId, groupUuidString);
2886                 mSubscriptionDatabaseManager.setGroupOwner(subId, callingPackage);
2887             }
2888 
2889             updateGroupDisabled();
2890             MultiSimSettingController.getInstance().notifySubscriptionGroupChanged(groupUuid);
2891             logl("addSubscriptionsIntoGroup: add subs " + Arrays.toString(subIdList)
2892                     + " to the group.");
2893         } finally {
2894             Binder.restoreCallingIdentity(identity);
2895         }
2896     }
2897 
2898     /**
2899      * Get subscriptionInfo list of subscriptions that are in the same group of given subId.
2900      * See {@link #createSubscriptionGroup(int[], String)} for more details.
2901      *
2902      * Caller must have {@link android.Manifest.permission#READ_PHONE_STATE}
2903      * or carrier privilege permission on the subscription.
2904      *
2905      * <p>Starting with API level 33, the caller also needs permission to access device identifiers
2906      * to get the list of subscriptions associated with a group UUID.
2907      * This method can be invoked if one of the following requirements is met:
2908      * <ul>
2909      *     <li>If the app has carrier privilege permission.
2910      *     {@link TelephonyManager#hasCarrierPrivileges()}
2911      *     <li>If the app has {@link android.Manifest.permission#READ_PHONE_STATE} permission and
2912      *     access to device identifiers.
2913      * </ul>
2914      *
2915      * @param groupUuid of which list of subInfo will be returned.
2916      * @param callingPackage The package making the call.
2917      * @param callingFeatureId The feature in the package.
2918      *
2919      * @return List of {@link SubscriptionInfo} that belong to the same group, including the given
2920      * subscription itself. It will return an empty list if no subscription belongs to the group.
2921      *
2922      * @throws SecurityException if the caller doesn't meet the requirements outlined above.
2923      */
2924     @Override
2925     @NonNull
2926     @RequiresPermission(anyOf = {
2927             Manifest.permission.READ_PHONE_STATE,
2928             Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
2929             "carrier privileges",
2930     })
getSubscriptionsInGroup(@onNull ParcelUuid groupUuid, @NonNull String callingPackage, @Nullable String callingFeatureId)2931     public List<SubscriptionInfo> getSubscriptionsInGroup(@NonNull ParcelUuid groupUuid,
2932             @NonNull String callingPackage, @Nullable String callingFeatureId) {
2933         // If the calling app neither has carrier privileges nor READ_PHONE_STATE and access to
2934         // device identifiers, it will throw a SecurityException.
2935         if (CompatChanges.isChangeEnabled(REQUIRE_DEVICE_IDENTIFIERS_FOR_GROUP_UUID,
2936                 Binder.getCallingUid())) {
2937             try {
2938                 if (!TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mContext,
2939                         callingPackage, callingFeatureId, "getSubscriptionsInGroup")) {
2940                     EventLog.writeEvent(0x534e4554, "213902861", Binder.getCallingUid());
2941                     throw new SecurityException("Need to have carrier privileges or access to "
2942                             + "device identifiers to call getSubscriptionsInGroup");
2943                 }
2944             } catch (SecurityException e) {
2945                 EventLog.writeEvent(0x534e4554, "213902861", Binder.getCallingUid());
2946                 throw e;
2947             }
2948         }
2949 
2950         enforceTelephonyFeatureWithException(callingPackage, "getSubscriptionsInGroup");
2951 
2952         return mSubscriptionDatabaseManager.getAllSubscriptions().stream()
2953                 .map(SubscriptionInfoInternal::toSubscriptionInfo)
2954                 .filter(info -> groupUuid.equals(info.getGroupUuid())
2955                         && (mSubscriptionManager.canManageSubscription(info, callingPackage)
2956                         || TelephonyPermissions.checkCallingOrSelfReadPhoneStateNoThrow(
2957                                 mContext, info.getSubscriptionId(), callingPackage,
2958                         callingFeatureId, "getSubscriptionsInGroup")))
2959                 .map(subscriptionInfo -> conditionallyRemoveIdentifiers(subscriptionInfo,
2960                         callingPackage, callingFeatureId, "getSubscriptionsInGroup"))
2961                 .collect(Collectors.toList());
2962     }
2963 
2964     /**
2965      * Get slot index associated with the subscription.
2966      *
2967      * @param subId The subscription id.
2968      *
2969      * @return Logical slot index (i.e. phone id) as a positive integer or
2970      * {@link SubscriptionManager#INVALID_SIM_SLOT_INDEX} if the supplied {@code subId} doesn't have
2971      * an associated slot index.
2972      */
2973     @Override
getSlotIndex(int subId)2974     public int getSlotIndex(int subId) {
2975         if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
2976             subId = getDefaultSubId();
2977         }
2978 
2979         for (Map.Entry<Integer, Integer> entry : mSlotIndexToSubId.entrySet()) {
2980             if (entry.getValue() == subId) return entry.getKey();
2981         }
2982 
2983         return SubscriptionManager.INVALID_SIM_SLOT_INDEX;
2984     }
2985 
2986     /**
2987      * Get the subscription id for specified slot index.
2988      *
2989      * @param slotIndex Logical SIM slot index.
2990      * @return The subscription id. {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} if SIM is
2991      * absent.
2992      */
2993     @Override
getSubId(int slotIndex)2994     public int getSubId(int slotIndex) {
2995         if (slotIndex == SubscriptionManager.DEFAULT_SIM_SLOT_INDEX) {
2996             slotIndex = getSlotIndex(getDefaultSubId());
2997         }
2998 
2999         // Check that we have a valid slotIndex or the slotIndex is for a remote SIM (remote SIM
3000         // uses special slot index that may be invalid otherwise)
3001         if (!SubscriptionManager.isValidSlotIndex(slotIndex)
3002                 && slotIndex != SubscriptionManager.SLOT_INDEX_FOR_REMOTE_SIM_SUB) {
3003             return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
3004         }
3005 
3006         return mSlotIndexToSubId.getOrDefault(slotIndex,
3007                 SubscriptionManager.INVALID_SUBSCRIPTION_ID);
3008     }
3009 
3010     /**
3011      * Update default sub id.
3012      */
updateDefaultSubId()3013     private void updateDefaultSubId() {
3014         int subId;
3015         boolean isVoiceCapable = mTelephonyManager.isVoiceCapable();
3016 
3017         if (isVoiceCapable) {
3018             subId = getDefaultVoiceSubId();
3019         } else {
3020             subId = getDefaultDataSubId();
3021         }
3022 
3023         // If the subId is not active, use the fist active subscription's subId.
3024         if (!mSlotIndexToSubId.containsValue(subId)) {
3025             int[] activeSubIds = getActiveSubIdList(true);
3026             if (activeSubIds.length > 0) {
3027                 subId = activeSubIds[0];
3028                 log("updateDefaultSubId: First available active sub = " + subId);
3029             } else {
3030                 subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
3031             }
3032         }
3033 
3034         if (mDefaultSubId.get() != subId) {
3035             int phoneId = getPhoneId(subId);
3036             logl("updateDefaultSubId: Default sub id updated from " + mDefaultSubId.get() + " to "
3037                     + subId + ", phoneId=" + phoneId);
3038             mDefaultSubId.set(subId);
3039 
3040             Intent intent = new Intent(SubscriptionManager.ACTION_DEFAULT_SUBSCRIPTION_CHANGED);
3041             intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
3042             SubscriptionManager.putPhoneIdAndSubIdExtra(intent, phoneId, subId);
3043             mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
3044         }
3045     }
3046 
3047     /**
3048      * @return The default subscription id.
3049      * @deprecated Use {@link #getDefaultSubIdAsUser}.
3050      */
3051     @Override
getDefaultSubId()3052     public int getDefaultSubId() {
3053         return getDefaultSubIdAsUser(BINDER_WRAPPER.getCallingUserHandle().getIdentifier());
3054     }
3055 
3056     /**
3057      * @param userId The given user Id to check.
3058      * @return The default subscription id.
3059      */
3060     @Override
getDefaultSubIdAsUser(@serIdInt int userId)3061     public int getDefaultSubIdAsUser(@UserIdInt int userId) {
3062         enforceTelephonyFeatureWithException(getCurrentPackageName(),
3063                 "getDefaultVoiceSubIdAsUser");
3064 
3065         return getDefaultAsUser(userId, mDefaultSubId.get());
3066     }
3067 
3068     /**
3069      * Get the default subscription visible to the caller.
3070      * @param userId The calling user Id.
3071      * @param defaultValue Useful if the user owns more than one subscription.
3072      * @return The subscription Id default to use.
3073      */
getDefaultAsUser(@serIdInt int userId, int defaultValue)3074     private int getDefaultAsUser(@UserIdInt int userId, int defaultValue) {
3075         // TODO: Not using mFlags.enforceSubscriptionUserFilter because this affects U CTS.
3076         if (mFeatureFlags.workProfileApiSplit()) {
3077             List<SubscriptionInfoInternal> subInfos =
3078                     getSubscriptionInfoStreamAsUser(UserHandle.of(userId))
3079                             .filter(SubscriptionInfoInternal::isActive)
3080                             .toList();
3081             if (subInfos.size() == 1) {
3082                 return subInfos.get(0).getSubscriptionId();
3083             }
3084         }
3085         return defaultValue;
3086     }
3087 
3088     /**
3089      * Get phone id from the subscription id. In the implementation, the logical SIM slot index
3090      * is equivalent to phone id. So this method is same as {@link #getSlotIndex(int)}.
3091      *
3092      * @param subId The subscription id.
3093      *
3094      * @return The phone id.
3095      */
3096     @Override
getPhoneId(int subId)3097     public int getPhoneId(int subId) {
3098         if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
3099             subId = getDefaultSubId();
3100         }
3101 
3102         if (!SubscriptionManager.isValidSubscriptionId(subId)) {
3103             return SubscriptionManager.INVALID_PHONE_INDEX;
3104         }
3105 
3106         // slot index and phone id are equivalent in the current implementation.
3107         int slotIndex = getSlotIndex(subId);
3108         if (SubscriptionManager.isValidSlotIndex(slotIndex)) {
3109             return slotIndex;
3110         }
3111 
3112         return SubscriptionManager.DEFAULT_PHONE_INDEX;
3113     }
3114 
3115     /**
3116      * @return Subscription id of the default cellular data. This reflects the user's default data
3117      * choice, which might be a little bit different than the active one returned by
3118      * {@link #getPreferredDataSubscriptionId()}.
3119      */
3120     @Override
getDefaultDataSubId()3121     public int getDefaultDataSubId() {
3122         return mDefaultDataSubId.get();
3123     }
3124 
3125     /**
3126      * Set the default data subscription id.
3127      *
3128      * @param subId The default data subscription id.
3129      *
3130      * @throws SecurityException if callers do not hold the required permission.
3131      */
3132     @Override
3133     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
setDefaultDataSubId(int subId)3134     public void setDefaultDataSubId(int subId) {
3135         enforcePermissions("setDefaultDataSubId", Manifest.permission.MODIFY_PHONE_STATE);
3136 
3137         if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
3138             throw new RuntimeException("setDefaultDataSubId called with DEFAULT_SUBSCRIPTION_ID");
3139         }
3140 
3141         enforceTelephonyFeatureWithException(getCurrentPackageName(), "setDefaultDataSubId");
3142 
3143         final long token = Binder.clearCallingIdentity();
3144         try {
3145             if (mDefaultDataSubId.set(subId)) {
3146                 remapRafIfApplicable();
3147 
3148                 MultiSimSettingController.getInstance().notifyDefaultDataSubChanged();
3149 
3150                 broadcastSubId(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED,
3151                         subId);
3152 
3153                 updateDefaultSubId();
3154             }
3155         } finally {
3156             Binder.restoreCallingIdentity(token);
3157         }
3158     }
3159 
3160     /**
3161      * Remap Radio Access Family if needed.
3162      */
remapRafIfApplicable()3163     private void remapRafIfApplicable() {
3164         boolean applicable = mSlotIndexToSubId.containsValue(getDefaultDataSubId());
3165         if (!applicable) return;
3166         ProxyController proxyController = ProxyController.getInstance();
3167         RadioAccessFamily[] rafs = new RadioAccessFamily[mTelephonyManager.getActiveModemCount()];
3168         for (int phoneId = 0; phoneId < rafs.length; phoneId++) {
3169             int raf = mSlotIndexToSubId.getOrDefault(phoneId,
3170                     SubscriptionManager.INVALID_SUBSCRIPTION_ID) == getDefaultDataSubId()
3171                     ? proxyController.getMaxRafSupported() : proxyController.getMinRafSupported();
3172             rafs[phoneId] = new RadioAccessFamily(phoneId, raf);
3173         }
3174         proxyController.setRadioCapability(rafs);
3175     }
3176 
3177     /**
3178      * @return The default subscription id for voice.
3179      * @deprecated Use {@link #getDefaultVoiceSubIdAsUser}.
3180      */
3181     @Override
getDefaultVoiceSubId()3182     public int getDefaultVoiceSubId() {
3183         return getDefaultVoiceSubIdAsUser(BINDER_WRAPPER.getCallingUserHandle().getIdentifier());
3184     }
3185 
3186     /**
3187      * @param userId The calling user Id.
3188      * @return The default voice subscription id.
3189      */
3190     @Override
getDefaultVoiceSubIdAsUser(@serIdInt int userId)3191     public int getDefaultVoiceSubIdAsUser(@UserIdInt int userId) {
3192         return getDefaultAsUser(userId, mDefaultVoiceSubId.get());
3193     }
3194 
3195     /**
3196      * Set the default voice subscription id.
3197      *
3198      * @param subId The default SMS subscription id.
3199      *
3200      * @throws SecurityException if callers do not hold the required permission.
3201      */
3202     @Override
3203     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
setDefaultVoiceSubId(int subId)3204     public void setDefaultVoiceSubId(int subId) {
3205         enforcePermissions("setDefaultVoiceSubId", Manifest.permission.MODIFY_PHONE_STATE);
3206 
3207         if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
3208             throw new RuntimeException("setDefaultVoiceSubId called with DEFAULT_SUB_ID");
3209         }
3210 
3211         enforceTelephonyFeatureWithException(getCurrentPackageName(), "setDefaultVoiceSubId");
3212 
3213         final long token = Binder.clearCallingIdentity();
3214         try {
3215             if (mDefaultVoiceSubId.set(subId)) {
3216                 broadcastSubId(TelephonyIntents.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED,
3217                         subId);
3218 
3219                 PhoneAccountHandle newHandle = subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID
3220                         ? null : mTelephonyManager.getPhoneAccountHandleForSubscriptionId(subId);
3221 
3222                 TelecomManager telecomManager = mContext.getSystemService(TelecomManager.class);
3223                 if (telecomManager != null) {
3224                     telecomManager.setUserSelectedOutgoingPhoneAccount(newHandle);
3225                 }
3226 
3227                 updateDefaultSubId();
3228             }
3229 
3230         } finally {
3231             Binder.restoreCallingIdentity(token);
3232         }
3233     }
3234 
3235     /**
3236      * @return The default subscription id for SMS.
3237      * @deprecated Use {@link #getDefaultSmsSubIdAsUser}.
3238      */
3239     @Override
getDefaultSmsSubId()3240     public int getDefaultSmsSubId() {
3241         return getDefaultSmsSubIdAsUser(BINDER_WRAPPER.getCallingUserHandle().getIdentifier());
3242     }
3243 
3244     /**
3245      * Get the default sms subscription id associated with the user. When a subscription is
3246      * associated with personal profile or work profile, the default sms subscription id will be
3247      * always the subscription it is associated with.
3248      *
3249      * @param userId The given user Id to check.
3250      * @return The default voice id.
3251      */
3252     @Override
getDefaultSmsSubIdAsUser(@serIdInt int userId)3253     public int getDefaultSmsSubIdAsUser(@UserIdInt int userId) {
3254         return getDefaultAsUser(userId, mDefaultSmsSubId.get());
3255     }
3256 
3257     /**
3258      * Set the default SMS subscription id.
3259      *
3260      * @param subId The default SMS subscription id.
3261      *
3262      * @throws SecurityException if callers do not hold the required permission.
3263      */
3264     @Override
3265     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
setDefaultSmsSubId(int subId)3266     public void setDefaultSmsSubId(int subId) {
3267         enforcePermissions("setDefaultSmsSubId", Manifest.permission.MODIFY_PHONE_STATE);
3268 
3269         if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
3270             throw new RuntimeException("setDefaultSmsSubId called with DEFAULT_SUB_ID");
3271         }
3272 
3273         enforceTelephonyFeatureWithException(getCurrentPackageName(), "setDefaultSmsSubId");
3274 
3275         final long token = Binder.clearCallingIdentity();
3276         try {
3277             if (mDefaultSmsSubId.set(subId)) {
3278                 broadcastSubId(SubscriptionManager.ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED,
3279                         subId);
3280             }
3281 
3282         } finally {
3283             Binder.restoreCallingIdentity(token);
3284         }
3285     }
3286 
3287     /**
3288      * Broadcast a sub Id with the given action.
3289      * @param action The intent action.
3290      * @param newSubId The sub Id to broadcast.
3291      */
broadcastSubId(@onNull String action, int newSubId)3292     private void broadcastSubId(@NonNull String action, int newSubId) {
3293         Intent intent = new Intent(action);
3294         intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
3295         SubscriptionManager.putSubscriptionIdExtra(intent, newSubId);
3296         mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
3297         log("broadcastSubId action: " + action + " subId= " + newSubId);
3298     }
3299 
3300     /**
3301      * Get the active subscription id list.
3302      *
3303      * @param visibleOnly {@code true} if only includes user visible subscription's sub id.
3304      *
3305      * @return List of the active subscription id.
3306      *
3307      * @throws SecurityException if callers do not hold the required permission.
3308      */
3309     @Override
3310     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
getActiveSubIdList(boolean visibleOnly)3311     public int[] getActiveSubIdList(boolean visibleOnly) {
3312         enforcePermissions("getActiveSubIdList", Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
3313 
3314         enforceTelephonyFeatureWithException(getCurrentPackageName(), "getActiveSubIdList");
3315 
3316         // UserHandle.ALL because this API is exposed as system API.
3317         return getActiveSubIdListAsUser(visibleOnly, UserHandle.ALL);
3318     }
3319 
3320     /**
3321      * Get the active subscription id list as user.
3322      * Must be used before clear Binder identity.
3323      *
3324      * @param visibleOnly {@code true} if only includes user visible subscription's sub id.
3325      * @param user If {@code null}, uses the calling user handle to judge which subscriptions are
3326      *             accessible to the caller.
3327      * @return List of the active subscription id.
3328      */
getActiveSubIdListAsUser(boolean visibleOnly, @NonNull final UserHandle user)3329     private int[] getActiveSubIdListAsUser(boolean visibleOnly, @NonNull final UserHandle user) {
3330         return mSlotIndexToSubId.values().stream()
3331                 .filter(subId -> {
3332                     SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager
3333                             .getSubscriptionInfoInternal(subId);
3334                     return subInfo != null && (!visibleOnly || subInfo.isVisible())
3335                             && isSubscriptionAssociatedWithUserInternal(
3336                                     subInfo, user.getIdentifier());
3337                 })
3338                 .mapToInt(x -> x)
3339                 .toArray();
3340     }
3341 
3342     /**
3343      * Set a field in the subscription database. Note not all fields are supported.
3344      *
3345      * @param subId Subscription Id of Subscription.
3346      * @param columnName Column name in the database. Note not all fields are supported.
3347      * @param value Value to store in the database.
3348      *
3349      * @throws IllegalArgumentException if {@code subscriptionId} is invalid, or the field is not
3350      * exposed.
3351      * @throws SecurityException if callers do not hold the required permission.
3352      *
3353      * @see #getSubscriptionProperty(int, String, String, String)
3354      * @see SimInfo for all the columns.
3355      */
3356     @Override
3357     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
setSubscriptionProperty(int subId, @NonNull String columnName, @NonNull String value)3358     public void setSubscriptionProperty(int subId, @NonNull String columnName,
3359             @NonNull String value) {
3360         enforcePermissions("setSubscriptionProperty", Manifest.permission.MODIFY_PHONE_STATE);
3361 
3362         final long token = Binder.clearCallingIdentity();
3363         try {
3364             logl("setSubscriptionProperty: subId=" + subId + ", columnName=" + columnName
3365                     + ", value=" + value + ", calling package=" + getCallingPackage());
3366 
3367             if (!SimInfo.getAllColumns().contains(columnName)) {
3368                 throw new IllegalArgumentException("Invalid column name " + columnName);
3369             }
3370 
3371             // Check if the columns are allowed to be accessed through the generic
3372             // getSubscriptionProperty method.
3373             if (!DIRECT_ACCESS_SUBSCRIPTION_COLUMNS.contains(columnName)) {
3374                 throw new SecurityException("Column " + columnName + " is not allowed be directly "
3375                         + "accessed through setSubscriptionProperty.");
3376             }
3377 
3378             mSubscriptionDatabaseManager.setSubscriptionProperty(subId, columnName, value);
3379         } finally {
3380             Binder.restoreCallingIdentity(token);
3381         }
3382     }
3383 
3384     /**
3385      * Get specific field in string format from the subscription info database.
3386      *
3387      * @param subId Subscription id of the subscription.
3388      * @param columnName Column name in subscription database.
3389      *
3390      * @return Value in string format associated with {@code subscriptionId} and {@code columnName}
3391      * from the database. {@code null} if the {@code subscriptionId} is invalid (for backward
3392      * compatible).
3393      *
3394      * @throws IllegalArgumentException if the field is not exposed.
3395      * @throws SecurityException if callers do not hold the required permission.
3396      *
3397      * @see SimInfo for all the columns.
3398      */
3399     @Override
3400     @Nullable
3401     @RequiresPermission(anyOf = {
3402             Manifest.permission.READ_PHONE_STATE,
3403             Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
3404             "carrier privileges",
3405     })
getSubscriptionProperty(int subId, @NonNull String columnName, @NonNull String callingPackage, @Nullable String callingFeatureId)3406     public String getSubscriptionProperty(int subId, @NonNull String columnName,
3407             @NonNull String callingPackage, @Nullable String callingFeatureId) {
3408         Objects.requireNonNull(columnName);
3409         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mContext, subId,
3410                 callingPackage, callingFeatureId,
3411                 "getSubscriptionProperty")) {
3412             throw new SecurityException("Need READ_PHONE_STATE, READ_PRIVILEGED_PHONE_STATE, or "
3413                     + "carrier privilege");
3414         }
3415 
3416         if (!SimInfo.getAllColumns().contains(columnName)) {
3417             throw new IllegalArgumentException("Invalid column name " + columnName);
3418         }
3419 
3420         // Check if the columns are allowed to be accessed through the generic
3421         // getSubscriptionProperty method.
3422         if (!DIRECT_ACCESS_SUBSCRIPTION_COLUMNS.contains(columnName)) {
3423             throw new SecurityException("Column " + columnName + " is not allowed be directly "
3424                     + "accessed through getSubscriptionProperty.");
3425         }
3426 
3427         enforceTelephonyFeatureWithException(callingPackage, "getSubscriptionProperty");
3428 
3429         final long token = Binder.clearCallingIdentity();
3430         try {
3431             Object value = mSubscriptionDatabaseManager.getSubscriptionProperty(subId, columnName);
3432             // The raw types of subscription database should only have 3 different types.
3433             if (value instanceof Integer) {
3434                 return String.valueOf(value);
3435             } else if (value instanceof String) {
3436                 return (String) value;
3437             } else if (value instanceof byte[]) {
3438                 return Base64.encodeToString((byte[]) value, Base64.DEFAULT);
3439             } else {
3440                 // This should not happen unless SubscriptionDatabaseManager.getSubscriptionProperty
3441                 // did not implement correctly.
3442                 throw new RuntimeException("Unexpected type " + value.getClass().getTypeName()
3443                         + " was returned from SubscriptionDatabaseManager for column "
3444                         + columnName);
3445             }
3446         } catch (IllegalArgumentException e) {
3447             loge("getSubscriptionProperty: Invalid subId " + subId + ", columnName=" + columnName);
3448             return null;
3449         } finally {
3450             Binder.restoreCallingIdentity(token);
3451         }
3452     }
3453 
3454     /**
3455      * Check if a subscription is active.
3456      *
3457      * @param subId The subscription id to check.
3458      *
3459      * @return {@code true} if the subscription is active.
3460      *
3461      * @throws IllegalArgumentException if the provided slot index is invalid.
3462      * @throws SecurityException if callers do not hold the required permission.
3463      */
3464     @Override
3465     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
isSubscriptionEnabled(int subId)3466     public boolean isSubscriptionEnabled(int subId) {
3467         enforcePermissions("isSubscriptionEnabled",
3468                 Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
3469         if (!SubscriptionManager.isValidSubscriptionId(subId)) {
3470             throw new IllegalArgumentException("Invalid subscription id " + subId);
3471         }
3472 
3473         enforceTelephonyFeatureWithException(getCurrentPackageName(), "isSubscriptionEnabled");
3474 
3475         final long identity = Binder.clearCallingIdentity();
3476         try {
3477             SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager
3478                     .getSubscriptionInfoInternal(subId);
3479             return subInfo != null && subInfo.isActive();
3480         } finally {
3481             Binder.restoreCallingIdentity(identity);
3482         }
3483     }
3484 
3485     /**
3486      * Get the active subscription id by logical SIM slot index.
3487      *
3488      * @param slotIndex The logical SIM slot index.
3489      * @return The active subscription id.
3490      *
3491      * @throws IllegalArgumentException if the provided slot index is invalid.
3492      * @throws SecurityException if callers do not hold the required permission.
3493      */
3494     @Override
3495     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
getEnabledSubscriptionId(int slotIndex)3496     public int getEnabledSubscriptionId(int slotIndex) {
3497         enforcePermissions("getEnabledSubscriptionId",
3498                 Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
3499 
3500         if (!SubscriptionManager.isValidSlotIndex(slotIndex)) {
3501             throw new IllegalArgumentException("Invalid slot index " + slotIndex);
3502         }
3503 
3504         enforceTelephonyFeatureWithException(getCurrentPackageName(), "getEnabledSubscriptionId");
3505 
3506         final long identity = Binder.clearCallingIdentity();
3507         try {
3508             return mSubscriptionDatabaseManager.getAllSubscriptions().stream()
3509                     .filter(subInfo -> subInfo.isActive() && subInfo.getSimSlotIndex() == slotIndex)
3510                     .mapToInt(SubscriptionInfoInternal::getSubscriptionId)
3511                     .findFirst()
3512                     .orElse(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
3513         } finally {
3514             Binder.restoreCallingIdentity(identity);
3515         }
3516     }
3517 
3518     /**
3519      * Check if a subscription is active.
3520      *
3521      * @param subId The subscription id.
3522      * @param callingPackage The package making the call.
3523      * @param callingFeatureId The feature in the package.
3524      *
3525      * @return {@code true} if the subscription is active.
3526      *
3527      * @throws SecurityException if callers do not hold the required permission.
3528      */
3529     @Override
3530     @RequiresPermission(anyOf = {
3531             Manifest.permission.READ_PHONE_STATE,
3532             Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
3533             "carrier privileges",
3534     })
isActiveSubId(int subId, @NonNull String callingPackage, @Nullable String callingFeatureId)3535     public boolean isActiveSubId(int subId, @NonNull String callingPackage,
3536             @Nullable String callingFeatureId) {
3537         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mContext, subId, callingPackage,
3538                 callingFeatureId, "isActiveSubId")) {
3539             throw new SecurityException("Need READ_PHONE_STATE, READ_PRIVILEGED_PHONE_STATE, or "
3540                     + "carrier privilege");
3541         }
3542 
3543         enforceTelephonyFeatureWithException(callingPackage, "isActiveSubId");
3544 
3545         final long identity = Binder.clearCallingIdentity();
3546         try {
3547             SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager
3548                     .getSubscriptionInfoInternal(subId);
3549             return subInfo != null && subInfo.isActive();
3550         } finally {
3551             Binder.restoreCallingIdentity(identity);
3552         }
3553     }
3554 
3555     /**
3556      * Get active data subscription id. Active data subscription refers to the subscription
3557      * currently chosen to provide cellular internet connection to the user. This may be
3558      * different from getDefaultDataSubscriptionId().
3559      *
3560      * @return Active data subscription id if any is chosen, or
3561      * SubscriptionManager.INVALID_SUBSCRIPTION_ID if not.
3562      *
3563      * @see android.telephony.TelephonyCallback.ActiveDataSubscriptionIdListener
3564      */
3565     @Override
getActiveDataSubscriptionId()3566     public int getActiveDataSubscriptionId() {
3567         final long token = Binder.clearCallingIdentity();
3568         try {
3569             PhoneSwitcher phoneSwitcher = PhoneSwitcher.getInstance();
3570             if (phoneSwitcher != null) {
3571                 int activeDataSubId = phoneSwitcher.getActiveDataSubId();
3572                 if (SubscriptionManager.isUsableSubscriptionId(activeDataSubId)) {
3573                     return activeDataSubId;
3574                 }
3575             }
3576             // If phone switcher isn't ready, or active data sub id is not available, use default
3577             // sub id from settings.
3578             return getDefaultDataSubId();
3579         } finally {
3580             Binder.restoreCallingIdentity(token);
3581         }
3582     }
3583 
3584     /**
3585      * Whether it's supported to disable / re-enable a subscription on a physical (non-euicc) SIM.
3586      *
3587      * Physical SIM refers non-euicc, or aka non-programmable SIM.
3588      *
3589      * It provides whether a physical SIM card can be disabled without taking it out, which is done
3590      * via {@link SubscriptionManager#setSubscriptionEnabled(int, boolean)} API.
3591      *
3592      * @return whether can disable subscriptions on physical SIMs.
3593      *
3594      * @throws SecurityException if callers do not hold the required permission.
3595      */
3596     @Override
3597     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
canDisablePhysicalSubscription()3598     public boolean canDisablePhysicalSubscription() {
3599         enforcePermissions("canDisablePhysicalSubscription",
3600                 Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
3601 
3602         enforceTelephonyFeatureWithException(getCurrentPackageName(),
3603                 "canDisablePhysicalSubscription");
3604 
3605         final long identity = Binder.clearCallingIdentity();
3606         try {
3607             Phone phone = PhoneFactory.getDefaultPhone();
3608             return phone != null && phone.canDisablePhysicalSubscription();
3609         } finally {
3610             Binder.restoreCallingIdentity(identity);
3611         }
3612     }
3613 
3614     /**
3615      * Set uicc applications being enabled or disabled.
3616      *
3617      * The value will be remembered on the subscription and will be applied whenever it's present.
3618      * If the subscription in currently present, it will also apply the setting to modem
3619      * immediately (the setting in the modem will not change until the modem receives and responds
3620      * to the request, but typically this should only take a few seconds. The user visible setting
3621      * available from {@link SubscriptionInfo#areUiccApplicationsEnabled()} will be updated
3622      * immediately.)
3623      *
3624      * @param enabled whether uicc applications are enabled or disabled.
3625      * @param subId which subscription to operate on.
3626      *
3627      * @throws IllegalArgumentException if the subscription does not exist.
3628      * @throws SecurityException if callers do not hold the required permission.
3629      */
3630     @Override
3631     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
setUiccApplicationsEnabled(boolean enabled, int subId)3632     public void setUiccApplicationsEnabled(boolean enabled, int subId) {
3633         enforcePermissions("setUiccApplicationsEnabled",
3634                 Manifest.permission.MODIFY_PHONE_STATE);
3635         logl("setUiccApplicationsEnabled: subId=" + subId + ", enabled=" + enabled
3636                 + ", calling package=" + getCallingPackage());
3637 
3638         enforceTelephonyFeatureWithException(getCurrentPackageName(),
3639                 "setUiccApplicationsEnabled");
3640 
3641         final long identity = Binder.clearCallingIdentity();
3642         try {
3643 
3644             SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager
3645                     .getSubscriptionInfoInternal(subId);
3646             if (subInfo == null) {
3647                 throw new IllegalArgumentException("setUiccApplicationsEnabled: Subscription "
3648                         + "doesn't exist. subId=" + subId);
3649             }
3650 
3651             if (subInfo.areUiccApplicationsEnabled() != enabled) {
3652                 mSubscriptionDatabaseManager.setUiccApplicationsEnabled(subId, enabled);
3653                 mSubscriptionManagerServiceCallbacks.forEach(
3654                         callback -> callback.invokeFromExecutor(
3655                                 () -> callback.onUiccApplicationsEnabledChanged(subId)));
3656             }
3657         } finally {
3658             Binder.restoreCallingIdentity(identity);
3659         }
3660     }
3661 
3662     /**
3663      * Set the device to device status sharing user preference for a subscription ID. The setting
3664      * app uses this method to indicate with whom they wish to share device to device status
3665      * information.
3666      *
3667      * @param sharing the status sharing preference.
3668      * @param subId the unique Subscription ID in database.
3669      *
3670      * @return the number of records updated.
3671      *
3672      * @throws IllegalArgumentException if the subscription does not exist, or the sharing
3673      * preference is invalid.
3674      * @throws SecurityException if callers do not hold the required permission.
3675      */
3676     @Override
3677     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
setDeviceToDeviceStatusSharing(@eviceToDeviceStatusSharingPreference int sharing, int subId)3678     public int setDeviceToDeviceStatusSharing(@DeviceToDeviceStatusSharingPreference int sharing,
3679             int subId) {
3680         enforcePermissions("setDeviceToDeviceStatusSharing",
3681                 Manifest.permission.MODIFY_PHONE_STATE);
3682 
3683         enforceTelephonyFeatureWithException(getCurrentPackageName(),
3684                 "setDeviceToDeviceStatusSharing");
3685 
3686         final long identity = Binder.clearCallingIdentity();
3687         try {
3688             if (sharing < SubscriptionManager.D2D_SHARING_DISABLED
3689                     || sharing > SubscriptionManager.D2D_SHARING_ALL) {
3690                 throw new IllegalArgumentException("invalid sharing " + sharing);
3691             }
3692 
3693             mSubscriptionDatabaseManager.setDeviceToDeviceStatusSharingPreference(subId, sharing);
3694             return 1;
3695         } finally {
3696             Binder.restoreCallingIdentity(identity);
3697         }
3698     }
3699 
3700     /**
3701      * Set the list of contacts that allow device to device status sharing for a subscription ID.
3702      * The setting app uses this method to indicate with whom they wish to share device to device
3703      * status information.
3704      *
3705      * @param contacts The list of contacts that allow device to device status sharing
3706      * @param subId The unique Subscription ID in database.
3707      *
3708      * @throws IllegalArgumentException if {@code subId} is invalid.
3709      * @throws NullPointerException if {@code contacts} is {@code null}.
3710      * @throws SecurityException if callers do not hold the required permission.
3711      */
3712     @Override
3713     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
setDeviceToDeviceStatusSharingContacts(@onNull String contacts, int subId)3714     public int setDeviceToDeviceStatusSharingContacts(@NonNull String contacts, int subId) {
3715         enforcePermissions("setDeviceToDeviceStatusSharingContacts",
3716                 Manifest.permission.MODIFY_PHONE_STATE);
3717 
3718         enforceTelephonyFeatureWithException(getCurrentPackageName(),
3719                 "setDeviceToDeviceStatusSharingContacts");
3720 
3721         final long identity = Binder.clearCallingIdentity();
3722         try {
3723             Objects.requireNonNull(contacts, "contacts");
3724             mSubscriptionDatabaseManager.setDeviceToDeviceStatusSharingContacts(subId, contacts);
3725             return 1;
3726         } finally {
3727             Binder.restoreCallingIdentity(identity);
3728         }
3729     }
3730 
3731     /**
3732      * Returns the phone number for the given {@code subscriptionId} and {@code source},
3733      * or an empty string if not available.
3734      *
3735      * <p>General apps that need to know the phone number should use
3736      * {@link SubscriptionManager#getPhoneNumber(int)} instead. This API may be suitable specific
3737      * apps that needs to know the phone number from a specific source. For example, a carrier app
3738      * needs to know exactly what's on {@link SubscriptionManager#PHONE_NUMBER_SOURCE_UICC UICC} and
3739      * decide if the previously set phone number of source
3740      * {@link SubscriptionManager#PHONE_NUMBER_SOURCE_CARRIER carrier} should be updated.
3741      *
3742      * <p>The API provides no guarantees of what format the number is in: the format can vary
3743      * depending on the {@code source} and the network etc. Programmatic parsing should be done
3744      * cautiously, for example, after formatting the number to a consistent format with
3745      * {@link android.telephony.PhoneNumberUtils#formatNumberToE164(String, String)}.
3746      *
3747      * <p>Note the assumption is that one subscription (which usually means one SIM) has
3748      * only one phone number. The multiple sources backup each other so hopefully at least one
3749      * is available. For example, for a carrier that doesn't typically set phone numbers
3750      * on {@link SubscriptionManager#PHONE_NUMBER_SOURCE_UICC UICC}, the source
3751      * {@link SubscriptionManager#PHONE_NUMBER_SOURCE_IMS IMS} may provide one. Or, a carrier may
3752      * decide to provide the phone number via source
3753      * {@link SubscriptionManager#PHONE_NUMBER_SOURCE_CARRIER carrier} if neither source UICC nor
3754      * IMS is available.
3755      *
3756      * <p>The availability and correctness of the phone number depends on the underlying source
3757      * and the network etc. Additional verification is needed to use this number for
3758      * security-related or other sensitive scenarios.
3759      *
3760      * @param subId The subscription ID.
3761      * @param source The source of the phone number.
3762      * @param callingPackage The package making the call.
3763      * @param callingFeatureId The feature in the package.
3764      *
3765      * @return The phone number, or an empty string if not available.
3766      *
3767      * @throws IllegalArgumentException if {@code source} is invalid.
3768      * @throws SecurityException if the caller doesn't have permissions required.
3769      *
3770      * @see SubscriptionManager#PHONE_NUMBER_SOURCE_UICC
3771      * @see SubscriptionManager#PHONE_NUMBER_SOURCE_CARRIER
3772      * @see SubscriptionManager#PHONE_NUMBER_SOURCE_IMS
3773      */
3774     @Override
3775     @NonNull
3776     @RequiresPermission(anyOf = {
3777             Manifest.permission.READ_PHONE_NUMBERS,
3778             Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
3779             "carrier privileges",
3780     })
getPhoneNumber(int subId, @PhoneNumberSource int source, @NonNull String callingPackage, @Nullable String callingFeatureId )3781     public String getPhoneNumber(int subId, @PhoneNumberSource int source,
3782             @NonNull String callingPackage, @Nullable String callingFeatureId /* unused */) {
3783         TelephonyPermissions.enforceAnyPermissionGrantedOrCarrierPrivileges(
3784                 mContext, subId, Binder.getCallingUid(), "getPhoneNumber",
3785                 Manifest.permission.READ_PHONE_NUMBERS,
3786                 Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
3787         enforceTelephonyFeatureWithException(callingPackage, "getPhoneNumber");
3788 
3789         if (mFeatureFlags.saferGetPhoneNumber()) {
3790             checkPhoneNumberSource(source);
3791             subId = checkAndGetSubId(subId);
3792             if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) return "";
3793 
3794             final long identity = Binder.clearCallingIdentity();
3795             try {
3796                 return getPhoneNumberFromSourceInternal(subId, source);
3797             } finally {
3798                 Binder.restoreCallingIdentity(identity);
3799             }
3800         } else {
3801             final long identity = Binder.clearCallingIdentity();
3802             try {
3803                 SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager
3804                         .getSubscriptionInfoInternal(subId);
3805 
3806                 if (subInfo == null) {
3807                     loge("Invalid sub id " + subId + ", callingPackage=" + callingPackage);
3808                     return "";
3809                 }
3810 
3811                 switch(source) {
3812                     case SubscriptionManager.PHONE_NUMBER_SOURCE_UICC:
3813                         Phone phone = PhoneFactory.getPhone(getSlotIndex(subId));
3814                         if (phone != null) {
3815                         return TextUtils.emptyIfNull(phone.getLine1Number());
3816                         } else {
3817                         return subInfo.getNumber();
3818                         }
3819                     case SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER:
3820                         return subInfo.getNumberFromCarrier();
3821                     case SubscriptionManager.PHONE_NUMBER_SOURCE_IMS:
3822                         return subInfo.getNumberFromIms();
3823                     default:
3824                         throw new IllegalArgumentException("Invalid number source " + source);
3825                 }
3826             } finally {
3827                 Binder.restoreCallingIdentity(identity);
3828             }
3829         }
3830     }
3831 
3832     /**
3833      * Get a resolved subId based on what the user passed in.
3834      *
3835      * Only use this before clearing the calling binder. Used for compatibility (only).
3836      * Do not use this behavior for new methods.
3837      *
3838      * @param subId the subId passed in by the user.
3839      */
checkAndGetSubId(int subId)3840     private int checkAndGetSubId(int subId) {
3841         if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
3842             // for historical reasons, INVALID_SUB_ID fails gracefully
3843             return subId;
3844         } else if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
3845             return getDefaultSubId();
3846         } else if (!SubscriptionManager.isValidSubscriptionId(subId)) {
3847             throw new IllegalArgumentException("Invalid SubId=" + subId);
3848         } else {
3849             return subId;
3850         }
3851     }
3852 
checkPhoneNumberSource(int source)3853     private void checkPhoneNumberSource(int source) {
3854         if (source == SubscriptionManager.PHONE_NUMBER_SOURCE_UICC
3855                 || source == SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER
3856                 || source == SubscriptionManager.PHONE_NUMBER_SOURCE_IMS) {
3857             return;
3858         }
3859 
3860         throw new IllegalArgumentException("Invalid number source " + source);
3861     }
3862 
getPhoneNumberFromSourceInternal( int subId, @PhoneNumberSource int source)3863     private @NonNull String getPhoneNumberFromSourceInternal(
3864             int subId,
3865             @PhoneNumberSource int source) {
3866 
3867         final SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager
3868                 .getSubscriptionInfoInternal(subId);
3869 
3870         if (subInfo == null) {
3871             loge("No SubscriptionInfo found for subId=" + subId);
3872             return "";
3873         }
3874 
3875         switch(source) {
3876             case SubscriptionManager.PHONE_NUMBER_SOURCE_UICC:
3877                 final Phone phone = PhoneFactory.getPhone(getSlotIndex(subId));
3878                 if (phone != null) {
3879                     return TextUtils.emptyIfNull(phone.getLine1Number());
3880                 } else {
3881                     return subInfo.getNumber();
3882                 }
3883             case SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER:
3884                 return subInfo.getNumberFromCarrier();
3885             case SubscriptionManager.PHONE_NUMBER_SOURCE_IMS:
3886                 return subInfo.getNumberFromIms();
3887             default:
3888                 loge("No SubscriptionInfo found for subId=" + subId);
3889                 return "";
3890         }
3891     }
3892 
3893     /**
3894      * Get phone number from first available source. The order would be
3895      * {@link SubscriptionManager#PHONE_NUMBER_SOURCE_CARRIER},
3896      * {@link SubscriptionManager#PHONE_NUMBER_SOURCE_UICC}, then
3897      * {@link SubscriptionManager#PHONE_NUMBER_SOURCE_IMS}.
3898      *
3899      * @param subId The subscription ID.
3900      * @param callingPackage The package making the call.
3901      * @param callingFeatureId The feature in the package.
3902      *
3903      * @return The phone number from the first available source.
3904      *
3905      * @throws IllegalArgumentException if {@code subId} is invalid.
3906      * @throws SecurityException if callers do not hold the required permission.
3907      */
3908     @Override
3909     @NonNull
3910     @RequiresPermission(anyOf = {
3911             Manifest.permission.READ_PHONE_NUMBERS,
3912             Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
3913             "carrier privileges",
3914     })
getPhoneNumberFromFirstAvailableSource(int subId, @NonNull String callingPackage, @Nullable String callingFeatureId)3915     public String getPhoneNumberFromFirstAvailableSource(int subId,
3916             @NonNull String callingPackage, @Nullable String callingFeatureId) {
3917         TelephonyPermissions.enforceAnyPermissionGrantedOrCarrierPrivileges(
3918                 mContext, subId, Binder.getCallingUid(), "getPhoneNumberFromFirstAvailableSource",
3919                 Manifest.permission.READ_PHONE_NUMBERS,
3920                 Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
3921 
3922         enforceTelephonyFeatureWithException(callingPackage,
3923                 "getPhoneNumberFromFirstAvailableSource");
3924 
3925         if (mFeatureFlags.saferGetPhoneNumber()) {
3926             subId = checkAndGetSubId(subId);
3927             if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) return "";
3928 
3929             final long identity = Binder.clearCallingIdentity();
3930             try {
3931                 String number;
3932                 number = getPhoneNumberFromSourceInternal(
3933                         subId,
3934                         SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER);
3935                 if (!TextUtils.isEmpty(number)) return number;
3936 
3937                 number = getPhoneNumberFromSourceInternal(
3938                         subId,
3939                         SubscriptionManager.PHONE_NUMBER_SOURCE_UICC);
3940                 if (!TextUtils.isEmpty(number)) return number;
3941 
3942                 number = getPhoneNumberFromSourceInternal(
3943                         subId,
3944                         SubscriptionManager.PHONE_NUMBER_SOURCE_IMS);
3945                 return TextUtils.emptyIfNull(number);
3946             } finally {
3947                 Binder.restoreCallingIdentity(identity);
3948             }
3949         } else {
3950             String numberFromCarrier = getPhoneNumber(subId,
3951                     SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER, callingPackage,
3952                     callingFeatureId);
3953             if (!TextUtils.isEmpty(numberFromCarrier)) {
3954                 return numberFromCarrier;
3955             }
3956             String numberFromUicc = getPhoneNumber(
3957                     subId, SubscriptionManager.PHONE_NUMBER_SOURCE_UICC, callingPackage,
3958                     callingFeatureId);
3959             if (!TextUtils.isEmpty(numberFromUicc)) {
3960                 return numberFromUicc;
3961             }
3962             String numberFromIms = getPhoneNumber(
3963                     subId, SubscriptionManager.PHONE_NUMBER_SOURCE_IMS, callingPackage,
3964                     callingFeatureId);
3965             if (!TextUtils.isEmpty(numberFromIms)) {
3966                 return numberFromIms;
3967             }
3968             return "";
3969         }
3970     }
3971 
3972     /**
3973      * Set the phone number of the subscription.
3974      *
3975      * @param subId The subscription id.
3976      * @param source The phone number source.
3977      * @param number The phone number.
3978      * @param callingPackage The package making the call.
3979      * @param callingFeatureId The feature in the package.
3980      *
3981      * @throws IllegalArgumentException {@code subId} is invalid, or {@code source} is not
3982      * {@link SubscriptionManager#PHONE_NUMBER_SOURCE_CARRIER}.
3983      * @throws NullPointerException if {@code number} is {@code null}.
3984      */
3985     @Override
3986     @RequiresPermission("carrier privileges")
setPhoneNumber(int subId, @PhoneNumberSource int source, @NonNull String number, @NonNull String callingPackage, @Nullable String callingFeatureId)3987     public void setPhoneNumber(int subId, @PhoneNumberSource int source, @NonNull String number,
3988             @NonNull String callingPackage, @Nullable String callingFeatureId) {
3989         if (!TelephonyPermissions.checkCarrierPrivilegeForSubId(mContext, subId)) {
3990             throw new SecurityException("setPhoneNumber for CARRIER needs carrier privilege.");
3991         }
3992 
3993         if (source != SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER) {
3994             throw new IllegalArgumentException("setPhoneNumber doesn't accept source "
3995                     + SubscriptionManager.phoneNumberSourceToString(source));
3996         }
3997 
3998         enforceTelephonyFeatureWithException(callingPackage, "setPhoneNumber");
3999 
4000         Objects.requireNonNull(number, "number");
4001 
4002         final long identity = Binder.clearCallingIdentity();
4003         try {
4004             mSubscriptionDatabaseManager.setNumberFromCarrier(subId, number);
4005         } finally {
4006             Binder.restoreCallingIdentity(identity);
4007         }
4008     }
4009 
4010     /**
4011      * Set the Usage Setting for this subscription.
4012      *
4013      * @param usageSetting the usage setting for this subscription
4014      * @param subId the unique SubscriptionInfo index in database
4015      * @param callingPackage The package making the IPC.
4016      *
4017      * @throws IllegalArgumentException if the subscription does not exist, or {@code usageSetting}
4018      * is invalid.
4019      * @throws SecurityException if doesn't have MODIFY_PHONE_STATE or Carrier Privileges
4020      */
4021     @Override
4022     @RequiresPermission(anyOf = {
4023             Manifest.permission.MODIFY_PHONE_STATE,
4024             "carrier privileges",
4025     })
setUsageSetting(@sageSetting int usageSetting, int subId, @NonNull String callingPackage)4026     public int setUsageSetting(@UsageSetting int usageSetting, int subId,
4027             @NonNull String callingPackage) {
4028         TelephonyPermissions.enforceAnyPermissionGrantedOrCarrierPrivileges(
4029                 mContext, Binder.getCallingUid(), subId, true, "setUsageSetting",
4030                 Manifest.permission.MODIFY_PHONE_STATE);
4031 
4032         if (usageSetting < SubscriptionManager.USAGE_SETTING_DEFAULT
4033                 || usageSetting > SubscriptionManager.USAGE_SETTING_DATA_CENTRIC) {
4034             throw new IllegalArgumentException("setUsageSetting: Invalid usage setting: "
4035                     + usageSetting);
4036         }
4037 
4038         final long token = Binder.clearCallingIdentity();
4039         try {
4040             mSubscriptionDatabaseManager.setUsageSetting(subId, usageSetting);
4041             return 1;
4042         } finally {
4043             Binder.restoreCallingIdentity(token);
4044         }
4045     }
4046 
4047     /**
4048      * Set UserHandle for this subscription.
4049      *
4050      * @param userHandle the userHandle associated with the subscription
4051      * Pass {@code null} user handle to clear the association
4052      * @param subId the unique SubscriptionInfo index in database
4053      * @return the number of records updated.
4054      *
4055      * @throws SecurityException if callers do not hold the required permission.
4056      * @throws IllegalArgumentException if {@code subId} is invalid.
4057      */
4058     @Override
4059     @RequiresPermission(Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION)
setSubscriptionUserHandle(@ullable UserHandle userHandle, int subId)4060     public int setSubscriptionUserHandle(@Nullable UserHandle userHandle, int subId) {
4061         enforcePermissions("setSubscriptionUserHandle",
4062                 Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION);
4063 
4064         if (userHandle == null) {
4065             userHandle = UserHandle.of(UserHandle.USER_NULL);
4066         }
4067 
4068         long token = Binder.clearCallingIdentity();
4069         try {
4070             // This can throw IllegalArgumentException if the subscription does not exist.
4071             mSubscriptionDatabaseManager.setUserId(subId, userHandle.getIdentifier());
4072             return 1;
4073         } finally {
4074             Binder.restoreCallingIdentity(token);
4075         }
4076     }
4077 
4078     /**
4079      * Get UserHandle of this subscription.
4080      *
4081      * @param subId the unique SubscriptionInfo index in database
4082      * @return userHandle associated with this subscription
4083      * or {@code null} if subscription is not associated with any user
4084      * or {code null} if subscripiton is not available on the device.
4085      *
4086      * @throws SecurityException if doesn't have required permission.
4087      */
4088     @Override
4089     @Nullable
4090     @RequiresPermission(Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION)
getSubscriptionUserHandle(int subId)4091     public UserHandle getSubscriptionUserHandle(int subId) {
4092         enforcePermissions("getSubscriptionUserHandle",
4093                 Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION);
4094         long token = Binder.clearCallingIdentity();
4095         try {
4096             SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager
4097                     .getSubscriptionInfoInternal(subId);
4098             if (subInfo == null) {
4099                 return null;
4100             }
4101 
4102             UserHandle userHandle = UserHandle.of(subInfo.getUserId());
4103             if (userHandle.getIdentifier() == UserHandle.USER_NULL) {
4104                 return null;
4105             }
4106             return userHandle;
4107         } finally {
4108             Binder.restoreCallingIdentity(token);
4109         }
4110     }
4111 
4112     /**
4113      * Returns whether the given subscription is associated with the calling user.
4114      *
4115      * @param subscriptionId the subscription ID of the subscription
4116      * @return {@code true} if the subscription is associated with the user that the calling process
4117      *         is running in; {@code false} otherwise.
4118      *
4119      * @throws IllegalArgumentException if subscription doesn't exist.
4120      * @throws SecurityException if the caller doesn't have permissions required.
4121      */
4122     @Override
isSubscriptionAssociatedWithCallingUser(int subscriptionId)4123     public boolean isSubscriptionAssociatedWithCallingUser(int subscriptionId) {
4124         enforcePermissions("isSubscriptionAssociatedWithCallingUser",
4125                 Manifest.permission.READ_PHONE_STATE);
4126 
4127         UserHandle myUserHandle = UserHandle.of(UserHandle.getCallingUserId());
4128         return mFeatureFlags.subscriptionUserAssociationQuery()
4129             && isSubscriptionAssociatedWithUserNoCheck(subscriptionId, myUserHandle);
4130     }
4131 
4132     /**
4133      * Check if subscription and user are associated with each other.
4134      *
4135      * @param subscriptionId the subId of the subscription
4136      * @param userHandle user handle of the user
4137      * @return {@code true} if subscription is associated with user
4138      * else {@code false} if subscription is not associated with user.
4139      *
4140      * @throws SecurityException if the caller doesn't have permissions required.
4141      * @throws IllegalArgumentException if the subscription has no records on device.
4142      */
4143     @Override
isSubscriptionAssociatedWithUser(int subscriptionId, @NonNull UserHandle userHandle)4144     public boolean isSubscriptionAssociatedWithUser(int subscriptionId,
4145             @NonNull UserHandle userHandle) {
4146         enforcePermissions("isSubscriptionAssociatedWithUser",
4147                 Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION);
4148 
4149         return isSubscriptionAssociatedWithUserNoCheck(subscriptionId, userHandle);
4150     }
4151 
isSubscriptionAssociatedWithUserNoCheck(int subscriptionId, @NonNull UserHandle userHandle)4152     private boolean isSubscriptionAssociatedWithUserNoCheck(int subscriptionId,
4153             @NonNull UserHandle userHandle) {
4154         SubscriptionInfoInternal subInfoInternal = mSubscriptionDatabaseManager
4155                 .getSubscriptionInfoInternal(subscriptionId);
4156         // Throw IAE if no record of the sub's association state.
4157         if (subInfoInternal == null) {
4158             throw new IllegalArgumentException(
4159                     "[isSubscriptionAssociatedWithUser]: Subscription doesn't exist: "
4160                             + subscriptionId);
4161         }
4162 
4163         if (mFeatureFlags.enforceSubscriptionUserFilter()) {
4164             return isSubscriptionAssociatedWithUserInternal(
4165                     subInfoInternal, userHandle.getIdentifier());
4166         }
4167 
4168         long token = Binder.clearCallingIdentity();
4169         try {
4170             // Get list of subscriptions associated with this user.
4171             List<SubscriptionInfo> associatedSubscriptionsList =
4172                     getSubscriptionInfoListAssociatedWithUser(userHandle);
4173             // Return true if required subscription is present in associated subscriptions list.
4174             for (SubscriptionInfo subInfo: associatedSubscriptionsList) {
4175                 if (subInfo.getSubscriptionId() == subscriptionId) {
4176                     return true;
4177                 }
4178             }
4179             return false;
4180         } finally {
4181             Binder.restoreCallingIdentity(token);
4182         }
4183     }
4184 
4185     /**
4186      * @param subInfo The subscription info to check.
4187      * @param userId The caller user Id.
4188      * @return {@code true} if the given user Id is allowed to access to the given subscription.
4189      */
isSubscriptionAssociatedWithUserInternal( @onNull SubscriptionInfoInternal subInfo, @UserIdInt int userId)4190     private boolean isSubscriptionAssociatedWithUserInternal(
4191             @NonNull SubscriptionInfoInternal subInfo, @UserIdInt int userId) {
4192         if (!mFeatureFlags.enforceSubscriptionUserFilter()
4193                 || !CompatChanges.isChangeEnabled(FILTER_ACCESSIBLE_SUBS_BY_USER,
4194                 Binder.getCallingUid())) {
4195             return true;
4196         }
4197         // Can access the unassociated sub if the user doesn't have its own.
4198         return (subInfo.getUserId() == UserHandle.USER_NULL
4199                 && mUserIdToAvailableSubs.get(userId) == null)
4200                 || userId == subInfo.getUserId()
4201                 || userId == UserHandle.USER_ALL;
4202     }
4203 
4204     /**
4205      * Get list of subscriptions associated with user.
4206      *
4207      * If user handle is associated with some subscriptions, return subscriptionsAssociatedWithUser
4208      * else return all the subscriptions which are not associated with any user.
4209      *
4210      * @param userHandle user handle of the user
4211      * @return list of subscriptionInfo associated with the user.
4212      *
4213      * @throws SecurityException if the caller doesn't have permissions required.
4214      *
4215      */
4216     @Override
4217     @NonNull
getSubscriptionInfoListAssociatedWithUser( @onNull UserHandle userHandle)4218     public List<SubscriptionInfo> getSubscriptionInfoListAssociatedWithUser(
4219             @NonNull UserHandle userHandle) {
4220         enforcePermissions("getSubscriptionInfoListAssociatedWithUser",
4221                 Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION);
4222 
4223         if (mFeatureFlags.enforceSubscriptionUserFilter()) {
4224             return getSubscriptionInfoStreamAsUser(userHandle)
4225                     .map(SubscriptionInfoInternal::toSubscriptionInfo)
4226                     .collect(Collectors.toList());
4227         }
4228 
4229         long token = Binder.clearCallingIdentity();
4230         try {
4231             List<SubscriptionInfoInternal> subInfoList =  mSubscriptionDatabaseManager
4232                     .getAllSubscriptions();
4233             if (subInfoList.isEmpty()) {
4234                 return new ArrayList<>();
4235             }
4236 
4237             List<SubscriptionInfo> subscriptionsAssociatedWithUser = new ArrayList<>();
4238             List<SubscriptionInfo> subscriptionsWithNoAssociation = new ArrayList<>();
4239             for (SubscriptionInfoInternal subInfo : subInfoList) {
4240                 if (subInfo.getUserId() == userHandle.getIdentifier()) {
4241                     // Store subscriptions whose user handle matches with required user handle.
4242                     subscriptionsAssociatedWithUser.add(subInfo.toSubscriptionInfo());
4243                 } else if (subInfo.getUserId() == UserHandle.USER_NULL) {
4244                     // Store subscriptions whose user handle is set to null.
4245                     subscriptionsWithNoAssociation.add(subInfo.toSubscriptionInfo());
4246                 }
4247             }
4248 
4249             UserManager userManager = mContext.getSystemService(UserManager.class);
4250             if ((userManager != null)
4251                     && (userManager.isManagedProfile(userHandle.getIdentifier()))) {
4252                 // For work profile, return subscriptions associated only with work profile even
4253                 // if it's empty.
4254                 return subscriptionsAssociatedWithUser;
4255             }
4256 
4257             // For all other profiles, if subscriptionsAssociatedWithUser is empty return all
4258             // the subscriptionsWithNoAssociation.
4259             return subscriptionsAssociatedWithUser.isEmpty()
4260                     ? subscriptionsWithNoAssociation : subscriptionsAssociatedWithUser;
4261         } finally {
4262             Binder.restoreCallingIdentity(token);
4263         }
4264     }
4265 
4266     /**
4267      * Get subscriptions accessible to the caller user.
4268      *
4269      * @param user The user to check.
4270      * @return a stream of accessible internal subscriptions.
4271      */
4272     @NonNull
getSubscriptionInfoStreamAsUser( @onNull final UserHandle user)4273     private Stream<SubscriptionInfoInternal> getSubscriptionInfoStreamAsUser(
4274             @NonNull final UserHandle user) {
4275         return mSubscriptionDatabaseManager.getAllSubscriptions().stream()
4276                 .filter(info -> isSubscriptionAssociatedWithUserInternal(
4277                         info, user.getIdentifier()));
4278     }
4279 
4280     /**
4281      * Called during setup wizard restore flow to attempt to restore the backed up sim-specific
4282      * configs to device for all existing SIMs in the subscription database {@link SimInfo}.
4283      * Internally, it will store the backup data in an internal file. This file will persist on
4284      * device for device's lifetime and will be used later on when a SIM is inserted to restore that
4285      * specific SIM's settings. End result is subscription database is modified to match any backed
4286      * up configs for the appropriate inserted SIMs.
4287      *
4288      * <p>
4289      * The {@link Uri} {@link SubscriptionManager#SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI} is
4290      * notified if any {@link SimInfo} entry is updated as the result of this method call.
4291      *
4292      * @param data with the sim specific configs to be backed up.
4293      */
4294     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
4295     @Override
restoreAllSimSpecificSettingsFromBackup(@onNull byte[] data)4296     public void restoreAllSimSpecificSettingsFromBackup(@NonNull byte[] data) {
4297         enforcePermissions("restoreAllSimSpecificSettingsFromBackup",
4298                 Manifest.permission.MODIFY_PHONE_STATE);
4299 
4300         enforceTelephonyFeatureWithException(getCurrentPackageName(),
4301                 "restoreAllSimSpecificSettingsFromBackup");
4302 
4303         long token = Binder.clearCallingIdentity();
4304         try {
4305             Bundle bundle = new Bundle();
4306             bundle.putByteArray(SubscriptionManager.KEY_SIM_SPECIFIC_SETTINGS_DATA, data);
4307             logl("restoreAllSimSpecificSettingsFromBackup");
4308             Bundle result = mContext.getContentResolver().call(
4309                     SubscriptionManager.SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI,
4310                     SubscriptionManager.RESTORE_SIM_SPECIFIC_SETTINGS_METHOD_NAME,
4311                     null, bundle);
4312 
4313             if (result != null && result.getBoolean(
4314                     SubscriptionManager.RESTORE_SIM_SPECIFIC_SETTINGS_DATABASE_UPDATED)) {
4315                 logl("Sim specific settings changed the database.");
4316                 mSubscriptionDatabaseManager.reloadDatabaseSync();
4317                 if (mFeatureFlags.backupAndRestoreForEnable2g()) {
4318                     Arrays.stream(PhoneFactory.getPhones())
4319                             .forEach(Phone::loadAllowedNetworksFromSubscriptionDatabase);
4320                 }
4321             }
4322         } finally {
4323             Binder.restoreCallingIdentity(token);
4324         }
4325     }
4326 
4327     /**
4328      * Register the callback for receiving information from {@link SubscriptionManagerService}.
4329      *
4330      * @param callback The callback.
4331      */
registerCallback(@onNull SubscriptionManagerServiceCallback callback)4332     public void registerCallback(@NonNull SubscriptionManagerServiceCallback callback) {
4333         mSubscriptionManagerServiceCallbacks.add(callback);
4334     }
4335 
4336     /**
4337      * Unregister the previously registered {@link SubscriptionManagerServiceCallback}.
4338      *
4339      * @param callback The callback to unregister.
4340      */
unregisterCallback(@onNull SubscriptionManagerServiceCallback callback)4341     public void unregisterCallback(@NonNull SubscriptionManagerServiceCallback callback) {
4342         mSubscriptionManagerServiceCallbacks.remove(callback);
4343     }
4344 
4345     /**
4346      * Enforce callers have any of the provided permissions.
4347      *
4348      * @param message Message to include in the exception.
4349      * @param permissions The permissions to enforce.
4350      *
4351      * @throws SecurityException if the caller does not have any permissions.
4352      */
enforcePermissions(@ullable String message, @NonNull String ...permissions)4353     private void enforcePermissions(@Nullable String message, @NonNull String ...permissions) {
4354         if (!hasPermissions(permissions)) {
4355             throw new SecurityException(
4356                     message + ". Does not have any of the following permissions. "
4357                             + Arrays.toString(permissions));
4358         }
4359     }
4360 
4361     /**
4362      * Check have any of the permissions
4363      * @param permissions The permissions to check.
4364      * @return {@code true} if the caller has one of the given permissions.
4365      */
hasPermissions(@onNull String ....permissions)4366     private boolean hasPermissions(@NonNull String ...permissions) {
4367         for (String permission : permissions) {
4368             if (mContext.checkCallingOrSelfPermission(permission)
4369                     == PackageManager.PERMISSION_GRANTED) {
4370                 return true;
4371             }
4372         }
4373         return false;
4374     }
4375 
4376     /**
4377      * Get the {@link SubscriptionInfoInternal} by subscription id.
4378      *
4379      * @param subId The subscription id.
4380      *
4381      * @return The subscription info. {@code null} if not found.
4382      */
4383     @Nullable
getSubscriptionInfoInternal(int subId)4384     public SubscriptionInfoInternal getSubscriptionInfoInternal(int subId) {
4385         return mSubscriptionDatabaseManager.getSubscriptionInfoInternal(subId);
4386     }
4387 
4388     /**
4389      * Get the {@link SubscriptionInfo} by subscription id.
4390      *
4391      * @param subId The subscription id.
4392      *
4393      * @return The subscription info. {@code null} if not found.
4394      */
4395     @Nullable
getSubscriptionInfo(int subId)4396     public SubscriptionInfo getSubscriptionInfo(int subId) {
4397         SubscriptionInfoInternal infoInternal = getSubscriptionInfoInternal(subId);
4398         return infoInternal != null ? infoInternal.toSubscriptionInfo() : null;
4399     }
4400 
4401     /**
4402      * Called when SIM becomes inactive.
4403      *
4404      * @param slotIndex The logical SIM slot index.
4405      * @param iccId iccId of the SIM in inactivate slot.
4406      */
updateSimStateForInactivePort(int slotIndex, @NonNull String iccId)4407     public void updateSimStateForInactivePort(int slotIndex, @NonNull String iccId) {
4408         mHandler.post(() -> {
4409             logl("updateSimStateForInactivePort: slotIndex=" + slotIndex + ", iccId="
4410                     + SubscriptionInfo.getPrintableId(iccId));
4411             if (mSlotIndexToSubId.containsKey(slotIndex)) {
4412                 // Re-enable the UICC application , so it will be in enabled state when it becomes
4413                 // active again. (Pre-U behavior)
4414                 mSubscriptionDatabaseManager.setUiccApplicationsEnabled(
4415                         mSlotIndexToSubId.get(slotIndex), true);
4416                 updateSubscription(slotIndex);
4417             }
4418             if (!TextUtils.isEmpty(iccId)) {
4419                 // When port is inactive, sometimes valid iccid is present in the slot status,
4420                 // hence update the portIndex. (Pre-U behavior)
4421                 SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager
4422                         .getSubscriptionInfoInternalByIccId(IccUtils.stripTrailingFs(iccId));
4423                 int subId;
4424                 if (subInfo != null) {
4425                     subId = subInfo.getSubscriptionId();
4426                     log("updateSimStateForInactivePort: Found existing subscription. subId="
4427                             + subId);
4428                 } else {
4429                     // If iccId is new, add a subscription record in the database so it can be
4430                     // activated later. (Pre-U behavior)
4431                     subId = insertSubscriptionInfo(IccUtils.stripTrailingFs(iccId),
4432                             SubscriptionManager.INVALID_SIM_SLOT_INDEX, "",
4433                             SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM);
4434                     mSubscriptionDatabaseManager.setDisplayName(subId,
4435                             mContext.getResources().getString(R.string.default_card_name, subId));
4436                     log("updateSimStateForInactivePort: Insert a new subscription for inactive SIM."
4437                             + " subId=" + subId);
4438                 }
4439                 if (SubscriptionManager.isValidSubscriptionId(subId)) {
4440                     mSubscriptionDatabaseManager.setPortIndex(subId, getPortIndex(iccId));
4441                 }
4442             }
4443         });
4444     }
4445 
4446     /**
4447      * Update SIM state. This method is supposed to be called by {@link UiccController} only.
4448      *
4449      * @param slotIndex The logical SIM slot index.
4450      * @param simState SIM state.
4451      * @param executor The executor to execute the callback.
4452      * @param updateCompleteCallback The callback to call when subscription manager service
4453      * completes subscription update. SIM state changed event will be broadcasted by
4454      * {@link UiccController} upon receiving callback.
4455      */
updateSimState(int slotIndex, @SimState int simState, @Nullable @CallbackExecutor Executor executor, @Nullable Runnable updateCompleteCallback)4456     public void updateSimState(int slotIndex, @SimState int simState,
4457             @Nullable @CallbackExecutor Executor executor,
4458             @Nullable Runnable updateCompleteCallback) {
4459         mHandler.post(() -> {
4460             mSimState[slotIndex] = simState;
4461             logl("updateSimState: slot " + slotIndex + " "
4462                     + TelephonyManager.simStateToString(simState));
4463             switch (simState) {
4464                 case TelephonyManager.SIM_STATE_ABSENT:
4465                 case TelephonyManager.SIM_STATE_PIN_REQUIRED:
4466                 case TelephonyManager.SIM_STATE_PUK_REQUIRED:
4467                 case TelephonyManager.SIM_STATE_NETWORK_LOCKED:
4468                 case TelephonyManager.SIM_STATE_PERM_DISABLED:
4469                 case TelephonyManager.SIM_STATE_CARD_IO_ERROR:
4470                 case TelephonyManager.SIM_STATE_LOADED:
4471                     updateSubscription(slotIndex);
4472                     break;
4473                 case TelephonyManager.SIM_STATE_NOT_READY:
4474                 case TelephonyManager.SIM_STATE_READY:
4475                     updateEmbeddedSubscriptions();
4476                     updateSubscription(slotIndex);
4477                     break;
4478                 case TelephonyManager.SIM_STATE_CARD_RESTRICTED:
4479                 default:
4480                     // No specific things needed to be done. Just return and broadcast the SIM
4481                     // states.
4482                     break;
4483             }
4484             if (executor != null && updateCompleteCallback != null) {
4485                 executor.execute(updateCompleteCallback);
4486             }
4487         });
4488     }
4489 
4490     /**
4491      * Get the calling package(s).
4492      *
4493      * @return The calling package(s).
4494      */
4495     @NonNull
getCallingPackage()4496     private String getCallingPackage() {
4497         if (Binder.getCallingUid() == Process.PHONE_UID) {
4498             // Too many packages running with phone uid. Just return one here.
4499             return "com.android.phone";
4500         }
4501         return Arrays.toString(mContext.getPackageManager().getPackagesForUid(
4502                 Binder.getCallingUid()));
4503     }
4504 
4505     /**
4506      * Update the {@link SubscriptionInfo#isGroupDisabled()} bit for the opportunistic
4507      * subscriptions.
4508      *
4509      * If all primary (non-opportunistic) subscriptions in the group are deactivated
4510      * (unplugged pSIM or deactivated eSIM profile), we should disable this opportunistic
4511      * subscriptions.
4512      */
4513     @VisibleForTesting
updateGroupDisabled()4514     public void updateGroupDisabled() {
4515         List<SubscriptionInfo> activeSubscriptions = mSubscriptionDatabaseManager
4516                 .getAllSubscriptions().stream()
4517                 .filter(SubscriptionInfoInternal::isActive)
4518                 .map(SubscriptionInfoInternal::toSubscriptionInfo)
4519                 .collect(Collectors.toList());
4520         for (SubscriptionInfo oppSubInfo : getOpportunisticSubscriptions(
4521                 mContext.getOpPackageName(), mContext.getFeatureId())) {
4522             boolean groupDisabled = activeSubscriptions.stream()
4523                     .noneMatch(subInfo -> !subInfo.isOpportunistic()
4524                             && Objects.equals(oppSubInfo.getGroupUuid(), subInfo.getGroupUuid()));
4525             mSubscriptionDatabaseManager.setGroupDisabled(
4526                     oppSubInfo.getSubscriptionId(), groupDisabled);
4527         }
4528     }
4529 
4530 
4531 
4532     /**
4533      * Set the transfer status of the subscriptionInfo that corresponds to subId.
4534      * @param subId The unique SubscriptionInfo key in database.
4535      * @param status The transfer status to change. This value must be one of the following.
4536      * {@link SubscriptionManager#TRANSFER_STATUS_NONE},
4537      * {@link SubscriptionManager#TRANSFER_STATUS_TRANSFERRED_OUT} or
4538      * {@link SubscriptionManager#TRANSFER_STATUS_CONVERTED}
4539      *
4540      */
4541     @Override
4542     @EnforcePermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
setTransferStatus(int subId, int status)4543     public void setTransferStatus(int subId, int status) {
4544         setTransferStatus_enforcePermission();
4545         if (mContext.checkCallingOrSelfPermission(
4546                 Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
4547                 != PackageManager.PERMISSION_GRANTED) {
4548             throw new SecurityException("Must have WRITE_EMBEDDED_SUBSCRIPTIONS to"
4549                     + "setTransferStatus");
4550         }
4551         long token = Binder.clearCallingIdentity();
4552         try {
4553             mSubscriptionDatabaseManager.setTransferStatus(subId, status);
4554         } finally {
4555             Binder.restoreCallingIdentity(token);
4556         }
4557     }
4558 
4559     /**
4560      * Set the satellite entitlement plmn list value in the subscription database.
4561      *
4562      * @param subId subscription id.
4563      * @param satelliteEntitlementPlmnList satellite entitlement plmn list
4564      */
setSatelliteEntitlementPlmnList(int subId, @NonNull List<String> satelliteEntitlementPlmnList)4565     public void setSatelliteEntitlementPlmnList(int subId,
4566             @NonNull List<String> satelliteEntitlementPlmnList) {
4567         try {
4568             mSubscriptionDatabaseManager.setSatelliteEntitlementPlmnList(
4569                     subId, satelliteEntitlementPlmnList);
4570         } catch (IllegalArgumentException e) {
4571             loge("setSatelliteEntitlementPlmnList: invalid subId=" + subId);
4572         }
4573     }
4574 
4575     /**
4576      * Get the satellite entitlement plmn list value from the subscription database.
4577      *
4578      * @param subId subscription id.
4579      * @return satellite entitlement plmn list
4580      */
4581     @NonNull
getSatelliteEntitlementPlmnList(int subId)4582     public List<String> getSatelliteEntitlementPlmnList(int subId) {
4583         SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager.getSubscriptionInfoInternal(
4584                 subId);
4585 
4586         return Optional.ofNullable(subInfo)
4587                 .map(SubscriptionInfoInternal::getSatelliteEntitlementPlmns)
4588                 .filter(s -> !s.isEmpty())
4589                 .map(s -> Arrays.stream(s.split(",")).collect(Collectors.toList()))
4590                 .orElse(new ArrayList<>());
4591     }
4592 
4593     /**
4594      * checks whether esim bootstrap is activated for any of the available active subscription info
4595      * list.
4596      *
4597      * @return {@code true} if esim bootstrap is activated for any of the active subscription,
4598      * else {@code false}
4599      *
4600      */
isEsimBootStrapProvisioningActivated()4601     public boolean isEsimBootStrapProvisioningActivated() {
4602         if (!mFeatureFlags.esimBootstrapProvisioningFlag()) {
4603             return false;
4604         }
4605 
4606         List<SubscriptionInfo> activeSubInfos =
4607                 getActiveSubscriptionInfoList(mContext.getOpPackageName(),
4608                         mContext.getAttributionTag(), true/*isForAllProfile*/);
4609 
4610         return activeSubInfos.stream().anyMatch(subInfo -> subInfo != null
4611                 && subInfo.getProfileClass() == SubscriptionManager.PROFILE_CLASS_PROVISIONING);
4612     }
4613 
4614     /**
4615      * checks whether esim bootstrap is activated for the subscription.
4616      *
4617      * @return {@code true} if esim bootstrap is activated for sub id else {@code false}
4618      *
4619      */
isEsimBootStrapProvisioningActiveForSubId(int subId)4620     public boolean isEsimBootStrapProvisioningActiveForSubId(int subId) {
4621         if (!mFeatureFlags.esimBootstrapProvisioningFlag()) {
4622             return false;
4623         }
4624 
4625         SubscriptionInfoInternal subInfo = getSubscriptionInfoInternal(subId);
4626         return subInfo != null
4627                 && subInfo.getProfileClass() == SubscriptionManager.PROFILE_CLASS_PROVISIONING;
4628     }
4629 
4630     /**
4631      * Get the current calling package name.
4632      * @return the current calling package name
4633      */
4634     @Nullable
getCurrentPackageName()4635     private String getCurrentPackageName() {
4636         if (mPackageManager == null) return null;
4637         String[] callingUids = mPackageManager.getPackagesForUid(Binder.getCallingUid());
4638         return (callingUids == null) ? null : callingUids[0];
4639     }
4640 
4641     /**
4642      * Make sure the device has required telephony feature
4643      *
4644      * @throws UnsupportedOperationException if the device does not have required telephony feature
4645      */
enforceTelephonyFeatureWithException(@ullable String callingPackage, @NonNull String methodName)4646     private void enforceTelephonyFeatureWithException(@Nullable String callingPackage,
4647             @NonNull String methodName) {
4648         if (callingPackage == null || mPackageManager == null) {
4649             return;
4650         }
4651 
4652         if (!mFeatureFlags.enforceTelephonyFeatureMappingForPublicApis()
4653                 || !CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, callingPackage,
4654                 Binder.getCallingUserHandle())
4655                 || mVendorApiLevel < Build.VERSION_CODES.VANILLA_ICE_CREAM) {
4656             // Skip to check associated telephony feature,
4657             // if compatibility change is not enabled for the current process or
4658             // the SDK version of vendor partition is less than Android V.
4659             return;
4660         }
4661 
4662         if (!mPackageManager.hasSystemFeature(FEATURE_TELEPHONY_SUBSCRIPTION)) {
4663             throw new UnsupportedOperationException(
4664                     methodName + " is unsupported without " + FEATURE_TELEPHONY_SUBSCRIPTION);
4665         }
4666     }
4667 
4668     /**
4669      * @return The logical SIM slot/sub mapping to string.
4670      */
4671     @NonNull
slotMappingToString()4672     private String slotMappingToString() {
4673         return "[" + mSlotIndexToSubId.entrySet().stream()
4674                 .map(e -> "slot " + e.getKey() + ": subId=" + e.getValue())
4675                 .collect(Collectors.joining(", ")) + "]";
4676     }
4677 
4678     /**
4679      * @param mccMnc MccMnc value to check whether it supports non-terrestrial network or not.
4680      * @return {@code true} if MCC/MNC is matched with in the device overlay key
4681      * "config_satellite_sim_plmn_identifier", {@code false} otherwise.
4682      */
isSatellitePlmn(@onNull String mccMnc)4683     private boolean isSatellitePlmn(@NonNull String mccMnc) {
4684         if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
4685             log("isSatellitePlmn: oemEnabledSatelliteFlag is disabled");
4686             return false;
4687         }
4688 
4689         final int id = R.string.config_satellite_sim_plmn_identifier;
4690         String overlayMccMnc = null;
4691         try {
4692             overlayMccMnc = mContext.getResources().getString(id);
4693         } catch (Resources.NotFoundException ex) {
4694             loge("isSatellitePlmn: id= " + id + ", ex=" + ex);
4695         }
4696         if (TextUtils.isEmpty(overlayMccMnc) && isMockModemAllowed()) {
4697             log("isSatellitePlmn: Read config_satellite_sim_plmn_identifier from device config");
4698             overlayMccMnc = DeviceConfig.getString(DeviceConfig.NAMESPACE_TELEPHONY,
4699                     "config_satellite_sim_plmn_identifier", "");
4700         }
4701         log("isSatellitePlmn: overlayMccMnc=" + overlayMccMnc + ", mccMnc=" + mccMnc);
4702         return TextUtils.equals(mccMnc, overlayMccMnc);
4703     }
4704 
4705     /**
4706      * Checks and matches the service provider name (spn) with the device overlay config to
4707      * determine whether non-terrestrial networks are supported.
4708      * @param spn service provider name of the profile.
4709      * @return {@code true} if the given spn is matched with the overlay key.
4710      * "config_satellite_sim_spn_identifier", {@code false} otherwise.
4711      */
isSatelliteSpn(@onNull String spn)4712     private boolean isSatelliteSpn(@NonNull String spn) {
4713         if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
4714             log("isSatelliteSpn: oemEnabledSatelliteFlag is disabled");
4715             return false;
4716         }
4717 
4718         final int id = R.string.config_satellite_sim_spn_identifier;
4719         String overlaySpn = null;
4720         try {
4721             overlaySpn = mContext.getResources().getString(id);
4722         } catch (Resources.NotFoundException ex) {
4723             loge("isSatelliteSpn: id= " + id + ", ex=" + ex);
4724         }
4725         if (TextUtils.isEmpty(overlaySpn) && isMockModemAllowed()) {
4726             log("isSatelliteSpn: Read config_satellite_sim_spn_identifier from device config");
4727             overlaySpn = DeviceConfig.getString(DeviceConfig.NAMESPACE_TELEPHONY,
4728                     "config_satellite_sim_spn_identifier", "");
4729         }
4730         log("isSatelliteSpn: overlaySpn=" + overlaySpn + ", spn=" + spn);
4731 
4732         if (TextUtils.isEmpty(spn) || TextUtils.isEmpty(overlaySpn)) {
4733             return false;
4734         }
4735 
4736         return TextUtils.equals(spn, overlaySpn);
4737     }
4738 
isMockModemAllowed()4739     private boolean isMockModemAllowed() {
4740         boolean isAllowed = SystemProperties.getBoolean(ALLOW_MOCK_MODEM_PROPERTY, false);
4741         return (SystemProperties.getBoolean(ALLOW_MOCK_MODEM_PROPERTY, false)
4742                 || SystemProperties.getBoolean(BOOT_ALLOW_MOCK_MODEM_PROPERTY, false));
4743     }
4744 
4745     /**
4746      * Iterates through previously subscribed SIMs to excludes subscriptions that are not visible
4747      * to the users to provide a more appropriate number to describe the current SIM.
4748      * @param subId current subscription id.
4749      * @return cardNumber subId excluding invisible subscriptions.
4750      */
getCardNumber(int subId)4751     private int getCardNumber(int subId) {
4752         int cardNumber = subId; // Initialize with the potential card number
4753         for (int i = subId - 1; i > 0; i--) {
4754             SubscriptionInfoInternal subInfo = getSubscriptionInfoInternal(i);
4755             if (subInfo != null && !subInfo.isVisible()) {
4756                 cardNumber--;
4757             }
4758         }
4759 
4760         return cardNumber;
4761     }
4762 
4763     /**
4764      * Log debug messages.
4765      *
4766      * @param s debug messages
4767      */
log(@onNull String s)4768     private void log(@NonNull String s) {
4769         Rlog.d(LOG_TAG, s);
4770     }
4771 
4772     /**
4773      * Log error messages.
4774      *
4775      * @param s error messages
4776      */
loge(@onNull String s)4777     private void loge(@NonNull String s) {
4778         Rlog.e(LOG_TAG, s);
4779     }
4780 
4781     /**
4782      * Log debug messages and also log into the local log.
4783      *
4784      * @param s debug messages
4785      */
logl(@onNull String s)4786     private void logl(@NonNull String s) {
4787         log(s);
4788         mLocalLog.log(s);
4789     }
4790 
4791     /**
4792      * Dump the state of {@link SubscriptionManagerService}.
4793      *
4794      * @param fd File descriptor
4795      * @param printWriter Print writer
4796      * @param args Arguments
4797      */
dump(@onNull FileDescriptor fd, @NonNull PrintWriter printWriter, @NonNull String[] args)4798     public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter printWriter,
4799             @NonNull String[] args) {
4800         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP,
4801                 "Requires android.Manifest.permission.DUMP");
4802         final long token = Binder.clearCallingIdentity();
4803         try {
4804             IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, "  ");
4805             pw.println(SubscriptionManagerService.class.getSimpleName() + ":");
4806             pw.println("Active modem count=" + mTelephonyManager.getActiveModemCount());
4807             pw.println("Logical SIM slot sub id mapping:");
4808             pw.increaseIndent();
4809             mSlotIndexToSubId.forEach((slotIndex, subId)
4810                     -> pw.println("Logical SIM slot " + slotIndex + ": subId=" + subId));
4811             pw.decreaseIndent();
4812             pw.println("ICCID:");
4813             pw.increaseIndent();
4814             for (int i = 0; i < mTelephonyManager.getActiveModemCount(); i++) {
4815                 pw.println("slot " + i + ": " + SubscriptionInfo.getPrintableId(getIccId(i)));
4816             }
4817             pw.decreaseIndent();
4818             pw.println();
4819             pw.println("defaultSubId=" + getDefaultSubId());
4820             pw.println("defaultVoiceSubId=" + getDefaultVoiceSubId());
4821             pw.println("defaultDataSubId=" + getDefaultDataSubId());
4822             pw.println("activeDataSubId=" + getActiveDataSubscriptionId());
4823             pw.println("defaultSmsSubId=" + getDefaultSmsSubId());
4824             pw.println("areAllSubscriptionsLoaded=" + areAllSubscriptionsLoaded());
4825             pw.println("mUserIdToAvailableSubs=" + mUserIdToAvailableSubs);
4826             pw.println();
4827             for (int i = 0; i < mSimState.length; i++) {
4828                 pw.println("mSimState[" + i + "]="
4829                         + TelephonyManager.simStateToString(mSimState[i]));
4830             }
4831 
4832             pw.println();
4833             pw.println("Active subscriptions:");
4834             pw.increaseIndent();
4835             mSubscriptionDatabaseManager.getAllSubscriptions().stream()
4836                     .filter(SubscriptionInfoInternal::isActive).forEach(pw::println);
4837             pw.decreaseIndent();
4838 
4839             pw.println();
4840             pw.println("All subscriptions:");
4841             pw.increaseIndent();
4842             mSubscriptionDatabaseManager.getAllSubscriptions().forEach(pw::println);
4843             pw.decreaseIndent();
4844             pw.println();
4845 
4846             pw.print("Embedded subscriptions: [");
4847             pw.println(mSubscriptionDatabaseManager.getAllSubscriptions().stream()
4848                     .filter(SubscriptionInfoInternal::isEmbedded)
4849                     .map(subInfo -> String.valueOf(subInfo.getSubscriptionId()))
4850                     .collect(Collectors.joining(", ")) + "]");
4851 
4852             pw.print("Opportunistic subscriptions: [");
4853             pw.println(mSubscriptionDatabaseManager.getAllSubscriptions().stream()
4854                     .filter(SubscriptionInfoInternal::isOpportunistic)
4855                     .map(subInfo -> String.valueOf(subInfo.getSubscriptionId()))
4856                     .collect(Collectors.joining(", ")) + "]");
4857 
4858             pw.print("getAvailableSubscriptionInfoList: [");
4859             pw.println(getAvailableSubscriptionInfoList(
4860                     mContext.getOpPackageName(), mContext.getFeatureId()).stream()
4861                     .map(subInfo -> String.valueOf(subInfo.getSubscriptionId()))
4862                     .collect(Collectors.joining(", ")) + "]");
4863 
4864             pw.print("getSelectableSubscriptionInfoList: [");
4865             pw.println(mSubscriptionManager.getSelectableSubscriptionInfoList().stream()
4866                     .map(subInfo -> String.valueOf(subInfo.getSubscriptionId()))
4867                     .collect(Collectors.joining(", ")) + "]");
4868 
4869             if (mEuiccManager != null) {
4870                 pw.println("Euicc enabled=" + mEuiccManager.isEnabled());
4871             }
4872             pw.println();
4873             pw.println("Local log:");
4874             pw.increaseIndent();
4875             mLocalLog.dump(fd, pw, args);
4876             pw.decreaseIndent();
4877             pw.decreaseIndent();
4878             pw.println();
4879             mSubscriptionDatabaseManager.dump(fd, pw, args);
4880         } finally {
4881             Binder.restoreCallingIdentity(token);
4882         }
4883     }
4884 }
4885