FileDocCategorySizeDatePackage
BatteryHistory.javaAPI DocAndroid 1.5 API32287Wed May 06 22:42:48 BST 2009com.android.settings.battery_history

BatteryHistory

public class BatteryHistory extends android.app.Activity implements android.view.View.OnClickListener, android.widget.AdapterView.OnItemSelectedListener

Fields Summary
private static final String
TAG
private static final int
SECONDS_PER_MINUTE
private static final int
SECONDS_PER_HOUR
private static final int
SECONDS_PER_DAY
private static final int
CPU_USAGE
private static final int
NETWORK_USAGE
private static final int
GPS_USAGE
private static final int
SENSOR_USAGE
private static final int
WAKELOCK_USAGE
private static final int
MISC_USAGE
private static final int
UNPLUGGED
private static final int
CURRENT
private static final int
TOTAL
private android.os.BatteryStats
mStats
private int
mWhich
private int
mType
private GraphableButton[]
mButtons
com.android.internal.app.IBatteryStats
mBatteryInfo
private List
mCpuUsage
private List
mNetworkUsage
private List
mSensorUsage
private List
mGpsUsage
private List
mWakelockUsage
private List
mMiscUsage
private boolean
mHaveCpuUsage
private boolean
mHaveNetworkUsage
private boolean
mHaveSensorUsage
private boolean
mHaveWakelockUsage
private boolean
mHaveMiscUsage
private android.widget.LinearLayout
mGraphLayout
private android.widget.LinearLayout
mTextLayout
private android.widget.TextView
mMessageText
private android.widget.TextView
mDetailsText
private android.widget.Button
mDetailsBackButton
private android.widget.Spinner
mTypeSpinner
private android.widget.Spinner
mWhichSpinner
private boolean
mDetailsShown
private final StringBuilder
mFormatBuilder
private final Formatter
mFormatter
Constructors Summary
Methods Summary
private voidcollectStatistics()

        if (mType == CPU_USAGE) {
            if (!mHaveCpuUsage) {
                mHaveCpuUsage = true;
                processCpuUsage();
            }
        }
        if (mType == NETWORK_USAGE) {
            if (!mHaveNetworkUsage) {
                mHaveNetworkUsage = true;
                processNetworkUsage();
            }
        }
        if (mType == GPS_USAGE || mType == SENSOR_USAGE) {
            if (!mHaveSensorUsage) {
                mHaveSensorUsage = true;
                processSensorUsage();
            }
        }
        if (mType == WAKELOCK_USAGE) {
            if (!mHaveWakelockUsage) {
                mHaveWakelockUsage = true;
                processWakelockUsage();
            }
        }
        if (mType == MISC_USAGE) {
            if (!mHaveMiscUsage) {
                mHaveMiscUsage = true;
                processMiscUsage();
            }
        }
    
private voiddisplayGraph()

        Log.i(TAG, "displayGraph");

        collectStatistics();
        
        // Hide the UI and selectively enable it below
        mMessageText.setVisibility(View.GONE);
        for (int i = 0; i < mButtons.length; i++) {
            mButtons[i].setVisibility(View.INVISIBLE);
        }
        
        double maxValue = -Double.MAX_VALUE;
        
        List<? extends Graphable> records = getGraphRecords();
        for (Graphable g : records) {
            double[] values = g.getValues();
            maxValue = Math.max(maxValue, values[values.length - 1]);
            maxValue = Math.max(maxValue, g.getMaxValue());
        }
        
        int[] colors = new int[2];
        colors[0] = 0xff0000ff;
        colors[1] = 0xffff0000;
        
        for (int i = 0; i < mButtons.length; i++) {
            mButtons[i].setVisibility(View.INVISIBLE);
        }
        
        int numRecords = Math.min(records.size(), mButtons.length);
        if (numRecords == 0) {
             mMessageText.setVisibility(View.VISIBLE);
             mMessageText.setText(R.string.battery_history_no_data);
        } else {
            for (int i = 0; i < numRecords; i++) {
                Graphable r = records.get(i);           

                mButtons[i].setText(r.getLabel());
                mButtons[i].setValues(r.getValues(), maxValue);
                mButtons[i].setVisibility(View.VISIBLE);
            }
        }
    
