12a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasani/*
22a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasani * Copyright (C) 2009 The Android Open Source Project
32a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasani *
42a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasani * Licensed under the Apache License, Version 2.0 (the "License");
52a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasani * you may not use this file except in compliance with the License.
62a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasani * You may obtain a copy of the License at
72a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasani *
82a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasani *      http://www.apache.org/licenses/LICENSE-2.0
92a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasani *
102a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasani * Unless required by applicable law or agreed to in writing, software
112a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasani * distributed under the License is distributed on an "AS IS" BASIS,
122a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasani * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasani * See the License for the specific language governing permissions and
142a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasani * limitations under the License.
152a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasani */
162a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasani
172a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasanipackage com.android.settings.fuelgauge;
182a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasani
19c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport android.app.Activity;
203069581512bcb9687cb8d79675f6c4950c9ac087Jason Monkimport android.content.Context;
21ebb36ec9207c9519f6ae6a1aa39909279aa1d0e9Zoltan Szatmary-Banimport android.graphics.drawable.Drawable;
222a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasaniimport android.os.BatteryStats;
23f7a5017fa60d4cd3c802a45a7b04a4c8f34d969eMichael Wrightimport android.os.Build;
242a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasaniimport android.os.Bundle;
2578fd96a1c5dd7b03fa09d8b3116243cc9661c5e6Amith Yamasaniimport android.os.Handler;
2678fd96a1c5dd7b03fa09d8b3116243cc9661c5e6Amith Yamasaniimport android.os.Message;
274444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinskiimport android.os.Process;
287c80af410b09fa14b6fdb5ecec14b6b96562de4cDianne Hackbornimport android.os.UserHandle;
2939b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport android.support.v7.preference.Preference;
3039b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport android.support.v7.preference.PreferenceGroup;
310d6a574100055f857a2eeab030485cf094da85b8Jason Monkimport android.text.TextUtils;
324444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinskiimport android.util.SparseArray;
33f2819e0eada8af3835141857b5d499bca90774a6Jason Monkimport android.util.TypedValue;
347f6aa6283ae759c5b013c142be036617cf79f725Amith Yamasaniimport android.view.Menu;
3559a48604b5a803fbec6857e07f9fa1adbc6b8bb4Dianne Hackbornimport android.view.MenuInflater;
367f6aa6283ae759c5b013c142be036617cf79f725Amith Yamasaniimport android.view.MenuItem;
379d1bfd1e8de6e46137a9571507c03526880d6a46Chris Wrenimport com.android.internal.logging.MetricsProto.MetricsEvent;
387c80af410b09fa14b6fdb5ecec14b6b96562de4cDianne Hackbornimport com.android.internal.os.BatterySipper;
39f2819e0eada8af3835141857b5d499bca90774a6Jason Monkimport com.android.internal.os.BatterySipper.DrainType;
406880ec09cd95359d42007d3c76ac4b9905743de7Jason Monkimport com.android.internal.os.PowerProfile;
41162e541011e6ca716bf4af191dee419c1a712d0eGilles Debunneimport com.android.settings.R;
421eb54eb2ff250eccdd700601011bd6457ddcbec1Jason Monkimport com.android.settings.Settings.HighPowerApplicationsActivity;
43263bcc8b732dbb47d3ce63904e0e05191fabbad6Fabrice Di Meglioimport com.android.settings.SettingsActivity;
441eb54eb2ff250eccdd700601011bd6457ddcbec1Jason Monkimport com.android.settings.applications.ManageApplications;
453069581512bcb9687cb8d79675f6c4950c9ac087Jason Monkimport com.android.settings.dashboard.SummaryLoader;
4627985e1f922eeb75da3214a7f88c63ac34dc4badJason Monkimport com.android.settingslib.BatteryInfo;
47162e541011e6ca716bf4af191dee419c1a712d0eGilles Debunne
48f2819e0eada8af3835141857b5d499bca90774a6Jason Monkimport java.util.ArrayList;
494444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinskiimport java.util.Collections;
504444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinskiimport java.util.Comparator;
512a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasaniimport java.util.List;
522a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasani
532a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasani/**
542a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasani * Displays a list of apps and subsystems that consume power, ordered by how much power was
552a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasani * consumed since the last time it was unplugged.
562a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasani */
571eb54eb2ff250eccdd700601011bd6457ddcbec1Jason Monkpublic class PowerUsageSummary extends PowerUsageBase {
582a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasani
5978fd96a1c5dd7b03fa09d8b3116243cc9661c5e6Amith Yamasani    private static final boolean DEBUG = false;
602a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasani
61f2819e0eada8af3835141857b5d499bca90774a6Jason Monk    private static final boolean USE_FAKE_DATA = false;
62f2819e0eada8af3835141857b5d499bca90774a6Jason Monk
633aaf0eb457639b52228143b84d9624bf73d862eaZoltan Szatmary-Ban    static final String TAG = "PowerUsageSummary";
647f6aa6283ae759c5b013c142be036617cf79f725Amith Yamasani
65a4379d6b38e568fcb60831d6f2fa349ba20f9b82Amith Yamasani    private static final String KEY_APP_LIST = "app_list";
661eb54eb2ff250eccdd700601011bd6457ddcbec1Jason Monk    private static final String KEY_BATTERY_HISTORY = "battery_history";
67537a0a82351d9671d14dccde8c9fc2a45c3c4f3aDianne Hackborn
687f6aa6283ae759c5b013c142be036617cf79f725Amith Yamasani    private static final int MENU_STATS_TYPE = Menu.FIRST;
691eb54eb2ff250eccdd700601011bd6457ddcbec1Jason Monk    private static final int MENU_HIGH_POWER_APPS = Menu.FIRST + 3;
701eb54eb2ff250eccdd700601011bd6457ddcbec1Jason Monk    private static final int MENU_HELP = Menu.FIRST + 4;
717c80af410b09fa14b6fdb5ecec14b6b96562de4cDianne Hackborn
727158e6299210d08f82c29135c001652508b79dfbDianne Hackborn    private BatteryHistoryPreference mHistPref;
732a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasani    private PreferenceGroup mAppListGroup;
742a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasani
754f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn    private int mStatsType = BatteryStats.STATS_SINCE_CHARGED;
762a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasani
77298f325f544e85d354aa0f802c3b2bb5812c52a6Zoltan Szatmary-Ban    private static final int MIN_POWER_THRESHOLD_MILLI_AMP = 5;
788f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski    private static final int MAX_ITEMS_TO_LIST = USE_FAKE_DATA ? 30 : 10;
79298f325f544e85d354aa0f802c3b2bb5812c52a6Zoltan Szatmary-Ban    private static final int MIN_AVERAGE_POWER_THRESHOLD_MILLI_AMP = 10;
80298f325f544e85d354aa0f802c3b2bb5812c52a6Zoltan Szatmary-Ban    private static final int SECONDS_IN_HOUR = 60 * 60;
812a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasani
82c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    @Override
8359a48604b5a803fbec6857e07f9fa1adbc6b8bb4Dianne Hackborn    public void onCreate(Bundle icicle) {
842a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasani        super.onCreate(icicle);
85f38fb38f26117176ba7b961e960ef5c79e28a152Jason Monk        setAnimationAllowed(true);
86cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn
872a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasani        addPreferencesFromResource(R.xml.power_usage_summary);
881eb54eb2ff250eccdd700601011bd6457ddcbec1Jason Monk        mHistPref = (BatteryHistoryPreference) findPreference(KEY_BATTERY_HISTORY);
89a4379d6b38e568fcb60831d6f2fa349ba20f9b82Amith Yamasani        mAppListGroup = (PreferenceGroup) findPreference(KEY_APP_LIST);
90be300225df4ac43f84c854a646ee1af5d1ae61e6Dianne Hackborn    }
91be300225df4ac43f84c854a646ee1af5d1ae61e6Dianne Hackborn
92be300225df4ac43f84c854a646ee1af5d1ae61e6Dianne Hackborn    @Override
938a963babe2e36b7a41f77b8d2598c97658196e58Chris Wren    protected int getMetricsCategory() {
949d1bfd1e8de6e46137a9571507c03526880d6a46Chris Wren        return MetricsEvent.FUELGAUGE_POWER_USAGE_SUMMARY;
958a963babe2e36b7a41f77b8d2598c97658196e58Chris Wren    }
968a963babe2e36b7a41f77b8d2598c97658196e58Chris Wren
978a963babe2e36b7a41f77b8d2598c97658196e58Chris Wren    @Override
9859a48604b5a803fbec6857e07f9fa1adbc6b8bb4Dianne Hackborn    public void onResume() {
992a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasani        super.onResume();
1000422a3bf61c17851abd87a67a0de30e412459b5cAmith Yamasani        refreshStats();
1012a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasani    }
1022a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasani
1037f6aa6283ae759c5b013c142be036617cf79f725Amith Yamasani    @Override
10459a48604b5a803fbec6857e07f9fa1adbc6b8bb4Dianne Hackborn    public void onPause() {
1057c80af410b09fa14b6fdb5ecec14b6b96562de4cDianne Hackborn        BatteryEntry.stopRequestQueue();
1067c80af410b09fa14b6fdb5ecec14b6b96562de4cDianne Hackborn        mHandler.removeMessages(BatteryEntry.MSG_UPDATE_NAME_ICON);
10778fd96a1c5dd7b03fa09d8b3116243cc9661c5e6Amith Yamasani        super.onPause();
10878fd96a1c5dd7b03fa09d8b3116243cc9661c5e6Amith Yamasani    }
10978fd96a1c5dd7b03fa09d8b3116243cc9661c5e6Amith Yamasani
11078fd96a1c5dd7b03fa09d8b3116243cc9661c5e6Amith Yamasani    @Override
11159a48604b5a803fbec6857e07f9fa1adbc6b8bb4Dianne Hackborn    public void onDestroy() {
11259a48604b5a803fbec6857e07f9fa1adbc6b8bb4Dianne Hackborn        super.onDestroy();
1137c80af410b09fa14b6fdb5ecec14b6b96562de4cDianne Hackborn        if (getActivity().isChangingConfigurations()) {
1147c80af410b09fa14b6fdb5ecec14b6b96562de4cDianne Hackborn            BatteryEntry.clearUidCache();
1157c80af410b09fa14b6fdb5ecec14b6b96562de4cDianne Hackborn        }
11659a48604b5a803fbec6857e07f9fa1adbc6b8bb4Dianne Hackborn    }
11759a48604b5a803fbec6857e07f9fa1adbc6b8bb4Dianne Hackborn
11859a48604b5a803fbec6857e07f9fa1adbc6b8bb4Dianne Hackborn    @Override
11939b467482d1bf256a111c757e9b7621c6f523271Jason Monk    public boolean onPreferenceTreeClick(Preference preference) {
1204f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn        if (!(preference instanceof PowerGaugePreference)) {
121d1ea8a05b089714955e1523c40cdd1263b447a1aJason Monk            return super.onPreferenceTreeClick(preference);
1224f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn        }
1237f6aa6283ae759c5b013c142be036617cf79f725Amith Yamasani        PowerGaugePreference pgp = (PowerGaugePreference) preference;
1247c80af410b09fa14b6fdb5ecec14b6b96562de4cDianne Hackborn        BatteryEntry entry = pgp.getInfo();
125263bcc8b732dbb47d3ce63904e0e05191fabbad6Fabrice Di Meglio        PowerUsageDetail.startBatteryDetailPage((SettingsActivity) getActivity(), mStatsHelper,
126e492ee06adbf4661d8b8b53f41f236c9173c5ca4Julia Reynolds                mStatsType, entry, true, true);
12739b467482d1bf256a111c757e9b7621c6f523271Jason Monk        return super.onPreferenceTreeClick(preference);
1287f6aa6283ae759c5b013c142be036617cf79f725Amith Yamasani    }
1297f6aa6283ae759c5b013c142be036617cf79f725Amith Yamasani
1307f6aa6283ae759c5b013c142be036617cf79f725Amith Yamasani    @Override
13159a48604b5a803fbec6857e07f9fa1adbc6b8bb4Dianne Hackborn    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
13278fd96a1c5dd7b03fa09d8b3116243cc9661c5e6Amith Yamasani        if (DEBUG) {
13378fd96a1c5dd7b03fa09d8b3116243cc9661c5e6Amith Yamasani            menu.add(0, MENU_STATS_TYPE, 0, R.string.menu_stats_total)
13478fd96a1c5dd7b03fa09d8b3116243cc9661c5e6Amith Yamasani                    .setIcon(com.android.internal.R.drawable.ic_menu_info_details)
13578fd96a1c5dd7b03fa09d8b3116243cc9661c5e6Amith Yamasani                    .setAlphabeticShortcut('t');
13678fd96a1c5dd7b03fa09d8b3116243cc9661c5e6Amith Yamasani        }
137b0b37ae21c172491bc170659b5f429601858ddc1Amith Yamasani
1381eb54eb2ff250eccdd700601011bd6457ddcbec1Jason Monk        menu.add(0, MENU_HIGH_POWER_APPS, 0, R.string.high_power_apps);
1393006c377c2f62add27e6c40d5b27349501b31d6cJason Monk        super.onCreateOptionsMenu(menu, inflater);
1403006c377c2f62add27e6c40d5b27349501b31d6cJason Monk    }
1411eb54eb2ff250eccdd700601011bd6457ddcbec1Jason Monk
1423006c377c2f62add27e6c40d5b27349501b31d6cJason Monk    @Override
1433006c377c2f62add27e6c40d5b27349501b31d6cJason Monk    protected int getHelpResource() {
1443006c377c2f62add27e6c40d5b27349501b31d6cJason Monk        return R.string.help_url_battery;
1457f6aa6283ae759c5b013c142be036617cf79f725Amith Yamasani    }
1467f6aa6283ae759c5b013c142be036617cf79f725Amith Yamasani
1477f6aa6283ae759c5b013c142be036617cf79f725Amith Yamasani    @Override
1487f6aa6283ae759c5b013c142be036617cf79f725Amith Yamasani    public boolean onOptionsItemSelected(MenuItem item) {
1491eb54eb2ff250eccdd700601011bd6457ddcbec1Jason Monk        final SettingsActivity sa = (SettingsActivity) getActivity();
1507f6aa6283ae759c5b013c142be036617cf79f725Amith Yamasani        switch (item.getItemId()) {
1517f6aa6283ae759c5b013c142be036617cf79f725Amith Yamasani            case MENU_STATS_TYPE:
1524f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn                if (mStatsType == BatteryStats.STATS_SINCE_CHARGED) {
1534f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn                    mStatsType = BatteryStats.STATS_SINCE_UNPLUGGED;
1547f6aa6283ae759c5b013c142be036617cf79f725Amith Yamasani                } else {
1554f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn                    mStatsType = BatteryStats.STATS_SINCE_CHARGED;
1567f6aa6283ae759c5b013c142be036617cf79f725Amith Yamasani                }
1570422a3bf61c17851abd87a67a0de30e412459b5cAmith Yamasani                refreshStats();
1587f6aa6283ae759c5b013c142be036617cf79f725Amith Yamasani                return true;
1591eb54eb2ff250eccdd700601011bd6457ddcbec1Jason Monk            case MENU_HIGH_POWER_APPS:
1601eb54eb2ff250eccdd700601011bd6457ddcbec1Jason Monk                Bundle args = new Bundle();
1611eb54eb2ff250eccdd700601011bd6457ddcbec1Jason Monk                args.putString(ManageApplications.EXTRA_CLASSNAME,
1621eb54eb2ff250eccdd700601011bd6457ddcbec1Jason Monk                        HighPowerApplicationsActivity.class.getName());
1631eb54eb2ff250eccdd700601011bd6457ddcbec1Jason Monk                sa.startPreferencePanel(ManageApplications.class.getName(), args,
1641eb54eb2ff250eccdd700601011bd6457ddcbec1Jason Monk                        R.string.high_power_apps, null, null, 0);
1651eb54eb2ff250eccdd700601011bd6457ddcbec1Jason Monk                return true;
1667f6aa6283ae759c5b013c142be036617cf79f725Amith Yamasani            default:
1671eb54eb2ff250eccdd700601011bd6457ddcbec1Jason Monk                return super.onOptionsItemSelected(item);
1687f6aa6283ae759c5b013c142be036617cf79f725Amith Yamasani        }
1697f6aa6283ae759c5b013c142be036617cf79f725Amith Yamasani    }
1707f6aa6283ae759c5b013c142be036617cf79f725Amith Yamasani
171137588d60b0d8bb9612fa42f6d650751f540177bAmith Yamasani    private void addNotAvailableMessage() {
1720d6a574100055f857a2eeab030485cf094da85b8Jason Monk        final String NOT_AVAILABLE = "not_available";
1730d6a574100055f857a2eeab030485cf094da85b8Jason Monk        Preference notAvailable = getCachedPreference(NOT_AVAILABLE);
1740d6a574100055f857a2eeab030485cf094da85b8Jason Monk        if (notAvailable == null) {
1750d6a574100055f857a2eeab030485cf094da85b8Jason Monk            notAvailable = new Preference(getPrefContext());
1760d6a574100055f857a2eeab030485cf094da85b8Jason Monk            notAvailable.setKey(NOT_AVAILABLE);
1770d6a574100055f857a2eeab030485cf094da85b8Jason Monk            notAvailable.setTitle(R.string.power_usage_not_available);
1780d6a574100055f857a2eeab030485cf094da85b8Jason Monk            mAppListGroup.addPreference(notAvailable);
1790d6a574100055f857a2eeab030485cf094da85b8Jason Monk        }
180137588d60b0d8bb9612fa42f6d650751f540177bAmith Yamasani    }
181137588d60b0d8bb9612fa42f6d650751f540177bAmith Yamasani
1828f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski    private static boolean isSharedGid(int uid) {
1838f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski        return UserHandle.getAppIdFromSharedAppGid(uid) > 0;
1848f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski    }
1858f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski
1868f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski    private static boolean isSystemUid(int uid) {
1878f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski        return uid >= Process.SYSTEM_UID && uid < Process.FIRST_APPLICATION_UID;
1888f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski    }
1898f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski
1904444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski    /**
1914444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski     * We want to coalesce some UIDs. For example, dex2oat runs under a shared gid that
1924444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski     * exists for all users of the same app. We detect this case and merge the power use
1934444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski     * for dex2oat to the device OWNER's use of the app.
1948f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski     * @return A sorted list of apps using power.
1954444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski     */
1964444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski    private static List<BatterySipper> getCoalescedUsageList(final List<BatterySipper> sippers) {
1974444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski        final SparseArray<BatterySipper> uidList = new SparseArray<>();
1984444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski
1994444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski        final ArrayList<BatterySipper> results = new ArrayList<>();
2004444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski        final int numSippers = sippers.size();
2014444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski        for (int i = 0; i < numSippers; i++) {
2028f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski            BatterySipper sipper = sippers.get(i);
2034444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski            if (sipper.getUid() > 0) {
2044444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski                int realUid = sipper.getUid();
2058f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski
2068f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                // Check if this UID is a shared GID. If so, we combine it with the OWNER's
2078f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                // actual app UID.
2088f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                if (isSharedGid(sipper.getUid())) {
20944879a387a6be6b93cdcc8894227d68af7dbbb1aXiaohui Chen                    realUid = UserHandle.getUid(UserHandle.USER_SYSTEM,
2104444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski                            UserHandle.getAppIdFromSharedAppGid(sipper.getUid()));
2114444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski                }
2124444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski
2138f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                // Check if this UID is a system UID (mediaserver, logd, nfc, drm, etc).
2148f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                if (isSystemUid(realUid)
2158f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                        && !"mediaserver".equals(sipper.packageWithHighestDrain)) {
2168f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                    // Use the system UID for all UIDs running in their own sandbox that
2178f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                    // are not apps. We exclude mediaserver because we already are expected to
2188f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                    // report that as a separate item.
2198f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                    realUid = Process.SYSTEM_UID;
2208f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                }
2218f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski
2228f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                if (realUid != sipper.getUid()) {
2238f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                    // Replace the BatterySipper with a new one with the real UID set.
2248f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                    BatterySipper newSipper = new BatterySipper(sipper.drainType,
2258f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                            new FakeUid(realUid), 0.0);
2268f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                    newSipper.add(sipper);
2278f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                    newSipper.packageWithHighestDrain = sipper.packageWithHighestDrain;
2288f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                    newSipper.mPackages = sipper.mPackages;
2298f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                    sipper = newSipper;
2308f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                }
2318f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski
2324444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski                int index = uidList.indexOfKey(realUid);
2334444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski                if (index < 0) {
2348f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                    // New entry.
2354444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski                    uidList.put(realUid, sipper);
2364444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski                } else {
2378f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                    // Combine BatterySippers if we already have one with this UID.
2388f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                    final BatterySipper existingSipper = uidList.valueAt(index);
2398f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                    existingSipper.add(sipper);
2408f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                    if (existingSipper.packageWithHighestDrain == null
2418f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                            && sipper.packageWithHighestDrain != null) {
2428f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                        existingSipper.packageWithHighestDrain = sipper.packageWithHighestDrain;
2438f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                    }
2448f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski
2458f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                    final int existingPackageLen = existingSipper.mPackages != null ?
2468f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                            existingSipper.mPackages.length : 0;
2478f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                    final int newPackageLen = sipper.mPackages != null ?
2488f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                            sipper.mPackages.length : 0;
2498f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                    if (newPackageLen > 0) {
2508f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                        String[] newPackages = new String[existingPackageLen + newPackageLen];
2518f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                        if (existingPackageLen > 0) {
2528f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                            System.arraycopy(existingSipper.mPackages, 0, newPackages, 0,
2538f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                                    existingPackageLen);
2548f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                        }
2558f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                        System.arraycopy(sipper.mPackages, 0, newPackages, existingPackageLen,
2568f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                                newPackageLen);
2578f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                        existingSipper.mPackages = newPackages;
2584444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski                    }
2594444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski                }
2604444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski            } else {
2614444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski                results.add(sipper);
2624444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski            }
2634444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski        }
2644444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski
2654444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski        final int numUidSippers = uidList.size();
2664444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski        for (int i = 0; i < numUidSippers; i++) {
2674444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski            results.add(uidList.valueAt(i));
2684444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski        }
2694444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski
2704444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski        // The sort order must have changed, so re-sort based on total power use.
2714444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski        Collections.sort(results, new Comparator<BatterySipper>() {
2724444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski            @Override
2734444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski            public int compare(BatterySipper a, BatterySipper b) {
2744444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski                return Double.compare(b.totalPowerMah, a.totalPowerMah);
2754444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski            }
2764444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski        });
2774444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski        return results;
2784444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski    }
2794444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski
2801eb54eb2ff250eccdd700601011bd6457ddcbec1Jason Monk    protected void refreshStats() {
2811eb54eb2ff250eccdd700601011bd6457ddcbec1Jason Monk        super.refreshStats();
2821eb54eb2ff250eccdd700601011bd6457ddcbec1Jason Monk        updatePreference(mHistPref);
2830d6a574100055f857a2eeab030485cf094da85b8Jason Monk        cacheRemoveAllPrefs(mAppListGroup);
2842a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasani        mAppListGroup.setOrderingAsAdded(false);
2857158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        boolean addedSome = false;
286298f325f544e85d354aa0f802c3b2bb5812c52a6Zoltan Szatmary-Ban
287be300225df4ac43f84c854a646ee1af5d1ae61e6Dianne Hackborn        final PowerProfile powerProfile = mStatsHelper.getPowerProfile();
288be300225df4ac43f84c854a646ee1af5d1ae61e6Dianne Hackborn        final BatteryStats stats = mStatsHelper.getStats();
289298f325f544e85d354aa0f802c3b2bb5812c52a6Zoltan Szatmary-Ban        final double averagePower = powerProfile.getAveragePower(PowerProfile.POWER_SCREEN_FULL);
290298f325f544e85d354aa0f802c3b2bb5812c52a6Zoltan Szatmary-Ban
291f2819e0eada8af3835141857b5d499bca90774a6Jason Monk        TypedValue value = new TypedValue();
292f2819e0eada8af3835141857b5d499bca90774a6Jason Monk        getContext().getTheme().resolveAttribute(android.R.attr.colorControlNormal, value, true);
293f2819e0eada8af3835141857b5d499bca90774a6Jason Monk        int colorControl = getContext().getColor(value.resourceId);
294f2819e0eada8af3835141857b5d499bca90774a6Jason Monk
295f2819e0eada8af3835141857b5d499bca90774a6Jason Monk        if (averagePower >= MIN_AVERAGE_POWER_THRESHOLD_MILLI_AMP || USE_FAKE_DATA) {
2964444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski            final List<BatterySipper> usageList = getCoalescedUsageList(
2974444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski                    USE_FAKE_DATA ? getFakeStats() : mStatsHelper.getUsageList());
298298f325f544e85d354aa0f802c3b2bb5812c52a6Zoltan Szatmary-Ban
299f2819e0eada8af3835141857b5d499bca90774a6Jason Monk            final int dischargeAmount = USE_FAKE_DATA ? 5000
300f2819e0eada8af3835141857b5d499bca90774a6Jason Monk                    : stats != null ? stats.getDischargeAmount(mStatsType) : 0;
301298f325f544e85d354aa0f802c3b2bb5812c52a6Zoltan Szatmary-Ban            final int numSippers = usageList.size();
302298f325f544e85d354aa0f802c3b2bb5812c52a6Zoltan Szatmary-Ban            for (int i = 0; i < numSippers; i++) {
303298f325f544e85d354aa0f802c3b2bb5812c52a6Zoltan Szatmary-Ban                final BatterySipper sipper = usageList.get(i);
3040c9c85a8479d3d5c42b6307d98951b87cf06dee5Adam Lesinski                if ((sipper.totalPowerMah * SECONDS_IN_HOUR) < MIN_POWER_THRESHOLD_MILLI_AMP) {
305298f325f544e85d354aa0f802c3b2bb5812c52a6Zoltan Szatmary-Ban                    continue;
306298f325f544e85d354aa0f802c3b2bb5812c52a6Zoltan Szatmary-Ban                }
307f2819e0eada8af3835141857b5d499bca90774a6Jason Monk                double totalPower = USE_FAKE_DATA ? 4000 : mStatsHelper.getTotalPower();
308298f325f544e85d354aa0f802c3b2bb5812c52a6Zoltan Szatmary-Ban                final double percentOfTotal =
309f2819e0eada8af3835141857b5d499bca90774a6Jason Monk                        ((sipper.totalPowerMah / totalPower) * dischargeAmount);
310298f325f544e85d354aa0f802c3b2bb5812c52a6Zoltan Szatmary-Ban                if (((int) (percentOfTotal + .5)) < 1) {
311298f325f544e85d354aa0f802c3b2bb5812c52a6Zoltan Szatmary-Ban                    continue;
312298f325f544e85d354aa0f802c3b2bb5812c52a6Zoltan Szatmary-Ban                }
313c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn                if (sipper.drainType == BatterySipper.DrainType.OVERCOUNTED) {
314c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn                    // Don't show over-counted unless it is at least 2/3 the size of
315c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn                    // the largest real entry, and its percent of total is more significant
3160c9c85a8479d3d5c42b6307d98951b87cf06dee5Adam Lesinski                    if (sipper.totalPowerMah < ((mStatsHelper.getMaxRealPower()*2)/3)) {
317c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn                        continue;
318c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn                    }
319c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn                    if (percentOfTotal < 10) {
320c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn                        continue;
321c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn                    }
322f7a5017fa60d4cd3c802a45a7b04a4c8f34d969eMichael Wright                    if ("user".equals(Build.TYPE)) {
323f7a5017fa60d4cd3c802a45a7b04a4c8f34d969eMichael Wright                        continue;
324f7a5017fa60d4cd3c802a45a7b04a4c8f34d969eMichael Wright                    }
325c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn                }
326c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn                if (sipper.drainType == BatterySipper.DrainType.UNACCOUNTED) {
327c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn                    // Don't show over-counted unless it is at least 1/2 the size of
328c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn                    // the largest real entry, and its percent of total is more significant
3290c9c85a8479d3d5c42b6307d98951b87cf06dee5Adam Lesinski                    if (sipper.totalPowerMah < (mStatsHelper.getMaxRealPower()/2)) {
330c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn                        continue;
331c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn                    }
332c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn                    if (percentOfTotal < 5) {
333c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn                        continue;
334c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn                    }
335f7a5017fa60d4cd3c802a45a7b04a4c8f34d969eMichael Wright                    if ("user".equals(Build.TYPE)) {
336f7a5017fa60d4cd3c802a45a7b04a4c8f34d969eMichael Wright                        continue;
337f7a5017fa60d4cd3c802a45a7b04a4c8f34d969eMichael Wright                    }
338c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn                }
339298f325f544e85d354aa0f802c3b2bb5812c52a6Zoltan Szatmary-Ban                final UserHandle userHandle = new UserHandle(UserHandle.getUserId(sipper.getUid()));
340298f325f544e85d354aa0f802c3b2bb5812c52a6Zoltan Szatmary-Ban                final BatteryEntry entry = new BatteryEntry(getActivity(), mHandler, mUm, sipper);
3413aaf0eb457639b52228143b84d9624bf73d862eaZoltan Szatmary-Ban                final Drawable badgedIcon = mUm.getBadgedIconForUser(entry.getIcon(),
342ebb36ec9207c9519f6ae6a1aa39909279aa1d0e9Zoltan Szatmary-Ban                        userHandle);
343cc2cbaf4212e121a6b9cf0de160af2f78572f233Kenny Guy                final CharSequence contentDescription = mUm.getBadgedLabelForUser(entry.getLabel(),
344ebb36ec9207c9519f6ae6a1aa39909279aa1d0e9Zoltan Szatmary-Ban                        userHandle);
3450d6a574100055f857a2eeab030485cf094da85b8Jason Monk                final String key = sipper.drainType == DrainType.APP ? sipper.getPackages() != null
3460d6a574100055f857a2eeab030485cf094da85b8Jason Monk                        ? TextUtils.concat(sipper.getPackages()).toString()
3470d6a574100055f857a2eeab030485cf094da85b8Jason Monk                        : String.valueOf(sipper.getUid())
3480d6a574100055f857a2eeab030485cf094da85b8Jason Monk                        : sipper.drainType.toString();
3490d6a574100055f857a2eeab030485cf094da85b8Jason Monk                PowerGaugePreference pref = (PowerGaugePreference) getCachedPreference(key);
3500d6a574100055f857a2eeab030485cf094da85b8Jason Monk                if (pref == null) {
3510d6a574100055f857a2eeab030485cf094da85b8Jason Monk                    pref = new PowerGaugePreference(getPrefContext(), badgedIcon,
3520d6a574100055f857a2eeab030485cf094da85b8Jason Monk                            contentDescription, entry);
3530d6a574100055f857a2eeab030485cf094da85b8Jason Monk                    pref.setKey(key);
3540d6a574100055f857a2eeab030485cf094da85b8Jason Monk                }
355298f325f544e85d354aa0f802c3b2bb5812c52a6Zoltan Szatmary-Ban
3561eb54eb2ff250eccdd700601011bd6457ddcbec1Jason Monk                final double percentOfMax = (sipper.totalPowerMah * 100)
3571eb54eb2ff250eccdd700601011bd6457ddcbec1Jason Monk                        / mStatsHelper.getMaxPower();
358298f325f544e85d354aa0f802c3b2bb5812c52a6Zoltan Szatmary-Ban                sipper.percent = percentOfTotal;
359298f325f544e85d354aa0f802c3b2bb5812c52a6Zoltan Szatmary-Ban                pref.setTitle(entry.getLabel());
360298f325f544e85d354aa0f802c3b2bb5812c52a6Zoltan Szatmary-Ban                pref.setOrder(i + 1);
361298f325f544e85d354aa0f802c3b2bb5812c52a6Zoltan Szatmary-Ban                pref.setPercent(percentOfMax, percentOfTotal);
362298f325f544e85d354aa0f802c3b2bb5812c52a6Zoltan Szatmary-Ban                if (sipper.uidObj != null) {
363298f325f544e85d354aa0f802c3b2bb5812c52a6Zoltan Szatmary-Ban                    pref.setKey(Integer.toString(sipper.uidObj.getUid()));
364298f325f544e85d354aa0f802c3b2bb5812c52a6Zoltan Szatmary-Ban                }
3655ef0a9e826aaa8405a26f53c756f9bf0549709c3Jason Monk                if ((sipper.drainType != DrainType.APP || sipper.uidObj.getUid() == 0)
3665ef0a9e826aaa8405a26f53c756f9bf0549709c3Jason Monk                         && sipper.drainType != DrainType.USER) {
367f2819e0eada8af3835141857b5d499bca90774a6Jason Monk                    pref.setTint(colorControl);
368f2819e0eada8af3835141857b5d499bca90774a6Jason Monk                }
369298f325f544e85d354aa0f802c3b2bb5812c52a6Zoltan Szatmary-Ban                addedSome = true;
370298f325f544e85d354aa0f802c3b2bb5812c52a6Zoltan Szatmary-Ban                mAppListGroup.addPreference(pref);
371a627844fedb00c46eb206e2e88739e4d58cdde24Jason Monk                if (mAppListGroup.getPreferenceCount() - getCachedCount()
372a627844fedb00c46eb206e2e88739e4d58cdde24Jason Monk                        > (MAX_ITEMS_TO_LIST + 1)) {
373298f325f544e85d354aa0f802c3b2bb5812c52a6Zoltan Szatmary-Ban                    break;
374298f325f544e85d354aa0f802c3b2bb5812c52a6Zoltan Szatmary-Ban                }
37578fd96a1c5dd7b03fa09d8b3116243cc9661c5e6Amith Yamasani            }
3762a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasani        }
3777158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        if (!addedSome) {
3787158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            addNotAvailableMessage();
3797158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        }
3800d6a574100055f857a2eeab030485cf094da85b8Jason Monk        removeCachedPrefs(mAppListGroup);
3817c80af410b09fa14b6fdb5ecec14b6b96562de4cDianne Hackborn
3827c80af410b09fa14b6fdb5ecec14b6b96562de4cDianne Hackborn        BatteryEntry.startRequestQueue();
3832a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasani    }
3842a2daf960c43a2c97b1c6da430138e08e9caa54fAmith Yamasani
385f2819e0eada8af3835141857b5d499bca90774a6Jason Monk    private static List<BatterySipper> getFakeStats() {
386f2819e0eada8af3835141857b5d499bca90774a6Jason Monk        ArrayList<BatterySipper> stats = new ArrayList<>();
387f2819e0eada8af3835141857b5d499bca90774a6Jason Monk        float use = 5;
388f2819e0eada8af3835141857b5d499bca90774a6Jason Monk        for (DrainType type : DrainType.values()) {
389f2819e0eada8af3835141857b5d499bca90774a6Jason Monk            if (type == DrainType.APP) {
390f2819e0eada8af3835141857b5d499bca90774a6Jason Monk                continue;
391f2819e0eada8af3835141857b5d499bca90774a6Jason Monk            }
392f2819e0eada8af3835141857b5d499bca90774a6Jason Monk            stats.add(new BatterySipper(type, null, use));
393f2819e0eada8af3835141857b5d499bca90774a6Jason Monk            use += 5;
394f2819e0eada8af3835141857b5d499bca90774a6Jason Monk        }
395a627844fedb00c46eb206e2e88739e4d58cdde24Jason Monk        for (int i = 0; i < 100; i++) {
396a627844fedb00c46eb206e2e88739e4d58cdde24Jason Monk            stats.add(new BatterySipper(DrainType.APP,
397a627844fedb00c46eb206e2e88739e4d58cdde24Jason Monk                    new FakeUid(Process.FIRST_APPLICATION_UID + i), use));
398a627844fedb00c46eb206e2e88739e4d58cdde24Jason Monk        }
39982f30d2a41fe8283f377c16d6684b013ae2a4faeJason Monk        stats.add(new BatterySipper(DrainType.APP,
40082f30d2a41fe8283f377c16d6684b013ae2a4faeJason Monk                new FakeUid(0), use));
4014444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski
4024444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski        // Simulate dex2oat process.
4034444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski        BatterySipper sipper = new BatterySipper(DrainType.APP,
4044444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski                new FakeUid(UserHandle.getSharedAppGid(Process.FIRST_APPLICATION_UID)), 10.0f);
4054444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski        sipper.packageWithHighestDrain = "dex2oat";
4066880ec09cd95359d42007d3c76ac4b9905743de7Jason Monk        stats.add(sipper);
4074444fb85a9527c0506594894de00441d88a7fbc8Adam Lesinski
4088f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski        sipper = new BatterySipper(DrainType.APP,
4098f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                new FakeUid(UserHandle.getSharedAppGid(Process.FIRST_APPLICATION_UID + 1)), 10.0f);
4108f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski        sipper.packageWithHighestDrain = "dex2oat";
4118f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski        stats.add(sipper);
4128f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski
4138f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski        sipper = new BatterySipper(DrainType.APP,
4148f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski                new FakeUid(UserHandle.getSharedAppGid(Process.LOG_UID)), 9.0f);
4158f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski        stats.add(sipper);
4168f743471d5367935aea7663e362913e9b68b8e61Adam Lesinski
417f2819e0eada8af3835141857b5d499bca90774a6Jason Monk        return stats;
418f2819e0eada8af3835141857b5d499bca90774a6Jason Monk    }
419f2819e0eada8af3835141857b5d499bca90774a6Jason Monk
42078fd96a1c5dd7b03fa09d8b3116243cc9661c5e6Amith Yamasani    Handler mHandler = new Handler() {
42178fd96a1c5dd7b03fa09d8b3116243cc9661c5e6Amith Yamasani
42278fd96a1c5dd7b03fa09d8b3116243cc9661c5e6Amith Yamasani        @Override
42378fd96a1c5dd7b03fa09d8b3116243cc9661c5e6Amith Yamasani        public void handleMessage(Message msg) {
42478fd96a1c5dd7b03fa09d8b3116243cc9661c5e6Amith Yamasani            switch (msg.what) {
4257c80af410b09fa14b6fdb5ecec14b6b96562de4cDianne Hackborn                case BatteryEntry.MSG_UPDATE_NAME_ICON:
4267c80af410b09fa14b6fdb5ecec14b6b96562de4cDianne Hackborn                    BatteryEntry entry = (BatteryEntry) msg.obj;
427c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    PowerGaugePreference pgp =
42878fd96a1c5dd7b03fa09d8b3116243cc9661c5e6Amith Yamasani                            (PowerGaugePreference) findPreference(
4297c80af410b09fa14b6fdb5ecec14b6b96562de4cDianne Hackborn                                    Integer.toString(entry.sipper.uidObj.getUid()));
43078fd96a1c5dd7b03fa09d8b3116243cc9661c5e6Amith Yamasani                    if (pgp != null) {
43108c2f36c3a8a32cbe052848f15b28accfb9b5049Zoltan Szatmary-Ban                        final int userId = UserHandle.getUserId(entry.sipper.getUid());
43208c2f36c3a8a32cbe052848f15b28accfb9b5049Zoltan Szatmary-Ban                        final UserHandle userHandle = new UserHandle(userId);
4333aaf0eb457639b52228143b84d9624bf73d862eaZoltan Szatmary-Ban                        pgp.setIcon(mUm.getBadgedIconForUser(entry.getIcon(), userHandle));
4347c80af410b09fa14b6fdb5ecec14b6b96562de4cDianne Hackborn                        pgp.setTitle(entry.name);
435d589bafc4a5d791194371d0fb8382aebd9322190Jason Monk                        if (entry.sipper.drainType == DrainType.APP) {
436d589bafc4a5d791194371d0fb8382aebd9322190Jason Monk                            pgp.setContentDescription(entry.name);
437d589bafc4a5d791194371d0fb8382aebd9322190Jason Monk                        }
43878fd96a1c5dd7b03fa09d8b3116243cc9661c5e6Amith Yamasani                    }
43978fd96a1c5dd7b03fa09d8b3116243cc9661c5e6Amith Yamasani                    break;
4407c80af410b09fa14b6fdb5ecec14b6b96562de4cDianne Hackborn                case BatteryEntry.MSG_REPORT_FULLY_DRAWN:
4415334cf609f783218efd553466df4cdb4b1aadca8Amith Yamasani                    Activity activity = getActivity();
4425334cf609f783218efd553466df4cdb4b1aadca8Amith Yamasani                    if (activity != null) {
4435334cf609f783218efd553466df4cdb4b1aadca8Amith Yamasani                        activity.reportFullyDrawn();
4445334cf609f783218efd553466df4cdb4b1aadca8Amith Yamasani                    }
44515ab7758df616a27c28276ab97ddb2e2de6089f7Dianne Hackborn                    break;
44678fd96a1c5dd7b03fa09d8b3116243cc9661c5e6Amith Yamasani            }
44778fd96a1c5dd7b03fa09d8b3116243cc9661c5e6Amith Yamasani            super.handleMessage(msg);
44878fd96a1c5dd7b03fa09d8b3116243cc9661c5e6Amith Yamasani        }
44978fd96a1c5dd7b03fa09d8b3116243cc9661c5e6Amith Yamasani    };
4503069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk
4513069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk    private static class SummaryProvider implements SummaryLoader.SummaryProvider {
4523069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk        private final Context mContext;
4533069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk        private final SummaryLoader mLoader;
4543069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk
4553069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk        private SummaryProvider(Context context, SummaryLoader loader) {
4563069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk            mContext = context;
4573069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk            mLoader = loader;
4583069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk        }
4593069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk
4603069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk        @Override
4613069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk        public void setListening(boolean listening) {
4623069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk            if (listening) {
4633069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk                // TODO: Listen.
46427985e1f922eeb75da3214a7f88c63ac34dc4badJason Monk                BatteryInfo.getBatteryInfo(mContext, new BatteryInfo.Callback() {
4653069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk                    @Override
46627985e1f922eeb75da3214a7f88c63ac34dc4badJason Monk                    public void onBatteryInfoLoaded(BatteryInfo info) {
46727985e1f922eeb75da3214a7f88c63ac34dc4badJason Monk                        mLoader.setSummary(SummaryProvider.this, info.mChargeLabelString);
4683069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk                    }
46927985e1f922eeb75da3214a7f88c63ac34dc4badJason Monk                });
4703069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk            }
4713069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk        }
4723069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk    }
4733069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk
4743069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk    public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY
4753069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk            = new SummaryLoader.SummaryProviderFactory() {
4763069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk        @Override
4773069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk        public SummaryLoader.SummaryProvider createSummaryProvider(Activity activity,
4783069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk                                                                   SummaryLoader summaryLoader) {
4793069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk            return new SummaryProvider(activity, summaryLoader);
4803069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk        }
4813069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk    };
4821fd2958ad43433b774500e0cf7013d21013257adAmith Yamasani}
483