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