1 package com.android.settingslib; 2 3 import android.annotation.ColorInt; 4 import android.content.Context; 5 import android.content.Intent; 6 import android.content.pm.PackageInfo; 7 import android.content.pm.PackageManager; 8 import android.content.pm.PackageManager.NameNotFoundException; 9 import android.content.pm.Signature; 10 import android.content.pm.UserInfo; 11 import android.content.res.ColorStateList; 12 import android.content.res.Resources; 13 import android.content.res.TypedArray; 14 import android.graphics.Bitmap; 15 import android.graphics.Color; 16 import android.graphics.drawable.Drawable; 17 import android.location.LocationManager; 18 import android.media.AudioManager; 19 import android.net.ConnectivityManager; 20 import android.os.BatteryManager; 21 import android.os.SystemProperties; 22 import android.os.UserHandle; 23 import android.os.UserManager; 24 import android.print.PrintManager; 25 import android.provider.Settings; 26 27 import com.android.internal.annotations.VisibleForTesting; 28 import com.android.internal.util.UserIcons; 29 import com.android.settingslib.drawable.UserIconDrawable; 30 import com.android.settingslib.wrapper.LocationManagerWrapper; 31 import java.text.NumberFormat; 32 33 public class Utils { 34 35 private static final String CURRENT_MODE_KEY = "CURRENT_MODE"; 36 private static final String NEW_MODE_KEY = "NEW_MODE"; 37 @VisibleForTesting 38 static final String STORAGE_MANAGER_SHOW_OPT_IN_PROPERTY = 39 "ro.storage_manager.show_opt_in"; 40 41 private static Signature[] sSystemSignature; 42 private static String sPermissionControllerPackageName; 43 private static String sServicesSystemSharedLibPackageName; 44 private static String sSharedSystemSharedLibPackageName; 45 46 static final int[] WIFI_PIE = { 47 com.android.internal.R.drawable.ic_wifi_signal_0, 48 com.android.internal.R.drawable.ic_wifi_signal_1, 49 com.android.internal.R.drawable.ic_wifi_signal_2, 50 com.android.internal.R.drawable.ic_wifi_signal_3, 51 com.android.internal.R.drawable.ic_wifi_signal_4 52 }; 53 updateLocationEnabled(Context context, boolean enabled, int userId, int source)54 public static void updateLocationEnabled(Context context, boolean enabled, int userId, 55 int source) { 56 Settings.Secure.putIntForUser( 57 context.getContentResolver(), Settings.Secure.LOCATION_CHANGER, source, 58 userId); 59 Intent intent = new Intent(LocationManager.MODE_CHANGING_ACTION); 60 61 final int oldMode = Settings.Secure.getIntForUser(context.getContentResolver(), 62 Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF, userId); 63 final int newMode = enabled 64 ? Settings.Secure.LOCATION_MODE_HIGH_ACCURACY 65 : Settings.Secure.LOCATION_MODE_OFF; 66 intent.putExtra(CURRENT_MODE_KEY, oldMode); 67 intent.putExtra(NEW_MODE_KEY, newMode); 68 context.sendBroadcastAsUser( 69 intent, UserHandle.of(userId), android.Manifest.permission.WRITE_SECURE_SETTINGS); 70 LocationManager locationManager = 71 (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); 72 LocationManagerWrapper wrapper = new LocationManagerWrapper(locationManager); 73 wrapper.setLocationEnabledForUser(enabled, UserHandle.of(userId)); 74 } 75 updateLocationMode(Context context, int oldMode, int newMode, int userId, int source)76 public static boolean updateLocationMode(Context context, int oldMode, int newMode, int userId, 77 int source) { 78 Settings.Secure.putIntForUser( 79 context.getContentResolver(), Settings.Secure.LOCATION_CHANGER, source, 80 userId); 81 Intent intent = new Intent(LocationManager.MODE_CHANGING_ACTION); 82 intent.putExtra(CURRENT_MODE_KEY, oldMode); 83 intent.putExtra(NEW_MODE_KEY, newMode); 84 context.sendBroadcastAsUser( 85 intent, UserHandle.of(userId), android.Manifest.permission.WRITE_SECURE_SETTINGS); 86 return Settings.Secure.putIntForUser( 87 context.getContentResolver(), Settings.Secure.LOCATION_MODE, newMode, userId); 88 } 89 90 /** 91 * Return string resource that best describes combination of tethering 92 * options available on this device. 93 */ getTetheringLabel(ConnectivityManager cm)94 public static int getTetheringLabel(ConnectivityManager cm) { 95 String[] usbRegexs = cm.getTetherableUsbRegexs(); 96 String[] wifiRegexs = cm.getTetherableWifiRegexs(); 97 String[] bluetoothRegexs = cm.getTetherableBluetoothRegexs(); 98 99 boolean usbAvailable = usbRegexs.length != 0; 100 boolean wifiAvailable = wifiRegexs.length != 0; 101 boolean bluetoothAvailable = bluetoothRegexs.length != 0; 102 103 if (wifiAvailable && usbAvailable && bluetoothAvailable) { 104 return R.string.tether_settings_title_all; 105 } else if (wifiAvailable && usbAvailable) { 106 return R.string.tether_settings_title_all; 107 } else if (wifiAvailable && bluetoothAvailable) { 108 return R.string.tether_settings_title_all; 109 } else if (wifiAvailable) { 110 return R.string.tether_settings_title_wifi; 111 } else if (usbAvailable && bluetoothAvailable) { 112 return R.string.tether_settings_title_usb_bluetooth; 113 } else if (usbAvailable) { 114 return R.string.tether_settings_title_usb; 115 } else { 116 return R.string.tether_settings_title_bluetooth; 117 } 118 } 119 120 /** 121 * Returns a label for the user, in the form of "User: user name" or "Work profile". 122 */ getUserLabel(Context context, UserInfo info)123 public static String getUserLabel(Context context, UserInfo info) { 124 String name = info != null ? info.name : null; 125 if (info.isManagedProfile()) { 126 // We use predefined values for managed profiles 127 return context.getString(R.string.managed_user_title); 128 } else if (info.isGuest()) { 129 name = context.getString(R.string.user_guest); 130 } 131 if (name == null && info != null) { 132 name = Integer.toString(info.id); 133 } else if (info == null) { 134 name = context.getString(R.string.unknown); 135 } 136 return context.getResources().getString(R.string.running_process_item_user_label, name); 137 } 138 139 /** 140 * Returns a circular icon for a user. 141 */ getUserIcon(Context context, UserManager um, UserInfo user)142 public static Drawable getUserIcon(Context context, UserManager um, UserInfo user) { 143 final int iconSize = UserIconDrawable.getSizeForList(context); 144 if (user.isManagedProfile()) { 145 Drawable drawable = UserIconDrawable.getManagedUserDrawable(context); 146 drawable.setBounds(0, 0, iconSize, iconSize); 147 return drawable; 148 } 149 if (user.iconPath != null) { 150 Bitmap icon = um.getUserIcon(user.id); 151 if (icon != null) { 152 return new UserIconDrawable(iconSize).setIcon(icon).bake(); 153 } 154 } 155 return new UserIconDrawable(iconSize).setIconDrawable( 156 UserIcons.getDefaultUserIcon(context.getResources(), user.id, /* light= */ false)) 157 .bake(); 158 } 159 160 /** Formats a double from 0.0..100.0 with an option to round **/ formatPercentage(double percentage, boolean round)161 public static String formatPercentage(double percentage, boolean round) { 162 final int localPercentage = round ? Math.round((float) percentage) : (int) percentage; 163 return formatPercentage(localPercentage); 164 } 165 166 /** Formats the ratio of amount/total as a percentage. */ formatPercentage(long amount, long total)167 public static String formatPercentage(long amount, long total) { 168 return formatPercentage(((double) amount) / total); 169 } 170 171 /** Formats an integer from 0..100 as a percentage. */ formatPercentage(int percentage)172 public static String formatPercentage(int percentage) { 173 return formatPercentage(((double) percentage) / 100.0); 174 } 175 176 /** Formats a double from 0.0..1.0 as a percentage. */ formatPercentage(double percentage)177 public static String formatPercentage(double percentage) { 178 return NumberFormat.getPercentInstance().format(percentage); 179 } 180 getBatteryLevel(Intent batteryChangedIntent)181 public static int getBatteryLevel(Intent batteryChangedIntent) { 182 int level = batteryChangedIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0); 183 int scale = batteryChangedIntent.getIntExtra(BatteryManager.EXTRA_SCALE, 100); 184 return (level * 100) / scale; 185 } 186 getBatteryStatus(Resources res, Intent batteryChangedIntent)187 public static String getBatteryStatus(Resources res, Intent batteryChangedIntent) { 188 int status = batteryChangedIntent.getIntExtra(BatteryManager.EXTRA_STATUS, 189 BatteryManager.BATTERY_STATUS_UNKNOWN); 190 String statusString; 191 if (status == BatteryManager.BATTERY_STATUS_CHARGING) { 192 statusString = res.getString(R.string.battery_info_status_charging); 193 } else if (status == BatteryManager.BATTERY_STATUS_DISCHARGING) { 194 statusString = res.getString(R.string.battery_info_status_discharging); 195 } else if (status == BatteryManager.BATTERY_STATUS_NOT_CHARGING) { 196 statusString = res.getString(R.string.battery_info_status_not_charging); 197 } else if (status == BatteryManager.BATTERY_STATUS_FULL) { 198 statusString = res.getString(R.string.battery_info_status_full); 199 } else { 200 statusString = res.getString(R.string.battery_info_status_unknown); 201 } 202 203 return statusString; 204 } 205 206 @ColorInt getColorAccent(Context context)207 public static int getColorAccent(Context context) { 208 return getColorAttr(context, android.R.attr.colorAccent); 209 } 210 211 @ColorInt getColorError(Context context)212 public static int getColorError(Context context) { 213 return getColorAttr(context, android.R.attr.colorError); 214 } 215 216 @ColorInt getDefaultColor(Context context, int resId)217 public static int getDefaultColor(Context context, int resId) { 218 final ColorStateList list = 219 context.getResources().getColorStateList(resId, context.getTheme()); 220 221 return list.getDefaultColor(); 222 } 223 224 @ColorInt getDisabled(Context context, int inputColor)225 public static int getDisabled(Context context, int inputColor) { 226 return applyAlphaAttr(context, android.R.attr.disabledAlpha, inputColor); 227 } 228 229 @ColorInt applyAlphaAttr(Context context, int attr, int inputColor)230 public static int applyAlphaAttr(Context context, int attr, int inputColor) { 231 TypedArray ta = context.obtainStyledAttributes(new int[]{attr}); 232 float alpha = ta.getFloat(0, 0); 233 ta.recycle(); 234 return applyAlpha(alpha, inputColor); 235 } 236 237 @ColorInt applyAlpha(float alpha, int inputColor)238 public static int applyAlpha(float alpha, int inputColor) { 239 alpha *= Color.alpha(inputColor); 240 return Color.argb((int) (alpha), Color.red(inputColor), Color.green(inputColor), 241 Color.blue(inputColor)); 242 } 243 244 @ColorInt getColorAttr(Context context, int attr)245 public static int getColorAttr(Context context, int attr) { 246 TypedArray ta = context.obtainStyledAttributes(new int[]{attr}); 247 @ColorInt int colorAccent = ta.getColor(0, 0); 248 ta.recycle(); 249 return colorAccent; 250 } 251 getThemeAttr(Context context, int attr)252 public static int getThemeAttr(Context context, int attr) { 253 TypedArray ta = context.obtainStyledAttributes(new int[]{attr}); 254 int theme = ta.getResourceId(0, 0); 255 ta.recycle(); 256 return theme; 257 } 258 getDrawable(Context context, int attr)259 public static Drawable getDrawable(Context context, int attr) { 260 TypedArray ta = context.obtainStyledAttributes(new int[]{attr}); 261 Drawable drawable = ta.getDrawable(0); 262 ta.recycle(); 263 return drawable; 264 } 265 266 /** 267 * Determine whether a package is a "system package", in which case certain things (like 268 * disabling notifications or disabling the package altogether) should be disallowed. 269 */ isSystemPackage(Resources resources, PackageManager pm, PackageInfo pkg)270 public static boolean isSystemPackage(Resources resources, PackageManager pm, PackageInfo pkg) { 271 if (sSystemSignature == null) { 272 sSystemSignature = new Signature[]{getSystemSignature(pm)}; 273 } 274 if (sPermissionControllerPackageName == null) { 275 sPermissionControllerPackageName = pm.getPermissionControllerPackageName(); 276 } 277 if (sServicesSystemSharedLibPackageName == null) { 278 sServicesSystemSharedLibPackageName = pm.getServicesSystemSharedLibraryPackageName(); 279 } 280 if (sSharedSystemSharedLibPackageName == null) { 281 sSharedSystemSharedLibPackageName = pm.getSharedSystemSharedLibraryPackageName(); 282 } 283 return (sSystemSignature[0] != null 284 && sSystemSignature[0].equals(getFirstSignature(pkg))) 285 || pkg.packageName.equals(sPermissionControllerPackageName) 286 || pkg.packageName.equals(sServicesSystemSharedLibPackageName) 287 || pkg.packageName.equals(sSharedSystemSharedLibPackageName) 288 || pkg.packageName.equals(PrintManager.PRINT_SPOOLER_PACKAGE_NAME) 289 || isDeviceProvisioningPackage(resources, pkg.packageName); 290 } 291 getFirstSignature(PackageInfo pkg)292 private static Signature getFirstSignature(PackageInfo pkg) { 293 if (pkg != null && pkg.signatures != null && pkg.signatures.length > 0) { 294 return pkg.signatures[0]; 295 } 296 return null; 297 } 298 getSystemSignature(PackageManager pm)299 private static Signature getSystemSignature(PackageManager pm) { 300 try { 301 final PackageInfo sys = pm.getPackageInfo("android", PackageManager.GET_SIGNATURES); 302 return getFirstSignature(sys); 303 } catch (NameNotFoundException e) { 304 } 305 return null; 306 } 307 308 /** 309 * Returns {@code true} if the supplied package is the device provisioning app. Otherwise, 310 * returns {@code false}. 311 */ isDeviceProvisioningPackage(Resources resources, String packageName)312 public static boolean isDeviceProvisioningPackage(Resources resources, String packageName) { 313 String deviceProvisioningPackage = resources.getString( 314 com.android.internal.R.string.config_deviceProvisioningPackage); 315 return deviceProvisioningPackage != null && deviceProvisioningPackage.equals(packageName); 316 } 317 318 /** 319 * Returns the Wifi icon resource for a given RSSI level. 320 * 321 * @param level The number of bars to show (0-4) 322 * @throws IllegalArgumentException if an invalid RSSI level is given. 323 */ getWifiIconResource(int level)324 public static int getWifiIconResource(int level) { 325 if (level < 0 || level >= WIFI_PIE.length) { 326 throw new IllegalArgumentException("No Wifi icon found for level: " + level); 327 } 328 return WIFI_PIE[level]; 329 } 330 getDefaultStorageManagerDaysToRetain(Resources resources)331 public static int getDefaultStorageManagerDaysToRetain(Resources resources) { 332 int defaultDays = Settings.Secure.AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN_DEFAULT; 333 try { 334 defaultDays = 335 resources.getInteger( 336 com.android 337 .internal 338 .R 339 .integer 340 .config_storageManagerDaystoRetainDefault); 341 } catch (Resources.NotFoundException e) { 342 // We are likely in a test environment. 343 } 344 return defaultDays; 345 } 346 isWifiOnly(Context context)347 public static boolean isWifiOnly(Context context) { 348 return !context.getSystemService(ConnectivityManager.class) 349 .isNetworkSupported(ConnectivityManager.TYPE_MOBILE); 350 } 351 352 /** Returns if the automatic storage management feature is turned on or not. **/ isStorageManagerEnabled(Context context)353 public static boolean isStorageManagerEnabled(Context context) { 354 boolean isDefaultOn; 355 try { 356 // Turn off by default if the opt-in was shown. 357 isDefaultOn = !SystemProperties.getBoolean(STORAGE_MANAGER_SHOW_OPT_IN_PROPERTY, true); 358 } catch (Resources.NotFoundException e) { 359 isDefaultOn = false; 360 } 361 return Settings.Secure.getInt(context.getContentResolver(), 362 Settings.Secure.AUTOMATIC_STORAGE_MANAGER_ENABLED, 363 isDefaultOn ? 1 : 0) 364 != 0; 365 } 366 367 /** 368 * get that {@link AudioManager#getMode()} is in ringing/call/communication(VoIP) status. 369 */ isAudioModeOngoingCall(Context context)370 public static boolean isAudioModeOngoingCall(Context context) { 371 final AudioManager audioManager = context.getSystemService(AudioManager.class); 372 final int audioMode = audioManager.getMode(); 373 return audioMode == AudioManager.MODE_RINGTONE 374 || audioMode == AudioManager.MODE_IN_CALL 375 || audioMode == AudioManager.MODE_IN_COMMUNICATION; 376 } 377 } 378