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