private final java.lang.StringformatRatio(long num, long den)

    
           
        if (den == 0L) {
            return "---%";
        }
        float perc = ((float)num) / ((float)den) * 100;
        mFormatBuilder.setLength(0);
        mFormatter.format("%.1f%%", perc);
        return mFormatBuilder.toString();
    
voidformatTime(double millis, java.lang.StringBuilder sb)

        int seconds = (int) Math.floor(millis / 1000);
        
        int days = 0, hours = 0, minutes = 0;
        if (seconds > SECONDS_PER_DAY) {
            days = seconds / SECONDS_PER_DAY;
            seconds -= days * SECONDS_PER_DAY;
        }
        if (seconds > SECONDS_PER_HOUR) {
            hours = seconds / SECONDS_PER_HOUR;
            seconds -= hours * SECONDS_PER_HOUR;
        }
        if (seconds > SECONDS_PER_MINUTE) {
            minutes = seconds / SECONDS_PER_MINUTE;
            seconds -= minutes * SECONDS_PER_MINUTE;
        }
        if (days > 0) {
            sb.append(getString(R.string.battery_history_days, days, hours, minutes, seconds));
        } else if (hours > 0) {
            sb.append(getString(R.string.battery_history_hours, hours, minutes, seconds));
        } else if (minutes > 0) { 
            sb.append(getString(R.string.battery_history_minutes, minutes, seconds));
        } else {
            sb.append(getString(R.string.battery_history_seconds, seconds));
        }
    
private java.util.ListgetGraphRecords()

        switch (mType) {
            case CPU_USAGE: return mCpuUsage;
            case NETWORK_USAGE : return mNetworkUsage;
            case SENSOR_USAGE: return mSensorUsage;
            case GPS_USAGE: return mGpsUsage;
            case WAKELOCK_USAGE: return mWakelockUsage;
            case MISC_USAGE: return mMiscUsage;
            default:
                return (List<? extends Graphable>) null; // TODO
        }
    
private static java.lang.StringgetLabel(java.lang.String packageName, android.content.pm.PackageManager pm)

    
           
        try {
            ApplicationInfo ai = pm.getApplicationInfo(packageName, 0);
            CharSequence label = ai.loadLabel(pm);
            if (label != null) {
                return label.toString();
            }
        } catch (NameNotFoundException e) {
            return packageName;
        }
        
        return "";
    
private voidhideDetails()

        mTextLayout.setVisibility(View.GONE);
        mGraphLayout.setVisibility(View.VISIBLE);
        mDetailsShown = false;
    
private voidload()

        try {
            byte[] data = mBatteryInfo.getStatistics();
            Parcel parcel = Parcel.obtain();
            //Log.i(TAG, "Got data: " + data.length + " bytes");
            parcel.unmarshall(data, 0, data.length);
            parcel.setDataPosition(0);
            mStats = com.android.internal.os.BatteryStatsImpl.CREATOR
                    .createFromParcel(parcel);
            //Log.i(TAG, "RECEIVED BATTERY INFO:");
            //mStats.dumpLocked(new LogPrinter(Log.INFO, TAG));
            
            mHaveCpuUsage =  mHaveNetworkUsage =  mHaveSensorUsage
                    = mHaveWakelockUsage = mHaveMiscUsage = false;
        } catch (RemoteException e) {
            Log.e(TAG, "RemoteException:", e);
        }
    
public voidonClick(android.view.View v)

        if (v == mDetailsBackButton) {
            hideDetails();
            return;
        }
        
        int id = ((Integer) v.getTag()).intValue();
        showDetails(id);
    
