BatteryStats.java revision 2d40bf91e6ad71505ec84743c5ad0b854ecf5928
1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.os;
18
19import java.io.PrintWriter;
20import java.util.ArrayList;
21import java.util.Formatter;
22import java.util.List;
23import java.util.Map;
24
25import android.content.pm.ApplicationInfo;
26import android.telephony.SignalStrength;
27import android.util.Log;
28import android.util.Printer;
29import android.util.SparseArray;
30import android.util.TimeUtils;
31
32/**
33 * A class providing access to battery usage statistics, including information on
34 * wakelocks, processes, packages, and services.  All times are represented in microseconds
35 * except where indicated otherwise.
36 * @hide
37 */
38public abstract class BatteryStats implements Parcelable {
39
40    private static final boolean LOCAL_LOGV = false;
41
42    /**
43     * A constant indicating a partial wake lock timer.
44     */
45    public static final int WAKE_TYPE_PARTIAL = 0;
46
47    /**
48     * A constant indicating a full wake lock timer.
49     */
50    public static final int WAKE_TYPE_FULL = 1;
51
52    /**
53     * A constant indicating a window wake lock timer.
54     */
55    public static final int WAKE_TYPE_WINDOW = 2;
56
57    /**
58     * A constant indicating a sensor timer.
59     */
60    public static final int SENSOR = 3;
61
62    /**
63     * A constant indicating a a wifi running timer
64     */
65    public static final int WIFI_RUNNING = 4;
66
67    /**
68     * A constant indicating a full wifi lock timer
69     */
70    public static final int FULL_WIFI_LOCK = 5;
71
72    /**
73     * A constant indicating a scan wifi lock timer
74     */
75    public static final int SCAN_WIFI_LOCK = 6;
76
77     /**
78      * A constant indicating a wifi multicast timer
79      */
80     public static final int WIFI_MULTICAST_ENABLED = 7;
81
82    /**
83     * A constant indicating an audio turn on timer
84     */
85    public static final int AUDIO_TURNED_ON = 7;
86
87    /**
88     * A constant indicating a video turn on timer
89     */
90    public static final int VIDEO_TURNED_ON = 8;
91
92    /**
93     * Include all of the data in the stats, including previously saved data.
94     */
95    public static final int STATS_SINCE_CHARGED = 0;
96
97    /**
98     * Include only the last run in the stats.
99     */
100    public static final int STATS_LAST = 1;
101
102    /**
103     * Include only the current run in the stats.
104     */
105    public static final int STATS_CURRENT = 2;
106
107    /**
108     * Include only the run since the last time the device was unplugged in the stats.
109     */
110    public static final int STATS_SINCE_UNPLUGGED = 3;
111
112    // NOTE: Update this list if you add/change any stats above.
113    // These characters are supposed to represent "total", "last", "current",
114    // and "unplugged". They were shortened for efficiency sake.
115    private static final String[] STAT_NAMES = { "t", "l", "c", "u" };
116
117    /**
118     * Bump the version on this if the checkin format changes.
119     */
120    private static final int BATTERY_STATS_CHECKIN_VERSION = 5;
121
122    private static final long BYTES_PER_KB = 1024;
123    private static final long BYTES_PER_MB = 1048576; // 1024^2
124    private static final long BYTES_PER_GB = 1073741824; //1024^3
125
126
127    private static final String UID_DATA = "uid";
128    private static final String APK_DATA = "apk";
129    private static final String PROCESS_DATA = "pr";
130    private static final String SENSOR_DATA = "sr";
131    private static final String WAKELOCK_DATA = "wl";
132    private static final String KERNEL_WAKELOCK_DATA = "kwl";
133    private static final String NETWORK_DATA = "nt";
134    private static final String USER_ACTIVITY_DATA = "ua";
135    private static final String BATTERY_DATA = "bt";
136    private static final String BATTERY_DISCHARGE_DATA = "dc";
137    private static final String BATTERY_LEVEL_DATA = "lv";
138    private static final String WIFI_LOCK_DATA = "wfl";
139    private static final String MISC_DATA = "m";
140    private static final String SCREEN_BRIGHTNESS_DATA = "br";
141    private static final String SIGNAL_STRENGTH_TIME_DATA = "sgt";
142    private static final String SIGNAL_SCANNING_TIME_DATA = "sst";
143    private static final String SIGNAL_STRENGTH_COUNT_DATA = "sgc";
144    private static final String DATA_CONNECTION_TIME_DATA = "dct";
145    private static final String DATA_CONNECTION_COUNT_DATA = "dcc";
146
147    private final StringBuilder mFormatBuilder = new StringBuilder(32);
148    private final Formatter mFormatter = new Formatter(mFormatBuilder);
149
150    /**
151     * State for keeping track of counting information.
152     */
153    public static abstract class Counter {
154
155        /**
156         * Returns the count associated with this Counter for the
157         * selected type of statistics.
158         *
159         * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT
160         */
161        public abstract int getCountLocked(int which);
162
163        /**
164         * Temporary for debugging.
165         */
166        public abstract void logState(Printer pw, String prefix);
167    }
168
169    /**
170     * State for keeping track of timing information.
171     */
172    public static abstract class Timer {
173
174        /**
175         * Returns the count associated with this Timer for the
176         * selected type of statistics.
177         *
178         * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT
179         */
180        public abstract int getCountLocked(int which);
181
182        /**
183         * Returns the total time in microseconds associated with this Timer for the
184         * selected type of statistics.
185         *
186         * @param batteryRealtime system realtime on  battery in microseconds
187         * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT
188         * @return a time in microseconds
189         */
190        public abstract long getTotalTimeLocked(long batteryRealtime, int which);
191
192        /**
193         * Temporary for debugging.
194         */
195        public abstract void logState(Printer pw, String prefix);
196    }
197
198    /**
199     * The statistics associated with a particular uid.
200     */
201    public static abstract class Uid {
202
203        /**
204         * Returns a mapping containing wakelock statistics.
205         *
206         * @return a Map from Strings to Uid.Wakelock objects.
207         */
208        public abstract Map<String, ? extends Wakelock> getWakelockStats();
209
210        /**
211         * The statistics associated with a particular wake lock.
212         */
213        public static abstract class Wakelock {
214            public abstract Timer getWakeTime(int type);
215        }
216
217        /**
218         * Returns a mapping containing sensor statistics.
219         *
220         * @return a Map from Integer sensor ids to Uid.Sensor objects.
221         */
222        public abstract Map<Integer, ? extends Sensor> getSensorStats();
223
224        /**
225         * Returns a mapping containing active process data.
226         */
227        public abstract SparseArray<? extends Pid> getPidStats();
228
229        /**
230         * Returns a mapping containing process statistics.
231         *
232         * @return a Map from Strings to Uid.Proc objects.
233         */
234        public abstract Map<String, ? extends Proc> getProcessStats();
235
236        /**
237         * Returns a mapping containing package statistics.
238         *
239         * @return a Map from Strings to Uid.Pkg objects.
240         */
241        public abstract Map<String, ? extends Pkg> getPackageStats();
242
243        /**
244         * {@hide}
245         */
246        public abstract int getUid();
247
248        /**
249         * {@hide}
250         */
251        public abstract long getTcpBytesReceived(int which);
252
253        /**
254         * {@hide}
255         */
256        public abstract long getTcpBytesSent(int which);
257
258        public abstract void noteWifiRunningLocked();
259        public abstract void noteWifiStoppedLocked();
260        public abstract void noteFullWifiLockAcquiredLocked();
261        public abstract void noteFullWifiLockReleasedLocked();
262        public abstract void noteScanWifiLockAcquiredLocked();
263        public abstract void noteScanWifiLockReleasedLocked();
264        public abstract void noteWifiMulticastEnabledLocked();
265        public abstract void noteWifiMulticastDisabledLocked();
266        public abstract void noteAudioTurnedOnLocked();
267        public abstract void noteAudioTurnedOffLocked();
268        public abstract void noteVideoTurnedOnLocked();
269        public abstract void noteVideoTurnedOffLocked();
270        public abstract long getWifiRunningTime(long batteryRealtime, int which);
271        public abstract long getFullWifiLockTime(long batteryRealtime, int which);
272        public abstract long getScanWifiLockTime(long batteryRealtime, int which);
273        public abstract long getWifiMulticastTime(long batteryRealtime,
274                                                  int which);
275        public abstract long getAudioTurnedOnTime(long batteryRealtime, int which);
276        public abstract long getVideoTurnedOnTime(long batteryRealtime, int which);
277
278        /**
279         * Note that these must match the constants in android.os.LocalPowerManager.
280         */
281        static final String[] USER_ACTIVITY_TYPES = {
282            "other", "cheek", "touch", "long_touch", "touch_up", "button", "unknown"
283        };
284
285        public static final int NUM_USER_ACTIVITY_TYPES = 7;
286
287        public abstract void noteUserActivityLocked(int type);
288        public abstract boolean hasUserActivity();
289        public abstract int getUserActivityCount(int type, int which);
290
291        public static abstract class Sensor {
292            // Magic sensor number for the GPS.
293            public static final int GPS = -10000;
294
295            public abstract int getHandle();
296
297            public abstract Timer getSensorTime();
298        }
299
300        public class Pid {
301            public long mWakeSum;
302            public long mWakeStart;
303        }
304
305        /**
306         * The statistics associated with a particular process.
307         */
308        public static abstract class Proc {
309
310            public static class ExcessivePower {
311                public static final int TYPE_WAKE = 1;
312                public static final int TYPE_CPU = 2;
313
314                public int type;
315                public long overTime;
316                public long usedTime;
317            }
318
319            /**
320             * Returns the total time (in 1/100 sec) spent executing in user code.
321             *
322             * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
323             */
324            public abstract long getUserTime(int which);
325
326            /**
327             * Returns the total time (in 1/100 sec) spent executing in system code.
328             *
329             * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
330             */
331            public abstract long getSystemTime(int which);
332
333            /**
334             * Returns the number of times the process has been started.
335             *
336             * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
337             */
338            public abstract int getStarts(int which);
339
340            /**
341             * Returns the cpu time spent in microseconds while the process was in the foreground.
342             * @param which one of STATS_TOTAL, STATS_LAST, STATS_CURRENT or STATS_UNPLUGGED
343             * @return foreground cpu time in microseconds
344             */
345            public abstract long getForegroundTime(int which);
346
347            /**
348             * Returns the approximate cpu time spent in microseconds, at a certain CPU speed.
349             * @param speedStep the index of the CPU speed. This is not the actual speed of the
350             * CPU.
351             * @param which one of STATS_TOTAL, STATS_LAST, STATS_CURRENT or STATS_UNPLUGGED
352             * @see BatteryStats#getCpuSpeedSteps()
353             */
354            public abstract long getTimeAtCpuSpeedStep(int speedStep, int which);
355
356            public abstract int countExcessivePowers();
357
358            public abstract ExcessivePower getExcessivePower(int i);
359        }
360
361        /**
362         * The statistics associated with a particular package.
363         */
364        public static abstract class Pkg {
365
366            /**
367             * Returns the number of times this package has done something that could wake up the
368             * device from sleep.
369             *
370             * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
371             */
372            public abstract int getWakeups(int which);
373
374            /**
375             * Returns a mapping containing service statistics.
376             */
377            public abstract Map<String, ? extends Serv> getServiceStats();
378
379            /**
380             * The statistics associated with a particular service.
381             */
382            public abstract class Serv {
383
384                /**
385                 * Returns the amount of time spent started.
386                 *
387                 * @param batteryUptime elapsed uptime on battery in microseconds.
388                 * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
389                 * @return
390                 */
391                public abstract long getStartTime(long batteryUptime, int which);
392
393                /**
394                 * Returns the total number of times startService() has been called.
395                 *
396                 * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
397                 */
398                public abstract int getStarts(int which);
399
400                /**
401                 * Returns the total number times the service has been launched.
402                 *
403                 * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
404                 */
405                public abstract int getLaunches(int which);
406            }
407        }
408    }
409
410    public final static class HistoryItem implements Parcelable {
411        public HistoryItem next;
412
413        public long time;
414
415        public static final byte CMD_UPDATE = 0;
416        public static final byte CMD_START = 1;
417        public static final byte CMD_OVERFLOW = 2;
418
419        public byte cmd;
420
421        public byte batteryLevel;
422        public byte batteryStatus;
423        public byte batteryHealth;
424        public byte batteryPlugType;
425
426        public char batteryTemperature;
427        public char batteryVoltage;
428
429        // Constants from SCREEN_BRIGHTNESS_*
430        public static final int STATE_BRIGHTNESS_MASK = 0x000000f;
431        public static final int STATE_BRIGHTNESS_SHIFT = 0;
432        // Constants from SIGNAL_STRENGTH_*
433        public static final int STATE_SIGNAL_STRENGTH_MASK = 0x00000f0;
434        public static final int STATE_SIGNAL_STRENGTH_SHIFT = 4;
435        // Constants from ServiceState.STATE_*
436        public static final int STATE_PHONE_STATE_MASK = 0x0000f00;
437        public static final int STATE_PHONE_STATE_SHIFT = 8;
438        // Constants from DATA_CONNECTION_*
439        public static final int STATE_DATA_CONNECTION_MASK = 0x000f000;
440        public static final int STATE_DATA_CONNECTION_SHIFT = 12;
441
442        public static final int STATE_BATTERY_PLUGGED_FLAG = 1<<30;
443        public static final int STATE_SCREEN_ON_FLAG = 1<<29;
444        public static final int STATE_GPS_ON_FLAG = 1<<28;
445        public static final int STATE_PHONE_IN_CALL_FLAG = 1<<27;
446        public static final int STATE_PHONE_SCANNING_FLAG = 1<<26;
447        public static final int STATE_WIFI_ON_FLAG = 1<<25;
448        public static final int STATE_WIFI_RUNNING_FLAG = 1<<24;
449        public static final int STATE_WIFI_FULL_LOCK_FLAG = 1<<23;
450        public static final int STATE_WIFI_SCAN_LOCK_FLAG = 1<<22;
451        public static final int STATE_WIFI_MULTICAST_ON_FLAG = 1<<21;
452        public static final int STATE_BLUETOOTH_ON_FLAG = 1<<20;
453        public static final int STATE_AUDIO_ON_FLAG = 1<<19;
454        public static final int STATE_VIDEO_ON_FLAG = 1<<18;
455        public static final int STATE_WAKE_LOCK_FLAG = 1<<17;
456        public static final int STATE_SENSOR_ON_FLAG = 1<<16;
457
458        public static final int MOST_INTERESTING_STATES =
459            STATE_BATTERY_PLUGGED_FLAG | STATE_SCREEN_ON_FLAG
460            | STATE_GPS_ON_FLAG | STATE_PHONE_IN_CALL_FLAG;
461
462        public int states;
463
464        public HistoryItem() {
465        }
466
467        public HistoryItem(long time, Parcel src) {
468            this.time = time;
469            int bat = src.readInt();
470            cmd = (byte)(bat&0xff);
471            batteryLevel = (byte)((bat>>8)&0xff);
472            batteryStatus = (byte)((bat>>16)&0xf);
473            batteryHealth = (byte)((bat>>20)&0xf);
474            batteryPlugType = (byte)((bat>>24)&0xf);
475            bat = src.readInt();
476            batteryTemperature = (char)(bat&0xffff);
477            batteryVoltage = (char)((bat>>16)&0xffff);
478            states = src.readInt();
479        }
480
481        public int describeContents() {
482            return 0;
483        }
484
485        public void writeToParcel(Parcel dest, int flags) {
486            dest.writeLong(time);
487            int bat = (((int)cmd)&0xff)
488                    | ((((int)batteryLevel)<<8)&0xff00)
489                    | ((((int)batteryStatus)<<16)&0xf0000)
490                    | ((((int)batteryHealth)<<20)&0xf00000)
491                    | ((((int)batteryPlugType)<<24)&0xf000000);
492            dest.writeInt(bat);
493            bat = (((int)batteryTemperature)&0xffff)
494                    | ((((int)batteryVoltage)<<16)&0xffff0000);
495            dest.writeInt(bat);
496            dest.writeInt(states);
497        }
498
499        public void setTo(HistoryItem o) {
500            time = o.time;
501            cmd = o.cmd;
502            batteryLevel = o.batteryLevel;
503            batteryStatus = o.batteryStatus;
504            batteryHealth = o.batteryHealth;
505            batteryPlugType = o.batteryPlugType;
506            batteryTemperature = o.batteryTemperature;
507            batteryVoltage = o.batteryVoltage;
508            states = o.states;
509        }
510
511        public void setTo(long time, byte cmd, HistoryItem o) {
512            this.time = time;
513            this.cmd = cmd;
514            batteryLevel = o.batteryLevel;
515            batteryStatus = o.batteryStatus;
516            batteryHealth = o.batteryHealth;
517            batteryPlugType = o.batteryPlugType;
518            batteryTemperature = o.batteryTemperature;
519            batteryVoltage = o.batteryVoltage;
520            states = o.states;
521        }
522
523        public boolean same(HistoryItem o) {
524            return batteryLevel == o.batteryLevel
525                    && batteryStatus == o.batteryStatus
526                    && batteryHealth == o.batteryHealth
527                    && batteryPlugType == o.batteryPlugType
528                    && batteryTemperature == o.batteryTemperature
529                    && batteryVoltage == o.batteryVoltage
530                    && states == o.states;
531        }
532    }
533
534    public static final class BitDescription {
535        public final int mask;
536        public final int shift;
537        public final String name;
538        public final String[] values;
539
540        public BitDescription(int mask, String name) {
541            this.mask = mask;
542            this.shift = -1;
543            this.name = name;
544            this.values = null;
545        }
546
547        public BitDescription(int mask, int shift, String name, String[] values) {
548            this.mask = mask;
549            this.shift = shift;
550            this.name = name;
551            this.values = values;
552        }
553    }
554
555    public abstract boolean startIteratingHistoryLocked();
556
557    public abstract boolean getNextHistoryLocked(HistoryItem out);
558
559    /**
560     * Return the current history of battery state changes.
561     */
562    public abstract HistoryItem getHistory();
563
564    /**
565     * Return the base time offset for the battery history.
566     */
567    public abstract long getHistoryBaseTime();
568
569    /**
570     * Returns the number of times the device has been started.
571     */
572    public abstract int getStartCount();
573
574    /**
575     * Returns the time in microseconds that the screen has been on while the device was
576     * running on battery.
577     *
578     * {@hide}
579     */
580    public abstract long getScreenOnTime(long batteryRealtime, int which);
581
582    public static final int SCREEN_BRIGHTNESS_DARK = 0;
583    public static final int SCREEN_BRIGHTNESS_DIM = 1;
584    public static final int SCREEN_BRIGHTNESS_MEDIUM = 2;
585    public static final int SCREEN_BRIGHTNESS_LIGHT = 3;
586    public static final int SCREEN_BRIGHTNESS_BRIGHT = 4;
587
588    static final String[] SCREEN_BRIGHTNESS_NAMES = {
589        "dark", "dim", "medium", "light", "bright"
590    };
591
592    public static final int NUM_SCREEN_BRIGHTNESS_BINS = 5;
593
594    /**
595     * Returns the time in microseconds that the screen has been on with
596     * the given brightness
597     *
598     * {@hide}
599     */
600    public abstract long getScreenBrightnessTime(int brightnessBin,
601            long batteryRealtime, int which);
602
603    public abstract int getInputEventCount(int which);
604
605    /**
606     * Returns the time in microseconds that the phone has been on while the device was
607     * running on battery.
608     *
609     * {@hide}
610     */
611    public abstract long getPhoneOnTime(long batteryRealtime, int which);
612
613    /**
614     * Returns the time in microseconds that the phone has been running with
615     * the given signal strength.
616     *
617     * {@hide}
618     */
619    public abstract long getPhoneSignalStrengthTime(int strengthBin,
620            long batteryRealtime, int which);
621
622    /**
623     * Returns the time in microseconds that the phone has been trying to
624     * acquire a signal.
625     *
626     * {@hide}
627     */
628    public abstract long getPhoneSignalScanningTime(
629            long batteryRealtime, int which);
630
631    /**
632     * Returns the number of times the phone has entered the given signal strength.
633     *
634     * {@hide}
635     */
636    public abstract int getPhoneSignalStrengthCount(int strengthBin, int which);
637
638    public static final int DATA_CONNECTION_NONE = 0;
639    public static final int DATA_CONNECTION_GPRS = 1;
640    public static final int DATA_CONNECTION_EDGE = 2;
641    public static final int DATA_CONNECTION_UMTS = 3;
642    public static final int DATA_CONNECTION_CDMA = 4;
643    public static final int DATA_CONNECTION_EVDO_0 = 5;
644    public static final int DATA_CONNECTION_EVDO_A = 6;
645    public static final int DATA_CONNECTION_1xRTT = 7;
646    public static final int DATA_CONNECTION_HSDPA = 8;
647    public static final int DATA_CONNECTION_HSUPA = 9;
648    public static final int DATA_CONNECTION_HSPA = 10;
649    public static final int DATA_CONNECTION_IDEN = 11;
650    public static final int DATA_CONNECTION_EVDO_B = 12;
651    public static final int DATA_CONNECTION_LTE = 13;
652    public static final int DATA_CONNECTION_EHRPD = 14;
653    public static final int DATA_CONNECTION_OTHER = 15;
654
655    static final String[] DATA_CONNECTION_NAMES = {
656        "none", "gprs", "edge", "umts", "cdma", "evdo_0", "evdo_A",
657        "1xrtt", "hsdpa", "hsupa", "hspa", "iden", "evdo_b", "lte",
658        "ehrpd", "other"
659    };
660
661    public static final int NUM_DATA_CONNECTION_TYPES = DATA_CONNECTION_OTHER+1;
662
663    /**
664     * Returns the time in microseconds that the phone has been running with
665     * the given data connection.
666     *
667     * {@hide}
668     */
669    public abstract long getPhoneDataConnectionTime(int dataType,
670            long batteryRealtime, int which);
671
672    /**
673     * Returns the number of times the phone has entered the given data
674     * connection type.
675     *
676     * {@hide}
677     */
678    public abstract int getPhoneDataConnectionCount(int dataType, int which);
679
680    public static final BitDescription[] HISTORY_STATE_DESCRIPTIONS
681            = new BitDescription[] {
682        new BitDescription(HistoryItem.STATE_BATTERY_PLUGGED_FLAG, "plugged"),
683        new BitDescription(HistoryItem.STATE_SCREEN_ON_FLAG, "screen"),
684        new BitDescription(HistoryItem.STATE_GPS_ON_FLAG, "gps"),
685        new BitDescription(HistoryItem.STATE_PHONE_IN_CALL_FLAG, "phone_in_call"),
686        new BitDescription(HistoryItem.STATE_PHONE_SCANNING_FLAG, "phone_scanning"),
687        new BitDescription(HistoryItem.STATE_WIFI_ON_FLAG, "wifi"),
688        new BitDescription(HistoryItem.STATE_WIFI_RUNNING_FLAG, "wifi_running"),
689        new BitDescription(HistoryItem.STATE_WIFI_FULL_LOCK_FLAG, "wifi_full_lock"),
690        new BitDescription(HistoryItem.STATE_WIFI_SCAN_LOCK_FLAG, "wifi_scan_lock"),
691        new BitDescription(HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG, "wifi_multicast"),
692        new BitDescription(HistoryItem.STATE_BLUETOOTH_ON_FLAG, "bluetooth"),
693        new BitDescription(HistoryItem.STATE_AUDIO_ON_FLAG, "audio"),
694        new BitDescription(HistoryItem.STATE_VIDEO_ON_FLAG, "video"),
695        new BitDescription(HistoryItem.STATE_WAKE_LOCK_FLAG, "wake_lock"),
696        new BitDescription(HistoryItem.STATE_SENSOR_ON_FLAG, "sensor"),
697        new BitDescription(HistoryItem.STATE_BRIGHTNESS_MASK,
698                HistoryItem.STATE_BRIGHTNESS_SHIFT, "brightness",
699                SCREEN_BRIGHTNESS_NAMES),
700        new BitDescription(HistoryItem.STATE_SIGNAL_STRENGTH_MASK,
701                HistoryItem.STATE_SIGNAL_STRENGTH_SHIFT, "signal_strength",
702                SignalStrength.SIGNAL_STRENGTH_NAMES),
703        new BitDescription(HistoryItem.STATE_PHONE_STATE_MASK,
704                HistoryItem.STATE_PHONE_STATE_SHIFT, "phone_state",
705                new String[] {"in", "out", "emergency", "off"}),
706        new BitDescription(HistoryItem.STATE_DATA_CONNECTION_MASK,
707                HistoryItem.STATE_DATA_CONNECTION_SHIFT, "data_conn",
708                DATA_CONNECTION_NAMES),
709    };
710
711    /**
712     * Returns the time in microseconds that wifi has been on while the device was
713     * running on battery.
714     *
715     * {@hide}
716     */
717    public abstract long getWifiOnTime(long batteryRealtime, int which);
718
719    /**
720     * Returns the time in microseconds that wifi has been on and the driver has
721     * been in the running state while the device was running on battery.
722     *
723     * {@hide}
724     */
725    public abstract long getGlobalWifiRunningTime(long batteryRealtime, int which);
726
727    /**
728     * Returns the time in microseconds that bluetooth has been on while the device was
729     * running on battery.
730     *
731     * {@hide}
732     */
733    public abstract long getBluetoothOnTime(long batteryRealtime, int which);
734
735    /**
736     * Return whether we are currently running on battery.
737     */
738    public abstract boolean getIsOnBattery();
739
740    /**
741     * Returns a SparseArray containing the statistics for each uid.
742     */
743    public abstract SparseArray<? extends Uid> getUidStats();
744
745    /**
746     * Returns the current battery uptime in microseconds.
747     *
748     * @param curTime the amount of elapsed realtime in microseconds.
749     */
750    public abstract long getBatteryUptime(long curTime);
751
752    /**
753     * @deprecated use getRadioDataUptime
754     */
755    public long getRadioDataUptimeMs() {
756        return getRadioDataUptime() / 1000;
757    }
758
759    /**
760     * Returns the time that the radio was on for data transfers.
761     * @return the uptime in microseconds while unplugged
762     */
763    public abstract long getRadioDataUptime();
764
765    /**
766     * Returns the current battery realtime in microseconds.
767     *
768     * @param curTime the amount of elapsed realtime in microseconds.
769     */
770    public abstract long getBatteryRealtime(long curTime);
771
772    /**
773     * Returns the battery percentage level at the last time the device was unplugged from power, or
774     * the last time it booted on battery power.
775     */
776    public abstract int getDischargeStartLevel();
777
778    /**
779     * Returns the current battery percentage level if we are in a discharge cycle, otherwise
780     * returns the level at the last plug event.
781     */
782    public abstract int getDischargeCurrentLevel();
783
784    /**
785     * Get the amount the battery has discharged since the stats were
786     * last reset after charging, as a lower-end approximation.
787     */
788    public abstract int getLowDischargeAmountSinceCharge();
789
790    /**
791     * Get the amount the battery has discharged since the stats were
792     * last reset after charging, as an upper-end approximation.
793     */
794    public abstract int getHighDischargeAmountSinceCharge();
795
796    /**
797     * Get the amount the battery has discharged while the screen was on,
798     * since the last time power was unplugged.
799     */
800    public abstract int getDischargeAmountScreenOn();
801
802    /**
803     * Get the amount the battery has discharged while the screen was on,
804     * since the last time the device was charged.
805     */
806    public abstract int getDischargeAmountScreenOnSinceCharge();
807
808    /**
809     * Get the amount the battery has discharged while the screen was off,
810     * since the last time power was unplugged.
811     */
812    public abstract int getDischargeAmountScreenOff();
813
814    /**
815     * Get the amount the battery has discharged while the screen was off,
816     * since the last time the device was charged.
817     */
818    public abstract int getDischargeAmountScreenOffSinceCharge();
819
820    /**
821     * Returns the total, last, or current battery uptime in microseconds.
822     *
823     * @param curTime the elapsed realtime in microseconds.
824     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
825     */
826    public abstract long computeBatteryUptime(long curTime, int which);
827
828    /**
829     * Returns the total, last, or current battery realtime in microseconds.
830     *
831     * @param curTime the current elapsed realtime in microseconds.
832     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
833     */
834    public abstract long computeBatteryRealtime(long curTime, int which);
835
836    /**
837     * Returns the total, last, or current uptime in microseconds.
838     *
839     * @param curTime the current elapsed realtime in microseconds.
840     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
841     */
842    public abstract long computeUptime(long curTime, int which);
843
844    /**
845     * Returns the total, last, or current realtime in microseconds.
846     * *
847     * @param curTime the current elapsed realtime in microseconds.
848     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
849     */
850    public abstract long computeRealtime(long curTime, int which);
851
852    public abstract Map<String, ? extends Timer> getKernelWakelockStats();
853
854    /** Returns the number of different speeds that the CPU can run at */
855    public abstract int getCpuSpeedSteps();
856
857    private final static void formatTimeRaw(StringBuilder out, long seconds) {
858        long days = seconds / (60 * 60 * 24);
859        if (days != 0) {
860            out.append(days);
861            out.append("d ");
862        }
863        long used = days * 60 * 60 * 24;
864
865        long hours = (seconds - used) / (60 * 60);
866        if (hours != 0 || used != 0) {
867            out.append(hours);
868            out.append("h ");
869        }
870        used += hours * 60 * 60;
871
872        long mins = (seconds-used) / 60;
873        if (mins != 0 || used != 0) {
874            out.append(mins);
875            out.append("m ");
876        }
877        used += mins * 60;
878
879        if (seconds != 0 || used != 0) {
880            out.append(seconds-used);
881            out.append("s ");
882        }
883    }
884
885    private final static void formatTime(StringBuilder sb, long time) {
886        long sec = time / 100;
887        formatTimeRaw(sb, sec);
888        sb.append((time - (sec * 100)) * 10);
889        sb.append("ms ");
890    }
891
892    private final static void formatTimeMs(StringBuilder sb, long time) {
893        long sec = time / 1000;
894        formatTimeRaw(sb, sec);
895        sb.append(time - (sec * 1000));
896        sb.append("ms ");
897    }
898
899    private final String formatRatioLocked(long num, long den) {
900        if (den == 0L) {
901            return "---%";
902        }
903        float perc = ((float)num) / ((float)den) * 100;
904        mFormatBuilder.setLength(0);
905        mFormatter.format("%.1f%%", perc);
906        return mFormatBuilder.toString();
907    }
908
909    private final String formatBytesLocked(long bytes) {
910        mFormatBuilder.setLength(0);
911
912        if (bytes < BYTES_PER_KB) {
913            return bytes + "B";
914        } else if (bytes < BYTES_PER_MB) {
915            mFormatter.format("%.2fKB", bytes / (double) BYTES_PER_KB);
916            return mFormatBuilder.toString();
917        } else if (bytes < BYTES_PER_GB){
918            mFormatter.format("%.2fMB", bytes / (double) BYTES_PER_MB);
919            return mFormatBuilder.toString();
920        } else {
921            mFormatter.format("%.2fGB", bytes / (double) BYTES_PER_GB);
922            return mFormatBuilder.toString();
923        }
924    }
925
926    /**
927     *
928     * @param sb a StringBuilder object.
929     * @param timer a Timer object contining the wakelock times.
930     * @param batteryRealtime the current on-battery time in microseconds.
931     * @param name the name of the wakelock.
932     * @param which which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
933     * @param linePrefix a String to be prepended to each line of output.
934     * @return the line prefix
935     */
936    private static final String printWakeLock(StringBuilder sb, Timer timer,
937            long batteryRealtime, String name, int which, String linePrefix) {
938
939        if (timer != null) {
940            // Convert from microseconds to milliseconds with rounding
941            long totalTimeMicros = timer.getTotalTimeLocked(batteryRealtime, which);
942            long totalTimeMillis = (totalTimeMicros + 500) / 1000;
943
944            int count = timer.getCountLocked(which);
945            if (totalTimeMillis != 0) {
946                sb.append(linePrefix);
947                formatTimeMs(sb, totalTimeMillis);
948                if (name != null) sb.append(name);
949                sb.append(' ');
950                sb.append('(');
951                sb.append(count);
952                sb.append(" times)");
953                return ", ";
954            }
955        }
956        return linePrefix;
957    }
958
959    /**
960     * Checkin version of wakelock printer. Prints simple comma-separated list.
961     *
962     * @param sb a StringBuilder object.
963     * @param timer a Timer object contining the wakelock times.
964     * @param now the current time in microseconds.
965     * @param name the name of the wakelock.
966     * @param which which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
967     * @param linePrefix a String to be prepended to each line of output.
968     * @return the line prefix
969     */
970    private static final String printWakeLockCheckin(StringBuilder sb, Timer timer, long now,
971            String name, int which, String linePrefix) {
972        long totalTimeMicros = 0;
973        int count = 0;
974        if (timer != null) {
975            totalTimeMicros = timer.getTotalTimeLocked(now, which);
976            count = timer.getCountLocked(which);
977        }
978        sb.append(linePrefix);
979        sb.append((totalTimeMicros + 500) / 1000); // microseconds to milliseconds with rounding
980        sb.append(',');
981        sb.append(name != null ? name + "," : "");
982        sb.append(count);
983        return ",";
984    }
985
986    /**
987     * Dump a comma-separated line of values for terse checkin mode.
988     *
989     * @param pw the PageWriter to dump log to
990     * @param category category of data (e.g. "total", "last", "unplugged", "current" )
991     * @param type type of data (e.g. "wakelock", "sensor", "process", "apk" ,  "process", "network")
992     * @param args type-dependent data arguments
993     */
994    private static final void dumpLine(PrintWriter pw, int uid, String category, String type,
995           Object... args ) {
996        pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
997        pw.print(uid); pw.print(',');
998        pw.print(category); pw.print(',');
999        pw.print(type);
1000
1001        for (Object arg : args) {
1002            pw.print(',');
1003            pw.print(arg);
1004        }
1005        pw.print('\n');
1006    }
1007
1008    /**
1009     * Checkin server version of dump to produce more compact, computer-readable log.
1010     *
1011     * NOTE: all times are expressed in 'ms'.
1012     */
1013    public final void dumpCheckinLocked(PrintWriter pw, int which, int reqUid) {
1014        final long rawUptime = SystemClock.uptimeMillis() * 1000;
1015        final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
1016        final long batteryUptime = getBatteryUptime(rawUptime);
1017        final long batteryRealtime = getBatteryRealtime(rawRealtime);
1018        final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
1019        final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
1020        final long totalRealtime = computeRealtime(rawRealtime, which);
1021        final long totalUptime = computeUptime(rawUptime, which);
1022        final long screenOnTime = getScreenOnTime(batteryRealtime, which);
1023        final long phoneOnTime = getPhoneOnTime(batteryRealtime, which);
1024        final long wifiOnTime = getWifiOnTime(batteryRealtime, which);
1025        final long wifiRunningTime = getGlobalWifiRunningTime(batteryRealtime, which);
1026        final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which);
1027
1028        StringBuilder sb = new StringBuilder(128);
1029
1030        SparseArray<? extends Uid> uidStats = getUidStats();
1031        final int NU = uidStats.size();
1032
1033        String category = STAT_NAMES[which];
1034
1035        // Dump "battery" stat
1036        dumpLine(pw, 0 /* uid */, category, BATTERY_DATA,
1037                which == STATS_SINCE_CHARGED ? getStartCount() : "N/A",
1038                whichBatteryRealtime / 1000, whichBatteryUptime / 1000,
1039                totalRealtime / 1000, totalUptime / 1000);
1040
1041        // Calculate total network and wakelock times across all uids.
1042        long rxTotal = 0;
1043        long txTotal = 0;
1044        long fullWakeLockTimeTotal = 0;
1045        long partialWakeLockTimeTotal = 0;
1046
1047        for (int iu = 0; iu < NU; iu++) {
1048            Uid u = uidStats.valueAt(iu);
1049            rxTotal += u.getTcpBytesReceived(which);
1050            txTotal += u.getTcpBytesSent(which);
1051
1052            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
1053            if (wakelocks.size() > 0) {
1054                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
1055                        : wakelocks.entrySet()) {
1056                    Uid.Wakelock wl = ent.getValue();
1057
1058                    Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
1059                    if (fullWakeTimer != null) {
1060                        fullWakeLockTimeTotal += fullWakeTimer.getTotalTimeLocked(batteryRealtime, which);
1061                    }
1062
1063                    Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
1064                    if (partialWakeTimer != null) {
1065                        partialWakeLockTimeTotal += partialWakeTimer.getTotalTimeLocked(
1066                            batteryRealtime, which);
1067                    }
1068                }
1069            }
1070        }
1071
1072        // Dump misc stats
1073        dumpLine(pw, 0 /* uid */, category, MISC_DATA,
1074                screenOnTime / 1000, phoneOnTime / 1000, wifiOnTime / 1000,
1075                wifiRunningTime / 1000, bluetoothOnTime / 1000, rxTotal, txTotal,
1076                fullWakeLockTimeTotal, partialWakeLockTimeTotal,
1077                getInputEventCount(which));
1078
1079        // Dump screen brightness stats
1080        Object[] args = new Object[NUM_SCREEN_BRIGHTNESS_BINS];
1081        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
1082            args[i] = getScreenBrightnessTime(i, batteryRealtime, which) / 1000;
1083        }
1084        dumpLine(pw, 0 /* uid */, category, SCREEN_BRIGHTNESS_DATA, args);
1085
1086        // Dump signal strength stats
1087        args = new Object[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
1088        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
1089            args[i] = getPhoneSignalStrengthTime(i, batteryRealtime, which) / 1000;
1090        }
1091        dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_TIME_DATA, args);
1092        dumpLine(pw, 0 /* uid */, category, SIGNAL_SCANNING_TIME_DATA,
1093                getPhoneSignalScanningTime(batteryRealtime, which) / 1000);
1094        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
1095            args[i] = getPhoneSignalStrengthCount(i, which);
1096        }
1097        dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_COUNT_DATA, args);
1098
1099        // Dump network type stats
1100        args = new Object[NUM_DATA_CONNECTION_TYPES];
1101        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
1102            args[i] = getPhoneDataConnectionTime(i, batteryRealtime, which) / 1000;
1103        }
1104        dumpLine(pw, 0 /* uid */, category, DATA_CONNECTION_TIME_DATA, args);
1105        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
1106            args[i] = getPhoneDataConnectionCount(i, which);
1107        }
1108        dumpLine(pw, 0 /* uid */, category, DATA_CONNECTION_COUNT_DATA, args);
1109
1110        if (which == STATS_SINCE_UNPLUGGED) {
1111            dumpLine(pw, 0 /* uid */, category, BATTERY_LEVEL_DATA, getDischargeStartLevel(),
1112                    getDischargeCurrentLevel());
1113        }
1114
1115        if (which == STATS_SINCE_UNPLUGGED) {
1116            dumpLine(pw, 0 /* uid */, category, BATTERY_DISCHARGE_DATA,
1117                    getDischargeStartLevel()-getDischargeCurrentLevel(),
1118                    getDischargeStartLevel()-getDischargeCurrentLevel(),
1119                    getDischargeAmountScreenOn(), getDischargeAmountScreenOff());
1120        } else {
1121            dumpLine(pw, 0 /* uid */, category, BATTERY_DISCHARGE_DATA,
1122                    getLowDischargeAmountSinceCharge(), getHighDischargeAmountSinceCharge(),
1123                    getDischargeAmountScreenOn(), getDischargeAmountScreenOff());
1124        }
1125
1126        if (reqUid < 0) {
1127            Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats();
1128            if (kernelWakelocks.size() > 0) {
1129                for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) {
1130                    sb.setLength(0);
1131                    printWakeLockCheckin(sb, ent.getValue(), batteryRealtime, null, which, "");
1132
1133                    dumpLine(pw, 0 /* uid */, category, KERNEL_WAKELOCK_DATA, ent.getKey(),
1134                            sb.toString());
1135                }
1136            }
1137        }
1138
1139        for (int iu = 0; iu < NU; iu++) {
1140            final int uid = uidStats.keyAt(iu);
1141            if (reqUid >= 0 && uid != reqUid) {
1142                continue;
1143            }
1144            Uid u = uidStats.valueAt(iu);
1145            // Dump Network stats per uid, if any
1146            long rx = u.getTcpBytesReceived(which);
1147            long tx = u.getTcpBytesSent(which);
1148            long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
1149            long scanWifiLockOnTime = u.getScanWifiLockTime(batteryRealtime, which);
1150            long uidWifiRunningTime = u.getWifiRunningTime(batteryRealtime, which);
1151
1152            if (rx > 0 || tx > 0) dumpLine(pw, uid, category, NETWORK_DATA, rx, tx);
1153
1154            if (fullWifiLockOnTime != 0 || scanWifiLockOnTime != 0
1155                    || uidWifiRunningTime != 0) {
1156                dumpLine(pw, uid, category, WIFI_LOCK_DATA,
1157                        fullWifiLockOnTime, scanWifiLockOnTime, uidWifiRunningTime);
1158            }
1159
1160            if (u.hasUserActivity()) {
1161                args = new Object[Uid.NUM_USER_ACTIVITY_TYPES];
1162                boolean hasData = false;
1163                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
1164                    int val = u.getUserActivityCount(i, which);
1165                    args[i] = val;
1166                    if (val != 0) hasData = true;
1167                }
1168                if (hasData) {
1169                    dumpLine(pw, 0 /* uid */, category, USER_ACTIVITY_DATA, args);
1170                }
1171            }
1172
1173            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
1174            if (wakelocks.size() > 0) {
1175                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
1176                        : wakelocks.entrySet()) {
1177                    Uid.Wakelock wl = ent.getValue();
1178                    String linePrefix = "";
1179                    sb.setLength(0);
1180                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_FULL),
1181                            batteryRealtime, "f", which, linePrefix);
1182                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL),
1183                            batteryRealtime, "p", which, linePrefix);
1184                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_WINDOW),
1185                            batteryRealtime, "w", which, linePrefix);
1186
1187                    // Only log if we had at lease one wakelock...
1188                    if (sb.length() > 0) {
1189                       dumpLine(pw, uid, category, WAKELOCK_DATA, ent.getKey(), sb.toString());
1190                    }
1191                }
1192            }
1193
1194            Map<Integer, ? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
1195            if (sensors.size() > 0)  {
1196                for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> ent
1197                        : sensors.entrySet()) {
1198                    Uid.Sensor se = ent.getValue();
1199                    int sensorNumber = ent.getKey();
1200                    Timer timer = se.getSensorTime();
1201                    if (timer != null) {
1202                        // Convert from microseconds to milliseconds with rounding
1203                        long totalTime = (timer.getTotalTimeLocked(batteryRealtime, which) + 500) / 1000;
1204                        int count = timer.getCountLocked(which);
1205                        if (totalTime != 0) {
1206                            dumpLine(pw, uid, category, SENSOR_DATA, sensorNumber, totalTime, count);
1207                        }
1208                    }
1209                }
1210            }
1211
1212            Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
1213            if (processStats.size() > 0) {
1214                for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
1215                        : processStats.entrySet()) {
1216                    Uid.Proc ps = ent.getValue();
1217
1218                    long userTime = ps.getUserTime(which);
1219                    long systemTime = ps.getSystemTime(which);
1220                    int starts = ps.getStarts(which);
1221
1222                    if (userTime != 0 || systemTime != 0 || starts != 0) {
1223                        dumpLine(pw, uid, category, PROCESS_DATA,
1224                                ent.getKey(), // proc
1225                                userTime * 10, // cpu time in ms
1226                                systemTime * 10, // user time in ms
1227                                starts); // process starts
1228                    }
1229                }
1230            }
1231
1232            Map<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats();
1233            if (packageStats.size() > 0) {
1234                for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent
1235                        : packageStats.entrySet()) {
1236
1237                    Uid.Pkg ps = ent.getValue();
1238                    int wakeups = ps.getWakeups(which);
1239                    Map<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
1240                    for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent
1241                            : serviceStats.entrySet()) {
1242                        BatteryStats.Uid.Pkg.Serv ss = sent.getValue();
1243                        long startTime = ss.getStartTime(batteryUptime, which);
1244                        int starts = ss.getStarts(which);
1245                        int launches = ss.getLaunches(which);
1246                        if (startTime != 0 || starts != 0 || launches != 0) {
1247                            dumpLine(pw, uid, category, APK_DATA,
1248                                    wakeups, // wakeup alarms
1249                                    ent.getKey(), // Apk
1250                                    sent.getKey(), // service
1251                                    startTime / 1000, // time spent started, in ms
1252                                    starts,
1253                                    launches);
1254                        }
1255                    }
1256                }
1257            }
1258        }
1259    }
1260
1261    @SuppressWarnings("unused")
1262    public final void dumpLocked(PrintWriter pw, String prefix, int which, int reqUid) {
1263        final long rawUptime = SystemClock.uptimeMillis() * 1000;
1264        final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
1265        final long batteryUptime = getBatteryUptime(rawUptime);
1266        final long batteryRealtime = getBatteryRealtime(rawRealtime);
1267
1268        final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
1269        final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
1270        final long totalRealtime = computeRealtime(rawRealtime, which);
1271        final long totalUptime = computeUptime(rawUptime, which);
1272
1273        StringBuilder sb = new StringBuilder(128);
1274
1275        SparseArray<? extends Uid> uidStats = getUidStats();
1276        final int NU = uidStats.size();
1277
1278        sb.setLength(0);
1279        sb.append(prefix);
1280                sb.append("  Time on battery: ");
1281                formatTimeMs(sb, whichBatteryRealtime / 1000); sb.append("(");
1282                sb.append(formatRatioLocked(whichBatteryRealtime, totalRealtime));
1283                sb.append(") realtime, ");
1284                formatTimeMs(sb, whichBatteryUptime / 1000);
1285                sb.append("("); sb.append(formatRatioLocked(whichBatteryUptime, totalRealtime));
1286                sb.append(") uptime");
1287        pw.println(sb.toString());
1288        sb.setLength(0);
1289        sb.append(prefix);
1290                sb.append("  Total run time: ");
1291                formatTimeMs(sb, totalRealtime / 1000);
1292                sb.append("realtime, ");
1293                formatTimeMs(sb, totalUptime / 1000);
1294                sb.append("uptime, ");
1295        pw.println(sb.toString());
1296
1297        final long screenOnTime = getScreenOnTime(batteryRealtime, which);
1298        final long phoneOnTime = getPhoneOnTime(batteryRealtime, which);
1299        final long wifiRunningTime = getGlobalWifiRunningTime(batteryRealtime, which);
1300        final long wifiOnTime = getWifiOnTime(batteryRealtime, which);
1301        final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which);
1302        sb.setLength(0);
1303        sb.append(prefix);
1304                sb.append("  Screen on: "); formatTimeMs(sb, screenOnTime / 1000);
1305                sb.append("("); sb.append(formatRatioLocked(screenOnTime, whichBatteryRealtime));
1306                sb.append("), Input events: "); sb.append(getInputEventCount(which));
1307                sb.append(", Active phone call: "); formatTimeMs(sb, phoneOnTime / 1000);
1308                sb.append("("); sb.append(formatRatioLocked(phoneOnTime, whichBatteryRealtime));
1309                sb.append(")");
1310        pw.println(sb.toString());
1311        sb.setLength(0);
1312        sb.append(prefix);
1313        sb.append("  Screen brightnesses: ");
1314        boolean didOne = false;
1315        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
1316            final long time = getScreenBrightnessTime(i, batteryRealtime, which);
1317            if (time == 0) {
1318                continue;
1319            }
1320            if (didOne) sb.append(", ");
1321            didOne = true;
1322            sb.append(SCREEN_BRIGHTNESS_NAMES[i]);
1323            sb.append(" ");
1324            formatTimeMs(sb, time/1000);
1325            sb.append("(");
1326            sb.append(formatRatioLocked(time, screenOnTime));
1327            sb.append(")");
1328        }
1329        if (!didOne) sb.append("No activity");
1330        pw.println(sb.toString());
1331
1332        // Calculate total network and wakelock times across all uids.
1333        long rxTotal = 0;
1334        long txTotal = 0;
1335        long fullWakeLockTimeTotalMicros = 0;
1336        long partialWakeLockTimeTotalMicros = 0;
1337
1338        if (reqUid < 0) {
1339            Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats();
1340            if (kernelWakelocks.size() > 0) {
1341                for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) {
1342
1343                    String linePrefix = ": ";
1344                    sb.setLength(0);
1345                    sb.append(prefix);
1346                    sb.append("  Kernel Wake lock ");
1347                    sb.append(ent.getKey());
1348                    linePrefix = printWakeLock(sb, ent.getValue(), batteryRealtime, null, which,
1349                            linePrefix);
1350                    if (!linePrefix.equals(": ")) {
1351                        sb.append(" realtime");
1352                        // Only print out wake locks that were held
1353                        pw.println(sb.toString());
1354                    }
1355                }
1356            }
1357        }
1358
1359        for (int iu = 0; iu < NU; iu++) {
1360            Uid u = uidStats.valueAt(iu);
1361            rxTotal += u.getTcpBytesReceived(which);
1362            txTotal += u.getTcpBytesSent(which);
1363
1364            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
1365            if (wakelocks.size() > 0) {
1366                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
1367                        : wakelocks.entrySet()) {
1368                    Uid.Wakelock wl = ent.getValue();
1369
1370                    Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
1371                    if (fullWakeTimer != null) {
1372                        fullWakeLockTimeTotalMicros += fullWakeTimer.getTotalTimeLocked(
1373                                batteryRealtime, which);
1374                    }
1375
1376                    Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
1377                    if (partialWakeTimer != null) {
1378                        partialWakeLockTimeTotalMicros += partialWakeTimer.getTotalTimeLocked(
1379                                batteryRealtime, which);
1380                    }
1381                }
1382            }
1383        }
1384
1385        pw.print(prefix);
1386                pw.print("  Total received: "); pw.print(formatBytesLocked(rxTotal));
1387                pw.print(", Total sent: "); pw.println(formatBytesLocked(txTotal));
1388        sb.setLength(0);
1389        sb.append(prefix);
1390                sb.append("  Total full wakelock time: "); formatTimeMs(sb,
1391                        (fullWakeLockTimeTotalMicros + 500) / 1000);
1392                sb.append(", Total partial waklock time: "); formatTimeMs(sb,
1393                        (partialWakeLockTimeTotalMicros + 500) / 1000);
1394        pw.println(sb.toString());
1395
1396        sb.setLength(0);
1397        sb.append(prefix);
1398        sb.append("  Signal levels: ");
1399        didOne = false;
1400        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
1401            final long time = getPhoneSignalStrengthTime(i, batteryRealtime, which);
1402            if (time == 0) {
1403                continue;
1404            }
1405            if (didOne) sb.append(", ");
1406            didOne = true;
1407            sb.append(SignalStrength.SIGNAL_STRENGTH_NAMES[i]);
1408            sb.append(" ");
1409            formatTimeMs(sb, time/1000);
1410            sb.append("(");
1411            sb.append(formatRatioLocked(time, whichBatteryRealtime));
1412            sb.append(") ");
1413            sb.append(getPhoneSignalStrengthCount(i, which));
1414            sb.append("x");
1415        }
1416        if (!didOne) sb.append("No activity");
1417        pw.println(sb.toString());
1418
1419        sb.setLength(0);
1420        sb.append(prefix);
1421        sb.append("  Signal scanning time: ");
1422        formatTimeMs(sb, getPhoneSignalScanningTime(batteryRealtime, which) / 1000);
1423        pw.println(sb.toString());
1424
1425        sb.setLength(0);
1426        sb.append(prefix);
1427        sb.append("  Radio types: ");
1428        didOne = false;
1429        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
1430            final long time = getPhoneDataConnectionTime(i, batteryRealtime, which);
1431            if (time == 0) {
1432                continue;
1433            }
1434            if (didOne) sb.append(", ");
1435            didOne = true;
1436            sb.append(DATA_CONNECTION_NAMES[i]);
1437            sb.append(" ");
1438            formatTimeMs(sb, time/1000);
1439            sb.append("(");
1440            sb.append(formatRatioLocked(time, whichBatteryRealtime));
1441            sb.append(") ");
1442            sb.append(getPhoneDataConnectionCount(i, which));
1443            sb.append("x");
1444        }
1445        if (!didOne) sb.append("No activity");
1446        pw.println(sb.toString());
1447
1448        sb.setLength(0);
1449        sb.append(prefix);
1450        sb.append("  Radio data uptime when unplugged: ");
1451        sb.append(getRadioDataUptime() / 1000);
1452        sb.append(" ms");
1453        pw.println(sb.toString());
1454
1455        sb.setLength(0);
1456        sb.append(prefix);
1457                sb.append("  Wifi on: "); formatTimeMs(sb, wifiOnTime / 1000);
1458                sb.append("("); sb.append(formatRatioLocked(wifiOnTime, whichBatteryRealtime));
1459                sb.append("), Wifi running: "); formatTimeMs(sb, wifiRunningTime / 1000);
1460                sb.append("("); sb.append(formatRatioLocked(wifiRunningTime, whichBatteryRealtime));
1461                sb.append("), Bluetooth on: "); formatTimeMs(sb, bluetoothOnTime / 1000);
1462                sb.append("("); sb.append(formatRatioLocked(bluetoothOnTime, whichBatteryRealtime));
1463                sb.append(")");
1464        pw.println(sb.toString());
1465
1466        pw.println(" ");
1467
1468        if (which == STATS_SINCE_UNPLUGGED) {
1469            if (getIsOnBattery()) {
1470                pw.print(prefix); pw.println("  Device is currently unplugged");
1471                pw.print(prefix); pw.print("    Discharge cycle start level: ");
1472                        pw.println(getDischargeStartLevel());
1473                pw.print(prefix); pw.print("    Discharge cycle current level: ");
1474                        pw.println(getDischargeCurrentLevel());
1475            } else {
1476                pw.print(prefix); pw.println("  Device is currently plugged into power");
1477                pw.print(prefix); pw.print("    Last discharge cycle start level: ");
1478                        pw.println(getDischargeStartLevel());
1479                pw.print(prefix); pw.print("    Last discharge cycle end level: ");
1480                        pw.println(getDischargeCurrentLevel());
1481            }
1482            pw.print(prefix); pw.print("    Amount discharged while screen on: ");
1483                    pw.println(getDischargeAmountScreenOn());
1484            pw.print(prefix); pw.print("    Amount discharged while screen off: ");
1485                    pw.println(getDischargeAmountScreenOff());
1486            pw.println(" ");
1487        } else {
1488            pw.print(prefix); pw.println("  Device battery use since last full charge");
1489            pw.print(prefix); pw.print("    Amount discharged (lower bound): ");
1490                    pw.println(getLowDischargeAmountSinceCharge());
1491            pw.print(prefix); pw.print("    Amount discharged (upper bound): ");
1492                    pw.println(getHighDischargeAmountSinceCharge());
1493            pw.print(prefix); pw.print("    Amount discharged while screen on: ");
1494                    pw.println(getDischargeAmountScreenOnSinceCharge());
1495            pw.print(prefix); pw.print("    Amount discharged while screen off: ");
1496                    pw.println(getDischargeAmountScreenOffSinceCharge());
1497            pw.println(" ");
1498        }
1499
1500
1501        for (int iu=0; iu<NU; iu++) {
1502            final int uid = uidStats.keyAt(iu);
1503            if (reqUid >= 0 && uid != reqUid && uid != Process.SYSTEM_UID) {
1504                continue;
1505            }
1506
1507            Uid u = uidStats.valueAt(iu);
1508
1509            pw.println(prefix + "  #" + uid + ":");
1510            boolean uidActivity = false;
1511
1512            long tcpReceived = u.getTcpBytesReceived(which);
1513            long tcpSent = u.getTcpBytesSent(which);
1514            long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
1515            long scanWifiLockOnTime = u.getScanWifiLockTime(batteryRealtime, which);
1516            long uidWifiRunningTime = u.getWifiRunningTime(batteryRealtime, which);
1517
1518            if (tcpReceived != 0 || tcpSent != 0) {
1519                pw.print(prefix); pw.print("    Network: ");
1520                        pw.print(formatBytesLocked(tcpReceived)); pw.print(" received, ");
1521                        pw.print(formatBytesLocked(tcpSent)); pw.println(" sent");
1522            }
1523
1524            if (u.hasUserActivity()) {
1525                boolean hasData = false;
1526                for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
1527                    int val = u.getUserActivityCount(i, which);
1528                    if (val != 0) {
1529                        if (!hasData) {
1530                            sb.setLength(0);
1531                            sb.append("    User activity: ");
1532                            hasData = true;
1533                        } else {
1534                            sb.append(", ");
1535                        }
1536                        sb.append(val);
1537                        sb.append(" ");
1538                        sb.append(Uid.USER_ACTIVITY_TYPES[i]);
1539                    }
1540                }
1541                if (hasData) {
1542                    pw.println(sb.toString());
1543                }
1544            }
1545
1546            if (fullWifiLockOnTime != 0 || scanWifiLockOnTime != 0
1547                    || uidWifiRunningTime != 0) {
1548                sb.setLength(0);
1549                sb.append(prefix); sb.append("    Wifi Running: ");
1550                        formatTimeMs(sb, uidWifiRunningTime / 1000);
1551                        sb.append("("); sb.append(formatRatioLocked(uidWifiRunningTime,
1552                                whichBatteryRealtime)); sb.append(")\n");
1553                sb.append(prefix); sb.append("    Full Wifi Lock: ");
1554                        formatTimeMs(sb, fullWifiLockOnTime / 1000);
1555                        sb.append("("); sb.append(formatRatioLocked(fullWifiLockOnTime,
1556                                whichBatteryRealtime)); sb.append(")\n");
1557                sb.append(prefix); sb.append("    Scan Wifi Lock: ");
1558                        formatTimeMs(sb, scanWifiLockOnTime / 1000);
1559                        sb.append("("); sb.append(formatRatioLocked(scanWifiLockOnTime,
1560                                whichBatteryRealtime)); sb.append(")");
1561                pw.println(sb.toString());
1562            }
1563
1564            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
1565            if (wakelocks.size() > 0) {
1566                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
1567                    : wakelocks.entrySet()) {
1568                    Uid.Wakelock wl = ent.getValue();
1569                    String linePrefix = ": ";
1570                    sb.setLength(0);
1571                    sb.append(prefix);
1572                    sb.append("    Wake lock ");
1573                    sb.append(ent.getKey());
1574                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_FULL), batteryRealtime,
1575                            "full", which, linePrefix);
1576                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), batteryRealtime,
1577                            "partial", which, linePrefix);
1578                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), batteryRealtime,
1579                            "window", which, linePrefix);
1580                    if (!linePrefix.equals(": ")) {
1581                        sb.append(" realtime");
1582                        // Only print out wake locks that were held
1583                        pw.println(sb.toString());
1584                        uidActivity = true;
1585                    }
1586                }
1587            }
1588
1589            Map<Integer, ? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
1590            if (sensors.size() > 0) {
1591                for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> ent
1592                    : sensors.entrySet()) {
1593                    Uid.Sensor se = ent.getValue();
1594                    int sensorNumber = ent.getKey();
1595                    sb.setLength(0);
1596                    sb.append(prefix);
1597                    sb.append("    Sensor ");
1598                    int handle = se.getHandle();
1599                    if (handle == Uid.Sensor.GPS) {
1600                        sb.append("GPS");
1601                    } else {
1602                        sb.append(handle);
1603                    }
1604                    sb.append(": ");
1605
1606                    Timer timer = se.getSensorTime();
1607                    if (timer != null) {
1608                        // Convert from microseconds to milliseconds with rounding
1609                        long totalTime = (timer.getTotalTimeLocked(
1610                                batteryRealtime, which) + 500) / 1000;
1611                        int count = timer.getCountLocked(which);
1612                        //timer.logState();
1613                        if (totalTime != 0) {
1614                            formatTimeMs(sb, totalTime);
1615                            sb.append("realtime (");
1616                            sb.append(count);
1617                            sb.append(" times)");
1618                        } else {
1619                            sb.append("(not used)");
1620                        }
1621                    } else {
1622                        sb.append("(not used)");
1623                    }
1624
1625                    pw.println(sb.toString());
1626                    uidActivity = true;
1627                }
1628            }
1629
1630            Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
1631            if (processStats.size() > 0) {
1632                for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
1633                    : processStats.entrySet()) {
1634                    Uid.Proc ps = ent.getValue();
1635                    long userTime;
1636                    long systemTime;
1637                    int starts;
1638                    int numExcessive;
1639
1640                    userTime = ps.getUserTime(which);
1641                    systemTime = ps.getSystemTime(which);
1642                    starts = ps.getStarts(which);
1643                    numExcessive = which == STATS_SINCE_CHARGED
1644                            ? ps.countExcessivePowers() : 0;
1645
1646                    if (userTime != 0 || systemTime != 0 || starts != 0
1647                            || numExcessive != 0) {
1648                        sb.setLength(0);
1649                        sb.append(prefix); sb.append("    Proc ");
1650                                sb.append(ent.getKey()); sb.append(":\n");
1651                        sb.append(prefix); sb.append("      CPU: ");
1652                                formatTime(sb, userTime); sb.append("usr + ");
1653                                formatTime(sb, systemTime); sb.append("krn");
1654                        if (starts != 0) {
1655                            sb.append("\n"); sb.append(prefix); sb.append("      ");
1656                                    sb.append(starts); sb.append(" proc starts");
1657                        }
1658                        pw.println(sb.toString());
1659                        for (int e=0; e<numExcessive; e++) {
1660                            Uid.Proc.ExcessivePower ew = ps.getExcessivePower(e);
1661                            if (ew != null) {
1662                                pw.print(prefix); pw.print("      * Killed for ");
1663                                        if (ew.type == Uid.Proc.ExcessivePower.TYPE_WAKE) {
1664                                            pw.print("wake lock");
1665                                        } else if (ew.type == Uid.Proc.ExcessivePower.TYPE_CPU) {
1666                                            pw.print("cpu");
1667                                        } else {
1668                                            pw.print("unknown");
1669                                        }
1670                                        pw.print(" use: ");
1671                                        TimeUtils.formatDuration(ew.usedTime, pw);
1672                                        pw.print(" over ");
1673                                        TimeUtils.formatDuration(ew.overTime, pw);
1674                                        pw.print(" (");
1675                                        pw.print((ew.usedTime*100)/ew.overTime);
1676                                        pw.println("%)");
1677                            }
1678                        }
1679                        uidActivity = true;
1680                    }
1681                }
1682            }
1683
1684            Map<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats();
1685            if (packageStats.size() > 0) {
1686                for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent
1687                    : packageStats.entrySet()) {
1688                    pw.print(prefix); pw.print("    Apk "); pw.print(ent.getKey()); pw.println(":");
1689                    boolean apkActivity = false;
1690                    Uid.Pkg ps = ent.getValue();
1691                    int wakeups = ps.getWakeups(which);
1692                    if (wakeups != 0) {
1693                        pw.print(prefix); pw.print("      ");
1694                                pw.print(wakeups); pw.println(" wakeup alarms");
1695                        apkActivity = true;
1696                    }
1697                    Map<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
1698                    if (serviceStats.size() > 0) {
1699                        for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent
1700                                : serviceStats.entrySet()) {
1701                            BatteryStats.Uid.Pkg.Serv ss = sent.getValue();
1702                            long startTime = ss.getStartTime(batteryUptime, which);
1703                            int starts = ss.getStarts(which);
1704                            int launches = ss.getLaunches(which);
1705                            if (startTime != 0 || starts != 0 || launches != 0) {
1706                                sb.setLength(0);
1707                                sb.append(prefix); sb.append("      Service ");
1708                                        sb.append(sent.getKey()); sb.append(":\n");
1709                                sb.append(prefix); sb.append("        Created for: ");
1710                                        formatTimeMs(sb, startTime / 1000);
1711                                        sb.append(" uptime\n");
1712                                sb.append(prefix); sb.append("        Starts: ");
1713                                        sb.append(starts);
1714                                        sb.append(", launches: "); sb.append(launches);
1715                                pw.println(sb.toString());
1716                                apkActivity = true;
1717                            }
1718                        }
1719                    }
1720                    if (!apkActivity) {
1721                        pw.print(prefix); pw.println("      (nothing executed)");
1722                    }
1723                    uidActivity = true;
1724                }
1725            }
1726            if (!uidActivity) {
1727                pw.print(prefix); pw.println("    (nothing executed)");
1728            }
1729        }
1730    }
1731
1732    void printBitDescriptions(PrintWriter pw, int oldval, int newval, BitDescription[] descriptions) {
1733        int diff = oldval ^ newval;
1734        if (diff == 0) return;
1735        for (int i=0; i<descriptions.length; i++) {
1736            BitDescription bd = descriptions[i];
1737            if ((diff&bd.mask) != 0) {
1738                if (bd.shift < 0) {
1739                    pw.print((newval&bd.mask) != 0 ? " +" : " -");
1740                    pw.print(bd.name);
1741                } else {
1742                    pw.print(" ");
1743                    pw.print(bd.name);
1744                    pw.print("=");
1745                    int val = (newval&bd.mask)>>bd.shift;
1746                    if (bd.values != null && val >= 0 && val < bd.values.length) {
1747                        pw.print(bd.values[val]);
1748                    } else {
1749                        pw.print(val);
1750                    }
1751                }
1752            }
1753        }
1754    }
1755
1756    /**
1757     * Dumps a human-readable summary of the battery statistics to the given PrintWriter.
1758     *
1759     * @param pw a Printer to receive the dump output.
1760     */
1761    @SuppressWarnings("unused")
1762    public void dumpLocked(PrintWriter pw) {
1763        final HistoryItem rec = new HistoryItem();
1764        if (startIteratingHistoryLocked()) {
1765            pw.println("Battery History:");
1766            long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
1767            int oldState = 0;
1768            int oldStatus = -1;
1769            int oldHealth = -1;
1770            int oldPlug = -1;
1771            int oldTemp = -1;
1772            int oldVolt = -1;
1773            while (getNextHistoryLocked(rec)) {
1774                pw.print("  ");
1775                TimeUtils.formatDuration(rec.time-now, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
1776                pw.print(" ");
1777                if (rec.cmd == HistoryItem.CMD_START) {
1778                    pw.println(" START");
1779                } else if (rec.cmd == HistoryItem.CMD_OVERFLOW) {
1780                    pw.println(" *OVERFLOW*");
1781                } else {
1782                    if (rec.batteryLevel < 10) pw.print("00");
1783                    else if (rec.batteryLevel < 100) pw.print("0");
1784                    pw.print(rec.batteryLevel);
1785                    pw.print(" ");
1786                    if (rec.states < 0x10) pw.print("0000000");
1787                    else if (rec.states < 0x100) pw.print("000000");
1788                    else if (rec.states < 0x1000) pw.print("00000");
1789                    else if (rec.states < 0x10000) pw.print("0000");
1790                    else if (rec.states < 0x100000) pw.print("000");
1791                    else if (rec.states < 0x1000000) pw.print("00");
1792                    else if (rec.states < 0x10000000) pw.print("0");
1793                    pw.print(Integer.toHexString(rec.states));
1794                    if (oldStatus != rec.batteryStatus) {
1795                        oldStatus = rec.batteryStatus;
1796                        pw.print(" status=");
1797                        switch (oldStatus) {
1798                            case BatteryManager.BATTERY_STATUS_UNKNOWN:
1799                                pw.print("unknown");
1800                                break;
1801                            case BatteryManager.BATTERY_STATUS_CHARGING:
1802                                pw.print("charging");
1803                                break;
1804                            case BatteryManager.BATTERY_STATUS_DISCHARGING:
1805                                pw.print("discharging");
1806                                break;
1807                            case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
1808                                pw.print("not-charging");
1809                                break;
1810                            case BatteryManager.BATTERY_STATUS_FULL:
1811                                pw.print("full");
1812                                break;
1813                            default:
1814                                pw.print(oldStatus);
1815                                break;
1816                        }
1817                    }
1818                    if (oldHealth != rec.batteryHealth) {
1819                        oldHealth = rec.batteryHealth;
1820                        pw.print(" health=");
1821                        switch (oldHealth) {
1822                            case BatteryManager.BATTERY_HEALTH_UNKNOWN:
1823                                pw.print("unknown");
1824                                break;
1825                            case BatteryManager.BATTERY_HEALTH_GOOD:
1826                                pw.print("good");
1827                                break;
1828                            case BatteryManager.BATTERY_HEALTH_OVERHEAT:
1829                                pw.print("overheat");
1830                                break;
1831                            case BatteryManager.BATTERY_HEALTH_DEAD:
1832                                pw.print("dead");
1833                                break;
1834                            case BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE:
1835                                pw.print("over-voltage");
1836                                break;
1837                            case BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE:
1838                                pw.print("failure");
1839                                break;
1840                            default:
1841                                pw.print(oldHealth);
1842                                break;
1843                        }
1844                    }
1845                    if (oldPlug != rec.batteryPlugType) {
1846                        oldPlug = rec.batteryPlugType;
1847                        pw.print(" plug=");
1848                        switch (oldPlug) {
1849                            case 0:
1850                                pw.print("none");
1851                                break;
1852                            case BatteryManager.BATTERY_PLUGGED_AC:
1853                                pw.print("ac");
1854                                break;
1855                            case BatteryManager.BATTERY_PLUGGED_USB:
1856                                pw.print("usb");
1857                                break;
1858                            default:
1859                                pw.print(oldPlug);
1860                                break;
1861                        }
1862                    }
1863                    if (oldTemp != rec.batteryTemperature) {
1864                        oldTemp = rec.batteryTemperature;
1865                        pw.print(" temp=");
1866                        pw.print(oldTemp);
1867                    }
1868                    if (oldVolt != rec.batteryVoltage) {
1869                        oldVolt = rec.batteryVoltage;
1870                        pw.print(" volt=");
1871                        pw.print(oldVolt);
1872                    }
1873                    printBitDescriptions(pw, oldState, rec.states,
1874                            HISTORY_STATE_DESCRIPTIONS);
1875                    pw.println();
1876                }
1877                oldState = rec.states;
1878            }
1879            pw.println("");
1880        }
1881
1882        SparseArray<? extends Uid> uidStats = getUidStats();
1883        final int NU = uidStats.size();
1884        boolean didPid = false;
1885        long nowRealtime = SystemClock.elapsedRealtime();
1886        for (int i=0; i<NU; i++) {
1887            Uid uid = uidStats.valueAt(i);
1888            SparseArray<? extends Uid.Pid> pids = uid.getPidStats();
1889            if (pids != null) {
1890                for (int j=0; j<pids.size(); j++) {
1891                    Uid.Pid pid = pids.valueAt(j);
1892                    if (!didPid) {
1893                        pw.println("Per-PID Stats:");
1894                        didPid = true;
1895                    }
1896                    long time = pid.mWakeSum + (pid.mWakeStart != 0
1897                            ? (nowRealtime - pid.mWakeStart) : 0);
1898                    pw.print("  PID "); pw.print(pids.keyAt(j));
1899                            pw.print(" wake time: ");
1900                            TimeUtils.formatDuration(time, pw);
1901                            pw.println("");
1902                }
1903            }
1904        }
1905        if (didPid) {
1906            pw.println("");
1907        }
1908
1909        pw.println("Statistics since last charge:");
1910        pw.println("  System starts: " + getStartCount()
1911                + ", currently on battery: " + getIsOnBattery());
1912        dumpLocked(pw, "", STATS_SINCE_CHARGED, -1);
1913        pw.println("");
1914        pw.println("Statistics since last unplugged:");
1915        dumpLocked(pw, "", STATS_SINCE_UNPLUGGED, -1);
1916    }
1917
1918    @SuppressWarnings("unused")
1919    public void dumpCheckinLocked(PrintWriter pw, String[] args, List<ApplicationInfo> apps) {
1920        boolean isUnpluggedOnly = false;
1921
1922        for (String arg : args) {
1923            if ("-u".equals(arg)) {
1924                if (LOCAL_LOGV) Log.v("BatteryStats", "Dumping unplugged data");
1925                isUnpluggedOnly = true;
1926            }
1927        }
1928
1929        if (apps != null) {
1930            SparseArray<ArrayList<String>> uids = new SparseArray<ArrayList<String>>();
1931            for (int i=0; i<apps.size(); i++) {
1932                ApplicationInfo ai = apps.get(i);
1933                ArrayList<String> pkgs = uids.get(ai.uid);
1934                if (pkgs == null) {
1935                    pkgs = new ArrayList<String>();
1936                    uids.put(ai.uid, pkgs);
1937                }
1938                pkgs.add(ai.packageName);
1939            }
1940            SparseArray<? extends Uid> uidStats = getUidStats();
1941            final int NU = uidStats.size();
1942            String[] lineArgs = new String[2];
1943            for (int i=0; i<NU; i++) {
1944                int uid = uidStats.keyAt(i);
1945                ArrayList<String> pkgs = uids.get(uid);
1946                if (pkgs != null) {
1947                    for (int j=0; j<pkgs.size(); j++) {
1948                        lineArgs[0] = Integer.toString(uid);
1949                        lineArgs[1] = pkgs.get(j);
1950                        dumpLine(pw, 0 /* uid */, "i" /* category */, UID_DATA,
1951                                (Object[])lineArgs);
1952                    }
1953                }
1954            }
1955        }
1956        if (isUnpluggedOnly) {
1957            dumpCheckinLocked(pw, STATS_SINCE_UNPLUGGED, -1);
1958        }
1959        else {
1960            dumpCheckinLocked(pw, STATS_SINCE_CHARGED, -1);
1961            dumpCheckinLocked(pw, STATS_SINCE_UNPLUGGED, -1);
1962        }
1963    }
1964}
1965