BatteryStats.java revision 105925376f8d0f6b318c9938c7b83ef7fef094da
1package android.os;
2
3import java.io.PrintWriter;
4import java.util.Formatter;
5import java.util.Map;
6
7import com.android.internal.os.BatteryStatsImpl.Timer;
8
9import android.util.Log;
10import android.util.Printer;
11import android.util.SparseArray;
12
13/**
14 * A class providing access to battery usage statistics, including information on
15 * wakelocks, processes, packages, and services.  All times are represented in microseconds
16 * except where indicated otherwise.
17 * @hide
18 */
19public abstract class BatteryStats implements Parcelable {
20
21    private static final boolean LOCAL_LOGV = false;
22
23    /**
24     * A constant indicating a partial wake lock timer.
25     */
26    public static final int WAKE_TYPE_PARTIAL = 0;
27
28    /**
29     * A constant indicating a full wake lock timer.
30     */
31    public static final int WAKE_TYPE_FULL = 1;
32
33    /**
34     * A constant indicating a window wake lock timer.
35     */
36    public static final int WAKE_TYPE_WINDOW = 2;
37
38    /**
39     * A constant indicating a sensor timer.
40     *
41     * {@hide}
42     */
43    public static final int SENSOR = 3;
44
45    /**
46     * A constant indicating a full wifi lock timer
47     *
48     * {@hide}
49     */
50    public static final int FULL_WIFI_LOCK = 4;
51
52    /**
53     * A constant indicating a scan wifi lock timer
54     *
55     * {@hide}
56     */
57    public static final int SCAN_WIFI_LOCK = 5;
58
59    /**
60     * Include all of the data in the stats, including previously saved data.
61     */
62    public static final int STATS_TOTAL = 0;
63
64    /**
65     * Include only the last run in the stats.
66     */
67    public static final int STATS_LAST = 1;
68
69    /**
70     * Include only the current run in the stats.
71     */
72    public static final int STATS_CURRENT = 2;
73
74    /**
75     * Include only the run since the last time the device was unplugged in the stats.
76     */
77    public static final int STATS_UNPLUGGED = 3;
78
79    /**
80     * Bump the version on this if the checkin format changes.
81     */
82    private static final int BATTERY_STATS_CHECKIN_VERSION = 1;
83
84    // TODO: Update this list if you add/change any stats above.
85    private static final String[] STAT_NAMES = { "total", "last", "current", "unplugged" };
86
87    private static final String APK_DATA = "apk";
88    private static final String PROCESS_DATA = "process";
89    private static final String SENSOR_DATA = "sensor";
90    private static final String WAKELOCK_DATA = "wakelock";
91    private static final String NETWORK_DATA = "network";
92    private static final String BATTERY_DATA = "battery";
93    private static final String WIFI_LOCK_DATA = "wifilock";
94    private static final String MISC_DATA = "misc";
95
96    private final StringBuilder mFormatBuilder = new StringBuilder(8);
97    private final Formatter mFormatter = new Formatter(mFormatBuilder);
98
99    /**
100     * State for keeping track of timing information.
101     */
102    public static abstract class Timer {
103
104        /**
105         * Returns the count associated with this Timer for the
106         * selected type of statistics.
107         *
108         * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT
109         */
110        public abstract int getCount(int which);
111
112        /**
113         * Returns the total time in microseconds associated with this Timer for the
114         * selected type of statistics.
115         *
116         * @param batteryRealtime system realtime on  battery in microseconds
117         * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT
118         * @return a time in microseconds
119         */
120        public abstract long getTotalTime(long batteryRealtime, int which);
121
122        /**
123         * Temporary for debugging.
124         */
125        public abstract void logState();
126    }
127
128    /**
129     * The statistics associated with a particular uid.
130     */
131    public static abstract class Uid {
132
133        /**
134         * Returns a mapping containing wakelock statistics.
135         *
136         * @return a Map from Strings to Uid.Wakelock objects.
137         */
138        public abstract Map<String, ? extends Wakelock> getWakelockStats();
139
140        /**
141         * The statistics associated with a particular wake lock.
142         */
143        public static abstract class Wakelock {
144            public abstract Timer getWakeTime(int type);
145        }
146
147        /**
148         * Returns a mapping containing sensor statistics.
149         *
150         * @return a Map from Integer sensor ids to Uid.Sensor objects.
151         */
152        public abstract Map<Integer, ? extends Sensor> getSensorStats();
153
154        /**
155         * Returns a mapping containing process statistics.
156         *
157         * @return a Map from Strings to Uid.Proc objects.
158         */
159        public abstract Map<String, ? extends Proc> getProcessStats();
160
161        /**
162         * Returns a mapping containing package statistics.
163         *
164         * @return a Map from Strings to Uid.Pkg objects.
165         */
166        public abstract Map<String, ? extends Pkg> getPackageStats();
167
168        /**
169         * {@hide}
170         */
171        public abstract int getUid();
172
173        /**
174         * {@hide}
175         */
176        public abstract long getTcpBytesReceived(int which);
177
178        /**
179         * {@hide}
180         */
181        public abstract long getTcpBytesSent(int which);
182
183        public abstract void noteFullWifiLockAcquiredLocked();
184        public abstract void noteFullWifiLockReleasedLocked();
185        public abstract void noteScanWifiLockAcquiredLocked();
186        public abstract void noteScanWifiLockReleasedLocked();
187        public abstract long getFullWifiLockTime(long batteryRealtime, int which);
188        public abstract long getScanWifiLockTime(long batteryRealtime, int which);
189
190        public static abstract class Sensor {
191            // Magic sensor number for the GPS.
192            public static final int GPS = -10000;
193
194            public abstract int getHandle();
195
196            public abstract Timer getSensorTime();
197        }
198
199        /**
200         * The statistics associated with a particular process.
201         */
202        public static abstract class Proc {
203
204            /**
205             * Returns the total time (in 1/100 sec) spent executing in user code.
206             *
207             * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
208             */
209            public abstract long getUserTime(int which);
210
211            /**
212             * Returns the total time (in 1/100 sec) spent executing in system code.
213             *
214             * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
215             */
216            public abstract long getSystemTime(int which);
217
218            /**
219             * Returns the number of times the process has been started.
220             *
221             * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
222             */
223            public abstract int getStarts(int which);
224        }
225
226        /**
227         * The statistics associated with a particular package.
228         */
229        public static abstract class Pkg {
230
231            /**
232             * Returns the number of times this package has done something that could wake up the
233             * device from sleep.
234             *
235             * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
236             */
237            public abstract int getWakeups(int which);
238
239            /**
240             * Returns a mapping containing service statistics.
241             */
242            public abstract Map<String, ? extends Serv> getServiceStats();
243
244            /**
245             * The statistics associated with a particular service.
246             */
247            public abstract class Serv {
248
249                /**
250                 * Returns the amount of time spent started.
251                 *
252                 * @param batteryUptime elapsed uptime on battery in microseconds.
253                 * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
254                 * @return
255                 */
256                public abstract long getStartTime(long batteryUptime, int which);
257
258                /**
259                 * Returns the total number of times startService() has been called.
260                 *
261                 * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
262                 */
263                public abstract int getStarts(int which);
264
265                /**
266                 * Returns the total number times the service has been launched.
267                 *
268                 * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
269                 */
270                public abstract int getLaunches(int which);
271            }
272        }
273    }
274
275    /**
276     * Returns the number of times the device has been started.
277     */
278    public abstract int getStartCount();
279
280    /**
281     * Returns the time in milliseconds that the screen has been on while the device was
282     * running on battery.
283     *
284     * {@hide}
285     */
286    public abstract long getScreenOnTime(long batteryRealtime, int which);
287
288    /**
289     * Returns the time in milliseconds that the phone has been on while the device was
290     * running on battery.
291     *
292     * {@hide}
293     */
294    public abstract long getPhoneOnTime(long batteryRealtime, int which);
295
296    /**
297     * Returns the time in milliseconds that wifi has been on while the device was
298     * running on battery.
299     *
300     * {@hide}
301     */
302    public abstract long getWifiOnTime(long batteryRealtime, int which);
303
304    /**
305     * Returns the time in milliseconds that bluetooth has been on while the device was
306     * running on battery.
307     *
308     * {@hide}
309     */
310    public abstract long getBluetoothOnTime(long batteryRealtime, int which);
311
312    /**
313     * Return whether we are currently running on battery.
314     */
315    public abstract boolean getIsOnBattery();
316
317    /**
318     * Returns a SparseArray containing the statistics for each uid.
319     */
320    public abstract SparseArray<? extends Uid> getUidStats();
321
322    /**
323     * Returns the current battery uptime in microseconds.
324     *
325     * @param curTime the amount of elapsed realtime in microseconds.
326     */
327    public abstract long getBatteryUptime(long curTime);
328
329    /**
330     * Returns the current battery realtime in microseconds.
331     *
332     * @param curTime the amount of elapsed realtime in microseconds.
333     */
334    public abstract long getBatteryRealtime(long curTime);
335
336    /**
337     * Returns the battery percentage level at the last time the device was unplugged from power,
338     * or the last time it was booted while unplugged.
339     */
340    public abstract int getUnpluggedStartLevel();
341
342    /**
343     * Returns the battery percentage level at the last time the device was plugged into power.
344     */
345    public abstract int getPluggedStartLevel();
346
347    /**
348     * Returns the total, last, or current battery uptime in microseconds.
349     *
350     * @param curTime the elapsed realtime in microseconds.
351     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
352     */
353    public abstract long computeBatteryUptime(long curTime, int which);
354
355    /**
356     * Returns the total, last, or current battery realtime in microseconds.
357     *
358     * @param curTime the current elapsed realtime in microseconds.
359     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
360     */
361    public abstract long computeBatteryRealtime(long curTime, int which);
362
363    /**
364     * Returns the total, last, or current uptime in microseconds.
365     *
366     * @param curTime the current elapsed realtime in microseconds.
367     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
368     */
369    public abstract long computeUptime(long curTime, int which);
370
371    /**
372     * Returns the total, last, or current realtime in microseconds.
373     * *
374     * @param curTime the current elapsed realtime in microseconds.
375     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
376     */
377    public abstract long computeRealtime(long curTime, int which);
378
379    private final static void formatTime(StringBuilder out, long seconds) {
380        long days = seconds / (60 * 60 * 24);
381        if (days != 0) {
382            out.append(days);
383            out.append("d ");
384        }
385        long used = days * 60 * 60 * 24;
386
387        long hours = (seconds - used) / (60 * 60);
388        if (hours != 0 || used != 0) {
389            out.append(hours);
390            out.append("h ");
391        }
392        used += hours * 60 * 60;
393
394        long mins = (seconds-used) / 60;
395        if (mins != 0 || used != 0) {
396            out.append(mins);
397            out.append("m ");
398        }
399        used += mins * 60;
400
401        if (seconds != 0 || used != 0) {
402            out.append(seconds-used);
403            out.append("s ");
404        }
405    }
406
407    private final static String formatTime(long time) {
408        long sec = time / 100;
409        StringBuilder sb = new StringBuilder();
410        formatTime(sb, sec);
411        sb.append((time - (sec * 100)) * 10);
412        sb.append("ms ");
413        return sb.toString();
414    }
415
416    private final static String formatTimeMs(long time) {
417        long sec = time / 1000;
418        StringBuilder sb = new StringBuilder();
419        formatTime(sb, sec);
420        sb.append(time - (sec * 1000));
421        sb.append("ms ");
422        return sb.toString();
423    }
424
425    private final String formatRatioLocked(long num, long den) {
426        if (den == 0L) {
427            return "---%";
428        }
429        float perc = ((float)num) / ((float)den) * 100;
430        mFormatBuilder.setLength(0);
431        mFormatter.format("%.1f%%", perc);
432        return mFormatBuilder.toString();
433    }
434
435    /**
436     *
437     * @param sb a StringBuilder object.
438     * @param timer a Timer object contining the wakelock times.
439     * @param batteryRealtime the current on-battery time in microseconds.
440     * @param name the name of the wakelock.
441     * @param which which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
442     * @param linePrefix a String to be prepended to each line of output.
443     * @return the line prefix
444     */
445    private static final String printWakeLock(StringBuilder sb, Timer timer,
446            long batteryRealtime, String name, int which, String linePrefix) {
447
448        if (timer != null) {
449            // Convert from microseconds to milliseconds with rounding
450            long totalTimeMicros = timer.getTotalTime(batteryRealtime, which);
451            long totalTimeMillis = (totalTimeMicros + 500) / 1000;
452
453            int count = timer.getCount(which);
454            if (totalTimeMillis != 0) {
455                sb.append(linePrefix);
456                sb.append(formatTimeMs(totalTimeMillis));
457                sb.append(name);
458                sb.append(' ');
459                sb.append('(');
460                sb.append(count);
461                sb.append(" times)");
462                return ", ";
463            }
464        }
465        return linePrefix;
466    }
467
468    /**
469     * Checkin version of wakelock printer. Prints simple comma-separated list.
470     *
471     * @param sb a StringBuilder object.
472     * @param timer a Timer object contining the wakelock times.
473     * @param now the current time in microseconds.
474     * @param name the name of the wakelock.
475     * @param which which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
476     * @param linePrefix a String to be prepended to each line of output.
477     * @return the line prefix
478     */
479    private static final String printWakeLockCheckin(StringBuilder sb, Timer timer, long now,
480        String name, int which, String linePrefix) {
481        long totalTimeMicros = 0;
482        int count = 0;
483        if (timer != null) {
484            totalTimeMicros = timer.getTotalTime(now, which);
485            count = timer.getCount(which);
486        }
487        sb.append(linePrefix);
488        sb.append((totalTimeMicros + 500) / 1000); // microseconds to milliseconds with rounding
489        sb.append(',');
490        sb.append(name);
491        sb.append(',');
492        sb.append(count);
493        return ",";
494    }
495
496    /**
497     * Dump a comma-separated line of values for terse checkin mode.
498     *
499     * @param pw the PageWriter to dump log to
500     * @param category category of data (e.g. "total", "last", "unplugged", "current" )
501     * @param type type of data (e.g. "wakelock", "sensor", "process", "apk" ,  "process", "network")
502     * @param args type-dependent data arguments
503     */
504    private static final void dumpLine(PrintWriter pw, int uid, String category, String type,
505           Object... args ) {
506        pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
507        pw.print(uid); pw.print(',');
508        pw.print(category); pw.print(',');
509        pw.print(type);
510
511        for (Object arg : args) {
512            pw.print(',');
513            pw.print(arg);
514        }
515        pw.print('\n');
516    }
517
518    /**
519     * Checkin server version of dump to produce more compact, computer-readable log.
520     *
521     * NOTE: all times are expressed in 'ms'.
522     * @param fd
523     * @param pw
524     * @param which
525     */
526    private final void dumpCheckinLocked(PrintWriter pw, int which) {
527        final long rawUptime = SystemClock.uptimeMillis() * 1000;
528        final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
529        final long batteryUptime = getBatteryUptime(rawUptime);
530        final long batteryRealtime = getBatteryRealtime(rawRealtime);
531        final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
532        final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
533        final long totalRealtime = computeRealtime(rawRealtime, which);
534        final long totalUptime = computeUptime(rawUptime, which);
535        final long screenOnTime = getScreenOnTime(batteryRealtime, which);
536        final long phoneOnTime = getPhoneOnTime(batteryRealtime, which);
537        final long wifiOnTime = getWifiOnTime(batteryRealtime, which);
538        final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which);
539
540        StringBuilder sb = new StringBuilder(128);
541
542        String category = STAT_NAMES[which];
543
544        // Dump "battery" stat
545        dumpLine(pw, 0 /* uid */, category, BATTERY_DATA,
546                which == STATS_TOTAL ? getStartCount() : "N/A",
547                whichBatteryUptime / 1000, whichBatteryRealtime / 1000,
548                totalUptime / 1000, totalRealtime / 1000);
549
550        // Dump misc stats
551        dumpLine(pw, 0 /* uid */, category, MISC_DATA,
552                screenOnTime / 1000, phoneOnTime / 1000, wifiOnTime / 1000, bluetoothOnTime / 1000);
553
554        if (which == STATS_UNPLUGGED) {
555            dumpLine(pw, 0 /* uid */, category, BATTERY_DATA, getUnpluggedStartLevel(),
556                    getPluggedStartLevel());
557        }
558
559        SparseArray<? extends Uid> uidStats = getUidStats();
560        final int NU = uidStats.size();
561        for (int iu = 0; iu < NU; iu++) {
562            final int uid = uidStats.keyAt(iu);
563            Uid u = uidStats.valueAt(iu);
564            // Dump Network stats per uid, if any
565            long rx = u.getTcpBytesReceived(which);
566            long tx = u.getTcpBytesSent(which);
567            long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
568            long scanWifiLockOnTime = u.getScanWifiLockTime(batteryRealtime, which);
569
570            if (rx > 0 || tx > 0) dumpLine(pw, uid, category, NETWORK_DATA, rx, tx);
571
572            if (fullWifiLockOnTime != 0 || scanWifiLockOnTime != 0) {
573                dumpLine(pw, uid, category, WIFI_LOCK_DATA,
574                        fullWifiLockOnTime, scanWifiLockOnTime);
575            }
576
577            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
578            if (wakelocks.size() > 0) {
579                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
580                        : wakelocks.entrySet()) {
581                    Uid.Wakelock wl = ent.getValue();
582                    String linePrefix = "";
583                    sb.setLength(0);
584                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_FULL), batteryRealtime,
585                            "full", which, linePrefix);
586                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), batteryRealtime,
587                            "partial", which, linePrefix);
588                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), batteryRealtime,
589                            "window", which, linePrefix);
590
591                    // Only log if we had at lease one wakelock...
592                    if (sb.length() > 0) {
593                       dumpLine(pw, uid, category, WAKELOCK_DATA, ent.getKey(), sb.toString());
594                    }
595                }
596            }
597
598            Map<Integer, ? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
599            if (sensors.size() > 0)  {
600                for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> ent
601                        : sensors.entrySet()) {
602                    Uid.Sensor se = ent.getValue();
603                    int sensorNumber = ent.getKey();
604                    Timer timer = se.getSensorTime();
605                    if (timer != null) {
606                        // Convert from microseconds to milliseconds with rounding
607                        long totalTime = (timer.getTotalTime(batteryRealtime, which) + 500) / 1000;
608                        int count = timer.getCount(which);
609                        if (totalTime != 0) {
610                            dumpLine(pw, uid, category, SENSOR_DATA, sensorNumber, totalTime, count);
611                        }
612                    }
613                }
614            }
615
616            Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
617            if (processStats.size() > 0) {
618                for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
619                        : processStats.entrySet()) {
620                    Uid.Proc ps = ent.getValue();
621
622                    long userTime = ps.getUserTime(which);
623                    long systemTime = ps.getSystemTime(which);
624                    int starts = ps.getStarts(which);
625
626                    if (userTime != 0 || systemTime != 0 || starts != 0) {
627                        dumpLine(pw, uid, category, PROCESS_DATA,
628                                ent.getKey(), // proc
629                                userTime * 10, // cpu time in ms
630                                systemTime * 10, // user time in ms
631                                starts); // process starts
632                    }
633                }
634            }
635
636            Map<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats();
637            if (packageStats.size() > 0) {
638                for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent
639                        : packageStats.entrySet()) {
640
641                    Uid.Pkg ps = ent.getValue();
642                    int wakeups = ps.getWakeups(which);
643                    Map<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
644                    for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent
645                            : serviceStats.entrySet()) {
646                        BatteryStats.Uid.Pkg.Serv ss = sent.getValue();
647                        long startTime = ss.getStartTime(batteryUptime, which);
648                        int starts = ss.getStarts(which);
649                        int launches = ss.getLaunches(which);
650                        if (startTime != 0 || starts != 0 || launches != 0) {
651                            dumpLine(pw, uid, category, APK_DATA,
652                                    wakeups, // wakeup alarms
653                                    ent.getKey(), // Apk
654                                    sent.getKey(), // service
655                                    startTime / 1000, // time spent started, in ms
656                                    starts,
657                                    launches);
658                        }
659                    }
660                }
661            }
662        }
663    }
664
665    @SuppressWarnings("unused")
666    private final void dumpLocked(Printer pw, String prefix, int which) {
667        final long rawUptime = SystemClock.uptimeMillis() * 1000;
668        final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
669        final long batteryUptime = getBatteryUptime(rawUptime);
670        final long batteryRealtime = getBatteryUptime(rawRealtime);
671
672        final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
673        final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
674        final long totalRealtime = computeRealtime(rawRealtime, which);
675        final long totalUptime = computeUptime(rawUptime, which);
676
677        StringBuilder sb = new StringBuilder(128);
678
679        pw.println(prefix
680                + "  Time on battery: " + formatTimeMs(whichBatteryUptime / 1000)
681                + "(" + formatRatioLocked(whichBatteryUptime, totalRealtime)
682                + ") uptime, "
683                + formatTimeMs(whichBatteryRealtime / 1000) + "("
684                + formatRatioLocked(whichBatteryRealtime, totalRealtime)
685                + ") realtime");
686        pw.println(prefix
687                + "  Total: "
688                + formatTimeMs(totalUptime / 1000)
689                + "uptime, "
690                + formatTimeMs(totalRealtime / 1000)
691                + "realtime");
692
693        final long screenOnTime = getScreenOnTime(batteryRealtime, which);
694        final long phoneOnTime = getPhoneOnTime(batteryRealtime, which);
695        final long wifiOnTime = getWifiOnTime(batteryRealtime, which);
696        final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which);
697        pw.println(prefix
698                + "  Time with screen on: " + formatTimeMs(screenOnTime / 1000)
699                + "(" + formatRatioLocked(screenOnTime, whichBatteryRealtime)
700                + "), time with phone on: " + formatTimeMs(phoneOnTime / 1000)
701                + "(" + formatRatioLocked(phoneOnTime, whichBatteryRealtime)
702                + "), time with wifi on: " + formatTimeMs(wifiOnTime / 1000)
703                + "(" + formatRatioLocked(wifiOnTime, whichBatteryRealtime)
704                + "), time with bluetooth on: " + formatTimeMs(bluetoothOnTime / 1000)
705                + "(" + formatRatioLocked(bluetoothOnTime, whichBatteryRealtime)+ ")");
706
707        pw.println(" ");
708
709        if (which == STATS_UNPLUGGED) {
710            if (getIsOnBattery()) {
711                pw.println(prefix + "  Device is currently unplugged");
712                pw.println(prefix + "    Discharge cycle start level: " +
713                        getUnpluggedStartLevel());
714            } else {
715                pw.println(prefix + "  Device is currently plugged into power");
716                pw.println(prefix + "    Last discharge cycle start level: " +
717                        getUnpluggedStartLevel());
718                pw.println(prefix + "    Last discharge cycle end level: " +
719                        getPluggedStartLevel());
720            }
721        }
722
723        pw.println(" ");
724
725        SparseArray<? extends Uid> uidStats = getUidStats();
726        final int NU = uidStats.size();
727        for (int iu=0; iu<NU; iu++) {
728            final int uid = uidStats.keyAt(iu);
729            Uid u = uidStats.valueAt(iu);
730            pw.println(prefix + "  #" + uid + ":");
731            boolean uidActivity = false;
732
733            long tcpReceived = u.getTcpBytesReceived(which);
734            long tcpSent = u.getTcpBytesSent(which);
735            long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
736            long scanWifiLockOnTime = u.getScanWifiLockTime(batteryRealtime, which);
737
738            if (tcpReceived != 0 || tcpSent != 0) {
739                pw.println(prefix + "    Network: " + tcpReceived + " bytes received, "
740                        + tcpSent + " bytes sent");
741            }
742            if (fullWifiLockOnTime != 0 || scanWifiLockOnTime != 0) {
743                pw.println(prefix + "    Full Wifi Lock Time: "
744                        + formatTime(fullWifiLockOnTime / 1000)
745                        + "(" + formatRatioLocked(fullWifiLockOnTime,
746                                whichBatteryRealtime)+ ")");
747                pw.println(prefix + "    Scan Wifi Lock Time: "
748                        + formatTime(scanWifiLockOnTime / 1000)
749                        + "(" + formatRatioLocked(scanWifiLockOnTime,
750                                whichBatteryRealtime)+ ")");
751            }
752
753            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
754            if (wakelocks.size() > 0) {
755                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
756                    : wakelocks.entrySet()) {
757                    Uid.Wakelock wl = ent.getValue();
758                    String linePrefix = ": ";
759                    sb.setLength(0);
760                    sb.append(prefix);
761                    sb.append("    Wake lock ");
762                    sb.append(ent.getKey());
763                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_FULL), batteryRealtime,
764                            "full", which, linePrefix);
765                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), batteryRealtime,
766                            "partial", which, linePrefix);
767                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), batteryRealtime,
768                            "window", which, linePrefix);
769                    if (!linePrefix.equals(": ")) {
770                        sb.append(" realtime");
771                    } else {
772                        sb.append(": (nothing executed)");
773                    }
774                    pw.println(sb.toString());
775                    uidActivity = true;
776                }
777            }
778
779            Map<Integer, ? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
780            if (sensors.size() > 0) {
781                for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> ent
782                    : sensors.entrySet()) {
783                    Uid.Sensor se = ent.getValue();
784                    int sensorNumber = ent.getKey();
785                    sb.setLength(0);
786                    sb.append(prefix);
787                    sb.append("    Sensor ");
788                    int handle = se.getHandle();
789                    if (handle == Uid.Sensor.GPS) {
790                        sb.append("GPS");
791                    } else {
792                        sb.append(handle);
793                    }
794                    sb.append(": ");
795
796                    Timer timer = se.getSensorTime();
797                    if (timer != null) {
798                        // Convert from microseconds to milliseconds with rounding
799                        long totalTime = (timer.getTotalTime(batteryRealtime, which) + 500) / 1000;
800                        int count = timer.getCount(which);
801                        //timer.logState();
802                        if (totalTime != 0) {
803                            sb.append(formatTimeMs(totalTime));
804                            sb.append("realtime (");
805                            sb.append(count);
806                            sb.append(" times)");
807                        } else {
808                            sb.append("(not used)");
809                        }
810                    } else {
811                        sb.append("(not used)");
812                    }
813
814                    pw.println(sb.toString());
815                    uidActivity = true;
816                }
817            }
818
819            Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
820            if (processStats.size() > 0) {
821                for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
822                    : processStats.entrySet()) {
823                    Uid.Proc ps = ent.getValue();
824                    long userTime;
825                    long systemTime;
826                    int starts;
827
828                    userTime = ps.getUserTime(which);
829                    systemTime = ps.getSystemTime(which);
830                    starts = ps.getStarts(which);
831
832                    if (userTime != 0 || systemTime != 0 || starts != 0) {
833                        pw.println(prefix + "    Proc " + ent.getKey() + ":");
834                        pw.println(prefix + "      CPU: " + formatTime(userTime) + "user + "
835                                + formatTime(systemTime) + "kernel");
836                        pw.println(prefix + "      " + starts + " process starts");
837                        uidActivity = true;
838                    }
839                }
840            }
841
842            Map<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats();
843            if (packageStats.size() > 0) {
844                for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent
845                    : packageStats.entrySet()) {
846                    pw.println(prefix + "    Apk " + ent.getKey() + ":");
847                    boolean apkActivity = false;
848                    Uid.Pkg ps = ent.getValue();
849                    int wakeups = ps.getWakeups(which);
850                    if (wakeups != 0) {
851                        pw.println(prefix + "      " + wakeups + " wakeup alarms");
852                        apkActivity = true;
853                    }
854                    Map<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
855                    if (serviceStats.size() > 0) {
856                        for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent
857                                : serviceStats.entrySet()) {
858                            BatteryStats.Uid.Pkg.Serv ss = sent.getValue();
859                            long startTime = ss.getStartTime(batteryUptime, which);
860                            int starts = ss.getStarts(which);
861                            int launches = ss.getLaunches(which);
862                            if (startTime != 0 || starts != 0 || launches != 0) {
863                                pw.println(prefix + "      Service " + sent.getKey() + ":");
864                                pw.println(prefix + "        Created for: "
865                                        + formatTimeMs(startTime / 1000)
866                                        + " uptime");
867                                pw.println(prefix + "        Starts: " + starts
868                                        + ", launches: " + launches);
869                                apkActivity = true;
870                            }
871                        }
872                    }
873                    if (!apkActivity) {
874                        pw.println(prefix + "      (nothing executed)");
875                    }
876                    uidActivity = true;
877                }
878            }
879            if (!uidActivity) {
880                pw.println(prefix + "    (nothing executed)");
881            }
882        }
883    }
884
885    /**
886     * Dumps a human-readable summary of the battery statistics to the given PrintWriter.
887     *
888     * @param pw a Printer to receive the dump output.
889     */
890    @SuppressWarnings("unused")
891    public void dumpLocked(Printer pw) {
892        pw.println("Total Statistics (Current and Historic):");
893        pw.println("  System starts: " + getStartCount()
894                + ", currently on battery: " + getIsOnBattery());
895        dumpLocked(pw, "", STATS_TOTAL);
896        pw.println("");
897        pw.println("Last Run Statistics (Previous run of system):");
898        dumpLocked(pw, "", STATS_LAST);
899        pw.println("");
900        pw.println("Current Battery Statistics (Currently running system):");
901        dumpLocked(pw, "", STATS_CURRENT);
902        pw.println("");
903        pw.println("Unplugged Statistics (Since last unplugged from power):");
904        dumpLocked(pw, "", STATS_UNPLUGGED);
905    }
906
907    @SuppressWarnings("unused")
908    public void dumpCheckinLocked(PrintWriter pw, String[] args) {
909        boolean isUnpluggedOnly = false;
910
911        for (String arg : args) {
912            if ("-u".equals(arg)) {
913                if (LOCAL_LOGV) Log.v("BatteryStats", "Dumping unplugged data");
914                isUnpluggedOnly = true;
915            }
916        }
917
918        if (isUnpluggedOnly) {
919            dumpCheckinLocked(pw, STATS_UNPLUGGED);
920        }
921        else {
922            dumpCheckinLocked(pw, STATS_TOTAL);
923            dumpCheckinLocked(pw, STATS_LAST);
924            dumpCheckinLocked(pw, STATS_UNPLUGGED);
925            dumpCheckinLocked(pw, STATS_CURRENT);
926        }
927    }
928
929}
930