public voidonCreate(android.os.Bundle icicle)

        super.onCreate(icicle);
        Log.i(TAG, "onCreate");
        
        setContentView(R.layout.battery_history);
        
        mStats = (BatteryStats)getLastNonConfigurationInstance();
        if (icicle != null) {
            if (mStats == null) {
                mStats = (BatteryStats)icicle.getParcelable("stats");
            }
            mType = icicle.getInt("type");
            mWhich = icicle.getInt("which");
        }
        
        mGraphLayout = (LinearLayout) findViewById(R.id.graphLayout);
        mTextLayout = (LinearLayout) findViewById(R.id.textLayout);
        mDetailsText = (TextView) findViewById(R.id.detailsText);
        mMessageText = (TextView) findViewById(R.id.messageText);
        
        mTypeSpinner = (Spinner) findViewById(R.id.typeSpinner);
        mTypeSpinner.setSelection(mType);
        mTypeSpinner.setOnItemSelectedListener(this);
        
        mWhichSpinner = (Spinner) findViewById(R.id.whichSpinner);
        mWhichSpinner.setOnItemSelectedListener(this);
        mWhichSpinner.setEnabled(true);
        
        mButtons = new GraphableButton[8];
        mButtons[0] = (GraphableButton) findViewById(R.id.button0);
        mButtons[1] = (GraphableButton) findViewById(R.id.button1);
        mButtons[2] = (GraphableButton) findViewById(R.id.button2);
        mButtons[3] = (GraphableButton) findViewById(R.id.button3);
        mButtons[4] = (GraphableButton) findViewById(R.id.button4);
        mButtons[5] = (GraphableButton) findViewById(R.id.button5);
        mButtons[6] = (GraphableButton) findViewById(R.id.button6);
        mButtons[7] = (GraphableButton) findViewById(R.id.button7);
        
        for (int i = 0; i < mButtons.length; i++) {
            mButtons[i].setTag(i);
            mButtons[i].setOnClickListener(this);
        }
        
        mBatteryInfo = IBatteryStats.Stub.asInterface(
                ServiceManager.getService("batteryinfo"));
        
        if (mStats == null) {
            load();
        }
        displayGraph();
    
public voidonItemSelected(android.widget.AdapterView parent, android.view.View view, int position, long id)

        int oldWhich = mWhich;
        
        if (parent.equals(mTypeSpinner)) {
            mType = position;
        } else if (parent.equals(mWhichSpinner)) {
            switch (position) {
                case UNPLUGGED:
                    mWhich = BatteryStats.STATS_UNPLUGGED;
                    break;
                case CURRENT:
                    mWhich = BatteryStats.STATS_CURRENT;
                    break;
                case TOTAL:
                    mWhich = BatteryStats.STATS_TOTAL;
                    break;
            }
        }
        
        if (oldWhich != mWhich) {
            mHaveCpuUsage =  mHaveNetworkUsage =  mHaveSensorUsage
                    = mHaveWakelockUsage = mHaveMiscUsage = false;
        }
        
        displayGraph();
    
