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