Home | History | Annotate | Download | only in os
      1 /*
      2  * Copyright (C) 2008 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 android.os;
     18 
     19 import java.io.PrintWriter;
     20 import java.util.ArrayList;
     21 import java.util.Collections;
     22 import java.util.Comparator;
     23 import java.util.Formatter;
     24 import java.util.List;
     25 import java.util.Map;
     26 
     27 import android.content.pm.ApplicationInfo;
     28 import android.telephony.SignalStrength;
     29 import android.util.Log;
     30 import android.util.Printer;
     31 import android.util.Slog;
     32 import android.util.SparseArray;
     33 import android.util.TimeUtils;
     34 
     35 /**
     36  * A class providing access to battery usage statistics, including information on
     37  * wakelocks, processes, packages, and services.  All times are represented in microseconds
     38  * except where indicated otherwise.
     39  * @hide
     40  */
     41 public abstract class BatteryStats implements Parcelable {
     42 
     43     private static final boolean LOCAL_LOGV = false;
     44 
     45     /**
     46      * A constant indicating a partial wake lock timer.
     47      */
     48     public static final int WAKE_TYPE_PARTIAL = 0;
     49 
     50     /**
     51      * A constant indicating a full wake lock timer.
     52      */
     53     public static final int WAKE_TYPE_FULL = 1;
     54 
     55     /**
     56      * A constant indicating a window wake lock timer.
     57      */
     58     public static final int WAKE_TYPE_WINDOW = 2;
     59 
     60     /**
     61      * A constant indicating a sensor timer.
     62      */
     63     public static final int SENSOR = 3;
     64 
     65     /**
     66      * A constant indicating a a wifi running timer
     67      */
     68     public static final int WIFI_RUNNING = 4;
     69 
     70     /**
     71      * A constant indicating a full wifi lock timer
     72      */
     73     public static final int FULL_WIFI_LOCK = 5;
     74 
     75     /**
     76      * A constant indicating a wifi scan
     77      */
     78     public static final int WIFI_SCAN = 6;
     79 
     80      /**
     81       * A constant indicating a wifi multicast timer
     82       */
     83      public static final int WIFI_MULTICAST_ENABLED = 7;
     84 
     85     /**
     86      * A constant indicating an audio turn on timer
     87      */
     88     public static final int AUDIO_TURNED_ON = 7;
     89 
     90     /**
     91      * A constant indicating a video turn on timer
     92      */
     93     public static final int VIDEO_TURNED_ON = 8;
     94 
     95     /**
     96      * A constant indicating a vibrator on timer
     97      */
     98     public static final int VIBRATOR_ON = 9;
     99 
    100     /**
    101      * Include all of the data in the stats, including previously saved data.
    102      */
    103     public static final int STATS_SINCE_CHARGED = 0;
    104 
    105     /**
    106      * Include only the last run in the stats.
    107      */
    108     public static final int STATS_LAST = 1;
    109 
    110     /**
    111      * Include only the current run in the stats.
    112      */
    113     public static final int STATS_CURRENT = 2;
    114 
    115     /**
    116      * Include only the run since the last time the device was unplugged in the stats.
    117      */
    118     public static final int STATS_SINCE_UNPLUGGED = 3;
    119 
    120     // NOTE: Update this list if you add/change any stats above.
    121     // These characters are supposed to represent "total", "last", "current",
    122     // and "unplugged". They were shortened for efficiency sake.
    123     private static final String[] STAT_NAMES = { "t", "l", "c", "u" };
    124 
    125     /**
    126      * Bump the version on this if the checkin format changes.
    127      */
    128     private static final int BATTERY_STATS_CHECKIN_VERSION = 5;
    129 
    130     private static final long BYTES_PER_KB = 1024;
    131     private static final long BYTES_PER_MB = 1048576; // 1024^2
    132     private static final long BYTES_PER_GB = 1073741824; //1024^3
    133 
    134 
    135     private static final String UID_DATA = "uid";
    136     private static final String APK_DATA = "apk";
    137     private static final String PROCESS_DATA = "pr";
    138     private static final String SENSOR_DATA = "sr";
    139     private static final String VIBRATOR_DATA = "vib";
    140     private static final String WAKELOCK_DATA = "wl";
    141     private static final String KERNEL_WAKELOCK_DATA = "kwl";
    142     private static final String NETWORK_DATA = "nt";
    143     private static final String USER_ACTIVITY_DATA = "ua";
    144     private static final String BATTERY_DATA = "bt";
    145     private static final String BATTERY_DISCHARGE_DATA = "dc";
    146     private static final String BATTERY_LEVEL_DATA = "lv";
    147     private static final String WIFI_DATA = "wfl";
    148     private static final String MISC_DATA = "m";
    149     private static final String SCREEN_BRIGHTNESS_DATA = "br";
    150     private static final String SIGNAL_STRENGTH_TIME_DATA = "sgt";
    151     private static final String SIGNAL_SCANNING_TIME_DATA = "sst";
    152     private static final String SIGNAL_STRENGTH_COUNT_DATA = "sgc";
    153     private static final String DATA_CONNECTION_TIME_DATA = "dct";
    154     private static final String DATA_CONNECTION_COUNT_DATA = "dcc";
    155 
    156     private final StringBuilder mFormatBuilder = new StringBuilder(32);
    157     private final Formatter mFormatter = new Formatter(mFormatBuilder);
    158 
    159     /**
    160      * State for keeping track of counting information.
    161      */
    162     public static abstract class Counter {
    163 
    164         /**
    165          * Returns the count associated with this Counter for the
    166          * selected type of statistics.
    167          *
    168          * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT
    169          */
    170         public abstract int getCountLocked(int which);
    171 
    172         /**
    173          * Temporary for debugging.
    174          */
    175         public abstract void logState(Printer pw, String prefix);
    176     }
    177 
    178     /**
    179      * State for keeping track of timing information.
    180      */
    181     public static abstract class Timer {
    182 
    183         /**
    184          * Returns the count associated with this Timer for the
    185          * selected type of statistics.
    186          *
    187          * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT
    188          */
    189         public abstract int getCountLocked(int which);
    190 
    191         /**
    192          * Returns the total time in microseconds associated with this Timer for the
    193          * selected type of statistics.
    194          *
    195          * @param batteryRealtime system realtime on  battery in microseconds
    196          * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT
    197          * @return a time in microseconds
    198          */
    199         public abstract long getTotalTimeLocked(long batteryRealtime, int which);
    200 
    201         /**
    202          * Temporary for debugging.
    203          */
    204         public abstract void logState(Printer pw, String prefix);
    205     }
    206 
    207     /**
    208      * The statistics associated with a particular uid.
    209      */
    210     public static abstract class Uid {
    211 
    212         /**
    213          * Returns a mapping containing wakelock statistics.
    214          *
    215          * @return a Map from Strings to Uid.Wakelock objects.
    216          */
    217         public abstract Map<String, ? extends Wakelock> getWakelockStats();
    218 
    219         /**
    220          * The statistics associated with a particular wake lock.
    221          */
    222         public static abstract class Wakelock {
    223             public abstract Timer getWakeTime(int type);
    224         }
    225 
    226         /**
    227          * Returns a mapping containing sensor statistics.
    228          *
    229          * @return a Map from Integer sensor ids to Uid.Sensor objects.
    230          */
    231         public abstract Map<Integer, ? extends Sensor> getSensorStats();
    232 
    233         /**
    234          * Returns a mapping containing active process data.
    235          */
    236         public abstract SparseArray<? extends Pid> getPidStats();
    237 
    238         /**
    239          * Returns a mapping containing process statistics.
    240          *
    241          * @return a Map from Strings to Uid.Proc objects.
    242          */
    243         public abstract Map<String, ? extends Proc> getProcessStats();
    244 
    245         /**
    246          * Returns a mapping containing package statistics.
    247          *
    248          * @return a Map from Strings to Uid.Pkg objects.
    249          */
    250         public abstract Map<String, ? extends Pkg> getPackageStats();
    251 
    252         /**
    253          * {@hide}
    254          */
    255         public abstract int getUid();
    256 
    257         /**
    258          * {@hide}
    259          */
    260         public abstract long getTcpBytesReceived(int which);
    261 
    262         /**
    263          * {@hide}
    264          */
    265         public abstract long getTcpBytesSent(int which);
    266 
    267         public abstract void noteWifiRunningLocked();
    268         public abstract void noteWifiStoppedLocked();
    269         public abstract void noteFullWifiLockAcquiredLocked();
    270         public abstract void noteFullWifiLockReleasedLocked();
    271         public abstract void noteWifiScanStartedLocked();
    272         public abstract void noteWifiScanStoppedLocked();
    273         public abstract void noteWifiMulticastEnabledLocked();
    274         public abstract void noteWifiMulticastDisabledLocked();
    275         public abstract void noteAudioTurnedOnLocked();
    276         public abstract void noteAudioTurnedOffLocked();
    277         public abstract void noteVideoTurnedOnLocked();
    278         public abstract void noteVideoTurnedOffLocked();
    279         public abstract long getWifiRunningTime(long batteryRealtime, int which);
    280         public abstract long getFullWifiLockTime(long batteryRealtime, int which);
    281         public abstract long getWifiScanTime(long batteryRealtime, int which);
    282         public abstract long getWifiMulticastTime(long batteryRealtime,
    283                                                   int which);
    284         public abstract long getAudioTurnedOnTime(long batteryRealtime, int which);
    285         public abstract long getVideoTurnedOnTime(long batteryRealtime, int which);
    286         public abstract Timer getVibratorOnTimer();
    287 
    288         /**
    289          * Note that these must match the constants in android.os.PowerManager.
    290          * Also, if the user activity types change, the BatteryStatsImpl.VERSION must
    291          * also be bumped.
    292          */
    293         static final String[] USER_ACTIVITY_TYPES = {
    294             "other", "button", "touch"
    295         };
    296 
    297         public static final int NUM_USER_ACTIVITY_TYPES = 3;
    298 
    299         public abstract void noteUserActivityLocked(int type);
    300         public abstract boolean hasUserActivity();
    301         public abstract int getUserActivityCount(int type, int which);
    302 
    303         public static abstract class Sensor {
    304             /*
    305              * FIXME: it's not correct to use this magic value because it
    306              * could clash with a sensor handle (which are defined by
    307              * the sensor HAL, and therefore out of our control
    308              */
    309             // Magic sensor number for the GPS.
    310             public static final int GPS = -10000;
    311 
    312             public abstract int getHandle();
    313 
    314             public abstract Timer getSensorTime();
    315         }
    316 
    317         public class Pid {
    318             public long mWakeSum;
    319             public long mWakeStart;
    320         }
    321 
    322         /**
    323          * The statistics associated with a particular process.
    324          */
    325         public static abstract class Proc {
    326 
    327             public static class ExcessivePower {
    328                 public static final int TYPE_WAKE = 1;
    329                 public static final int TYPE_CPU = 2;
    330 
    331                 public int type;
    332                 public long overTime;
    333                 public long usedTime;
    334             }
    335 
    336             /**
    337              * Returns the total time (in 1/100 sec) spent executing in user code.
    338              *
    339              * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
    340              */
    341             public abstract long getUserTime(int which);
    342 
    343             /**
    344              * Returns the total time (in 1/100 sec) spent executing in system code.
    345              *
    346              * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
    347              */
    348             public abstract long getSystemTime(int which);
    349 
    350             /**
    351              * Returns the number of times the process has been started.
    352              *
    353              * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
    354              */
    355             public abstract int getStarts(int which);
    356 
    357             /**
    358              * Returns the cpu time spent in microseconds while the process was in the foreground.
    359              * @param which one of STATS_TOTAL, STATS_LAST, STATS_CURRENT or STATS_UNPLUGGED
    360              * @return foreground cpu time in microseconds
    361              */
    362             public abstract long getForegroundTime(int which);
    363 
    364             /**
    365              * Returns the approximate cpu time spent in microseconds, at a certain CPU speed.
    366              * @param speedStep the index of the CPU speed. This is not the actual speed of the
    367              * CPU.
    368              * @param which one of STATS_TOTAL, STATS_LAST, STATS_CURRENT or STATS_UNPLUGGED
    369              * @see BatteryStats#getCpuSpeedSteps()
    370              */
    371             public abstract long getTimeAtCpuSpeedStep(int speedStep, int which);
    372 
    373             public abstract int countExcessivePowers();
    374 
    375             public abstract ExcessivePower getExcessivePower(int i);
    376         }
    377 
    378         /**
    379          * The statistics associated with a particular package.
    380          */
    381         public static abstract class Pkg {
    382 
    383             /**
    384              * Returns the number of times this package has done something that could wake up the
    385              * device from sleep.
    386              *
    387              * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
    388              */
    389             public abstract int getWakeups(int which);
    390 
    391             /**
    392              * Returns a mapping containing service statistics.
    393              */
    394             public abstract Map<String, ? extends Serv> getServiceStats();
    395 
    396             /**
    397              * The statistics associated with a particular service.
    398              */
    399             public abstract class Serv {
    400 
    401                 /**
    402                  * Returns the amount of time spent started.
    403                  *
    404                  * @param batteryUptime elapsed uptime on battery in microseconds.
    405                  * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
    406                  * @return
    407                  */
    408                 public abstract long getStartTime(long batteryUptime, int which);
    409 
    410                 /**
    411                  * Returns the total number of times startService() has been called.
    412                  *
    413                  * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
    414                  */
    415                 public abstract int getStarts(int which);
    416 
    417                 /**
    418                  * Returns the total number times the service has been launched.
    419                  *
    420                  * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
    421                  */
    422                 public abstract int getLaunches(int which);
    423             }
    424         }
    425     }
    426 
    427     public final static class HistoryItem implements Parcelable {
    428         static final String TAG = "HistoryItem";
    429         static final boolean DEBUG = false;
    430 
    431         public HistoryItem next;
    432 
    433         public long time;
    434 
    435         public static final byte CMD_NULL = 0;
    436         public static final byte CMD_UPDATE = 1;
    437         public static final byte CMD_START = 2;
    438         public static final byte CMD_OVERFLOW = 3;
    439 
    440         public byte cmd = CMD_NULL;
    441 
    442         public byte batteryLevel;
    443         public byte batteryStatus;
    444         public byte batteryHealth;
    445         public byte batteryPlugType;
    446 
    447         public char batteryTemperature;
    448         public char batteryVoltage;
    449 
    450         // Constants from SCREEN_BRIGHTNESS_*
    451         public static final int STATE_BRIGHTNESS_MASK = 0x0000000f;
    452         public static final int STATE_BRIGHTNESS_SHIFT = 0;
    453         // Constants from SIGNAL_STRENGTH_*
    454         public static final int STATE_SIGNAL_STRENGTH_MASK = 0x000000f0;
    455         public static final int STATE_SIGNAL_STRENGTH_SHIFT = 4;
    456         // Constants from ServiceState.STATE_*
    457         public static final int STATE_PHONE_STATE_MASK = 0x00000f00;
    458         public static final int STATE_PHONE_STATE_SHIFT = 8;
    459         // Constants from DATA_CONNECTION_*
    460         public static final int STATE_DATA_CONNECTION_MASK = 0x0000f000;
    461         public static final int STATE_DATA_CONNECTION_SHIFT = 12;
    462 
    463         // These states always appear directly in the first int token
    464         // of a delta change; they should be ones that change relatively
    465         // frequently.
    466         public static final int STATE_WAKE_LOCK_FLAG = 1<<30;
    467         public static final int STATE_SENSOR_ON_FLAG = 1<<29;
    468         public static final int STATE_GPS_ON_FLAG = 1<<28;
    469         public static final int STATE_PHONE_SCANNING_FLAG = 1<<27;
    470         public static final int STATE_WIFI_RUNNING_FLAG = 1<<26;
    471         public static final int STATE_WIFI_FULL_LOCK_FLAG = 1<<25;
    472         public static final int STATE_WIFI_SCAN_FLAG = 1<<24;
    473         public static final int STATE_WIFI_MULTICAST_ON_FLAG = 1<<23;
    474         // These are on the lower bits used for the command; if they change
    475         // we need to write another int of data.
    476         public static final int STATE_AUDIO_ON_FLAG = 1<<22;
    477         public static final int STATE_VIDEO_ON_FLAG = 1<<21;
    478         public static final int STATE_SCREEN_ON_FLAG = 1<<20;
    479         public static final int STATE_BATTERY_PLUGGED_FLAG = 1<<19;
    480         public static final int STATE_PHONE_IN_CALL_FLAG = 1<<18;
    481         public static final int STATE_WIFI_ON_FLAG = 1<<17;
    482         public static final int STATE_BLUETOOTH_ON_FLAG = 1<<16;
    483 
    484         public static final int MOST_INTERESTING_STATES =
    485             STATE_BATTERY_PLUGGED_FLAG | STATE_SCREEN_ON_FLAG
    486             | STATE_GPS_ON_FLAG | STATE_PHONE_IN_CALL_FLAG;
    487 
    488         public int states;
    489 
    490         public HistoryItem() {
    491         }
    492 
    493         public HistoryItem(long time, Parcel src) {
    494             this.time = time;
    495             readFromParcel(src);
    496         }
    497 
    498         public int describeContents() {
    499             return 0;
    500         }
    501 
    502         public void writeToParcel(Parcel dest, int flags) {
    503             dest.writeLong(time);
    504             int bat = (((int)cmd)&0xff)
    505                     | ((((int)batteryLevel)<<8)&0xff00)
    506                     | ((((int)batteryStatus)<<16)&0xf0000)
    507                     | ((((int)batteryHealth)<<20)&0xf00000)
    508                     | ((((int)batteryPlugType)<<24)&0xf000000);
    509             dest.writeInt(bat);
    510             bat = (((int)batteryTemperature)&0xffff)
    511                     | ((((int)batteryVoltage)<<16)&0xffff0000);
    512             dest.writeInt(bat);
    513             dest.writeInt(states);
    514         }
    515 
    516         private void readFromParcel(Parcel src) {
    517             int bat = src.readInt();
    518             cmd = (byte)(bat&0xff);
    519             batteryLevel = (byte)((bat>>8)&0xff);
    520             batteryStatus = (byte)((bat>>16)&0xf);
    521             batteryHealth = (byte)((bat>>20)&0xf);
    522             batteryPlugType = (byte)((bat>>24)&0xf);
    523             bat = src.readInt();
    524             batteryTemperature = (char)(bat&0xffff);
    525             batteryVoltage = (char)((bat>>16)&0xffff);
    526             states = src.readInt();
    527         }
    528 
    529         // Part of initial delta int that specifies the time delta.
    530         static final int DELTA_TIME_MASK = 0x3ffff;
    531         static final int DELTA_TIME_ABS = 0x3fffd;    // Following is an entire abs update.
    532         static final int DELTA_TIME_INT = 0x3fffe;    // The delta is a following int
    533         static final int DELTA_TIME_LONG = 0x3ffff;   // The delta is a following long
    534         // Part of initial delta int holding the command code.
    535         static final int DELTA_CMD_MASK = 0x3;
    536         static final int DELTA_CMD_SHIFT = 18;
    537         // Flag in delta int: a new battery level int follows.
    538         static final int DELTA_BATTERY_LEVEL_FLAG = 1<<20;
    539         // Flag in delta int: a new full state and battery status int follows.
    540         static final int DELTA_STATE_FLAG = 1<<21;
    541         static final int DELTA_STATE_MASK = 0xffc00000;
    542 
    543         public void writeDelta(Parcel dest, HistoryItem last) {
    544             if (last == null || last.cmd != CMD_UPDATE) {
    545                 dest.writeInt(DELTA_TIME_ABS);
    546                 writeToParcel(dest, 0);
    547                 return;
    548             }
    549 
    550             final long deltaTime = time - last.time;
    551             final int lastBatteryLevelInt = last.buildBatteryLevelInt();
    552             final int lastStateInt = last.buildStateInt();
    553 
    554             int deltaTimeToken;
    555             if (deltaTime < 0 || deltaTime > Integer.MAX_VALUE) {
    556                 deltaTimeToken = DELTA_TIME_LONG;
    557             } else if (deltaTime >= DELTA_TIME_ABS) {
    558                 deltaTimeToken = DELTA_TIME_INT;
    559             } else {
    560                 deltaTimeToken = (int)deltaTime;
    561             }
    562             int firstToken = deltaTimeToken
    563                     | (cmd<<DELTA_CMD_SHIFT)
    564                     | (states&DELTA_STATE_MASK);
    565             final int batteryLevelInt = buildBatteryLevelInt();
    566             final boolean batteryLevelIntChanged = batteryLevelInt != lastBatteryLevelInt;
    567             if (batteryLevelIntChanged) {
    568                 firstToken |= DELTA_BATTERY_LEVEL_FLAG;
    569             }
    570             final int stateInt = buildStateInt();
    571             final boolean stateIntChanged = stateInt != lastStateInt;
    572             if (stateIntChanged) {
    573                 firstToken |= DELTA_STATE_FLAG;
    574             }
    575             dest.writeInt(firstToken);
    576             if (DEBUG) Slog.i(TAG, "WRITE DELTA: firstToken=0x" + Integer.toHexString(firstToken)
    577                     + " deltaTime=" + deltaTime);
    578 
    579             if (deltaTimeToken >= DELTA_TIME_INT) {
    580                 if (deltaTimeToken == DELTA_TIME_INT) {
    581                     if (DEBUG) Slog.i(TAG, "WRITE DELTA: int deltaTime=" + (int)deltaTime);
    582                     dest.writeInt((int)deltaTime);
    583                 } else {
    584                     if (DEBUG) Slog.i(TAG, "WRITE DELTA: long deltaTime=" + deltaTime);
    585                     dest.writeLong(deltaTime);
    586                 }
    587             }
    588             if (batteryLevelIntChanged) {
    589                 dest.writeInt(batteryLevelInt);
    590                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryToken=0x"
    591                         + Integer.toHexString(batteryLevelInt)
    592                         + " batteryLevel=" + batteryLevel
    593                         + " batteryTemp=" + (int)batteryTemperature
    594                         + " batteryVolt=" + (int)batteryVoltage);
    595             }
    596             if (stateIntChanged) {
    597                 dest.writeInt(stateInt);
    598                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: stateToken=0x"
    599                         + Integer.toHexString(stateInt)
    600                         + " batteryStatus=" + batteryStatus
    601                         + " batteryHealth=" + batteryHealth
    602                         + " batteryPlugType=" + batteryPlugType
    603                         + " states=0x" + Integer.toHexString(states));
    604             }
    605         }
    606 
    607         private int buildBatteryLevelInt() {
    608             return ((((int)batteryLevel)<<24)&0xff000000)
    609                     | ((((int)batteryTemperature)<<14)&0x00ffc000)
    610                     | (((int)batteryVoltage)&0x00003fff);
    611         }
    612 
    613         private int buildStateInt() {
    614             return ((((int)batteryStatus)<<28)&0xf0000000)
    615                     | ((((int)batteryHealth)<<24)&0x0f000000)
    616                     | ((((int)batteryPlugType)<<22)&0x00c00000)
    617                     | (states&(~DELTA_STATE_MASK));
    618         }
    619 
    620         public void readDelta(Parcel src) {
    621             int firstToken = src.readInt();
    622             int deltaTimeToken = firstToken&DELTA_TIME_MASK;
    623             cmd = (byte)((firstToken>>DELTA_CMD_SHIFT)&DELTA_CMD_MASK);
    624             if (DEBUG) Slog.i(TAG, "READ DELTA: firstToken=0x" + Integer.toHexString(firstToken)
    625                     + " deltaTimeToken=" + deltaTimeToken);
    626 
    627             if (deltaTimeToken < DELTA_TIME_ABS) {
    628                 time += deltaTimeToken;
    629             } else if (deltaTimeToken == DELTA_TIME_ABS) {
    630                 time = src.readLong();
    631                 readFromParcel(src);
    632                 return;
    633             } else if (deltaTimeToken == DELTA_TIME_INT) {
    634                 int delta = src.readInt();
    635                 time += delta;
    636                 if (DEBUG) Slog.i(TAG, "READ DELTA: time delta=" + delta + " new time=" + time);
    637             } else {
    638                 long delta = src.readLong();
    639                 if (DEBUG) Slog.i(TAG, "READ DELTA: time delta=" + delta + " new time=" + time);
    640                 time += delta;
    641             }
    642 
    643             if ((firstToken&DELTA_BATTERY_LEVEL_FLAG) != 0) {
    644                 int batteryLevelInt = src.readInt();
    645                 batteryLevel = (byte)((batteryLevelInt>>24)&0xff);
    646                 batteryTemperature = (char)((batteryLevelInt>>14)&0x3ff);
    647                 batteryVoltage = (char)(batteryLevelInt&0x3fff);
    648                 if (DEBUG) Slog.i(TAG, "READ DELTA: batteryToken=0x"
    649                         + Integer.toHexString(batteryLevelInt)
    650                         + " batteryLevel=" + batteryLevel
    651                         + " batteryTemp=" + (int)batteryTemperature
    652                         + " batteryVolt=" + (int)batteryVoltage);
    653             }
    654 
    655             if ((firstToken&DELTA_STATE_FLAG) != 0) {
    656                 int stateInt = src.readInt();
    657                 states = (firstToken&DELTA_STATE_MASK) | (stateInt&(~DELTA_STATE_MASK));
    658                 batteryStatus = (byte)((stateInt>>28)&0xf);
    659                 batteryHealth = (byte)((stateInt>>24)&0xf);
    660                 batteryPlugType = (byte)((stateInt>>22)&0x3);
    661                 if (DEBUG) Slog.i(TAG, "READ DELTA: stateToken=0x"
    662                         + Integer.toHexString(stateInt)
    663                         + " batteryStatus=" + batteryStatus
    664                         + " batteryHealth=" + batteryHealth
    665                         + " batteryPlugType=" + batteryPlugType
    666                         + " states=0x" + Integer.toHexString(states));
    667             } else {
    668                 states = (firstToken&DELTA_STATE_MASK) | (states&(~DELTA_STATE_MASK));
    669             }
    670         }
    671 
    672         public void clear() {
    673             time = 0;
    674             cmd = CMD_NULL;
    675             batteryLevel = 0;
    676             batteryStatus = 0;
    677             batteryHealth = 0;
    678             batteryPlugType = 0;
    679             batteryTemperature = 0;
    680             batteryVoltage = 0;
    681             states = 0;
    682         }
    683 
    684         public void setTo(HistoryItem o) {
    685             time = o.time;
    686             cmd = o.cmd;
    687             batteryLevel = o.batteryLevel;
    688             batteryStatus = o.batteryStatus;
    689             batteryHealth = o.batteryHealth;
    690             batteryPlugType = o.batteryPlugType;
    691             batteryTemperature = o.batteryTemperature;
    692             batteryVoltage = o.batteryVoltage;
    693             states = o.states;
    694         }
    695 
    696         public void setTo(long time, byte cmd, HistoryItem o) {
    697             this.time = time;
    698             this.cmd = cmd;
    699             batteryLevel = o.batteryLevel;
    700             batteryStatus = o.batteryStatus;
    701             batteryHealth = o.batteryHealth;
    702             batteryPlugType = o.batteryPlugType;
    703             batteryTemperature = o.batteryTemperature;
    704             batteryVoltage = o.batteryVoltage;
    705             states = o.states;
    706         }
    707 
    708         public boolean same(HistoryItem o) {
    709             return batteryLevel == o.batteryLevel
    710                     && batteryStatus == o.batteryStatus
    711                     && batteryHealth == o.batteryHealth
    712                     && batteryPlugType == o.batteryPlugType
    713                     && batteryTemperature == o.batteryTemperature
    714                     && batteryVoltage == o.batteryVoltage
    715                     && states == o.states;
    716         }
    717     }
    718 
    719     public static final class BitDescription {
    720         public final int mask;
    721         public final int shift;
    722         public final String name;
    723         public final String[] values;
    724 
    725         public BitDescription(int mask, String name) {
    726             this.mask = mask;
    727             this.shift = -1;
    728             this.name = name;
    729             this.values = null;
    730         }
    731 
    732         public BitDescription(int mask, int shift, String name, String[] values) {
    733             this.mask = mask;
    734             this.shift = shift;
    735             this.name = name;
    736             this.values = values;
    737         }
    738     }
    739 
    740     public abstract boolean startIteratingHistoryLocked();
    741 
    742     public abstract boolean getNextHistoryLocked(HistoryItem out);
    743 
    744     public abstract void finishIteratingHistoryLocked();
    745 
    746     public abstract boolean startIteratingOldHistoryLocked();
    747 
    748     public abstract boolean getNextOldHistoryLocked(HistoryItem out);
    749 
    750     public abstract void finishIteratingOldHistoryLocked();
    751 
    752     /**
    753      * Return the base time offset for the battery history.
    754      */
    755     public abstract long getHistoryBaseTime();
    756 
    757     /**
    758      * Returns the number of times the device has been started.
    759      */
    760     public abstract int getStartCount();
    761 
    762     /**
    763      * Returns the time in microseconds that the screen has been on while the device was
    764      * running on battery.
    765      *
    766      * {@hide}
    767      */
    768     public abstract long getScreenOnTime(long batteryRealtime, int which);
    769 
    770     public static final int SCREEN_BRIGHTNESS_DARK = 0;
    771     public static final int SCREEN_BRIGHTNESS_DIM = 1;
    772     public static final int SCREEN_BRIGHTNESS_MEDIUM = 2;
    773     public static final int SCREEN_BRIGHTNESS_LIGHT = 3;
    774     public static final int SCREEN_BRIGHTNESS_BRIGHT = 4;
    775 
    776     static final String[] SCREEN_BRIGHTNESS_NAMES = {
    777         "dark", "dim", "medium", "light", "bright"
    778     };
    779 
    780     public static final int NUM_SCREEN_BRIGHTNESS_BINS = 5;
    781 
    782     /**
    783      * Returns the time in microseconds that the screen has been on with
    784      * the given brightness
    785      *
    786      * {@hide}
    787      */
    788     public abstract long getScreenBrightnessTime(int brightnessBin,
    789             long batteryRealtime, int which);
    790 
    791     public abstract int getInputEventCount(int which);
    792 
    793     /**
    794      * Returns the time in microseconds that the phone has been on while the device was
    795      * running on battery.
    796      *
    797      * {@hide}
    798      */
    799     public abstract long getPhoneOnTime(long batteryRealtime, int which);
    800 
    801     /**
    802      * Returns the time in microseconds that the phone has been running with
    803      * the given signal strength.
    804      *
    805      * {@hide}
    806      */
    807     public abstract long getPhoneSignalStrengthTime(int strengthBin,
    808             long batteryRealtime, int which);
    809 
    810     /**
    811      * Returns the time in microseconds that the phone has been trying to
    812      * acquire a signal.
    813      *
    814      * {@hide}
    815      */
    816     public abstract long getPhoneSignalScanningTime(
    817             long batteryRealtime, int which);
    818 
    819     /**
    820      * Returns the number of times the phone has entered the given signal strength.
    821      *
    822      * {@hide}
    823      */
    824     public abstract int getPhoneSignalStrengthCount(int strengthBin, int which);
    825 
    826     public static final int DATA_CONNECTION_NONE = 0;
    827     public static final int DATA_CONNECTION_GPRS = 1;
    828     public static final int DATA_CONNECTION_EDGE = 2;
    829     public static final int DATA_CONNECTION_UMTS = 3;
    830     public static final int DATA_CONNECTION_CDMA = 4;
    831     public static final int DATA_CONNECTION_EVDO_0 = 5;
    832     public static final int DATA_CONNECTION_EVDO_A = 6;
    833     public static final int DATA_CONNECTION_1xRTT = 7;
    834     public static final int DATA_CONNECTION_HSDPA = 8;
    835     public static final int DATA_CONNECTION_HSUPA = 9;
    836     public static final int DATA_CONNECTION_HSPA = 10;
    837     public static final int DATA_CONNECTION_IDEN = 11;
    838     public static final int DATA_CONNECTION_EVDO_B = 12;
    839     public static final int DATA_CONNECTION_LTE = 13;
    840     public static final int DATA_CONNECTION_EHRPD = 14;
    841     public static final int DATA_CONNECTION_OTHER = 15;
    842 
    843     static final String[] DATA_CONNECTION_NAMES = {
    844         "none", "gprs", "edge", "umts", "cdma", "evdo_0", "evdo_A",
    845         "1xrtt", "hsdpa", "hsupa", "hspa", "iden", "evdo_b", "lte",
    846         "ehrpd", "other"
    847     };
    848 
    849     public static final int NUM_DATA_CONNECTION_TYPES = DATA_CONNECTION_OTHER+1;
    850 
    851     /**
    852      * Returns the time in microseconds that the phone has been running with
    853      * the given data connection.
    854      *
    855      * {@hide}
    856      */
    857     public abstract long getPhoneDataConnectionTime(int dataType,
    858             long batteryRealtime, int which);
    859 
    860     /**
    861      * Returns the number of times the phone has entered the given data
    862      * connection type.
    863      *
    864      * {@hide}
    865      */
    866     public abstract int getPhoneDataConnectionCount(int dataType, int which);
    867 
    868     public static final BitDescription[] HISTORY_STATE_DESCRIPTIONS
    869             = new BitDescription[] {
    870         new BitDescription(HistoryItem.STATE_BATTERY_PLUGGED_FLAG, "plugged"),
    871         new BitDescription(HistoryItem.STATE_SCREEN_ON_FLAG, "screen"),
    872         new BitDescription(HistoryItem.STATE_GPS_ON_FLAG, "gps"),
    873         new BitDescription(HistoryItem.STATE_PHONE_IN_CALL_FLAG, "phone_in_call"),
    874         new BitDescription(HistoryItem.STATE_PHONE_SCANNING_FLAG, "phone_scanning"),
    875         new BitDescription(HistoryItem.STATE_WIFI_ON_FLAG, "wifi"),
    876         new BitDescription(HistoryItem.STATE_WIFI_RUNNING_FLAG, "wifi_running"),
    877         new BitDescription(HistoryItem.STATE_WIFI_FULL_LOCK_FLAG, "wifi_full_lock"),
    878         new BitDescription(HistoryItem.STATE_WIFI_SCAN_FLAG, "wifi_scan"),
    879         new BitDescription(HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG, "wifi_multicast"),
    880         new BitDescription(HistoryItem.STATE_BLUETOOTH_ON_FLAG, "bluetooth"),
    881         new BitDescription(HistoryItem.STATE_AUDIO_ON_FLAG, "audio"),
    882         new BitDescription(HistoryItem.STATE_VIDEO_ON_FLAG, "video"),
    883         new BitDescription(HistoryItem.STATE_WAKE_LOCK_FLAG, "wake_lock"),
    884         new BitDescription(HistoryItem.STATE_SENSOR_ON_FLAG, "sensor"),
    885         new BitDescription(HistoryItem.STATE_BRIGHTNESS_MASK,
    886                 HistoryItem.STATE_BRIGHTNESS_SHIFT, "brightness",
    887                 SCREEN_BRIGHTNESS_NAMES),
    888         new BitDescription(HistoryItem.STATE_SIGNAL_STRENGTH_MASK,
    889                 HistoryItem.STATE_SIGNAL_STRENGTH_SHIFT, "signal_strength",
    890                 SignalStrength.SIGNAL_STRENGTH_NAMES),
    891         new BitDescription(HistoryItem.STATE_PHONE_STATE_MASK,
    892                 HistoryItem.STATE_PHONE_STATE_SHIFT, "phone_state",
    893                 new String[] {"in", "out", "emergency", "off"}),
    894         new BitDescription(HistoryItem.STATE_DATA_CONNECTION_MASK,
    895                 HistoryItem.STATE_DATA_CONNECTION_SHIFT, "data_conn",
    896                 DATA_CONNECTION_NAMES),
    897     };
    898 
    899     /**
    900      * Returns the time in microseconds that wifi has been on while the device was
    901      * running on battery.
    902      *
    903      * {@hide}
    904      */
    905     public abstract long getWifiOnTime(long batteryRealtime, int which);
    906 
    907     /**
    908      * Returns the time in microseconds that wifi has been on and the driver has
    909      * been in the running state while the device was running on battery.
    910      *
    911      * {@hide}
    912      */
    913     public abstract long getGlobalWifiRunningTime(long batteryRealtime, int which);
    914 
    915     /**
    916      * Returns the time in microseconds that bluetooth has been on while the device was
    917      * running on battery.
    918      *
    919      * {@hide}
    920      */
    921     public abstract long getBluetoothOnTime(long batteryRealtime, int which);
    922 
    923     /**
    924      * Return whether we are currently running on battery.
    925      */
    926     public abstract boolean getIsOnBattery();
    927 
    928     /**
    929      * Returns a SparseArray containing the statistics for each uid.
    930      */
    931     public abstract SparseArray<? extends Uid> getUidStats();
    932 
    933     /**
    934      * Returns the current battery uptime in microseconds.
    935      *
    936      * @param curTime the amount of elapsed realtime in microseconds.
    937      */
    938     public abstract long getBatteryUptime(long curTime);
    939 
    940     /**
    941      * @deprecated use getRadioDataUptime
    942      */
    943     public long getRadioDataUptimeMs() {
    944         return getRadioDataUptime() / 1000;
    945     }
    946 
    947     /**
    948      * Returns the time that the radio was on for data transfers.
    949      * @return the uptime in microseconds while unplugged
    950      */
    951     public abstract long getRadioDataUptime();
    952 
    953     /**
    954      * Returns the current battery realtime in microseconds.
    955      *
    956      * @param curTime the amount of elapsed realtime in microseconds.
    957      */
    958     public abstract long getBatteryRealtime(long curTime);
    959 
    960     /**
    961      * Returns the battery percentage level at the last time the device was unplugged from power, or
    962      * the last time it booted on battery power.
    963      */
    964     public abstract int getDischargeStartLevel();
    965 
    966     /**
    967      * Returns the current battery percentage level if we are in a discharge cycle, otherwise
    968      * returns the level at the last plug event.
    969      */
    970     public abstract int getDischargeCurrentLevel();
    971 
    972     /**
    973      * Get the amount the battery has discharged since the stats were
    974      * last reset after charging, as a lower-end approximation.
    975      */
    976     public abstract int getLowDischargeAmountSinceCharge();
    977 
    978     /**
    979      * Get the amount the battery has discharged since the stats were
    980      * last reset after charging, as an upper-end approximation.
    981      */
    982     public abstract int getHighDischargeAmountSinceCharge();
    983 
    984     /**
    985      * Get the amount the battery has discharged while the screen was on,
    986      * since the last time power was unplugged.
    987      */
    988     public abstract int getDischargeAmountScreenOn();
    989 
    990     /**
    991      * Get the amount the battery has discharged while the screen was on,
    992      * since the last time the device was charged.
    993      */
    994     public abstract int getDischargeAmountScreenOnSinceCharge();
    995 
    996     /**
    997      * Get the amount the battery has discharged while the screen was off,
    998      * since the last time power was unplugged.
    999      */
   1000     public abstract int getDischargeAmountScreenOff();
   1001 
   1002     /**
   1003      * Get the amount the battery has discharged while the screen was off,
   1004      * since the last time the device was charged.
   1005      */
   1006     public abstract int getDischargeAmountScreenOffSinceCharge();
   1007 
   1008     /**
   1009      * Returns the total, last, or current battery uptime in microseconds.
   1010      *
   1011      * @param curTime the elapsed realtime in microseconds.
   1012      * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
   1013      */
   1014     public abstract long computeBatteryUptime(long curTime, int which);
   1015 
   1016     /**
   1017      * Returns the total, last, or current battery realtime in microseconds.
   1018      *
   1019      * @param curTime the current elapsed realtime in microseconds.
   1020      * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
   1021      */
   1022     public abstract long computeBatteryRealtime(long curTime, int which);
   1023 
   1024     /**
   1025      * Returns the total, last, or current uptime in microseconds.
   1026      *
   1027      * @param curTime the current elapsed realtime in microseconds.
   1028      * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
   1029      */
   1030     public abstract long computeUptime(long curTime, int which);
   1031 
   1032     /**
   1033      * Returns the total, last, or current realtime in microseconds.
   1034      * *
   1035      * @param curTime the current elapsed realtime in microseconds.
   1036      * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
   1037      */
   1038     public abstract long computeRealtime(long curTime, int which);
   1039 
   1040     public abstract Map<String, ? extends Timer> getKernelWakelockStats();
   1041 
   1042     /** Returns the number of different speeds that the CPU can run at */
   1043     public abstract int getCpuSpeedSteps();
   1044 
   1045     private final static void formatTimeRaw(StringBuilder out, long seconds) {
   1046         long days = seconds / (60 * 60 * 24);
   1047         if (days != 0) {
   1048             out.append(days);
   1049             out.append("d ");
   1050         }
   1051         long used = days * 60 * 60 * 24;
   1052 
   1053         long hours = (seconds - used) / (60 * 60);
   1054         if (hours != 0 || used != 0) {
   1055             out.append(hours);
   1056             out.append("h ");
   1057         }
   1058         used += hours * 60 * 60;
   1059 
   1060         long mins = (seconds-used) / 60;
   1061         if (mins != 0 || used != 0) {
   1062             out.append(mins);
   1063             out.append("m ");
   1064         }
   1065         used += mins * 60;
   1066 
   1067         if (seconds != 0 || used != 0) {
   1068             out.append(seconds-used);
   1069             out.append("s ");
   1070         }
   1071     }
   1072 
   1073     private final static void formatTime(StringBuilder sb, long time) {
   1074         long sec = time / 100;
   1075         formatTimeRaw(sb, sec);
   1076         sb.append((time - (sec * 100)) * 10);
   1077         sb.append("ms ");
   1078     }
   1079 
   1080     private final static void formatTimeMs(StringBuilder sb, long time) {
   1081         long sec = time / 1000;
   1082         formatTimeRaw(sb, sec);
   1083         sb.append(time - (sec * 1000));
   1084         sb.append("ms ");
   1085     }
   1086 
   1087     private final String formatRatioLocked(long num, long den) {
   1088         if (den == 0L) {
   1089             return "---%";
   1090         }
   1091         float perc = ((float)num) / ((float)den) * 100;
   1092         mFormatBuilder.setLength(0);
   1093         mFormatter.format("%.1f%%", perc);
   1094         return mFormatBuilder.toString();
   1095     }
   1096 
   1097     private final String formatBytesLocked(long bytes) {
   1098         mFormatBuilder.setLength(0);
   1099 
   1100         if (bytes < BYTES_PER_KB) {
   1101             return bytes + "B";
   1102         } else if (bytes < BYTES_PER_MB) {
   1103             mFormatter.format("%.2fKB", bytes / (double) BYTES_PER_KB);
   1104             return mFormatBuilder.toString();
   1105         } else if (bytes < BYTES_PER_GB){
   1106             mFormatter.format("%.2fMB", bytes / (double) BYTES_PER_MB);
   1107             return mFormatBuilder.toString();
   1108         } else {
   1109             mFormatter.format("%.2fGB", bytes / (double) BYTES_PER_GB);
   1110             return mFormatBuilder.toString();
   1111         }
   1112     }
   1113 
   1114     private static long computeWakeLock(Timer timer, long batteryRealtime, int which) {
   1115         if (timer != null) {
   1116             // Convert from microseconds to milliseconds with rounding
   1117             long totalTimeMicros = timer.getTotalTimeLocked(batteryRealtime, which);
   1118             long totalTimeMillis = (totalTimeMicros + 500) / 1000;
   1119             return totalTimeMillis;
   1120         }
   1121         return 0;
   1122     }
   1123 
   1124     /**
   1125      *
   1126      * @param sb a StringBuilder object.
   1127      * @param timer a Timer object contining the wakelock times.
   1128      * @param batteryRealtime the current on-battery time in microseconds.
   1129      * @param name the name of the wakelock.
   1130      * @param which which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
   1131      * @param linePrefix a String to be prepended to each line of output.
   1132      * @return the line prefix
   1133      */
   1134     private static final String printWakeLock(StringBuilder sb, Timer timer,
   1135             long batteryRealtime, String name, int which, String linePrefix) {
   1136 
   1137         if (timer != null) {
   1138             long totalTimeMillis = computeWakeLock(timer, batteryRealtime, which);
   1139 
   1140             int count = timer.getCountLocked(which);
   1141             if (totalTimeMillis != 0) {
   1142                 sb.append(linePrefix);
   1143                 formatTimeMs(sb, totalTimeMillis);
   1144                 if (name != null) {
   1145                     sb.append(name);
   1146                     sb.append(' ');
   1147                 }
   1148                 sb.append('(');
   1149                 sb.append(count);
   1150                 sb.append(" times)");
   1151                 return ", ";
   1152             }
   1153         }
   1154         return linePrefix;
   1155     }
   1156 
   1157     /**
   1158      * Checkin version of wakelock printer. Prints simple comma-separated list.
   1159      *
   1160      * @param sb a StringBuilder object.
   1161      * @param timer a Timer object contining the wakelock times.
   1162      * @param now the current time in microseconds.
   1163      * @param name the name of the wakelock.
   1164      * @param which which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
   1165      * @param linePrefix a String to be prepended to each line of output.
   1166      * @return the line prefix
   1167      */
   1168     private static final String printWakeLockCheckin(StringBuilder sb, Timer timer, long now,
   1169             String name, int which, String linePrefix) {
   1170         long totalTimeMicros = 0;
   1171         int count = 0;
   1172         if (timer != null) {
   1173             totalTimeMicros = timer.getTotalTimeLocked(now, which);
   1174             count = timer.getCountLocked(which);
   1175         }
   1176         sb.append(linePrefix);
   1177         sb.append((totalTimeMicros + 500) / 1000); // microseconds to milliseconds with rounding
   1178         sb.append(',');
   1179         sb.append(name != null ? name + "," : "");
   1180         sb.append(count);
   1181         return ",";
   1182     }
   1183 
   1184     /**
   1185      * Dump a comma-separated line of values for terse checkin mode.
   1186      *
   1187      * @param pw the PageWriter to dump log to
   1188      * @param category category of data (e.g. "total", "last", "unplugged", "current" )
   1189      * @param type type of data (e.g. "wakelock", "sensor", "process", "apk" ,  "process", "network")
   1190      * @param args type-dependent data arguments
   1191      */
   1192     private static final void dumpLine(PrintWriter pw, int uid, String category, String type,
   1193            Object... args ) {
   1194         pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
   1195         pw.print(uid); pw.print(',');
   1196         pw.print(category); pw.print(',');
   1197         pw.print(type);
   1198 
   1199         for (Object arg : args) {
   1200             pw.print(',');
   1201             pw.print(arg);
   1202         }
   1203         pw.print('\n');
   1204     }
   1205 
   1206     /**
   1207      * Checkin server version of dump to produce more compact, computer-readable log.
   1208      *
   1209      * NOTE: all times are expressed in 'ms'.
   1210      */
   1211     public final void dumpCheckinLocked(PrintWriter pw, int which, int reqUid) {
   1212         final long rawUptime = SystemClock.uptimeMillis() * 1000;
   1213         final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
   1214         final long batteryUptime = getBatteryUptime(rawUptime);
   1215         final long batteryRealtime = getBatteryRealtime(rawRealtime);
   1216         final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
   1217         final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
   1218         final long totalRealtime = computeRealtime(rawRealtime, which);
   1219         final long totalUptime = computeUptime(rawUptime, which);
   1220         final long screenOnTime = getScreenOnTime(batteryRealtime, which);
   1221         final long phoneOnTime = getPhoneOnTime(batteryRealtime, which);
   1222         final long wifiOnTime = getWifiOnTime(batteryRealtime, which);
   1223         final long wifiRunningTime = getGlobalWifiRunningTime(batteryRealtime, which);
   1224         final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which);
   1225 
   1226         StringBuilder sb = new StringBuilder(128);
   1227 
   1228         SparseArray<? extends Uid> uidStats = getUidStats();
   1229         final int NU = uidStats.size();
   1230 
   1231         String category = STAT_NAMES[which];
   1232 
   1233         // Dump "battery" stat
   1234         dumpLine(pw, 0 /* uid */, category, BATTERY_DATA,
   1235                 which == STATS_SINCE_CHARGED ? getStartCount() : "N/A",
   1236                 whichBatteryRealtime / 1000, whichBatteryUptime / 1000,
   1237                 totalRealtime / 1000, totalUptime / 1000);
   1238 
   1239         // Calculate total network and wakelock times across all uids.
   1240         long rxTotal = 0;
   1241         long txTotal = 0;
   1242         long fullWakeLockTimeTotal = 0;
   1243         long partialWakeLockTimeTotal = 0;
   1244 
   1245         for (int iu = 0; iu < NU; iu++) {
   1246             Uid u = uidStats.valueAt(iu);
   1247             rxTotal += u.getTcpBytesReceived(which);
   1248             txTotal += u.getTcpBytesSent(which);
   1249 
   1250             Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
   1251             if (wakelocks.size() > 0) {
   1252                 for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
   1253                         : wakelocks.entrySet()) {
   1254                     Uid.Wakelock wl = ent.getValue();
   1255 
   1256                     Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
   1257                     if (fullWakeTimer != null) {
   1258                         fullWakeLockTimeTotal += fullWakeTimer.getTotalTimeLocked(batteryRealtime, which);
   1259                     }
   1260 
   1261                     Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
   1262                     if (partialWakeTimer != null) {
   1263                         partialWakeLockTimeTotal += partialWakeTimer.getTotalTimeLocked(
   1264                             batteryRealtime, which);
   1265                     }
   1266                 }
   1267             }
   1268         }
   1269 
   1270         // Dump misc stats
   1271         dumpLine(pw, 0 /* uid */, category, MISC_DATA,
   1272                 screenOnTime / 1000, phoneOnTime / 1000, wifiOnTime / 1000,
   1273                 wifiRunningTime / 1000, bluetoothOnTime / 1000, rxTotal, txTotal,
   1274                 fullWakeLockTimeTotal, partialWakeLockTimeTotal,
   1275                 getInputEventCount(which));
   1276 
   1277         // Dump screen brightness stats
   1278         Object[] args = new Object[NUM_SCREEN_BRIGHTNESS_BINS];
   1279         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
   1280             args[i] = getScreenBrightnessTime(i, batteryRealtime, which) / 1000;
   1281         }
   1282         dumpLine(pw, 0 /* uid */, category, SCREEN_BRIGHTNESS_DATA, args);
   1283 
   1284         // Dump signal strength stats
   1285         args = new Object[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
   1286         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
   1287             args[i] = getPhoneSignalStrengthTime(i, batteryRealtime, which) / 1000;
   1288         }
   1289         dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_TIME_DATA, args);
   1290         dumpLine(pw, 0 /* uid */, category, SIGNAL_SCANNING_TIME_DATA,
   1291                 getPhoneSignalScanningTime(batteryRealtime, which) / 1000);
   1292         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
   1293             args[i] = getPhoneSignalStrengthCount(i, which);
   1294         }
   1295         dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_COUNT_DATA, args);
   1296 
   1297         // Dump network type stats
   1298         args = new Object[NUM_DATA_CONNECTION_TYPES];
   1299         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
   1300             args[i] = getPhoneDataConnectionTime(i, batteryRealtime, which) / 1000;
   1301         }
   1302         dumpLine(pw, 0 /* uid */, category, DATA_CONNECTION_TIME_DATA, args);
   1303         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
   1304             args[i] = getPhoneDataConnectionCount(i, which);
   1305         }
   1306         dumpLine(pw, 0 /* uid */, category, DATA_CONNECTION_COUNT_DATA, args);
   1307 
   1308         if (which == STATS_SINCE_UNPLUGGED) {
   1309             dumpLine(pw, 0 /* uid */, category, BATTERY_LEVEL_DATA, getDischargeStartLevel(),
   1310                     getDischargeCurrentLevel());
   1311         }
   1312 
   1313         if (which == STATS_SINCE_UNPLUGGED) {
   1314             dumpLine(pw, 0 /* uid */, category, BATTERY_DISCHARGE_DATA,
   1315                     getDischargeStartLevel()-getDischargeCurrentLevel(),
   1316                     getDischargeStartLevel()-getDischargeCurrentLevel(),
   1317                     getDischargeAmountScreenOn(), getDischargeAmountScreenOff());
   1318         } else {
   1319             dumpLine(pw, 0 /* uid */, category, BATTERY_DISCHARGE_DATA,
   1320                     getLowDischargeAmountSinceCharge(), getHighDischargeAmountSinceCharge(),
   1321                     getDischargeAmountScreenOn(), getDischargeAmountScreenOff());
   1322         }
   1323 
   1324         if (reqUid < 0) {
   1325             Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats();
   1326             if (kernelWakelocks.size() > 0) {
   1327                 for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) {
   1328                     sb.setLength(0);
   1329                     printWakeLockCheckin(sb, ent.getValue(), batteryRealtime, null, which, "");
   1330 
   1331                     dumpLine(pw, 0 /* uid */, category, KERNEL_WAKELOCK_DATA, ent.getKey(),
   1332                             sb.toString());
   1333                 }
   1334             }
   1335         }
   1336 
   1337         for (int iu = 0; iu < NU; iu++) {
   1338             final int uid = uidStats.keyAt(iu);
   1339             if (reqUid >= 0 && uid != reqUid) {
   1340                 continue;
   1341             }
   1342             Uid u = uidStats.valueAt(iu);
   1343             // Dump Network stats per uid, if any
   1344             long rx = u.getTcpBytesReceived(which);
   1345             long tx = u.getTcpBytesSent(which);
   1346             long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
   1347             long wifiScanTime = u.getWifiScanTime(batteryRealtime, which);
   1348             long uidWifiRunningTime = u.getWifiRunningTime(batteryRealtime, which);
   1349 
   1350             if (rx > 0 || tx > 0) dumpLine(pw, uid, category, NETWORK_DATA, rx, tx);
   1351 
   1352             if (fullWifiLockOnTime != 0 || wifiScanTime != 0
   1353                     || uidWifiRunningTime != 0) {
   1354                 dumpLine(pw, uid, category, WIFI_DATA,
   1355                         fullWifiLockOnTime, wifiScanTime, uidWifiRunningTime);
   1356             }
   1357 
   1358             if (u.hasUserActivity()) {
   1359                 args = new Object[Uid.NUM_USER_ACTIVITY_TYPES];
   1360                 boolean hasData = false;
   1361                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
   1362                     int val = u.getUserActivityCount(i, which);
   1363                     args[i] = val;
   1364                     if (val != 0) hasData = true;
   1365                 }
   1366                 if (hasData) {
   1367                     dumpLine(pw, 0 /* uid */, category, USER_ACTIVITY_DATA, args);
   1368                 }
   1369             }
   1370 
   1371             Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
   1372             if (wakelocks.size() > 0) {
   1373                 for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
   1374                         : wakelocks.entrySet()) {
   1375                     Uid.Wakelock wl = ent.getValue();
   1376                     String linePrefix = "";
   1377                     sb.setLength(0);
   1378                     linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_FULL),
   1379                             batteryRealtime, "f", which, linePrefix);
   1380                     linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL),
   1381                             batteryRealtime, "p", which, linePrefix);
   1382                     linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_WINDOW),
   1383                             batteryRealtime, "w", which, linePrefix);
   1384 
   1385                     // Only log if we had at lease one wakelock...
   1386                     if (sb.length() > 0) {
   1387                        dumpLine(pw, uid, category, WAKELOCK_DATA, ent.getKey(), sb.toString());
   1388                     }
   1389                 }
   1390             }
   1391 
   1392             Map<Integer, ? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
   1393             if (sensors.size() > 0)  {
   1394                 for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> ent
   1395                         : sensors.entrySet()) {
   1396                     Uid.Sensor se = ent.getValue();
   1397                     int sensorNumber = ent.getKey();
   1398                     Timer timer = se.getSensorTime();
   1399                     if (timer != null) {
   1400                         // Convert from microseconds to milliseconds with rounding
   1401                         long totalTime = (timer.getTotalTimeLocked(batteryRealtime, which) + 500) / 1000;
   1402                         int count = timer.getCountLocked(which);
   1403                         if (totalTime != 0) {
   1404                             dumpLine(pw, uid, category, SENSOR_DATA, sensorNumber, totalTime, count);
   1405                         }
   1406                     }
   1407                 }
   1408             }
   1409 
   1410             Timer vibTimer = u.getVibratorOnTimer();
   1411             if (vibTimer != null) {
   1412                 // Convert from microseconds to milliseconds with rounding
   1413                 long totalTime = (vibTimer.getTotalTimeLocked(batteryRealtime, which) + 500) / 1000;
   1414                 int count = vibTimer.getCountLocked(which);
   1415                 if (totalTime != 0) {
   1416                     dumpLine(pw, uid, category, VIBRATOR_DATA, totalTime, count);
   1417                 }
   1418             }
   1419 
   1420             Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
   1421             if (processStats.size() > 0) {
   1422                 for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
   1423                         : processStats.entrySet()) {
   1424                     Uid.Proc ps = ent.getValue();
   1425 
   1426                     long userTime = ps.getUserTime(which);
   1427                     long systemTime = ps.getSystemTime(which);
   1428                     int starts = ps.getStarts(which);
   1429 
   1430                     if (userTime != 0 || systemTime != 0 || starts != 0) {
   1431                         dumpLine(pw, uid, category, PROCESS_DATA,
   1432                                 ent.getKey(), // proc
   1433                                 userTime * 10, // cpu time in ms
   1434                                 systemTime * 10, // user time in ms
   1435                                 starts); // process starts
   1436                     }
   1437                 }
   1438             }
   1439 
   1440             Map<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats();
   1441             if (packageStats.size() > 0) {
   1442                 for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent
   1443                         : packageStats.entrySet()) {
   1444 
   1445                     Uid.Pkg ps = ent.getValue();
   1446                     int wakeups = ps.getWakeups(which);
   1447                     Map<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
   1448                     for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent
   1449                             : serviceStats.entrySet()) {
   1450                         BatteryStats.Uid.Pkg.Serv ss = sent.getValue();
   1451                         long startTime = ss.getStartTime(batteryUptime, which);
   1452                         int starts = ss.getStarts(which);
   1453                         int launches = ss.getLaunches(which);
   1454                         if (startTime != 0 || starts != 0 || launches != 0) {
   1455                             dumpLine(pw, uid, category, APK_DATA,
   1456                                     wakeups, // wakeup alarms
   1457                                     ent.getKey(), // Apk
   1458                                     sent.getKey(), // service
   1459                                     startTime / 1000, // time spent started, in ms
   1460                                     starts,
   1461                                     launches);
   1462                         }
   1463                     }
   1464                 }
   1465             }
   1466         }
   1467     }
   1468 
   1469     static final class TimerEntry {
   1470         final String mName;
   1471         final int mId;
   1472         final BatteryStats.Timer mTimer;
   1473         final long mTime;
   1474         TimerEntry(String name, int id, BatteryStats.Timer timer, long time) {
   1475             mName = name;
   1476             mId = id;
   1477             mTimer = timer;
   1478             mTime = time;
   1479         }
   1480     }
   1481 
   1482     @SuppressWarnings("unused")
   1483     public final void dumpLocked(PrintWriter pw, String prefix, final int which, int reqUid) {
   1484         final long rawUptime = SystemClock.uptimeMillis() * 1000;
   1485         final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
   1486         final long batteryUptime = getBatteryUptime(rawUptime);
   1487         final long batteryRealtime = getBatteryRealtime(rawRealtime);
   1488 
   1489         final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
   1490         final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
   1491         final long totalRealtime = computeRealtime(rawRealtime, which);
   1492         final long totalUptime = computeUptime(rawUptime, which);
   1493 
   1494         StringBuilder sb = new StringBuilder(128);
   1495 
   1496         SparseArray<? extends Uid> uidStats = getUidStats();
   1497         final int NU = uidStats.size();
   1498 
   1499         sb.setLength(0);
   1500         sb.append(prefix);
   1501                 sb.append("  Time on battery: ");
   1502                 formatTimeMs(sb, whichBatteryRealtime / 1000); sb.append("(");
   1503                 sb.append(formatRatioLocked(whichBatteryRealtime, totalRealtime));
   1504                 sb.append(") realtime, ");
   1505                 formatTimeMs(sb, whichBatteryUptime / 1000);
   1506                 sb.append("("); sb.append(formatRatioLocked(whichBatteryUptime, totalRealtime));
   1507                 sb.append(") uptime");
   1508         pw.println(sb.toString());
   1509         sb.setLength(0);
   1510         sb.append(prefix);
   1511                 sb.append("  Total run time: ");
   1512                 formatTimeMs(sb, totalRealtime / 1000);
   1513                 sb.append("realtime, ");
   1514                 formatTimeMs(sb, totalUptime / 1000);
   1515                 sb.append("uptime, ");
   1516         pw.println(sb.toString());
   1517 
   1518         final long screenOnTime = getScreenOnTime(batteryRealtime, which);
   1519         final long phoneOnTime = getPhoneOnTime(batteryRealtime, which);
   1520         final long wifiRunningTime = getGlobalWifiRunningTime(batteryRealtime, which);
   1521         final long wifiOnTime = getWifiOnTime(batteryRealtime, which);
   1522         final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which);
   1523         sb.setLength(0);
   1524         sb.append(prefix);
   1525                 sb.append("  Screen on: "); formatTimeMs(sb, screenOnTime / 1000);
   1526                 sb.append("("); sb.append(formatRatioLocked(screenOnTime, whichBatteryRealtime));
   1527                 sb.append("), Input events: "); sb.append(getInputEventCount(which));
   1528                 sb.append(", Active phone call: "); formatTimeMs(sb, phoneOnTime / 1000);
   1529                 sb.append("("); sb.append(formatRatioLocked(phoneOnTime, whichBatteryRealtime));
   1530                 sb.append(")");
   1531         pw.println(sb.toString());
   1532         sb.setLength(0);
   1533         sb.append(prefix);
   1534         sb.append("  Screen brightnesses: ");
   1535         boolean didOne = false;
   1536         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
   1537             final long time = getScreenBrightnessTime(i, batteryRealtime, which);
   1538             if (time == 0) {
   1539                 continue;
   1540             }
   1541             if (didOne) sb.append(", ");
   1542             didOne = true;
   1543             sb.append(SCREEN_BRIGHTNESS_NAMES[i]);
   1544             sb.append(" ");
   1545             formatTimeMs(sb, time/1000);
   1546             sb.append("(");
   1547             sb.append(formatRatioLocked(time, screenOnTime));
   1548             sb.append(")");
   1549         }
   1550         if (!didOne) sb.append("No activity");
   1551         pw.println(sb.toString());
   1552 
   1553         // Calculate total network and wakelock times across all uids.
   1554         long rxTotal = 0;
   1555         long txTotal = 0;
   1556         long fullWakeLockTimeTotalMicros = 0;
   1557         long partialWakeLockTimeTotalMicros = 0;
   1558 
   1559         final Comparator<TimerEntry> timerComparator = new Comparator<TimerEntry>() {
   1560             @Override
   1561             public int compare(TimerEntry lhs, TimerEntry rhs) {
   1562                 long lhsTime = lhs.mTime;
   1563                 long rhsTime = rhs.mTime;
   1564                 if (lhsTime < rhsTime) {
   1565                     return 1;
   1566                 }
   1567                 if (lhsTime > rhsTime) {
   1568                     return -1;
   1569                 }
   1570                 return 0;
   1571             }
   1572         };
   1573 
   1574         if (reqUid < 0) {
   1575             Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats();
   1576             if (kernelWakelocks.size() > 0) {
   1577                 final ArrayList<TimerEntry> timers = new ArrayList<TimerEntry>();
   1578                 for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) {
   1579                     BatteryStats.Timer timer = ent.getValue();
   1580                     long totalTimeMillis = computeWakeLock(timer, batteryRealtime, which);
   1581                     if (totalTimeMillis > 0) {
   1582                         timers.add(new TimerEntry(ent.getKey(), 0, timer, totalTimeMillis));
   1583                     }
   1584                 }
   1585                 Collections.sort(timers, timerComparator);
   1586                 for (int i=0; i<timers.size(); i++) {
   1587                     TimerEntry timer = timers.get(i);
   1588                     String linePrefix = ": ";
   1589                     sb.setLength(0);
   1590                     sb.append(prefix);
   1591                     sb.append("  Kernel Wake lock ");
   1592                     sb.append(timer.mName);
   1593                     linePrefix = printWakeLock(sb, timer.mTimer, batteryRealtime, null,
   1594                             which, linePrefix);
   1595                     if (!linePrefix.equals(": ")) {
   1596                         sb.append(" realtime");
   1597                         // Only print out wake locks that were held
   1598                         pw.println(sb.toString());
   1599                     }
   1600                 }
   1601             }
   1602         }
   1603 
   1604         final ArrayList<TimerEntry> timers = new ArrayList<TimerEntry>();
   1605 
   1606         for (int iu = 0; iu < NU; iu++) {
   1607             Uid u = uidStats.valueAt(iu);
   1608             rxTotal += u.getTcpBytesReceived(which);
   1609             txTotal += u.getTcpBytesSent(which);
   1610 
   1611             Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
   1612             if (wakelocks.size() > 0) {
   1613                 for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
   1614                         : wakelocks.entrySet()) {
   1615                     Uid.Wakelock wl = ent.getValue();
   1616 
   1617                     Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
   1618                     if (fullWakeTimer != null) {
   1619                         fullWakeLockTimeTotalMicros += fullWakeTimer.getTotalTimeLocked(
   1620                                 batteryRealtime, which);
   1621                     }
   1622 
   1623                     Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
   1624                     if (partialWakeTimer != null) {
   1625                         long totalTimeMicros = partialWakeTimer.getTotalTimeLocked(
   1626                                 batteryRealtime, which);
   1627                         if (totalTimeMicros > 0) {
   1628                             if (reqUid < 0) {
   1629                                 // Only show the ordered list of all wake
   1630                                 // locks if the caller is not asking for data
   1631                                 // about a specific uid.
   1632                                 timers.add(new TimerEntry(ent.getKey(), u.getUid(),
   1633                                         partialWakeTimer, totalTimeMicros));
   1634                             }
   1635                             partialWakeLockTimeTotalMicros += totalTimeMicros;
   1636                         }
   1637                     }
   1638                 }
   1639             }
   1640         }
   1641 
   1642         pw.print(prefix);
   1643                 pw.print("  Total received: "); pw.print(formatBytesLocked(rxTotal));
   1644                 pw.print(", Total sent: "); pw.println(formatBytesLocked(txTotal));
   1645         sb.setLength(0);
   1646         sb.append(prefix);
   1647                 sb.append("  Total full wakelock time: "); formatTimeMs(sb,
   1648                         (fullWakeLockTimeTotalMicros + 500) / 1000);
   1649                 sb.append(", Total partial wakelock time: "); formatTimeMs(sb,
   1650                         (partialWakeLockTimeTotalMicros + 500) / 1000);
   1651         pw.println(sb.toString());
   1652 
   1653         sb.setLength(0);
   1654         sb.append(prefix);
   1655         sb.append("  Signal levels: ");
   1656         didOne = false;
   1657         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
   1658             final long time = getPhoneSignalStrengthTime(i, batteryRealtime, which);
   1659             if (time == 0) {
   1660                 continue;
   1661             }
   1662             if (didOne) sb.append(", ");
   1663             didOne = true;
   1664             sb.append(SignalStrength.SIGNAL_STRENGTH_NAMES[i]);
   1665             sb.append(" ");
   1666             formatTimeMs(sb, time/1000);
   1667             sb.append("(");
   1668             sb.append(formatRatioLocked(time, whichBatteryRealtime));
   1669             sb.append(") ");
   1670             sb.append(getPhoneSignalStrengthCount(i, which));
   1671             sb.append("x");
   1672         }
   1673         if (!didOne) sb.append("No activity");
   1674         pw.println(sb.toString());
   1675 
   1676         sb.setLength(0);
   1677         sb.append(prefix);
   1678         sb.append("  Signal scanning time: ");
   1679         formatTimeMs(sb, getPhoneSignalScanningTime(batteryRealtime, which) / 1000);
   1680         pw.println(sb.toString());
   1681 
   1682         sb.setLength(0);
   1683         sb.append(prefix);
   1684         sb.append("  Radio types: ");
   1685         didOne = false;
   1686         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
   1687             final long time = getPhoneDataConnectionTime(i, batteryRealtime, which);
   1688             if (time == 0) {
   1689                 continue;
   1690             }
   1691             if (didOne) sb.append(", ");
   1692             didOne = true;
   1693             sb.append(DATA_CONNECTION_NAMES[i]);
   1694             sb.append(" ");
   1695             formatTimeMs(sb, time/1000);
   1696             sb.append("(");
   1697             sb.append(formatRatioLocked(time, whichBatteryRealtime));
   1698             sb.append(") ");
   1699             sb.append(getPhoneDataConnectionCount(i, which));
   1700             sb.append("x");
   1701         }
   1702         if (!didOne) sb.append("No activity");
   1703         pw.println(sb.toString());
   1704 
   1705         sb.setLength(0);
   1706         sb.append(prefix);
   1707         sb.append("  Radio data uptime when unplugged: ");
   1708         sb.append(getRadioDataUptime() / 1000);
   1709         sb.append(" ms");
   1710         pw.println(sb.toString());
   1711 
   1712         sb.setLength(0);
   1713         sb.append(prefix);
   1714                 sb.append("  Wifi on: "); formatTimeMs(sb, wifiOnTime / 1000);
   1715                 sb.append("("); sb.append(formatRatioLocked(wifiOnTime, whichBatteryRealtime));
   1716                 sb.append("), Wifi running: "); formatTimeMs(sb, wifiRunningTime / 1000);
   1717                 sb.append("("); sb.append(formatRatioLocked(wifiRunningTime, whichBatteryRealtime));
   1718                 sb.append("), Bluetooth on: "); formatTimeMs(sb, bluetoothOnTime / 1000);
   1719                 sb.append("("); sb.append(formatRatioLocked(bluetoothOnTime, whichBatteryRealtime));
   1720                 sb.append(")");
   1721         pw.println(sb.toString());
   1722 
   1723         pw.println(" ");
   1724 
   1725         if (which == STATS_SINCE_UNPLUGGED) {
   1726             if (getIsOnBattery()) {
   1727                 pw.print(prefix); pw.println("  Device is currently unplugged");
   1728                 pw.print(prefix); pw.print("    Discharge cycle start level: ");
   1729                         pw.println(getDischargeStartLevel());
   1730                 pw.print(prefix); pw.print("    Discharge cycle current level: ");
   1731                         pw.println(getDischargeCurrentLevel());
   1732             } else {
   1733                 pw.print(prefix); pw.println("  Device is currently plugged into power");
   1734                 pw.print(prefix); pw.print("    Last discharge cycle start level: ");
   1735                         pw.println(getDischargeStartLevel());
   1736                 pw.print(prefix); pw.print("    Last discharge cycle end level: ");
   1737                         pw.println(getDischargeCurrentLevel());
   1738             }
   1739             pw.print(prefix); pw.print("    Amount discharged while screen on: ");
   1740                     pw.println(getDischargeAmountScreenOn());
   1741             pw.print(prefix); pw.print("    Amount discharged while screen off: ");
   1742                     pw.println(getDischargeAmountScreenOff());
   1743             pw.println(" ");
   1744         } else {
   1745             pw.print(prefix); pw.println("  Device battery use since last full charge");
   1746             pw.print(prefix); pw.print("    Amount discharged (lower bound): ");
   1747                     pw.println(getLowDischargeAmountSinceCharge());
   1748             pw.print(prefix); pw.print("    Amount discharged (upper bound): ");
   1749                     pw.println(getHighDischargeAmountSinceCharge());
   1750             pw.print(prefix); pw.print("    Amount discharged while screen on: ");
   1751                     pw.println(getDischargeAmountScreenOnSinceCharge());
   1752             pw.print(prefix); pw.print("    Amount discharged while screen off: ");
   1753                     pw.println(getDischargeAmountScreenOffSinceCharge());
   1754             pw.println();
   1755         }
   1756 
   1757         if (timers.size() > 0) {
   1758             Collections.sort(timers, timerComparator);
   1759             pw.print(prefix); pw.println("  All partial wake locks:");
   1760             for (int i=0; i<timers.size(); i++) {
   1761                 TimerEntry timer = timers.get(i);
   1762                 sb.setLength(0);
   1763                 sb.append("  Wake lock #");
   1764                 sb.append(timer.mId);
   1765                 sb.append(" ");
   1766                 sb.append(timer.mName);
   1767                 printWakeLock(sb, timer.mTimer, batteryRealtime, null, which, ": ");
   1768                 sb.append(" realtime");
   1769                 pw.println(sb.toString());
   1770             }
   1771             timers.clear();
   1772             pw.println();
   1773         }
   1774 
   1775         for (int iu=0; iu<NU; iu++) {
   1776             final int uid = uidStats.keyAt(iu);
   1777             if (reqUid >= 0 && uid != reqUid && uid != Process.SYSTEM_UID) {
   1778                 continue;
   1779             }
   1780 
   1781             Uid u = uidStats.valueAt(iu);
   1782 
   1783             pw.println(prefix + "  #" + uid + ":");
   1784             boolean uidActivity = false;
   1785 
   1786             long tcpReceived = u.getTcpBytesReceived(which);
   1787             long tcpSent = u.getTcpBytesSent(which);
   1788             long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
   1789             long wifiScanTime = u.getWifiScanTime(batteryRealtime, which);
   1790             long uidWifiRunningTime = u.getWifiRunningTime(batteryRealtime, which);
   1791 
   1792             if (tcpReceived != 0 || tcpSent != 0) {
   1793                 pw.print(prefix); pw.print("    Network: ");
   1794                         pw.print(formatBytesLocked(tcpReceived)); pw.print(" received, ");
   1795                         pw.print(formatBytesLocked(tcpSent)); pw.println(" sent");
   1796             }
   1797 
   1798             if (u.hasUserActivity()) {
   1799                 boolean hasData = false;
   1800                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
   1801                     int val = u.getUserActivityCount(i, which);
   1802                     if (val != 0) {
   1803                         if (!hasData) {
   1804                             sb.setLength(0);
   1805                             sb.append("    User activity: ");
   1806                             hasData = true;
   1807                         } else {
   1808                             sb.append(", ");
   1809                         }
   1810                         sb.append(val);
   1811                         sb.append(" ");
   1812                         sb.append(Uid.USER_ACTIVITY_TYPES[i]);
   1813                     }
   1814                 }
   1815                 if (hasData) {
   1816                     pw.println(sb.toString());
   1817                 }
   1818             }
   1819 
   1820             if (fullWifiLockOnTime != 0 || wifiScanTime != 0
   1821                     || uidWifiRunningTime != 0) {
   1822                 sb.setLength(0);
   1823                 sb.append(prefix); sb.append("    Wifi Running: ");
   1824                         formatTimeMs(sb, uidWifiRunningTime / 1000);
   1825                         sb.append("("); sb.append(formatRatioLocked(uidWifiRunningTime,
   1826                                 whichBatteryRealtime)); sb.append(")\n");
   1827                 sb.append(prefix); sb.append("    Full Wifi Lock: ");
   1828                         formatTimeMs(sb, fullWifiLockOnTime / 1000);
   1829                         sb.append("("); sb.append(formatRatioLocked(fullWifiLockOnTime,
   1830                                 whichBatteryRealtime)); sb.append(")\n");
   1831                 sb.append(prefix); sb.append("    Wifi Scan: ");
   1832                         formatTimeMs(sb, wifiScanTime / 1000);
   1833                         sb.append("("); sb.append(formatRatioLocked(wifiScanTime,
   1834                                 whichBatteryRealtime)); sb.append(")");
   1835                 pw.println(sb.toString());
   1836             }
   1837 
   1838             Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
   1839             if (wakelocks.size() > 0) {
   1840                 long totalFull = 0, totalPartial = 0, totalWindow = 0;
   1841                 int count = 0;
   1842                 for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
   1843                     : wakelocks.entrySet()) {
   1844                     Uid.Wakelock wl = ent.getValue();
   1845                     String linePrefix = ": ";
   1846                     sb.setLength(0);
   1847                     sb.append(prefix);
   1848                     sb.append("    Wake lock ");
   1849                     sb.append(ent.getKey());
   1850                     linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_FULL), batteryRealtime,
   1851                             "full", which, linePrefix);
   1852                     linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), batteryRealtime,
   1853                             "partial", which, linePrefix);
   1854                     linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), batteryRealtime,
   1855                             "window", which, linePrefix);
   1856                     if (!linePrefix.equals(": ")) {
   1857                         sb.append(" realtime");
   1858                         // Only print out wake locks that were held
   1859                         pw.println(sb.toString());
   1860                         uidActivity = true;
   1861                         count++;
   1862                     }
   1863                     totalFull += computeWakeLock(wl.getWakeTime(WAKE_TYPE_FULL),
   1864                             batteryRealtime, which);
   1865                     totalPartial += computeWakeLock(wl.getWakeTime(WAKE_TYPE_PARTIAL),
   1866                             batteryRealtime, which);
   1867                     totalWindow += computeWakeLock(wl.getWakeTime(WAKE_TYPE_WINDOW),
   1868                             batteryRealtime, which);
   1869                 }
   1870                 if (count > 1) {
   1871                     if (totalFull != 0 || totalPartial != 0 || totalWindow != 0) {
   1872                         sb.setLength(0);
   1873                         sb.append(prefix);
   1874                         sb.append("    TOTAL wake: ");
   1875                         boolean needComma = false;
   1876                         if (totalFull != 0) {
   1877                             needComma = true;
   1878                             formatTimeMs(sb, totalFull);
   1879                             sb.append("full");
   1880                         }
   1881                         if (totalPartial != 0) {
   1882                             if (needComma) {
   1883                                 sb.append(", ");
   1884                             }
   1885                             needComma = true;
   1886                             formatTimeMs(sb, totalPartial);
   1887                             sb.append("partial");
   1888                         }
   1889                         if (totalWindow != 0) {
   1890                             if (needComma) {
   1891                                 sb.append(", ");
   1892                             }
   1893                             needComma = true;
   1894                             formatTimeMs(sb, totalWindow);
   1895                             sb.append("window");
   1896                         }
   1897                         sb.append(" realtime");
   1898                         pw.println(sb.toString());
   1899                     }
   1900                 }
   1901             }
   1902 
   1903             Map<Integer, ? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
   1904             if (sensors.size() > 0) {
   1905                 for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> ent
   1906                     : sensors.entrySet()) {
   1907                     Uid.Sensor se = ent.getValue();
   1908                     int sensorNumber = ent.getKey();
   1909                     sb.setLength(0);
   1910                     sb.append(prefix);
   1911                     sb.append("    Sensor ");
   1912                     int handle = se.getHandle();
   1913                     if (handle == Uid.Sensor.GPS) {
   1914                         sb.append("GPS");
   1915                     } else {
   1916                         sb.append(handle);
   1917                     }
   1918                     sb.append(": ");
   1919 
   1920                     Timer timer = se.getSensorTime();
   1921                     if (timer != null) {
   1922                         // Convert from microseconds to milliseconds with rounding
   1923                         long totalTime = (timer.getTotalTimeLocked(
   1924                                 batteryRealtime, which) + 500) / 1000;
   1925                         int count = timer.getCountLocked(which);
   1926                         //timer.logState();
   1927                         if (totalTime != 0) {
   1928                             formatTimeMs(sb, totalTime);
   1929                             sb.append("realtime (");
   1930                             sb.append(count);
   1931                             sb.append(" times)");
   1932                         } else {
   1933                             sb.append("(not used)");
   1934                         }
   1935                     } else {
   1936                         sb.append("(not used)");
   1937                     }
   1938 
   1939                     pw.println(sb.toString());
   1940                     uidActivity = true;
   1941                 }
   1942             }
   1943 
   1944             Timer vibTimer = u.getVibratorOnTimer();
   1945             if (vibTimer != null) {
   1946                 // Convert from microseconds to milliseconds with rounding
   1947                 long totalTime = (vibTimer.getTotalTimeLocked(
   1948                         batteryRealtime, which) + 500) / 1000;
   1949                 int count = vibTimer.getCountLocked(which);
   1950                 //timer.logState();
   1951                 if (totalTime != 0) {
   1952                     sb.setLength(0);
   1953                     sb.append(prefix);
   1954                     sb.append("    Vibrator: ");
   1955                     formatTimeMs(sb, totalTime);
   1956                     sb.append("realtime (");
   1957                     sb.append(count);
   1958                     sb.append(" times)");
   1959                     pw.println(sb.toString());
   1960                     uidActivity = true;
   1961                 }
   1962             }
   1963 
   1964             Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
   1965             if (processStats.size() > 0) {
   1966                 for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
   1967                     : processStats.entrySet()) {
   1968                     Uid.Proc ps = ent.getValue();
   1969                     long userTime;
   1970                     long systemTime;
   1971                     int starts;
   1972                     int numExcessive;
   1973 
   1974                     userTime = ps.getUserTime(which);
   1975                     systemTime = ps.getSystemTime(which);
   1976                     starts = ps.getStarts(which);
   1977                     numExcessive = which == STATS_SINCE_CHARGED
   1978                             ? ps.countExcessivePowers() : 0;
   1979 
   1980                     if (userTime != 0 || systemTime != 0 || starts != 0
   1981                             || numExcessive != 0) {
   1982                         sb.setLength(0);
   1983                         sb.append(prefix); sb.append("    Proc ");
   1984                                 sb.append(ent.getKey()); sb.append(":\n");
   1985                         sb.append(prefix); sb.append("      CPU: ");
   1986                                 formatTime(sb, userTime); sb.append("usr + ");
   1987                                 formatTime(sb, systemTime); sb.append("krn");
   1988                         if (starts != 0) {
   1989                             sb.append("\n"); sb.append(prefix); sb.append("      ");
   1990                                     sb.append(starts); sb.append(" proc starts");
   1991                         }
   1992                         pw.println(sb.toString());
   1993                         for (int e=0; e<numExcessive; e++) {
   1994                             Uid.Proc.ExcessivePower ew = ps.getExcessivePower(e);
   1995                             if (ew != null) {
   1996                                 pw.print(prefix); pw.print("      * Killed for ");
   1997                                         if (ew.type == Uid.Proc.ExcessivePower.TYPE_WAKE) {
   1998                                             pw.print("wake lock");
   1999                                         } else if (ew.type == Uid.Proc.ExcessivePower.TYPE_CPU) {
   2000                                             pw.print("cpu");
   2001                                         } else {
   2002                                             pw.print("unknown");
   2003                                         }
   2004                                         pw.print(" use: ");
   2005                                         TimeUtils.formatDuration(ew.usedTime, pw);
   2006                                         pw.print(" over ");
   2007                                         TimeUtils.formatDuration(ew.overTime, pw);
   2008                                         pw.print(" (");
   2009                                         pw.print((ew.usedTime*100)/ew.overTime);
   2010                                         pw.println("%)");
   2011                             }
   2012                         }
   2013                         uidActivity = true;
   2014                     }
   2015                 }
   2016             }
   2017 
   2018             Map<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats();
   2019             if (packageStats.size() > 0) {
   2020                 for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent
   2021                     : packageStats.entrySet()) {
   2022                     pw.print(prefix); pw.print("    Apk "); pw.print(ent.getKey()); pw.println(":");
   2023                     boolean apkActivity = false;
   2024                     Uid.Pkg ps = ent.getValue();
   2025                     int wakeups = ps.getWakeups(which);
   2026                     if (wakeups != 0) {
   2027                         pw.print(prefix); pw.print("      ");
   2028                                 pw.print(wakeups); pw.println(" wakeup alarms");
   2029                         apkActivity = true;
   2030                     }
   2031                     Map<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
   2032                     if (serviceStats.size() > 0) {
   2033                         for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent
   2034                                 : serviceStats.entrySet()) {
   2035                             BatteryStats.Uid.Pkg.Serv ss = sent.getValue();
   2036                             long startTime = ss.getStartTime(batteryUptime, which);
   2037                             int starts = ss.getStarts(which);
   2038                             int launches = ss.getLaunches(which);
   2039                             if (startTime != 0 || starts != 0 || launches != 0) {
   2040                                 sb.setLength(0);
   2041                                 sb.append(prefix); sb.append("      Service ");
   2042                                         sb.append(sent.getKey()); sb.append(":\n");
   2043                                 sb.append(prefix); sb.append("        Created for: ");
   2044                                         formatTimeMs(sb, startTime / 1000);
   2045                                         sb.append(" uptime\n");
   2046                                 sb.append(prefix); sb.append("        Starts: ");
   2047                                         sb.append(starts);
   2048                                         sb.append(", launches: "); sb.append(launches);
   2049                                 pw.println(sb.toString());
   2050                                 apkActivity = true;
   2051                             }
   2052                         }
   2053                     }
   2054                     if (!apkActivity) {
   2055                         pw.print(prefix); pw.println("      (nothing executed)");
   2056                     }
   2057                     uidActivity = true;
   2058                 }
   2059             }
   2060             if (!uidActivity) {
   2061                 pw.print(prefix); pw.println("    (nothing executed)");
   2062             }
   2063         }
   2064     }
   2065 
   2066     static void printBitDescriptions(PrintWriter pw, int oldval, int newval, BitDescription[] descriptions) {
   2067         int diff = oldval ^ newval;
   2068         if (diff == 0) return;
   2069         for (int i=0; i<descriptions.length; i++) {
   2070             BitDescription bd = descriptions[i];
   2071             if ((diff&bd.mask) != 0) {
   2072                 if (bd.shift < 0) {
   2073                     pw.print((newval&bd.mask) != 0 ? " +" : " -");
   2074                     pw.print(bd.name);
   2075                 } else {
   2076                     pw.print(" ");
   2077                     pw.print(bd.name);
   2078                     pw.print("=");
   2079                     int val = (newval&bd.mask)>>bd.shift;
   2080                     if (bd.values != null && val >= 0 && val < bd.values.length) {
   2081                         pw.print(bd.values[val]);
   2082                     } else {
   2083                         pw.print(val);
   2084                     }
   2085                 }
   2086             }
   2087         }
   2088     }
   2089 
   2090     public void prepareForDumpLocked() {
   2091     }
   2092 
   2093     public static class HistoryPrinter {
   2094         int oldState = 0;
   2095         int oldStatus = -1;
   2096         int oldHealth = -1;
   2097         int oldPlug = -1;
   2098         int oldTemp = -1;
   2099         int oldVolt = -1;
   2100 
   2101         public void printNextItem(PrintWriter pw, HistoryItem rec, long now) {
   2102             pw.print("  ");
   2103             TimeUtils.formatDuration(rec.time-now, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
   2104             pw.print(" ");
   2105             if (rec.cmd == HistoryItem.CMD_START) {
   2106                 pw.println(" START");
   2107             } else if (rec.cmd == HistoryItem.CMD_OVERFLOW) {
   2108                 pw.println(" *OVERFLOW*");
   2109             } else {
   2110                 if (rec.batteryLevel < 10) pw.print("00");
   2111                 else if (rec.batteryLevel < 100) pw.print("0");
   2112                 pw.print(rec.batteryLevel);
   2113                 pw.print(" ");
   2114                 if (rec.states < 0x10) pw.print("0000000");
   2115                 else if (rec.states < 0x100) pw.print("000000");
   2116                 else if (rec.states < 0x1000) pw.print("00000");
   2117                 else if (rec.states < 0x10000) pw.print("0000");
   2118                 else if (rec.states < 0x100000) pw.print("000");
   2119                 else if (rec.states < 0x1000000) pw.print("00");
   2120                 else if (rec.states < 0x10000000) pw.print("0");
   2121                 pw.print(Integer.toHexString(rec.states));
   2122                 if (oldStatus != rec.batteryStatus) {
   2123                     oldStatus = rec.batteryStatus;
   2124                     pw.print(" status=");
   2125                     switch (oldStatus) {
   2126                         case BatteryManager.BATTERY_STATUS_UNKNOWN:
   2127                             pw.print("unknown");
   2128                             break;
   2129                         case BatteryManager.BATTERY_STATUS_CHARGING:
   2130                             pw.print("charging");
   2131                             break;
   2132                         case BatteryManager.BATTERY_STATUS_DISCHARGING:
   2133                             pw.print("discharging");
   2134                             break;
   2135                         case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
   2136                             pw.print("not-charging");
   2137                             break;
   2138                         case BatteryManager.BATTERY_STATUS_FULL:
   2139                             pw.print("full");
   2140                             break;
   2141                         default:
   2142                             pw.print(oldStatus);
   2143                             break;
   2144                     }
   2145                 }
   2146                 if (oldHealth != rec.batteryHealth) {
   2147                     oldHealth = rec.batteryHealth;
   2148                     pw.print(" health=");
   2149                     switch (oldHealth) {
   2150                         case BatteryManager.BATTERY_HEALTH_UNKNOWN:
   2151                             pw.print("unknown");
   2152                             break;
   2153                         case BatteryManager.BATTERY_HEALTH_GOOD:
   2154                             pw.print("good");
   2155                             break;
   2156                         case BatteryManager.BATTERY_HEALTH_OVERHEAT:
   2157                             pw.print("overheat");
   2158                             break;
   2159                         case BatteryManager.BATTERY_HEALTH_DEAD:
   2160                             pw.print("dead");
   2161                             break;
   2162                         case BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE:
   2163                             pw.print("over-voltage");
   2164                             break;
   2165                         case BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE:
   2166                             pw.print("failure");
   2167                             break;
   2168                         default:
   2169                             pw.print(oldHealth);
   2170                             break;
   2171                     }
   2172                 }
   2173                 if (oldPlug != rec.batteryPlugType) {
   2174                     oldPlug = rec.batteryPlugType;
   2175                     pw.print(" plug=");
   2176                     switch (oldPlug) {
   2177                         case 0:
   2178                             pw.print("none");
   2179                             break;
   2180                         case BatteryManager.BATTERY_PLUGGED_AC:
   2181                             pw.print("ac");
   2182                             break;
   2183                         case BatteryManager.BATTERY_PLUGGED_USB:
   2184                             pw.print("usb");
   2185                             break;
   2186                         case BatteryManager.BATTERY_PLUGGED_WIRELESS:
   2187                             pw.print("wireless");
   2188                             break;
   2189                         default:
   2190                             pw.print(oldPlug);
   2191                             break;
   2192                     }
   2193                 }
   2194                 if (oldTemp != rec.batteryTemperature) {
   2195                     oldTemp = rec.batteryTemperature;
   2196                     pw.print(" temp=");
   2197                     pw.print(oldTemp);
   2198                 }
   2199                 if (oldVolt != rec.batteryVoltage) {
   2200                     oldVolt = rec.batteryVoltage;
   2201                     pw.print(" volt=");
   2202                     pw.print(oldVolt);
   2203                 }
   2204                 printBitDescriptions(pw, oldState, rec.states,
   2205                         HISTORY_STATE_DESCRIPTIONS);
   2206                 pw.println();
   2207             }
   2208             oldState = rec.states;
   2209         }
   2210     }
   2211 
   2212     /**
   2213      * Dumps a human-readable summary of the battery statistics to the given PrintWriter.
   2214      *
   2215      * @param pw a Printer to receive the dump output.
   2216      */
   2217     @SuppressWarnings("unused")
   2218     public void dumpLocked(PrintWriter pw) {
   2219         prepareForDumpLocked();
   2220 
   2221         long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
   2222 
   2223         final HistoryItem rec = new HistoryItem();
   2224         if (startIteratingHistoryLocked()) {
   2225             pw.println("Battery History:");
   2226             HistoryPrinter hprinter = new HistoryPrinter();
   2227             while (getNextHistoryLocked(rec)) {
   2228                 hprinter.printNextItem(pw, rec, now);
   2229             }
   2230             finishIteratingHistoryLocked();
   2231             pw.println("");
   2232         }
   2233 
   2234         if (startIteratingOldHistoryLocked()) {
   2235             pw.println("Old battery History:");
   2236             HistoryPrinter hprinter = new HistoryPrinter();
   2237             while (getNextOldHistoryLocked(rec)) {
   2238                 hprinter.printNextItem(pw, rec, now);
   2239             }
   2240             finishIteratingOldHistoryLocked();
   2241             pw.println("");
   2242         }
   2243 
   2244         SparseArray<? extends Uid> uidStats = getUidStats();
   2245         final int NU = uidStats.size();
   2246         boolean didPid = false;
   2247         long nowRealtime = SystemClock.elapsedRealtime();
   2248         for (int i=0; i<NU; i++) {
   2249             Uid uid = uidStats.valueAt(i);
   2250             SparseArray<? extends Uid.Pid> pids = uid.getPidStats();
   2251             if (pids != null) {
   2252                 for (int j=0; j<pids.size(); j++) {
   2253                     Uid.Pid pid = pids.valueAt(j);
   2254                     if (!didPid) {
   2255                         pw.println("Per-PID Stats:");
   2256                         didPid = true;
   2257                     }
   2258                     long time = pid.mWakeSum + (pid.mWakeStart != 0
   2259                             ? (nowRealtime - pid.mWakeStart) : 0);
   2260                     pw.print("  PID "); pw.print(pids.keyAt(j));
   2261                             pw.print(" wake time: ");
   2262                             TimeUtils.formatDuration(time, pw);
   2263                             pw.println("");
   2264                 }
   2265             }
   2266         }
   2267         if (didPid) {
   2268             pw.println("");
   2269         }
   2270 
   2271         pw.println("Statistics since last charge:");
   2272         pw.println("  System starts: " + getStartCount()
   2273                 + ", currently on battery: " + getIsOnBattery());
   2274         dumpLocked(pw, "", STATS_SINCE_CHARGED, -1);
   2275         pw.println("");
   2276         pw.println("Statistics since last unplugged:");
   2277         dumpLocked(pw, "", STATS_SINCE_UNPLUGGED, -1);
   2278     }
   2279 
   2280     @SuppressWarnings("unused")
   2281     public void dumpCheckinLocked(PrintWriter pw, String[] args, List<ApplicationInfo> apps) {
   2282         prepareForDumpLocked();
   2283 
   2284         boolean isUnpluggedOnly = false;
   2285 
   2286         for (String arg : args) {
   2287             if ("-u".equals(arg)) {
   2288                 if (LOCAL_LOGV) Log.v("BatteryStats", "Dumping unplugged data");
   2289                 isUnpluggedOnly = true;
   2290             }
   2291         }
   2292 
   2293         if (apps != null) {
   2294             SparseArray<ArrayList<String>> uids = new SparseArray<ArrayList<String>>();
   2295             for (int i=0; i<apps.size(); i++) {
   2296                 ApplicationInfo ai = apps.get(i);
   2297                 ArrayList<String> pkgs = uids.get(ai.uid);
   2298                 if (pkgs == null) {
   2299                     pkgs = new ArrayList<String>();
   2300                     uids.put(ai.uid, pkgs);
   2301                 }
   2302                 pkgs.add(ai.packageName);
   2303             }
   2304             SparseArray<? extends Uid> uidStats = getUidStats();
   2305             final int NU = uidStats.size();
   2306             String[] lineArgs = new String[2];
   2307             for (int i=0; i<NU; i++) {
   2308                 int uid = uidStats.keyAt(i);
   2309                 ArrayList<String> pkgs = uids.get(uid);
   2310                 if (pkgs != null) {
   2311                     for (int j=0; j<pkgs.size(); j++) {
   2312                         lineArgs[0] = Integer.toString(uid);
   2313                         lineArgs[1] = pkgs.get(j);
   2314                         dumpLine(pw, 0 /* uid */, "i" /* category */, UID_DATA,
   2315                                 (Object[])lineArgs);
   2316                     }
   2317                 }
   2318             }
   2319         }
   2320         if (isUnpluggedOnly) {
   2321             dumpCheckinLocked(pw, STATS_SINCE_UNPLUGGED, -1);
   2322         }
   2323         else {
   2324             dumpCheckinLocked(pw, STATS_SINCE_CHARGED, -1);
   2325             dumpCheckinLocked(pw, STATS_SINCE_UNPLUGGED, -1);
   2326         }
   2327     }
   2328 }
   2329