public booleanonKeyDown(int keyCode, android.view.KeyEvent event)

        if (keyCode == KeyEvent.KEYCODE_BACK && mDetailsShown) {
            hideDetails();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    
public voidonNothingSelected(android.widget.AdapterView parent)

        // Do nothing
    
public java.lang.ObjectonRetainNonConfigurationInstance()

        BatteryStats stats = mStats;
        mStats = null;
        return stats;
    
protected voidonSaveInstanceState(android.os.Bundle outState)

        super.onSaveInstanceState(outState);
        if (mStats != null) {
            outState.putParcelable("stats", mStats);
        }
        outState.putInt("type", mType);
        outState.putInt("which", mWhich);
    
private voidprocessCpuUsage()

        mCpuUsage.clear();
        
        long uSecTime = SystemClock.uptimeMillis() * 1000;
        final long uSecNow = mStats.computeBatteryUptime(uSecTime, mWhich) / 1000;
        
        SparseArray<? extends Uid> uidStats = mStats.getUidStats();
        final int NU = uidStats.size();
        for (int iu = 0; iu < NU; iu++) {
            Uid u = uidStats.valueAt(iu);

            Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
            if (processStats.size() > 0) {
                for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
                        : processStats.entrySet()) {

                    Uid.Proc ps = ent.getValue();
                    long userTime = ps.getUserTime(mWhich);
                    long systemTime = ps.getSystemTime(mWhich);
                    long starts = ps.getStarts(mWhich);

                    if (userTime != 0 || systemTime != 0) {
                        mCpuUsage.add(new CpuUsage(u.getUid(), ent.getKey(),
                                userTime, systemTime, starts, uSecNow));
                    }
                }
            }
        }
        Collections.sort(mCpuUsage);
    
private voidprocessMiscUsage()

        mMiscUsage.clear();
        
        long rawRealtime = SystemClock.elapsedRealtime() * 1000;
        final long batteryRealtime = mStats.getBatteryRealtime(rawRealtime);
        final long whichRealtime = mStats.computeBatteryRealtime(rawRealtime, mWhich) / 1000;
        
        long time = mStats.computeBatteryUptime(SystemClock.uptimeMillis() * 1000, mWhich) / 1000;
        if (time > 0) {
            mMiscUsage.add(new MiscUsage(getString(
                    R.string.battery_history_awake_label)
                    + " (" + formatRatio(time, whichRealtime) + ")",
                    R.string.battery_history_awake,
                    time, whichRealtime)); 
        }
        
        time = mStats.getScreenOnTime(batteryRealtime, mWhich) / 1000;
        if (time > 0) {
            mMiscUsage.add(new MiscUsage(getString(
                    R.string.battery_history_screen_on_label)
                    + " (" + formatRatio(time, whichRealtime) + ")",
                    R.string.battery_history_screen_on,
                    time, whichRealtime)); 
        }
        
        time = mStats.getPhoneOnTime(batteryRealtime, mWhich) / 1000;
        if (time > 0) {
            mMiscUsage.add(new MiscUsage(getString(
                    R.string.battery_history_phone_on_label)
                    + " (" + formatRatio(time, whichRealtime) + ")",
                    R.string.battery_history_phone_on,
                    time, whichRealtime)); 
        }
        
        time = mStats.getWifiOnTime(batteryRealtime, mWhich) / 1000;
        if (time > 0) {
            mMiscUsage.add(new MiscUsage("Wifi On ("
                    + formatRatio(time, whichRealtime) + ")",
                    "Time spent with Wifi on:",
                    time, whichRealtime)); 
        }
        
        time = mStats.getWifiRunningTime(batteryRealtime, mWhich) / 1000;
        if (time > 0) {
            mMiscUsage.add(new MiscUsage("Wifi Running ("
                    + formatRatio(time, whichRealtime) + ")",
                    "Time spent with Wifi running:",
                    time, whichRealtime)); 
        }
        
        time = mStats.getBluetoothOnTime(batteryRealtime, mWhich) / 1000;
        if (time > 0) {
            mMiscUsage.add(new MiscUsage("Bluetooth On ("
                    + formatRatio(time, whichRealtime) + ")",
                    "Time spent with Bluetooth on:",
                    time, whichRealtime)); 
        }
        
        Collections.sort(mMiscUsage);
    
private voidprocessNetworkUsage()

        mNetworkUsage.clear();
        
        SparseArray<? extends Uid> uidStats = mStats.getUidStats();
        final int NU = uidStats.size();
        for (int iu = 0; iu < NU; iu++) {
            Uid u = uidStats.valueAt(iu);
            
            long received = u.getTcpBytesReceived(mWhich);
            long sent = u.getTcpBytesSent(mWhich);
            if (received + sent > 0) {
                mNetworkUsage.add(new NetworkUsage(u.getUid(), received, sent));
            }
        }
        Collections.sort(mNetworkUsage);
    
