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