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