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