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