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