BatterySipper.java revision ea38e678537cf740b5f30c1d69c7a332e98cdd2c
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 */
16package com.android.settings.fuelgauge;
17
18import com.android.settings.R;
19import com.android.settings.fuelgauge.PowerUsageDetail.DrainType;
20
21import android.content.Context;
22import android.content.pm.ApplicationInfo;
23import android.content.pm.PackageInfo;
24import android.content.pm.PackageManager;
25import android.content.pm.PackageManager.NameNotFoundException;
26import android.graphics.drawable.Drawable;
27import android.os.Handler;
28import android.os.BatteryStats.Uid;
29
30import java.util.ArrayList;
31import java.util.HashMap;
32
33class BatterySipper implements Comparable<BatterySipper> {
34    final Context mContext;
35    final HashMap<String,UidToDetail> mUidCache = new HashMap<String,UidToDetail>();
36    final ArrayList<BatterySipper> mRequestQueue;
37    final Handler mHandler;
38    String name;
39    Drawable icon;
40    int iconId; // For passing to the detail screen.
41    Uid uidObj;
42    double value;
43    double[] values;
44    DrainType drainType;
45    long usageTime;
46    long cpuTime;
47    long gpsTime;
48    long cpuFgTime;
49    double percent;
50    double noCoveragePercent;
51    String defaultPackageName;
52
53    static class UidToDetail {
54        String name;
55        String packageName;
56        Drawable icon;
57    }
58
59    BatterySipper(Context context, ArrayList<BatterySipper> requestQueue,
60            Handler handler, String label, DrainType drainType,
61            int iconId, Uid uid, double[] values) {
62        mContext = context;
63        mRequestQueue = requestQueue;
64        mHandler = handler;
65        this.values = values;
66        name = label;
67        this.drainType = drainType;
68        if (iconId > 0) {
69            icon = mContext.getResources().getDrawable(iconId);
70        }
71        if (values != null) value = values[0];
72        if ((label == null || iconId == 0) && uid != null) {
73            getQuickNameIconForUid(uid);
74        }
75        uidObj = uid;
76    }
77
78    double getSortValue() {
79        return value;
80    }
81
82    double[] getValues() {
83        return values;
84    }
85
86    Drawable getIcon() {
87        return icon;
88    }
89
90    public int compareTo(BatterySipper other) {
91        // Return the flipped value because we want the items in descending order
92        return (int) (other.getSortValue() - getSortValue());
93    }
94
95    void getQuickNameIconForUid(Uid uidObj) {
96        final int uid = uidObj.getUid();
97        final String uidString = Integer.toString(uid);
98        if (mUidCache.containsKey(uidString)) {
99            UidToDetail utd = mUidCache.get(uidString);
100            defaultPackageName = utd.packageName;
101            name = utd.name;
102            icon = utd.icon;
103            return;
104        }
105        PackageManager pm = mContext.getPackageManager();
106        final Drawable defaultActivityIcon = pm.getDefaultActivityIcon();
107        String[] packages = pm.getPackagesForUid(uid);
108        icon = pm.getDefaultActivityIcon();
109        if (packages == null) {
110            //name = Integer.toString(uid);
111            if (uid == 0) {
112                name = mContext.getResources().getString(R.string.process_kernel_label);
113            } else if ("mediaserver".equals(name)) {
114                name = mContext.getResources().getString(R.string.process_mediaserver_label);
115            }
116            iconId = R.drawable.ic_power_system;
117            icon = mContext.getResources().getDrawable(iconId);
118            return;
119        } else {
120            //name = packages[0];
121        }
122        synchronized (mRequestQueue) {
123            mRequestQueue.add(this);
124        }
125    }
126
127    /**
128     * Sets name and icon
129     * @param uid Uid of the application
130     */
131    void getNameIcon() {
132        PackageManager pm = mContext.getPackageManager();
133        final int uid = uidObj.getUid();
134        final Drawable defaultActivityIcon = pm.getDefaultActivityIcon();
135        String[] packages = pm.getPackagesForUid(uid);
136        if (packages == null) {
137            name = Integer.toString(uid);
138            return;
139        }
140
141        String[] packageLabels = new String[packages.length];
142        System.arraycopy(packages, 0, packageLabels, 0, packages.length);
143
144        int preferredIndex = -1;
145        // Convert package names to user-facing labels where possible
146        for (int i = 0; i < packageLabels.length; i++) {
147            // Check if package matches preferred package
148            if (packageLabels[i].equals(name)) preferredIndex = i;
149            try {
150                ApplicationInfo ai = pm.getApplicationInfo(packageLabels[i], 0);
151                CharSequence label = ai.loadLabel(pm);
152                if (label != null) {
153                    packageLabels[i] = label.toString();
154                }
155                if (ai.icon != 0) {
156                    defaultPackageName = packages[i];
157                    icon = ai.loadIcon(pm);
158                    break;
159                }
160            } catch (NameNotFoundException e) {
161            }
162        }
163        if (icon == null) icon = defaultActivityIcon;
164
165        if (packageLabels.length == 1) {
166            name = packageLabels[0];
167        } else {
168            // Look for an official name for this UID.
169            for (String pkgName : packages) {
170                try {
171                    final PackageInfo pi = pm.getPackageInfo(pkgName, 0);
172                    if (pi.sharedUserLabel != 0) {
173                        final CharSequence nm = pm.getText(pkgName,
174                                pi.sharedUserLabel, pi.applicationInfo);
175                        if (nm != null) {
176                            name = nm.toString();
177                            if (pi.applicationInfo.icon != 0) {
178                                defaultPackageName = pkgName;
179                                icon = pi.applicationInfo.loadIcon(pm);
180                            }
181                            break;
182                        }
183                    }
184                } catch (PackageManager.NameNotFoundException e) {
185                }
186            }
187        }
188        final String uidString = Integer.toString(uidObj.getUid());
189        UidToDetail utd = new UidToDetail();
190        utd.name = name;
191        utd.icon = icon;
192        utd.packageName = defaultPackageName;
193        mUidCache.put(uidString, utd);
194        mHandler.sendMessage(mHandler.obtainMessage(PowerUsageSummary.MSG_UPDATE_NAME_ICON, this));
195    }
196}