private voidprocessSensorUsage()

        mGpsUsage.clear();
        mSensorUsage.clear();
        
        long uSecTime = SystemClock.elapsedRealtime() * 1000;
        final long uSecNow = mStats.computeBatteryRealtime(uSecTime, mWhich) / 1000;
        
        SparseArray<? extends Uid> uidStats = mStats.getUidStats();
        final int NU = uidStats.size();
        for (int iu = 0; iu < NU; iu++) {
            Uid u = uidStats.valueAt(iu);
            int uid = u.getUid();
            
            Map<Integer, ? extends BatteryStats.Uid.Sensor> sensorStats = u.getSensorStats();
            long timeGps = 0;
            int countGps = 0;
            long timeOther = 0;
            int countOther = 0;
            if (sensorStats.size() > 0) {
                for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> ent
                        : sensorStats.entrySet()) {

                    Uid.Sensor se = ent.getValue();
                    int handle = se.getHandle();
                    Timer timer = se.getSensorTime();
                    if (timer != null) {
                        // Convert from microseconds to milliseconds with rounding
                        long totalTime = (timer.getTotalTime(uSecNow, mWhich) + 500) / 1000;
                        int count = timer.getCount(mWhich);
                        if (handle == BatteryStats.Uid.Sensor.GPS) {
                            timeGps += totalTime;
                            countGps += count;
                        } else {
                            timeOther += totalTime;
                            countOther += count;
                        }
                    }
                }
            }
            
            if (timeGps > 0) {
                mGpsUsage.add(new SensorUsage(uid, timeGps, countGps, uSecNow));
            }
            if (timeOther > 0) {
                mSensorUsage.add(new SensorUsage(uid, timeOther, countOther, uSecNow));
            }
        }
        
        Collections.sort(mGpsUsage);
        Collections.sort(mSensorUsage);
    
private voidprocessWakelockUsage()

        mWakelockUsage.clear();
        
        long uSecTime = SystemClock.elapsedRealtime() * 1000;
        final long uSecNow = mStats.computeBatteryRealtime(uSecTime, mWhich) / 1000;
        
        SparseArray<? extends Uid> uidStats = mStats.getUidStats();
        final int NU = uidStats.size();
        for (int iu = 0; iu < NU; iu++) {
            Uid u = uidStats.valueAt(iu);
            int uid = u.getUid();
            
            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelockStats = u.getWakelockStats();
            long time = 0;
            int count = 0;
            if (wakelockStats.size() > 0) {
                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
                        : wakelockStats.entrySet()) {

                    Uid.Wakelock wl = ent.getValue();
                    Timer timer = wl.getWakeTime(BatteryStats.WAKE_TYPE_PARTIAL);
                    if (timer != null) {
                        // Convert from microseconds to milliseconds with rounding
                        time += (timer.getTotalTime(uSecNow, mWhich) + 500) / 1000;
                        count += timer.getCount(mWhich);
                    }
                }
            }
            
            if (time > 0) {
                mWakelockUsage.add(new WakelockUsage(uid, time, count, uSecNow));
            }
        }
        
        Collections.sort(mWakelockUsage);
    
private voidshowDetails(int id)

        mGraphLayout.setVisibility(View.GONE);
        mTextLayout.setVisibility(View.VISIBLE);
            
        StringBuilder info = new StringBuilder();
        List<? extends Graphable> records = getGraphRecords();
        if (id < records.size()) {
            Graphable record = records.get(id);
            record.getInfo(info);
        } else {
            info.append(getString(R.string.battery_history_details_for, id));
        }
        mDetailsText.setText(info.toString());
        mDetailsShown = true;