1 /* 2 * Copyright (C) 2009 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 package com.android.settings.fuelgauge; 17 18 import com.android.settings.R; 19 import com.android.settings.fuelgauge.PowerUsageDetail.DrainType; 20 21 import android.content.Context; 22 import android.content.pm.ApplicationInfo; 23 import android.content.pm.PackageInfo; 24 import android.content.pm.PackageManager; 25 import android.content.pm.PackageManager.NameNotFoundException; 26 import android.graphics.drawable.Drawable; 27 import android.os.Handler; 28 import android.os.BatteryStats.Uid; 29 30 import java.util.ArrayList; 31 import java.util.HashMap; 32 33 /** 34 * Contains information about package name, icon image, power usage about an 35 * application or a system service. 36 */ 37 public class BatterySipper implements Comparable<BatterySipper> { 38 final Context mContext; 39 /* Cache cleared when PowerUsageSummary is destroyed */ 40 static final HashMap<String,UidToDetail> sUidCache = new HashMap<String,UidToDetail>(); 41 final ArrayList<BatterySipper> mRequestQueue; 42 final Handler mHandler; 43 String name; 44 Drawable icon; 45 int iconId; // For passing to the detail screen. 46 Uid uidObj; 47 double value; 48 double[] values; 49 DrainType drainType; 50 long usageTime; 51 long cpuTime; 52 long gpsTime; 53 long wifiRunningTime; 54 long cpuFgTime; 55 long wakeLockTime; 56 long mobileRxBytes; 57 long mobileTxBytes; 58 long wifiRxBytes; 59 long wifiTxBytes; 60 double percent; 61 double noCoveragePercent; 62 String defaultPackageName; 63 String[] mPackages; 64 65 static class UidToDetail { 66 String name; 67 String packageName; 68 Drawable icon; 69 } 70 71 BatterySipper(Context context, ArrayList<BatterySipper> requestQueue, 72 Handler handler, String label, DrainType drainType, 73 int iconId, Uid uid, double[] values) { 74 mContext = context; 75 mRequestQueue = requestQueue; 76 mHandler = handler; 77 this.values = values; 78 name = label; 79 this.drainType = drainType; 80 if (iconId > 0) { 81 icon = mContext.getResources().getDrawable(iconId); 82 } 83 if (values != null) value = values[0]; 84 if ((label == null || iconId == 0) && uid != null) { 85 getQuickNameIconForUid(uid); 86 } 87 uidObj = uid; 88 } 89 90 double getSortValue() { 91 return value; 92 } 93 94 double[] getValues() { 95 return values; 96 } 97 98 public Drawable getIcon() { 99 return icon; 100 } 101 102 /** 103 * Gets the application name 104 */ 105 public String getLabel() { 106 return name; 107 } 108 109 @Override 110 public int compareTo(BatterySipper other) { 111 // Return the flipped value because we want the items in descending order 112 return Double.compare(other.getSortValue(), getSortValue()); 113 } 114 115 /** 116 * Gets a list of packages associated with the current user 117 */ 118 public String[] getPackages() { 119 return mPackages; 120 } 121 122 public int getUid() { 123 // Bail out if the current sipper is not an App sipper. 124 if (uidObj == null) { 125 return 0; 126 } 127 return uidObj.getUid(); 128 } 129 130 void getQuickNameIconForUid(Uid uidObj) { 131 final int uid = uidObj.getUid(); 132 final String uidString = Integer.toString(uid); 133 if (sUidCache.containsKey(uidString)) { 134 UidToDetail utd = sUidCache.get(uidString); 135 defaultPackageName = utd.packageName; 136 name = utd.name; 137 icon = utd.icon; 138 return; 139 } 140 PackageManager pm = mContext.getPackageManager(); 141 String[] packages = pm.getPackagesForUid(uid); 142 icon = pm.getDefaultActivityIcon(); 143 if (packages == null) { 144 //name = Integer.toString(uid); 145 if (uid == 0) { 146 name = mContext.getResources().getString(R.string.process_kernel_label); 147 } else if ("mediaserver".equals(name)) { 148 name = mContext.getResources().getString(R.string.process_mediaserver_label); 149 } 150 iconId = R.drawable.ic_power_system; 151 icon = mContext.getResources().getDrawable(iconId); 152 return; 153 } else { 154 //name = packages[0]; 155 } 156 if (mHandler != null) { 157 synchronized (mRequestQueue) { 158 mRequestQueue.add(this); 159 } 160 } 161 } 162 163 public static void clearUidCache() { 164 sUidCache.clear(); 165 } 166 167 /** 168 * Loads the app label and icon image and stores into the cache. 169 */ 170 public void loadNameAndIcon() { 171 // Bail out if the current sipper is not an App sipper. 172 if (uidObj == null) { 173 return; 174 } 175 PackageManager pm = mContext.getPackageManager(); 176 final int uid = uidObj.getUid(); 177 final Drawable defaultActivityIcon = pm.getDefaultActivityIcon(); 178 mPackages = pm.getPackagesForUid(uid); 179 if (mPackages == null) { 180 name = Integer.toString(uid); 181 return; 182 } 183 184 String[] packageLabels = new String[mPackages.length]; 185 System.arraycopy(mPackages, 0, packageLabels, 0, mPackages.length); 186 187 int preferredIndex = -1; 188 // Convert package names to user-facing labels where possible 189 for (int i = 0; i < packageLabels.length; i++) { 190 // Check if package matches preferred package 191 if (packageLabels[i].equals(name)) preferredIndex = i; 192 try { 193 ApplicationInfo ai = pm.getApplicationInfo(packageLabels[i], 0); 194 CharSequence label = ai.loadLabel(pm); 195 if (label != null) { 196 packageLabels[i] = label.toString(); 197 } 198 if (ai.icon != 0) { 199 defaultPackageName = mPackages[i]; 200 icon = ai.loadIcon(pm); 201 break; 202 } 203 } catch (NameNotFoundException e) { 204 } 205 } 206 if (icon == null) icon = defaultActivityIcon; 207 208 if (packageLabels.length == 1) { 209 name = packageLabels[0]; 210 } else { 211 // Look for an official name for this UID. 212 for (String pkgName : mPackages) { 213 try { 214 final PackageInfo pi = pm.getPackageInfo(pkgName, 0); 215 if (pi.sharedUserLabel != 0) { 216 final CharSequence nm = pm.getText(pkgName, 217 pi.sharedUserLabel, pi.applicationInfo); 218 if (nm != null) { 219 name = nm.toString(); 220 if (pi.applicationInfo.icon != 0) { 221 defaultPackageName = pkgName; 222 icon = pi.applicationInfo.loadIcon(pm); 223 } 224 break; 225 } 226 } 227 } catch (PackageManager.NameNotFoundException e) { 228 } 229 } 230 } 231 final String uidString = Integer.toString(uidObj.getUid()); 232 UidToDetail utd = new UidToDetail(); 233 utd.name = name; 234 utd.icon = icon; 235 utd.packageName = defaultPackageName; 236 sUidCache.put(uidString, utd); 237 if (mHandler != null) { 238 mHandler.sendMessage( 239 mHandler.obtainMessage(BatteryStatsHelper.MSG_UPDATE_NAME_ICON, this)); 240 } 241 } 242 } 243