1ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn/*
2ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn * Copyright (C) 2009 The Android Open Source Project
3ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn *
4ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License");
5ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn * you may not use this file except in compliance with the License.
6ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn * You may obtain a copy of the License at
7ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn *
8ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn *      http://www.apache.org/licenses/LICENSE-2.0
9ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn *
10ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn * Unless required by applicable law or agreed to in writing, software
11ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS,
12ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn * See the License for the specific language governing permissions and
14ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn * limitations under the License.
15ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn */
16ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornpackage com.android.settings.fuelgauge;
17ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
18ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornimport com.android.settings.R;
19ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornimport com.android.settings.fuelgauge.PowerUsageDetail.DrainType;
20ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
21ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornimport android.content.Context;
22ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornimport android.content.pm.ApplicationInfo;
23ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornimport android.content.pm.PackageInfo;
24ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornimport android.content.pm.PackageManager;
25ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornimport android.content.pm.PackageManager.NameNotFoundException;
26ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornimport android.graphics.drawable.Drawable;
27ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornimport android.os.Handler;
28ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornimport android.os.BatteryStats.Uid;
29ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
30ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornimport java.util.ArrayList;
31ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornimport java.util.HashMap;
32ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
33ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornclass BatterySipper implements Comparable<BatterySipper> {
34ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    final Context mContext;
35ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    final HashMap<String,UidToDetail> mUidCache = new HashMap<String,UidToDetail>();
36ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    final ArrayList<BatterySipper> mRequestQueue;
37ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    final Handler mHandler;
38ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    String name;
39ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    Drawable icon;
40ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    int iconId; // For passing to the detail screen.
41ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    Uid uidObj;
42ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    double value;
43ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    double[] values;
44ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    DrainType drainType;
45ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    long usageTime;
46ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    long cpuTime;
47ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    long gpsTime;
48cb818619c669d4257a4df969dd03eff479ba84d0Dianne Hackborn    long wifiRunningTime;
49ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    long cpuFgTime;
50be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn    long wakeLockTime;
51cb818619c669d4257a4df969dd03eff479ba84d0Dianne Hackborn    long tcpBytesReceived;
52cb818619c669d4257a4df969dd03eff479ba84d0Dianne Hackborn    long tcpBytesSent;
53ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    double percent;
54ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    double noCoveragePercent;
55ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    String defaultPackageName;
56ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
57ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    static class UidToDetail {
58ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        String name;
59ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        String packageName;
60ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        Drawable icon;
61ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    }
62ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
63ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    BatterySipper(Context context, ArrayList<BatterySipper> requestQueue,
64ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            Handler handler, String label, DrainType drainType,
65ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            int iconId, Uid uid, double[] values) {
66ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        mContext = context;
67ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        mRequestQueue = requestQueue;
68ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        mHandler = handler;
69ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        this.values = values;
70ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        name = label;
71ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        this.drainType = drainType;
72ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        if (iconId > 0) {
73ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            icon = mContext.getResources().getDrawable(iconId);
74ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        }
75ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        if (values != null) value = values[0];
76ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        if ((label == null || iconId == 0) && uid != null) {
77ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            getQuickNameIconForUid(uid);
78ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        }
79ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        uidObj = uid;
80ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    }
81ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
82ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    double getSortValue() {
83ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        return value;
84ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    }
85ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
86ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    double[] getValues() {
87ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        return values;
88ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    }
89ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
90ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    Drawable getIcon() {
91ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        return icon;
92ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    }
93ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
94ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    public int compareTo(BatterySipper other) {
95ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        // Return the flipped value because we want the items in descending order
96ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        return (int) (other.getSortValue() - getSortValue());
97ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    }
98ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
99ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    void getQuickNameIconForUid(Uid uidObj) {
100ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        final int uid = uidObj.getUid();
101ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        final String uidString = Integer.toString(uid);
102ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        if (mUidCache.containsKey(uidString)) {
103ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            UidToDetail utd = mUidCache.get(uidString);
104ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            defaultPackageName = utd.packageName;
105ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            name = utd.name;
106ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            icon = utd.icon;
107ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            return;
108ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        }
109ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        PackageManager pm = mContext.getPackageManager();
110ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        String[] packages = pm.getPackagesForUid(uid);
111ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        icon = pm.getDefaultActivityIcon();
112ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        if (packages == null) {
113ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            //name = Integer.toString(uid);
114ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            if (uid == 0) {
115ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                name = mContext.getResources().getString(R.string.process_kernel_label);
116ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            } else if ("mediaserver".equals(name)) {
117ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                name = mContext.getResources().getString(R.string.process_mediaserver_label);
118ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            }
119ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            iconId = R.drawable.ic_power_system;
120ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            icon = mContext.getResources().getDrawable(iconId);
121ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            return;
122ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        } else {
123ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            //name = packages[0];
124ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        }
125ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        synchronized (mRequestQueue) {
126ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            mRequestQueue.add(this);
127ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        }
128ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    }
129ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
130ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    /**
131ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn     * Sets name and icon
132ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn     * @param uid Uid of the application
133ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn     */
134ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    void getNameIcon() {
135ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        PackageManager pm = mContext.getPackageManager();
136ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        final int uid = uidObj.getUid();
137ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        final Drawable defaultActivityIcon = pm.getDefaultActivityIcon();
138ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        String[] packages = pm.getPackagesForUid(uid);
139ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        if (packages == null) {
140ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            name = Integer.toString(uid);
141ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            return;
142ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        }
143ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
144ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        String[] packageLabels = new String[packages.length];
145ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        System.arraycopy(packages, 0, packageLabels, 0, packages.length);
146ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
147ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        int preferredIndex = -1;
148ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        // Convert package names to user-facing labels where possible
149ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        for (int i = 0; i < packageLabels.length; i++) {
150ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            // Check if package matches preferred package
151ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            if (packageLabels[i].equals(name)) preferredIndex = i;
152ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            try {
153ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                ApplicationInfo ai = pm.getApplicationInfo(packageLabels[i], 0);
154ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                CharSequence label = ai.loadLabel(pm);
155ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                if (label != null) {
156ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                    packageLabels[i] = label.toString();
157ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                }
158ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                if (ai.icon != 0) {
159ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                    defaultPackageName = packages[i];
160ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                    icon = ai.loadIcon(pm);
161ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                    break;
162ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                }
163ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            } catch (NameNotFoundException e) {
164ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            }
165ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        }
166ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        if (icon == null) icon = defaultActivityIcon;
167ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
168ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        if (packageLabels.length == 1) {
169ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            name = packageLabels[0];
170ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        } else {
171ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            // Look for an official name for this UID.
172ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            for (String pkgName : packages) {
173ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                try {
174ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                    final PackageInfo pi = pm.getPackageInfo(pkgName, 0);
175ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                    if (pi.sharedUserLabel != 0) {
176ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                        final CharSequence nm = pm.getText(pkgName,
177ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                                pi.sharedUserLabel, pi.applicationInfo);
178ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                        if (nm != null) {
179ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                            name = nm.toString();
180ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                            if (pi.applicationInfo.icon != 0) {
181ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                                defaultPackageName = pkgName;
182ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                                icon = pi.applicationInfo.loadIcon(pm);
183ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                            }
184ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                            break;
185ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                        }
186ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                    }
187ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                } catch (PackageManager.NameNotFoundException e) {
188ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                }
189ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            }
190ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        }
191ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        final String uidString = Integer.toString(uidObj.getUid());
192ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        UidToDetail utd = new UidToDetail();
193ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        utd.name = name;
194ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        utd.icon = icon;
195ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        utd.packageName = defaultPackageName;
196ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        mUidCache.put(uidString, utd);
197ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        mHandler.sendMessage(mHandler.obtainMessage(PowerUsageSummary.MSG_UPDATE_NAME_ICON, this));
198ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    }
199ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn}