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