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