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