BatteryStats.java revision 5347bd4cda2b6afc18f8acab48e52131f35ed13c
1package android.os;
2
3import java.io.PrintWriter;
4import java.util.Formatter;
5import java.util.Map;
6
7import android.util.Log;
8import android.util.Printer;
9import android.util.SparseArray;
10
11/**
12 * A class providing access to battery usage statistics, including information on
13 * wakelocks, processes, packages, and services.  All times are represented in microseconds
14 * except where indicated otherwise.
15 * @hide
16 */
17public abstract class BatteryStats implements Parcelable {
18
19    private static final boolean LOCAL_LOGV = false;
20
21    /**
22     * A constant indicating a partial wake lock timer.
23     */
24    public static final int WAKE_TYPE_PARTIAL = 0;
25
26    /**
27     * A constant indicating a full wake lock timer.
28     */
29    public static final int WAKE_TYPE_FULL = 1;
30
31    /**
32     * A constant indicating a window wake lock timer.
33     */
34    public static final int WAKE_TYPE_WINDOW = 2;
35
36    /**
37     * A constant indicating a sensor timer.
38     *
39     * {@hide}
40     */
41    public static final int SENSOR = 3;
42
43    /**
44     * A constant indicating a a wifi turn on timer
45     *
46     * {@hide}
47     */
48    public static final int WIFI_TURNED_ON = 4;
49
50    /**
51     * A constant indicating a full wifi lock timer
52     *
53     * {@hide}
54     */
55    public static final int FULL_WIFI_LOCK = 5;
56
57    /**
58     * A constant indicating a scan wifi lock timer
59     *
60     * {@hide}
61     */
62    public static final int SCAN_WIFI_LOCK = 6;
63
64     /**
65      * A constant indicating a wifi multicast timer
66      *
67      * {@hide}
68      */
69     public static final int WIFI_MULTICAST_ENABLED = 7;
70
71    /**
72     * Include all of the data in the stats, including previously saved data.
73     */
74    public static final int STATS_TOTAL = 0;
75
76    /**
77     * Include only the last run in the stats.
78     */
79    public static final int STATS_LAST = 1;
80
81    /**
82     * Include only the current run in the stats.
83     */
84    public static final int STATS_CURRENT = 2;
85
86    /**
87     * Include only the run since the last time the device was unplugged in the stats.
88     */
89    public static final int STATS_UNPLUGGED = 3;
90
91    // NOTE: Update this list if you add/change any stats above.
92    // These characters are supposed to represent "total", "last", "current",
93    // and "unplugged". They were shortened for effeciency sake.
94    private static final String[] STAT_NAMES = { "t", "l", "c", "u" };
95
96    /**
97     * Bump the version on this if the checkin format changes.
98     */
99    private static final int BATTERY_STATS_CHECKIN_VERSION = 5;
100
101    private static final long BYTES_PER_KB = 1024;
102    private static final long BYTES_PER_MB = 1048576; // 1024^2
103    private static final long BYTES_PER_GB = 1073741824; //1024^3
104
105
106    private static final String APK_DATA = "apk";
107    private static final String PROCESS_DATA = "pr";
108    private static final String SENSOR_DATA = "sr";
109    private static final String WAKELOCK_DATA = "wl";
110    private static final String KERNEL_WAKELOCK_DATA = "kwl";
111    private static final String NETWORK_DATA = "nt";
112    private static final String USER_ACTIVITY_DATA = "ua";
113    private static final String BATTERY_DATA = "bt";
114    private static final String BATTERY_LEVEL_DATA = "lv";
115    private static final String WIFI_LOCK_DATA = "wfl";
116    private static final String MISC_DATA = "m";
117    private static final String SCREEN_BRIGHTNESS_DATA = "br";
118    private static final String SIGNAL_STRENGTH_TIME_DATA = "sgt";
119    private static final String SIGNAL_STRENGTH_COUNT_DATA = "sgc";
120    private static final String DATA_CONNECTION_TIME_DATA = "dct";
121    private static final String DATA_CONNECTION_COUNT_DATA = "dcc";
122
123    private final StringBuilder mFormatBuilder = new StringBuilder(32);
124    private final Formatter mFormatter = new Formatter(mFormatBuilder);
125
126    /**
127     * State for keeping track of counting information.
128     */
129    public static abstract class Counter {
130
131        /**
132         * Returns the count associated with this Counter for the
133         * selected type of statistics.
134         *
135         * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT
136         */
137        public abstract int getCountLocked(int which);
138
139        /**
140         * Temporary for debugging.
141         */
142        public abstract void logState(Printer pw, String prefix);
143    }
144
145    /**
146     * State for keeping track of timing information.
147     */
148    public static abstract class Timer {
149
150        /**
151         * Returns the count associated with this Timer for the
152         * selected type of statistics.
153         *
154         * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT
155         */
156        public abstract int getCountLocked(int which);
157
158        /**
159         * Returns the total time in microseconds associated with this Timer for the
160         * selected type of statistics.
161         *
162         * @param batteryRealtime system realtime on  battery in microseconds
163         * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT
164         * @return a time in microseconds
165         */
166        public abstract long getTotalTimeLocked(long batteryRealtime, int which);
167
168        /**
169         * Temporary for debugging.
170         */
171        public abstract void logState(Printer pw, String prefix);
172    }
173
174    /**
175     * The statistics associated with a particular uid.
176     */
177    public static abstract class Uid {
178
179        /**
180         * Returns a mapping containing wakelock statistics.
181         *
182         * @return a Map from Strings to Uid.Wakelock objects.
183         */
184        public abstract Map<String, ? extends Wakelock> getWakelockStats();
185
186        /**
187         * The statistics associated with a particular wake lock.
188         */
189        public static abstract class Wakelock {
190            public abstract Timer getWakeTime(int type);
191        }
192
193        /**
194         * Returns a mapping containing sensor statistics.
195         *
196         * @return a Map from Integer sensor ids to Uid.Sensor objects.
197         */
198        public abstract Map<Integer, ? extends Sensor> getSensorStats();
199
200        /**
201         * Returns a mapping containing process statistics.
202         *
203         * @return a Map from Strings to Uid.Proc objects.
204         */
205        public abstract Map<String, ? extends Proc> getProcessStats();
206
207        /**
208         * Returns a mapping containing package statistics.
209         *
210         * @return a Map from Strings to Uid.Pkg objects.
211         */
212        public abstract Map<String, ? extends Pkg> getPackageStats();
213
214        /**
215         * {@hide}
216         */
217        public abstract int getUid();
218
219        /**
220         * {@hide}
221         */
222        public abstract long getTcpBytesReceived(int which);
223
224        /**
225         * {@hide}
226         */
227        public abstract long getTcpBytesSent(int which);
228
229        public abstract void noteWifiTurnedOnLocked();
230        public abstract void noteWifiTurnedOffLocked();
231        public abstract void noteFullWifiLockAcquiredLocked();
232        public abstract void noteFullWifiLockReleasedLocked();
233        public abstract void noteScanWifiLockAcquiredLocked();
234        public abstract void noteScanWifiLockReleasedLocked();
235        public abstract void noteWifiMulticastEnabledLocked();
236        public abstract void noteWifiMulticastDisabledLocked();
237        public abstract long getWifiTurnedOnTime(long batteryRealtime, int which);
238        public abstract long getFullWifiLockTime(long batteryRealtime, int which);
239        public abstract long getScanWifiLockTime(long batteryRealtime, int which);
240        public abstract long getWifiMulticastTime(long batteryRealtime,
241                                                  int which);
242
243        /**
244         * Note that these must match the constants in android.os.LocalPowerManager.
245         */
246        static final String[] USER_ACTIVITY_TYPES = {
247            "other", "cheek", "touch", "long_touch", "touch_up", "button", "unknown"
248        };
249
250        public static final int NUM_USER_ACTIVITY_TYPES = 7;
251
252        public abstract void noteUserActivityLocked(int type);
253        public abstract boolean hasUserActivity();
254        public abstract int getUserActivityCount(int type, int which);
255
256        public static abstract class Sensor {
257            // Magic sensor number for the GPS.
258            public static final int GPS = -10000;
259
260            public abstract int getHandle();
261
262            public abstract Timer getSensorTime();
263        }
264
265        /**
266         * The statistics associated with a particular process.
267         */
268        public static abstract class Proc {
269
270            /**
271             * Returns the total time (in 1/100 sec) spent executing in user code.
272             *
273             * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
274             */
275            public abstract long getUserTime(int which);
276
277            /**
278             * Returns the total time (in 1/100 sec) spent executing in system code.
279             *
280             * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
281             */
282            public abstract long getSystemTime(int which);
283
284            /**
285             * Returns the number of times the process has been started.
286             *
287             * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
288             */
289            public abstract int getStarts(int which);
290        }
291
292        /**
293         * The statistics associated with a particular package.
294         */
295        public static abstract class Pkg {
296
297            /**
298             * Returns the number of times this package has done something that could wake up the
299             * device from sleep.
300             *
301             * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
302             */
303            public abstract int getWakeups(int which);
304
305            /**
306             * Returns a mapping containing service statistics.
307             */
308            public abstract Map<String, ? extends Serv> getServiceStats();
309
310            /**
311             * The statistics associated with a particular service.
312             */
313            public abstract class Serv {
314
315                /**
316                 * Returns the amount of time spent started.
317                 *
318                 * @param batteryUptime elapsed uptime on battery in microseconds.
319                 * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
320                 * @return
321                 */
322                public abstract long getStartTime(long batteryUptime, int which);
323
324                /**
325                 * Returns the total number of times startService() has been called.
326                 *
327                 * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
328                 */
329                public abstract int getStarts(int which);
330
331                /**
332                 * Returns the total number times the service has been launched.
333                 *
334                 * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
335                 */
336                public abstract int getLaunches(int which);
337            }
338        }
339    }
340
341    /**
342     * Returns the number of times the device has been started.
343     */
344    public abstract int getStartCount();
345
346    /**
347     * Returns the time in milliseconds that the screen has been on while the device was
348     * running on battery.
349     *
350     * {@hide}
351     */
352    public abstract long getScreenOnTime(long batteryRealtime, int which);
353
354    public static final int SCREEN_BRIGHTNESS_DARK = 0;
355    public static final int SCREEN_BRIGHTNESS_DIM = 1;
356    public static final int SCREEN_BRIGHTNESS_MEDIUM = 2;
357    public static final int SCREEN_BRIGHTNESS_LIGHT = 3;
358    public static final int SCREEN_BRIGHTNESS_BRIGHT = 4;
359
360    static final String[] SCREEN_BRIGHTNESS_NAMES = {
361        "dark", "dim", "medium", "light", "bright"
362    };
363
364    public static final int NUM_SCREEN_BRIGHTNESS_BINS = 5;
365
366    /**
367     * Returns the time in milliseconds that the screen has been on with
368     * the given brightness
369     *
370     * {@hide}
371     */
372    public abstract long getScreenBrightnessTime(int brightnessBin,
373            long batteryRealtime, int which);
374
375    public abstract int getInputEventCount(int which);
376
377    /**
378     * Returns the time in milliseconds that the phone has been on while the device was
379     * running on battery.
380     *
381     * {@hide}
382     */
383    public abstract long getPhoneOnTime(long batteryRealtime, int which);
384
385    public static final int SIGNAL_STRENGTH_NONE_OR_UNKNOWN = 0;
386    public static final int SIGNAL_STRENGTH_POOR = 1;
387    public static final int SIGNAL_STRENGTH_MODERATE = 2;
388    public static final int SIGNAL_STRENGTH_GOOD = 3;
389    public static final int SIGNAL_STRENGTH_GREAT = 4;
390
391    static final String[] SIGNAL_STRENGTH_NAMES = {
392        "none", "poor", "moderate", "good", "great"
393    };
394
395    public static final int NUM_SIGNAL_STRENGTH_BINS = 5;
396
397    /**
398     * Returns the time in milliseconds that the phone has been running with
399     * the given signal strength.
400     *
401     * {@hide}
402     */
403    public abstract long getPhoneSignalStrengthTime(int strengthBin,
404            long batteryRealtime, int which);
405
406    /**
407     * Returns the number of times the phone has entered the given signal strength.
408     *
409     * {@hide}
410     */
411    public abstract int getPhoneSignalStrengthCount(int strengthBin, int which);
412
413    public static final int DATA_CONNECTION_NONE = 0;
414    public static final int DATA_CONNECTION_GPRS = 1;
415    public static final int DATA_CONNECTION_EDGE = 2;
416    public static final int DATA_CONNECTION_UMTS = 3;
417    public static final int DATA_CONNECTION_OTHER = 4;
418
419    static final String[] DATA_CONNECTION_NAMES = {
420        "none", "gprs", "edge", "umts", "other"
421    };
422
423    public static final int NUM_DATA_CONNECTION_TYPES = 5;
424
425    /**
426     * Returns the time in milliseconds that the phone has been running with
427     * the given data connection.
428     *
429     * {@hide}
430     */
431    public abstract long getPhoneDataConnectionTime(int dataType,
432            long batteryRealtime, int which);
433
434    /**
435     * Returns the number of times the phone has entered the given data
436     * connection type.
437     *
438     * {@hide}
439     */
440    public abstract int getPhoneDataConnectionCount(int dataType, int which);
441
442    /**
443     * Returns the time in milliseconds that wifi has been on while the device was
444     * running on battery.
445     *
446     * {@hide}
447     */
448    public abstract long getWifiOnTime(long batteryRealtime, int which);
449
450    /**
451     * Returns the time in milliseconds that wifi has been on and the driver has
452     * been in the running state while the device was running on battery.
453     *
454     * {@hide}
455     */
456    public abstract long getWifiRunningTime(long batteryRealtime, int which);
457
458    /**
459     * Returns the time in milliseconds that bluetooth has been on while the device was
460     * running on battery.
461     *
462     * {@hide}
463     */
464    public abstract long getBluetoothOnTime(long batteryRealtime, int which);
465
466    /**
467     * Return whether we are currently running on battery.
468     */
469    public abstract boolean getIsOnBattery();
470
471    /**
472     * Returns a SparseArray containing the statistics for each uid.
473     */
474    public abstract SparseArray<? extends Uid> getUidStats();
475
476    /**
477     * Returns the current battery uptime in microseconds.
478     *
479     * @param curTime the amount of elapsed realtime in microseconds.
480     */
481    public abstract long getBatteryUptime(long curTime);
482
483    /**
484     * Returns the current battery realtime in microseconds.
485     *
486     * @param curTime the amount of elapsed realtime in microseconds.
487     */
488    public abstract long getBatteryRealtime(long curTime);
489
490    /**
491     * Returns the battery percentage level at the last time the device was unplugged from power, or
492     * the last time it booted on battery power.
493     */
494    public abstract int getDischargeStartLevel();
495
496    /**
497     * Returns the current battery percentage level if we are in a discharge cycle, otherwise
498     * returns the level at the last plug event.
499     */
500    public abstract int getDischargeCurrentLevel();
501
502    /**
503     * Returns the total, last, or current battery uptime in microseconds.
504     *
505     * @param curTime the elapsed realtime in microseconds.
506     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
507     */
508    public abstract long computeBatteryUptime(long curTime, int which);
509
510    /**
511     * Returns the total, last, or current battery realtime in microseconds.
512     *
513     * @param curTime the current elapsed realtime in microseconds.
514     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
515     */
516    public abstract long computeBatteryRealtime(long curTime, int which);
517
518    /**
519     * Returns the total, last, or current uptime in microseconds.
520     *
521     * @param curTime the current elapsed realtime in microseconds.
522     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
523     */
524    public abstract long computeUptime(long curTime, int which);
525
526    /**
527     * Returns the total, last, or current realtime in microseconds.
528     * *
529     * @param curTime the current elapsed realtime in microseconds.
530     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
531     */
532    public abstract long computeRealtime(long curTime, int which);
533
534    public abstract Map<String, ? extends Timer> getKernelWakelockStats();
535
536    private final static void formatTimeRaw(StringBuilder out, long seconds) {
537        long days = seconds / (60 * 60 * 24);
538        if (days != 0) {
539            out.append(days);
540            out.append("d ");
541        }
542        long used = days * 60 * 60 * 24;
543
544        long hours = (seconds - used) / (60 * 60);
545        if (hours != 0 || used != 0) {
546            out.append(hours);
547            out.append("h ");
548        }
549        used += hours * 60 * 60;
550
551        long mins = (seconds-used) / 60;
552        if (mins != 0 || used != 0) {
553            out.append(mins);
554            out.append("m ");
555        }
556        used += mins * 60;
557
558        if (seconds != 0 || used != 0) {
559            out.append(seconds-used);
560            out.append("s ");
561        }
562    }
563
564    private final static void formatTime(StringBuilder sb, long time) {
565        long sec = time / 100;
566        formatTimeRaw(sb, sec);
567        sb.append((time - (sec * 100)) * 10);
568        sb.append("ms ");
569    }
570
571    private final static void formatTimeMs(StringBuilder sb, long time) {
572        long sec = time / 1000;
573        formatTimeRaw(sb, sec);
574        sb.append(time - (sec * 1000));
575        sb.append("ms ");
576    }
577
578    private final String formatRatioLocked(long num, long den) {
579        if (den == 0L) {
580            return "---%";
581        }
582        float perc = ((float)num) / ((float)den) * 100;
583        mFormatBuilder.setLength(0);
584        mFormatter.format("%.1f%%", perc);
585        return mFormatBuilder.toString();
586    }
587
588    private final String formatBytesLocked(long bytes) {
589        mFormatBuilder.setLength(0);
590
591        if (bytes < BYTES_PER_KB) {
592            return bytes + "B";
593        } else if (bytes < BYTES_PER_MB) {
594            mFormatter.format("%.2fKB", bytes / (double) BYTES_PER_KB);
595            return mFormatBuilder.toString();
596        } else if (bytes < BYTES_PER_GB){
597            mFormatter.format("%.2fMB", bytes / (double) BYTES_PER_MB);
598            return mFormatBuilder.toString();
599        } else {
600            mFormatter.format("%.2fGB", bytes / (double) BYTES_PER_GB);
601            return mFormatBuilder.toString();
602        }
603    }
604
605    /**
606     *
607     * @param sb a StringBuilder object.
608     * @param timer a Timer object contining the wakelock times.
609     * @param batteryRealtime the current on-battery time in microseconds.
610     * @param name the name of the wakelock.
611     * @param which which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
612     * @param linePrefix a String to be prepended to each line of output.
613     * @return the line prefix
614     */
615    private static final String printWakeLock(StringBuilder sb, Timer timer,
616            long batteryRealtime, String name, int which, String linePrefix) {
617
618        if (timer != null) {
619            // Convert from microseconds to milliseconds with rounding
620            long totalTimeMicros = timer.getTotalTimeLocked(batteryRealtime, which);
621            long totalTimeMillis = (totalTimeMicros + 500) / 1000;
622
623            int count = timer.getCountLocked(which);
624            if (totalTimeMillis != 0) {
625                sb.append(linePrefix);
626                formatTimeMs(sb, totalTimeMillis);
627                if (name != null) sb.append(name);
628                sb.append(' ');
629                sb.append('(');
630                sb.append(count);
631                sb.append(" times)");
632                return ", ";
633            }
634        }
635        return linePrefix;
636    }
637
638    /**
639     * Checkin version of wakelock printer. Prints simple comma-separated list.
640     *
641     * @param sb a StringBuilder object.
642     * @param timer a Timer object contining the wakelock times.
643     * @param now the current time in microseconds.
644     * @param name the name of the wakelock.
645     * @param which which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
646     * @param linePrefix a String to be prepended to each line of output.
647     * @return the line prefix
648     */
649    private static final String printWakeLockCheckin(StringBuilder sb, Timer timer, long now,
650            String name, int which, String linePrefix) {
651        long totalTimeMicros = 0;
652        int count = 0;
653        if (timer != null) {
654            totalTimeMicros = timer.getTotalTimeLocked(now, which);
655            count = timer.getCountLocked(which);
656        }
657        sb.append(linePrefix);
658        sb.append((totalTimeMicros + 500) / 1000); // microseconds to milliseconds with rounding
659        sb.append(',');
660        sb.append(name != null ? name + "," : "");
661        sb.append(count);
662        return ",";
663    }
664
665    /**
666     * Dump a comma-separated line of values for terse checkin mode.
667     *
668     * @param pw the PageWriter to dump log to
669     * @param category category of data (e.g. "total", "last", "unplugged", "current" )
670     * @param type type of data (e.g. "wakelock", "sensor", "process", "apk" ,  "process", "network")
671     * @param args type-dependent data arguments
672     */
673    private static final void dumpLine(PrintWriter pw, int uid, String category, String type,
674           Object... args ) {
675        pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
676        pw.print(uid); pw.print(',');
677        pw.print(category); pw.print(',');
678        pw.print(type);
679
680        for (Object arg : args) {
681            pw.print(',');
682            pw.print(arg);
683        }
684        pw.print('\n');
685    }
686
687    /**
688     * Checkin server version of dump to produce more compact, computer-readable log.
689     *
690     * NOTE: all times are expressed in 'ms'.
691     * @param fd
692     * @param pw
693     * @param which
694     */
695    private final void dumpCheckinLocked(PrintWriter pw, int which) {
696        final long rawUptime = SystemClock.uptimeMillis() * 1000;
697        final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
698        final long batteryUptime = getBatteryUptime(rawUptime);
699        final long batteryRealtime = getBatteryRealtime(rawRealtime);
700        final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
701        final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
702        final long totalRealtime = computeRealtime(rawRealtime, which);
703        final long totalUptime = computeUptime(rawUptime, which);
704        final long screenOnTime = getScreenOnTime(batteryRealtime, which);
705        final long phoneOnTime = getPhoneOnTime(batteryRealtime, which);
706        final long wifiOnTime = getWifiOnTime(batteryRealtime, which);
707        final long wifiRunningTime = getWifiRunningTime(batteryRealtime, which);
708        final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which);
709
710        StringBuilder sb = new StringBuilder(128);
711
712        SparseArray<? extends Uid> uidStats = getUidStats();
713        final int NU = uidStats.size();
714
715        String category = STAT_NAMES[which];
716
717        // Dump "battery" stat
718        dumpLine(pw, 0 /* uid */, category, BATTERY_DATA,
719                which == STATS_TOTAL ? getStartCount() : "N/A",
720                whichBatteryRealtime / 1000, whichBatteryUptime / 1000,
721                totalRealtime / 1000, totalUptime / 1000);
722
723        // Calculate total network and wakelock times across all uids.
724        long rxTotal = 0;
725        long txTotal = 0;
726        long fullWakeLockTimeTotal = 0;
727        long partialWakeLockTimeTotal = 0;
728
729        for (int iu = 0; iu < NU; iu++) {
730            Uid u = uidStats.valueAt(iu);
731            rxTotal += u.getTcpBytesReceived(which);
732            txTotal += u.getTcpBytesSent(which);
733
734            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
735            if (wakelocks.size() > 0) {
736                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
737                        : wakelocks.entrySet()) {
738                    Uid.Wakelock wl = ent.getValue();
739
740                    Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
741                    if (fullWakeTimer != null) {
742                        fullWakeLockTimeTotal += fullWakeTimer.getTotalTimeLocked(batteryRealtime, which);
743                    }
744
745                    Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
746                    if (partialWakeTimer != null) {
747                        partialWakeLockTimeTotal += partialWakeTimer.getTotalTimeLocked(
748                            batteryRealtime, which);
749                    }
750                }
751            }
752        }
753
754        // Dump misc stats
755        dumpLine(pw, 0 /* uid */, category, MISC_DATA,
756                screenOnTime / 1000, phoneOnTime / 1000, wifiOnTime / 1000,
757                wifiRunningTime / 1000, bluetoothOnTime / 1000, rxTotal, txTotal,
758                fullWakeLockTimeTotal, partialWakeLockTimeTotal,
759                getInputEventCount(which));
760
761        // Dump screen brightness stats
762        Object[] args = new Object[NUM_SCREEN_BRIGHTNESS_BINS];
763        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
764            args[i] = getScreenBrightnessTime(i, batteryRealtime, which) / 1000;
765        }
766        dumpLine(pw, 0 /* uid */, category, SCREEN_BRIGHTNESS_DATA, args);
767
768        // Dump signal strength stats
769        args = new Object[NUM_SIGNAL_STRENGTH_BINS];
770        for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
771            args[i] = getPhoneSignalStrengthTime(i, batteryRealtime, which) / 1000;
772        }
773        dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_TIME_DATA, args);
774        for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
775            args[i] = getPhoneSignalStrengthCount(i, which);
776        }
777        dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_COUNT_DATA, args);
778
779        // Dump network type stats
780        args = new Object[NUM_DATA_CONNECTION_TYPES];
781        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
782            args[i] = getPhoneDataConnectionTime(i, batteryRealtime, which) / 1000;
783        }
784        dumpLine(pw, 0 /* uid */, category, DATA_CONNECTION_TIME_DATA, args);
785        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
786            args[i] = getPhoneDataConnectionCount(i, which);
787        }
788        dumpLine(pw, 0 /* uid */, category, DATA_CONNECTION_COUNT_DATA, args);
789
790        if (which == STATS_UNPLUGGED) {
791            dumpLine(pw, 0 /* uid */, category, BATTERY_LEVEL_DATA, getDischargeStartLevel(),
792                    getDischargeCurrentLevel());
793        }
794
795        Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats();
796        if (kernelWakelocks.size() > 0) {
797            for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) {
798                sb.setLength(0);
799                printWakeLockCheckin(sb, ent.getValue(), batteryRealtime, null, which, "");
800
801                dumpLine(pw, 0 /* uid */, category, KERNEL_WAKELOCK_DATA, ent.getKey(),
802                        sb.toString());
803            }
804        }
805
806        for (int iu = 0; iu < NU; iu++) {
807            final int uid = uidStats.keyAt(iu);
808            Uid u = uidStats.valueAt(iu);
809            // Dump Network stats per uid, if any
810            long rx = u.getTcpBytesReceived(which);
811            long tx = u.getTcpBytesSent(which);
812            long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
813            long scanWifiLockOnTime = u.getScanWifiLockTime(batteryRealtime, which);
814            long wifiTurnedOnTime = u.getWifiTurnedOnTime(batteryRealtime, which);
815
816            if (rx > 0 || tx > 0) dumpLine(pw, uid, category, NETWORK_DATA, rx, tx);
817
818            if (fullWifiLockOnTime != 0 || scanWifiLockOnTime != 0
819                    || wifiTurnedOnTime != 0) {
820                dumpLine(pw, uid, category, WIFI_LOCK_DATA,
821                        fullWifiLockOnTime, scanWifiLockOnTime, wifiTurnedOnTime);
822            }
823
824            if (u.hasUserActivity()) {
825                args = new Object[Uid.NUM_USER_ACTIVITY_TYPES];
826                boolean hasData = false;
827                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
828                    int val = u.getUserActivityCount(i, which);
829                    args[i] = val;
830                    if (val != 0) hasData = true;
831                }
832                if (hasData) {
833                    dumpLine(pw, 0 /* uid */, category, USER_ACTIVITY_DATA, args);
834                }
835            }
836
837            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
838            if (wakelocks.size() > 0) {
839                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
840                        : wakelocks.entrySet()) {
841                    Uid.Wakelock wl = ent.getValue();
842                    String linePrefix = "";
843                    sb.setLength(0);
844                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_FULL),
845                            batteryRealtime, "f", which, linePrefix);
846                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL),
847                            batteryRealtime, "p", which, linePrefix);
848                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_WINDOW),
849                            batteryRealtime, "w", which, linePrefix);
850
851                    // Only log if we had at lease one wakelock...
852                    if (sb.length() > 0) {
853                       dumpLine(pw, uid, category, WAKELOCK_DATA, ent.getKey(), sb.toString());
854                    }
855                }
856            }
857
858            Map<Integer, ? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
859            if (sensors.size() > 0)  {
860                for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> ent
861                        : sensors.entrySet()) {
862                    Uid.Sensor se = ent.getValue();
863                    int sensorNumber = ent.getKey();
864                    Timer timer = se.getSensorTime();
865                    if (timer != null) {
866                        // Convert from microseconds to milliseconds with rounding
867                        long totalTime = (timer.getTotalTimeLocked(batteryRealtime, which) + 500) / 1000;
868                        int count = timer.getCountLocked(which);
869                        if (totalTime != 0) {
870                            dumpLine(pw, uid, category, SENSOR_DATA, sensorNumber, totalTime, count);
871                        }
872                    }
873                }
874            }
875
876            Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
877            if (processStats.size() > 0) {
878                for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
879                        : processStats.entrySet()) {
880                    Uid.Proc ps = ent.getValue();
881
882                    long userTime = ps.getUserTime(which);
883                    long systemTime = ps.getSystemTime(which);
884                    int starts = ps.getStarts(which);
885
886                    if (userTime != 0 || systemTime != 0 || starts != 0) {
887                        dumpLine(pw, uid, category, PROCESS_DATA,
888                                ent.getKey(), // proc
889                                userTime * 10, // cpu time in ms
890                                systemTime * 10, // user time in ms
891                                starts); // process starts
892                    }
893                }
894            }
895
896            Map<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats();
897            if (packageStats.size() > 0) {
898                for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent
899                        : packageStats.entrySet()) {
900
901                    Uid.Pkg ps = ent.getValue();
902                    int wakeups = ps.getWakeups(which);
903                    Map<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
904                    for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent
905                            : serviceStats.entrySet()) {
906                        BatteryStats.Uid.Pkg.Serv ss = sent.getValue();
907                        long startTime = ss.getStartTime(batteryUptime, which);
908                        int starts = ss.getStarts(which);
909                        int launches = ss.getLaunches(which);
910                        if (startTime != 0 || starts != 0 || launches != 0) {
911                            dumpLine(pw, uid, category, APK_DATA,
912                                    wakeups, // wakeup alarms
913                                    ent.getKey(), // Apk
914                                    sent.getKey(), // service
915                                    startTime / 1000, // time spent started, in ms
916                                    starts,
917                                    launches);
918                        }
919                    }
920                }
921            }
922        }
923    }
924
925    @SuppressWarnings("unused")
926    private final void dumpLocked(PrintWriter pw, String prefix, int which) {
927        final long rawUptime = SystemClock.uptimeMillis() * 1000;
928        final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
929        final long batteryUptime = getBatteryUptime(rawUptime);
930        final long batteryRealtime = getBatteryRealtime(rawRealtime);
931
932        final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
933        final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
934        final long totalRealtime = computeRealtime(rawRealtime, which);
935        final long totalUptime = computeUptime(rawUptime, which);
936
937        StringBuilder sb = new StringBuilder(128);
938
939        SparseArray<? extends Uid> uidStats = getUidStats();
940        final int NU = uidStats.size();
941
942        sb.setLength(0);
943        sb.append(prefix);
944                sb.append("  Time on battery: ");
945                formatTimeMs(sb, whichBatteryRealtime / 1000); sb.append("(");
946                sb.append(formatRatioLocked(whichBatteryRealtime, totalRealtime));
947                sb.append(") realtime, ");
948                formatTimeMs(sb, whichBatteryUptime / 1000);
949                sb.append("("); sb.append(formatRatioLocked(whichBatteryUptime, totalRealtime));
950                sb.append(") uptime");
951        pw.println(sb.toString());
952        sb.setLength(0);
953        sb.append(prefix);
954                sb.append("  Total run time: ");
955                formatTimeMs(sb, totalRealtime / 1000);
956                sb.append("realtime, ");
957                formatTimeMs(sb, totalUptime / 1000);
958                sb.append("uptime, ");
959        pw.println(sb.toString());
960
961        final long screenOnTime = getScreenOnTime(batteryRealtime, which);
962        final long phoneOnTime = getPhoneOnTime(batteryRealtime, which);
963        final long wifiRunningTime = getWifiRunningTime(batteryRealtime, which);
964        final long wifiOnTime = getWifiOnTime(batteryRealtime, which);
965        final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which);
966        sb.setLength(0);
967        sb.append(prefix);
968                sb.append("  Screen on: "); formatTimeMs(sb, screenOnTime / 1000);
969                sb.append("("); sb.append(formatRatioLocked(screenOnTime, whichBatteryRealtime));
970                sb.append("), Input events: "); sb.append(getInputEventCount(which));
971                sb.append(", Active phone call: "); formatTimeMs(sb, phoneOnTime / 1000);
972                sb.append("("); sb.append(formatRatioLocked(phoneOnTime, whichBatteryRealtime));
973                sb.append(")");
974        pw.println(sb.toString());
975        sb.setLength(0);
976        sb.append(prefix);
977        sb.append("  Screen brightnesses: ");
978        boolean didOne = false;
979        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
980            final long time = getScreenBrightnessTime(i, batteryRealtime, which);
981            if (time == 0) {
982                continue;
983            }
984            if (didOne) sb.append(", ");
985            didOne = true;
986            sb.append(SCREEN_BRIGHTNESS_NAMES[i]);
987            sb.append(" ");
988            formatTimeMs(sb, time/1000);
989            sb.append("(");
990            sb.append(formatRatioLocked(time, screenOnTime));
991            sb.append(")");
992        }
993        if (!didOne) sb.append("No activity");
994        pw.println(sb.toString());
995
996        // Calculate total network and wakelock times across all uids.
997        long rxTotal = 0;
998        long txTotal = 0;
999        long fullWakeLockTimeTotalMicros = 0;
1000        long partialWakeLockTimeTotalMicros = 0;
1001
1002        Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats();
1003        if (kernelWakelocks.size() > 0) {
1004            for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) {
1005
1006                String linePrefix = ": ";
1007                sb.setLength(0);
1008                sb.append(prefix);
1009                sb.append("  Kernel Wake lock ");
1010                sb.append(ent.getKey());
1011                linePrefix = printWakeLock(sb, ent.getValue(), batteryRealtime, null, which,
1012                        linePrefix);
1013                if (!linePrefix.equals(": ")) {
1014                    sb.append(" realtime");
1015                } else {
1016                    sb.append(": (nothing executed)");
1017                }
1018                pw.println(sb.toString());
1019            }
1020        }
1021
1022        for (int iu = 0; iu < NU; iu++) {
1023            Uid u = uidStats.valueAt(iu);
1024            rxTotal += u.getTcpBytesReceived(which);
1025            txTotal += u.getTcpBytesSent(which);
1026
1027            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
1028            if (wakelocks.size() > 0) {
1029                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
1030                        : wakelocks.entrySet()) {
1031                    Uid.Wakelock wl = ent.getValue();
1032
1033                    Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
1034                    if (fullWakeTimer != null) {
1035                        fullWakeLockTimeTotalMicros += fullWakeTimer.getTotalTimeLocked(
1036                                batteryRealtime, which);
1037                    }
1038
1039                    Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
1040                    if (partialWakeTimer != null) {
1041                        partialWakeLockTimeTotalMicros += partialWakeTimer.getTotalTimeLocked(
1042                                batteryRealtime, which);
1043                    }
1044                }
1045            }
1046        }
1047
1048        pw.print(prefix);
1049                pw.print("  Total received: "); pw.print(formatBytesLocked(rxTotal));
1050                pw.print(", Total sent: "); pw.println(formatBytesLocked(txTotal));
1051        sb.setLength(0);
1052        sb.append(prefix);
1053                sb.append("  Total full wakelock time: "); formatTimeMs(sb,
1054                        (fullWakeLockTimeTotalMicros + 500) / 1000);
1055                sb.append(", Total partial waklock time: "); formatTimeMs(sb,
1056                        (partialWakeLockTimeTotalMicros + 500) / 1000);
1057        pw.println(sb.toString());
1058
1059        sb.setLength(0);
1060        sb.append(prefix);
1061        sb.append("  Signal levels: ");
1062        didOne = false;
1063        for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
1064            final long time = getPhoneSignalStrengthTime(i, batteryRealtime, which);
1065            if (time == 0) {
1066                continue;
1067            }
1068            if (didOne) sb.append(", ");
1069            didOne = true;
1070            sb.append(SIGNAL_STRENGTH_NAMES[i]);
1071            sb.append(" ");
1072            formatTimeMs(sb, time/1000);
1073            sb.append("(");
1074            sb.append(formatRatioLocked(time, whichBatteryRealtime));
1075            sb.append(") ");
1076            sb.append(getPhoneSignalStrengthCount(i, which));
1077            sb.append("x");
1078        }
1079        if (!didOne) sb.append("No activity");
1080        pw.println(sb.toString());
1081
1082        sb.setLength(0);
1083        sb.append(prefix);
1084        sb.append("  Radio types: ");
1085        didOne = false;
1086        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
1087            final long time = getPhoneDataConnectionTime(i, batteryRealtime, which);
1088            if (time == 0) {
1089                continue;
1090            }
1091            if (didOne) sb.append(", ");
1092            didOne = true;
1093            sb.append(DATA_CONNECTION_NAMES[i]);
1094            sb.append(" ");
1095            formatTimeMs(sb, time/1000);
1096            sb.append("(");
1097            sb.append(formatRatioLocked(time, whichBatteryRealtime));
1098            sb.append(") ");
1099            sb.append(getPhoneDataConnectionCount(i, which));
1100            sb.append("x");
1101        }
1102        if (!didOne) sb.append("No activity");
1103        pw.println(sb.toString());
1104
1105        sb.setLength(0);
1106        sb.append(prefix);
1107                sb.append("  Wifi on: "); formatTimeMs(sb, wifiOnTime / 1000);
1108                sb.append("("); sb.append(formatRatioLocked(wifiOnTime, whichBatteryRealtime));
1109                sb.append("), Wifi running: "); formatTimeMs(sb, wifiRunningTime / 1000);
1110                sb.append("("); sb.append(formatRatioLocked(wifiRunningTime, whichBatteryRealtime));
1111                sb.append("), Bluetooth on: "); formatTimeMs(sb, bluetoothOnTime / 1000);
1112                sb.append("("); sb.append(formatRatioLocked(bluetoothOnTime, whichBatteryRealtime));
1113                sb.append(")");
1114        pw.println(sb.toString());
1115
1116        pw.println(" ");
1117
1118        if (which == STATS_UNPLUGGED) {
1119            if (getIsOnBattery()) {
1120                pw.print(prefix); pw.println("  Device is currently unplugged");
1121                pw.print(prefix); pw.print("    Discharge cycle start level: ");
1122                        pw.println(getDischargeStartLevel());
1123                pw.print(prefix); pw.print("    Discharge cycle current level: ");
1124                        pw.println(getDischargeCurrentLevel());
1125            } else {
1126                pw.print(prefix); pw.println("  Device is currently plugged into power");
1127                pw.print(prefix); pw.print("    Last discharge cycle start level: ");
1128                        pw.println(getDischargeStartLevel());
1129                pw.print(prefix); pw.print("    Last discharge cycle end level: ");
1130                        pw.println(getDischargeCurrentLevel());
1131            }
1132            pw.println(" ");
1133        }
1134
1135
1136        for (int iu=0; iu<NU; iu++) {
1137            final int uid = uidStats.keyAt(iu);
1138            Uid u = uidStats.valueAt(iu);
1139            pw.println(prefix + "  #" + uid + ":");
1140            boolean uidActivity = false;
1141
1142            long tcpReceived = u.getTcpBytesReceived(which);
1143            long tcpSent = u.getTcpBytesSent(which);
1144            long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
1145            long scanWifiLockOnTime = u.getScanWifiLockTime(batteryRealtime, which);
1146            long wifiTurnedOnTime = u.getWifiTurnedOnTime(batteryRealtime, which);
1147
1148            if (tcpReceived != 0 || tcpSent != 0) {
1149                pw.print(prefix); pw.print("    Network: ");
1150                        pw.print(formatBytesLocked(tcpReceived)); pw.print(" received, ");
1151                        pw.print(formatBytesLocked(tcpSent)); pw.println(" sent");
1152            }
1153
1154            if (u.hasUserActivity()) {
1155                boolean hasData = false;
1156                for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
1157                    int val = u.getUserActivityCount(i, which);
1158                    if (val != 0) {
1159                        if (!hasData) {
1160                            sb.setLength(0);
1161                            sb.append("    User activity: ");
1162                            hasData = true;
1163                        } else {
1164                            sb.append(", ");
1165                        }
1166                        sb.append(val);
1167                        sb.append(" ");
1168                        sb.append(Uid.USER_ACTIVITY_TYPES[i]);
1169                    }
1170                }
1171                if (hasData) {
1172                    pw.println(sb.toString());
1173                }
1174            }
1175
1176            if (fullWifiLockOnTime != 0 || scanWifiLockOnTime != 0
1177                    || wifiTurnedOnTime != 0) {
1178                sb.setLength(0);
1179                sb.append(prefix); sb.append("    Turned Wifi On: ");
1180                        formatTimeMs(sb, wifiTurnedOnTime / 1000);
1181                        sb.append("("); sb.append(formatRatioLocked(wifiTurnedOnTime,
1182                                whichBatteryRealtime)); sb.append(")\n");
1183                sb.append(prefix); sb.append("    Full Wifi Lock: ");
1184                        formatTimeMs(sb, fullWifiLockOnTime / 1000);
1185                        sb.append("("); sb.append(formatRatioLocked(fullWifiLockOnTime,
1186                                whichBatteryRealtime)); sb.append(")\n");
1187                sb.append(prefix); sb.append("    Scan Wifi Lock: ");
1188                        formatTimeMs(sb, scanWifiLockOnTime / 1000);
1189                        sb.append("("); sb.append(formatRatioLocked(scanWifiLockOnTime,
1190                                whichBatteryRealtime)); sb.append(")");
1191                pw.println(sb.toString());
1192            }
1193
1194            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
1195            if (wakelocks.size() > 0) {
1196                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
1197                    : wakelocks.entrySet()) {
1198                    Uid.Wakelock wl = ent.getValue();
1199                    String linePrefix = ": ";
1200                    sb.setLength(0);
1201                    sb.append(prefix);
1202                    sb.append("    Wake lock ");
1203                    sb.append(ent.getKey());
1204                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_FULL), batteryRealtime,
1205                            "full", which, linePrefix);
1206                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), batteryRealtime,
1207                            "partial", which, linePrefix);
1208                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), batteryRealtime,
1209                            "window", which, linePrefix);
1210                    if (!linePrefix.equals(": ")) {
1211                        sb.append(" realtime");
1212                    } else {
1213                        sb.append(": (nothing executed)");
1214                    }
1215                    pw.println(sb.toString());
1216                    uidActivity = true;
1217                }
1218            }
1219
1220            Map<Integer, ? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
1221            if (sensors.size() > 0) {
1222                for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> ent
1223                    : sensors.entrySet()) {
1224                    Uid.Sensor se = ent.getValue();
1225                    int sensorNumber = ent.getKey();
1226                    sb.setLength(0);
1227                    sb.append(prefix);
1228                    sb.append("    Sensor ");
1229                    int handle = se.getHandle();
1230                    if (handle == Uid.Sensor.GPS) {
1231                        sb.append("GPS");
1232                    } else {
1233                        sb.append(handle);
1234                    }
1235                    sb.append(": ");
1236
1237                    Timer timer = se.getSensorTime();
1238                    if (timer != null) {
1239                        // Convert from microseconds to milliseconds with rounding
1240                        long totalTime = (timer.getTotalTimeLocked(
1241                                batteryRealtime, which) + 500) / 1000;
1242                        int count = timer.getCountLocked(which);
1243                        //timer.logState();
1244                        if (totalTime != 0) {
1245                            formatTimeMs(sb, totalTime);
1246                            sb.append("realtime (");
1247                            sb.append(count);
1248                            sb.append(" times)");
1249                        } else {
1250                            sb.append("(not used)");
1251                        }
1252                    } else {
1253                        sb.append("(not used)");
1254                    }
1255
1256                    pw.println(sb.toString());
1257                    uidActivity = true;
1258                }
1259            }
1260
1261            Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
1262            if (processStats.size() > 0) {
1263                for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
1264                    : processStats.entrySet()) {
1265                    Uid.Proc ps = ent.getValue();
1266                    long userTime;
1267                    long systemTime;
1268                    int starts;
1269
1270                    userTime = ps.getUserTime(which);
1271                    systemTime = ps.getSystemTime(which);
1272                    starts = ps.getStarts(which);
1273
1274                    if (userTime != 0 || systemTime != 0 || starts != 0) {
1275                        sb.setLength(0);
1276                        sb.append(prefix); sb.append("    Proc ");
1277                                sb.append(ent.getKey()); sb.append(":\n");
1278                        sb.append(prefix); sb.append("      CPU: ");
1279                                formatTime(sb, userTime); sb.append("usr + ");
1280                                formatTime(sb, systemTime); sb.append("krn\n");
1281                        sb.append(prefix); sb.append("      "); sb.append(starts);
1282                                sb.append(" proc starts");
1283                        pw.println(sb.toString());
1284                        uidActivity = true;
1285                    }
1286                }
1287            }
1288
1289            Map<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats();
1290            if (packageStats.size() > 0) {
1291                for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent
1292                    : packageStats.entrySet()) {
1293                    pw.print(prefix); pw.print("    Apk "); pw.print(ent.getKey()); pw.println(":");
1294                    boolean apkActivity = false;
1295                    Uid.Pkg ps = ent.getValue();
1296                    int wakeups = ps.getWakeups(which);
1297                    if (wakeups != 0) {
1298                        pw.print(prefix); pw.print("      ");
1299                                pw.print(wakeups); pw.println(" wakeup alarms");
1300                        apkActivity = true;
1301                    }
1302                    Map<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
1303                    if (serviceStats.size() > 0) {
1304                        for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent
1305                                : serviceStats.entrySet()) {
1306                            BatteryStats.Uid.Pkg.Serv ss = sent.getValue();
1307                            long startTime = ss.getStartTime(batteryUptime, which);
1308                            int starts = ss.getStarts(which);
1309                            int launches = ss.getLaunches(which);
1310                            if (startTime != 0 || starts != 0 || launches != 0) {
1311                                sb.setLength(0);
1312                                sb.append(prefix); sb.append("      Service ");
1313                                        sb.append(sent.getKey()); sb.append(":\n");
1314                                sb.append(prefix); sb.append("        Created for: ");
1315                                        formatTimeMs(sb, startTime / 1000);
1316                                        sb.append(" uptime\n");
1317                                sb.append(prefix); sb.append("        Starts: ");
1318                                        sb.append(starts);
1319                                        sb.append(", launches: "); sb.append(launches);
1320                                pw.println(sb.toString());
1321                                apkActivity = true;
1322                            }
1323                        }
1324                    }
1325                    if (!apkActivity) {
1326                        pw.print(prefix); pw.println("      (nothing executed)");
1327                    }
1328                    uidActivity = true;
1329                }
1330            }
1331            if (!uidActivity) {
1332                pw.print(prefix); pw.println("    (nothing executed)");
1333            }
1334        }
1335    }
1336
1337    /**
1338     * Dumps a human-readable summary of the battery statistics to the given PrintWriter.
1339     *
1340     * @param pw a Printer to receive the dump output.
1341     */
1342    @SuppressWarnings("unused")
1343    public void dumpLocked(PrintWriter pw) {
1344        pw.println("Total Statistics (Current and Historic):");
1345        pw.println("  System starts: " + getStartCount()
1346                + ", currently on battery: " + getIsOnBattery());
1347        dumpLocked(pw, "", STATS_TOTAL);
1348        pw.println("");
1349        pw.println("Last Run Statistics (Previous run of system):");
1350        dumpLocked(pw, "", STATS_LAST);
1351        pw.println("");
1352        pw.println("Current Battery Statistics (Currently running system):");
1353        dumpLocked(pw, "", STATS_CURRENT);
1354        pw.println("");
1355        pw.println("Unplugged Statistics (Since last unplugged from power):");
1356        dumpLocked(pw, "", STATS_UNPLUGGED);
1357    }
1358
1359    @SuppressWarnings("unused")
1360    public void dumpCheckinLocked(PrintWriter pw, String[] args) {
1361        boolean isUnpluggedOnly = false;
1362
1363        for (String arg : args) {
1364            if ("-u".equals(arg)) {
1365                if (LOCAL_LOGV) Log.v("BatteryStats", "Dumping unplugged data");
1366                isUnpluggedOnly = true;
1367            }
1368        }
1369
1370        if (isUnpluggedOnly) {
1371            dumpCheckinLocked(pw, STATS_UNPLUGGED);
1372        }
1373        else {
1374            dumpCheckinLocked(pw, STATS_TOTAL);
1375            dumpCheckinLocked(pw, STATS_LAST);
1376            dumpCheckinLocked(pw, STATS_UNPLUGGED);
1377            dumpCheckinLocked(pw, STATS_CURRENT);
1378        }
1379    }
1380
1381}
1382