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