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