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