1 package com.android.settingslib; 2 3 import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_USER_LABEL; 4 5 import android.annotation.ColorInt; 6 import android.annotation.Nullable; 7 import android.app.admin.DevicePolicyManager; 8 import android.content.Context; 9 import android.content.Intent; 10 import android.content.pm.ApplicationInfo; 11 import android.content.pm.PackageInfo; 12 import android.content.pm.PackageManager; 13 import android.content.pm.PackageManager.NameNotFoundException; 14 import android.content.pm.Signature; 15 import android.content.pm.UserInfo; 16 import android.content.res.ColorStateList; 17 import android.content.res.Resources; 18 import android.content.res.TypedArray; 19 import android.graphics.Bitmap; 20 import android.graphics.Canvas; 21 import android.graphics.Color; 22 import android.graphics.ColorFilter; 23 import android.graphics.ColorMatrix; 24 import android.graphics.ColorMatrixColorFilter; 25 import android.graphics.drawable.Drawable; 26 import android.location.LocationManager; 27 import android.media.AudioManager; 28 import android.net.NetworkCapabilities; 29 import android.net.TetheringManager; 30 import android.net.vcn.VcnTransportInfo; 31 import android.net.wifi.WifiInfo; 32 import android.os.BatteryManager; 33 import android.os.Build; 34 import android.os.SystemProperties; 35 import android.os.UserHandle; 36 import android.os.UserManager; 37 import android.print.PrintManager; 38 import android.provider.Settings; 39 import android.telephony.AccessNetworkConstants; 40 import android.telephony.NetworkRegistrationInfo; 41 import android.telephony.ServiceState; 42 import android.telephony.TelephonyManager; 43 44 import androidx.annotation.NonNull; 45 import androidx.annotation.RequiresApi; 46 import androidx.core.graphics.drawable.RoundedBitmapDrawable; 47 import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory; 48 49 import com.android.internal.annotations.VisibleForTesting; 50 import com.android.internal.util.UserIcons; 51 import com.android.launcher3.icons.BaseIconFactory.IconOptions; 52 import com.android.launcher3.icons.IconFactory; 53 import com.android.settingslib.drawable.UserIconDrawable; 54 import com.android.settingslib.fuelgauge.BatteryStatus; 55 import com.android.settingslib.utils.BuildCompatUtils; 56 57 import java.text.NumberFormat; 58 59 public class Utils { 60 61 @VisibleForTesting 62 static final String STORAGE_MANAGER_ENABLED_PROPERTY = 63 "ro.storage_manager.enabled"; 64 65 private static Signature[] sSystemSignature; 66 private static String sPermissionControllerPackageName; 67 private static String sServicesSystemSharedLibPackageName; 68 private static String sSharedSystemSharedLibPackageName; 69 70 static final int[] WIFI_PIE = { 71 com.android.internal.R.drawable.ic_wifi_signal_0, 72 com.android.internal.R.drawable.ic_wifi_signal_1, 73 com.android.internal.R.drawable.ic_wifi_signal_2, 74 com.android.internal.R.drawable.ic_wifi_signal_3, 75 com.android.internal.R.drawable.ic_wifi_signal_4 76 }; 77 78 static final int[] SHOW_X_WIFI_PIE = { 79 R.drawable.ic_show_x_wifi_signal_0, 80 R.drawable.ic_show_x_wifi_signal_1, 81 R.drawable.ic_show_x_wifi_signal_2, 82 R.drawable.ic_show_x_wifi_signal_3, 83 R.drawable.ic_show_x_wifi_signal_4 84 }; 85 updateLocationEnabled(Context context, boolean enabled, int userId, int source)86 public static void updateLocationEnabled(Context context, boolean enabled, int userId, 87 int source) { 88 Settings.Secure.putIntForUser( 89 context.getContentResolver(), Settings.Secure.LOCATION_CHANGER, source, 90 userId); 91 92 LocationManager locationManager = context.getSystemService(LocationManager.class); 93 locationManager.setLocationEnabledForUser(enabled, UserHandle.of(userId)); 94 } 95 96 /** 97 * Return string resource that best describes combination of tethering 98 * options available on this device. 99 */ getTetheringLabel(TetheringManager tm)100 public static int getTetheringLabel(TetheringManager tm) { 101 String[] usbRegexs = tm.getTetherableUsbRegexs(); 102 String[] wifiRegexs = tm.getTetherableWifiRegexs(); 103 String[] bluetoothRegexs = tm.getTetherableBluetoothRegexs(); 104 105 boolean usbAvailable = usbRegexs.length != 0; 106 boolean wifiAvailable = wifiRegexs.length != 0; 107 boolean bluetoothAvailable = bluetoothRegexs.length != 0; 108 109 if (wifiAvailable && usbAvailable && bluetoothAvailable) { 110 return R.string.tether_settings_title_all; 111 } else if (wifiAvailable && usbAvailable) { 112 return R.string.tether_settings_title_all; 113 } else if (wifiAvailable && bluetoothAvailable) { 114 return R.string.tether_settings_title_all; 115 } else if (wifiAvailable) { 116 return R.string.tether_settings_title_wifi; 117 } else if (usbAvailable && bluetoothAvailable) { 118 return R.string.tether_settings_title_usb_bluetooth; 119 } else if (usbAvailable) { 120 return R.string.tether_settings_title_usb; 121 } else { 122 return R.string.tether_settings_title_bluetooth; 123 } 124 } 125 126 /** 127 * Returns a label for the user, in the form of "User: user name" or "Work profile". 128 */ getUserLabel(Context context, UserInfo info)129 public static String getUserLabel(Context context, UserInfo info) { 130 String name = info != null ? info.name : null; 131 if (info.isManagedProfile()) { 132 // We use predefined values for managed profiles 133 return BuildCompatUtils.isAtLeastT() 134 ? getUpdatableManagedUserTitle(context) 135 : context.getString(R.string.managed_user_title); 136 } else if (info.isGuest()) { 137 name = context.getString(com.android.internal.R.string.guest_name); 138 } 139 if (name == null && info != null) { 140 name = Integer.toString(info.id); 141 } else if (info == null) { 142 name = context.getString(R.string.unknown); 143 } 144 return context.getResources().getString(R.string.running_process_item_user_label, name); 145 } 146 147 @RequiresApi(Build.VERSION_CODES.TIRAMISU) getUpdatableManagedUserTitle(Context context)148 private static String getUpdatableManagedUserTitle(Context context) { 149 return context.getSystemService(DevicePolicyManager.class).getResources().getString( 150 WORK_PROFILE_USER_LABEL, 151 () -> context.getString(R.string.managed_user_title)); 152 } 153 154 /** 155 * Returns a circular icon for a user. 156 */ getUserIcon(Context context, UserManager um, UserInfo user)157 public static Drawable getUserIcon(Context context, UserManager um, UserInfo user) { 158 final int iconSize = UserIconDrawable.getDefaultSize(context); 159 if (user.isManagedProfile()) { 160 Drawable drawable = UserIconDrawable.getManagedUserDrawable(context); 161 drawable.setBounds(0, 0, iconSize, iconSize); 162 return drawable; 163 } 164 if (user.iconPath != null) { 165 Bitmap icon = um.getUserIcon(user.id); 166 if (icon != null) { 167 return new UserIconDrawable(iconSize).setIcon(icon).bake(); 168 } 169 } 170 return new UserIconDrawable(iconSize).setIconDrawable( 171 UserIcons.getDefaultUserIcon(context.getResources(), user.id, /* light= */ false)) 172 .bake(); 173 } 174 175 /** Formats a double from 0.0..100.0 with an option to round **/ formatPercentage(double percentage, boolean round)176 public static String formatPercentage(double percentage, boolean round) { 177 final int localPercentage = round ? Math.round((float) percentage) : (int) percentage; 178 return formatPercentage(localPercentage); 179 } 180 181 /** Formats the ratio of amount/total as a percentage. */ formatPercentage(long amount, long total)182 public static String formatPercentage(long amount, long total) { 183 return formatPercentage(((double) amount) / total); 184 } 185 186 /** Formats an integer from 0..100 as a percentage. */ formatPercentage(int percentage)187 public static String formatPercentage(int percentage) { 188 return formatPercentage(((double) percentage) / 100.0); 189 } 190 191 /** Formats a double from 0.0..1.0 as a percentage. */ formatPercentage(double percentage)192 public static String formatPercentage(double percentage) { 193 return NumberFormat.getPercentInstance().format(percentage); 194 } 195 getBatteryLevel(Intent batteryChangedIntent)196 public static int getBatteryLevel(Intent batteryChangedIntent) { 197 int level = batteryChangedIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0); 198 int scale = batteryChangedIntent.getIntExtra(BatteryManager.EXTRA_SCALE, 100); 199 return (level * 100) / scale; 200 } 201 202 /** 203 * Get battery status string 204 * 205 * @param context the context 206 * @param batteryChangedIntent battery broadcast intent received from {@link 207 * Intent.ACTION_BATTERY_CHANGED}. 208 * @param compactStatus to present compact battery charging string if {@code true} 209 * @return battery status string 210 */ getBatteryStatus(Context context, Intent batteryChangedIntent, boolean compactStatus)211 public static String getBatteryStatus(Context context, Intent batteryChangedIntent, 212 boolean compactStatus) { 213 final int status = batteryChangedIntent.getIntExtra(BatteryManager.EXTRA_STATUS, 214 BatteryManager.BATTERY_STATUS_UNKNOWN); 215 final Resources res = context.getResources(); 216 217 String statusString = res.getString(R.string.battery_info_status_unknown); 218 final BatteryStatus batteryStatus = new BatteryStatus(batteryChangedIntent); 219 220 if (batteryStatus.isCharged()) { 221 statusString = res.getString(compactStatus 222 ? R.string.battery_info_status_full_charged 223 : R.string.battery_info_status_full); 224 } else { 225 if (status == BatteryManager.BATTERY_STATUS_CHARGING) { 226 if (compactStatus) { 227 statusString = res.getString(R.string.battery_info_status_charging); 228 } else if (batteryStatus.isPluggedInWired()) { 229 switch (batteryStatus.getChargingSpeed(context)) { 230 case BatteryStatus.CHARGING_FAST: 231 statusString = res.getString( 232 R.string.battery_info_status_charging_fast); 233 break; 234 case BatteryStatus.CHARGING_SLOWLY: 235 statusString = res.getString( 236 R.string.battery_info_status_charging_slow); 237 break; 238 default: 239 statusString = res.getString(R.string.battery_info_status_charging); 240 break; 241 } 242 } else if (batteryStatus.isPluggedInDock()) { 243 statusString = res.getString(R.string.battery_info_status_charging_dock); 244 } else { 245 statusString = res.getString(R.string.battery_info_status_charging_wireless); 246 } 247 } else if (status == BatteryManager.BATTERY_STATUS_DISCHARGING) { 248 statusString = res.getString(R.string.battery_info_status_discharging); 249 } else if (status == BatteryManager.BATTERY_STATUS_NOT_CHARGING) { 250 statusString = res.getString(R.string.battery_info_status_not_charging); 251 } 252 } 253 254 return statusString; 255 } 256 getColorAccent(Context context)257 public static ColorStateList getColorAccent(Context context) { 258 return getColorAttr(context, android.R.attr.colorAccent); 259 } 260 getColorError(Context context)261 public static ColorStateList getColorError(Context context) { 262 return getColorAttr(context, android.R.attr.colorError); 263 } 264 265 @ColorInt getColorAccentDefaultColor(Context context)266 public static int getColorAccentDefaultColor(Context context) { 267 return getColorAttrDefaultColor(context, android.R.attr.colorAccent); 268 } 269 270 @ColorInt getColorErrorDefaultColor(Context context)271 public static int getColorErrorDefaultColor(Context context) { 272 return getColorAttrDefaultColor(context, android.R.attr.colorError); 273 } 274 275 @ColorInt getColorStateListDefaultColor(Context context, int resId)276 public static int getColorStateListDefaultColor(Context context, int resId) { 277 final ColorStateList list = 278 context.getResources().getColorStateList(resId, context.getTheme()); 279 return list.getDefaultColor(); 280 } 281 282 /** 283 * This method computes disabled color from normal color 284 * 285 * @param context the context 286 * @param inputColor normal color. 287 * @return disabled color. 288 */ 289 @ColorInt getDisabled(Context context, int inputColor)290 public static int getDisabled(Context context, int inputColor) { 291 return applyAlphaAttr(context, android.R.attr.disabledAlpha, inputColor); 292 } 293 294 @ColorInt applyAlphaAttr(Context context, int attr, int inputColor)295 public static int applyAlphaAttr(Context context, int attr, int inputColor) { 296 TypedArray ta = context.obtainStyledAttributes(new int[]{attr}); 297 float alpha = ta.getFloat(0, 0); 298 ta.recycle(); 299 return applyAlpha(alpha, inputColor); 300 } 301 302 @ColorInt applyAlpha(float alpha, int inputColor)303 public static int applyAlpha(float alpha, int inputColor) { 304 alpha *= Color.alpha(inputColor); 305 return Color.argb((int) (alpha), Color.red(inputColor), Color.green(inputColor), 306 Color.blue(inputColor)); 307 } 308 309 @ColorInt getColorAttrDefaultColor(Context context, int attr)310 public static int getColorAttrDefaultColor(Context context, int attr) { 311 return getColorAttrDefaultColor(context, attr, 0); 312 } 313 314 /** 315 * Get color styled attribute {@code attr}, default to {@code defValue} if not found. 316 */ 317 @ColorInt getColorAttrDefaultColor(Context context, int attr, @ColorInt int defValue)318 public static int getColorAttrDefaultColor(Context context, int attr, @ColorInt int defValue) { 319 TypedArray ta = context.obtainStyledAttributes(new int[]{attr}); 320 @ColorInt int colorAccent = ta.getColor(0, defValue); 321 ta.recycle(); 322 return colorAccent; 323 } 324 getColorAttr(Context context, int attr)325 public static ColorStateList getColorAttr(Context context, int attr) { 326 TypedArray ta = context.obtainStyledAttributes(new int[]{attr}); 327 ColorStateList stateList = null; 328 try { 329 stateList = ta.getColorStateList(0); 330 } finally { 331 ta.recycle(); 332 } 333 return stateList; 334 } 335 getThemeAttr(Context context, int attr)336 public static int getThemeAttr(Context context, int attr) { 337 return getThemeAttr(context, attr, 0); 338 } 339 getThemeAttr(Context context, int attr, int defaultValue)340 public static int getThemeAttr(Context context, int attr, int defaultValue) { 341 TypedArray ta = context.obtainStyledAttributes(new int[]{attr}); 342 int theme = ta.getResourceId(0, defaultValue); 343 ta.recycle(); 344 return theme; 345 } 346 getDrawable(Context context, int attr)347 public static Drawable getDrawable(Context context, int attr) { 348 TypedArray ta = context.obtainStyledAttributes(new int[]{attr}); 349 Drawable drawable = ta.getDrawable(0); 350 ta.recycle(); 351 return drawable; 352 } 353 354 /** 355 * Create a color matrix suitable for a ColorMatrixColorFilter that modifies only the color but 356 * preserves the alpha for a given drawable 357 * @param color 358 * @return a color matrix that uses the source alpha and given color 359 */ getAlphaInvariantColorMatrixForColor(@olorInt int color)360 public static ColorMatrix getAlphaInvariantColorMatrixForColor(@ColorInt int color) { 361 int r = Color.red(color); 362 int g = Color.green(color); 363 int b = Color.blue(color); 364 365 ColorMatrix cm = new ColorMatrix(new float[] { 366 0, 0, 0, 0, r, 367 0, 0, 0, 0, g, 368 0, 0, 0, 0, b, 369 0, 0, 0, 1, 0 }); 370 371 return cm; 372 } 373 374 /** 375 * Create a ColorMatrixColorFilter to tint a drawable but retain its alpha characteristics 376 * 377 * @return a ColorMatrixColorFilter which changes the color of the output but is invariant on 378 * the source alpha 379 */ getAlphaInvariantColorFilterForColor(@olorInt int color)380 public static ColorFilter getAlphaInvariantColorFilterForColor(@ColorInt int color) { 381 return new ColorMatrixColorFilter(getAlphaInvariantColorMatrixForColor(color)); 382 } 383 384 /** 385 * Determine whether a package is a "system package", in which case certain things (like 386 * disabling notifications or disabling the package altogether) should be disallowed. 387 */ isSystemPackage(Resources resources, PackageManager pm, PackageInfo pkg)388 public static boolean isSystemPackage(Resources resources, PackageManager pm, PackageInfo pkg) { 389 if (sSystemSignature == null) { 390 sSystemSignature = new Signature[]{getSystemSignature(pm)}; 391 } 392 if (sPermissionControllerPackageName == null) { 393 sPermissionControllerPackageName = pm.getPermissionControllerPackageName(); 394 } 395 if (sServicesSystemSharedLibPackageName == null) { 396 sServicesSystemSharedLibPackageName = pm.getServicesSystemSharedLibraryPackageName(); 397 } 398 if (sSharedSystemSharedLibPackageName == null) { 399 sSharedSystemSharedLibPackageName = pm.getSharedSystemSharedLibraryPackageName(); 400 } 401 return (sSystemSignature[0] != null 402 && sSystemSignature[0].equals(getFirstSignature(pkg))) 403 || pkg.packageName.equals(sPermissionControllerPackageName) 404 || pkg.packageName.equals(sServicesSystemSharedLibPackageName) 405 || pkg.packageName.equals(sSharedSystemSharedLibPackageName) 406 || pkg.packageName.equals(PrintManager.PRINT_SPOOLER_PACKAGE_NAME) 407 || isDeviceProvisioningPackage(resources, pkg.packageName); 408 } 409 getFirstSignature(PackageInfo pkg)410 private static Signature getFirstSignature(PackageInfo pkg) { 411 if (pkg != null && pkg.signatures != null && pkg.signatures.length > 0) { 412 return pkg.signatures[0]; 413 } 414 return null; 415 } 416 getSystemSignature(PackageManager pm)417 private static Signature getSystemSignature(PackageManager pm) { 418 try { 419 final PackageInfo sys = pm.getPackageInfo("android", PackageManager.GET_SIGNATURES); 420 return getFirstSignature(sys); 421 } catch (NameNotFoundException e) { 422 } 423 return null; 424 } 425 426 /** 427 * Returns {@code true} if the supplied package is the device provisioning app. Otherwise, 428 * returns {@code false}. 429 */ isDeviceProvisioningPackage(Resources resources, String packageName)430 public static boolean isDeviceProvisioningPackage(Resources resources, String packageName) { 431 String deviceProvisioningPackage = resources.getString( 432 com.android.internal.R.string.config_deviceProvisioningPackage); 433 return deviceProvisioningPackage != null && deviceProvisioningPackage.equals(packageName); 434 } 435 436 /** 437 * Returns the Wifi icon resource for a given RSSI level. 438 * 439 * @param level The number of bars to show (0-4) 440 * @throws IllegalArgumentException if an invalid RSSI level is given. 441 */ getWifiIconResource(int level)442 public static int getWifiIconResource(int level) { 443 return getWifiIconResource(false /* showX */, level); 444 } 445 446 /** 447 * Returns the Wifi icon resource for a given RSSI level. 448 * 449 * @param showX True if a connected Wi-Fi network has the problem which should show Pie+x 450 * signal icon to users. 451 * @param level The number of bars to show (0-4) 452 * @throws IllegalArgumentException if an invalid RSSI level is given. 453 */ getWifiIconResource(boolean showX, int level)454 public static int getWifiIconResource(boolean showX, int level) { 455 if (level < 0 || level >= WIFI_PIE.length) { 456 throw new IllegalArgumentException("No Wifi icon found for level: " + level); 457 } 458 return showX ? SHOW_X_WIFI_PIE[level] : WIFI_PIE[level]; 459 } 460 getDefaultStorageManagerDaysToRetain(Resources resources)461 public static int getDefaultStorageManagerDaysToRetain(Resources resources) { 462 int defaultDays = Settings.Secure.AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN_DEFAULT; 463 try { 464 defaultDays = 465 resources.getInteger( 466 com.android 467 .internal 468 .R 469 .integer 470 .config_storageManagerDaystoRetainDefault); 471 } catch (Resources.NotFoundException e) { 472 // We are likely in a test environment. 473 } 474 return defaultDays; 475 } 476 isWifiOnly(Context context)477 public static boolean isWifiOnly(Context context) { 478 return !context.getSystemService(TelephonyManager.class).isDataCapable(); 479 } 480 481 /** Returns if the automatic storage management feature is turned on or not. **/ isStorageManagerEnabled(Context context)482 public static boolean isStorageManagerEnabled(Context context) { 483 boolean isDefaultOn; 484 try { 485 isDefaultOn = SystemProperties.getBoolean(STORAGE_MANAGER_ENABLED_PROPERTY, false); 486 } catch (Resources.NotFoundException e) { 487 isDefaultOn = false; 488 } 489 return Settings.Secure.getInt(context.getContentResolver(), 490 Settings.Secure.AUTOMATIC_STORAGE_MANAGER_ENABLED, 491 isDefaultOn ? 1 : 0) 492 != 0; 493 } 494 495 /** 496 * get that {@link AudioManager#getMode()} is in ringing/call/communication(VoIP) status. 497 */ isAudioModeOngoingCall(Context context)498 public static boolean isAudioModeOngoingCall(Context context) { 499 final AudioManager audioManager = context.getSystemService(AudioManager.class); 500 final int audioMode = audioManager.getMode(); 501 return audioMode == AudioManager.MODE_RINGTONE 502 || audioMode == AudioManager.MODE_IN_CALL 503 || audioMode == AudioManager.MODE_IN_COMMUNICATION; 504 } 505 506 /** 507 * Return the service state is in-service or not. 508 * To make behavior consistent with SystemUI and Settings/AboutPhone/SIM status UI 509 * 510 * @param serviceState Service state. {@link ServiceState} 511 */ isInService(ServiceState serviceState)512 public static boolean isInService(ServiceState serviceState) { 513 if (serviceState == null) { 514 return false; 515 } 516 int state = getCombinedServiceState(serviceState); 517 if (state == ServiceState.STATE_POWER_OFF 518 || state == ServiceState.STATE_OUT_OF_SERVICE 519 || state == ServiceState.STATE_EMERGENCY_ONLY) { 520 return false; 521 } else { 522 return true; 523 } 524 } 525 526 /** 527 * Return the combined service state. 528 * To make behavior consistent with SystemUI and Settings/AboutPhone/SIM status UI 529 * 530 * @param serviceState Service state. {@link ServiceState} 531 */ getCombinedServiceState(ServiceState serviceState)532 public static int getCombinedServiceState(ServiceState serviceState) { 533 if (serviceState == null) { 534 return ServiceState.STATE_OUT_OF_SERVICE; 535 } 536 537 // Consider the device to be in service if either voice or data 538 // service is available. Some SIM cards are marketed as data-only 539 // and do not support voice service, and on these SIM cards, we 540 // want to show signal bars for data service as well as the "no 541 // service" or "emergency calls only" text that indicates that voice 542 // is not available. Note that we ignore the IWLAN service state 543 // because that state indicates the use of VoWIFI and not cell service 544 final int state = serviceState.getState(); 545 final int dataState = serviceState.getDataRegistrationState(); 546 547 if (state == ServiceState.STATE_OUT_OF_SERVICE 548 || state == ServiceState.STATE_EMERGENCY_ONLY) { 549 if (dataState == ServiceState.STATE_IN_SERVICE && isNotInIwlan(serviceState)) { 550 return ServiceState.STATE_IN_SERVICE; 551 } 552 } 553 return state; 554 } 555 556 /** Get the corresponding adaptive icon drawable. */ getBadgedIcon(Context context, Drawable icon, UserHandle user)557 public static Drawable getBadgedIcon(Context context, Drawable icon, UserHandle user) { 558 try (IconFactory iconFactory = IconFactory.obtain(context)) { 559 return iconFactory 560 .createBadgedIconBitmap(icon, new IconOptions().setUser(user)) 561 .newIcon(context); 562 } 563 } 564 565 /** Get the {@link Drawable} that represents the app icon */ getBadgedIcon(Context context, ApplicationInfo appInfo)566 public static Drawable getBadgedIcon(Context context, ApplicationInfo appInfo) { 567 return getBadgedIcon(context, appInfo.loadUnbadgedIcon(context.getPackageManager()), 568 UserHandle.getUserHandleForUid(appInfo.uid)); 569 } 570 isNotInIwlan(ServiceState serviceState)571 private static boolean isNotInIwlan(ServiceState serviceState) { 572 final NetworkRegistrationInfo networkRegWlan = serviceState.getNetworkRegistrationInfo( 573 NetworkRegistrationInfo.DOMAIN_PS, 574 AccessNetworkConstants.TRANSPORT_TYPE_WLAN); 575 if (networkRegWlan == null) { 576 return true; 577 } 578 579 final boolean isInIwlan = (networkRegWlan.getRegistrationState() 580 == NetworkRegistrationInfo.REGISTRATION_STATE_HOME) 581 || (networkRegWlan.getRegistrationState() 582 == NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING); 583 return !isInIwlan; 584 } 585 586 /** 587 * Returns a bitmap with rounded corner. 588 * 589 * @param context application context. 590 * @param source bitmap to apply round corner. 591 * @param cornerRadius corner radius value. 592 */ convertCornerRadiusBitmap(@onNull Context context, @NonNull Bitmap source, @NonNull float cornerRadius)593 public static Bitmap convertCornerRadiusBitmap(@NonNull Context context, 594 @NonNull Bitmap source, @NonNull float cornerRadius) { 595 final Bitmap roundedBitmap = Bitmap.createBitmap(source.getWidth(), source.getHeight(), 596 Bitmap.Config.ARGB_8888); 597 final RoundedBitmapDrawable drawable = 598 RoundedBitmapDrawableFactory.create(context.getResources(), source); 599 drawable.setAntiAlias(true); 600 drawable.setCornerRadius(cornerRadius); 601 final Canvas canvas = new Canvas(roundedBitmap); 602 drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); 603 drawable.draw(canvas); 604 return roundedBitmap; 605 } 606 607 /** 608 * Returns the WifiInfo for the underlying WiFi network of the VCN network, returns null if the 609 * input NetworkCapabilities is not for a VCN network with underlying WiFi network. 610 * 611 * TODO(b/238425913): Move this method to be inside systemui not settingslib once we've migrated 612 * off of {@link WifiStatusTracker} and {@link NetworkControllerImpl}. 613 * 614 * @param networkCapabilities NetworkCapabilities of the network. 615 */ 616 @Nullable tryGetWifiInfoForVcn(NetworkCapabilities networkCapabilities)617 public static WifiInfo tryGetWifiInfoForVcn(NetworkCapabilities networkCapabilities) { 618 if (networkCapabilities.getTransportInfo() == null 619 || !(networkCapabilities.getTransportInfo() instanceof VcnTransportInfo)) { 620 return null; 621 } 622 VcnTransportInfo vcnTransportInfo = 623 (VcnTransportInfo) networkCapabilities.getTransportInfo(); 624 return vcnTransportInfo.getWifiInfo(); 625 } 626 } 627