BatteryStats.java revision 13ac041b9f21043bc7c848a743be618bfd7a67e9
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.println();
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                        String name = ent.getKey();
1411                        if (name.indexOf(',') >= 0) {
1412                            name = name.replace(',', '_');
1413                        }
1414                        dumpLine(pw, uid, category, WAKELOCK_DATA, name, sb.toString());
1415                    }
1416                }
1417            }
1418
1419            Map<Integer, ? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
1420            if (sensors.size() > 0)  {
1421                for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> ent
1422                        : sensors.entrySet()) {
1423                    Uid.Sensor se = ent.getValue();
1424                    int sensorNumber = ent.getKey();
1425                    Timer timer = se.getSensorTime();
1426                    if (timer != null) {
1427                        // Convert from microseconds to milliseconds with rounding
1428                        long totalTime = (timer.getTotalTimeLocked(batteryRealtime, which) + 500) / 1000;
1429                        int count = timer.getCountLocked(which);
1430                        if (totalTime != 0) {
1431                            dumpLine(pw, uid, category, SENSOR_DATA, sensorNumber, totalTime, count);
1432                        }
1433                    }
1434                }
1435            }
1436
1437            Timer vibTimer = u.getVibratorOnTimer();
1438            if (vibTimer != null) {
1439                // Convert from microseconds to milliseconds with rounding
1440                long totalTime = (vibTimer.getTotalTimeLocked(batteryRealtime, which) + 500) / 1000;
1441                int count = vibTimer.getCountLocked(which);
1442                if (totalTime != 0) {
1443                    dumpLine(pw, uid, category, VIBRATOR_DATA, totalTime, count);
1444                }
1445            }
1446
1447            Timer fgTimer = u.getForegroundActivityTimer();
1448            if (fgTimer != null) {
1449                // Convert from microseconds to milliseconds with rounding
1450                long totalTime = (fgTimer.getTotalTimeLocked(batteryRealtime, which) + 500) / 1000;
1451                int count = fgTimer.getCountLocked(which);
1452                if (totalTime != 0) {
1453                    dumpLine(pw, uid, category, FOREGROUND_DATA, totalTime, count);
1454                }
1455            }
1456
1457            Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
1458            if (processStats.size() > 0) {
1459                for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
1460                        : processStats.entrySet()) {
1461                    Uid.Proc ps = ent.getValue();
1462
1463                    final long userMillis = ps.getUserTime(which) * 10;
1464                    final long systemMillis = ps.getSystemTime(which) * 10;
1465                    final long foregroundMillis = ps.getForegroundTime(which) * 10;
1466                    final long starts = ps.getStarts(which);
1467
1468                    if (userMillis != 0 || systemMillis != 0 || foregroundMillis != 0
1469                            || starts != 0) {
1470                        dumpLine(pw, uid, category, PROCESS_DATA, ent.getKey(), userMillis,
1471                                systemMillis, foregroundMillis, starts);
1472                    }
1473                }
1474            }
1475
1476            Map<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats();
1477            if (packageStats.size() > 0) {
1478                for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent
1479                        : packageStats.entrySet()) {
1480
1481                    Uid.Pkg ps = ent.getValue();
1482                    int wakeups = ps.getWakeups(which);
1483                    Map<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
1484                    for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent
1485                            : serviceStats.entrySet()) {
1486                        BatteryStats.Uid.Pkg.Serv ss = sent.getValue();
1487                        long startTime = ss.getStartTime(batteryUptime, which);
1488                        int starts = ss.getStarts(which);
1489                        int launches = ss.getLaunches(which);
1490                        if (startTime != 0 || starts != 0 || launches != 0) {
1491                            dumpLine(pw, uid, category, APK_DATA,
1492                                    wakeups, // wakeup alarms
1493                                    ent.getKey(), // Apk
1494                                    sent.getKey(), // service
1495                                    startTime / 1000, // time spent started, in ms
1496                                    starts,
1497                                    launches);
1498                        }
1499                    }
1500                }
1501            }
1502        }
1503    }
1504
1505    static final class TimerEntry {
1506        final String mName;
1507        final int mId;
1508        final BatteryStats.Timer mTimer;
1509        final long mTime;
1510        TimerEntry(String name, int id, BatteryStats.Timer timer, long time) {
1511            mName = name;
1512            mId = id;
1513            mTimer = timer;
1514            mTime = time;
1515        }
1516    }
1517
1518    @SuppressWarnings("unused")
1519    public final void dumpLocked(PrintWriter pw, String prefix, final int which, int reqUid) {
1520        final long rawUptime = SystemClock.uptimeMillis() * 1000;
1521        final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
1522        final long batteryUptime = getBatteryUptime(rawUptime);
1523        final long batteryRealtime = getBatteryRealtime(rawRealtime);
1524
1525        final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
1526        final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
1527        final long totalRealtime = computeRealtime(rawRealtime, which);
1528        final long totalUptime = computeUptime(rawUptime, which);
1529
1530        StringBuilder sb = new StringBuilder(128);
1531
1532        SparseArray<? extends Uid> uidStats = getUidStats();
1533        final int NU = uidStats.size();
1534
1535        sb.setLength(0);
1536        sb.append(prefix);
1537                sb.append("  Time on battery: ");
1538                formatTimeMs(sb, whichBatteryRealtime / 1000); sb.append("(");
1539                sb.append(formatRatioLocked(whichBatteryRealtime, totalRealtime));
1540                sb.append(") realtime, ");
1541                formatTimeMs(sb, whichBatteryUptime / 1000);
1542                sb.append("("); sb.append(formatRatioLocked(whichBatteryUptime, totalRealtime));
1543                sb.append(") uptime");
1544        pw.println(sb.toString());
1545        sb.setLength(0);
1546        sb.append(prefix);
1547                sb.append("  Total run time: ");
1548                formatTimeMs(sb, totalRealtime / 1000);
1549                sb.append("realtime, ");
1550                formatTimeMs(sb, totalUptime / 1000);
1551                sb.append("uptime, ");
1552        pw.println(sb.toString());
1553
1554        final long screenOnTime = getScreenOnTime(batteryRealtime, which);
1555        final long phoneOnTime = getPhoneOnTime(batteryRealtime, which);
1556        final long wifiRunningTime = getGlobalWifiRunningTime(batteryRealtime, which);
1557        final long wifiOnTime = getWifiOnTime(batteryRealtime, which);
1558        final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which);
1559        sb.setLength(0);
1560        sb.append(prefix);
1561                sb.append("  Screen on: "); formatTimeMs(sb, screenOnTime / 1000);
1562                sb.append("("); sb.append(formatRatioLocked(screenOnTime, whichBatteryRealtime));
1563                sb.append("), Input events: "); sb.append(getInputEventCount(which));
1564                sb.append(", Active phone call: "); formatTimeMs(sb, phoneOnTime / 1000);
1565                sb.append("("); sb.append(formatRatioLocked(phoneOnTime, whichBatteryRealtime));
1566                sb.append(")");
1567        pw.println(sb.toString());
1568        sb.setLength(0);
1569        sb.append(prefix);
1570        sb.append("  Screen brightnesses: ");
1571        boolean didOne = false;
1572        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
1573            final long time = getScreenBrightnessTime(i, batteryRealtime, which);
1574            if (time == 0) {
1575                continue;
1576            }
1577            if (didOne) sb.append(", ");
1578            didOne = true;
1579            sb.append(SCREEN_BRIGHTNESS_NAMES[i]);
1580            sb.append(" ");
1581            formatTimeMs(sb, time/1000);
1582            sb.append("(");
1583            sb.append(formatRatioLocked(time, screenOnTime));
1584            sb.append(")");
1585        }
1586        if (!didOne) sb.append("No activity");
1587        pw.println(sb.toString());
1588
1589        // Calculate total network and wakelock times across all uids.
1590        long mobileRxTotal = 0;
1591        long mobileTxTotal = 0;
1592        long wifiRxTotal = 0;
1593        long wifiTxTotal = 0;
1594        long fullWakeLockTimeTotalMicros = 0;
1595        long partialWakeLockTimeTotalMicros = 0;
1596
1597        final Comparator<TimerEntry> timerComparator = new Comparator<TimerEntry>() {
1598            @Override
1599            public int compare(TimerEntry lhs, TimerEntry rhs) {
1600                long lhsTime = lhs.mTime;
1601                long rhsTime = rhs.mTime;
1602                if (lhsTime < rhsTime) {
1603                    return 1;
1604                }
1605                if (lhsTime > rhsTime) {
1606                    return -1;
1607                }
1608                return 0;
1609            }
1610        };
1611
1612        if (reqUid < 0) {
1613            Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats();
1614            if (kernelWakelocks.size() > 0) {
1615                final ArrayList<TimerEntry> timers = new ArrayList<TimerEntry>();
1616                for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) {
1617                    BatteryStats.Timer timer = ent.getValue();
1618                    long totalTimeMillis = computeWakeLock(timer, batteryRealtime, which);
1619                    if (totalTimeMillis > 0) {
1620                        timers.add(new TimerEntry(ent.getKey(), 0, timer, totalTimeMillis));
1621                    }
1622                }
1623                Collections.sort(timers, timerComparator);
1624                for (int i=0; i<timers.size(); i++) {
1625                    TimerEntry timer = timers.get(i);
1626                    String linePrefix = ": ";
1627                    sb.setLength(0);
1628                    sb.append(prefix);
1629                    sb.append("  Kernel Wake lock ");
1630                    sb.append(timer.mName);
1631                    linePrefix = printWakeLock(sb, timer.mTimer, batteryRealtime, null,
1632                            which, linePrefix);
1633                    if (!linePrefix.equals(": ")) {
1634                        sb.append(" realtime");
1635                        // Only print out wake locks that were held
1636                        pw.println(sb.toString());
1637                    }
1638                }
1639            }
1640        }
1641
1642        final ArrayList<TimerEntry> timers = new ArrayList<TimerEntry>();
1643
1644        for (int iu = 0; iu < NU; iu++) {
1645            Uid u = uidStats.valueAt(iu);
1646            mobileRxTotal += u.getNetworkActivityCount(NETWORK_MOBILE_RX_BYTES, which);
1647            mobileTxTotal += u.getNetworkActivityCount(NETWORK_MOBILE_TX_BYTES, which);
1648            wifiRxTotal += u.getNetworkActivityCount(NETWORK_WIFI_RX_BYTES, which);
1649            wifiTxTotal += u.getNetworkActivityCount(NETWORK_WIFI_TX_BYTES, which);
1650
1651            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
1652            if (wakelocks.size() > 0) {
1653                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
1654                        : wakelocks.entrySet()) {
1655                    Uid.Wakelock wl = ent.getValue();
1656
1657                    Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
1658                    if (fullWakeTimer != null) {
1659                        fullWakeLockTimeTotalMicros += fullWakeTimer.getTotalTimeLocked(
1660                                batteryRealtime, which);
1661                    }
1662
1663                    Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
1664                    if (partialWakeTimer != null) {
1665                        long totalTimeMicros = partialWakeTimer.getTotalTimeLocked(
1666                                batteryRealtime, which);
1667                        if (totalTimeMicros > 0) {
1668                            if (reqUid < 0) {
1669                                // Only show the ordered list of all wake
1670                                // locks if the caller is not asking for data
1671                                // about a specific uid.
1672                                timers.add(new TimerEntry(ent.getKey(), u.getUid(),
1673                                        partialWakeTimer, totalTimeMicros));
1674                            }
1675                            partialWakeLockTimeTotalMicros += totalTimeMicros;
1676                        }
1677                    }
1678                }
1679            }
1680        }
1681
1682        pw.print(prefix);
1683                pw.print("  Mobile total received: "); pw.print(formatBytesLocked(mobileRxTotal));
1684                pw.print(", Total sent: "); pw.println(formatBytesLocked(mobileTxTotal));
1685        pw.print(prefix);
1686                pw.print("  Wi-Fi total received: "); pw.print(formatBytesLocked(wifiRxTotal));
1687                pw.print(", Total sent: "); pw.println(formatBytesLocked(wifiTxTotal));
1688        sb.setLength(0);
1689        sb.append(prefix);
1690                sb.append("  Total full wakelock time: "); formatTimeMs(sb,
1691                        (fullWakeLockTimeTotalMicros + 500) / 1000);
1692                sb.append(", Total partial wakelock time: "); formatTimeMs(sb,
1693                        (partialWakeLockTimeTotalMicros + 500) / 1000);
1694        pw.println(sb.toString());
1695
1696        sb.setLength(0);
1697        sb.append(prefix);
1698        sb.append("  Signal levels: ");
1699        didOne = false;
1700        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
1701            final long time = getPhoneSignalStrengthTime(i, batteryRealtime, which);
1702            if (time == 0) {
1703                continue;
1704            }
1705            if (didOne) sb.append(", ");
1706            didOne = true;
1707            sb.append(SignalStrength.SIGNAL_STRENGTH_NAMES[i]);
1708            sb.append(" ");
1709            formatTimeMs(sb, time/1000);
1710            sb.append("(");
1711            sb.append(formatRatioLocked(time, whichBatteryRealtime));
1712            sb.append(") ");
1713            sb.append(getPhoneSignalStrengthCount(i, which));
1714            sb.append("x");
1715        }
1716        if (!didOne) sb.append("No activity");
1717        pw.println(sb.toString());
1718
1719        sb.setLength(0);
1720        sb.append(prefix);
1721        sb.append("  Signal scanning time: ");
1722        formatTimeMs(sb, getPhoneSignalScanningTime(batteryRealtime, which) / 1000);
1723        pw.println(sb.toString());
1724
1725        sb.setLength(0);
1726        sb.append(prefix);
1727        sb.append("  Radio types: ");
1728        didOne = false;
1729        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
1730            final long time = getPhoneDataConnectionTime(i, batteryRealtime, which);
1731            if (time == 0) {
1732                continue;
1733            }
1734            if (didOne) sb.append(", ");
1735            didOne = true;
1736            sb.append(DATA_CONNECTION_NAMES[i]);
1737            sb.append(" ");
1738            formatTimeMs(sb, time/1000);
1739            sb.append("(");
1740            sb.append(formatRatioLocked(time, whichBatteryRealtime));
1741            sb.append(") ");
1742            sb.append(getPhoneDataConnectionCount(i, which));
1743            sb.append("x");
1744        }
1745        if (!didOne) sb.append("No activity");
1746        pw.println(sb.toString());
1747
1748        sb.setLength(0);
1749        sb.append(prefix);
1750        sb.append("  Radio data uptime when unplugged: ");
1751        sb.append(getRadioDataUptime() / 1000);
1752        sb.append(" ms");
1753        pw.println(sb.toString());
1754
1755        sb.setLength(0);
1756        sb.append(prefix);
1757                sb.append("  Wifi on: "); formatTimeMs(sb, wifiOnTime / 1000);
1758                sb.append("("); sb.append(formatRatioLocked(wifiOnTime, whichBatteryRealtime));
1759                sb.append("), Wifi running: "); formatTimeMs(sb, wifiRunningTime / 1000);
1760                sb.append("("); sb.append(formatRatioLocked(wifiRunningTime, whichBatteryRealtime));
1761                sb.append("), Bluetooth on: "); formatTimeMs(sb, bluetoothOnTime / 1000);
1762                sb.append("("); sb.append(formatRatioLocked(bluetoothOnTime, whichBatteryRealtime));
1763                sb.append(")");
1764        pw.println(sb.toString());
1765
1766        pw.println(" ");
1767
1768        if (which == STATS_SINCE_UNPLUGGED) {
1769            if (getIsOnBattery()) {
1770                pw.print(prefix); pw.println("  Device is currently unplugged");
1771                pw.print(prefix); pw.print("    Discharge cycle start level: ");
1772                        pw.println(getDischargeStartLevel());
1773                pw.print(prefix); pw.print("    Discharge cycle current level: ");
1774                        pw.println(getDischargeCurrentLevel());
1775            } else {
1776                pw.print(prefix); pw.println("  Device is currently plugged into power");
1777                pw.print(prefix); pw.print("    Last discharge cycle start level: ");
1778                        pw.println(getDischargeStartLevel());
1779                pw.print(prefix); pw.print("    Last discharge cycle end level: ");
1780                        pw.println(getDischargeCurrentLevel());
1781            }
1782            pw.print(prefix); pw.print("    Amount discharged while screen on: ");
1783                    pw.println(getDischargeAmountScreenOn());
1784            pw.print(prefix); pw.print("    Amount discharged while screen off: ");
1785                    pw.println(getDischargeAmountScreenOff());
1786            pw.println(" ");
1787        } else {
1788            pw.print(prefix); pw.println("  Device battery use since last full charge");
1789            pw.print(prefix); pw.print("    Amount discharged (lower bound): ");
1790                    pw.println(getLowDischargeAmountSinceCharge());
1791            pw.print(prefix); pw.print("    Amount discharged (upper bound): ");
1792                    pw.println(getHighDischargeAmountSinceCharge());
1793            pw.print(prefix); pw.print("    Amount discharged while screen on: ");
1794                    pw.println(getDischargeAmountScreenOnSinceCharge());
1795            pw.print(prefix); pw.print("    Amount discharged while screen off: ");
1796                    pw.println(getDischargeAmountScreenOffSinceCharge());
1797            pw.println();
1798        }
1799
1800        if (timers.size() > 0) {
1801            Collections.sort(timers, timerComparator);
1802            pw.print(prefix); pw.println("  All partial wake locks:");
1803            for (int i=0; i<timers.size(); i++) {
1804                TimerEntry timer = timers.get(i);
1805                sb.setLength(0);
1806                sb.append("  Wake lock #");
1807                sb.append(timer.mId);
1808                sb.append(" ");
1809                sb.append(timer.mName);
1810                printWakeLock(sb, timer.mTimer, batteryRealtime, null, which, ": ");
1811                sb.append(" realtime");
1812                pw.println(sb.toString());
1813            }
1814            timers.clear();
1815            pw.println();
1816        }
1817
1818        for (int iu=0; iu<NU; iu++) {
1819            final int uid = uidStats.keyAt(iu);
1820            if (reqUid >= 0 && uid != reqUid && uid != Process.SYSTEM_UID) {
1821                continue;
1822            }
1823
1824            Uid u = uidStats.valueAt(iu);
1825
1826            pw.println(prefix + "  #" + uid + ":");
1827            boolean uidActivity = false;
1828
1829            long mobileRxBytes = u.getNetworkActivityCount(NETWORK_MOBILE_RX_BYTES, which);
1830            long mobileTxBytes = u.getNetworkActivityCount(NETWORK_MOBILE_TX_BYTES, which);
1831            long wifiRxBytes = u.getNetworkActivityCount(NETWORK_WIFI_RX_BYTES, which);
1832            long wifiTxBytes = u.getNetworkActivityCount(NETWORK_WIFI_TX_BYTES, which);
1833            long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
1834            long wifiScanTime = u.getWifiScanTime(batteryRealtime, which);
1835            long uidWifiRunningTime = u.getWifiRunningTime(batteryRealtime, which);
1836
1837            if (mobileRxBytes > 0 || mobileTxBytes > 0) {
1838                pw.print(prefix); pw.print("    Mobile network: ");
1839                        pw.print(formatBytesLocked(mobileRxBytes)); pw.print(" received, ");
1840                        pw.print(formatBytesLocked(mobileTxBytes)); pw.println(" sent");
1841            }
1842            if (wifiRxBytes > 0 || wifiTxBytes > 0) {
1843                pw.print(prefix); pw.print("    Wi-Fi network: ");
1844                        pw.print(formatBytesLocked(wifiRxBytes)); pw.print(" received, ");
1845                        pw.print(formatBytesLocked(wifiTxBytes)); pw.println(" sent");
1846            }
1847
1848            if (u.hasUserActivity()) {
1849                boolean hasData = false;
1850                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
1851                    int val = u.getUserActivityCount(i, which);
1852                    if (val != 0) {
1853                        if (!hasData) {
1854                            sb.setLength(0);
1855                            sb.append("    User activity: ");
1856                            hasData = true;
1857                        } else {
1858                            sb.append(", ");
1859                        }
1860                        sb.append(val);
1861                        sb.append(" ");
1862                        sb.append(Uid.USER_ACTIVITY_TYPES[i]);
1863                    }
1864                }
1865                if (hasData) {
1866                    pw.println(sb.toString());
1867                }
1868            }
1869
1870            if (fullWifiLockOnTime != 0 || wifiScanTime != 0
1871                    || uidWifiRunningTime != 0) {
1872                sb.setLength(0);
1873                sb.append(prefix); sb.append("    Wifi Running: ");
1874                        formatTimeMs(sb, uidWifiRunningTime / 1000);
1875                        sb.append("("); sb.append(formatRatioLocked(uidWifiRunningTime,
1876                                whichBatteryRealtime)); sb.append(")\n");
1877                sb.append(prefix); sb.append("    Full Wifi Lock: ");
1878                        formatTimeMs(sb, fullWifiLockOnTime / 1000);
1879                        sb.append("("); sb.append(formatRatioLocked(fullWifiLockOnTime,
1880                                whichBatteryRealtime)); sb.append(")\n");
1881                sb.append(prefix); sb.append("    Wifi Scan: ");
1882                        formatTimeMs(sb, wifiScanTime / 1000);
1883                        sb.append("("); sb.append(formatRatioLocked(wifiScanTime,
1884                                whichBatteryRealtime)); sb.append(")");
1885                pw.println(sb.toString());
1886            }
1887
1888            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
1889            if (wakelocks.size() > 0) {
1890                long totalFull = 0, totalPartial = 0, totalWindow = 0;
1891                int count = 0;
1892                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
1893                    : wakelocks.entrySet()) {
1894                    Uid.Wakelock wl = ent.getValue();
1895                    String linePrefix = ": ";
1896                    sb.setLength(0);
1897                    sb.append(prefix);
1898                    sb.append("    Wake lock ");
1899                    sb.append(ent.getKey());
1900                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_FULL), batteryRealtime,
1901                            "full", which, linePrefix);
1902                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), batteryRealtime,
1903                            "partial", which, linePrefix);
1904                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), batteryRealtime,
1905                            "window", which, linePrefix);
1906                    if (!linePrefix.equals(": ")) {
1907                        sb.append(" realtime");
1908                        // Only print out wake locks that were held
1909                        pw.println(sb.toString());
1910                        uidActivity = true;
1911                        count++;
1912                    }
1913                    totalFull += computeWakeLock(wl.getWakeTime(WAKE_TYPE_FULL),
1914                            batteryRealtime, which);
1915                    totalPartial += computeWakeLock(wl.getWakeTime(WAKE_TYPE_PARTIAL),
1916                            batteryRealtime, which);
1917                    totalWindow += computeWakeLock(wl.getWakeTime(WAKE_TYPE_WINDOW),
1918                            batteryRealtime, which);
1919                }
1920                if (count > 1) {
1921                    if (totalFull != 0 || totalPartial != 0 || totalWindow != 0) {
1922                        sb.setLength(0);
1923                        sb.append(prefix);
1924                        sb.append("    TOTAL wake: ");
1925                        boolean needComma = false;
1926                        if (totalFull != 0) {
1927                            needComma = true;
1928                            formatTimeMs(sb, totalFull);
1929                            sb.append("full");
1930                        }
1931                        if (totalPartial != 0) {
1932                            if (needComma) {
1933                                sb.append(", ");
1934                            }
1935                            needComma = true;
1936                            formatTimeMs(sb, totalPartial);
1937                            sb.append("partial");
1938                        }
1939                        if (totalWindow != 0) {
1940                            if (needComma) {
1941                                sb.append(", ");
1942                            }
1943                            needComma = true;
1944                            formatTimeMs(sb, totalWindow);
1945                            sb.append("window");
1946                        }
1947                        sb.append(" realtime");
1948                        pw.println(sb.toString());
1949                    }
1950                }
1951            }
1952
1953            Map<Integer, ? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
1954            if (sensors.size() > 0) {
1955                for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> ent
1956                    : sensors.entrySet()) {
1957                    Uid.Sensor se = ent.getValue();
1958                    int sensorNumber = ent.getKey();
1959                    sb.setLength(0);
1960                    sb.append(prefix);
1961                    sb.append("    Sensor ");
1962                    int handle = se.getHandle();
1963                    if (handle == Uid.Sensor.GPS) {
1964                        sb.append("GPS");
1965                    } else {
1966                        sb.append(handle);
1967                    }
1968                    sb.append(": ");
1969
1970                    Timer timer = se.getSensorTime();
1971                    if (timer != null) {
1972                        // Convert from microseconds to milliseconds with rounding
1973                        long totalTime = (timer.getTotalTimeLocked(
1974                                batteryRealtime, which) + 500) / 1000;
1975                        int count = timer.getCountLocked(which);
1976                        //timer.logState();
1977                        if (totalTime != 0) {
1978                            formatTimeMs(sb, totalTime);
1979                            sb.append("realtime (");
1980                            sb.append(count);
1981                            sb.append(" times)");
1982                        } else {
1983                            sb.append("(not used)");
1984                        }
1985                    } else {
1986                        sb.append("(not used)");
1987                    }
1988
1989                    pw.println(sb.toString());
1990                    uidActivity = true;
1991                }
1992            }
1993
1994            Timer vibTimer = u.getVibratorOnTimer();
1995            if (vibTimer != null) {
1996                // Convert from microseconds to milliseconds with rounding
1997                long totalTime = (vibTimer.getTotalTimeLocked(
1998                        batteryRealtime, which) + 500) / 1000;
1999                int count = vibTimer.getCountLocked(which);
2000                //timer.logState();
2001                if (totalTime != 0) {
2002                    sb.setLength(0);
2003                    sb.append(prefix);
2004                    sb.append("    Vibrator: ");
2005                    formatTimeMs(sb, totalTime);
2006                    sb.append("realtime (");
2007                    sb.append(count);
2008                    sb.append(" times)");
2009                    pw.println(sb.toString());
2010                    uidActivity = true;
2011                }
2012            }
2013
2014            Timer fgTimer = u.getForegroundActivityTimer();
2015            if (fgTimer != null) {
2016                // Convert from microseconds to milliseconds with rounding
2017                long totalTime = (fgTimer.getTotalTimeLocked(batteryRealtime, which) + 500) / 1000;
2018                int count = fgTimer.getCountLocked(which);
2019                if (totalTime != 0) {
2020                    sb.setLength(0);
2021                    sb.append(prefix);
2022                    sb.append("    Foreground activities: ");
2023                    formatTimeMs(sb, totalTime);
2024                    sb.append("realtime (");
2025                    sb.append(count);
2026                    sb.append(" times)");
2027                    pw.println(sb.toString());
2028                    uidActivity = true;
2029                }
2030            }
2031
2032            Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
2033            if (processStats.size() > 0) {
2034                for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
2035                    : processStats.entrySet()) {
2036                    Uid.Proc ps = ent.getValue();
2037                    long userTime;
2038                    long systemTime;
2039                    long foregroundTime;
2040                    int starts;
2041                    int numExcessive;
2042
2043                    userTime = ps.getUserTime(which);
2044                    systemTime = ps.getSystemTime(which);
2045                    foregroundTime = ps.getForegroundTime(which);
2046                    starts = ps.getStarts(which);
2047                    numExcessive = which == STATS_SINCE_CHARGED
2048                            ? ps.countExcessivePowers() : 0;
2049
2050                    if (userTime != 0 || systemTime != 0 || foregroundTime != 0 || starts != 0
2051                            || numExcessive != 0) {
2052                        sb.setLength(0);
2053                        sb.append(prefix); sb.append("    Proc ");
2054                                sb.append(ent.getKey()); sb.append(":\n");
2055                        sb.append(prefix); sb.append("      CPU: ");
2056                                formatTime(sb, userTime); sb.append("usr + ");
2057                                formatTime(sb, systemTime); sb.append("krn ; ");
2058                                formatTime(sb, foregroundTime); sb.append("fg");
2059                        if (starts != 0) {
2060                            sb.append("\n"); sb.append(prefix); sb.append("      ");
2061                                    sb.append(starts); sb.append(" proc starts");
2062                        }
2063                        pw.println(sb.toString());
2064                        for (int e=0; e<numExcessive; e++) {
2065                            Uid.Proc.ExcessivePower ew = ps.getExcessivePower(e);
2066                            if (ew != null) {
2067                                pw.print(prefix); pw.print("      * Killed for ");
2068                                        if (ew.type == Uid.Proc.ExcessivePower.TYPE_WAKE) {
2069                                            pw.print("wake lock");
2070                                        } else if (ew.type == Uid.Proc.ExcessivePower.TYPE_CPU) {
2071                                            pw.print("cpu");
2072                                        } else {
2073                                            pw.print("unknown");
2074                                        }
2075                                        pw.print(" use: ");
2076                                        TimeUtils.formatDuration(ew.usedTime, pw);
2077                                        pw.print(" over ");
2078                                        TimeUtils.formatDuration(ew.overTime, pw);
2079                                        pw.print(" (");
2080                                        pw.print((ew.usedTime*100)/ew.overTime);
2081                                        pw.println("%)");
2082                            }
2083                        }
2084                        uidActivity = true;
2085                    }
2086                }
2087            }
2088
2089            Map<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats();
2090            if (packageStats.size() > 0) {
2091                for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent
2092                    : packageStats.entrySet()) {
2093                    pw.print(prefix); pw.print("    Apk "); pw.print(ent.getKey()); pw.println(":");
2094                    boolean apkActivity = false;
2095                    Uid.Pkg ps = ent.getValue();
2096                    int wakeups = ps.getWakeups(which);
2097                    if (wakeups != 0) {
2098                        pw.print(prefix); pw.print("      ");
2099                                pw.print(wakeups); pw.println(" wakeup alarms");
2100                        apkActivity = true;
2101                    }
2102                    Map<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
2103                    if (serviceStats.size() > 0) {
2104                        for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent
2105                                : serviceStats.entrySet()) {
2106                            BatteryStats.Uid.Pkg.Serv ss = sent.getValue();
2107                            long startTime = ss.getStartTime(batteryUptime, which);
2108                            int starts = ss.getStarts(which);
2109                            int launches = ss.getLaunches(which);
2110                            if (startTime != 0 || starts != 0 || launches != 0) {
2111                                sb.setLength(0);
2112                                sb.append(prefix); sb.append("      Service ");
2113                                        sb.append(sent.getKey()); sb.append(":\n");
2114                                sb.append(prefix); sb.append("        Created for: ");
2115                                        formatTimeMs(sb, startTime / 1000);
2116                                        sb.append("uptime\n");
2117                                sb.append(prefix); sb.append("        Starts: ");
2118                                        sb.append(starts);
2119                                        sb.append(", launches: "); sb.append(launches);
2120                                pw.println(sb.toString());
2121                                apkActivity = true;
2122                            }
2123                        }
2124                    }
2125                    if (!apkActivity) {
2126                        pw.print(prefix); pw.println("      (nothing executed)");
2127                    }
2128                    uidActivity = true;
2129                }
2130            }
2131            if (!uidActivity) {
2132                pw.print(prefix); pw.println("    (nothing executed)");
2133            }
2134        }
2135    }
2136
2137    static void printBitDescriptions(PrintWriter pw, int oldval, int newval, BitDescription[] descriptions) {
2138        int diff = oldval ^ newval;
2139        if (diff == 0) return;
2140        for (int i=0; i<descriptions.length; i++) {
2141            BitDescription bd = descriptions[i];
2142            if ((diff&bd.mask) != 0) {
2143                if (bd.shift < 0) {
2144                    pw.print((newval&bd.mask) != 0 ? " +" : " -");
2145                    pw.print(bd.name);
2146                } else {
2147                    pw.print(" ");
2148                    pw.print(bd.name);
2149                    pw.print("=");
2150                    int val = (newval&bd.mask)>>bd.shift;
2151                    if (bd.values != null && val >= 0 && val < bd.values.length) {
2152                        pw.print(bd.values[val]);
2153                    } else {
2154                        pw.print(val);
2155                    }
2156                }
2157            }
2158        }
2159    }
2160
2161    public void prepareForDumpLocked() {
2162    }
2163
2164    public static class HistoryPrinter {
2165        int oldState = 0;
2166        int oldStatus = -1;
2167        int oldHealth = -1;
2168        int oldPlug = -1;
2169        int oldTemp = -1;
2170        int oldVolt = -1;
2171
2172        public void printNextItem(PrintWriter pw, HistoryItem rec, long now) {
2173            pw.print("  ");
2174            TimeUtils.formatDuration(rec.time-now, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
2175            pw.print(" ");
2176            if (rec.cmd == HistoryItem.CMD_START) {
2177                pw.println(" START");
2178            } else if (rec.cmd == HistoryItem.CMD_OVERFLOW) {
2179                pw.println(" *OVERFLOW*");
2180            } else {
2181                if (rec.batteryLevel < 10) pw.print("00");
2182                else if (rec.batteryLevel < 100) pw.print("0");
2183                pw.print(rec.batteryLevel);
2184                pw.print(" ");
2185                if (rec.states < 0x10) pw.print("0000000");
2186                else if (rec.states < 0x100) pw.print("000000");
2187                else if (rec.states < 0x1000) pw.print("00000");
2188                else if (rec.states < 0x10000) pw.print("0000");
2189                else if (rec.states < 0x100000) pw.print("000");
2190                else if (rec.states < 0x1000000) pw.print("00");
2191                else if (rec.states < 0x10000000) pw.print("0");
2192                pw.print(Integer.toHexString(rec.states));
2193                if (oldStatus != rec.batteryStatus) {
2194                    oldStatus = rec.batteryStatus;
2195                    pw.print(" status=");
2196                    switch (oldStatus) {
2197                        case BatteryManager.BATTERY_STATUS_UNKNOWN:
2198                            pw.print("unknown");
2199                            break;
2200                        case BatteryManager.BATTERY_STATUS_CHARGING:
2201                            pw.print("charging");
2202                            break;
2203                        case BatteryManager.BATTERY_STATUS_DISCHARGING:
2204                            pw.print("discharging");
2205                            break;
2206                        case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
2207                            pw.print("not-charging");
2208                            break;
2209                        case BatteryManager.BATTERY_STATUS_FULL:
2210                            pw.print("full");
2211                            break;
2212                        default:
2213                            pw.print(oldStatus);
2214                            break;
2215                    }
2216                }
2217                if (oldHealth != rec.batteryHealth) {
2218                    oldHealth = rec.batteryHealth;
2219                    pw.print(" health=");
2220                    switch (oldHealth) {
2221                        case BatteryManager.BATTERY_HEALTH_UNKNOWN:
2222                            pw.print("unknown");
2223                            break;
2224                        case BatteryManager.BATTERY_HEALTH_GOOD:
2225                            pw.print("good");
2226                            break;
2227                        case BatteryManager.BATTERY_HEALTH_OVERHEAT:
2228                            pw.print("overheat");
2229                            break;
2230                        case BatteryManager.BATTERY_HEALTH_DEAD:
2231                            pw.print("dead");
2232                            break;
2233                        case BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE:
2234                            pw.print("over-voltage");
2235                            break;
2236                        case BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE:
2237                            pw.print("failure");
2238                            break;
2239                        default:
2240                            pw.print(oldHealth);
2241                            break;
2242                    }
2243                }
2244                if (oldPlug != rec.batteryPlugType) {
2245                    oldPlug = rec.batteryPlugType;
2246                    pw.print(" plug=");
2247                    switch (oldPlug) {
2248                        case 0:
2249                            pw.print("none");
2250                            break;
2251                        case BatteryManager.BATTERY_PLUGGED_AC:
2252                            pw.print("ac");
2253                            break;
2254                        case BatteryManager.BATTERY_PLUGGED_USB:
2255                            pw.print("usb");
2256                            break;
2257                        case BatteryManager.BATTERY_PLUGGED_WIRELESS:
2258                            pw.print("wireless");
2259                            break;
2260                        default:
2261                            pw.print(oldPlug);
2262                            break;
2263                    }
2264                }
2265                if (oldTemp != rec.batteryTemperature) {
2266                    oldTemp = rec.batteryTemperature;
2267                    pw.print(" temp=");
2268                    pw.print(oldTemp);
2269                }
2270                if (oldVolt != rec.batteryVoltage) {
2271                    oldVolt = rec.batteryVoltage;
2272                    pw.print(" volt=");
2273                    pw.print(oldVolt);
2274                }
2275                printBitDescriptions(pw, oldState, rec.states,
2276                        HISTORY_STATE_DESCRIPTIONS);
2277                pw.println();
2278            }
2279            oldState = rec.states;
2280        }
2281
2282        public void printNextItemCheckin(PrintWriter pw, HistoryItem rec, long now) {
2283            pw.print(rec.time-now);
2284            pw.print(",");
2285            if (rec.cmd == HistoryItem.CMD_START) {
2286                pw.print("start");
2287            } else if (rec.cmd == HistoryItem.CMD_OVERFLOW) {
2288                pw.print("overflow");
2289            } else {
2290                pw.print(rec.batteryLevel);
2291                pw.print(",");
2292                pw.print(rec.states);
2293                pw.print(",");
2294                pw.print(rec.batteryStatus);
2295                pw.print(",");
2296                pw.print(rec.batteryHealth);
2297                pw.print(",");
2298                pw.print(rec.batteryPlugType);
2299                pw.print(",");
2300                pw.print((int)rec.batteryTemperature);
2301                pw.print(",");
2302                pw.print((int)rec.batteryVoltage);
2303            }
2304        }
2305    }
2306
2307    /**
2308     * Dumps a human-readable summary of the battery statistics to the given PrintWriter.
2309     *
2310     * @param pw a Printer to receive the dump output.
2311     */
2312    @SuppressWarnings("unused")
2313    public void dumpLocked(PrintWriter pw, boolean isUnpluggedOnly, int reqUid) {
2314        prepareForDumpLocked();
2315
2316        long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
2317
2318        final HistoryItem rec = new HistoryItem();
2319        if (startIteratingHistoryLocked()) {
2320            pw.println("Battery History:");
2321            HistoryPrinter hprinter = new HistoryPrinter();
2322            while (getNextHistoryLocked(rec)) {
2323                hprinter.printNextItem(pw, rec, now);
2324            }
2325            finishIteratingHistoryLocked();
2326            pw.println("");
2327        }
2328
2329        if (startIteratingOldHistoryLocked()) {
2330            pw.println("Old battery History:");
2331            HistoryPrinter hprinter = new HistoryPrinter();
2332            while (getNextOldHistoryLocked(rec)) {
2333                hprinter.printNextItem(pw, rec, now);
2334            }
2335            finishIteratingOldHistoryLocked();
2336            pw.println("");
2337        }
2338
2339        SparseArray<? extends Uid> uidStats = getUidStats();
2340        final int NU = uidStats.size();
2341        boolean didPid = false;
2342        long nowRealtime = SystemClock.elapsedRealtime();
2343        for (int i=0; i<NU; i++) {
2344            Uid uid = uidStats.valueAt(i);
2345            SparseArray<? extends Uid.Pid> pids = uid.getPidStats();
2346            if (pids != null) {
2347                for (int j=0; j<pids.size(); j++) {
2348                    Uid.Pid pid = pids.valueAt(j);
2349                    if (!didPid) {
2350                        pw.println("Per-PID Stats:");
2351                        didPid = true;
2352                    }
2353                    long time = pid.mWakeSum + (pid.mWakeStart != 0
2354                            ? (nowRealtime - pid.mWakeStart) : 0);
2355                    pw.print("  PID "); pw.print(pids.keyAt(j));
2356                            pw.print(" wake time: ");
2357                            TimeUtils.formatDuration(time, pw);
2358                            pw.println("");
2359                }
2360            }
2361        }
2362        if (didPid) {
2363            pw.println("");
2364        }
2365
2366        if (!isUnpluggedOnly) {
2367            pw.println("Statistics since last charge:");
2368            pw.println("  System starts: " + getStartCount()
2369                    + ", currently on battery: " + getIsOnBattery());
2370            dumpLocked(pw, "", STATS_SINCE_CHARGED, reqUid);
2371            pw.println("");
2372        }
2373        pw.println("Statistics since last unplugged:");
2374        dumpLocked(pw, "", STATS_SINCE_UNPLUGGED, reqUid);
2375    }
2376
2377    @SuppressWarnings("unused")
2378    public void dumpCheckinLocked(
2379            PrintWriter pw, List<ApplicationInfo> apps, boolean isUnpluggedOnly) {
2380        prepareForDumpLocked();
2381
2382        long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
2383
2384        final HistoryItem rec = new HistoryItem();
2385        if (startIteratingHistoryLocked()) {
2386            HistoryPrinter hprinter = new HistoryPrinter();
2387            while (getNextHistoryLocked(rec)) {
2388                pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
2389                pw.print(0); pw.print(',');
2390                pw.print("h"); pw.print(',');
2391                hprinter.printNextItemCheckin(pw, rec, now);
2392                pw.println();
2393            }
2394            finishIteratingHistoryLocked();
2395        }
2396
2397        if (apps != null) {
2398            SparseArray<ArrayList<String>> uids = new SparseArray<ArrayList<String>>();
2399            for (int i=0; i<apps.size(); i++) {
2400                ApplicationInfo ai = apps.get(i);
2401                ArrayList<String> pkgs = uids.get(ai.uid);
2402                if (pkgs == null) {
2403                    pkgs = new ArrayList<String>();
2404                    uids.put(ai.uid, pkgs);
2405                }
2406                pkgs.add(ai.packageName);
2407            }
2408            SparseArray<? extends Uid> uidStats = getUidStats();
2409            final int NU = uidStats.size();
2410            String[] lineArgs = new String[2];
2411            for (int i=0; i<NU; i++) {
2412                int uid = uidStats.keyAt(i);
2413                ArrayList<String> pkgs = uids.get(uid);
2414                if (pkgs != null) {
2415                    for (int j=0; j<pkgs.size(); j++) {
2416                        lineArgs[0] = Integer.toString(uid);
2417                        lineArgs[1] = pkgs.get(j);
2418                        dumpLine(pw, 0 /* uid */, "i" /* category */, UID_DATA,
2419                                (Object[])lineArgs);
2420                    }
2421                }
2422            }
2423        }
2424        if (isUnpluggedOnly) {
2425            dumpCheckinLocked(pw, STATS_SINCE_UNPLUGGED, -1);
2426        }
2427        else {
2428            dumpCheckinLocked(pw, STATS_SINCE_CHARGED, -1);
2429            dumpCheckinLocked(pw, STATS_SINCE_UNPLUGGED, -1);
2430        }
2431    }
2432}
2433