BatteryStats.java revision 617f877c06c82584a38f41bb60d836e08c5e3bda
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,
476     * or the last time it was booted while unplugged.
477     */
478    public abstract int getUnpluggedStartLevel();
479
480    /**
481     * Returns the battery percentage level at the last time the device was plugged into power.
482     */
483    public abstract int getPluggedStartLevel();
484
485    /**
486     * Returns the total, last, or current battery uptime in microseconds.
487     *
488     * @param curTime the elapsed realtime in microseconds.
489     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
490     */
491    public abstract long computeBatteryUptime(long curTime, int which);
492
493    /**
494     * Returns the total, last, or current battery realtime in microseconds.
495     *
496     * @param curTime the current elapsed realtime in microseconds.
497     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
498     */
499    public abstract long computeBatteryRealtime(long curTime, int which);
500
501    /**
502     * Returns the total, last, or current uptime in microseconds.
503     *
504     * @param curTime the current elapsed realtime in microseconds.
505     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
506     */
507    public abstract long computeUptime(long curTime, int which);
508
509    /**
510     * Returns the total, last, or current realtime in microseconds.
511     * *
512     * @param curTime the current elapsed realtime in microseconds.
513     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
514     */
515    public abstract long computeRealtime(long curTime, int which);
516
517    private final static void formatTime(StringBuilder out, long seconds) {
518        long days = seconds / (60 * 60 * 24);
519        if (days != 0) {
520            out.append(days);
521            out.append("d ");
522        }
523        long used = days * 60 * 60 * 24;
524
525        long hours = (seconds - used) / (60 * 60);
526        if (hours != 0 || used != 0) {
527            out.append(hours);
528            out.append("h ");
529        }
530        used += hours * 60 * 60;
531
532        long mins = (seconds-used) / 60;
533        if (mins != 0 || used != 0) {
534            out.append(mins);
535            out.append("m ");
536        }
537        used += mins * 60;
538
539        if (seconds != 0 || used != 0) {
540            out.append(seconds-used);
541            out.append("s ");
542        }
543    }
544
545    private final static String formatTime(long time) {
546        long sec = time / 100;
547        StringBuilder sb = new StringBuilder();
548        formatTime(sb, sec);
549        sb.append((time - (sec * 100)) * 10);
550        sb.append("ms ");
551        return sb.toString();
552    }
553
554    private final static String formatTimeMs(long time) {
555        long sec = time / 1000;
556        StringBuilder sb = new StringBuilder();
557        formatTime(sb, sec);
558        sb.append(time - (sec * 1000));
559        sb.append("ms ");
560        return sb.toString();
561    }
562
563    private final String formatRatioLocked(long num, long den) {
564        if (den == 0L) {
565            return "---%";
566        }
567        float perc = ((float)num) / ((float)den) * 100;
568        mFormatBuilder.setLength(0);
569        mFormatter.format("%.1f%%", perc);
570        return mFormatBuilder.toString();
571    }
572
573    private final String formatBytesLocked(long bytes) {
574        mFormatBuilder.setLength(0);
575
576        if (bytes < BYTES_PER_KB) {
577            return bytes + "B";
578        } else if (bytes < BYTES_PER_MB) {
579            mFormatter.format("%.2fKB", bytes / (double) BYTES_PER_KB);
580            return mFormatBuilder.toString();
581        } else if (bytes < BYTES_PER_GB){
582            mFormatter.format("%.2fMB", bytes / (double) BYTES_PER_MB);
583            return mFormatBuilder.toString();
584        } else {
585            mFormatter.format("%.2fGB", bytes / (double) BYTES_PER_GB);
586            return mFormatBuilder.toString();
587        }
588    }
589
590    /**
591     *
592     * @param sb a StringBuilder object.
593     * @param timer a Timer object contining the wakelock times.
594     * @param batteryRealtime the current on-battery time in microseconds.
595     * @param name the name of the wakelock.
596     * @param which which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
597     * @param linePrefix a String to be prepended to each line of output.
598     * @return the line prefix
599     */
600    private static final String printWakeLock(StringBuilder sb, Timer timer,
601            long batteryRealtime, String name, int which, String linePrefix) {
602
603        if (timer != null) {
604            // Convert from microseconds to milliseconds with rounding
605            long totalTimeMicros = timer.getTotalTime(batteryRealtime, which);
606            long totalTimeMillis = (totalTimeMicros + 500) / 1000;
607
608            int count = timer.getCount(which);
609            if (totalTimeMillis != 0) {
610                sb.append(linePrefix);
611                sb.append(formatTimeMs(totalTimeMillis));
612                sb.append(name);
613                sb.append(' ');
614                sb.append('(');
615                sb.append(count);
616                sb.append(" times)");
617                return ", ";
618            }
619        }
620        return linePrefix;
621    }
622
623    /**
624     * Checkin version of wakelock printer. Prints simple comma-separated list.
625     *
626     * @param sb a StringBuilder object.
627     * @param timer a Timer object contining the wakelock times.
628     * @param now the current time in microseconds.
629     * @param name the name of the wakelock.
630     * @param which which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
631     * @param linePrefix a String to be prepended to each line of output.
632     * @return the line prefix
633     */
634    private static final String printWakeLockCheckin(StringBuilder sb, Timer timer, long now,
635        String name, int which, String linePrefix) {
636        long totalTimeMicros = 0;
637        int count = 0;
638        if (timer != null) {
639            totalTimeMicros = timer.getTotalTime(now, which);
640            count = timer.getCount(which);
641        }
642        sb.append(linePrefix);
643        sb.append((totalTimeMicros + 500) / 1000); // microseconds to milliseconds with rounding
644        sb.append(',');
645        sb.append(name);
646        sb.append(',');
647        sb.append(count);
648        return ",";
649    }
650
651    /**
652     * Dump a comma-separated line of values for terse checkin mode.
653     *
654     * @param pw the PageWriter to dump log to
655     * @param category category of data (e.g. "total", "last", "unplugged", "current" )
656     * @param type type of data (e.g. "wakelock", "sensor", "process", "apk" ,  "process", "network")
657     * @param args type-dependent data arguments
658     */
659    private static final void dumpLine(PrintWriter pw, int uid, String category, String type,
660           Object... args ) {
661        pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
662        pw.print(uid); pw.print(',');
663        pw.print(category); pw.print(',');
664        pw.print(type);
665
666        for (Object arg : args) {
667            pw.print(',');
668            pw.print(arg);
669        }
670        pw.print('\n');
671    }
672
673    /**
674     * Checkin server version of dump to produce more compact, computer-readable log.
675     *
676     * NOTE: all times are expressed in 'ms'.
677     * @param fd
678     * @param pw
679     * @param which
680     */
681    private final void dumpCheckinLocked(PrintWriter pw, int which) {
682        final long rawUptime = SystemClock.uptimeMillis() * 1000;
683        final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
684        final long batteryUptime = getBatteryUptime(rawUptime);
685        final long batteryRealtime = getBatteryRealtime(rawRealtime);
686        final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
687        final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
688        final long totalRealtime = computeRealtime(rawRealtime, which);
689        final long totalUptime = computeUptime(rawUptime, which);
690        final long screenOnTime = getScreenOnTime(batteryRealtime, which);
691        final long phoneOnTime = getPhoneOnTime(batteryRealtime, which);
692        final long wifiOnTime = getWifiOnTime(batteryRealtime, which);
693        final long wifiRunningTime = getWifiRunningTime(batteryRealtime, which);
694        final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which);
695
696        StringBuilder sb = new StringBuilder(128);
697
698        SparseArray<? extends Uid> uidStats = getUidStats();
699        final int NU = uidStats.size();
700
701        String category = STAT_NAMES[which];
702
703        // Dump "battery" stat
704        dumpLine(pw, 0 /* uid */, category, BATTERY_DATA,
705                which == STATS_TOTAL ? getStartCount() : "N/A",
706                whichBatteryRealtime / 1000, whichBatteryUptime / 1000,
707                totalRealtime / 1000, totalUptime / 1000);
708
709        // Calculate total network and wakelock times across all uids.
710        long rxTotal = 0;
711        long txTotal = 0;
712        long fullWakeLockTimeTotal = 0;
713        long partialWakeLockTimeTotal = 0;
714
715        for (int iu = 0; iu < NU; iu++) {
716            Uid u = uidStats.valueAt(iu);
717            rxTotal += u.getTcpBytesReceived(which);
718            txTotal += u.getTcpBytesSent(which);
719
720            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
721            if (wakelocks.size() > 0) {
722                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
723                        : wakelocks.entrySet()) {
724                    Uid.Wakelock wl = ent.getValue();
725
726                    Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
727                    if (fullWakeTimer != null) {
728                        fullWakeLockTimeTotal += fullWakeTimer.getTotalTime(batteryRealtime, which);
729                    }
730
731                    Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
732                    if (partialWakeTimer != null) {
733                        partialWakeLockTimeTotal += partialWakeTimer.getTotalTime(
734                            batteryRealtime, which);
735                    }
736                }
737            }
738        }
739
740        // Dump misc stats
741        dumpLine(pw, 0 /* uid */, category, MISC_DATA,
742                screenOnTime / 1000, phoneOnTime / 1000, wifiOnTime / 1000,
743                wifiRunningTime / 1000, bluetoothOnTime / 1000, rxTotal, txTotal,
744                fullWakeLockTimeTotal, partialWakeLockTimeTotal,
745                getInputEventCount(which));
746
747        // Dump screen brightness stats
748        Object[] args = new Object[NUM_SCREEN_BRIGHTNESS_BINS];
749        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
750            args[i] = getScreenBrightnessTime(i, batteryRealtime, which) / 1000;
751        }
752        dumpLine(pw, 0 /* uid */, category, SCREEN_BRIGHTNESS_DATA, args);
753
754        // Dump signal strength stats
755        args = new Object[NUM_SIGNAL_STRENGTH_BINS];
756        for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
757            args[i] = getPhoneSignalStrengthTime(i, batteryRealtime, which) / 1000;
758        }
759        dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_TIME_DATA, args);
760        for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
761            args[i] = getPhoneSignalStrengthCount(i, which);
762        }
763        dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_COUNT_DATA, args);
764
765        // Dump network type stats
766        args = new Object[NUM_DATA_CONNECTION_TYPES];
767        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
768            args[i] = getPhoneDataConnectionTime(i, batteryRealtime, which) / 1000;
769        }
770        dumpLine(pw, 0 /* uid */, category, DATA_CONNECTION_TIME_DATA, args);
771        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
772            args[i] = getPhoneDataConnectionCount(i, which);
773        }
774        dumpLine(pw, 0 /* uid */, category, DATA_CONNECTION_COUNT_DATA, args);
775
776        if (which == STATS_UNPLUGGED) {
777            dumpLine(pw, 0 /* uid */, category, BATTERY_DATA, getUnpluggedStartLevel(),
778                    getPluggedStartLevel());
779        }
780
781        for (int iu = 0; iu < NU; iu++) {
782            final int uid = uidStats.keyAt(iu);
783            Uid u = uidStats.valueAt(iu);
784            // Dump Network stats per uid, if any
785            long rx = u.getTcpBytesReceived(which);
786            long tx = u.getTcpBytesSent(which);
787            long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
788            long scanWifiLockOnTime = u.getScanWifiLockTime(batteryRealtime, which);
789            long wifiTurnedOnTime = u.getWifiTurnedOnTime(batteryRealtime, which);
790
791            if (rx > 0 || tx > 0) dumpLine(pw, uid, category, NETWORK_DATA, rx, tx);
792
793            if (fullWifiLockOnTime != 0 || scanWifiLockOnTime != 0
794                    || wifiTurnedOnTime != 0) {
795                dumpLine(pw, uid, category, WIFI_LOCK_DATA,
796                        fullWifiLockOnTime, scanWifiLockOnTime, wifiTurnedOnTime);
797            }
798
799            if (u.hasUserActivity()) {
800                args = new Object[Uid.NUM_USER_ACTIVITY_TYPES];
801                boolean hasData = false;
802                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
803                    int val = u.getUserActivityCount(i, which);
804                    args[i] = val;
805                    if (val != 0) hasData = true;
806                }
807                if (hasData) {
808                    dumpLine(pw, 0 /* uid */, category, USER_ACTIVITY_DATA, args);
809                }
810            }
811
812            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
813            if (wakelocks.size() > 0) {
814                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
815                        : wakelocks.entrySet()) {
816                    Uid.Wakelock wl = ent.getValue();
817                    String linePrefix = "";
818                    sb.setLength(0);
819                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_FULL), batteryRealtime,
820                            "full", which, linePrefix);
821                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), batteryRealtime,
822                            "partial", which, linePrefix);
823                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), batteryRealtime,
824                            "window", which, linePrefix);
825
826                    // Only log if we had at lease one wakelock...
827                    if (sb.length() > 0) {
828                       dumpLine(pw, uid, category, WAKELOCK_DATA, ent.getKey(), sb.toString());
829                    }
830                }
831            }
832
833            Map<Integer, ? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
834            if (sensors.size() > 0)  {
835                for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> ent
836                        : sensors.entrySet()) {
837                    Uid.Sensor se = ent.getValue();
838                    int sensorNumber = ent.getKey();
839                    Timer timer = se.getSensorTime();
840                    if (timer != null) {
841                        // Convert from microseconds to milliseconds with rounding
842                        long totalTime = (timer.getTotalTime(batteryRealtime, which) + 500) / 1000;
843                        int count = timer.getCount(which);
844                        if (totalTime != 0) {
845                            dumpLine(pw, uid, category, SENSOR_DATA, sensorNumber, totalTime, count);
846                        }
847                    }
848                }
849            }
850
851            Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
852            if (processStats.size() > 0) {
853                for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
854                        : processStats.entrySet()) {
855                    Uid.Proc ps = ent.getValue();
856
857                    long userTime = ps.getUserTime(which);
858                    long systemTime = ps.getSystemTime(which);
859                    int starts = ps.getStarts(which);
860
861                    if (userTime != 0 || systemTime != 0 || starts != 0) {
862                        dumpLine(pw, uid, category, PROCESS_DATA,
863                                ent.getKey(), // proc
864                                userTime * 10, // cpu time in ms
865                                systemTime * 10, // user time in ms
866                                starts); // process starts
867                    }
868                }
869            }
870
871            Map<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats();
872            if (packageStats.size() > 0) {
873                for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent
874                        : packageStats.entrySet()) {
875
876                    Uid.Pkg ps = ent.getValue();
877                    int wakeups = ps.getWakeups(which);
878                    Map<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
879                    for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent
880                            : serviceStats.entrySet()) {
881                        BatteryStats.Uid.Pkg.Serv ss = sent.getValue();
882                        long startTime = ss.getStartTime(batteryUptime, which);
883                        int starts = ss.getStarts(which);
884                        int launches = ss.getLaunches(which);
885                        if (startTime != 0 || starts != 0 || launches != 0) {
886                            dumpLine(pw, uid, category, APK_DATA,
887                                    wakeups, // wakeup alarms
888                                    ent.getKey(), // Apk
889                                    sent.getKey(), // service
890                                    startTime / 1000, // time spent started, in ms
891                                    starts,
892                                    launches);
893                        }
894                    }
895                }
896            }
897        }
898    }
899
900    @SuppressWarnings("unused")
901    private final void dumpLocked(Printer pw, String prefix, int which) {
902        final long rawUptime = SystemClock.uptimeMillis() * 1000;
903        final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
904        final long batteryUptime = getBatteryUptime(rawUptime);
905        final long batteryRealtime = getBatteryRealtime(rawRealtime);
906
907        final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
908        final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
909        final long totalRealtime = computeRealtime(rawRealtime, which);
910        final long totalUptime = computeUptime(rawUptime, which);
911
912        StringBuilder sb = new StringBuilder(128);
913
914        SparseArray<? extends Uid> uidStats = getUidStats();
915        final int NU = uidStats.size();
916
917        pw.println(prefix
918                + "  Time on battery: "
919                + formatTimeMs(whichBatteryRealtime / 1000) + "("
920                + formatRatioLocked(whichBatteryRealtime, totalRealtime)
921                + ") realtime, "
922                + formatTimeMs(whichBatteryUptime / 1000)
923                + "(" + formatRatioLocked(whichBatteryUptime, totalRealtime)
924                + ") uptime");
925        pw.println(prefix
926                + "  Total run time: "
927                + formatTimeMs(totalRealtime / 1000)
928                + "realtime, "
929                + formatTimeMs(totalUptime / 1000)
930                + "uptime, ");
931
932        final long screenOnTime = getScreenOnTime(batteryRealtime, which);
933        final long phoneOnTime = getPhoneOnTime(batteryRealtime, which);
934        final long wifiRunningTime = getWifiRunningTime(batteryRealtime, which);
935        final long wifiOnTime = getWifiOnTime(batteryRealtime, which);
936        final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which);
937        pw.println(prefix
938                + "  Screen on: " + formatTimeMs(screenOnTime / 1000)
939                + "(" + formatRatioLocked(screenOnTime, whichBatteryRealtime)
940                + "), Input events: " + getInputEventCount(which)
941                + ", Active phone call: " + formatTimeMs(phoneOnTime / 1000)
942                + "(" + formatRatioLocked(phoneOnTime, whichBatteryRealtime) + ")");
943        sb.setLength(0);
944        sb.append("  Screen brightnesses: ");
945        boolean didOne = false;
946        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
947            final long time = getScreenBrightnessTime(i, batteryRealtime, which);
948            if (time == 0) {
949                continue;
950            }
951            if (didOne) sb.append(", ");
952            didOne = true;
953            sb.append(SCREEN_BRIGHTNESS_NAMES[i]);
954            sb.append(" ");
955            sb.append(formatTimeMs(time/1000));
956            sb.append("(");
957            sb.append(formatRatioLocked(time, screenOnTime));
958            sb.append(")");
959        }
960        if (!didOne) sb.append("No activity");
961        pw.println(sb.toString());
962
963        // Calculate total network and wakelock times across all uids.
964        long rxTotal = 0;
965        long txTotal = 0;
966        long fullWakeLockTimeTotalMicros = 0;
967        long partialWakeLockTimeTotalMicros = 0;
968
969        for (int iu = 0; iu < NU; iu++) {
970            Uid u = uidStats.valueAt(iu);
971            rxTotal += u.getTcpBytesReceived(which);
972            txTotal += u.getTcpBytesSent(which);
973
974            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
975            if (wakelocks.size() > 0) {
976                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
977                        : wakelocks.entrySet()) {
978                    Uid.Wakelock wl = ent.getValue();
979
980                    Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
981                    if (fullWakeTimer != null) {
982                        fullWakeLockTimeTotalMicros += fullWakeTimer.getTotalTime(
983                                batteryRealtime, which);
984                    }
985
986                    Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
987                    if (partialWakeTimer != null) {
988                        partialWakeLockTimeTotalMicros += partialWakeTimer.getTotalTime(
989                                batteryRealtime, which);
990                    }
991                }
992            }
993        }
994
995        pw.println(prefix
996                + "  Total received: " + formatBytesLocked(rxTotal)
997                + ", Total sent: " + formatBytesLocked(txTotal));
998        pw.println(prefix
999                + "  Total full wakelock time: " + formatTimeMs(
1000                        (fullWakeLockTimeTotalMicros + 500) / 1000)
1001                + ", Total partial waklock time: " + formatTimeMs(
1002                        (partialWakeLockTimeTotalMicros + 500) / 1000));
1003
1004        sb.setLength(0);
1005        sb.append("  Signal levels: ");
1006        didOne = false;
1007        for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
1008            final long time = getPhoneSignalStrengthTime(i, batteryRealtime, which);
1009            if (time == 0) {
1010                continue;
1011            }
1012            if (didOne) sb.append(", ");
1013            didOne = true;
1014            sb.append(SIGNAL_STRENGTH_NAMES[i]);
1015            sb.append(" ");
1016            sb.append(formatTimeMs(time/1000));
1017            sb.append("(");
1018            sb.append(formatRatioLocked(time, whichBatteryRealtime));
1019            sb.append(") ");
1020            sb.append(getPhoneSignalStrengthCount(i, which));
1021            sb.append("x");
1022        }
1023        if (!didOne) sb.append("No activity");
1024        pw.println(sb.toString());
1025
1026        sb.setLength(0);
1027        sb.append("  Radio types: ");
1028        didOne = false;
1029        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
1030            final long time = getPhoneDataConnectionTime(i, batteryRealtime, which);
1031            if (time == 0) {
1032                continue;
1033            }
1034            if (didOne) sb.append(", ");
1035            didOne = true;
1036            sb.append(DATA_CONNECTION_NAMES[i]);
1037            sb.append(" ");
1038            sb.append(formatTimeMs(time/1000));
1039            sb.append("(");
1040            sb.append(formatRatioLocked(time, whichBatteryRealtime));
1041            sb.append(") ");
1042            sb.append(getPhoneDataConnectionCount(i, which));
1043            sb.append("x");
1044        }
1045        if (!didOne) sb.append("No activity");
1046        pw.println(sb.toString());
1047
1048        pw.println(prefix
1049                + "  Wifi on: " + formatTimeMs(wifiOnTime / 1000)
1050                + "(" + formatRatioLocked(wifiOnTime, whichBatteryRealtime)
1051                + "), Wifi running: " + formatTimeMs(wifiRunningTime / 1000)
1052                + "(" + formatRatioLocked(wifiRunningTime, whichBatteryRealtime)
1053                + "), Bluetooth on: " + formatTimeMs(bluetoothOnTime / 1000)
1054                + "(" + formatRatioLocked(bluetoothOnTime, whichBatteryRealtime)+ ")");
1055
1056        pw.println(" ");
1057
1058        if (which == STATS_UNPLUGGED) {
1059            if (getIsOnBattery()) {
1060                pw.println(prefix + "  Device is currently unplugged");
1061                pw.println(prefix + "    Discharge cycle start level: " +
1062                        getUnpluggedStartLevel());
1063            } else {
1064                pw.println(prefix + "  Device is currently plugged into power");
1065                pw.println(prefix + "    Last discharge cycle start level: " +
1066                        getUnpluggedStartLevel());
1067                pw.println(prefix + "    Last discharge cycle end level: " +
1068                        getPluggedStartLevel());
1069            }
1070            pw.println(" ");
1071        }
1072
1073
1074        for (int iu=0; iu<NU; iu++) {
1075            final int uid = uidStats.keyAt(iu);
1076            Uid u = uidStats.valueAt(iu);
1077            pw.println(prefix + "  #" + uid + ":");
1078            boolean uidActivity = false;
1079
1080            long tcpReceived = u.getTcpBytesReceived(which);
1081            long tcpSent = u.getTcpBytesSent(which);
1082            long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
1083            long scanWifiLockOnTime = u.getScanWifiLockTime(batteryRealtime, which);
1084            long wifiTurnedOnTime = u.getWifiTurnedOnTime(batteryRealtime, which);
1085
1086            if (tcpReceived != 0 || tcpSent != 0) {
1087                pw.println(prefix + "    Network: " + formatBytesLocked(tcpReceived) + " received, "
1088                        + formatBytesLocked(tcpSent) + " sent");
1089            }
1090
1091            if (u.hasUserActivity()) {
1092                boolean hasData = false;
1093                for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
1094                    int val = u.getUserActivityCount(i, which);
1095                    if (val != 0) {
1096                        if (!hasData) {
1097                            sb.setLength(0);
1098                            sb.append("    User activity: ");
1099                            hasData = true;
1100                        } else {
1101                            sb.append(", ");
1102                        }
1103                        sb.append(val);
1104                        sb.append(" ");
1105                        sb.append(Uid.USER_ACTIVITY_TYPES[i]);
1106                    }
1107                }
1108                if (hasData) {
1109                    pw.println(sb.toString());
1110                }
1111            }
1112
1113            if (fullWifiLockOnTime != 0 || scanWifiLockOnTime != 0
1114                    || wifiTurnedOnTime != 0) {
1115                pw.println(prefix + "    Turned Wifi On Time: "
1116                        + formatTimeMs(wifiTurnedOnTime / 1000)
1117                        + "(" + formatRatioLocked(wifiTurnedOnTime,
1118                                whichBatteryRealtime)+ ")");
1119                pw.println(prefix + "    Full Wifi Lock Time: "
1120                        + formatTimeMs(fullWifiLockOnTime / 1000)
1121                        + "(" + formatRatioLocked(fullWifiLockOnTime,
1122                                whichBatteryRealtime)+ ")");
1123                pw.println(prefix + "    Scan Wifi Lock Time: "
1124                        + formatTimeMs(scanWifiLockOnTime / 1000)
1125                        + "(" + formatRatioLocked(scanWifiLockOnTime,
1126                                whichBatteryRealtime)+ ")");
1127            }
1128
1129            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
1130            if (wakelocks.size() > 0) {
1131                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
1132                    : wakelocks.entrySet()) {
1133                    Uid.Wakelock wl = ent.getValue();
1134                    String linePrefix = ": ";
1135                    sb.setLength(0);
1136                    sb.append(prefix);
1137                    sb.append("    Wake lock ");
1138                    sb.append(ent.getKey());
1139                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_FULL), batteryRealtime,
1140                            "full", which, linePrefix);
1141                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), batteryRealtime,
1142                            "partial", which, linePrefix);
1143                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), batteryRealtime,
1144                            "window", which, linePrefix);
1145                    if (!linePrefix.equals(": ")) {
1146                        sb.append(" realtime");
1147                    } else {
1148                        sb.append(": (nothing executed)");
1149                    }
1150                    pw.println(sb.toString());
1151                    uidActivity = true;
1152                }
1153            }
1154
1155            Map<Integer, ? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
1156            if (sensors.size() > 0) {
1157                for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> ent
1158                    : sensors.entrySet()) {
1159                    Uid.Sensor se = ent.getValue();
1160                    int sensorNumber = ent.getKey();
1161                    sb.setLength(0);
1162                    sb.append(prefix);
1163                    sb.append("    Sensor ");
1164                    int handle = se.getHandle();
1165                    if (handle == Uid.Sensor.GPS) {
1166                        sb.append("GPS");
1167                    } else {
1168                        sb.append(handle);
1169                    }
1170                    sb.append(": ");
1171
1172                    Timer timer = se.getSensorTime();
1173                    if (timer != null) {
1174                        // Convert from microseconds to milliseconds with rounding
1175                        long totalTime = (timer.getTotalTime(batteryRealtime, which) + 500) / 1000;
1176                        int count = timer.getCount(which);
1177                        //timer.logState();
1178                        if (totalTime != 0) {
1179                            sb.append(formatTimeMs(totalTime));
1180                            sb.append("realtime (");
1181                            sb.append(count);
1182                            sb.append(" times)");
1183                        } else {
1184                            sb.append("(not used)");
1185                        }
1186                    } else {
1187                        sb.append("(not used)");
1188                    }
1189
1190                    pw.println(sb.toString());
1191                    uidActivity = true;
1192                }
1193            }
1194
1195            Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
1196            if (processStats.size() > 0) {
1197                for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
1198                    : processStats.entrySet()) {
1199                    Uid.Proc ps = ent.getValue();
1200                    long userTime;
1201                    long systemTime;
1202                    int starts;
1203
1204                    userTime = ps.getUserTime(which);
1205                    systemTime = ps.getSystemTime(which);
1206                    starts = ps.getStarts(which);
1207
1208                    if (userTime != 0 || systemTime != 0 || starts != 0) {
1209                        pw.println(prefix + "    Proc " + ent.getKey() + ":");
1210                        pw.println(prefix + "      CPU: " + formatTime(userTime) + "user + "
1211                                + formatTime(systemTime) + "kernel");
1212                        pw.println(prefix + "      " + starts + " process starts");
1213                        uidActivity = true;
1214                    }
1215                }
1216            }
1217
1218            Map<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats();
1219            if (packageStats.size() > 0) {
1220                for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent
1221                    : packageStats.entrySet()) {
1222                    pw.println(prefix + "    Apk " + ent.getKey() + ":");
1223                    boolean apkActivity = false;
1224                    Uid.Pkg ps = ent.getValue();
1225                    int wakeups = ps.getWakeups(which);
1226                    if (wakeups != 0) {
1227                        pw.println(prefix + "      " + wakeups + " wakeup alarms");
1228                        apkActivity = true;
1229                    }
1230                    Map<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
1231                    if (serviceStats.size() > 0) {
1232                        for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent
1233                                : serviceStats.entrySet()) {
1234                            BatteryStats.Uid.Pkg.Serv ss = sent.getValue();
1235                            long startTime = ss.getStartTime(batteryUptime, which);
1236                            int starts = ss.getStarts(which);
1237                            int launches = ss.getLaunches(which);
1238                            if (startTime != 0 || starts != 0 || launches != 0) {
1239                                pw.println(prefix + "      Service " + sent.getKey() + ":");
1240                                pw.println(prefix + "        Created for: "
1241                                        + formatTimeMs(startTime / 1000)
1242                                        + " uptime");
1243                                pw.println(prefix + "        Starts: " + starts
1244                                        + ", launches: " + launches);
1245                                apkActivity = true;
1246                            }
1247                        }
1248                    }
1249                    if (!apkActivity) {
1250                        pw.println(prefix + "      (nothing executed)");
1251                    }
1252                    uidActivity = true;
1253                }
1254            }
1255            if (!uidActivity) {
1256                pw.println(prefix + "    (nothing executed)");
1257            }
1258        }
1259    }
1260
1261    /**
1262     * Dumps a human-readable summary of the battery statistics to the given PrintWriter.
1263     *
1264     * @param pw a Printer to receive the dump output.
1265     */
1266    @SuppressWarnings("unused")
1267    public void dumpLocked(Printer pw) {
1268        pw.println("Total Statistics (Current and Historic):");
1269        pw.println("  System starts: " + getStartCount()
1270                + ", currently on battery: " + getIsOnBattery());
1271        dumpLocked(pw, "", STATS_TOTAL);
1272        pw.println("");
1273        pw.println("Last Run Statistics (Previous run of system):");
1274        dumpLocked(pw, "", STATS_LAST);
1275        pw.println("");
1276        pw.println("Current Battery Statistics (Currently running system):");
1277        dumpLocked(pw, "", STATS_CURRENT);
1278        pw.println("");
1279        pw.println("Unplugged Statistics (Since last unplugged from power):");
1280        dumpLocked(pw, "", STATS_UNPLUGGED);
1281    }
1282
1283    @SuppressWarnings("unused")
1284    public void dumpCheckinLocked(PrintWriter pw, String[] args) {
1285        boolean isUnpluggedOnly = false;
1286
1287        for (String arg : args) {
1288            if ("-u".equals(arg)) {
1289                if (LOCAL_LOGV) Log.v("BatteryStats", "Dumping unplugged data");
1290                isUnpluggedOnly = true;
1291            }
1292        }
1293
1294        if (isUnpluggedOnly) {
1295            dumpCheckinLocked(pw, STATS_UNPLUGGED);
1296        }
1297        else {
1298            dumpCheckinLocked(pw, STATS_TOTAL);
1299            dumpCheckinLocked(pw, STATS_LAST);
1300            dumpCheckinLocked(pw, STATS_UNPLUGGED);
1301            dumpCheckinLocked(pw, STATS_CURRENT);
1302        }
1303    }
1304
1305}
1306