• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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.settings.network.telephony;
18 
19 import static android.provider.Telephony.Carriers.ENFORCE_MANAGED_URI;
20 
21 import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.CDMA;
22 import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.EVDO;
23 import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.GSM;
24 import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.LTE;
25 import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.NR;
26 import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.RAF_TD_SCDMA;
27 import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.RAF_UNKNOWN;
28 import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.WCDMA;
29 import static com.android.settings.network.telephony.TelephonyConstants.TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO;
30 import static com.android.settings.network.telephony.TelephonyConstants.TelephonyManagerConstants.NETWORK_MODE_LTE_GSM_WCDMA;
31 import static com.android.settings.network.telephony.TelephonyConstants.TelephonyManagerConstants.NETWORK_MODE_NR_LTE_CDMA_EVDO;
32 import static com.android.settings.network.telephony.TelephonyConstants.TelephonyManagerConstants.NETWORK_MODE_NR_LTE_GSM_WCDMA;
33 
34 import android.annotation.Nullable;
35 import android.content.ContentResolver;
36 import android.content.Context;
37 import android.content.Intent;
38 import android.content.pm.PackageManager;
39 import android.content.pm.ResolveInfo;
40 import android.database.Cursor;
41 import android.graphics.Color;
42 import android.graphics.drawable.ColorDrawable;
43 import android.graphics.drawable.Drawable;
44 import android.graphics.drawable.LayerDrawable;
45 import android.net.ConnectivityManager;
46 import android.net.Network;
47 import android.net.NetworkCapabilities;
48 import android.os.Bundle;
49 import android.os.PersistableBundle;
50 import android.os.SystemClock;
51 import android.os.SystemProperties;
52 import android.os.UserManager;
53 import android.provider.Settings;
54 import android.telecom.PhoneAccountHandle;
55 import android.telecom.TelecomManager;
56 import android.telephony.CarrierConfigManager;
57 import android.telephony.ServiceState;
58 import android.telephony.SubscriptionInfo;
59 import android.telephony.SubscriptionManager;
60 import android.telephony.TelephonyManager;
61 import android.telephony.euicc.EuiccManager;
62 import android.telephony.ims.ImsManager;
63 import android.telephony.ims.ImsRcsManager;
64 import android.telephony.ims.ProvisioningManager;
65 import android.telephony.ims.RcsUceAdapter;
66 import android.telephony.ims.feature.MmTelFeature;
67 import android.telephony.ims.stub.ImsRegistrationImplBase;
68 import android.text.TextUtils;
69 import android.util.Log;
70 import android.view.Gravity;
71 
72 import androidx.annotation.VisibleForTesting;
73 
74 import com.android.internal.util.ArrayUtils;
75 import com.android.settings.R;
76 import com.android.settings.Utils;
77 import com.android.settings.core.BasePreferenceController;
78 import com.android.settings.core.SubSettingLauncher;
79 import com.android.settings.network.CarrierConfigCache;
80 import com.android.settings.network.SubscriptionUtil;
81 import com.android.settings.network.ims.WifiCallingQueryImsState;
82 import com.android.settings.network.telephony.TelephonyConstants.TelephonyManagerConstants;
83 import com.android.settingslib.core.instrumentation.Instrumentable;
84 import com.android.settingslib.development.DevelopmentSettingsEnabler;
85 import com.android.settingslib.graph.SignalDrawable;
86 import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity;
87 import com.android.settingslib.utils.ThreadUtils;
88 
89 import java.util.Arrays;
90 import java.util.HashSet;
91 import java.util.List;
92 import java.util.Set;
93 import java.util.concurrent.ExecutionException;
94 import java.util.concurrent.Future;
95 import java.util.concurrent.TimeUnit;
96 import java.util.concurrent.TimeoutException;
97 
98 public class MobileNetworkUtils {
99 
100     private static final String TAG = "MobileNetworkUtils";
101 
102     // CID of the device.
103     private static final String KEY_CID = "ro.boot.cid";
104     // CIDs of devices which should not show anything related to eSIM.
105     private static final String KEY_ESIM_CID_IGNORE = "ro.setupwizard.esim_cid_ignore";
106     // System Property which is used to decide whether the default eSIM UI will be shown,
107     // the default value is false.
108     private static final String KEY_ENABLE_ESIM_UI_BY_DEFAULT =
109             "esim.enable_esim_system_ui_by_default";
110     private static final String LEGACY_ACTION_CONFIGURE_PHONE_ACCOUNT =
111             "android.telecom.action.CONNECTION_SERVICE_CONFIGURE";
112     private static final String RTL_MARK = "\u200F";
113 
114     // The following constants are used to draw signal icon.
115     public static final int NO_CELL_DATA_TYPE_ICON = 0;
116     public static final Drawable EMPTY_DRAWABLE = new ColorDrawable(Color.TRANSPARENT);
117 
118     /**
119      * Return true if current user limited by UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS.
120      *
121      * Note: Guest user should have this restriction through
122      *       GuestTelephonyPreferenceController.java.
123      *       However, it's not help with those devices upgraded their software.
124      */
isMobileNetworkUserRestricted(Context context)125     public static boolean isMobileNetworkUserRestricted(Context context) {
126         UserManager um = context.getSystemService(UserManager.class);
127         boolean disallow = false;
128         if (um != null) {
129             disallow = um.isGuestUser() || um.hasUserRestriction(
130                     UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS);
131         }
132         return disallow;
133     }
134 
135     /**
136      * Returns if DPC APNs are enforced.
137      */
isDpcApnEnforced(Context context)138     public static boolean isDpcApnEnforced(Context context) {
139         try (Cursor enforceCursor = context.getContentResolver().query(ENFORCE_MANAGED_URI,
140                 null, null, null, null)) {
141             if (enforceCursor == null || enforceCursor.getCount() != 1) {
142                 return false;
143             }
144             enforceCursor.moveToFirst();
145             return enforceCursor.getInt(0) > 0;
146         }
147     }
148 
149     /**
150      * Returns true if Wifi calling is provisioned for the specific subscription with id
151      * {@code subId}.
152      */
153     @VisibleForTesting
isWfcProvisionedOnDevice(int subId)154     public static boolean isWfcProvisionedOnDevice(int subId) {
155         final ProvisioningManager provisioningMgr =
156                 ProvisioningManager.createForSubscriptionId(subId);
157         if (provisioningMgr == null) {
158             return true;
159         }
160         return provisioningMgr.getProvisioningStatusForCapability(
161                 MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
162                 ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN);
163     }
164 
165     /**
166      * @return The current user setting for whether or not contact discovery is enabled for the
167      * subscription id specified.
168      * @see RcsUceAdapter#isUceSettingEnabled()
169      */
isContactDiscoveryEnabled(Context context, int subId)170     public static boolean isContactDiscoveryEnabled(Context context, int subId) {
171         ImsManager imsManager =
172                 context.getSystemService(ImsManager.class);
173         return isContactDiscoveryEnabled(imsManager, subId);
174     }
175 
176     /**
177      * @return The current user setting for whether or not contact discovery is enabled for the
178      * subscription id specified.
179      * @see RcsUceAdapter#isUceSettingEnabled()
180      */
isContactDiscoveryEnabled(ImsManager imsManager, int subId)181     public static boolean isContactDiscoveryEnabled(ImsManager imsManager,
182             int subId) {
183         ImsRcsManager manager = getImsRcsManager(imsManager, subId);
184         if (manager == null) return false;
185         RcsUceAdapter adapter = manager.getUceAdapter();
186         try {
187             return adapter.isUceSettingEnabled();
188         } catch (android.telephony.ims.ImsException e) {
189             Log.w(TAG, "UCE service is not available: " + e.getMessage());
190         }
191         return false;
192     }
193 
194     /**
195      * Set the new user setting to enable or disable contact discovery through RCS UCE.
196      * @see RcsUceAdapter#setUceSettingEnabled(boolean)
197      */
setContactDiscoveryEnabled(ImsManager imsManager, int subId, boolean isEnabled)198     public static void setContactDiscoveryEnabled(ImsManager imsManager,
199             int subId, boolean isEnabled) {
200         ImsRcsManager manager = getImsRcsManager(imsManager, subId);
201         if (manager == null) return;
202         RcsUceAdapter adapter = manager.getUceAdapter();
203         try {
204             adapter.setUceSettingEnabled(isEnabled);
205         } catch (android.telephony.ims.ImsException e) {
206             Log.w(TAG, "UCE service is not available: " + e.getMessage());
207         }
208     }
209 
210     /**
211      * @return The ImsRcsManager associated with the subscription specified.
212      */
getImsRcsManager(ImsManager imsManager, int subId)213     private static ImsRcsManager getImsRcsManager(ImsManager imsManager,
214             int subId) {
215         if (imsManager == null) return null;
216         try {
217             return imsManager.getImsRcsManager(subId);
218         } catch (Exception e) {
219             Log.w(TAG, "Could not resolve ImsRcsManager: " + e.getMessage());
220         }
221         return null;
222     }
223 
224     /**
225      * @return true if contact discovery is available for the subscription specified and the option
226      * should be shown to the user, false if the option should be hidden.
227      */
isContactDiscoveryVisible(Context context, int subId)228     public static boolean isContactDiscoveryVisible(Context context, int subId) {
229         CarrierConfigCache carrierConfigCache = CarrierConfigCache.getInstance(context);
230         if (!carrierConfigCache.hasCarrierConfigManager()) {
231             Log.w(TAG, "isContactDiscoveryVisible: Could not resolve carrier config");
232             return false;
233         }
234         PersistableBundle bundle = carrierConfigCache.getConfigForSubId(subId);
235         return bundle == null ? false : bundle.getBoolean(
236                 CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL, false /*default*/)
237                 || bundle.getBoolean(CarrierConfigManager.Ims.KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL,
238                 false /*default*/);
239     }
240 
buildPhoneAccountConfigureIntent( Context context, PhoneAccountHandle accountHandle)241     public static Intent buildPhoneAccountConfigureIntent(
242             Context context, PhoneAccountHandle accountHandle) {
243         Intent intent = buildConfigureIntent(
244                 context, accountHandle, TelecomManager.ACTION_CONFIGURE_PHONE_ACCOUNT);
245 
246         if (intent == null) {
247             // If the new configuration didn't work, try the old configuration intent.
248             intent = buildConfigureIntent(context, accountHandle,
249                     LEGACY_ACTION_CONFIGURE_PHONE_ACCOUNT);
250         }
251         return intent;
252     }
253 
buildConfigureIntent( Context context, PhoneAccountHandle accountHandle, String actionStr)254     private static Intent buildConfigureIntent(
255             Context context, PhoneAccountHandle accountHandle, String actionStr) {
256         if (accountHandle == null || accountHandle.getComponentName() == null
257                 || TextUtils.isEmpty(accountHandle.getComponentName().getPackageName())) {
258             return null;
259         }
260 
261         // Build the settings intent.
262         Intent intent = new Intent(actionStr);
263         intent.setPackage(accountHandle.getComponentName().getPackageName());
264         intent.addCategory(Intent.CATEGORY_DEFAULT);
265         intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, accountHandle);
266 
267         // Check to see that the phone account package can handle the setting intent.
268         final PackageManager pm = context.getPackageManager();
269         final List<ResolveInfo> resolutions = pm.queryIntentActivities(intent, 0);
270         if (resolutions.size() == 0) {
271             intent = null;  // set no intent if the package cannot handle it.
272         }
273 
274         return intent;
275     }
276 
277     /**
278      * Whether to show the entry point to eUICC settings.
279      *
280      * <p>We show the entry point on any device which supports eUICC as long as either the eUICC
281      * was ever provisioned (that is, at least one profile was ever downloaded onto it), or if
282      * the user has enabled development mode.
283      */
showEuiccSettings(Context context)284     public static boolean showEuiccSettings(Context context) {
285         if (!SubscriptionUtil.isSimHardwareVisible(context)) {
286             return false;
287         }
288         long timeForAccess = SystemClock.elapsedRealtime();
289         try {
290             Boolean isShow = ((Future<Boolean>) ThreadUtils.postOnBackgroundThread(() -> {
291                         try {
292                             return showEuiccSettingsDetecting(context);
293                         } catch (Exception threadException) {
294                             Log.w(TAG, "Accessing Euicc failure", threadException);
295                         }
296                         return Boolean.FALSE;
297                     })).get(3, TimeUnit.SECONDS);
298             return ((isShow != null) && isShow.booleanValue());
299         } catch (ExecutionException | InterruptedException | TimeoutException exception) {
300             timeForAccess = SystemClock.elapsedRealtime() - timeForAccess;
301             Log.w(TAG, "Accessing Euicc takes too long: +" + timeForAccess + "ms");
302         }
303         return false;
304     }
305 
306     // The same as #showEuiccSettings(Context context)
showEuiccSettingsDetecting(Context context)307     public static Boolean showEuiccSettingsDetecting(Context context) {
308         final EuiccManager euiccManager =
309                 (EuiccManager) context.getSystemService(EuiccManager.class);
310         if (!euiccManager.isEnabled()) {
311             Log.w(TAG, "EuiccManager is not enabled.");
312             return false;
313         }
314 
315         final ContentResolver cr = context.getContentResolver();
316         final boolean esimIgnoredDevice =
317                 Arrays.asList(TextUtils.split(SystemProperties.get(KEY_ESIM_CID_IGNORE, ""), ","))
318                         .contains(SystemProperties.get(KEY_CID));
319         final boolean enabledEsimUiByDefault =
320                 SystemProperties.getBoolean(KEY_ENABLE_ESIM_UI_BY_DEFAULT, true);
321         final boolean euiccProvisioned =
322                 Settings.Global.getInt(cr, Settings.Global.EUICC_PROVISIONED, 0) != 0;
323         final boolean inDeveloperMode =
324                 DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(context);
325         Log.i(TAG,
326                 String.format("showEuiccSettings: esimIgnoredDevice: %b, enabledEsimUiByDefault: "
327                         + "%b, euiccProvisioned: %b, inDeveloperMode: %b.",
328                 esimIgnoredDevice, enabledEsimUiByDefault, euiccProvisioned, inDeveloperMode));
329         return (euiccProvisioned
330                 || (!esimIgnoredDevice && inDeveloperMode)
331                 || (!esimIgnoredDevice && enabledEsimUiByDefault
332                         && isCurrentCountrySupported(context)));
333     }
334 
335     /**
336      * Return {@code true} if mobile data is enabled
337      */
isMobileDataEnabled(Context context)338     public static boolean isMobileDataEnabled(Context context) {
339         final TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class);
340         if (!telephonyManager.isDataEnabled()) {
341             // Check if the data is enabled on the second SIM in the case of dual SIM.
342             final TelephonyManager tmDefaultData = telephonyManager.createForSubscriptionId(
343                     SubscriptionManager.getDefaultDataSubscriptionId());
344             if (tmDefaultData == null || !tmDefaultData.isDataEnabled()) {
345                 return false;
346             }
347         }
348         return true;
349     }
350 
351     /**
352      * Set whether to enable data for {@code subId}, also whether to disable data for other
353      * subscription
354      */
setMobileDataEnabled(Context context, int subId, boolean enabled, boolean disableOtherSubscriptions)355     public static void setMobileDataEnabled(Context context, int subId, boolean enabled,
356             boolean disableOtherSubscriptions) {
357         final TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class)
358                 .createForSubscriptionId(subId);
359         final SubscriptionManager subscriptionManager = context.getSystemService(
360                 SubscriptionManager.class);
361         telephonyManager.setDataEnabled(enabled);
362 
363         if (disableOtherSubscriptions) {
364             final List<SubscriptionInfo> subInfoList =
365                     subscriptionManager.getActiveSubscriptionInfoList();
366             if (subInfoList != null) {
367                 for (SubscriptionInfo subInfo : subInfoList) {
368                     // We never disable mobile data for opportunistic subscriptions.
369                     if (subInfo.getSubscriptionId() != subId && !subInfo.isOpportunistic()) {
370                         context.getSystemService(TelephonyManager.class).createForSubscriptionId(
371                                 subInfo.getSubscriptionId()).setDataEnabled(false);
372                     }
373                 }
374             }
375         }
376     }
377 
378     /**
379      * Return {@code true} if show CDMA category
380      */
isCdmaOptions(Context context, int subId)381     public static boolean isCdmaOptions(Context context, int subId) {
382         if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
383             return false;
384         }
385         final PersistableBundle carrierConfig =
386                 CarrierConfigCache.getInstance(context).getConfigForSubId(subId);
387         if (carrierConfig != null
388                 && !carrierConfig.getBoolean(
389                 CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL)
390                 && carrierConfig.getBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL)) {
391             return true;
392         }
393 
394         final TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class)
395                 .createForSubscriptionId(subId);
396         if (telephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
397             return true;
398         }
399 
400         if (isWorldMode(context, subId)) {
401             final int settingsNetworkMode = getNetworkTypeFromRaf(
402                     (int) telephonyManager.getAllowedNetworkTypesForReason(
403                             TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER));
404 
405             if (settingsNetworkMode == NETWORK_MODE_LTE_GSM_WCDMA
406                     || settingsNetworkMode == NETWORK_MODE_LTE_CDMA_EVDO
407                     || settingsNetworkMode == NETWORK_MODE_NR_LTE_GSM_WCDMA
408                     || settingsNetworkMode == NETWORK_MODE_NR_LTE_CDMA_EVDO) {
409                 return true;
410             }
411 
412             if (shouldSpeciallyUpdateGsmCdma(context, subId)) {
413                 return true;
414             }
415         }
416 
417         return false;
418     }
419 
420     /**
421      * return {@code true} if we need show Gsm related settings
422      */
isGsmOptions(Context context, int subId)423     public static boolean isGsmOptions(Context context, int subId) {
424         if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
425             return false;
426         }
427         if (isGsmBasicOptions(context, subId)) {
428             return true;
429         }
430         final TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class)
431                 .createForSubscriptionId(subId);
432         final int networkMode = getNetworkTypeFromRaf(
433                 (int) telephonyManager.getAllowedNetworkTypesForReason(
434                         TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER));
435         if (isWorldMode(context, subId)) {
436             if (networkMode == NETWORK_MODE_LTE_CDMA_EVDO
437                     || networkMode == NETWORK_MODE_LTE_GSM_WCDMA
438                     || networkMode == NETWORK_MODE_NR_LTE_CDMA_EVDO
439                     || networkMode == NETWORK_MODE_NR_LTE_GSM_WCDMA) {
440                 return true;
441             } else if (shouldSpeciallyUpdateGsmCdma(context, subId)) {
442                 return true;
443             }
444         }
445 
446         return false;
447     }
448 
isGsmBasicOptions(Context context, int subId)449     private static boolean isGsmBasicOptions(Context context, int subId) {
450         final PersistableBundle carrierConfig =
451                 CarrierConfigCache.getInstance(context).getConfigForSubId(subId);
452         if (carrierConfig != null
453                 && !carrierConfig.getBoolean(
454                 CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL)
455                 && carrierConfig.getBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL)) {
456             return true;
457         }
458 
459         final TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class)
460                 .createForSubscriptionId(subId);
461         if (telephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM) {
462             return true;
463         }
464 
465         return false;
466     }
467 
468     /**
469      * Return {@code true} if it is world mode, and we may show advanced options in telephony
470      * settings
471      */
isWorldMode(Context context, int subId)472     public static boolean isWorldMode(Context context, int subId) {
473         final PersistableBundle carrierConfig =
474                 CarrierConfigCache.getInstance(context).getConfigForSubId(subId);
475         return carrierConfig == null
476                 ? false
477                 : carrierConfig.getBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL);
478     }
479 
480     /**
481      * Return {@code true} if we need show settings for network selection(i.e. Verizon)
482      */
shouldDisplayNetworkSelectOptions(Context context, int subId)483     public static boolean shouldDisplayNetworkSelectOptions(Context context, int subId) {
484         final TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class)
485                 .createForSubscriptionId(subId);
486         final PersistableBundle carrierConfig =
487                 CarrierConfigCache.getInstance(context).getConfigForSubId(subId);
488         if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID
489                 || carrierConfig == null
490                 || !carrierConfig.getBoolean(
491                 CarrierConfigManager.KEY_OPERATOR_SELECTION_EXPAND_BOOL)
492                 || carrierConfig.getBoolean(
493                 CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL)
494                 || (carrierConfig.getBoolean(CarrierConfigManager.KEY_CSP_ENABLED_BOOL)
495                 && !telephonyManager.isManualNetworkSelectionAllowed())) {
496             return false;
497         }
498 
499         if (isWorldMode(context, subId)) {
500             final int networkMode = getNetworkTypeFromRaf(
501                     (int) telephonyManager.getAllowedNetworkTypesForReason(
502                             TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER));
503             if (networkMode == TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO) {
504                 return false;
505             }
506             if (shouldSpeciallyUpdateGsmCdma(context, subId)) {
507                 return false;
508             }
509 
510             if (networkMode == TelephonyManagerConstants.NETWORK_MODE_LTE_GSM_WCDMA) {
511                 return true;
512             }
513         }
514 
515         return isGsmBasicOptions(context, subId);
516     }
517 
518     /**
519      * Return {@code true} if Tdscdma is supported in current subscription
520      */
isTdscdmaSupported(Context context, int subId)521     public static boolean isTdscdmaSupported(Context context, int subId) {
522         return isTdscdmaSupported(context,
523                 context.getSystemService(TelephonyManager.class).createForSubscriptionId(subId));
524     }
525 
526     //TODO(b/117651939): move it to telephony
isTdscdmaSupported(Context context, TelephonyManager telephonyManager)527     private static boolean isTdscdmaSupported(Context context, TelephonyManager telephonyManager) {
528         final PersistableBundle carrierConfig = CarrierConfigCache.getInstance(context).getConfig();
529 
530         if (carrierConfig == null) {
531             return false;
532         }
533 
534         if (carrierConfig.getBoolean(CarrierConfigManager.KEY_SUPPORT_TDSCDMA_BOOL)) {
535             return true;
536         }
537         final String[] numericArray = carrierConfig.getStringArray(
538                 CarrierConfigManager.KEY_SUPPORT_TDSCDMA_ROAMING_NETWORKS_STRING_ARRAY);
539         if (numericArray == null) {
540             return false;
541         }
542         final ServiceState serviceState = telephonyManager.getServiceState();
543         final String operatorNumeric =
544                 (serviceState != null) ? serviceState.getOperatorNumeric() : null;
545         if (operatorNumeric == null) {
546             return false;
547         }
548         for (String numeric : numericArray) {
549             if (operatorNumeric.equals(numeric)) {
550                 return true;
551             }
552         }
553         return false;
554     }
555 
556     /**
557      * Return subId that supported by search. If there are more than one, return first one,
558      * otherwise return {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID}
559      */
getSearchableSubscriptionId(Context context)560     public static int getSearchableSubscriptionId(Context context) {
561         final int[] subIds = getActiveSubscriptionIdList(context);
562 
563         return subIds.length >= 1 ? subIds[0] : SubscriptionManager.INVALID_SUBSCRIPTION_ID;
564     }
565 
566     /**
567      * Return availability for a default subscription id. If subId already been set, use it to
568      * check, otherwise traverse all active subIds on device to check.
569      * @param context context
570      * @param defSubId Default subId get from telephony preference controller
571      * @param callback Callback to check availability for a specific subId
572      * @return Availability
573      *
574      * @see BasePreferenceController#getAvailabilityStatus()
575      */
getAvailability(Context context, int defSubId, TelephonyAvailabilityCallback callback)576     public static int getAvailability(Context context, int defSubId,
577             TelephonyAvailabilityCallback callback) {
578         if (defSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
579             // If subId has been set, return the corresponding status
580             return callback.getAvailabilityStatus(defSubId);
581         } else {
582             // Otherwise, search whether there is one subId in device that support this preference
583             final int[] subIds = getActiveSubscriptionIdList(context);
584             if (ArrayUtils.isEmpty(subIds)) {
585                 return callback.getAvailabilityStatus(
586                         SubscriptionManager.INVALID_SUBSCRIPTION_ID);
587             } else {
588                 for (final int subId : subIds) {
589                     final int status = callback.getAvailabilityStatus(subId);
590                     if (status == BasePreferenceController.AVAILABLE) {
591                         return status;
592                     }
593                 }
594                 return callback.getAvailabilityStatus(subIds[0]);
595             }
596         }
597     }
598 
599     /**
600      * This method is migrated from {@link com.android.phone.MobileNetworkSettings} and we should
601      * use it carefully. This code snippet doesn't have very clear meaning however we should
602      * update GSM or CDMA differently based on what it returns.
603      *
604      * 1. For all CDMA settings, make them visible if it return {@code true}
605      * 2. For GSM settings, make them visible if it return {@code true} unless 3
606      * 3. For network select settings, make it invisible if it return {@code true}
607      */
608     @VisibleForTesting
shouldSpeciallyUpdateGsmCdma(Context context, int subId)609     static boolean shouldSpeciallyUpdateGsmCdma(Context context, int subId) {
610         if (!isWorldMode(context, subId)) {
611             return false;
612         }
613         final TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class)
614                 .createForSubscriptionId(subId);
615         final int networkMode = getNetworkTypeFromRaf(
616                 (int) telephonyManager.getAllowedNetworkTypesForReason(
617                         TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER));
618         if (networkMode == TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_GSM
619                 || networkMode == TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA
620                 || networkMode == TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA
621                 || networkMode == TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_WCDMA
622                 || networkMode
623                 == TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA
624                 || networkMode == TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA) {
625             if (!isTdscdmaSupported(context, subId)) {
626                 return true;
627             }
628         }
629 
630         return false;
631     }
632 
getSignalStrengthIcon(Context context, int level, int numLevels, int iconType, boolean cutOut, boolean carrierNetworkChanged)633     public static Drawable getSignalStrengthIcon(Context context, int level, int numLevels,
634             int iconType, boolean cutOut, boolean carrierNetworkChanged) {
635         final SignalDrawable signalDrawable = new SignalDrawable(context);
636         signalDrawable.setLevel(
637                 carrierNetworkChanged ? SignalDrawable.getCarrierChangeState(numLevels)
638                         : SignalDrawable.getState(level, numLevels, cutOut));
639 
640         // Make the network type drawable
641         final Drawable networkDrawable =
642                 iconType == NO_CELL_DATA_TYPE_ICON
643                         ? EMPTY_DRAWABLE
644                         : context.getResources().getDrawable(iconType, context.getTheme());
645 
646         // Overlay the two drawables
647         final Drawable[] layers = {networkDrawable, signalDrawable};
648         final int iconSize =
649                 context.getResources().getDimensionPixelSize(R.dimen.signal_strength_icon_size);
650 
651         final LayerDrawable icons = new LayerDrawable(layers);
652         // Set the network type icon at the top left
653         icons.setLayerGravity(0 /* index of networkDrawable */, Gravity.TOP | Gravity.LEFT);
654         // Set the signal strength icon at the bottom right
655         icons.setLayerGravity(1 /* index of SignalDrawable */, Gravity.BOTTOM | Gravity.RIGHT);
656         icons.setLayerSize(1 /* index of SignalDrawable */, iconSize, iconSize);
657         icons.setTintList(Utils.getColorAttr(context, android.R.attr.colorControlNormal));
658         return icons;
659     }
660 
661     /**
662      * This method is migrated from
663      * {@link android.telephony.TelephonyManager.getNetworkOperatorName}. Which provides
664      *
665      * 1. Better support under multi-SIM environment.
666      * 2. Similar design which aligned with operator name displayed in status bar
667      */
getCurrentCarrierNameForDisplay(Context context, int subId)668     public static CharSequence getCurrentCarrierNameForDisplay(Context context, int subId) {
669         final SubscriptionManager sm = context.getSystemService(SubscriptionManager.class);
670         if (sm != null) {
671             final SubscriptionInfo subInfo = getSubscriptionInfo(sm, subId);
672             if (subInfo != null) {
673                 return subInfo.getCarrierName();
674             }
675         }
676         return getOperatorNameFromTelephonyManager(context);
677     }
678 
getCurrentCarrierNameForDisplay(Context context)679     public static CharSequence getCurrentCarrierNameForDisplay(Context context) {
680         final SubscriptionManager sm = context.getSystemService(SubscriptionManager.class);
681         if (sm != null) {
682             final int subId = sm.getDefaultSubscriptionId();
683             final SubscriptionInfo subInfo = getSubscriptionInfo(sm, subId);
684             if (subInfo != null) {
685                 return subInfo.getCarrierName();
686             }
687         }
688         return getOperatorNameFromTelephonyManager(context);
689     }
690 
getSubscriptionInfo(SubscriptionManager subManager, int subId)691     private static SubscriptionInfo getSubscriptionInfo(SubscriptionManager subManager, int subId) {
692         List<SubscriptionInfo> subInfos = subManager.getActiveSubscriptionInfoList();
693         if (subInfos == null) {
694             return null;
695         }
696         for (SubscriptionInfo subInfo : subInfos) {
697             if (subInfo.getSubscriptionId() == subId) {
698                 return subInfo;
699             }
700         }
701         return null;
702     }
703 
getOperatorNameFromTelephonyManager(Context context)704     private static String getOperatorNameFromTelephonyManager(Context context) {
705         final TelephonyManager tm =
706                 (TelephonyManager) context.getSystemService(TelephonyManager.class);
707         if (tm == null) {
708             return null;
709         }
710         return tm.getNetworkOperatorName();
711     }
712 
getActiveSubscriptionIdList(Context context)713     private static int[] getActiveSubscriptionIdList(Context context) {
714         final SubscriptionManager subscriptionManager = context.getSystemService(
715                 SubscriptionManager.class);
716         final List<SubscriptionInfo> subInfoList =
717                 subscriptionManager.getActiveSubscriptionInfoList();
718         if (subInfoList == null) {
719             return new int[0];
720         }
721         int[] activeSubIds = new int[subInfoList.size()];
722         int i = 0;
723         for (SubscriptionInfo subInfo : subInfoList) {
724             activeSubIds[i] = subInfo.getSubscriptionId();
725             i++;
726         }
727         return activeSubIds;
728     }
729 
730     /**
731      * Loop through all the device logical slots to check whether the user's current country
732      * supports eSIM.
733      */
isCurrentCountrySupported(Context context)734     private static boolean isCurrentCountrySupported(Context context) {
735         final EuiccManager em = (EuiccManager) context.getSystemService(EuiccManager.class);
736         final TelephonyManager tm =
737                 (TelephonyManager) context.getSystemService(TelephonyManager.class);
738 
739         Set<String> countrySet = new HashSet<>();
740         for (int i = 0; i < tm.getPhoneCount(); i++) {
741             String countryCode = tm.getNetworkCountryIso(i);
742             if (!TextUtils.isEmpty(countryCode)) {
743                 countrySet.add(countryCode);
744             }
745         }
746         boolean isSupported = countrySet.stream().anyMatch(em::isSupportedCountry);
747         Log.i(TAG, "isCurrentCountrySupported countryCodes: " + countrySet
748                 + " eSIMSupported: " + isSupported);
749         return isSupported;
750     }
751 
752     /**
753      *  Imported from {@link android.telephony.RadioAccessFamily}
754      */
getRafFromNetworkType(int type)755     public static long getRafFromNetworkType(int type) {
756         switch (type) {
757             case TelephonyManagerConstants.NETWORK_MODE_WCDMA_PREF:
758                 return GSM | WCDMA;
759             case TelephonyManagerConstants.NETWORK_MODE_GSM_ONLY:
760                 return GSM;
761             case TelephonyManagerConstants.NETWORK_MODE_WCDMA_ONLY:
762                 return WCDMA;
763             case TelephonyManagerConstants.NETWORK_MODE_GSM_UMTS:
764                 return GSM | WCDMA;
765             case TelephonyManagerConstants.NETWORK_MODE_CDMA_EVDO:
766                 return CDMA | EVDO;
767             case TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO:
768                 return LTE | CDMA | EVDO;
769             case TelephonyManagerConstants.NETWORK_MODE_LTE_GSM_WCDMA:
770                 return LTE | GSM | WCDMA;
771             case TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA:
772                 return LTE | CDMA | EVDO | GSM | WCDMA;
773             case TelephonyManagerConstants.NETWORK_MODE_LTE_ONLY:
774                 return LTE;
775             case TelephonyManagerConstants.NETWORK_MODE_LTE_WCDMA:
776                 return LTE | WCDMA;
777             case TelephonyManagerConstants.NETWORK_MODE_CDMA_NO_EVDO:
778                 return CDMA;
779             case TelephonyManagerConstants.NETWORK_MODE_EVDO_NO_CDMA:
780                 return EVDO;
781             case TelephonyManagerConstants.NETWORK_MODE_GLOBAL:
782                 return GSM | WCDMA | CDMA | EVDO;
783             case TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_ONLY:
784                 return RAF_TD_SCDMA;
785             case TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_WCDMA:
786                 return RAF_TD_SCDMA | WCDMA;
787             case TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA:
788                 return LTE | RAF_TD_SCDMA;
789             case TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_GSM:
790                 return RAF_TD_SCDMA | GSM;
791             case TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_GSM:
792                 return LTE | RAF_TD_SCDMA | GSM;
793             case TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_GSM_WCDMA:
794                 return RAF_TD_SCDMA | GSM | WCDMA;
795             case TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_WCDMA:
796                 return LTE | RAF_TD_SCDMA | WCDMA;
797             case TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA:
798                 return LTE | RAF_TD_SCDMA | GSM | WCDMA;
799             case TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
800                 return RAF_TD_SCDMA | CDMA | EVDO | GSM | WCDMA;
801             case TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
802                 return LTE | RAF_TD_SCDMA | CDMA | EVDO | GSM | WCDMA;
803             case (TelephonyManagerConstants.NETWORK_MODE_NR_ONLY):
804                 return NR;
805             case (TelephonyManagerConstants.NETWORK_MODE_NR_LTE):
806                 return NR | LTE;
807             case (TelephonyManagerConstants.NETWORK_MODE_NR_LTE_CDMA_EVDO):
808                 return NR | LTE | CDMA | EVDO;
809             case (TelephonyManagerConstants.NETWORK_MODE_NR_LTE_GSM_WCDMA):
810                 return NR | LTE | GSM | WCDMA;
811             case (TelephonyManagerConstants.NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA):
812                 return NR | LTE | CDMA | EVDO | GSM | WCDMA;
813             case (TelephonyManagerConstants.NETWORK_MODE_NR_LTE_WCDMA):
814                 return NR | LTE | WCDMA;
815             case (TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA):
816                 return NR | LTE | RAF_TD_SCDMA;
817             case (TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_GSM):
818                 return NR | LTE | RAF_TD_SCDMA | GSM;
819             case (TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_WCDMA):
820                 return NR | LTE | RAF_TD_SCDMA | WCDMA;
821             case (TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA):
822                 return NR | LTE | RAF_TD_SCDMA | GSM | WCDMA;
823             case (TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA):
824                 return NR | LTE | RAF_TD_SCDMA | CDMA | EVDO | GSM | WCDMA;
825             default:
826                 return RAF_UNKNOWN;
827         }
828     }
829 
830     /**
831      *  Imported from {@link android.telephony.RadioAccessFamily}
832      */
getNetworkTypeFromRaf(int raf)833     public static int getNetworkTypeFromRaf(int raf) {
834         raf = getAdjustedRaf(raf);
835 
836         switch (raf) {
837             case (GSM | WCDMA):
838                 return TelephonyManagerConstants.NETWORK_MODE_WCDMA_PREF;
839             case GSM:
840                 return TelephonyManagerConstants.NETWORK_MODE_GSM_ONLY;
841             case WCDMA:
842                 return TelephonyManagerConstants.NETWORK_MODE_WCDMA_ONLY;
843             case (CDMA | EVDO):
844                 return TelephonyManagerConstants.NETWORK_MODE_CDMA_EVDO;
845             case (LTE | CDMA | EVDO):
846                 return TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO;
847             case (LTE | GSM | WCDMA):
848                 return TelephonyManagerConstants.NETWORK_MODE_LTE_GSM_WCDMA;
849             case (LTE | CDMA | EVDO | GSM | WCDMA):
850                 return TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA;
851             case LTE:
852                 return TelephonyManagerConstants.NETWORK_MODE_LTE_ONLY;
853             case (LTE | WCDMA):
854                 return TelephonyManagerConstants.NETWORK_MODE_LTE_WCDMA;
855             case CDMA:
856                 return TelephonyManagerConstants.NETWORK_MODE_CDMA_NO_EVDO;
857             case EVDO:
858                 return TelephonyManagerConstants.NETWORK_MODE_EVDO_NO_CDMA;
859             case (GSM | WCDMA | CDMA | EVDO):
860                 return TelephonyManagerConstants.NETWORK_MODE_GLOBAL;
861             case RAF_TD_SCDMA:
862                 return TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_ONLY;
863             case (RAF_TD_SCDMA | WCDMA):
864                 return TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_WCDMA;
865             case (LTE | RAF_TD_SCDMA):
866                 return TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA;
867             case (RAF_TD_SCDMA | GSM):
868                 return TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_GSM;
869             case (LTE | RAF_TD_SCDMA | GSM):
870                 return TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_GSM;
871             case (RAF_TD_SCDMA | GSM | WCDMA):
872                 return TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_GSM_WCDMA;
873             case (LTE | RAF_TD_SCDMA | WCDMA):
874                 return TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_WCDMA;
875             case (LTE | RAF_TD_SCDMA | GSM | WCDMA):
876                 return TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA;
877             case (RAF_TD_SCDMA | CDMA | EVDO | GSM | WCDMA):
878                 return TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA;
879             case (LTE | RAF_TD_SCDMA | CDMA | EVDO | GSM | WCDMA):
880                 return TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA;
881             case (NR):
882                 return TelephonyManagerConstants.NETWORK_MODE_NR_ONLY;
883             case (NR | LTE):
884                 return TelephonyManagerConstants.NETWORK_MODE_NR_LTE;
885             case (NR | LTE | CDMA | EVDO):
886                 return TelephonyManagerConstants.NETWORK_MODE_NR_LTE_CDMA_EVDO;
887             case (NR | LTE | GSM | WCDMA):
888                 return TelephonyManagerConstants.NETWORK_MODE_NR_LTE_GSM_WCDMA;
889             case (NR | LTE | CDMA | EVDO | GSM | WCDMA):
890                 return TelephonyManagerConstants.NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA;
891             case (NR | LTE | WCDMA):
892                 return TelephonyManagerConstants.NETWORK_MODE_NR_LTE_WCDMA;
893             case (NR | LTE | RAF_TD_SCDMA):
894                 return TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA;
895             case (NR | LTE | RAF_TD_SCDMA | GSM):
896                 return TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_GSM;
897             case (NR | LTE | RAF_TD_SCDMA | WCDMA):
898                 return TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_WCDMA;
899             case (NR | LTE | RAF_TD_SCDMA | GSM | WCDMA):
900                 return TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA;
901             case (NR | LTE | RAF_TD_SCDMA | CDMA | EVDO | GSM | WCDMA):
902                 return TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA;
903             default:
904                 return TelephonyManagerConstants.NETWORK_MODE_UNKNOWN;
905         }
906     }
907 
908     /**
909      *  Imported from {@link android.telephony.RadioAccessFamily}
910      */
getAdjustedRaf(int raf)911     private static int getAdjustedRaf(int raf) {
912         raf = ((GSM & raf) > 0) ? (GSM | raf) : raf;
913         raf = ((WCDMA & raf) > 0) ? (WCDMA | raf) : raf;
914         raf = ((CDMA & raf) > 0) ? (CDMA | raf) : raf;
915         raf = ((EVDO & raf) > 0) ? (EVDO | raf) : raf;
916         raf = ((LTE & raf) > 0) ? (LTE | raf) : raf;
917         raf = ((NR & raf) > 0) ? (NR | raf) : raf;
918         return raf;
919     }
920 
921     /**
922      * Copied from SubscriptionsPreferenceController#activeNetworkIsCellular()
923      */
activeNetworkIsCellular(Context context)924     public static boolean activeNetworkIsCellular(Context context) {
925         final ConnectivityManager connectivityManager =
926                 context.getSystemService(ConnectivityManager.class);
927         final Network activeNetwork = connectivityManager.getActiveNetwork();
928         if (activeNetwork == null) {
929             return false;
930         }
931         final NetworkCapabilities networkCapabilities =
932                 connectivityManager.getNetworkCapabilities(activeNetwork);
933         if (networkCapabilities == null) {
934             return false;
935         }
936         return networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR);
937     }
938 
939     /**
940      * Copied from WifiCallingPreferenceController#isWifiCallingEnabled()
941      */
isWifiCallingEnabled(Context context, int subId, @Nullable WifiCallingQueryImsState queryImsState)942     public static boolean isWifiCallingEnabled(Context context, int subId,
943             @Nullable WifiCallingQueryImsState queryImsState) {
944         if (queryImsState == null) {
945             queryImsState = new WifiCallingQueryImsState(context, subId);
946         }
947         return queryImsState.isReadyToWifiCalling();
948     }
949 
950     /**
951      * Returns preferred status of Calls & SMS separately when Provider Model is enabled.
952      */
getPreferredStatus(boolean isRtlMode, Context context, boolean isPreferredCallStatus, List<SubscriptionInfoEntity> entityList)953     public static CharSequence getPreferredStatus(boolean isRtlMode, Context context,
954             boolean isPreferredCallStatus, List<SubscriptionInfoEntity> entityList) {
955         if (entityList != null && !entityList.isEmpty()) {
956             final StringBuilder summary = new StringBuilder();
957             for (SubscriptionInfoEntity subInfo : entityList) {
958                 int subsSize = entityList.size();
959                 final CharSequence displayName = subInfo.uniqueName;
960 
961                 // Set displayName as summary if there is only one valid SIM.
962                 if (subsSize == 1 && subInfo.isValidSubscription) {
963                     return displayName;
964                 }
965 
966                 CharSequence status = isPreferredCallStatus
967                         ? getPreferredCallStatus(context, subInfo)
968                         : getPreferredSmsStatus(context, subInfo);
969                 if (status.toString().isEmpty()) {
970                     // If there are 2 or more SIMs and one of these has no preferred status,
971                     // set only its displayName as summary.
972                     summary.append(displayName);
973                 } else {
974                     summary.append(displayName)
975                             .append(" (")
976                             .append(status)
977                             .append(")");
978                 }
979                 // Do not add ", " for the last subscription.
980                 if (subInfo != entityList.get(entityList.size() - 1)) {
981                     summary.append(", ");
982                 }
983 
984                 if (isRtlMode) {
985                     summary.insert(0, RTL_MARK).insert(summary.length(), RTL_MARK);
986                 }
987             }
988             return summary;
989         } else {
990             return "";
991         }
992     }
993 
getPreferredCallStatus(Context context, SubscriptionInfoEntity subInfo)994     private static CharSequence getPreferredCallStatus(Context context,
995             SubscriptionInfoEntity subInfo) {
996         String status = "";
997         if (subInfo.getSubId() == SubscriptionManager.getDefaultVoiceSubscriptionId()) {
998             status = setSummaryResId(context, R.string.calls_sms_preferred);
999         }
1000 
1001         return status;
1002     }
1003 
getPreferredSmsStatus(Context context, SubscriptionInfoEntity subInfo)1004     private static CharSequence getPreferredSmsStatus(Context context,
1005             SubscriptionInfoEntity subInfo) {
1006         String status = "";
1007         if (subInfo.getSubId() == SubscriptionManager.getDefaultSmsSubscriptionId()) {
1008             status = setSummaryResId(context, R.string.calls_sms_preferred);
1009         }
1010 
1011         return status;
1012     }
1013 
setSummaryResId(Context context, int resId)1014     private static String setSummaryResId(Context context, int resId) {
1015         return context.getResources().getString(resId);
1016     }
1017 
launchMobileNetworkSettings(Context context, SubscriptionInfo info)1018     public static void launchMobileNetworkSettings(Context context, SubscriptionInfo info) {
1019         if (!SubscriptionUtil.isSimHardwareVisible(context)) {
1020             Log.e(TAG, "launchMobileNetworkSettings fail, device without such UI.");
1021             return;
1022         }
1023         final int subId = info.getSubscriptionId();
1024         if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1025             Log.d(TAG, "launchMobileNetworkSettings fail, subId is invalid.");
1026             return;
1027         }
1028 
1029         Log.d(TAG, "launchMobileNetworkSettings for subId: " + subId);
1030         final Bundle extra = new Bundle();
1031         extra.putInt(Settings.EXTRA_SUB_ID, subId);
1032         new SubSettingLauncher(context)
1033                 .setTitleText(SubscriptionUtil.getUniqueSubscriptionDisplayName(info, context))
1034                 .setDestination(MobileNetworkSettings.class.getCanonicalName())
1035                 .setSourceMetricsCategory(Instrumentable.METRICS_CATEGORY_UNKNOWN)
1036                 .setArguments(extra)
1037                 .launch();
1038     }
1039 
launchMobileNetworkSettings(Context context, SubscriptionInfoEntity info)1040     public static void launchMobileNetworkSettings(Context context, SubscriptionInfoEntity info) {
1041         final int subId = Integer.valueOf(info.subId);
1042         if (!info.isValidSubscription) {
1043             Log.d(TAG, "launchMobileNetworkSettings fail, subId is invalid.");
1044             return;
1045         }
1046 
1047         Log.d(TAG, "launchMobileNetworkSettings for SubscriptionInfoEntity subId: " + subId);
1048         final Bundle extra = new Bundle();
1049         extra.putInt(Settings.EXTRA_SUB_ID, subId);
1050         new SubSettingLauncher(context)
1051                 .setTitleText(info.uniqueName)
1052                 .setDestination(MobileNetworkSettings.class.getCanonicalName())
1053                 .setSourceMetricsCategory(Instrumentable.METRICS_CATEGORY_UNKNOWN)
1054                 .setArguments(extra)
1055                 .launch();
1056     }
1057 
1058 }
1059