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