1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.fuelgauge; 18 19 import android.app.Activity; 20 import android.content.BroadcastReceiver; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.content.IntentFilter; 24 import android.os.BatteryStats; 25 import android.os.Bundle; 26 import android.os.Handler; 27 import android.os.Message; 28 import android.os.Parcel; 29 import android.preference.Preference; 30 import android.preference.PreferenceActivity; 31 import android.preference.PreferenceFragment; 32 import android.preference.PreferenceGroup; 33 import android.preference.PreferenceScreen; 34 import android.text.TextUtils; 35 import android.view.Menu; 36 import android.view.MenuInflater; 37 import android.view.MenuItem; 38 39 import com.android.internal.os.PowerProfile; 40 import com.android.settings.HelpUtils; 41 import com.android.settings.R; 42 43 import java.util.List; 44 45 /** 46 * Displays a list of apps and subsystems that consume power, ordered by how much power was 47 * consumed since the last time it was unplugged. 48 */ 49 public class PowerUsageSummary extends PreferenceFragment { 50 51 private static final boolean DEBUG = false; 52 53 private static final String TAG = "PowerUsageSummary"; 54 55 private static final String KEY_APP_LIST = "app_list"; 56 private static final String KEY_BATTERY_STATUS = "battery_status"; 57 58 private static final int MENU_STATS_TYPE = Menu.FIRST; 59 private static final int MENU_STATS_REFRESH = Menu.FIRST + 1; 60 private static final int MENU_HELP = Menu.FIRST + 2; 61 62 private PreferenceGroup mAppListGroup; 63 private Preference mBatteryStatusPref; 64 65 private int mStatsType = BatteryStats.STATS_SINCE_CHARGED; 66 67 private static final int MIN_POWER_THRESHOLD = 5; 68 private static final int MAX_ITEMS_TO_LIST = 10; 69 70 private BatteryStatsHelper mStatsHelper; 71 72 private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() { 73 74 @Override 75 public void onReceive(Context context, Intent intent) { 76 String action = intent.getAction(); 77 if (Intent.ACTION_BATTERY_CHANGED.equals(action)) { 78 String batteryLevel = com.android.settings.Utils.getBatteryPercentage(intent); 79 String batteryStatus = com.android.settings.Utils.getBatteryStatus(getResources(), 80 intent); 81 String batterySummary = context.getResources().getString( 82 R.string.power_usage_level_and_status, batteryLevel, batteryStatus); 83 mBatteryStatusPref.setTitle(batterySummary); 84 mStatsHelper.clearStats(); 85 refreshStats(); 86 } 87 } 88 }; 89 90 @Override 91 public void onAttach(Activity activity) { 92 super.onAttach(activity); 93 mStatsHelper = new BatteryStatsHelper(activity, mHandler); 94 } 95 96 @Override 97 public void onCreate(Bundle icicle) { 98 super.onCreate(icicle); 99 mStatsHelper.create(icicle); 100 101 addPreferencesFromResource(R.xml.power_usage_summary); 102 mAppListGroup = (PreferenceGroup) findPreference(KEY_APP_LIST); 103 mBatteryStatusPref = mAppListGroup.findPreference(KEY_BATTERY_STATUS); 104 setHasOptionsMenu(true); 105 } 106 107 @Override 108 public void onResume() { 109 super.onResume(); 110 getActivity().registerReceiver(mBatteryInfoReceiver, 111 new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); 112 refreshStats(); 113 } 114 115 @Override 116 public void onPause() { 117 mStatsHelper.pause(); 118 mHandler.removeMessages(BatteryStatsHelper.MSG_UPDATE_NAME_ICON); 119 getActivity().unregisterReceiver(mBatteryInfoReceiver); 120 super.onPause(); 121 } 122 123 @Override 124 public void onDestroy() { 125 super.onDestroy(); 126 mStatsHelper.destroy(); 127 } 128 129 @Override 130 public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { 131 if (preference instanceof BatteryHistoryPreference) { 132 Parcel hist = Parcel.obtain(); 133 mStatsHelper.getStats().writeToParcelWithoutUids(hist, 0); 134 byte[] histData = hist.marshall(); 135 Bundle args = new Bundle(); 136 args.putByteArray(BatteryHistoryDetail.EXTRA_STATS, histData); 137 PreferenceActivity pa = (PreferenceActivity)getActivity(); 138 pa.startPreferencePanel(BatteryHistoryDetail.class.getName(), args, 139 R.string.history_details_title, null, null, 0); 140 return super.onPreferenceTreeClick(preferenceScreen, preference); 141 } 142 if (!(preference instanceof PowerGaugePreference)) { 143 return false; 144 } 145 PowerGaugePreference pgp = (PowerGaugePreference) preference; 146 BatterySipper sipper = pgp.getInfo(); 147 mStatsHelper.startBatteryDetailPage((PreferenceActivity) getActivity(), sipper, true); 148 return super.onPreferenceTreeClick(preferenceScreen, preference); 149 } 150 151 @Override 152 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 153 if (DEBUG) { 154 menu.add(0, MENU_STATS_TYPE, 0, R.string.menu_stats_total) 155 .setIcon(com.android.internal.R.drawable.ic_menu_info_details) 156 .setAlphabeticShortcut('t'); 157 } 158 MenuItem refresh = menu.add(0, MENU_STATS_REFRESH, 0, R.string.menu_stats_refresh) 159 .setIcon(R.drawable.ic_menu_refresh_holo_dark) 160 .setAlphabeticShortcut('r'); 161 refresh.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | 162 MenuItem.SHOW_AS_ACTION_WITH_TEXT); 163 164 String helpUrl; 165 if (!TextUtils.isEmpty(helpUrl = getResources().getString(R.string.help_url_battery))) { 166 final MenuItem help = menu.add(0, MENU_HELP, 0, R.string.help_label); 167 HelpUtils.prepareHelpMenuItem(getActivity(), help, helpUrl); 168 } 169 } 170 171 @Override 172 public boolean onOptionsItemSelected(MenuItem item) { 173 switch (item.getItemId()) { 174 case MENU_STATS_TYPE: 175 if (mStatsType == BatteryStats.STATS_SINCE_CHARGED) { 176 mStatsType = BatteryStats.STATS_SINCE_UNPLUGGED; 177 } else { 178 mStatsType = BatteryStats.STATS_SINCE_CHARGED; 179 } 180 refreshStats(); 181 return true; 182 case MENU_STATS_REFRESH: 183 mStatsHelper.clearStats(); 184 refreshStats(); 185 return true; 186 default: 187 return false; 188 } 189 } 190 191 private void addNotAvailableMessage() { 192 Preference notAvailable = new Preference(getActivity()); 193 notAvailable.setTitle(R.string.power_usage_not_available); 194 mAppListGroup.addPreference(notAvailable); 195 } 196 197 private void refreshStats() { 198 mAppListGroup.removeAll(); 199 mAppListGroup.setOrderingAsAdded(false); 200 201 mBatteryStatusPref.setOrder(-2); 202 mAppListGroup.addPreference(mBatteryStatusPref); 203 BatteryHistoryPreference hist = new BatteryHistoryPreference( 204 getActivity(), mStatsHelper.getStats()); 205 hist.setOrder(-1); 206 mAppListGroup.addPreference(hist); 207 208 if (mStatsHelper.getPowerProfile().getAveragePower( 209 PowerProfile.POWER_SCREEN_FULL) < 10) { 210 addNotAvailableMessage(); 211 return; 212 } 213 mStatsHelper.refreshStats(false); 214 List<BatterySipper> usageList = mStatsHelper.getUsageList(); 215 for (BatterySipper sipper : usageList) { 216 if (sipper.getSortValue() < MIN_POWER_THRESHOLD) continue; 217 final double percentOfTotal = 218 ((sipper.getSortValue() / mStatsHelper.getTotalPower()) * 100); 219 if (percentOfTotal < 1) continue; 220 PowerGaugePreference pref = 221 new PowerGaugePreference(getActivity(), sipper.getIcon(), sipper); 222 final double percentOfMax = 223 (sipper.getSortValue() * 100) / mStatsHelper.getMaxPower(); 224 sipper.percent = percentOfTotal; 225 pref.setTitle(sipper.name); 226 pref.setOrder(Integer.MAX_VALUE - (int) sipper.getSortValue()); // Invert the order 227 pref.setPercent(percentOfMax, percentOfTotal); 228 if (sipper.uidObj != null) { 229 pref.setKey(Integer.toString(sipper.uidObj.getUid())); 230 } 231 mAppListGroup.addPreference(pref); 232 if (mAppListGroup.getPreferenceCount() > (MAX_ITEMS_TO_LIST+1)) break; 233 } 234 } 235 236 Handler mHandler = new Handler() { 237 238 @Override 239 public void handleMessage(Message msg) { 240 switch (msg.what) { 241 case BatteryStatsHelper.MSG_UPDATE_NAME_ICON: 242 BatterySipper bs = (BatterySipper) msg.obj; 243 PowerGaugePreference pgp = 244 (PowerGaugePreference) findPreference( 245 Integer.toString(bs.uidObj.getUid())); 246 if (pgp != null) { 247 pgp.setIcon(bs.icon); 248 pgp.setTitle(bs.name); 249 } 250 break; 251 case BatteryStatsHelper.MSG_REPORT_FULLY_DRAWN: 252 Activity activity = getActivity(); 253 if (activity != null) { 254 activity.reportFullyDrawn(); 255 } 256 break; 257 } 258 super.handleMessage(msg); 259 } 260 }; 261 } 262