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