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