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