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.BitmapFactory; 16 import android.graphics.Color; 17 import android.graphics.PorterDuff; 18 import android.graphics.drawable.Drawable; 19 import android.graphics.drawable.LayerDrawable; 20 import android.net.ConnectivityManager; 21 import android.net.NetworkBadging; 22 import android.os.BatteryManager; 23 import android.os.UserManager; 24 import android.print.PrintManager; 25 import android.provider.Settings; 26 import android.view.View; 27 28 import com.android.internal.util.UserIcons; 29 import com.android.settingslib.drawable.UserIconDrawable; 30 31 import java.text.NumberFormat; 32 33 public class Utils { 34 private static Signature[] sSystemSignature; 35 private static String sPermissionControllerPackageName; 36 private static String sServicesSystemSharedLibPackageName; 37 private static String sSharedSystemSharedLibPackageName; 38 39 static final int[] WIFI_PIE_FOR_BADGING = { 40 com.android.internal.R.drawable.ic_signal_wifi_badged_0_bars, 41 com.android.internal.R.drawable.ic_signal_wifi_badged_1_bar, 42 com.android.internal.R.drawable.ic_signal_wifi_badged_2_bars, 43 com.android.internal.R.drawable.ic_signal_wifi_badged_3_bars, 44 com.android.internal.R.drawable.ic_signal_wifi_badged_4_bars 45 }; 46 47 /** 48 * Return string resource that best describes combination of tethering 49 * options available on this device. 50 */ 51 public static int getTetheringLabel(ConnectivityManager cm) { 52 String[] usbRegexs = cm.getTetherableUsbRegexs(); 53 String[] wifiRegexs = cm.getTetherableWifiRegexs(); 54 String[] bluetoothRegexs = cm.getTetherableBluetoothRegexs(); 55 56 boolean usbAvailable = usbRegexs.length != 0; 57 boolean wifiAvailable = wifiRegexs.length != 0; 58 boolean bluetoothAvailable = bluetoothRegexs.length != 0; 59 60 if (wifiAvailable && usbAvailable && bluetoothAvailable) { 61 return R.string.tether_settings_title_all; 62 } else if (wifiAvailable && usbAvailable) { 63 return R.string.tether_settings_title_all; 64 } else if (wifiAvailable && bluetoothAvailable) { 65 return R.string.tether_settings_title_all; 66 } else if (wifiAvailable) { 67 return R.string.tether_settings_title_wifi; 68 } else if (usbAvailable && bluetoothAvailable) { 69 return R.string.tether_settings_title_usb_bluetooth; 70 } else if (usbAvailable) { 71 return R.string.tether_settings_title_usb; 72 } else { 73 return R.string.tether_settings_title_bluetooth; 74 } 75 } 76 77 /** 78 * Returns a label for the user, in the form of "User: user name" or "Work profile". 79 */ 80 public static String getUserLabel(Context context, UserInfo info) { 81 String name = info != null ? info.name : null; 82 if (info.isManagedProfile()) { 83 // We use predefined values for managed profiles 84 return context.getString(R.string.managed_user_title); 85 } else if (info.isGuest()) { 86 name = context.getString(R.string.user_guest); 87 } 88 if (name == null && info != null) { 89 name = Integer.toString(info.id); 90 } else if (info == null) { 91 name = context.getString(R.string.unknown); 92 } 93 return context.getResources().getString(R.string.running_process_item_user_label, name); 94 } 95 96 /** 97 * Returns a circular icon for a user. 98 */ 99 public static Drawable getUserIcon(Context context, UserManager um, UserInfo user) { 100 final int iconSize = UserIconDrawable.getSizeForList(context); 101 if (user.isManagedProfile()) { 102 Drawable drawable = context.getDrawable(com.android.internal.R.drawable.ic_corp_icon); 103 drawable.setBounds(0, 0, iconSize, iconSize); 104 return drawable; 105 } 106 if (user.iconPath != null) { 107 Bitmap icon = um.getUserIcon(user.id); 108 if (icon != null) { 109 return new UserIconDrawable(iconSize).setIcon(icon).bake(); 110 } 111 } 112 return new UserIconDrawable(iconSize).setIconDrawable( 113 UserIcons.getDefaultUserIcon(user.id, /* light= */ false)).bake(); 114 } 115 116 /** Formats a double from 0.0..100.0 with an option to round **/ 117 public static String formatPercentage(double percentage, boolean round) { 118 final int localPercentage = round ? Math.round((float) percentage) : (int) percentage; 119 return formatPercentage(localPercentage); 120 } 121 122 /** Formats the ratio of amount/total as a percentage. */ 123 public static String formatPercentage(long amount, long total) { 124 return formatPercentage(((double) amount) / total); 125 } 126 127 /** Formats an integer from 0..100 as a percentage. */ 128 public static String formatPercentage(int percentage) { 129 return formatPercentage(((double) percentage) / 100.0); 130 } 131 132 /** Formats a double from 0.0..1.0 as a percentage. */ 133 public static String formatPercentage(double percentage) { 134 return NumberFormat.getPercentInstance().format(percentage); 135 } 136 137 public static int getBatteryLevel(Intent batteryChangedIntent) { 138 int level = batteryChangedIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0); 139 int scale = batteryChangedIntent.getIntExtra(BatteryManager.EXTRA_SCALE, 100); 140 return (level * 100) / scale; 141 } 142 143 public static String getBatteryStatus(Resources res, Intent batteryChangedIntent) { 144 int status = batteryChangedIntent.getIntExtra(BatteryManager.EXTRA_STATUS, 145 BatteryManager.BATTERY_STATUS_UNKNOWN); 146 String statusString; 147 if (status == BatteryManager.BATTERY_STATUS_CHARGING) { 148 statusString = res.getString(R.string.battery_info_status_charging); 149 } else if (status == BatteryManager.BATTERY_STATUS_DISCHARGING) { 150 statusString = res.getString(R.string.battery_info_status_discharging); 151 } else if (status == BatteryManager.BATTERY_STATUS_NOT_CHARGING) { 152 statusString = res.getString(R.string.battery_info_status_not_charging); 153 } else if (status == BatteryManager.BATTERY_STATUS_FULL) { 154 statusString = res.getString(R.string.battery_info_status_full); 155 } else { 156 statusString = res.getString(R.string.battery_info_status_unknown); 157 } 158 159 return statusString; 160 } 161 162 @ColorInt 163 public static int getColorAccent(Context context) { 164 return getColorAttr(context, android.R.attr.colorAccent); 165 } 166 167 @ColorInt 168 public static int getColorError(Context context) { 169 return getColorAttr(context, android.R.attr.colorError); 170 } 171 172 @ColorInt 173 public static int getDefaultColor(Context context, int resId) { 174 final ColorStateList list = 175 context.getResources().getColorStateList(resId, context.getTheme()); 176 177 return list.getDefaultColor(); 178 } 179 180 @ColorInt 181 public static int getDisabled(Context context, int inputColor) { 182 return applyAlphaAttr(context, android.R.attr.disabledAlpha, inputColor); 183 } 184 185 @ColorInt 186 public static int applyAlphaAttr(Context context, int attr, int inputColor) { 187 TypedArray ta = context.obtainStyledAttributes(new int[]{attr}); 188 float alpha = ta.getFloat(0, 0); 189 ta.recycle(); 190 return applyAlpha(alpha, inputColor); 191 } 192 193 @ColorInt 194 public static int applyAlpha(float alpha, int inputColor) { 195 alpha *= Color.alpha(inputColor); 196 return Color.argb((int) (alpha), Color.red(inputColor), Color.green(inputColor), 197 Color.blue(inputColor)); 198 } 199 200 @ColorInt 201 public static int getColorAttr(Context context, int attr) { 202 TypedArray ta = context.obtainStyledAttributes(new int[]{attr}); 203 @ColorInt int colorAccent = ta.getColor(0, 0); 204 ta.recycle(); 205 return colorAccent; 206 } 207 208 public static int getThemeAttr(Context context, int attr) { 209 TypedArray ta = context.obtainStyledAttributes(new int[]{attr}); 210 int theme = ta.getResourceId(0, 0); 211 ta.recycle(); 212 return theme; 213 } 214 215 public static Drawable getDrawable(Context context, int attr) { 216 TypedArray ta = context.obtainStyledAttributes(new int[]{attr}); 217 Drawable drawable = ta.getDrawable(0); 218 ta.recycle(); 219 return drawable; 220 } 221 222 /** 223 * Determine whether a package is a "system package", in which case certain things (like 224 * disabling notifications or disabling the package altogether) should be disallowed. 225 */ 226 public static boolean isSystemPackage(Resources resources, PackageManager pm, PackageInfo pkg) { 227 if (sSystemSignature == null) { 228 sSystemSignature = new Signature[]{ getSystemSignature(pm) }; 229 } 230 if (sPermissionControllerPackageName == null) { 231 sPermissionControllerPackageName = pm.getPermissionControllerPackageName(); 232 } 233 if (sServicesSystemSharedLibPackageName == null) { 234 sServicesSystemSharedLibPackageName = pm.getServicesSystemSharedLibraryPackageName(); 235 } 236 if (sSharedSystemSharedLibPackageName == null) { 237 sSharedSystemSharedLibPackageName = pm.getSharedSystemSharedLibraryPackageName(); 238 } 239 return (sSystemSignature[0] != null 240 && sSystemSignature[0].equals(getFirstSignature(pkg))) 241 || pkg.packageName.equals(sPermissionControllerPackageName) 242 || pkg.packageName.equals(sServicesSystemSharedLibPackageName) 243 || pkg.packageName.equals(sSharedSystemSharedLibPackageName) 244 || pkg.packageName.equals(PrintManager.PRINT_SPOOLER_PACKAGE_NAME) 245 || isDeviceProvisioningPackage(resources, pkg.packageName); 246 } 247 248 private static Signature getFirstSignature(PackageInfo pkg) { 249 if (pkg != null && pkg.signatures != null && pkg.signatures.length > 0) { 250 return pkg.signatures[0]; 251 } 252 return null; 253 } 254 255 private static Signature getSystemSignature(PackageManager pm) { 256 try { 257 final PackageInfo sys = pm.getPackageInfo("android", PackageManager.GET_SIGNATURES); 258 return getFirstSignature(sys); 259 } catch (NameNotFoundException e) { 260 } 261 return null; 262 } 263 264 /** 265 * Returns {@code true} if the supplied package is the device provisioning app. Otherwise, 266 * returns {@code false}. 267 */ 268 public static boolean isDeviceProvisioningPackage(Resources resources, String packageName) { 269 String deviceProvisioningPackage = resources.getString( 270 com.android.internal.R.string.config_deviceProvisioningPackage); 271 return deviceProvisioningPackage != null && deviceProvisioningPackage.equals(packageName); 272 } 273 274 /** 275 * Returns a badged Wifi icon drawable. 276 * 277 * <p>The first layer contains the Wifi pie and the second layer contains the badge. Callers 278 * should set the drawable to the appropriate size and tint color. 279 * 280 * @param context The caller's context (must have access to internal resources) 281 * @param level The number of bars to show (0-4) 282 * @param badge The badge enum {@see android.net.ScoredNetwork} 283 * 284 * @throws IllegalArgumentException if an invalid badge enum is given 285 * 286 * @deprecated TODO(sghuman): Finalize the form of this method and then move it to a new 287 * location. 288 */ 289 public static LayerDrawable getBadgedWifiIcon(Context context, int level, int badge) { 290 return new LayerDrawable( 291 new Drawable[] { 292 context.getDrawable(WIFI_PIE_FOR_BADGING[level]), 293 context.getDrawable(getWifiBadgeResource(badge)) 294 }); 295 } 296 297 private static int getWifiBadgeResource(int badge) { 298 switch (badge) { 299 case NetworkBadging.BADGING_NONE: 300 return View.NO_ID; 301 case NetworkBadging.BADGING_SD: 302 return com.android.internal.R.drawable.ic_signal_wifi_badged_sd; 303 case NetworkBadging.BADGING_HD: 304 return com.android.internal.R.drawable.ic_signal_wifi_badged_hd; 305 case NetworkBadging.BADGING_4K: 306 return com.android.internal.R.drawable.ic_signal_wifi_badged_4k; 307 default: 308 throw new IllegalArgumentException( 309 "No badge resource found for badge value: " + badge); 310 } 311 } 312 313 public static int getDefaultStorageManagerDaysToRetain(Resources resources) { 314 int defaultDays = Settings.Secure.AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN_DEFAULT; 315 try { 316 defaultDays = 317 resources.getInteger( 318 com.android 319 .internal 320 .R 321 .integer 322 .config_storageManagerDaystoRetainDefault); 323 } catch (Resources.NotFoundException e) { 324 // We are likely in a test environment. 325 } 326 return defaultDays; 327 } 328 } 329