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