Home | History | Annotate | Download | only in fuelgauge
      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