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