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