BatteryStats.java revision 49021f5f790c31f62d4cee9fafcae13505bed798
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_OTHER = 15;
848
849    static final String[] DATA_CONNECTION_NAMES = {
850        "none", "gprs", "edge", "umts", "cdma", "evdo_0", "evdo_A",
851        "1xrtt", "hsdpa", "hsupa", "hspa", "iden", "evdo_b", "lte",
852        "ehrpd", "other"
853    };
854
855    public static final int NUM_DATA_CONNECTION_TYPES = DATA_CONNECTION_OTHER+1;
856
857    /**
858     * Returns the time in microseconds that the phone has been running with
859     * the given data connection.
860     *
861     * {@hide}
862     */
863    public abstract long getPhoneDataConnectionTime(int dataType,
864            long batteryRealtime, int which);
865
866    /**
867     * Returns the number of times the phone has entered the given data
868     * connection type.
869     *
870     * {@hide}
871     */
872    public abstract int getPhoneDataConnectionCount(int dataType, int which);
873
874    public static final BitDescription[] HISTORY_STATE_DESCRIPTIONS
875            = new BitDescription[] {
876        new BitDescription(HistoryItem.STATE_BATTERY_PLUGGED_FLAG, "plugged"),
877        new BitDescription(HistoryItem.STATE_SCREEN_ON_FLAG, "screen"),
878        new BitDescription(HistoryItem.STATE_GPS_ON_FLAG, "gps"),
879        new BitDescription(HistoryItem.STATE_PHONE_IN_CALL_FLAG, "phone_in_call"),
880        new BitDescription(HistoryItem.STATE_PHONE_SCANNING_FLAG, "phone_scanning"),
881        new BitDescription(HistoryItem.STATE_WIFI_ON_FLAG, "wifi"),
882        new BitDescription(HistoryItem.STATE_WIFI_RUNNING_FLAG, "wifi_running"),
883        new BitDescription(HistoryItem.STATE_WIFI_FULL_LOCK_FLAG, "wifi_full_lock"),
884        new BitDescription(HistoryItem.STATE_WIFI_SCAN_FLAG, "wifi_scan"),
885        new BitDescription(HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG, "wifi_multicast"),
886        new BitDescription(HistoryItem.STATE_BLUETOOTH_ON_FLAG, "bluetooth"),
887        new BitDescription(HistoryItem.STATE_AUDIO_ON_FLAG, "audio"),
888        new BitDescription(HistoryItem.STATE_VIDEO_ON_FLAG, "video"),
889        new BitDescription(HistoryItem.STATE_WAKE_LOCK_FLAG, "wake_lock"),
890        new BitDescription(HistoryItem.STATE_SENSOR_ON_FLAG, "sensor"),
891        new BitDescription(HistoryItem.STATE_BRIGHTNESS_MASK,
892                HistoryItem.STATE_BRIGHTNESS_SHIFT, "brightness",
893                SCREEN_BRIGHTNESS_NAMES),
894        new BitDescription(HistoryItem.STATE_SIGNAL_STRENGTH_MASK,
895                HistoryItem.STATE_SIGNAL_STRENGTH_SHIFT, "signal_strength",
896                SignalStrength.SIGNAL_STRENGTH_NAMES),
897        new BitDescription(HistoryItem.STATE_PHONE_STATE_MASK,
898                HistoryItem.STATE_PHONE_STATE_SHIFT, "phone_state",
899                new String[] {"in", "out", "emergency", "off"}),
900        new BitDescription(HistoryItem.STATE_DATA_CONNECTION_MASK,
901                HistoryItem.STATE_DATA_CONNECTION_SHIFT, "data_conn",
902                DATA_CONNECTION_NAMES),
903    };
904
905    /**
906     * Returns the time in microseconds that wifi has been on while the device was
907     * running on battery.
908     *
909     * {@hide}
910     */
911    public abstract long getWifiOnTime(long batteryRealtime, int which);
912
913    /**
914     * Returns the time in microseconds that wifi has been on and the driver has
915     * been in the running state while the device was running on battery.
916     *
917     * {@hide}
918     */
919    public abstract long getGlobalWifiRunningTime(long batteryRealtime, int which);
920
921    /**
922     * Returns the time in microseconds that bluetooth has been on while the device was
923     * running on battery.
924     *
925     * {@hide}
926     */
927    public abstract long getBluetoothOnTime(long batteryRealtime, int which);
928
929    public static final int NETWORK_MOBILE_RX_BYTES = 0;
930    public static final int NETWORK_MOBILE_TX_BYTES = 1;
931    public static final int NETWORK_WIFI_RX_BYTES = 2;
932    public static final int NETWORK_WIFI_TX_BYTES = 3;
933
934    public static final int NUM_NETWORK_ACTIVITY_TYPES = NETWORK_WIFI_TX_BYTES + 1;
935
936    public abstract long getNetworkActivityCount(int type, int which);
937
938    /**
939     * Return whether we are currently running on battery.
940     */
941    public abstract boolean getIsOnBattery();
942
943    /**
944     * Returns a SparseArray containing the statistics for each uid.
945     */
946    public abstract SparseArray<? extends Uid> getUidStats();
947
948    /**
949     * Returns the current battery uptime in microseconds.
950     *
951     * @param curTime the amount of elapsed realtime in microseconds.
952     */
953    public abstract long getBatteryUptime(long curTime);
954
955    /**
956     * @deprecated use getRadioDataUptime
957     */
958    public long getRadioDataUptimeMs() {
959        return getRadioDataUptime() / 1000;
960    }
961
962    /**
963     * Returns the time that the radio was on for data transfers.
964     * @return the uptime in microseconds while unplugged
965     */
966    public abstract long getRadioDataUptime();
967
968    /**
969     * Returns the current battery realtime in microseconds.
970     *
971     * @param curTime the amount of elapsed realtime in microseconds.
972     */
973    public abstract long getBatteryRealtime(long curTime);
974
975    /**
976     * Returns the battery percentage level at the last time the device was unplugged from power, or
977     * the last time it booted on battery power.
978     */
979    public abstract int getDischargeStartLevel();
980
981    /**
982     * Returns the current battery percentage level if we are in a discharge cycle, otherwise
983     * returns the level at the last plug event.
984     */
985    public abstract int getDischargeCurrentLevel();
986
987    /**
988     * Get the amount the battery has discharged since the stats were
989     * last reset after charging, as a lower-end approximation.
990     */
991    public abstract int getLowDischargeAmountSinceCharge();
992
993    /**
994     * Get the amount the battery has discharged since the stats were
995     * last reset after charging, as an upper-end approximation.
996     */
997    public abstract int getHighDischargeAmountSinceCharge();
998
999    /**
1000     * Get the amount the battery has discharged while the screen was on,
1001     * since the last time power was unplugged.
1002     */
1003    public abstract int getDischargeAmountScreenOn();
1004
1005    /**
1006     * Get the amount the battery has discharged while the screen was on,
1007     * since the last time the device was charged.
1008     */
1009    public abstract int getDischargeAmountScreenOnSinceCharge();
1010
1011    /**
1012     * Get the amount the battery has discharged while the screen was off,
1013     * since the last time power was unplugged.
1014     */
1015    public abstract int getDischargeAmountScreenOff();
1016
1017    /**
1018     * Get the amount the battery has discharged while the screen was off,
1019     * since the last time the device was charged.
1020     */
1021    public abstract int getDischargeAmountScreenOffSinceCharge();
1022
1023    /**
1024     * Returns the total, last, or current battery uptime in microseconds.
1025     *
1026     * @param curTime the elapsed realtime in microseconds.
1027     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
1028     */
1029    public abstract long computeBatteryUptime(long curTime, int which);
1030
1031    /**
1032     * Returns the total, last, or current battery realtime in microseconds.
1033     *
1034     * @param curTime the current elapsed realtime in microseconds.
1035     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
1036     */
1037    public abstract long computeBatteryRealtime(long curTime, int which);
1038
1039    /**
1040     * Returns the total, last, or current uptime in microseconds.
1041     *
1042     * @param curTime the current elapsed realtime in microseconds.
1043     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
1044     */
1045    public abstract long computeUptime(long curTime, int which);
1046
1047    /**
1048     * Returns the total, last, or current realtime in microseconds.
1049     * *
1050     * @param curTime the current elapsed realtime in microseconds.
1051     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
1052     */
1053    public abstract long computeRealtime(long curTime, int which);
1054
1055    public abstract Map<String, ? extends Timer> getKernelWakelockStats();
1056
1057    /** Returns the number of different speeds that the CPU can run at */
1058    public abstract int getCpuSpeedSteps();
1059
1060    private final static void formatTimeRaw(StringBuilder out, long seconds) {
1061        long days = seconds / (60 * 60 * 24);
1062        if (days != 0) {
1063            out.append(days);
1064            out.append("d ");
1065        }
1066        long used = days * 60 * 60 * 24;
1067
1068        long hours = (seconds - used) / (60 * 60);
1069        if (hours != 0 || used != 0) {
1070            out.append(hours);
1071            out.append("h ");
1072        }
1073        used += hours * 60 * 60;
1074
1075        long mins = (seconds-used) / 60;
1076        if (mins != 0 || used != 0) {
1077            out.append(mins);
1078            out.append("m ");
1079        }
1080        used += mins * 60;
1081
1082        if (seconds != 0 || used != 0) {
1083            out.append(seconds-used);
1084            out.append("s ");
1085        }
1086    }
1087
1088    private final static void formatTime(StringBuilder sb, long time) {
1089        long sec = time / 100;
1090        formatTimeRaw(sb, sec);
1091        sb.append((time - (sec * 100)) * 10);
1092        sb.append("ms ");
1093    }
1094
1095    private final static void formatTimeMs(StringBuilder sb, long time) {
1096        long sec = time / 1000;
1097        formatTimeRaw(sb, sec);
1098        sb.append(time - (sec * 1000));
1099        sb.append("ms ");
1100    }
1101
1102    private final String formatRatioLocked(long num, long den) {
1103        if (den == 0L) {
1104            return "---%";
1105        }
1106        float perc = ((float)num) / ((float)den) * 100;
1107        mFormatBuilder.setLength(0);
1108        mFormatter.format("%.1f%%", perc);
1109        return mFormatBuilder.toString();
1110    }
1111
1112    private final String formatBytesLocked(long bytes) {
1113        mFormatBuilder.setLength(0);
1114
1115        if (bytes < BYTES_PER_KB) {
1116            return bytes + "B";
1117        } else if (bytes < BYTES_PER_MB) {
1118            mFormatter.format("%.2fKB", bytes / (double) BYTES_PER_KB);
1119            return mFormatBuilder.toString();
1120        } else if (bytes < BYTES_PER_GB){
1121            mFormatter.format("%.2fMB", bytes / (double) BYTES_PER_MB);
1122            return mFormatBuilder.toString();
1123        } else {
1124            mFormatter.format("%.2fGB", bytes / (double) BYTES_PER_GB);
1125            return mFormatBuilder.toString();
1126        }
1127    }
1128
1129    private static long computeWakeLock(Timer timer, long batteryRealtime, int which) {
1130        if (timer != null) {
1131            // Convert from microseconds to milliseconds with rounding
1132            long totalTimeMicros = timer.getTotalTimeLocked(batteryRealtime, which);
1133            long totalTimeMillis = (totalTimeMicros + 500) / 1000;
1134            return totalTimeMillis;
1135        }
1136        return 0;
1137    }
1138
1139    /**
1140     *
1141     * @param sb a StringBuilder object.
1142     * @param timer a Timer object contining the wakelock times.
1143     * @param batteryRealtime the current on-battery time in microseconds.
1144     * @param name the name of the wakelock.
1145     * @param which which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
1146     * @param linePrefix a String to be prepended to each line of output.
1147     * @return the line prefix
1148     */
1149    private static final String printWakeLock(StringBuilder sb, Timer timer,
1150            long batteryRealtime, String name, int which, String linePrefix) {
1151
1152        if (timer != null) {
1153            long totalTimeMillis = computeWakeLock(timer, batteryRealtime, which);
1154
1155            int count = timer.getCountLocked(which);
1156            if (totalTimeMillis != 0) {
1157                sb.append(linePrefix);
1158                formatTimeMs(sb, totalTimeMillis);
1159                if (name != null) {
1160                    sb.append(name);
1161                    sb.append(' ');
1162                }
1163                sb.append('(');
1164                sb.append(count);
1165                sb.append(" times)");
1166                return ", ";
1167            }
1168        }
1169        return linePrefix;
1170    }
1171
1172    /**
1173     * Checkin version of wakelock printer. Prints simple comma-separated list.
1174     *
1175     * @param sb a StringBuilder object.
1176     * @param timer a Timer object contining the wakelock times.
1177     * @param now the current time in microseconds.
1178     * @param name the name of the wakelock.
1179     * @param which which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
1180     * @param linePrefix a String to be prepended to each line of output.
1181     * @return the line prefix
1182     */
1183    private static final String printWakeLockCheckin(StringBuilder sb, Timer timer, long now,
1184            String name, int which, String linePrefix) {
1185        long totalTimeMicros = 0;
1186        int count = 0;
1187        if (timer != null) {
1188            totalTimeMicros = timer.getTotalTimeLocked(now, which);
1189            count = timer.getCountLocked(which);
1190        }
1191        sb.append(linePrefix);
1192        sb.append((totalTimeMicros + 500) / 1000); // microseconds to milliseconds with rounding
1193        sb.append(',');
1194        sb.append(name != null ? name + "," : "");
1195        sb.append(count);
1196        return ",";
1197    }
1198
1199    /**
1200     * Dump a comma-separated line of values for terse checkin mode.
1201     *
1202     * @param pw the PageWriter to dump log to
1203     * @param category category of data (e.g. "total", "last", "unplugged", "current" )
1204     * @param type type of data (e.g. "wakelock", "sensor", "process", "apk" ,  "process", "network")
1205     * @param args type-dependent data arguments
1206     */
1207    private static final void dumpLine(PrintWriter pw, int uid, String category, String type,
1208           Object... args ) {
1209        pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
1210        pw.print(uid); pw.print(',');
1211        pw.print(category); pw.print(',');
1212        pw.print(type);
1213
1214        for (Object arg : args) {
1215            pw.print(',');
1216            pw.print(arg);
1217        }
1218        pw.println();
1219    }
1220
1221    /**
1222     * Checkin server version of dump to produce more compact, computer-readable log.
1223     *
1224     * NOTE: all times are expressed in 'ms'.
1225     */
1226    public final void dumpCheckinLocked(PrintWriter pw, int which, int reqUid) {
1227        final long rawUptime = SystemClock.uptimeMillis() * 1000;
1228        final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
1229        final long batteryUptime = getBatteryUptime(rawUptime);
1230        final long batteryRealtime = getBatteryRealtime(rawRealtime);
1231        final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
1232        final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
1233        final long totalRealtime = computeRealtime(rawRealtime, which);
1234        final long totalUptime = computeUptime(rawUptime, which);
1235        final long screenOnTime = getScreenOnTime(batteryRealtime, which);
1236        final long phoneOnTime = getPhoneOnTime(batteryRealtime, which);
1237        final long wifiOnTime = getWifiOnTime(batteryRealtime, which);
1238        final long wifiRunningTime = getGlobalWifiRunningTime(batteryRealtime, which);
1239        final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which);
1240
1241        StringBuilder sb = new StringBuilder(128);
1242
1243        SparseArray<? extends Uid> uidStats = getUidStats();
1244        final int NU = uidStats.size();
1245
1246        String category = STAT_NAMES[which];
1247
1248        // Dump "battery" stat
1249        dumpLine(pw, 0 /* uid */, category, BATTERY_DATA,
1250                which == STATS_SINCE_CHARGED ? getStartCount() : "N/A",
1251                whichBatteryRealtime / 1000, whichBatteryUptime / 1000,
1252                totalRealtime / 1000, totalUptime / 1000);
1253
1254        // Calculate total network and wakelock times across all uids.
1255        long mobileRxTotal = 0;
1256        long mobileTxTotal = 0;
1257        long wifiRxTotal = 0;
1258        long wifiTxTotal = 0;
1259        long fullWakeLockTimeTotal = 0;
1260        long partialWakeLockTimeTotal = 0;
1261
1262        for (int iu = 0; iu < NU; iu++) {
1263            Uid u = uidStats.valueAt(iu);
1264            mobileRxTotal += u.getNetworkActivityCount(NETWORK_MOBILE_RX_BYTES, which);
1265            mobileTxTotal += u.getNetworkActivityCount(NETWORK_MOBILE_TX_BYTES, which);
1266            wifiRxTotal += u.getNetworkActivityCount(NETWORK_WIFI_RX_BYTES, which);
1267            wifiTxTotal += u.getNetworkActivityCount(NETWORK_WIFI_TX_BYTES, which);
1268
1269            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
1270            if (wakelocks.size() > 0) {
1271                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
1272                        : wakelocks.entrySet()) {
1273                    Uid.Wakelock wl = ent.getValue();
1274
1275                    Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
1276                    if (fullWakeTimer != null) {
1277                        fullWakeLockTimeTotal += fullWakeTimer.getTotalTimeLocked(batteryRealtime, which);
1278                    }
1279
1280                    Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
1281                    if (partialWakeTimer != null) {
1282                        partialWakeLockTimeTotal += partialWakeTimer.getTotalTimeLocked(
1283                            batteryRealtime, which);
1284                    }
1285                }
1286            }
1287        }
1288
1289        // Dump misc stats
1290        dumpLine(pw, 0 /* uid */, category, MISC_DATA,
1291                screenOnTime / 1000, phoneOnTime / 1000, wifiOnTime / 1000,
1292                wifiRunningTime / 1000, bluetoothOnTime / 1000,
1293                mobileRxTotal, mobileTxTotal, wifiRxTotal, wifiTxTotal,
1294                fullWakeLockTimeTotal, partialWakeLockTimeTotal,
1295                getInputEventCount(which));
1296
1297        // Dump screen brightness stats
1298        Object[] args = new Object[NUM_SCREEN_BRIGHTNESS_BINS];
1299        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
1300            args[i] = getScreenBrightnessTime(i, batteryRealtime, which) / 1000;
1301        }
1302        dumpLine(pw, 0 /* uid */, category, SCREEN_BRIGHTNESS_DATA, args);
1303
1304        // Dump signal strength stats
1305        args = new Object[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
1306        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
1307            args[i] = getPhoneSignalStrengthTime(i, batteryRealtime, which) / 1000;
1308        }
1309        dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_TIME_DATA, args);
1310        dumpLine(pw, 0 /* uid */, category, SIGNAL_SCANNING_TIME_DATA,
1311                getPhoneSignalScanningTime(batteryRealtime, which) / 1000);
1312        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
1313            args[i] = getPhoneSignalStrengthCount(i, which);
1314        }
1315        dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_COUNT_DATA, args);
1316
1317        // Dump network type stats
1318        args = new Object[NUM_DATA_CONNECTION_TYPES];
1319        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
1320            args[i] = getPhoneDataConnectionTime(i, batteryRealtime, which) / 1000;
1321        }
1322        dumpLine(pw, 0 /* uid */, category, DATA_CONNECTION_TIME_DATA, args);
1323        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
1324            args[i] = getPhoneDataConnectionCount(i, which);
1325        }
1326        dumpLine(pw, 0 /* uid */, category, DATA_CONNECTION_COUNT_DATA, args);
1327
1328        if (which == STATS_SINCE_UNPLUGGED) {
1329            dumpLine(pw, 0 /* uid */, category, BATTERY_LEVEL_DATA, getDischargeStartLevel(),
1330                    getDischargeCurrentLevel());
1331        }
1332
1333        if (which == STATS_SINCE_UNPLUGGED) {
1334            dumpLine(pw, 0 /* uid */, category, BATTERY_DISCHARGE_DATA,
1335                    getDischargeStartLevel()-getDischargeCurrentLevel(),
1336                    getDischargeStartLevel()-getDischargeCurrentLevel(),
1337                    getDischargeAmountScreenOn(), getDischargeAmountScreenOff());
1338        } else {
1339            dumpLine(pw, 0 /* uid */, category, BATTERY_DISCHARGE_DATA,
1340                    getLowDischargeAmountSinceCharge(), getHighDischargeAmountSinceCharge(),
1341                    getDischargeAmountScreenOn(), getDischargeAmountScreenOff());
1342        }
1343
1344        if (reqUid < 0) {
1345            Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats();
1346            if (kernelWakelocks.size() > 0) {
1347                for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) {
1348                    sb.setLength(0);
1349                    printWakeLockCheckin(sb, ent.getValue(), batteryRealtime, null, which, "");
1350
1351                    dumpLine(pw, 0 /* uid */, category, KERNEL_WAKELOCK_DATA, ent.getKey(),
1352                            sb.toString());
1353                }
1354            }
1355        }
1356
1357        for (int iu = 0; iu < NU; iu++) {
1358            final int uid = uidStats.keyAt(iu);
1359            if (reqUid >= 0 && uid != reqUid) {
1360                continue;
1361            }
1362            Uid u = uidStats.valueAt(iu);
1363            // Dump Network stats per uid, if any
1364            long mobileRx = u.getNetworkActivityCount(NETWORK_MOBILE_RX_BYTES, which);
1365            long mobileTx = u.getNetworkActivityCount(NETWORK_MOBILE_TX_BYTES, which);
1366            long wifiRx = u.getNetworkActivityCount(NETWORK_WIFI_RX_BYTES, which);
1367            long wifiTx = u.getNetworkActivityCount(NETWORK_WIFI_TX_BYTES, which);
1368            long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
1369            long wifiScanTime = u.getWifiScanTime(batteryRealtime, which);
1370            long uidWifiRunningTime = u.getWifiRunningTime(batteryRealtime, which);
1371
1372            if (mobileRx > 0 || mobileTx > 0 || wifiRx > 0 || wifiTx > 0) {
1373                dumpLine(pw, uid, category, NETWORK_DATA, mobileRx, mobileTx, wifiRx, wifiTx);
1374            }
1375
1376            if (fullWifiLockOnTime != 0 || wifiScanTime != 0
1377                    || uidWifiRunningTime != 0) {
1378                dumpLine(pw, uid, category, WIFI_DATA,
1379                        fullWifiLockOnTime, wifiScanTime, uidWifiRunningTime);
1380            }
1381
1382            if (u.hasUserActivity()) {
1383                args = new Object[Uid.NUM_USER_ACTIVITY_TYPES];
1384                boolean hasData = false;
1385                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
1386                    int val = u.getUserActivityCount(i, which);
1387                    args[i] = val;
1388                    if (val != 0) hasData = true;
1389                }
1390                if (hasData) {
1391                    dumpLine(pw, 0 /* uid */, category, USER_ACTIVITY_DATA, args);
1392                }
1393            }
1394
1395            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
1396            if (wakelocks.size() > 0) {
1397                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
1398                        : wakelocks.entrySet()) {
1399                    Uid.Wakelock wl = ent.getValue();
1400                    String linePrefix = "";
1401                    sb.setLength(0);
1402                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_FULL),
1403                            batteryRealtime, "f", which, linePrefix);
1404                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL),
1405                            batteryRealtime, "p", which, linePrefix);
1406                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_WINDOW),
1407                            batteryRealtime, "w", which, linePrefix);
1408
1409                    // Only log if we had at lease one wakelock...
1410                    if (sb.length() > 0) {
1411                        String name = ent.getKey();
1412                        if (name.indexOf(',') >= 0) {
1413                            name = name.replace(',', '_');
1414                        }
1415                        dumpLine(pw, uid, category, WAKELOCK_DATA, name, sb.toString());
1416                    }
1417                }
1418            }
1419
1420            Map<Integer, ? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
1421            if (sensors.size() > 0)  {
1422                for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> ent
1423                        : sensors.entrySet()) {
1424                    Uid.Sensor se = ent.getValue();
1425                    int sensorNumber = ent.getKey();
1426                    Timer timer = se.getSensorTime();
1427                    if (timer != null) {
1428                        // Convert from microseconds to milliseconds with rounding
1429                        long totalTime = (timer.getTotalTimeLocked(batteryRealtime, which) + 500) / 1000;
1430                        int count = timer.getCountLocked(which);
1431                        if (totalTime != 0) {
1432                            dumpLine(pw, uid, category, SENSOR_DATA, sensorNumber, totalTime, count);
1433                        }
1434                    }
1435                }
1436            }
1437
1438            Timer vibTimer = u.getVibratorOnTimer();
1439            if (vibTimer != null) {
1440                // Convert from microseconds to milliseconds with rounding
1441                long totalTime = (vibTimer.getTotalTimeLocked(batteryRealtime, which) + 500) / 1000;
1442                int count = vibTimer.getCountLocked(which);
1443                if (totalTime != 0) {
1444                    dumpLine(pw, uid, category, VIBRATOR_DATA, totalTime, count);
1445                }
1446            }
1447
1448            Timer fgTimer = u.getForegroundActivityTimer();
1449            if (fgTimer != null) {
1450                // Convert from microseconds to milliseconds with rounding
1451                long totalTime = (fgTimer.getTotalTimeLocked(batteryRealtime, which) + 500) / 1000;
1452                int count = fgTimer.getCountLocked(which);
1453                if (totalTime != 0) {
1454                    dumpLine(pw, uid, category, FOREGROUND_DATA, totalTime, count);
1455                }
1456            }
1457
1458            Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
1459            if (processStats.size() > 0) {
1460                for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
1461                        : processStats.entrySet()) {
1462                    Uid.Proc ps = ent.getValue();
1463
1464                    final long userMillis = ps.getUserTime(which) * 10;
1465                    final long systemMillis = ps.getSystemTime(which) * 10;
1466                    final long foregroundMillis = ps.getForegroundTime(which) * 10;
1467                    final long starts = ps.getStarts(which);
1468
1469                    if (userMillis != 0 || systemMillis != 0 || foregroundMillis != 0
1470                            || starts != 0) {
1471                        dumpLine(pw, uid, category, PROCESS_DATA, ent.getKey(), userMillis,
1472                                systemMillis, foregroundMillis, starts);
1473                    }
1474                }
1475            }
1476
1477            Map<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats();
1478            if (packageStats.size() > 0) {
1479                for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent
1480                        : packageStats.entrySet()) {
1481
1482                    Uid.Pkg ps = ent.getValue();
1483                    int wakeups = ps.getWakeups(which);
1484                    Map<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
1485                    for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent
1486                            : serviceStats.entrySet()) {
1487                        BatteryStats.Uid.Pkg.Serv ss = sent.getValue();
1488                        long startTime = ss.getStartTime(batteryUptime, which);
1489                        int starts = ss.getStarts(which);
1490                        int launches = ss.getLaunches(which);
1491                        if (startTime != 0 || starts != 0 || launches != 0) {
1492                            dumpLine(pw, uid, category, APK_DATA,
1493                                    wakeups, // wakeup alarms
1494                                    ent.getKey(), // Apk
1495                                    sent.getKey(), // service
1496                                    startTime / 1000, // time spent started, in ms
1497                                    starts,
1498                                    launches);
1499                        }
1500                    }
1501                }
1502            }
1503        }
1504    }
1505
1506    static final class TimerEntry {
1507        final String mName;
1508        final int mId;
1509        final BatteryStats.Timer mTimer;
1510        final long mTime;
1511        TimerEntry(String name, int id, BatteryStats.Timer timer, long time) {
1512            mName = name;
1513            mId = id;
1514            mTimer = timer;
1515            mTime = time;
1516        }
1517    }
1518
1519    @SuppressWarnings("unused")
1520    public final void dumpLocked(PrintWriter pw, String prefix, final int which, int reqUid) {
1521        final long rawUptime = SystemClock.uptimeMillis() * 1000;
1522        final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
1523        final long batteryUptime = getBatteryUptime(rawUptime);
1524        final long batteryRealtime = getBatteryRealtime(rawRealtime);
1525
1526        final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
1527        final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
1528        final long totalRealtime = computeRealtime(rawRealtime, which);
1529        final long totalUptime = computeUptime(rawUptime, which);
1530
1531        StringBuilder sb = new StringBuilder(128);
1532
1533        SparseArray<? extends Uid> uidStats = getUidStats();
1534        final int NU = uidStats.size();
1535
1536        sb.setLength(0);
1537        sb.append(prefix);
1538                sb.append("  Time on battery: ");
1539                formatTimeMs(sb, whichBatteryRealtime / 1000); sb.append("(");
1540                sb.append(formatRatioLocked(whichBatteryRealtime, totalRealtime));
1541                sb.append(") realtime, ");
1542                formatTimeMs(sb, whichBatteryUptime / 1000);
1543                sb.append("("); sb.append(formatRatioLocked(whichBatteryUptime, totalRealtime));
1544                sb.append(") uptime");
1545        pw.println(sb.toString());
1546        sb.setLength(0);
1547        sb.append(prefix);
1548                sb.append("  Total run time: ");
1549                formatTimeMs(sb, totalRealtime / 1000);
1550                sb.append("realtime, ");
1551                formatTimeMs(sb, totalUptime / 1000);
1552                sb.append("uptime, ");
1553        pw.println(sb.toString());
1554
1555        final long screenOnTime = getScreenOnTime(batteryRealtime, which);
1556        final long phoneOnTime = getPhoneOnTime(batteryRealtime, which);
1557        final long wifiRunningTime = getGlobalWifiRunningTime(batteryRealtime, which);
1558        final long wifiOnTime = getWifiOnTime(batteryRealtime, which);
1559        final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which);
1560        sb.setLength(0);
1561        sb.append(prefix);
1562                sb.append("  Screen on: "); formatTimeMs(sb, screenOnTime / 1000);
1563                sb.append("("); sb.append(formatRatioLocked(screenOnTime, whichBatteryRealtime));
1564                sb.append("), Input events: "); sb.append(getInputEventCount(which));
1565                sb.append(", Active phone call: "); formatTimeMs(sb, phoneOnTime / 1000);
1566                sb.append("("); sb.append(formatRatioLocked(phoneOnTime, whichBatteryRealtime));
1567                sb.append(")");
1568        pw.println(sb.toString());
1569        sb.setLength(0);
1570        sb.append(prefix);
1571        sb.append("  Screen brightnesses: ");
1572        boolean didOne = false;
1573        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
1574            final long time = getScreenBrightnessTime(i, batteryRealtime, which);
1575            if (time == 0) {
1576                continue;
1577            }
1578            if (didOne) sb.append(", ");
1579            didOne = true;
1580            sb.append(SCREEN_BRIGHTNESS_NAMES[i]);
1581            sb.append(" ");
1582            formatTimeMs(sb, time/1000);
1583            sb.append("(");
1584            sb.append(formatRatioLocked(time, screenOnTime));
1585            sb.append(")");
1586        }
1587        if (!didOne) sb.append("No activity");
1588        pw.println(sb.toString());
1589
1590        // Calculate total network and wakelock times across all uids.
1591        long mobileRxTotal = 0;
1592        long mobileTxTotal = 0;
1593        long wifiRxTotal = 0;
1594        long wifiTxTotal = 0;
1595        long fullWakeLockTimeTotalMicros = 0;
1596        long partialWakeLockTimeTotalMicros = 0;
1597
1598        final Comparator<TimerEntry> timerComparator = new Comparator<TimerEntry>() {
1599            @Override
1600            public int compare(TimerEntry lhs, TimerEntry rhs) {
1601                long lhsTime = lhs.mTime;
1602                long rhsTime = rhs.mTime;
1603                if (lhsTime < rhsTime) {
1604                    return 1;
1605                }
1606                if (lhsTime > rhsTime) {
1607                    return -1;
1608                }
1609                return 0;
1610            }
1611        };
1612
1613        if (reqUid < 0) {
1614            Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats();
1615            if (kernelWakelocks.size() > 0) {
1616                final ArrayList<TimerEntry> timers = new ArrayList<TimerEntry>();
1617                for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) {
1618                    BatteryStats.Timer timer = ent.getValue();
1619                    long totalTimeMillis = computeWakeLock(timer, batteryRealtime, which);
1620                    if (totalTimeMillis > 0) {
1621                        timers.add(new TimerEntry(ent.getKey(), 0, timer, totalTimeMillis));
1622                    }
1623                }
1624                Collections.sort(timers, timerComparator);
1625                for (int i=0; i<timers.size(); i++) {
1626                    TimerEntry timer = timers.get(i);
1627                    String linePrefix = ": ";
1628                    sb.setLength(0);
1629                    sb.append(prefix);
1630                    sb.append("  Kernel Wake lock ");
1631                    sb.append(timer.mName);
1632                    linePrefix = printWakeLock(sb, timer.mTimer, batteryRealtime, null,
1633                            which, linePrefix);
1634                    if (!linePrefix.equals(": ")) {
1635                        sb.append(" realtime");
1636                        // Only print out wake locks that were held
1637                        pw.println(sb.toString());
1638                    }
1639                }
1640            }
1641        }
1642
1643        final ArrayList<TimerEntry> timers = new ArrayList<TimerEntry>();
1644
1645        for (int iu = 0; iu < NU; iu++) {
1646            Uid u = uidStats.valueAt(iu);
1647            mobileRxTotal += u.getNetworkActivityCount(NETWORK_MOBILE_RX_BYTES, which);
1648            mobileTxTotal += u.getNetworkActivityCount(NETWORK_MOBILE_TX_BYTES, which);
1649            wifiRxTotal += u.getNetworkActivityCount(NETWORK_WIFI_RX_BYTES, which);
1650            wifiTxTotal += u.getNetworkActivityCount(NETWORK_WIFI_TX_BYTES, which);
1651
1652            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
1653            if (wakelocks.size() > 0) {
1654                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
1655                        : wakelocks.entrySet()) {
1656                    Uid.Wakelock wl = ent.getValue();
1657
1658                    Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
1659                    if (fullWakeTimer != null) {
1660                        fullWakeLockTimeTotalMicros += fullWakeTimer.getTotalTimeLocked(
1661                                batteryRealtime, which);
1662                    }
1663
1664                    Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
1665                    if (partialWakeTimer != null) {
1666                        long totalTimeMicros = partialWakeTimer.getTotalTimeLocked(
1667                                batteryRealtime, which);
1668                        if (totalTimeMicros > 0) {
1669                            if (reqUid < 0) {
1670                                // Only show the ordered list of all wake
1671                                // locks if the caller is not asking for data
1672                                // about a specific uid.
1673                                timers.add(new TimerEntry(ent.getKey(), u.getUid(),
1674                                        partialWakeTimer, totalTimeMicros));
1675                            }
1676                            partialWakeLockTimeTotalMicros += totalTimeMicros;
1677                        }
1678                    }
1679                }
1680            }
1681        }
1682
1683        pw.print(prefix);
1684                pw.print("  Mobile total received: "); pw.print(formatBytesLocked(mobileRxTotal));
1685                pw.print(", Total sent: "); pw.println(formatBytesLocked(mobileTxTotal));
1686        pw.print(prefix);
1687                pw.print("  Wi-Fi total received: "); pw.print(formatBytesLocked(wifiRxTotal));
1688                pw.print(", Total sent: "); pw.println(formatBytesLocked(wifiTxTotal));
1689        sb.setLength(0);
1690        sb.append(prefix);
1691                sb.append("  Total full wakelock time: "); formatTimeMs(sb,
1692                        (fullWakeLockTimeTotalMicros + 500) / 1000);
1693                sb.append(", Total partial wakelock time: "); formatTimeMs(sb,
1694                        (partialWakeLockTimeTotalMicros + 500) / 1000);
1695        pw.println(sb.toString());
1696
1697        sb.setLength(0);
1698        sb.append(prefix);
1699        sb.append("  Signal levels: ");
1700        didOne = false;
1701        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
1702            final long time = getPhoneSignalStrengthTime(i, batteryRealtime, which);
1703            if (time == 0) {
1704                continue;
1705            }
1706            if (didOne) sb.append(", ");
1707            didOne = true;
1708            sb.append(SignalStrength.SIGNAL_STRENGTH_NAMES[i]);
1709            sb.append(" ");
1710            formatTimeMs(sb, time/1000);
1711            sb.append("(");
1712            sb.append(formatRatioLocked(time, whichBatteryRealtime));
1713            sb.append(") ");
1714            sb.append(getPhoneSignalStrengthCount(i, which));
1715            sb.append("x");
1716        }
1717        if (!didOne) sb.append("No activity");
1718        pw.println(sb.toString());
1719
1720        sb.setLength(0);
1721        sb.append(prefix);
1722        sb.append("  Signal scanning time: ");
1723        formatTimeMs(sb, getPhoneSignalScanningTime(batteryRealtime, which) / 1000);
1724        pw.println(sb.toString());
1725
1726        sb.setLength(0);
1727        sb.append(prefix);
1728        sb.append("  Radio types: ");
1729        didOne = false;
1730        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
1731            final long time = getPhoneDataConnectionTime(i, batteryRealtime, which);
1732            if (time == 0) {
1733                continue;
1734            }
1735            if (didOne) sb.append(", ");
1736            didOne = true;
1737            sb.append(DATA_CONNECTION_NAMES[i]);
1738            sb.append(" ");
1739            formatTimeMs(sb, time/1000);
1740            sb.append("(");
1741            sb.append(formatRatioLocked(time, whichBatteryRealtime));
1742            sb.append(") ");
1743            sb.append(getPhoneDataConnectionCount(i, which));
1744            sb.append("x");
1745        }
1746        if (!didOne) sb.append("No activity");
1747        pw.println(sb.toString());
1748
1749        sb.setLength(0);
1750        sb.append(prefix);
1751        sb.append("  Radio data uptime when unplugged: ");
1752        sb.append(getRadioDataUptime() / 1000);
1753        sb.append(" ms");
1754        pw.println(sb.toString());
1755
1756        sb.setLength(0);
1757        sb.append(prefix);
1758                sb.append("  Wifi on: "); formatTimeMs(sb, wifiOnTime / 1000);
1759                sb.append("("); sb.append(formatRatioLocked(wifiOnTime, whichBatteryRealtime));
1760                sb.append("), Wifi running: "); formatTimeMs(sb, wifiRunningTime / 1000);
1761                sb.append("("); sb.append(formatRatioLocked(wifiRunningTime, whichBatteryRealtime));
1762                sb.append("), Bluetooth on: "); formatTimeMs(sb, bluetoothOnTime / 1000);
1763                sb.append("("); sb.append(formatRatioLocked(bluetoothOnTime, whichBatteryRealtime));
1764                sb.append(")");
1765        pw.println(sb.toString());
1766
1767        pw.println(" ");
1768
1769        if (which == STATS_SINCE_UNPLUGGED) {
1770            if (getIsOnBattery()) {
1771                pw.print(prefix); pw.println("  Device is currently unplugged");
1772                pw.print(prefix); pw.print("    Discharge cycle start level: ");
1773                        pw.println(getDischargeStartLevel());
1774                pw.print(prefix); pw.print("    Discharge cycle current level: ");
1775                        pw.println(getDischargeCurrentLevel());
1776            } else {
1777                pw.print(prefix); pw.println("  Device is currently plugged into power");
1778                pw.print(prefix); pw.print("    Last discharge cycle start level: ");
1779                        pw.println(getDischargeStartLevel());
1780                pw.print(prefix); pw.print("    Last discharge cycle end level: ");
1781                        pw.println(getDischargeCurrentLevel());
1782            }
1783            pw.print(prefix); pw.print("    Amount discharged while screen on: ");
1784                    pw.println(getDischargeAmountScreenOn());
1785            pw.print(prefix); pw.print("    Amount discharged while screen off: ");
1786                    pw.println(getDischargeAmountScreenOff());
1787            pw.println(" ");
1788        } else {
1789            pw.print(prefix); pw.println("  Device battery use since last full charge");
1790            pw.print(prefix); pw.print("    Amount discharged (lower bound): ");
1791                    pw.println(getLowDischargeAmountSinceCharge());
1792            pw.print(prefix); pw.print("    Amount discharged (upper bound): ");
1793                    pw.println(getHighDischargeAmountSinceCharge());
1794            pw.print(prefix); pw.print("    Amount discharged while screen on: ");
1795                    pw.println(getDischargeAmountScreenOnSinceCharge());
1796            pw.print(prefix); pw.print("    Amount discharged while screen off: ");
1797                    pw.println(getDischargeAmountScreenOffSinceCharge());
1798            pw.println();
1799        }
1800
1801        if (timers.size() > 0) {
1802            Collections.sort(timers, timerComparator);
1803            pw.print(prefix); pw.println("  All partial wake locks:");
1804            for (int i=0; i<timers.size(); i++) {
1805                TimerEntry timer = timers.get(i);
1806                sb.setLength(0);
1807                sb.append("  Wake lock ");
1808                UserHandle.formatUid(sb, timer.mId);
1809                sb.append(" ");
1810                sb.append(timer.mName);
1811                printWakeLock(sb, timer.mTimer, batteryRealtime, null, which, ": ");
1812                sb.append(" realtime");
1813                pw.println(sb.toString());
1814            }
1815            timers.clear();
1816            pw.println();
1817        }
1818
1819        for (int iu=0; iu<NU; iu++) {
1820            final int uid = uidStats.keyAt(iu);
1821            if (reqUid >= 0 && uid != reqUid && uid != Process.SYSTEM_UID) {
1822                continue;
1823            }
1824
1825            Uid u = uidStats.valueAt(iu);
1826
1827            pw.print(prefix);
1828            pw.print("  ");
1829            UserHandle.formatUid(pw, uid);
1830            pw.println(":");
1831            boolean uidActivity = false;
1832
1833            long mobileRxBytes = u.getNetworkActivityCount(NETWORK_MOBILE_RX_BYTES, which);
1834            long mobileTxBytes = u.getNetworkActivityCount(NETWORK_MOBILE_TX_BYTES, which);
1835            long wifiRxBytes = u.getNetworkActivityCount(NETWORK_WIFI_RX_BYTES, which);
1836            long wifiTxBytes = u.getNetworkActivityCount(NETWORK_WIFI_TX_BYTES, which);
1837            long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
1838            long wifiScanTime = u.getWifiScanTime(batteryRealtime, which);
1839            long uidWifiRunningTime = u.getWifiRunningTime(batteryRealtime, which);
1840
1841            if (mobileRxBytes > 0 || mobileTxBytes > 0) {
1842                pw.print(prefix); pw.print("    Mobile network: ");
1843                        pw.print(formatBytesLocked(mobileRxBytes)); pw.print(" received, ");
1844                        pw.print(formatBytesLocked(mobileTxBytes)); pw.println(" sent");
1845            }
1846            if (wifiRxBytes > 0 || wifiTxBytes > 0) {
1847                pw.print(prefix); pw.print("    Wi-Fi network: ");
1848                        pw.print(formatBytesLocked(wifiRxBytes)); pw.print(" received, ");
1849                        pw.print(formatBytesLocked(wifiTxBytes)); pw.println(" sent");
1850            }
1851
1852            if (u.hasUserActivity()) {
1853                boolean hasData = false;
1854                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
1855                    int val = u.getUserActivityCount(i, which);
1856                    if (val != 0) {
1857                        if (!hasData) {
1858                            sb.setLength(0);
1859                            sb.append("    User activity: ");
1860                            hasData = true;
1861                        } else {
1862                            sb.append(", ");
1863                        }
1864                        sb.append(val);
1865                        sb.append(" ");
1866                        sb.append(Uid.USER_ACTIVITY_TYPES[i]);
1867                    }
1868                }
1869                if (hasData) {
1870                    pw.println(sb.toString());
1871                }
1872            }
1873
1874            if (fullWifiLockOnTime != 0 || wifiScanTime != 0
1875                    || uidWifiRunningTime != 0) {
1876                sb.setLength(0);
1877                sb.append(prefix); sb.append("    Wifi Running: ");
1878                        formatTimeMs(sb, uidWifiRunningTime / 1000);
1879                        sb.append("("); sb.append(formatRatioLocked(uidWifiRunningTime,
1880                                whichBatteryRealtime)); sb.append(")\n");
1881                sb.append(prefix); sb.append("    Full Wifi Lock: ");
1882                        formatTimeMs(sb, fullWifiLockOnTime / 1000);
1883                        sb.append("("); sb.append(formatRatioLocked(fullWifiLockOnTime,
1884                                whichBatteryRealtime)); sb.append(")\n");
1885                sb.append(prefix); sb.append("    Wifi Scan: ");
1886                        formatTimeMs(sb, wifiScanTime / 1000);
1887                        sb.append("("); sb.append(formatRatioLocked(wifiScanTime,
1888                                whichBatteryRealtime)); sb.append(")");
1889                pw.println(sb.toString());
1890            }
1891
1892            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
1893            if (wakelocks.size() > 0) {
1894                long totalFull = 0, totalPartial = 0, totalWindow = 0;
1895                int count = 0;
1896                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
1897                    : wakelocks.entrySet()) {
1898                    Uid.Wakelock wl = ent.getValue();
1899                    String linePrefix = ": ";
1900                    sb.setLength(0);
1901                    sb.append(prefix);
1902                    sb.append("    Wake lock ");
1903                    sb.append(ent.getKey());
1904                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_FULL), batteryRealtime,
1905                            "full", which, linePrefix);
1906                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), batteryRealtime,
1907                            "partial", which, linePrefix);
1908                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), batteryRealtime,
1909                            "window", which, linePrefix);
1910                    if (!linePrefix.equals(": ")) {
1911                        sb.append(" realtime");
1912                        // Only print out wake locks that were held
1913                        pw.println(sb.toString());
1914                        uidActivity = true;
1915                        count++;
1916                    }
1917                    totalFull += computeWakeLock(wl.getWakeTime(WAKE_TYPE_FULL),
1918                            batteryRealtime, which);
1919                    totalPartial += computeWakeLock(wl.getWakeTime(WAKE_TYPE_PARTIAL),
1920                            batteryRealtime, which);
1921                    totalWindow += computeWakeLock(wl.getWakeTime(WAKE_TYPE_WINDOW),
1922                            batteryRealtime, which);
1923                }
1924                if (count > 1) {
1925                    if (totalFull != 0 || totalPartial != 0 || totalWindow != 0) {
1926                        sb.setLength(0);
1927                        sb.append(prefix);
1928                        sb.append("    TOTAL wake: ");
1929                        boolean needComma = false;
1930                        if (totalFull != 0) {
1931                            needComma = true;
1932                            formatTimeMs(sb, totalFull);
1933                            sb.append("full");
1934                        }
1935                        if (totalPartial != 0) {
1936                            if (needComma) {
1937                                sb.append(", ");
1938                            }
1939                            needComma = true;
1940                            formatTimeMs(sb, totalPartial);
1941                            sb.append("partial");
1942                        }
1943                        if (totalWindow != 0) {
1944                            if (needComma) {
1945                                sb.append(", ");
1946                            }
1947                            needComma = true;
1948                            formatTimeMs(sb, totalWindow);
1949                            sb.append("window");
1950                        }
1951                        sb.append(" realtime");
1952                        pw.println(sb.toString());
1953                    }
1954                }
1955            }
1956
1957            Map<Integer, ? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
1958            if (sensors.size() > 0) {
1959                for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> ent
1960                    : sensors.entrySet()) {
1961                    Uid.Sensor se = ent.getValue();
1962                    int sensorNumber = ent.getKey();
1963                    sb.setLength(0);
1964                    sb.append(prefix);
1965                    sb.append("    Sensor ");
1966                    int handle = se.getHandle();
1967                    if (handle == Uid.Sensor.GPS) {
1968                        sb.append("GPS");
1969                    } else {
1970                        sb.append(handle);
1971                    }
1972                    sb.append(": ");
1973
1974                    Timer timer = se.getSensorTime();
1975                    if (timer != null) {
1976                        // Convert from microseconds to milliseconds with rounding
1977                        long totalTime = (timer.getTotalTimeLocked(
1978                                batteryRealtime, which) + 500) / 1000;
1979                        int count = timer.getCountLocked(which);
1980                        //timer.logState();
1981                        if (totalTime != 0) {
1982                            formatTimeMs(sb, totalTime);
1983                            sb.append("realtime (");
1984                            sb.append(count);
1985                            sb.append(" times)");
1986                        } else {
1987                            sb.append("(not used)");
1988                        }
1989                    } else {
1990                        sb.append("(not used)");
1991                    }
1992
1993                    pw.println(sb.toString());
1994                    uidActivity = true;
1995                }
1996            }
1997
1998            Timer vibTimer = u.getVibratorOnTimer();
1999            if (vibTimer != null) {
2000                // Convert from microseconds to milliseconds with rounding
2001                long totalTime = (vibTimer.getTotalTimeLocked(
2002                        batteryRealtime, which) + 500) / 1000;
2003                int count = vibTimer.getCountLocked(which);
2004                //timer.logState();
2005                if (totalTime != 0) {
2006                    sb.setLength(0);
2007                    sb.append(prefix);
2008                    sb.append("    Vibrator: ");
2009                    formatTimeMs(sb, totalTime);
2010                    sb.append("realtime (");
2011                    sb.append(count);
2012                    sb.append(" times)");
2013                    pw.println(sb.toString());
2014                    uidActivity = true;
2015                }
2016            }
2017
2018            Timer fgTimer = u.getForegroundActivityTimer();
2019            if (fgTimer != null) {
2020                // Convert from microseconds to milliseconds with rounding
2021                long totalTime = (fgTimer.getTotalTimeLocked(batteryRealtime, which) + 500) / 1000;
2022                int count = fgTimer.getCountLocked(which);
2023                if (totalTime != 0) {
2024                    sb.setLength(0);
2025                    sb.append(prefix);
2026                    sb.append("    Foreground activities: ");
2027                    formatTimeMs(sb, totalTime);
2028                    sb.append("realtime (");
2029                    sb.append(count);
2030                    sb.append(" times)");
2031                    pw.println(sb.toString());
2032                    uidActivity = true;
2033                }
2034            }
2035
2036            Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
2037            if (processStats.size() > 0) {
2038                for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
2039                    : processStats.entrySet()) {
2040                    Uid.Proc ps = ent.getValue();
2041                    long userTime;
2042                    long systemTime;
2043                    long foregroundTime;
2044                    int starts;
2045                    int numExcessive;
2046
2047                    userTime = ps.getUserTime(which);
2048                    systemTime = ps.getSystemTime(which);
2049                    foregroundTime = ps.getForegroundTime(which);
2050                    starts = ps.getStarts(which);
2051                    numExcessive = which == STATS_SINCE_CHARGED
2052                            ? ps.countExcessivePowers() : 0;
2053
2054                    if (userTime != 0 || systemTime != 0 || foregroundTime != 0 || starts != 0
2055                            || numExcessive != 0) {
2056                        sb.setLength(0);
2057                        sb.append(prefix); sb.append("    Proc ");
2058                                sb.append(ent.getKey()); sb.append(":\n");
2059                        sb.append(prefix); sb.append("      CPU: ");
2060                                formatTime(sb, userTime); sb.append("usr + ");
2061                                formatTime(sb, systemTime); sb.append("krn ; ");
2062                                formatTime(sb, foregroundTime); sb.append("fg");
2063                        if (starts != 0) {
2064                            sb.append("\n"); sb.append(prefix); sb.append("      ");
2065                                    sb.append(starts); sb.append(" proc starts");
2066                        }
2067                        pw.println(sb.toString());
2068                        for (int e=0; e<numExcessive; e++) {
2069                            Uid.Proc.ExcessivePower ew = ps.getExcessivePower(e);
2070                            if (ew != null) {
2071                                pw.print(prefix); pw.print("      * Killed for ");
2072                                        if (ew.type == Uid.Proc.ExcessivePower.TYPE_WAKE) {
2073                                            pw.print("wake lock");
2074                                        } else if (ew.type == Uid.Proc.ExcessivePower.TYPE_CPU) {
2075                                            pw.print("cpu");
2076                                        } else {
2077                                            pw.print("unknown");
2078                                        }
2079                                        pw.print(" use: ");
2080                                        TimeUtils.formatDuration(ew.usedTime, pw);
2081                                        pw.print(" over ");
2082                                        TimeUtils.formatDuration(ew.overTime, pw);
2083                                        pw.print(" (");
2084                                        pw.print((ew.usedTime*100)/ew.overTime);
2085                                        pw.println("%)");
2086                            }
2087                        }
2088                        uidActivity = true;
2089                    }
2090                }
2091            }
2092
2093            Map<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats();
2094            if (packageStats.size() > 0) {
2095                for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent
2096                    : packageStats.entrySet()) {
2097                    pw.print(prefix); pw.print("    Apk "); pw.print(ent.getKey()); pw.println(":");
2098                    boolean apkActivity = false;
2099                    Uid.Pkg ps = ent.getValue();
2100                    int wakeups = ps.getWakeups(which);
2101                    if (wakeups != 0) {
2102                        pw.print(prefix); pw.print("      ");
2103                                pw.print(wakeups); pw.println(" wakeup alarms");
2104                        apkActivity = true;
2105                    }
2106                    Map<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
2107                    if (serviceStats.size() > 0) {
2108                        for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent
2109                                : serviceStats.entrySet()) {
2110                            BatteryStats.Uid.Pkg.Serv ss = sent.getValue();
2111                            long startTime = ss.getStartTime(batteryUptime, which);
2112                            int starts = ss.getStarts(which);
2113                            int launches = ss.getLaunches(which);
2114                            if (startTime != 0 || starts != 0 || launches != 0) {
2115                                sb.setLength(0);
2116                                sb.append(prefix); sb.append("      Service ");
2117                                        sb.append(sent.getKey()); sb.append(":\n");
2118                                sb.append(prefix); sb.append("        Created for: ");
2119                                        formatTimeMs(sb, startTime / 1000);
2120                                        sb.append("uptime\n");
2121                                sb.append(prefix); sb.append("        Starts: ");
2122                                        sb.append(starts);
2123                                        sb.append(", launches: "); sb.append(launches);
2124                                pw.println(sb.toString());
2125                                apkActivity = true;
2126                            }
2127                        }
2128                    }
2129                    if (!apkActivity) {
2130                        pw.print(prefix); pw.println("      (nothing executed)");
2131                    }
2132                    uidActivity = true;
2133                }
2134            }
2135            if (!uidActivity) {
2136                pw.print(prefix); pw.println("    (nothing executed)");
2137            }
2138        }
2139    }
2140
2141    static void printBitDescriptions(PrintWriter pw, int oldval, int newval, BitDescription[] descriptions) {
2142        int diff = oldval ^ newval;
2143        if (diff == 0) return;
2144        for (int i=0; i<descriptions.length; i++) {
2145            BitDescription bd = descriptions[i];
2146            if ((diff&bd.mask) != 0) {
2147                if (bd.shift < 0) {
2148                    pw.print((newval&bd.mask) != 0 ? " +" : " -");
2149                    pw.print(bd.name);
2150                } else {
2151                    pw.print(" ");
2152                    pw.print(bd.name);
2153                    pw.print("=");
2154                    int val = (newval&bd.mask)>>bd.shift;
2155                    if (bd.values != null && val >= 0 && val < bd.values.length) {
2156                        pw.print(bd.values[val]);
2157                    } else {
2158                        pw.print(val);
2159                    }
2160                }
2161            }
2162        }
2163    }
2164
2165    public void prepareForDumpLocked() {
2166    }
2167
2168    public static class HistoryPrinter {
2169        int oldState = 0;
2170        int oldStatus = -1;
2171        int oldHealth = -1;
2172        int oldPlug = -1;
2173        int oldTemp = -1;
2174        int oldVolt = -1;
2175
2176        public void printNextItem(PrintWriter pw, HistoryItem rec, long now) {
2177            pw.print("  ");
2178            TimeUtils.formatDuration(rec.time-now, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
2179            pw.print(" ");
2180            if (rec.cmd == HistoryItem.CMD_START) {
2181                pw.println(" START");
2182            } else if (rec.cmd == HistoryItem.CMD_OVERFLOW) {
2183                pw.println(" *OVERFLOW*");
2184            } else {
2185                if (rec.batteryLevel < 10) pw.print("00");
2186                else if (rec.batteryLevel < 100) pw.print("0");
2187                pw.print(rec.batteryLevel);
2188                pw.print(" ");
2189                if (rec.states < 0x10) pw.print("0000000");
2190                else if (rec.states < 0x100) pw.print("000000");
2191                else if (rec.states < 0x1000) pw.print("00000");
2192                else if (rec.states < 0x10000) pw.print("0000");
2193                else if (rec.states < 0x100000) pw.print("000");
2194                else if (rec.states < 0x1000000) pw.print("00");
2195                else if (rec.states < 0x10000000) pw.print("0");
2196                pw.print(Integer.toHexString(rec.states));
2197                if (oldStatus != rec.batteryStatus) {
2198                    oldStatus = rec.batteryStatus;
2199                    pw.print(" status=");
2200                    switch (oldStatus) {
2201                        case BatteryManager.BATTERY_STATUS_UNKNOWN:
2202                            pw.print("unknown");
2203                            break;
2204                        case BatteryManager.BATTERY_STATUS_CHARGING:
2205                            pw.print("charging");
2206                            break;
2207                        case BatteryManager.BATTERY_STATUS_DISCHARGING:
2208                            pw.print("discharging");
2209                            break;
2210                        case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
2211                            pw.print("not-charging");
2212                            break;
2213                        case BatteryManager.BATTERY_STATUS_FULL:
2214                            pw.print("full");
2215                            break;
2216                        default:
2217                            pw.print(oldStatus);
2218                            break;
2219                    }
2220                }
2221                if (oldHealth != rec.batteryHealth) {
2222                    oldHealth = rec.batteryHealth;
2223                    pw.print(" health=");
2224                    switch (oldHealth) {
2225                        case BatteryManager.BATTERY_HEALTH_UNKNOWN:
2226                            pw.print("unknown");
2227                            break;
2228                        case BatteryManager.BATTERY_HEALTH_GOOD:
2229                            pw.print("good");
2230                            break;
2231                        case BatteryManager.BATTERY_HEALTH_OVERHEAT:
2232                            pw.print("overheat");
2233                            break;
2234                        case BatteryManager.BATTERY_HEALTH_DEAD:
2235                            pw.print("dead");
2236                            break;
2237                        case BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE:
2238                            pw.print("over-voltage");
2239                            break;
2240                        case BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE:
2241                            pw.print("failure");
2242                            break;
2243                        default:
2244                            pw.print(oldHealth);
2245                            break;
2246                    }
2247                }
2248                if (oldPlug != rec.batteryPlugType) {
2249                    oldPlug = rec.batteryPlugType;
2250                    pw.print(" plug=");
2251                    switch (oldPlug) {
2252                        case 0:
2253                            pw.print("none");
2254                            break;
2255                        case BatteryManager.BATTERY_PLUGGED_AC:
2256                            pw.print("ac");
2257                            break;
2258                        case BatteryManager.BATTERY_PLUGGED_USB:
2259                            pw.print("usb");
2260                            break;
2261                        case BatteryManager.BATTERY_PLUGGED_WIRELESS:
2262                            pw.print("wireless");
2263                            break;
2264                        default:
2265                            pw.print(oldPlug);
2266                            break;
2267                    }
2268                }
2269                if (oldTemp != rec.batteryTemperature) {
2270                    oldTemp = rec.batteryTemperature;
2271                    pw.print(" temp=");
2272                    pw.print(oldTemp);
2273                }
2274                if (oldVolt != rec.batteryVoltage) {
2275                    oldVolt = rec.batteryVoltage;
2276                    pw.print(" volt=");
2277                    pw.print(oldVolt);
2278                }
2279                printBitDescriptions(pw, oldState, rec.states,
2280                        HISTORY_STATE_DESCRIPTIONS);
2281                pw.println();
2282            }
2283            oldState = rec.states;
2284        }
2285
2286        public void printNextItemCheckin(PrintWriter pw, HistoryItem rec, long now) {
2287            pw.print(rec.time-now);
2288            pw.print(",");
2289            if (rec.cmd == HistoryItem.CMD_START) {
2290                pw.print("start");
2291            } else if (rec.cmd == HistoryItem.CMD_OVERFLOW) {
2292                pw.print("overflow");
2293            } else {
2294                pw.print(rec.batteryLevel);
2295                pw.print(",");
2296                pw.print(rec.states);
2297                pw.print(",");
2298                pw.print(rec.batteryStatus);
2299                pw.print(",");
2300                pw.print(rec.batteryHealth);
2301                pw.print(",");
2302                pw.print(rec.batteryPlugType);
2303                pw.print(",");
2304                pw.print((int)rec.batteryTemperature);
2305                pw.print(",");
2306                pw.print((int)rec.batteryVoltage);
2307            }
2308        }
2309    }
2310
2311    /**
2312     * Dumps a human-readable summary of the battery statistics to the given PrintWriter.
2313     *
2314     * @param pw a Printer to receive the dump output.
2315     */
2316    @SuppressWarnings("unused")
2317    public void dumpLocked(PrintWriter pw, boolean isUnpluggedOnly, int reqUid) {
2318        prepareForDumpLocked();
2319
2320        long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
2321
2322        final HistoryItem rec = new HistoryItem();
2323        if (startIteratingHistoryLocked()) {
2324            pw.println("Battery History:");
2325            HistoryPrinter hprinter = new HistoryPrinter();
2326            while (getNextHistoryLocked(rec)) {
2327                hprinter.printNextItem(pw, rec, now);
2328            }
2329            finishIteratingHistoryLocked();
2330            pw.println("");
2331        }
2332
2333        if (startIteratingOldHistoryLocked()) {
2334            pw.println("Old battery History:");
2335            HistoryPrinter hprinter = new HistoryPrinter();
2336            while (getNextOldHistoryLocked(rec)) {
2337                hprinter.printNextItem(pw, rec, now);
2338            }
2339            finishIteratingOldHistoryLocked();
2340            pw.println("");
2341        }
2342
2343        SparseArray<? extends Uid> uidStats = getUidStats();
2344        final int NU = uidStats.size();
2345        boolean didPid = false;
2346        long nowRealtime = SystemClock.elapsedRealtime();
2347        for (int i=0; i<NU; i++) {
2348            Uid uid = uidStats.valueAt(i);
2349            SparseArray<? extends Uid.Pid> pids = uid.getPidStats();
2350            if (pids != null) {
2351                for (int j=0; j<pids.size(); j++) {
2352                    Uid.Pid pid = pids.valueAt(j);
2353                    if (!didPid) {
2354                        pw.println("Per-PID Stats:");
2355                        didPid = true;
2356                    }
2357                    long time = pid.mWakeSum + (pid.mWakeStart != 0
2358                            ? (nowRealtime - pid.mWakeStart) : 0);
2359                    pw.print("  PID "); pw.print(pids.keyAt(j));
2360                            pw.print(" wake time: ");
2361                            TimeUtils.formatDuration(time, pw);
2362                            pw.println("");
2363                }
2364            }
2365        }
2366        if (didPid) {
2367            pw.println("");
2368        }
2369
2370        if (!isUnpluggedOnly) {
2371            pw.println("Statistics since last charge:");
2372            pw.println("  System starts: " + getStartCount()
2373                    + ", currently on battery: " + getIsOnBattery());
2374            dumpLocked(pw, "", STATS_SINCE_CHARGED, reqUid);
2375            pw.println("");
2376        }
2377        pw.println("Statistics since last unplugged:");
2378        dumpLocked(pw, "", STATS_SINCE_UNPLUGGED, reqUid);
2379    }
2380
2381    @SuppressWarnings("unused")
2382    public void dumpCheckinLocked(
2383            PrintWriter pw, List<ApplicationInfo> apps, boolean isUnpluggedOnly,
2384            boolean includeHistory) {
2385        prepareForDumpLocked();
2386
2387        long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
2388
2389        if (includeHistory) {
2390            final HistoryItem rec = new HistoryItem();
2391            if (startIteratingHistoryLocked()) {
2392                HistoryPrinter hprinter = new HistoryPrinter();
2393                while (getNextHistoryLocked(rec)) {
2394                    pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
2395                    pw.print(0); pw.print(',');
2396                    pw.print(HISTORY_DATA); pw.print(',');
2397                    hprinter.printNextItemCheckin(pw, rec, now);
2398                    pw.println();
2399                }
2400                finishIteratingHistoryLocked();
2401            }
2402        }
2403
2404        if (apps != null) {
2405            SparseArray<ArrayList<String>> uids = new SparseArray<ArrayList<String>>();
2406            for (int i=0; i<apps.size(); i++) {
2407                ApplicationInfo ai = apps.get(i);
2408                ArrayList<String> pkgs = uids.get(ai.uid);
2409                if (pkgs == null) {
2410                    pkgs = new ArrayList<String>();
2411                    uids.put(ai.uid, pkgs);
2412                }
2413                pkgs.add(ai.packageName);
2414            }
2415            SparseArray<? extends Uid> uidStats = getUidStats();
2416            final int NU = uidStats.size();
2417            String[] lineArgs = new String[2];
2418            for (int i=0; i<NU; i++) {
2419                int uid = uidStats.keyAt(i);
2420                ArrayList<String> pkgs = uids.get(uid);
2421                if (pkgs != null) {
2422                    for (int j=0; j<pkgs.size(); j++) {
2423                        lineArgs[0] = Integer.toString(uid);
2424                        lineArgs[1] = pkgs.get(j);
2425                        dumpLine(pw, 0 /* uid */, "i" /* category */, UID_DATA,
2426                                (Object[])lineArgs);
2427                    }
2428                }
2429            }
2430        }
2431        if (isUnpluggedOnly) {
2432            dumpCheckinLocked(pw, STATS_SINCE_UNPLUGGED, -1);
2433        }
2434        else {
2435            dumpCheckinLocked(pw, STATS_SINCE_CHARGED, -1);
2436            dumpCheckinLocked(pw, STATS_SINCE_UNPLUGGED, -1);
2437        }
2438    }
2439}
2440