BatteryStats.java revision d4c5f8919b0522bcaab41a5863c313fec52d3a79
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 wifi has been on and the driver has
306     * been in the running state while the device was running on battery.
307     *
308     * {@hide}
309     */
310    public abstract long getWifiRunningTime(long batteryRealtime, int which);
311
312    /**
313     * Returns the time in milliseconds that bluetooth has been on while the device was
314     * running on battery.
315     *
316     * {@hide}
317     */
318    public abstract long getBluetoothOnTime(long batteryRealtime, int which);
319
320    /**
321     * Return whether we are currently running on battery.
322     */
323    public abstract boolean getIsOnBattery();
324
325    /**
326     * Returns a SparseArray containing the statistics for each uid.
327     */
328    public abstract SparseArray<? extends Uid> getUidStats();
329
330    /**
331     * Returns the current battery uptime in microseconds.
332     *
333     * @param curTime the amount of elapsed realtime in microseconds.
334     */
335    public abstract long getBatteryUptime(long curTime);
336
337    /**
338     * Returns the current battery realtime in microseconds.
339     *
340     * @param curTime the amount of elapsed realtime in microseconds.
341     */
342    public abstract long getBatteryRealtime(long curTime);
343
344    /**
345     * Returns the battery percentage level at the last time the device was unplugged from power,
346     * or the last time it was booted while unplugged.
347     */
348    public abstract int getUnpluggedStartLevel();
349
350    /**
351     * Returns the battery percentage level at the last time the device was plugged into power.
352     */
353    public abstract int getPluggedStartLevel();
354
355    /**
356     * Returns the total, last, or current battery uptime in microseconds.
357     *
358     * @param curTime the elapsed realtime in microseconds.
359     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
360     */
361    public abstract long computeBatteryUptime(long curTime, int which);
362
363    /**
364     * Returns the total, last, or current battery realtime 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 computeBatteryRealtime(long curTime, int which);
370
371    /**
372     * Returns the total, last, or current uptime 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 computeUptime(long curTime, int which);
378
379    /**
380     * Returns the total, last, or current realtime in microseconds.
381     * *
382     * @param curTime the current elapsed realtime in microseconds.
383     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
384     */
385    public abstract long computeRealtime(long curTime, int which);
386
387    private final static void formatTime(StringBuilder out, long seconds) {
388        long days = seconds / (60 * 60 * 24);
389        if (days != 0) {
390            out.append(days);
391            out.append("d ");
392        }
393        long used = days * 60 * 60 * 24;
394
395        long hours = (seconds - used) / (60 * 60);
396        if (hours != 0 || used != 0) {
397            out.append(hours);
398            out.append("h ");
399        }
400        used += hours * 60 * 60;
401
402        long mins = (seconds-used) / 60;
403        if (mins != 0 || used != 0) {
404            out.append(mins);
405            out.append("m ");
406        }
407        used += mins * 60;
408
409        if (seconds != 0 || used != 0) {
410            out.append(seconds-used);
411            out.append("s ");
412        }
413    }
414
415    private final static String formatTime(long time) {
416        long sec = time / 100;
417        StringBuilder sb = new StringBuilder();
418        formatTime(sb, sec);
419        sb.append((time - (sec * 100)) * 10);
420        sb.append("ms ");
421        return sb.toString();
422    }
423
424    private final static String formatTimeMs(long time) {
425        long sec = time / 1000;
426        StringBuilder sb = new StringBuilder();
427        formatTime(sb, sec);
428        sb.append(time - (sec * 1000));
429        sb.append("ms ");
430        return sb.toString();
431    }
432
433    private final String formatRatioLocked(long num, long den) {
434        if (den == 0L) {
435            return "---%";
436        }
437        float perc = ((float)num) / ((float)den) * 100;
438        mFormatBuilder.setLength(0);
439        mFormatter.format("%.1f%%", perc);
440        return mFormatBuilder.toString();
441    }
442
443    /**
444     *
445     * @param sb a StringBuilder object.
446     * @param timer a Timer object contining the wakelock times.
447     * @param batteryRealtime the current on-battery time in microseconds.
448     * @param name the name of the wakelock.
449     * @param which which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
450     * @param linePrefix a String to be prepended to each line of output.
451     * @return the line prefix
452     */
453    private static final String printWakeLock(StringBuilder sb, Timer timer,
454            long batteryRealtime, String name, int which, String linePrefix) {
455
456        if (timer != null) {
457            // Convert from microseconds to milliseconds with rounding
458            long totalTimeMicros = timer.getTotalTime(batteryRealtime, which);
459            long totalTimeMillis = (totalTimeMicros + 500) / 1000;
460
461            int count = timer.getCount(which);
462            if (totalTimeMillis != 0) {
463                sb.append(linePrefix);
464                sb.append(formatTimeMs(totalTimeMillis));
465                sb.append(name);
466                sb.append(' ');
467                sb.append('(');
468                sb.append(count);
469                sb.append(" times)");
470                return ", ";
471            }
472        }
473        return linePrefix;
474    }
475
476    /**
477     * Checkin version of wakelock printer. Prints simple comma-separated list.
478     *
479     * @param sb a StringBuilder object.
480     * @param timer a Timer object contining the wakelock times.
481     * @param now the current time in microseconds.
482     * @param name the name of the wakelock.
483     * @param which which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
484     * @param linePrefix a String to be prepended to each line of output.
485     * @return the line prefix
486     */
487    private static final String printWakeLockCheckin(StringBuilder sb, Timer timer, long now,
488        String name, int which, String linePrefix) {
489        long totalTimeMicros = 0;
490        int count = 0;
491        if (timer != null) {
492            totalTimeMicros = timer.getTotalTime(now, which);
493            count = timer.getCount(which);
494        }
495        sb.append(linePrefix);
496        sb.append((totalTimeMicros + 500) / 1000); // microseconds to milliseconds with rounding
497        sb.append(',');
498        sb.append(name);
499        sb.append(',');
500        sb.append(count);
501        return ",";
502    }
503
504    /**
505     * Dump a comma-separated line of values for terse checkin mode.
506     *
507     * @param pw the PageWriter to dump log to
508     * @param category category of data (e.g. "total", "last", "unplugged", "current" )
509     * @param type type of data (e.g. "wakelock", "sensor", "process", "apk" ,  "process", "network")
510     * @param args type-dependent data arguments
511     */
512    private static final void dumpLine(PrintWriter pw, int uid, String category, String type,
513           Object... args ) {
514        pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
515        pw.print(uid); pw.print(',');
516        pw.print(category); pw.print(',');
517        pw.print(type);
518
519        for (Object arg : args) {
520            pw.print(',');
521            pw.print(arg);
522        }
523        pw.print('\n');
524    }
525
526    /**
527     * Checkin server version of dump to produce more compact, computer-readable log.
528     *
529     * NOTE: all times are expressed in 'ms'.
530     * @param fd
531     * @param pw
532     * @param which
533     */
534    private final void dumpCheckinLocked(PrintWriter pw, int which) {
535        final long rawUptime = SystemClock.uptimeMillis() * 1000;
536        final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
537        final long batteryUptime = getBatteryUptime(rawUptime);
538        final long batteryRealtime = getBatteryRealtime(rawRealtime);
539        final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
540        final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
541        final long totalRealtime = computeRealtime(rawRealtime, which);
542        final long totalUptime = computeUptime(rawUptime, which);
543        final long screenOnTime = getScreenOnTime(batteryRealtime, which);
544        final long phoneOnTime = getPhoneOnTime(batteryRealtime, which);
545        final long wifiOnTime = getWifiOnTime(batteryRealtime, which);
546        final long wifiRunningTime = getWifiRunningTime(batteryRealtime, which);
547        final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which);
548
549        StringBuilder sb = new StringBuilder(128);
550
551        String category = STAT_NAMES[which];
552
553        // Dump "battery" stat
554        dumpLine(pw, 0 /* uid */, category, BATTERY_DATA,
555                which == STATS_TOTAL ? getStartCount() : "N/A",
556                whichBatteryUptime / 1000, whichBatteryRealtime / 1000,
557                totalUptime / 1000, totalRealtime / 1000);
558
559        // Dump misc stats
560        dumpLine(pw, 0 /* uid */, category, MISC_DATA,
561                screenOnTime / 1000, phoneOnTime / 1000, wifiOnTime / 1000,
562                wifiRunningTime / 1000, bluetoothOnTime / 1000);
563
564        if (which == STATS_UNPLUGGED) {
565            dumpLine(pw, 0 /* uid */, category, BATTERY_DATA, getUnpluggedStartLevel(),
566                    getPluggedStartLevel());
567        }
568
569        SparseArray<? extends Uid> uidStats = getUidStats();
570        final int NU = uidStats.size();
571        for (int iu = 0; iu < NU; iu++) {
572            final int uid = uidStats.keyAt(iu);
573            Uid u = uidStats.valueAt(iu);
574            // Dump Network stats per uid, if any
575            long rx = u.getTcpBytesReceived(which);
576            long tx = u.getTcpBytesSent(which);
577            long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
578            long scanWifiLockOnTime = u.getScanWifiLockTime(batteryRealtime, which);
579
580            if (rx > 0 || tx > 0) dumpLine(pw, uid, category, NETWORK_DATA, rx, tx);
581
582            if (fullWifiLockOnTime != 0 || scanWifiLockOnTime != 0) {
583                dumpLine(pw, uid, category, WIFI_LOCK_DATA,
584                        fullWifiLockOnTime, scanWifiLockOnTime);
585            }
586
587            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
588            if (wakelocks.size() > 0) {
589                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
590                        : wakelocks.entrySet()) {
591                    Uid.Wakelock wl = ent.getValue();
592                    String linePrefix = "";
593                    sb.setLength(0);
594                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_FULL), batteryRealtime,
595                            "full", which, linePrefix);
596                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), batteryRealtime,
597                            "partial", which, linePrefix);
598                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), batteryRealtime,
599                            "window", which, linePrefix);
600
601                    // Only log if we had at lease one wakelock...
602                    if (sb.length() > 0) {
603                       dumpLine(pw, uid, category, WAKELOCK_DATA, ent.getKey(), sb.toString());
604                    }
605                }
606            }
607
608            Map<Integer, ? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
609            if (sensors.size() > 0)  {
610                for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> ent
611                        : sensors.entrySet()) {
612                    Uid.Sensor se = ent.getValue();
613                    int sensorNumber = ent.getKey();
614                    Timer timer = se.getSensorTime();
615                    if (timer != null) {
616                        // Convert from microseconds to milliseconds with rounding
617                        long totalTime = (timer.getTotalTime(batteryRealtime, which) + 500) / 1000;
618                        int count = timer.getCount(which);
619                        if (totalTime != 0) {
620                            dumpLine(pw, uid, category, SENSOR_DATA, sensorNumber, totalTime, count);
621                        }
622                    }
623                }
624            }
625
626            Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
627            if (processStats.size() > 0) {
628                for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
629                        : processStats.entrySet()) {
630                    Uid.Proc ps = ent.getValue();
631
632                    long userTime = ps.getUserTime(which);
633                    long systemTime = ps.getSystemTime(which);
634                    int starts = ps.getStarts(which);
635
636                    if (userTime != 0 || systemTime != 0 || starts != 0) {
637                        dumpLine(pw, uid, category, PROCESS_DATA,
638                                ent.getKey(), // proc
639                                userTime * 10, // cpu time in ms
640                                systemTime * 10, // user time in ms
641                                starts); // process starts
642                    }
643                }
644            }
645
646            Map<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats();
647            if (packageStats.size() > 0) {
648                for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent
649                        : packageStats.entrySet()) {
650
651                    Uid.Pkg ps = ent.getValue();
652                    int wakeups = ps.getWakeups(which);
653                    Map<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
654                    for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent
655                            : serviceStats.entrySet()) {
656                        BatteryStats.Uid.Pkg.Serv ss = sent.getValue();
657                        long startTime = ss.getStartTime(batteryUptime, which);
658                        int starts = ss.getStarts(which);
659                        int launches = ss.getLaunches(which);
660                        if (startTime != 0 || starts != 0 || launches != 0) {
661                            dumpLine(pw, uid, category, APK_DATA,
662                                    wakeups, // wakeup alarms
663                                    ent.getKey(), // Apk
664                                    sent.getKey(), // service
665                                    startTime / 1000, // time spent started, in ms
666                                    starts,
667                                    launches);
668                        }
669                    }
670                }
671            }
672        }
673    }
674
675    @SuppressWarnings("unused")
676    private final void dumpLocked(Printer pw, String prefix, int which) {
677        final long rawUptime = SystemClock.uptimeMillis() * 1000;
678        final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
679        final long batteryUptime = getBatteryUptime(rawUptime);
680        final long batteryRealtime = getBatteryRealtime(rawRealtime);
681
682        final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
683        final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
684        final long totalRealtime = computeRealtime(rawRealtime, which);
685        final long totalUptime = computeUptime(rawUptime, which);
686
687        StringBuilder sb = new StringBuilder(128);
688
689        pw.println(prefix
690                + "  Time on battery: " + formatTimeMs(whichBatteryUptime / 1000)
691                + "(" + formatRatioLocked(whichBatteryUptime, totalRealtime)
692                + ") uptime, "
693                + formatTimeMs(whichBatteryRealtime / 1000) + "("
694                + formatRatioLocked(whichBatteryRealtime, totalRealtime)
695                + ") realtime");
696        pw.println(prefix
697                + "  Total: "
698                + formatTimeMs(totalUptime / 1000)
699                + "uptime, "
700                + formatTimeMs(totalRealtime / 1000)
701                + "realtime");
702
703        final long screenOnTime = getScreenOnTime(batteryRealtime, which);
704        final long phoneOnTime = getPhoneOnTime(batteryRealtime, which);
705        final long wifiRunningTime = getWifiRunningTime(batteryRealtime, which);
706        final long wifiOnTime = getWifiOnTime(batteryRealtime, which);
707        final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which);
708        pw.println(prefix
709                + "  Time with screen on: " + formatTimeMs(screenOnTime / 1000)
710                + "(" + formatRatioLocked(screenOnTime, whichBatteryRealtime)
711                + "), time with phone on: " + formatTimeMs(phoneOnTime / 1000)
712                + "(" + formatRatioLocked(phoneOnTime, whichBatteryRealtime)
713                + "), time with wifi on: " + formatTimeMs(wifiOnTime / 1000)
714                + "(" + formatRatioLocked(wifiOnTime, whichBatteryRealtime)
715                + "), time with wifi running: " + formatTimeMs(wifiRunningTime / 1000)
716                + "(" + formatRatioLocked(wifiRunningTime, whichBatteryRealtime)
717                + "), time with bluetooth on: " + formatTimeMs(bluetoothOnTime / 1000)
718                + "(" + formatRatioLocked(bluetoothOnTime, whichBatteryRealtime)+ ")");
719
720        pw.println(" ");
721
722        if (which == STATS_UNPLUGGED) {
723            if (getIsOnBattery()) {
724                pw.println(prefix + "  Device is currently unplugged");
725                pw.println(prefix + "    Discharge cycle start level: " +
726                        getUnpluggedStartLevel());
727            } else {
728                pw.println(prefix + "  Device is currently plugged into power");
729                pw.println(prefix + "    Last discharge cycle start level: " +
730                        getUnpluggedStartLevel());
731                pw.println(prefix + "    Last discharge cycle end level: " +
732                        getPluggedStartLevel());
733            }
734        }
735
736        pw.println(" ");
737
738        SparseArray<? extends Uid> uidStats = getUidStats();
739        final int NU = uidStats.size();
740        for (int iu=0; iu<NU; iu++) {
741            final int uid = uidStats.keyAt(iu);
742            Uid u = uidStats.valueAt(iu);
743            pw.println(prefix + "  #" + uid + ":");
744            boolean uidActivity = false;
745
746            long tcpReceived = u.getTcpBytesReceived(which);
747            long tcpSent = u.getTcpBytesSent(which);
748            long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
749            long scanWifiLockOnTime = u.getScanWifiLockTime(batteryRealtime, which);
750
751            if (tcpReceived != 0 || tcpSent != 0) {
752                pw.println(prefix + "    Network: " + tcpReceived + " bytes received, "
753                        + tcpSent + " bytes sent");
754            }
755            if (fullWifiLockOnTime != 0 || scanWifiLockOnTime != 0) {
756                pw.println(prefix + "    Full Wifi Lock Time: "
757                        + formatTime(fullWifiLockOnTime / 1000)
758                        + "(" + formatRatioLocked(fullWifiLockOnTime,
759                                whichBatteryRealtime)+ ")");
760                pw.println(prefix + "    Scan Wifi Lock Time: "
761                        + formatTime(scanWifiLockOnTime / 1000)
762                        + "(" + formatRatioLocked(scanWifiLockOnTime,
763                                whichBatteryRealtime)+ ")");
764            }
765
766            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
767            if (wakelocks.size() > 0) {
768                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
769                    : wakelocks.entrySet()) {
770                    Uid.Wakelock wl = ent.getValue();
771                    String linePrefix = ": ";
772                    sb.setLength(0);
773                    sb.append(prefix);
774                    sb.append("    Wake lock ");
775                    sb.append(ent.getKey());
776                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_FULL), batteryRealtime,
777                            "full", which, linePrefix);
778                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), batteryRealtime,
779                            "partial", which, linePrefix);
780                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), batteryRealtime,
781                            "window", which, linePrefix);
782                    if (!linePrefix.equals(": ")) {
783                        sb.append(" realtime");
784                    } else {
785                        sb.append(": (nothing executed)");
786                    }
787                    pw.println(sb.toString());
788                    uidActivity = true;
789                }
790            }
791
792            Map<Integer, ? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
793            if (sensors.size() > 0) {
794                for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> ent
795                    : sensors.entrySet()) {
796                    Uid.Sensor se = ent.getValue();
797                    int sensorNumber = ent.getKey();
798                    sb.setLength(0);
799                    sb.append(prefix);
800                    sb.append("    Sensor ");
801                    int handle = se.getHandle();
802                    if (handle == Uid.Sensor.GPS) {
803                        sb.append("GPS");
804                    } else {
805                        sb.append(handle);
806                    }
807                    sb.append(": ");
808
809                    Timer timer = se.getSensorTime();
810                    if (timer != null) {
811                        // Convert from microseconds to milliseconds with rounding
812                        long totalTime = (timer.getTotalTime(batteryRealtime, which) + 500) / 1000;
813                        int count = timer.getCount(which);
814                        //timer.logState();
815                        if (totalTime != 0) {
816                            sb.append(formatTimeMs(totalTime));
817                            sb.append("realtime (");
818                            sb.append(count);
819                            sb.append(" times)");
820                        } else {
821                            sb.append("(not used)");
822                        }
823                    } else {
824                        sb.append("(not used)");
825                    }
826
827                    pw.println(sb.toString());
828                    uidActivity = true;
829                }
830            }
831
832            Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
833            if (processStats.size() > 0) {
834                for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
835                    : processStats.entrySet()) {
836                    Uid.Proc ps = ent.getValue();
837                    long userTime;
838                    long systemTime;
839                    int starts;
840
841                    userTime = ps.getUserTime(which);
842                    systemTime = ps.getSystemTime(which);
843                    starts = ps.getStarts(which);
844
845                    if (userTime != 0 || systemTime != 0 || starts != 0) {
846                        pw.println(prefix + "    Proc " + ent.getKey() + ":");
847                        pw.println(prefix + "      CPU: " + formatTime(userTime) + "user + "
848                                + formatTime(systemTime) + "kernel");
849                        pw.println(prefix + "      " + starts + " process starts");
850                        uidActivity = true;
851                    }
852                }
853            }
854
855            Map<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats();
856            if (packageStats.size() > 0) {
857                for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent
858                    : packageStats.entrySet()) {
859                    pw.println(prefix + "    Apk " + ent.getKey() + ":");
860                    boolean apkActivity = false;
861                    Uid.Pkg ps = ent.getValue();
862                    int wakeups = ps.getWakeups(which);
863                    if (wakeups != 0) {
864                        pw.println(prefix + "      " + wakeups + " wakeup alarms");
865                        apkActivity = true;
866                    }
867                    Map<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
868                    if (serviceStats.size() > 0) {
869                        for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent
870                                : serviceStats.entrySet()) {
871                            BatteryStats.Uid.Pkg.Serv ss = sent.getValue();
872                            long startTime = ss.getStartTime(batteryUptime, which);
873                            int starts = ss.getStarts(which);
874                            int launches = ss.getLaunches(which);
875                            if (startTime != 0 || starts != 0 || launches != 0) {
876                                pw.println(prefix + "      Service " + sent.getKey() + ":");
877                                pw.println(prefix + "        Created for: "
878                                        + formatTimeMs(startTime / 1000)
879                                        + " uptime");
880                                pw.println(prefix + "        Starts: " + starts
881                                        + ", launches: " + launches);
882                                apkActivity = true;
883                            }
884                        }
885                    }
886                    if (!apkActivity) {
887                        pw.println(prefix + "      (nothing executed)");
888                    }
889                    uidActivity = true;
890                }
891            }
892            if (!uidActivity) {
893                pw.println(prefix + "    (nothing executed)");
894            }
895        }
896    }
897
898    /**
899     * Dumps a human-readable summary of the battery statistics to the given PrintWriter.
900     *
901     * @param pw a Printer to receive the dump output.
902     */
903    @SuppressWarnings("unused")
904    public void dumpLocked(Printer pw) {
905        pw.println("Total Statistics (Current and Historic):");
906        pw.println("  System starts: " + getStartCount()
907                + ", currently on battery: " + getIsOnBattery());
908        dumpLocked(pw, "", STATS_TOTAL);
909        pw.println("");
910        pw.println("Last Run Statistics (Previous run of system):");
911        dumpLocked(pw, "", STATS_LAST);
912        pw.println("");
913        pw.println("Current Battery Statistics (Currently running system):");
914        dumpLocked(pw, "", STATS_CURRENT);
915        pw.println("");
916        pw.println("Unplugged Statistics (Since last unplugged from power):");
917        dumpLocked(pw, "", STATS_UNPLUGGED);
918    }
919
920    @SuppressWarnings("unused")
921    public void dumpCheckinLocked(PrintWriter pw, String[] args) {
922        boolean isUnpluggedOnly = false;
923
924        for (String arg : args) {
925            if ("-u".equals(arg)) {
926                if (LOCAL_LOGV) Log.v("BatteryStats", "Dumping unplugged data");
927                isUnpluggedOnly = true;
928            }
929        }
930
931        if (isUnpluggedOnly) {
932            dumpCheckinLocked(pw, STATS_UNPLUGGED);
933        }
934        else {
935            dumpCheckinLocked(pw, STATS_TOTAL);
936            dumpCheckinLocked(pw, STATS_LAST);
937            dumpCheckinLocked(pw, STATS_UNPLUGGED);
938            dumpCheckinLocked(pw, STATS_CURRENT);
939        }
940    }
941
942}
943