1 /* 2 * Copyright (C) 2022 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.fuelgauge.batteryusage; 18 19 import android.app.AppGlobals; 20 import android.content.Context; 21 import android.content.pm.ApplicationInfo; 22 import android.content.pm.IPackageManager; 23 import android.content.pm.PackageInfo; 24 import android.content.pm.PackageManager; 25 import android.content.pm.PackageManager.NameNotFoundException; 26 import android.content.pm.UserInfo; 27 import android.graphics.drawable.Drawable; 28 import android.os.BatteryConsumer; 29 import android.os.BatteryConsumer.Dimensions; 30 import android.os.Process; 31 import android.os.RemoteException; 32 import android.os.UidBatteryConsumer; 33 import android.os.UserBatteryConsumer; 34 import android.os.UserHandle; 35 import android.os.UserManager; 36 import android.util.ArrayMap; 37 import android.util.DebugUtils; 38 import android.util.Log; 39 40 import com.android.settings.R; 41 import com.android.settings.fuelgauge.BatteryUtils; 42 import com.android.settingslib.Utils; 43 import com.android.settingslib.utils.StringUtil; 44 45 import java.util.Comparator; 46 import java.util.Locale; 47 48 /** 49 * Wraps the power usage data of a BatterySipper with information about package name and icon image. 50 */ 51 public class BatteryEntry { 52 53 /** The app name and icon in app list. */ 54 public static final class NameAndIcon { 55 public final String mName; 56 public final String mPackageName; 57 public final Drawable mIcon; 58 public final int mIconId; 59 NameAndIcon(String name, Drawable icon, int iconId)60 public NameAndIcon(String name, Drawable icon, int iconId) { 61 this(name, /* packageName= */ null, icon, iconId); 62 } 63 NameAndIcon(String name, String packageName, Drawable icon, int iconId)64 public NameAndIcon(String name, String packageName, Drawable icon, int iconId) { 65 this.mName = name; 66 this.mIcon = icon; 67 this.mIconId = iconId; 68 this.mPackageName = packageName; 69 } 70 } 71 72 private static final String TAG = "BatteryEntry"; 73 private static final String PACKAGE_SYSTEM = "android"; 74 75 static final int BATTERY_USAGE_INDEX_FOREGROUND = 0; 76 static final int BATTERY_USAGE_INDEX_FOREGROUND_SERVICE = 1; 77 static final int BATTERY_USAGE_INDEX_BACKGROUND = 2; 78 static final int BATTERY_USAGE_INDEX_CACHED = 3; 79 80 static final Dimensions[] BATTERY_DIMENSIONS = 81 new Dimensions[] { 82 new Dimensions( 83 BatteryConsumer.POWER_COMPONENT_ANY, 84 BatteryConsumer.PROCESS_STATE_FOREGROUND), 85 new Dimensions( 86 BatteryConsumer.POWER_COMPONENT_ANY, 87 BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE), 88 new Dimensions( 89 BatteryConsumer.POWER_COMPONENT_ANY, 90 BatteryConsumer.PROCESS_STATE_BACKGROUND), 91 new Dimensions( 92 BatteryConsumer.POWER_COMPONENT_ANY, BatteryConsumer.PROCESS_STATE_CACHED), 93 }; 94 95 static final ArrayMap<String, UidToDetail> sUidCache = new ArrayMap<>(); 96 97 static Locale sCurrentLocale = null; 98 99 /** Clears the UID cache. */ clearUidCache()100 public static void clearUidCache() { 101 sUidCache.clear(); 102 } 103 104 public static final Comparator<BatteryEntry> COMPARATOR = 105 (a, b) -> Double.compare(b.getConsumedPower(), a.getConsumedPower()); 106 107 private final Context mContext; 108 private final BatteryConsumer mBatteryConsumer; 109 private final int mUid; 110 private final boolean mIsHidden; 111 @ConvertUtils.ConsumerType private final int mConsumerType; 112 @BatteryConsumer.PowerComponent private final int mPowerComponentId; 113 private long mUsageDurationMs; 114 private long mTimeInForegroundMs; 115 private long mTimeInForegroundServiceMs; 116 private long mTimeInBackgroundMs; 117 118 public String mName; 119 public Drawable mIcon; 120 public int mIconId; 121 public double mPercent; 122 private String mDefaultPackageName; 123 private double mConsumedPower; 124 private double mConsumedPowerInForeground; 125 private double mConsumedPowerInForegroundService; 126 private double mConsumedPowerInBackground; 127 private double mConsumedPowerInCached; 128 129 static class UidToDetail { 130 String mName; 131 String mPackageName; 132 Drawable mIcon; 133 } 134 BatteryEntry( Context context, UserManager um, BatteryConsumer batteryConsumer, boolean isHidden, int uid, String[] packages, String packageName)135 public BatteryEntry( 136 Context context, 137 UserManager um, 138 BatteryConsumer batteryConsumer, 139 boolean isHidden, 140 int uid, 141 String[] packages, 142 String packageName) { 143 this(context, um, batteryConsumer, isHidden, uid, packages, packageName, true); 144 } 145 BatteryEntry( Context context, UserManager um, BatteryConsumer batteryConsumer, boolean isHidden, int uid, String[] packages, String packageName, boolean loadDataInBackground)146 public BatteryEntry( 147 Context context, 148 UserManager um, 149 BatteryConsumer batteryConsumer, 150 boolean isHidden, 151 int uid, 152 String[] packages, 153 String packageName, 154 boolean loadDataInBackground) { 155 mContext = context; 156 mBatteryConsumer = batteryConsumer; 157 mIsHidden = isHidden; 158 mDefaultPackageName = packageName; 159 mPowerComponentId = -1; 160 161 if (batteryConsumer instanceof UidBatteryConsumer) { 162 mUid = uid; 163 mConsumerType = ConvertUtils.CONSUMER_TYPE_UID_BATTERY; 164 mConsumedPower = batteryConsumer.getConsumedPower(); 165 166 UidBatteryConsumer uidBatteryConsumer = (UidBatteryConsumer) batteryConsumer; 167 if (mDefaultPackageName == null) { 168 // Apps should only have one package 169 if (packages != null && packages.length == 1) { 170 mDefaultPackageName = packages[0]; 171 } else { 172 mDefaultPackageName = 173 isSystemUid(uid) 174 ? PACKAGE_SYSTEM 175 : uidBatteryConsumer.getPackageWithHighestDrain(); 176 } 177 } 178 if (mDefaultPackageName != null) { 179 PackageManager pm = context.getPackageManager(); 180 try { 181 ApplicationInfo appInfo = 182 pm.getApplicationInfo(mDefaultPackageName, 0 /* no flags */); 183 mName = pm.getApplicationLabel(appInfo).toString(); 184 } catch (NameNotFoundException e) { 185 Log.d( 186 TAG, 187 "PackageManager failed to retrieve ApplicationInfo for: " 188 + mDefaultPackageName); 189 mName = mDefaultPackageName; 190 } 191 } 192 mTimeInForegroundMs = 193 uidBatteryConsumer.getTimeInProcessStateMs( 194 UidBatteryConsumer.PROCESS_STATE_FOREGROUND); 195 mTimeInForegroundServiceMs = 196 uidBatteryConsumer.getTimeInProcessStateMs( 197 UidBatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE); 198 mTimeInBackgroundMs = 199 uidBatteryConsumer.getTimeInProcessStateMs( 200 UidBatteryConsumer.PROCESS_STATE_BACKGROUND); 201 mConsumedPowerInForeground = 202 safeGetConsumedPower( 203 uidBatteryConsumer, BATTERY_DIMENSIONS[BATTERY_USAGE_INDEX_FOREGROUND]); 204 mConsumedPowerInForegroundService = 205 safeGetConsumedPower( 206 uidBatteryConsumer, 207 BATTERY_DIMENSIONS[BATTERY_USAGE_INDEX_FOREGROUND_SERVICE]); 208 mConsumedPowerInBackground = 209 safeGetConsumedPower( 210 uidBatteryConsumer, BATTERY_DIMENSIONS[BATTERY_USAGE_INDEX_BACKGROUND]); 211 mConsumedPowerInCached = 212 safeGetConsumedPower( 213 uidBatteryConsumer, BATTERY_DIMENSIONS[BATTERY_USAGE_INDEX_CACHED]); 214 } else if (batteryConsumer instanceof UserBatteryConsumer) { 215 mUid = Process.INVALID_UID; 216 mConsumerType = ConvertUtils.CONSUMER_TYPE_USER_BATTERY; 217 mConsumedPower = batteryConsumer.getConsumedPower(); 218 final NameAndIcon nameAndIcon = 219 getNameAndIconFromUserId( 220 context, ((UserBatteryConsumer) batteryConsumer).getUserId()); 221 mIcon = nameAndIcon.mIcon; 222 mName = nameAndIcon.mName; 223 } else { 224 throw new IllegalArgumentException("Unsupported: " + batteryConsumer); 225 } 226 } 227 228 /** Battery entry for a power component of AggregateBatteryConsumer */ BatteryEntry( Context context, int powerComponentId, double devicePowerMah, long usageDurationMs, boolean isHidden)229 public BatteryEntry( 230 Context context, 231 int powerComponentId, 232 double devicePowerMah, 233 long usageDurationMs, 234 boolean isHidden) { 235 mContext = context; 236 mBatteryConsumer = null; 237 mUid = Process.INVALID_UID; 238 mIsHidden = isHidden; 239 mPowerComponentId = powerComponentId; 240 mConsumedPower = devicePowerMah; 241 mUsageDurationMs = usageDurationMs; 242 mConsumerType = ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY; 243 244 final NameAndIcon nameAndIcon = getNameAndIconFromPowerComponent(context, powerComponentId); 245 mIconId = nameAndIcon.mIconId; 246 mName = nameAndIcon.mName; 247 if (mIconId != 0) { 248 mIcon = context.getDrawable(mIconId); 249 } 250 } 251 252 /** Battery entry for a custom power component of AggregateBatteryConsumer */ BatteryEntry( Context context, int powerComponentId, String powerComponentName, double devicePowerMah)253 public BatteryEntry( 254 Context context, 255 int powerComponentId, 256 String powerComponentName, 257 double devicePowerMah) { 258 mContext = context; 259 mBatteryConsumer = null; 260 mUid = Process.INVALID_UID; 261 mIsHidden = false; 262 mPowerComponentId = powerComponentId; 263 264 mIconId = R.drawable.ic_power_system; 265 mIcon = context.getDrawable(mIconId); 266 mName = powerComponentName; 267 mConsumedPower = devicePowerMah; 268 mConsumerType = ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY; 269 } 270 getIcon()271 public Drawable getIcon() { 272 return mIcon; 273 } 274 getLabel()275 public String getLabel() { 276 return mName; 277 } 278 279 @ConvertUtils.ConsumerType getConsumerType()280 public int getConsumerType() { 281 return mConsumerType; 282 } 283 284 @BatteryConsumer.PowerComponent getPowerComponentId()285 public int getPowerComponentId() { 286 return mPowerComponentId; 287 } 288 289 /** Loads the app label and icon image and stores into the cache. */ loadNameAndIcon( Context context, int uid, BatteryEntry batteryEntry, String defaultPackageName, String name, Drawable icon)290 public static NameAndIcon loadNameAndIcon( 291 Context context, 292 int uid, 293 BatteryEntry batteryEntry, 294 String defaultPackageName, 295 String name, 296 Drawable icon) { 297 // Bail out if the current sipper is not an App sipper. 298 if (uid == 0 || uid == Process.INVALID_UID) { 299 return null; 300 } 301 302 final PackageManager pm = context.getPackageManager(); 303 final String[] packages = 304 isSystemUid(uid) ? new String[] {PACKAGE_SYSTEM} : pm.getPackagesForUid(uid); 305 if (packages != null) { 306 final String[] packageLabels = new String[packages.length]; 307 System.arraycopy(packages, 0, packageLabels, 0, packages.length); 308 309 // Convert package names to user-facing labels where possible 310 final IPackageManager ipm = AppGlobals.getPackageManager(); 311 final int userId = UserHandle.getUserId(uid); 312 for (int i = 0; i < packageLabels.length; i++) { 313 try { 314 final ApplicationInfo ai = 315 ipm.getApplicationInfo(packageLabels[i], 0 /* no flags */, userId); 316 if (ai == null) { 317 Log.d( 318 TAG, 319 "Retrieving null app info for package " 320 + packageLabels[i] 321 + ", user " 322 + userId); 323 continue; 324 } 325 final CharSequence label = ai.loadLabel(pm); 326 if (label != null) { 327 packageLabels[i] = label.toString(); 328 } 329 if (ai.icon != 0) { 330 defaultPackageName = packages[i]; 331 icon = ai.loadIcon(pm); 332 break; 333 } 334 } catch (RemoteException e) { 335 Log.d( 336 TAG, 337 "Error while retrieving app info for package " 338 + packageLabels[i] 339 + ", user " 340 + userId, 341 e); 342 } 343 } 344 345 if (packageLabels.length == 1) { 346 name = packageLabels[0]; 347 } else { 348 // Look for an official name for this UID. 349 for (String pkgName : packages) { 350 try { 351 final PackageInfo pi = ipm.getPackageInfo(pkgName, 0, userId); 352 if (pi == null) { 353 Log.d( 354 TAG, 355 "Retrieving null package info for package " 356 + pkgName 357 + ", user " 358 + userId); 359 continue; 360 } 361 if (pi.sharedUserLabel != 0) { 362 final CharSequence nm = 363 pm.getText(pkgName, pi.sharedUserLabel, pi.applicationInfo); 364 if (nm != null) { 365 name = nm.toString(); 366 if (pi.applicationInfo.icon != 0) { 367 defaultPackageName = pkgName; 368 icon = pi.applicationInfo.loadIcon(pm); 369 } 370 break; 371 } 372 } 373 } catch (RemoteException e) { 374 Log.d( 375 TAG, 376 "Error while retrieving package info for package " 377 + pkgName 378 + ", user " 379 + userId, 380 e); 381 } 382 } 383 } 384 } 385 386 final String uidString = Integer.toString(uid); 387 if (icon == null) { 388 icon = pm.getDefaultActivityIcon(); 389 } 390 391 UidToDetail utd = new UidToDetail(); 392 utd.mName = name; 393 utd.mIcon = icon; 394 utd.mPackageName = defaultPackageName; 395 396 sUidCache.put(uidString, utd); 397 return new NameAndIcon(name, defaultPackageName, icon, /* iconId= */ 0); 398 } 399 400 /** Returns a string that uniquely identifies this battery consumer. */ getKey()401 public String getKey() { 402 if (mBatteryConsumer instanceof UidBatteryConsumer) { 403 return Integer.toString(mUid); 404 } else if (mBatteryConsumer instanceof UserBatteryConsumer) { 405 return "U|" + ((UserBatteryConsumer) mBatteryConsumer).getUserId(); 406 } else { 407 return "S|" + mPowerComponentId; 408 } 409 } 410 411 /** Returns true if the entry is hidden from the battery usage summary list. */ isHidden()412 public boolean isHidden() { 413 return mIsHidden; 414 } 415 416 /** Returns true if this entry describes an app (UID). */ isAppEntry()417 public boolean isAppEntry() { 418 return mBatteryConsumer instanceof UidBatteryConsumer; 419 } 420 421 /** Returns true if this entry describes a User. */ isUserEntry()422 public boolean isUserEntry() { 423 if (mBatteryConsumer instanceof UserBatteryConsumer) { 424 return true; 425 } 426 return false; 427 } 428 429 /** 430 * Returns the package name that should be used to represent the UID described by this entry. 431 */ getDefaultPackageName()432 public String getDefaultPackageName() { 433 return mDefaultPackageName; 434 } 435 436 /** Returns the UID of the app described by this entry. */ getUid()437 public int getUid() { 438 return mUid; 439 } 440 441 /** Returns foreground time/ms that is attributed to this entry. */ getTimeInForegroundMs()442 public long getTimeInForegroundMs() { 443 return (mBatteryConsumer instanceof UidBatteryConsumer) 444 ? mTimeInForegroundMs 445 : mUsageDurationMs; 446 } 447 448 /** Returns foreground service time/ms that is attributed to this entry. */ getTimeInForegroundServiceMs()449 public long getTimeInForegroundServiceMs() { 450 return (mBatteryConsumer instanceof UidBatteryConsumer) ? mTimeInForegroundServiceMs : 0; 451 } 452 453 /** Returns background activity time/ms that is attributed to this entry. */ getTimeInBackgroundMs()454 public long getTimeInBackgroundMs() { 455 return (mBatteryConsumer instanceof UidBatteryConsumer) ? mTimeInBackgroundMs : 0; 456 } 457 458 /** Returns total amount of power (in milli-amp-hours) that is attributed to this entry. */ getConsumedPower()459 public double getConsumedPower() { 460 return mConsumedPower; 461 } 462 463 /** 464 * Returns amount of power (in milli-amp-hours) used in foreground that is attributed to this 465 * entry. 466 */ getConsumedPowerInForeground()467 public double getConsumedPowerInForeground() { 468 if (mBatteryConsumer instanceof UidBatteryConsumer) { 469 return mConsumedPowerInForeground; 470 } else { 471 return 0; 472 } 473 } 474 475 /** 476 * Returns amount of power (in milli-amp-hours) used in foreground service that is attributed to 477 * this entry. 478 */ getConsumedPowerInForegroundService()479 public double getConsumedPowerInForegroundService() { 480 if (mBatteryConsumer instanceof UidBatteryConsumer) { 481 return mConsumedPowerInForegroundService; 482 } else { 483 return 0; 484 } 485 } 486 487 /** 488 * Returns amount of power (in milli-amp-hours) used in background that is attributed to this 489 * entry. 490 */ getConsumedPowerInBackground()491 public double getConsumedPowerInBackground() { 492 if (mBatteryConsumer instanceof UidBatteryConsumer) { 493 return mConsumedPowerInBackground; 494 } else { 495 return 0; 496 } 497 } 498 499 /** 500 * Returns amount of power (in milli-amp-hours) used in cached that is attributed to this entry. 501 */ getConsumedPowerInCached()502 public double getConsumedPowerInCached() { 503 if (mBatteryConsumer instanceof UidBatteryConsumer) { 504 return mConsumedPowerInCached; 505 } else { 506 return 0; 507 } 508 } 509 510 /** 511 * Adds the consumed power of the supplied BatteryConsumer to this entry. Also uses its package 512 * with highest drain, if necessary. 513 */ add(BatteryConsumer batteryConsumer)514 public void add(BatteryConsumer batteryConsumer) { 515 mConsumedPower += batteryConsumer.getConsumedPower(); 516 if (batteryConsumer instanceof UidBatteryConsumer) { 517 UidBatteryConsumer uidBatteryConsumer = (UidBatteryConsumer) batteryConsumer; 518 mTimeInForegroundMs += 519 uidBatteryConsumer.getTimeInProcessStateMs( 520 UidBatteryConsumer.PROCESS_STATE_FOREGROUND); 521 mTimeInForegroundServiceMs += 522 uidBatteryConsumer.getTimeInProcessStateMs( 523 UidBatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE); 524 mTimeInBackgroundMs += 525 uidBatteryConsumer.getTimeInProcessStateMs( 526 UidBatteryConsumer.PROCESS_STATE_BACKGROUND); 527 mConsumedPowerInForeground += 528 safeGetConsumedPower( 529 uidBatteryConsumer, BATTERY_DIMENSIONS[BATTERY_USAGE_INDEX_FOREGROUND]); 530 mConsumedPowerInForegroundService += 531 safeGetConsumedPower( 532 uidBatteryConsumer, 533 BATTERY_DIMENSIONS[BATTERY_USAGE_INDEX_FOREGROUND_SERVICE]); 534 mConsumedPowerInBackground += 535 safeGetConsumedPower( 536 uidBatteryConsumer, BATTERY_DIMENSIONS[BATTERY_USAGE_INDEX_BACKGROUND]); 537 mConsumedPowerInCached += 538 safeGetConsumedPower( 539 uidBatteryConsumer, BATTERY_DIMENSIONS[BATTERY_USAGE_INDEX_CACHED]); 540 if (mDefaultPackageName == null) { 541 mDefaultPackageName = uidBatteryConsumer.getPackageWithHighestDrain(); 542 } 543 } 544 } 545 546 /** Gets name and icon resource from UserBatteryConsumer userId. */ getNameAndIconFromUserId(Context context, final int userId)547 public static NameAndIcon getNameAndIconFromUserId(Context context, final int userId) { 548 UserManager um = context.getSystemService(UserManager.class); 549 UserInfo info = um.getUserInfo(userId); 550 551 Drawable icon = null; 552 String name = null; 553 if (info != null) { 554 icon = Utils.getUserIcon(context, um, info); 555 name = Utils.getUserLabel(context, info); 556 } else { 557 name = 558 context.getResources() 559 .getString(R.string.running_process_item_removed_user_label); 560 } 561 return new NameAndIcon(name, icon, 0 /* iconId */); 562 } 563 564 /** Gets name and icon resource from UidBatteryConsumer uid. */ getNameAndIconFromUid(Context context, String name, final int uid)565 public static NameAndIcon getNameAndIconFromUid(Context context, String name, final int uid) { 566 Drawable icon = context.getDrawable(R.drawable.ic_power_system); 567 if (uid == 0) { 568 name = 569 context.getResources() 570 .getString(com.android.settingslib.R.string.process_kernel_label); 571 } else if (uid == BatteryUtils.UID_REMOVED_APPS) { 572 name = context.getResources().getString(R.string.process_removed_apps); 573 } else if (uid == BatteryUtils.UID_TETHERING) { 574 name = context.getResources().getString(R.string.process_network_tethering); 575 } else if ("mediaserver".equals(name)) { 576 name = context.getResources().getString(R.string.process_mediaserver_label); 577 } else if ("dex2oat".equals(name) || "dex2oat32".equals(name) || "dex2oat64".equals(name)) { 578 name = context.getResources().getString(R.string.process_dex2oat_label); 579 } 580 return new NameAndIcon(name, icon, 0 /* iconId */); 581 } 582 583 /** Gets name and icon resource from BatteryConsumer power component ID. */ getNameAndIconFromPowerComponent( Context context, @BatteryConsumer.PowerComponent int powerComponentId)584 public static NameAndIcon getNameAndIconFromPowerComponent( 585 Context context, @BatteryConsumer.PowerComponent int powerComponentId) { 586 String name; 587 int iconId; 588 switch (powerComponentId) { 589 // Please see go/battery-usage-system-component-map 590 case BatteryConsumer.POWER_COMPONENT_SCREEN: // id: 0 591 name = context.getResources().getString(R.string.power_screen); 592 iconId = R.drawable.ic_settings_display; 593 break; 594 case BatteryConsumer.POWER_COMPONENT_CPU: // id: 1 595 name = context.getResources().getString(R.string.power_cpu); 596 iconId = R.drawable.ic_settings_cpu; 597 break; 598 case BatteryConsumer.POWER_COMPONENT_BLUETOOTH: // id: 2 599 name = context.getResources().getString(R.string.power_bluetooth); 600 iconId = R.drawable.ic_settings_bluetooth; 601 break; 602 case BatteryConsumer.POWER_COMPONENT_CAMERA: // id: 3 603 name = context.getResources().getString(R.string.power_camera); 604 iconId = R.drawable.ic_settings_camera; 605 break; 606 case BatteryConsumer.POWER_COMPONENT_FLASHLIGHT: // id: 6 607 name = context.getResources().getString(R.string.power_flashlight); 608 iconId = R.drawable.ic_settings_flashlight; 609 break; 610 case BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO: // id: 8 611 name = context.getResources().getString(R.string.power_cell); 612 iconId = R.drawable.ic_settings_cellular; 613 break; 614 case BatteryConsumer.POWER_COMPONENT_GNSS: // id: 10 615 name = context.getResources().getString(R.string.power_gps); 616 iconId = R.drawable.ic_settings_gps; 617 break; 618 case BatteryConsumer.POWER_COMPONENT_WIFI: // id: 11 619 name = context.getResources().getString(R.string.power_wifi); 620 iconId = R.drawable.ic_settings_wireless_no_theme; 621 break; 622 case BatteryConsumer.POWER_COMPONENT_PHONE: // id: 14 623 name = context.getResources().getString(R.string.power_phone); 624 iconId = R.drawable.ic_settings_voice_calls; 625 break; 626 case BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY: // id :15 627 name = context.getResources().getString(R.string.ambient_display_screen_title); 628 iconId = R.drawable.ic_settings_aod; 629 break; 630 default: 631 Log.w( 632 TAG, 633 "unknown attribute:" 634 + DebugUtils.constantToString( 635 BatteryConsumer.class, 636 "POWER_COMPONENT_", 637 powerComponentId)); 638 name = null; 639 iconId = R.drawable.ic_power_system; 640 break; 641 } 642 return new NameAndIcon(name, null /* icon */, iconId); 643 } 644 645 /** Whether the uid is system uid. */ isSystemUid(int uid)646 public static boolean isSystemUid(int uid) { 647 return uid == Process.SYSTEM_UID; 648 } 649 safeGetConsumedPower( final UidBatteryConsumer uidBatteryConsumer, final Dimensions dimension)650 private static double safeGetConsumedPower( 651 final UidBatteryConsumer uidBatteryConsumer, final Dimensions dimension) { 652 try { 653 return uidBatteryConsumer.getConsumedPower(dimension); 654 } catch (IllegalArgumentException e) { 655 Log.e(TAG, "safeGetConsumedPower failed:" + e); 656 return 0.0d; 657 } 658 } 659 660 @Override toString()661 public String toString() { 662 return new StringBuilder() 663 .append("BatteryEntry{") 664 .append(String.format("\n\tname=%s isHidden=%b", mName, mIsHidden)) 665 .append(String.format("\n\tconsume=%.2f%% | %f", mPercent, mConsumedPower)) 666 .append( 667 String.format( 668 "\n\tconsume power= foreground:%f foregroundService:%f", 669 mConsumedPowerInForeground, mConsumedPowerInForegroundService)) 670 .append( 671 String.format( 672 "\n\tconsume power= background:%f cached:%f", 673 mConsumedPowerInBackground, mConsumedPowerInCached)) 674 .append( 675 String.format( 676 "\n\ttime= foreground:%s foregroundService:%s " 677 + "background:%s usageDuration:%s", 678 StringUtil.formatElapsedTime( 679 mContext, 680 (double) mTimeInForegroundMs, 681 /* withSeconds= */ true, 682 /* collapseTimeUnit= */ false), 683 StringUtil.formatElapsedTime( 684 mContext, 685 (double) mTimeInForegroundServiceMs, 686 /* withSeconds= */ true, 687 /* collapseTimeUnit= */ false), 688 StringUtil.formatElapsedTime( 689 mContext, 690 (double) mTimeInBackgroundMs, 691 /* withSeconds= */ true, 692 /* collapseTimeUnit= */ false), 693 StringUtil.formatElapsedTime( 694 mContext, 695 (double) mUsageDurationMs, 696 /* withSeconds= */ true, 697 /* collapseTimeUnit= */ false))) 698 .append(String.format("\n\tpackage:%s uid:%d", mDefaultPackageName, mUid)) 699 .toString(); 700 } 701 } 702