BatteryStats.java revision a7c837f043c1ca0bdecd42645ba7da8c5717566d
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.Collections;
22import java.util.Comparator;
23import java.util.Formatter;
24import java.util.List;
25import java.util.Map;
26
27import android.content.Context;
28import android.content.pm.ApplicationInfo;
29import android.telephony.SignalStrength;
30import android.util.Printer;
31import android.util.SparseArray;
32import android.util.TimeUtils;
33import com.android.internal.os.BatterySipper;
34import com.android.internal.os.BatteryStatsHelper;
35
36/**
37 * A class providing access to battery usage statistics, including information on
38 * wakelocks, processes, packages, and services.  All times are represented in microseconds
39 * except where indicated otherwise.
40 * @hide
41 */
42public abstract class BatteryStats implements Parcelable {
43
44    private static final boolean LOCAL_LOGV = false;
45
46    /** @hide */
47    public static final String SERVICE_NAME = "batterystats";
48
49    /**
50     * A constant indicating a partial wake lock timer.
51     */
52    public static final int WAKE_TYPE_PARTIAL = 0;
53
54    /**
55     * A constant indicating a full wake lock timer.
56     */
57    public static final int WAKE_TYPE_FULL = 1;
58
59    /**
60     * A constant indicating a window wake lock timer.
61     */
62    public static final int WAKE_TYPE_WINDOW = 2;
63
64    /**
65     * A constant indicating a sensor timer.
66     */
67    public static final int SENSOR = 3;
68
69    /**
70     * A constant indicating a a wifi running timer
71     */
72    public static final int WIFI_RUNNING = 4;
73
74    /**
75     * A constant indicating a full wifi lock timer
76     */
77    public static final int FULL_WIFI_LOCK = 5;
78
79    /**
80     * A constant indicating a wifi scan
81     */
82    public static final int WIFI_SCAN = 6;
83
84     /**
85      * A constant indicating a wifi multicast timer
86      */
87     public static final int WIFI_MULTICAST_ENABLED = 7;
88
89    /**
90     * A constant indicating an audio turn on timer
91     */
92    public static final int AUDIO_TURNED_ON = 7;
93
94    /**
95     * A constant indicating a video turn on timer
96     */
97    public static final int VIDEO_TURNED_ON = 8;
98
99    /**
100     * A constant indicating a vibrator on timer
101     */
102    public static final int VIBRATOR_ON = 9;
103
104    /**
105     * A constant indicating a foreground activity timer
106     */
107    public static final int FOREGROUND_ACTIVITY = 10;
108
109    /**
110     * A constant indicating a wifi batched scan is active
111     */
112    public static final int WIFI_BATCHED_SCAN = 11;
113
114    /**
115     * Include all of the data in the stats, including previously saved data.
116     */
117    public static final int STATS_SINCE_CHARGED = 0;
118
119    /**
120     * Include only the last run in the stats.
121     */
122    public static final int STATS_LAST = 1;
123
124    /**
125     * Include only the current run in the stats.
126     */
127    public static final int STATS_CURRENT = 2;
128
129    /**
130     * Include only the run since the last time the device was unplugged in the stats.
131     */
132    public static final int STATS_SINCE_UNPLUGGED = 3;
133
134    // NOTE: Update this list if you add/change any stats above.
135    // These characters are supposed to represent "total", "last", "current",
136    // and "unplugged". They were shortened for efficiency sake.
137    private static final String[] STAT_NAMES = { "t", "l", "c", "u" };
138
139    /**
140     * Bump the version on this if the checkin format changes.
141     */
142    private static final int BATTERY_STATS_CHECKIN_VERSION = 7;
143
144    private static final long BYTES_PER_KB = 1024;
145    private static final long BYTES_PER_MB = 1048576; // 1024^2
146    private static final long BYTES_PER_GB = 1073741824; //1024^3
147
148
149    private static final String UID_DATA = "uid";
150    private static final String APK_DATA = "apk";
151    private static final String PROCESS_DATA = "pr";
152    private static final String SENSOR_DATA = "sr";
153    private static final String VIBRATOR_DATA = "vib";
154    private static final String FOREGROUND_DATA = "fg";
155    private static final String WAKELOCK_DATA = "wl";
156    private static final String KERNEL_WAKELOCK_DATA = "kwl";
157    private static final String NETWORK_DATA = "nt";
158    private static final String USER_ACTIVITY_DATA = "ua";
159    private static final String BATTERY_DATA = "bt";
160    private static final String BATTERY_DISCHARGE_DATA = "dc";
161    private static final String BATTERY_LEVEL_DATA = "lv";
162    private static final String WIFI_DATA = "wfl";
163    private static final String MISC_DATA = "m";
164    private static final String GLOBAL_NETWORK_DATA = "gn";
165    private static final String HISTORY_DATA = "h";
166    private static final String SCREEN_BRIGHTNESS_DATA = "br";
167    private static final String SIGNAL_STRENGTH_TIME_DATA = "sgt";
168    private static final String SIGNAL_SCANNING_TIME_DATA = "sst";
169    private static final String SIGNAL_STRENGTH_COUNT_DATA = "sgc";
170    private static final String DATA_CONNECTION_TIME_DATA = "dct";
171    private static final String DATA_CONNECTION_COUNT_DATA = "dcc";
172    private static final String POWER_USE_SUMMARY_DATA = "pws";
173    private static final String POWER_USE_ITEM_DATA = "pwi";
174
175    private final StringBuilder mFormatBuilder = new StringBuilder(32);
176    private final Formatter mFormatter = new Formatter(mFormatBuilder);
177
178    /**
179     * State for keeping track of counting information.
180     */
181    public static abstract class Counter {
182
183        /**
184         * Returns the count associated with this Counter for the
185         * selected type of statistics.
186         *
187         * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT
188         */
189        public abstract int getCountLocked(int which);
190
191        /**
192         * Temporary for debugging.
193         */
194        public abstract void logState(Printer pw, String prefix);
195    }
196
197    /**
198     * State for keeping track of timing information.
199     */
200    public static abstract class Timer {
201
202        /**
203         * Returns the count associated with this Timer for the
204         * selected type of statistics.
205         *
206         * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT
207         */
208        public abstract int getCountLocked(int which);
209
210        /**
211         * Returns the total time in microseconds associated with this Timer for the
212         * selected type of statistics.
213         *
214         * @param batteryRealtime system realtime on  battery in microseconds
215         * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT
216         * @return a time in microseconds
217         */
218        public abstract long getTotalTimeLocked(long batteryRealtime, int which);
219
220        /**
221         * Temporary for debugging.
222         */
223        public abstract void logState(Printer pw, String prefix);
224    }
225
226    /**
227     * The statistics associated with a particular uid.
228     */
229    public static abstract class Uid {
230
231        /**
232         * Returns a mapping containing wakelock statistics.
233         *
234         * @return a Map from Strings to Uid.Wakelock objects.
235         */
236        public abstract Map<String, ? extends Wakelock> getWakelockStats();
237
238        /**
239         * The statistics associated with a particular wake lock.
240         */
241        public static abstract class Wakelock {
242            public abstract Timer getWakeTime(int type);
243        }
244
245        /**
246         * Returns a mapping containing sensor statistics.
247         *
248         * @return a Map from Integer sensor ids to Uid.Sensor objects.
249         */
250        public abstract Map<Integer, ? extends Sensor> getSensorStats();
251
252        /**
253         * Returns a mapping containing active process data.
254         */
255        public abstract SparseArray<? extends Pid> getPidStats();
256
257        /**
258         * Returns a mapping containing process statistics.
259         *
260         * @return a Map from Strings to Uid.Proc objects.
261         */
262        public abstract Map<String, ? extends Proc> getProcessStats();
263
264        /**
265         * Returns a mapping containing package statistics.
266         *
267         * @return a Map from Strings to Uid.Pkg objects.
268         */
269        public abstract Map<String, ? extends Pkg> getPackageStats();
270
271        /**
272         * {@hide}
273         */
274        public abstract int getUid();
275
276        public abstract void noteWifiRunningLocked();
277        public abstract void noteWifiStoppedLocked();
278        public abstract void noteFullWifiLockAcquiredLocked();
279        public abstract void noteFullWifiLockReleasedLocked();
280        public abstract void noteWifiScanStartedLocked();
281        public abstract void noteWifiScanStoppedLocked();
282        public abstract void noteWifiBatchedScanStartedLocked(int csph);
283        public abstract void noteWifiBatchedScanStoppedLocked();
284        public abstract void noteWifiMulticastEnabledLocked();
285        public abstract void noteWifiMulticastDisabledLocked();
286        public abstract void noteAudioTurnedOnLocked();
287        public abstract void noteAudioTurnedOffLocked();
288        public abstract void noteVideoTurnedOnLocked();
289        public abstract void noteVideoTurnedOffLocked();
290        public abstract void noteActivityResumedLocked();
291        public abstract void noteActivityPausedLocked();
292        public abstract long getWifiRunningTime(long batteryRealtime, int which);
293        public abstract long getFullWifiLockTime(long batteryRealtime, int which);
294        public abstract long getWifiScanTime(long batteryRealtime, int which);
295        public abstract long getWifiBatchedScanTime(int csphBin, long batteryRealtime, int which);
296        public abstract long getWifiMulticastTime(long batteryRealtime,
297                                                  int which);
298        public abstract long getAudioTurnedOnTime(long batteryRealtime, int which);
299        public abstract long getVideoTurnedOnTime(long batteryRealtime, int which);
300        public abstract Timer getForegroundActivityTimer();
301        public abstract Timer getVibratorOnTimer();
302
303        public static final int NUM_WIFI_BATCHED_SCAN_BINS = 5;
304
305        /**
306         * Note that these must match the constants in android.os.PowerManager.
307         * Also, if the user activity types change, the BatteryStatsImpl.VERSION must
308         * also be bumped.
309         */
310        static final String[] USER_ACTIVITY_TYPES = {
311            "other", "button", "touch"
312        };
313
314        public static final int NUM_USER_ACTIVITY_TYPES = 3;
315
316        public abstract void noteUserActivityLocked(int type);
317        public abstract boolean hasUserActivity();
318        public abstract int getUserActivityCount(int type, int which);
319
320        public abstract boolean hasNetworkActivity();
321        public abstract long getNetworkActivityBytes(int type, int which);
322        public abstract long getNetworkActivityPackets(int type, int which);
323
324        public static abstract class Sensor {
325            /*
326             * FIXME: it's not correct to use this magic value because it
327             * could clash with a sensor handle (which are defined by
328             * the sensor HAL, and therefore out of our control
329             */
330            // Magic sensor number for the GPS.
331            public static final int GPS = -10000;
332
333            public abstract int getHandle();
334
335            public abstract Timer getSensorTime();
336        }
337
338        public class Pid {
339            public long mWakeSum;
340            public long mWakeStart;
341        }
342
343        /**
344         * The statistics associated with a particular process.
345         */
346        public static abstract class Proc {
347
348            public static class ExcessivePower {
349                public static final int TYPE_WAKE = 1;
350                public static final int TYPE_CPU = 2;
351
352                public int type;
353                public long overTime;
354                public long usedTime;
355            }
356
357            /**
358             * Returns the total time (in 1/100 sec) spent executing in user code.
359             *
360             * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
361             */
362            public abstract long getUserTime(int which);
363
364            /**
365             * Returns the total time (in 1/100 sec) spent executing in system code.
366             *
367             * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
368             */
369            public abstract long getSystemTime(int which);
370
371            /**
372             * Returns the number of times the process has been started.
373             *
374             * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
375             */
376            public abstract int getStarts(int which);
377
378            /**
379             * Returns the cpu time spent in microseconds while the process was in the foreground.
380             * @param which one of STATS_TOTAL, STATS_LAST, STATS_CURRENT or STATS_UNPLUGGED
381             * @return foreground cpu time in microseconds
382             */
383            public abstract long getForegroundTime(int which);
384
385            /**
386             * Returns the approximate cpu time spent in microseconds, at a certain CPU speed.
387             * @param speedStep the index of the CPU speed. This is not the actual speed of the
388             * CPU.
389             * @param which one of STATS_TOTAL, STATS_LAST, STATS_CURRENT or STATS_UNPLUGGED
390             * @see BatteryStats#getCpuSpeedSteps()
391             */
392            public abstract long getTimeAtCpuSpeedStep(int speedStep, int which);
393
394            public abstract int countExcessivePowers();
395
396            public abstract ExcessivePower getExcessivePower(int i);
397        }
398
399        /**
400         * The statistics associated with a particular package.
401         */
402        public static abstract class Pkg {
403
404            /**
405             * Returns the number of times this package has done something that could wake up the
406             * device from sleep.
407             *
408             * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
409             */
410            public abstract int getWakeups(int which);
411
412            /**
413             * Returns a mapping containing service statistics.
414             */
415            public abstract Map<String, ? extends Serv> getServiceStats();
416
417            /**
418             * The statistics associated with a particular service.
419             */
420            public abstract class Serv {
421
422                /**
423                 * Returns the amount of time spent started.
424                 *
425                 * @param batteryUptime elapsed uptime on battery in microseconds.
426                 * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
427                 * @return
428                 */
429                public abstract long getStartTime(long batteryUptime, int which);
430
431                /**
432                 * Returns the total number of times startService() has been called.
433                 *
434                 * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
435                 */
436                public abstract int getStarts(int which);
437
438                /**
439                 * Returns the total number times the service has been launched.
440                 *
441                 * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
442                 */
443                public abstract int getLaunches(int which);
444            }
445        }
446    }
447
448    public final static class HistoryItem implements Parcelable {
449        static final String TAG = "HistoryItem";
450        static final boolean DEBUG = false;
451
452        public HistoryItem next;
453
454        public long time;
455
456        // The command codes 0-3 can be written with delta updates; all others require
457        // that a full entry be written.
458        public static final byte CMD_UPDATE = 0;
459        public static final byte CMD_EVENT = 1;
460        public static final byte CMD_NULL = -1;
461        public static final byte CMD_START = 4;
462        public static final byte CMD_OVERFLOW = 5;
463
464        public byte cmd = CMD_NULL;
465
466        /**
467         * Return whether the command code is a delta data update.
468         */
469        public static boolean isDeltaData(byte cmd) {
470            return cmd >= 0 && cmd <= 3;
471        }
472
473        /**
474         * Return whether the command code is a delta data update.
475         */
476        public boolean isDeltaData() {
477            return cmd >= 0 && cmd <= 3;
478        }
479
480        public byte batteryLevel;
481        public byte batteryStatus;
482        public byte batteryHealth;
483        public byte batteryPlugType;
484
485        public short batteryTemperature;
486        public char batteryVoltage;
487
488        // Constants from SCREEN_BRIGHTNESS_*
489        public static final int STATE_BRIGHTNESS_SHIFT = 0;
490        public static final int STATE_BRIGHTNESS_MASK = 0x7;
491        // Constants from SIGNAL_STRENGTH_*
492        public static final int STATE_SIGNAL_STRENGTH_SHIFT = 3;
493        public static final int STATE_SIGNAL_STRENGTH_MASK = 0x7 << STATE_SIGNAL_STRENGTH_SHIFT;
494        // Constants from ServiceState.STATE_*
495        public static final int STATE_PHONE_STATE_SHIFT = 6;
496        public static final int STATE_PHONE_STATE_MASK = 0x7 << STATE_PHONE_STATE_SHIFT;
497        // Constants from DATA_CONNECTION_*
498        public static final int STATE_DATA_CONNECTION_SHIFT = 9;
499        public static final int STATE_DATA_CONNECTION_MASK = 0x1f;
500
501        // These states always appear directly in the first int token
502        // of a delta change; they should be ones that change relatively
503        // frequently.
504        public static final int STATE_WAKE_LOCK_FLAG = 1<<30;
505        public static final int STATE_SENSOR_ON_FLAG = 1<<29;
506        public static final int STATE_GPS_ON_FLAG = 1<<28;
507        public static final int STATE_PHONE_SCANNING_FLAG = 1<<27;
508        public static final int STATE_WIFI_RUNNING_FLAG = 1<<26;
509        public static final int STATE_WIFI_FULL_LOCK_FLAG = 1<<25;
510        public static final int STATE_WIFI_SCAN_FLAG = 1<<24;
511        public static final int STATE_WIFI_MULTICAST_ON_FLAG = 1<<23;
512        // These are on the lower bits used for the command; if they change
513        // we need to write another int of data.
514        public static final int STATE_AUDIO_ON_FLAG = 1<<22;
515        public static final int STATE_VIDEO_ON_FLAG = 1<<21;
516        public static final int STATE_SCREEN_ON_FLAG = 1<<20;
517        public static final int STATE_BATTERY_PLUGGED_FLAG = 1<<19;
518        public static final int STATE_PHONE_IN_CALL_FLAG = 1<<18;
519        public static final int STATE_WIFI_ON_FLAG = 1<<17;
520        public static final int STATE_BLUETOOTH_ON_FLAG = 1<<16;
521
522        public static final int MOST_INTERESTING_STATES =
523            STATE_BATTERY_PLUGGED_FLAG | STATE_SCREEN_ON_FLAG
524            | STATE_GPS_ON_FLAG | STATE_PHONE_IN_CALL_FLAG;
525
526        public int states;
527
528        public static final int EVENT_NONE = 0;
529        public static final int EVENT_APP_FOREGROUND = 1;
530
531        // For CMD_EVENT.
532        public int eventCode;
533        public int eventUid;
534        public String eventName;
535
536        public HistoryItem() {
537        }
538
539        public HistoryItem(long time, Parcel src) {
540            this.time = time;
541            readFromParcel(src);
542        }
543
544        public int describeContents() {
545            return 0;
546        }
547
548        public void writeToParcel(Parcel dest, int flags) {
549            dest.writeLong(time);
550            int bat = (((int)cmd)&0xff)
551                    | ((((int)batteryLevel)<<8)&0xff00)
552                    | ((((int)batteryStatus)<<16)&0xf0000)
553                    | ((((int)batteryHealth)<<20)&0xf00000)
554                    | ((((int)batteryPlugType)<<24)&0xf000000);
555            dest.writeInt(bat);
556            bat = (((int)batteryTemperature)&0xffff)
557                    | ((((int)batteryVoltage)<<16)&0xffff0000);
558            dest.writeInt(bat);
559            dest.writeInt(states);
560            if (cmd == CMD_EVENT) {
561                dest.writeInt(eventCode);
562                dest.writeInt(eventUid);
563                dest.writeString(eventName);
564            }
565        }
566
567        public void readFromParcel(Parcel src) {
568            int bat = src.readInt();
569            cmd = (byte)(bat&0xff);
570            batteryLevel = (byte)((bat>>8)&0xff);
571            batteryStatus = (byte)((bat>>16)&0xf);
572            batteryHealth = (byte)((bat>>20)&0xf);
573            batteryPlugType = (byte)((bat>>24)&0xf);
574            bat = src.readInt();
575            batteryTemperature = (short)(bat&0xffff);
576            batteryVoltage = (char)((bat>>16)&0xffff);
577            states = src.readInt();
578            if (cmd == CMD_EVENT) {
579                eventCode = src.readInt();
580                eventUid = src.readInt();
581                eventName = src.readString();
582            } else {
583                eventCode = EVENT_NONE;
584            }
585        }
586
587        public void clear() {
588            time = 0;
589            cmd = CMD_NULL;
590            batteryLevel = 0;
591            batteryStatus = 0;
592            batteryHealth = 0;
593            batteryPlugType = 0;
594            batteryTemperature = 0;
595            batteryVoltage = 0;
596            states = 0;
597            eventCode = EVENT_NONE;
598            eventUid = 0;
599            eventName = null;
600        }
601
602        public void setTo(HistoryItem o) {
603            time = o.time;
604            cmd = o.cmd;
605            batteryLevel = o.batteryLevel;
606            batteryStatus = o.batteryStatus;
607            batteryHealth = o.batteryHealth;
608            batteryPlugType = o.batteryPlugType;
609            batteryTemperature = o.batteryTemperature;
610            batteryVoltage = o.batteryVoltage;
611            states = o.states;
612            eventCode = o.eventCode;
613            eventUid = o.eventUid;
614            eventName = o.eventName;
615        }
616
617        public void setTo(long time, byte cmd, int eventCode, int eventUid, String eventName,
618                HistoryItem o) {
619            this.time = time;
620            this.cmd = cmd;
621            this.eventCode = eventCode;
622            this.eventUid = eventUid;
623            this.eventName = eventName;
624            batteryLevel = o.batteryLevel;
625            batteryStatus = o.batteryStatus;
626            batteryHealth = o.batteryHealth;
627            batteryPlugType = o.batteryPlugType;
628            batteryTemperature = o.batteryTemperature;
629            batteryVoltage = o.batteryVoltage;
630            states = o.states;
631        }
632
633        public boolean sameNonEvent(HistoryItem o) {
634            return batteryLevel == o.batteryLevel
635                    && batteryStatus == o.batteryStatus
636                    && batteryHealth == o.batteryHealth
637                    && batteryPlugType == o.batteryPlugType
638                    && batteryTemperature == o.batteryTemperature
639                    && batteryVoltage == o.batteryVoltage
640                    && states == o.states;
641        }
642
643        public boolean same(HistoryItem o) {
644            if (!sameNonEvent(o) || eventCode != o.eventCode || eventUid != o.eventUid) {
645                return false;
646            }
647            if (eventName == o.eventName) {
648                return true;
649            }
650            return eventName != null && o.eventName != null && eventName.equals(o.eventName);
651        }
652    }
653
654    public static final class BitDescription {
655        public final int mask;
656        public final int shift;
657        public final String name;
658        public final String shortName;
659        public final String[] values;
660        public final String[] shortValues;
661
662        public BitDescription(int mask, String name, String shortName) {
663            this.mask = mask;
664            this.shift = -1;
665            this.name = name;
666            this.shortName = shortName;
667            this.values = null;
668            this.shortValues = null;
669        }
670
671        public BitDescription(int mask, int shift, String name, String shortName,
672                String[] values, String[] shortValues) {
673            this.mask = mask;
674            this.shift = shift;
675            this.name = name;
676            this.shortName = shortName;
677            this.values = values;
678            this.shortValues = shortValues;
679        }
680    }
681
682    public abstract boolean startIteratingHistoryLocked();
683
684    public abstract boolean getNextHistoryLocked(HistoryItem out);
685
686    public abstract void finishIteratingHistoryLocked();
687
688    public abstract boolean startIteratingOldHistoryLocked();
689
690    public abstract boolean getNextOldHistoryLocked(HistoryItem out);
691
692    public abstract void finishIteratingOldHistoryLocked();
693
694    /**
695     * Return the base time offset for the battery history.
696     */
697    public abstract long getHistoryBaseTime();
698
699    /**
700     * Returns the number of times the device has been started.
701     */
702    public abstract int getStartCount();
703
704    /**
705     * Returns the time in microseconds that the screen has been on while the device was
706     * running on battery.
707     *
708     * {@hide}
709     */
710    public abstract long getScreenOnTime(long batteryRealtime, int which);
711
712    public static final int SCREEN_BRIGHTNESS_DARK = 0;
713    public static final int SCREEN_BRIGHTNESS_DIM = 1;
714    public static final int SCREEN_BRIGHTNESS_MEDIUM = 2;
715    public static final int SCREEN_BRIGHTNESS_LIGHT = 3;
716    public static final int SCREEN_BRIGHTNESS_BRIGHT = 4;
717
718    static final String[] SCREEN_BRIGHTNESS_NAMES = {
719        "dark", "dim", "medium", "light", "bright"
720    };
721
722    static final String[] SCREEN_BRIGHTNESS_SHORT_NAMES = {
723        "0", "1", "2", "3", "4"
724    };
725
726    public static final int NUM_SCREEN_BRIGHTNESS_BINS = 5;
727
728    /**
729     * Returns the time in microseconds that the screen has been on with
730     * the given brightness
731     *
732     * {@hide}
733     */
734    public abstract long getScreenBrightnessTime(int brightnessBin,
735            long batteryRealtime, int which);
736
737    public abstract int getInputEventCount(int which);
738
739    /**
740     * Returns the time in microseconds that the phone has been on while the device was
741     * running on battery.
742     *
743     * {@hide}
744     */
745    public abstract long getPhoneOnTime(long batteryRealtime, int which);
746
747    /**
748     * Returns the time in microseconds that the phone has been running with
749     * the given signal strength.
750     *
751     * {@hide}
752     */
753    public abstract long getPhoneSignalStrengthTime(int strengthBin,
754            long batteryRealtime, int which);
755
756    /**
757     * Returns the time in microseconds that the phone has been trying to
758     * acquire a signal.
759     *
760     * {@hide}
761     */
762    public abstract long getPhoneSignalScanningTime(
763            long batteryRealtime, int which);
764
765    /**
766     * Returns the number of times the phone has entered the given signal strength.
767     *
768     * {@hide}
769     */
770    public abstract int getPhoneSignalStrengthCount(int strengthBin, int which);
771
772    public static final int DATA_CONNECTION_NONE = 0;
773    public static final int DATA_CONNECTION_GPRS = 1;
774    public static final int DATA_CONNECTION_EDGE = 2;
775    public static final int DATA_CONNECTION_UMTS = 3;
776    public static final int DATA_CONNECTION_CDMA = 4;
777    public static final int DATA_CONNECTION_EVDO_0 = 5;
778    public static final int DATA_CONNECTION_EVDO_A = 6;
779    public static final int DATA_CONNECTION_1xRTT = 7;
780    public static final int DATA_CONNECTION_HSDPA = 8;
781    public static final int DATA_CONNECTION_HSUPA = 9;
782    public static final int DATA_CONNECTION_HSPA = 10;
783    public static final int DATA_CONNECTION_IDEN = 11;
784    public static final int DATA_CONNECTION_EVDO_B = 12;
785    public static final int DATA_CONNECTION_LTE = 13;
786    public static final int DATA_CONNECTION_EHRPD = 14;
787    public static final int DATA_CONNECTION_HSPAP = 15;
788    public static final int DATA_CONNECTION_OTHER = 16;
789
790    static final String[] DATA_CONNECTION_NAMES = {
791        "none", "gprs", "edge", "umts", "cdma", "evdo_0", "evdo_A",
792        "1xrtt", "hsdpa", "hsupa", "hspa", "iden", "evdo_b", "lte",
793        "ehrpd", "hspap", "other"
794    };
795
796    public static final int NUM_DATA_CONNECTION_TYPES = DATA_CONNECTION_OTHER+1;
797
798    /**
799     * Returns the time in microseconds that the phone has been running with
800     * the given data connection.
801     *
802     * {@hide}
803     */
804    public abstract long getPhoneDataConnectionTime(int dataType,
805            long batteryRealtime, int which);
806
807    /**
808     * Returns the number of times the phone has entered the given data
809     * connection type.
810     *
811     * {@hide}
812     */
813    public abstract int getPhoneDataConnectionCount(int dataType, int which);
814
815    public static final BitDescription[] HISTORY_STATE_DESCRIPTIONS
816            = new BitDescription[] {
817        new BitDescription(HistoryItem.STATE_BATTERY_PLUGGED_FLAG, "plugged", "BP"),
818        new BitDescription(HistoryItem.STATE_SCREEN_ON_FLAG, "screen", "S"),
819        new BitDescription(HistoryItem.STATE_GPS_ON_FLAG, "gps", "g"),
820        new BitDescription(HistoryItem.STATE_PHONE_IN_CALL_FLAG, "phone_in_call", "Pcl"),
821        new BitDescription(HistoryItem.STATE_PHONE_SCANNING_FLAG, "phone_scanning", "Psc"),
822        new BitDescription(HistoryItem.STATE_WIFI_ON_FLAG, "wifi", "W"),
823        new BitDescription(HistoryItem.STATE_WIFI_RUNNING_FLAG, "wifi_running", "Wr"),
824        new BitDescription(HistoryItem.STATE_WIFI_FULL_LOCK_FLAG, "wifi_full_lock", "Wl"),
825        new BitDescription(HistoryItem.STATE_WIFI_SCAN_FLAG, "wifi_scan", "Ws"),
826        new BitDescription(HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG, "wifi_multicast", "Wm"),
827        new BitDescription(HistoryItem.STATE_BLUETOOTH_ON_FLAG, "bluetooth", "b"),
828        new BitDescription(HistoryItem.STATE_AUDIO_ON_FLAG, "audio", "a"),
829        new BitDescription(HistoryItem.STATE_VIDEO_ON_FLAG, "video", "v"),
830        new BitDescription(HistoryItem.STATE_WAKE_LOCK_FLAG, "wake_lock", "w"),
831        new BitDescription(HistoryItem.STATE_SENSOR_ON_FLAG, "sensor", "s"),
832        new BitDescription(HistoryItem.STATE_BRIGHTNESS_MASK,
833                HistoryItem.STATE_BRIGHTNESS_SHIFT, "brightness", "Sb",
834                SCREEN_BRIGHTNESS_NAMES, SCREEN_BRIGHTNESS_SHORT_NAMES),
835        new BitDescription(HistoryItem.STATE_SIGNAL_STRENGTH_MASK,
836                HistoryItem.STATE_SIGNAL_STRENGTH_SHIFT, "signal_strength", "Pss",
837                SignalStrength.SIGNAL_STRENGTH_NAMES, new String[] {
838                    "0", "1", "2", "3", "4"
839        }),
840        new BitDescription(HistoryItem.STATE_PHONE_STATE_MASK,
841                HistoryItem.STATE_PHONE_STATE_SHIFT, "phone_state", "Pst",
842                new String[] {"in", "out", "emergency", "off"},
843                new String[] {"in", "out", "em", "off"}),
844        new BitDescription(HistoryItem.STATE_DATA_CONNECTION_MASK,
845                HistoryItem.STATE_DATA_CONNECTION_SHIFT, "data_conn", "Pcn",
846                DATA_CONNECTION_NAMES, DATA_CONNECTION_NAMES),
847    };
848
849    /**
850     * Returns the time in microseconds that wifi has been on while the device was
851     * running on battery.
852     *
853     * {@hide}
854     */
855    public abstract long getWifiOnTime(long batteryRealtime, int which);
856
857    /**
858     * Returns the time in microseconds that wifi has been on and the driver has
859     * been in the running state while the device was running on battery.
860     *
861     * {@hide}
862     */
863    public abstract long getGlobalWifiRunningTime(long batteryRealtime, int which);
864
865    /**
866     * Returns the time in microseconds that bluetooth has been on while the device was
867     * running on battery.
868     *
869     * {@hide}
870     */
871    public abstract long getBluetoothOnTime(long batteryRealtime, int which);
872
873    public abstract int getBluetoothPingCount();
874
875    public static final int NETWORK_MOBILE_RX_DATA = 0;
876    public static final int NETWORK_MOBILE_TX_DATA = 1;
877    public static final int NETWORK_WIFI_RX_DATA = 2;
878    public static final int NETWORK_WIFI_TX_DATA = 3;
879
880    public static final int NUM_NETWORK_ACTIVITY_TYPES = NETWORK_WIFI_TX_DATA + 1;
881
882    public abstract long getNetworkActivityBytes(int type, int which);
883    public abstract long getNetworkActivityPackets(int type, int which);
884
885    /**
886     * Return whether we are currently running on battery.
887     */
888    public abstract boolean getIsOnBattery();
889
890    /**
891     * Returns a SparseArray containing the statistics for each uid.
892     */
893    public abstract SparseArray<? extends Uid> getUidStats();
894
895    /**
896     * Returns the current battery uptime in microseconds.
897     *
898     * @param curTime the amount of elapsed realtime in microseconds.
899     */
900    public abstract long getBatteryUptime(long curTime);
901
902    /**
903     * @deprecated use getRadioDataUptime
904     */
905    public long getRadioDataUptimeMs() {
906        return getRadioDataUptime() / 1000;
907    }
908
909    /**
910     * Returns the time that the radio was on for data transfers.
911     * @return the uptime in microseconds while unplugged
912     */
913    public abstract long getRadioDataUptime();
914
915    /**
916     * Returns the current battery realtime in microseconds.
917     *
918     * @param curTime the amount of elapsed realtime in microseconds.
919     */
920    public abstract long getBatteryRealtime(long curTime);
921
922    /**
923     * Returns the battery percentage level at the last time the device was unplugged from power, or
924     * the last time it booted on battery power.
925     */
926    public abstract int getDischargeStartLevel();
927
928    /**
929     * Returns the current battery percentage level if we are in a discharge cycle, otherwise
930     * returns the level at the last plug event.
931     */
932    public abstract int getDischargeCurrentLevel();
933
934    /**
935     * Get the amount the battery has discharged since the stats were
936     * last reset after charging, as a lower-end approximation.
937     */
938    public abstract int getLowDischargeAmountSinceCharge();
939
940    /**
941     * Get the amount the battery has discharged since the stats were
942     * last reset after charging, as an upper-end approximation.
943     */
944    public abstract int getHighDischargeAmountSinceCharge();
945
946    /**
947     * Get the amount the battery has discharged while the screen was on,
948     * since the last time power was unplugged.
949     */
950    public abstract int getDischargeAmountScreenOn();
951
952    /**
953     * Get the amount the battery has discharged while the screen was on,
954     * since the last time the device was charged.
955     */
956    public abstract int getDischargeAmountScreenOnSinceCharge();
957
958    /**
959     * Get the amount the battery has discharged while the screen was off,
960     * since the last time power was unplugged.
961     */
962    public abstract int getDischargeAmountScreenOff();
963
964    /**
965     * Get the amount the battery has discharged while the screen was off,
966     * since the last time the device was charged.
967     */
968    public abstract int getDischargeAmountScreenOffSinceCharge();
969
970    /**
971     * Returns the total, last, or current battery uptime in microseconds.
972     *
973     * @param curTime the elapsed realtime in microseconds.
974     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
975     */
976    public abstract long computeBatteryUptime(long curTime, int which);
977
978    /**
979     * Returns the total, last, or current battery realtime in microseconds.
980     *
981     * @param curTime the current elapsed realtime in microseconds.
982     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
983     */
984    public abstract long computeBatteryRealtime(long curTime, int which);
985
986    /**
987     * Returns the total, last, or current uptime in microseconds.
988     *
989     * @param curTime the current elapsed realtime in microseconds.
990     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
991     */
992    public abstract long computeUptime(long curTime, int which);
993
994    /**
995     * Returns the total, last, or current realtime in microseconds.
996     * *
997     * @param curTime the current elapsed realtime in microseconds.
998     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
999     */
1000    public abstract long computeRealtime(long curTime, int which);
1001
1002    public abstract Map<String, ? extends Timer> getKernelWakelockStats();
1003
1004    /** Returns the number of different speeds that the CPU can run at */
1005    public abstract int getCpuSpeedSteps();
1006
1007    public abstract void writeToParcelWithoutUids(Parcel out, int flags);
1008
1009    private final static void formatTimeRaw(StringBuilder out, long seconds) {
1010        long days = seconds / (60 * 60 * 24);
1011        if (days != 0) {
1012            out.append(days);
1013            out.append("d ");
1014        }
1015        long used = days * 60 * 60 * 24;
1016
1017        long hours = (seconds - used) / (60 * 60);
1018        if (hours != 0 || used != 0) {
1019            out.append(hours);
1020            out.append("h ");
1021        }
1022        used += hours * 60 * 60;
1023
1024        long mins = (seconds-used) / 60;
1025        if (mins != 0 || used != 0) {
1026            out.append(mins);
1027            out.append("m ");
1028        }
1029        used += mins * 60;
1030
1031        if (seconds != 0 || used != 0) {
1032            out.append(seconds-used);
1033            out.append("s ");
1034        }
1035    }
1036
1037    private final static void formatTime(StringBuilder sb, long time) {
1038        long sec = time / 100;
1039        formatTimeRaw(sb, sec);
1040        sb.append((time - (sec * 100)) * 10);
1041        sb.append("ms ");
1042    }
1043
1044    private final static void formatTimeMs(StringBuilder sb, long time) {
1045        long sec = time / 1000;
1046        formatTimeRaw(sb, sec);
1047        sb.append(time - (sec * 1000));
1048        sb.append("ms ");
1049    }
1050
1051    private final String formatRatioLocked(long num, long den) {
1052        if (den == 0L) {
1053            return "--%";
1054        }
1055        float perc = ((float)num) / ((float)den) * 100;
1056        mFormatBuilder.setLength(0);
1057        mFormatter.format("%.1f%%", perc);
1058        return mFormatBuilder.toString();
1059    }
1060
1061    private final String formatBytesLocked(long bytes) {
1062        mFormatBuilder.setLength(0);
1063
1064        if (bytes < BYTES_PER_KB) {
1065            return bytes + "B";
1066        } else if (bytes < BYTES_PER_MB) {
1067            mFormatter.format("%.2fKB", bytes / (double) BYTES_PER_KB);
1068            return mFormatBuilder.toString();
1069        } else if (bytes < BYTES_PER_GB){
1070            mFormatter.format("%.2fMB", bytes / (double) BYTES_PER_MB);
1071            return mFormatBuilder.toString();
1072        } else {
1073            mFormatter.format("%.2fGB", bytes / (double) BYTES_PER_GB);
1074            return mFormatBuilder.toString();
1075        }
1076    }
1077
1078    private static long computeWakeLock(Timer timer, long batteryRealtime, int which) {
1079        if (timer != null) {
1080            // Convert from microseconds to milliseconds with rounding
1081            long totalTimeMicros = timer.getTotalTimeLocked(batteryRealtime, which);
1082            long totalTimeMillis = (totalTimeMicros + 500) / 1000;
1083            return totalTimeMillis;
1084        }
1085        return 0;
1086    }
1087
1088    /**
1089     *
1090     * @param sb a StringBuilder object.
1091     * @param timer a Timer object contining the wakelock times.
1092     * @param batteryRealtime the current on-battery time in microseconds.
1093     * @param name the name of the wakelock.
1094     * @param which which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
1095     * @param linePrefix a String to be prepended to each line of output.
1096     * @return the line prefix
1097     */
1098    private static final String printWakeLock(StringBuilder sb, Timer timer,
1099            long batteryRealtime, String name, int which, String linePrefix) {
1100
1101        if (timer != null) {
1102            long totalTimeMillis = computeWakeLock(timer, batteryRealtime, which);
1103
1104            int count = timer.getCountLocked(which);
1105            if (totalTimeMillis != 0) {
1106                sb.append(linePrefix);
1107                formatTimeMs(sb, totalTimeMillis);
1108                if (name != null) {
1109                    sb.append(name);
1110                    sb.append(' ');
1111                }
1112                sb.append('(');
1113                sb.append(count);
1114                sb.append(" times)");
1115                return ", ";
1116            }
1117        }
1118        return linePrefix;
1119    }
1120
1121    /**
1122     * Checkin version of wakelock printer. Prints simple comma-separated list.
1123     *
1124     * @param sb a StringBuilder object.
1125     * @param timer a Timer object contining the wakelock times.
1126     * @param now the current time in microseconds.
1127     * @param name the name of the wakelock.
1128     * @param which which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
1129     * @param linePrefix a String to be prepended to each line of output.
1130     * @return the line prefix
1131     */
1132    private static final String printWakeLockCheckin(StringBuilder sb, Timer timer, long now,
1133            String name, int which, String linePrefix) {
1134        long totalTimeMicros = 0;
1135        int count = 0;
1136        if (timer != null) {
1137            totalTimeMicros = timer.getTotalTimeLocked(now, which);
1138            count = timer.getCountLocked(which);
1139        }
1140        sb.append(linePrefix);
1141        sb.append((totalTimeMicros + 500) / 1000); // microseconds to milliseconds with rounding
1142        sb.append(',');
1143        sb.append(name != null ? name + "," : "");
1144        sb.append(count);
1145        return ",";
1146    }
1147
1148    /**
1149     * Dump a comma-separated line of values for terse checkin mode.
1150     *
1151     * @param pw the PageWriter to dump log to
1152     * @param category category of data (e.g. "total", "last", "unplugged", "current" )
1153     * @param type type of data (e.g. "wakelock", "sensor", "process", "apk" ,  "process", "network")
1154     * @param args type-dependent data arguments
1155     */
1156    private static final void dumpLine(PrintWriter pw, int uid, String category, String type,
1157           Object... args ) {
1158        pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
1159        pw.print(uid); pw.print(',');
1160        pw.print(category); pw.print(',');
1161        pw.print(type);
1162
1163        for (Object arg : args) {
1164            pw.print(',');
1165            pw.print(arg);
1166        }
1167        pw.println();
1168    }
1169
1170    /**
1171     * Checkin server version of dump to produce more compact, computer-readable log.
1172     *
1173     * NOTE: all times are expressed in 'ms'.
1174     */
1175    public final void dumpCheckinLocked(Context context, PrintWriter pw, int which, int reqUid) {
1176        final long rawUptime = SystemClock.uptimeMillis() * 1000;
1177        final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
1178        final long batteryUptime = getBatteryUptime(rawUptime);
1179        final long batteryRealtime = getBatteryRealtime(rawRealtime);
1180        final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
1181        final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
1182        final long totalRealtime = computeRealtime(rawRealtime, which);
1183        final long totalUptime = computeUptime(rawUptime, which);
1184        final long screenOnTime = getScreenOnTime(batteryRealtime, which);
1185        final long phoneOnTime = getPhoneOnTime(batteryRealtime, which);
1186        final long wifiOnTime = getWifiOnTime(batteryRealtime, which);
1187        final long wifiRunningTime = getGlobalWifiRunningTime(batteryRealtime, which);
1188        final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which);
1189
1190        StringBuilder sb = new StringBuilder(128);
1191
1192        SparseArray<? extends Uid> uidStats = getUidStats();
1193        final int NU = uidStats.size();
1194
1195        String category = STAT_NAMES[which];
1196
1197        // Dump "battery" stat
1198        dumpLine(pw, 0 /* uid */, category, BATTERY_DATA,
1199                which == STATS_SINCE_CHARGED ? getStartCount() : "N/A",
1200                whichBatteryRealtime / 1000, whichBatteryUptime / 1000,
1201                totalRealtime / 1000, totalUptime / 1000);
1202
1203        // Calculate wakelock times across all uids.
1204        long fullWakeLockTimeTotal = 0;
1205        long partialWakeLockTimeTotal = 0;
1206
1207        for (int iu = 0; iu < NU; iu++) {
1208            Uid u = uidStats.valueAt(iu);
1209
1210            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
1211            if (wakelocks.size() > 0) {
1212                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
1213                        : wakelocks.entrySet()) {
1214                    Uid.Wakelock wl = ent.getValue();
1215
1216                    Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
1217                    if (fullWakeTimer != null) {
1218                        fullWakeLockTimeTotal += fullWakeTimer.getTotalTimeLocked(batteryRealtime, which);
1219                    }
1220
1221                    Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
1222                    if (partialWakeTimer != null) {
1223                        partialWakeLockTimeTotal += partialWakeTimer.getTotalTimeLocked(
1224                            batteryRealtime, which);
1225                    }
1226                }
1227            }
1228        }
1229
1230        long mobileRxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
1231        long mobileTxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
1232        long wifiRxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
1233        long wifiTxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
1234        long mobileRxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
1235        long mobileTxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
1236        long wifiRxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
1237        long wifiTxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
1238
1239        // Dump network stats
1240        dumpLine(pw, 0 /* uid */, category, GLOBAL_NETWORK_DATA,
1241                mobileRxTotalBytes, mobileTxTotalBytes, wifiRxTotalBytes, wifiTxTotalBytes,
1242                mobileRxTotalPackets, mobileTxTotalPackets, wifiRxTotalPackets, wifiTxTotalPackets);
1243
1244        // Dump misc stats
1245        dumpLine(pw, 0 /* uid */, category, MISC_DATA,
1246                screenOnTime / 1000, phoneOnTime / 1000, wifiOnTime / 1000,
1247                wifiRunningTime / 1000, bluetoothOnTime / 1000,
1248                mobileRxTotalBytes, mobileTxTotalBytes, wifiRxTotalBytes, wifiTxTotalBytes,
1249                fullWakeLockTimeTotal, partialWakeLockTimeTotal,
1250                getInputEventCount(which));
1251
1252        // Dump screen brightness stats
1253        Object[] args = new Object[NUM_SCREEN_BRIGHTNESS_BINS];
1254        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
1255            args[i] = getScreenBrightnessTime(i, batteryRealtime, which) / 1000;
1256        }
1257        dumpLine(pw, 0 /* uid */, category, SCREEN_BRIGHTNESS_DATA, args);
1258
1259        // Dump signal strength stats
1260        args = new Object[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
1261        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
1262            args[i] = getPhoneSignalStrengthTime(i, batteryRealtime, which) / 1000;
1263        }
1264        dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_TIME_DATA, args);
1265        dumpLine(pw, 0 /* uid */, category, SIGNAL_SCANNING_TIME_DATA,
1266                getPhoneSignalScanningTime(batteryRealtime, which) / 1000);
1267        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
1268            args[i] = getPhoneSignalStrengthCount(i, which);
1269        }
1270        dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_COUNT_DATA, args);
1271
1272        // Dump network type stats
1273        args = new Object[NUM_DATA_CONNECTION_TYPES];
1274        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
1275            args[i] = getPhoneDataConnectionTime(i, batteryRealtime, which) / 1000;
1276        }
1277        dumpLine(pw, 0 /* uid */, category, DATA_CONNECTION_TIME_DATA, args);
1278        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
1279            args[i] = getPhoneDataConnectionCount(i, which);
1280        }
1281        dumpLine(pw, 0 /* uid */, category, DATA_CONNECTION_COUNT_DATA, args);
1282
1283        if (which == STATS_SINCE_UNPLUGGED) {
1284            dumpLine(pw, 0 /* uid */, category, BATTERY_LEVEL_DATA, getDischargeStartLevel(),
1285                    getDischargeCurrentLevel());
1286        }
1287
1288        if (which == STATS_SINCE_UNPLUGGED) {
1289            dumpLine(pw, 0 /* uid */, category, BATTERY_DISCHARGE_DATA,
1290                    getDischargeStartLevel()-getDischargeCurrentLevel(),
1291                    getDischargeStartLevel()-getDischargeCurrentLevel(),
1292                    getDischargeAmountScreenOn(), getDischargeAmountScreenOff());
1293        } else {
1294            dumpLine(pw, 0 /* uid */, category, BATTERY_DISCHARGE_DATA,
1295                    getLowDischargeAmountSinceCharge(), getHighDischargeAmountSinceCharge(),
1296                    getDischargeAmountScreenOn(), getDischargeAmountScreenOff());
1297        }
1298
1299        if (reqUid < 0) {
1300            Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats();
1301            if (kernelWakelocks.size() > 0) {
1302                for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) {
1303                    sb.setLength(0);
1304                    printWakeLockCheckin(sb, ent.getValue(), batteryRealtime, null, which, "");
1305
1306                    dumpLine(pw, 0 /* uid */, category, KERNEL_WAKELOCK_DATA, ent.getKey(),
1307                            sb.toString());
1308                }
1309            }
1310        }
1311
1312        BatteryStatsHelper helper = new BatteryStatsHelper(context);
1313        helper.create(this);
1314        helper.refreshStats(which, UserHandle.USER_ALL);
1315        List<BatterySipper> sippers = helper.getUsageList();
1316        if (sippers != null && sippers.size() > 0) {
1317            dumpLine(pw, 0 /* uid */, category, POWER_USE_SUMMARY_DATA,
1318                    BatteryStatsHelper.makemAh(helper.getPowerProfile().getBatteryCapacity()),
1319                    BatteryStatsHelper.makemAh(helper.getTotalPower()),
1320                    BatteryStatsHelper.makemAh(helper.getMinDrainedPower()),
1321                    BatteryStatsHelper.makemAh(helper.getMaxDrainedPower()));
1322            for (int i=0; i<sippers.size(); i++) {
1323                BatterySipper bs = sippers.get(i);
1324                int uid = 0;
1325                String label;
1326                switch (bs.drainType) {
1327                    case IDLE:
1328                        label="idle";
1329                        break;
1330                    case CELL:
1331                        label="cell";
1332                        break;
1333                    case PHONE:
1334                        label="phone";
1335                        break;
1336                    case WIFI:
1337                        label="wifi";
1338                        break;
1339                    case BLUETOOTH:
1340                        label="blue";
1341                        break;
1342                    case SCREEN:
1343                        label="scrn";
1344                        break;
1345                    case APP:
1346                        uid = bs.uidObj.getUid();
1347                        label = "uid";
1348                        break;
1349                    case USER:
1350                        uid = UserHandle.getUid(bs.userId, 0);
1351                        label = "user";
1352                        break;
1353                    case UNACCOUNTED:
1354                        label = "unacc";
1355                        break;
1356                    case OVERCOUNTED:
1357                        label = "over";
1358                        break;
1359                    default:
1360                        label = "???";
1361                }
1362                dumpLine(pw, uid, category, POWER_USE_ITEM_DATA, label,
1363                        BatteryStatsHelper.makemAh(bs.value));
1364            }
1365        }
1366
1367        for (int iu = 0; iu < NU; iu++) {
1368            final int uid = uidStats.keyAt(iu);
1369            if (reqUid >= 0 && uid != reqUid) {
1370                continue;
1371            }
1372            Uid u = uidStats.valueAt(iu);
1373            // Dump Network stats per uid, if any
1374            long mobileBytesRx = u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
1375            long mobileBytesTx = u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
1376            long wifiBytesRx = u.getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
1377            long wifiBytesTx = u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
1378            long mobilePacketsRx = u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
1379            long mobilePacketsTx = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
1380            long wifiPacketsRx = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
1381            long wifiPacketsTx = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
1382            long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
1383            long wifiScanTime = u.getWifiScanTime(batteryRealtime, which);
1384            long uidWifiRunningTime = u.getWifiRunningTime(batteryRealtime, which);
1385
1386            if (mobileBytesRx > 0 || mobileBytesTx > 0 || wifiBytesRx > 0 || wifiBytesTx > 0
1387                    || mobilePacketsRx > 0 || mobilePacketsTx > 0 || wifiPacketsRx > 0
1388                    || wifiPacketsTx > 0) {
1389                dumpLine(pw, uid, category, NETWORK_DATA, mobileBytesRx, mobileBytesTx,
1390                        wifiBytesRx, wifiBytesTx,
1391                        mobilePacketsRx, mobilePacketsTx,
1392                        wifiPacketsRx, wifiPacketsTx);
1393            }
1394
1395            if (fullWifiLockOnTime != 0 || wifiScanTime != 0
1396                    || uidWifiRunningTime != 0) {
1397                dumpLine(pw, uid, category, WIFI_DATA,
1398                        fullWifiLockOnTime, wifiScanTime, uidWifiRunningTime);
1399            }
1400
1401            if (u.hasUserActivity()) {
1402                args = new Object[Uid.NUM_USER_ACTIVITY_TYPES];
1403                boolean hasData = false;
1404                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
1405                    int val = u.getUserActivityCount(i, which);
1406                    args[i] = val;
1407                    if (val != 0) hasData = true;
1408                }
1409                if (hasData) {
1410                    dumpLine(pw, 0 /* uid */, category, USER_ACTIVITY_DATA, args);
1411                }
1412            }
1413
1414            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
1415            if (wakelocks.size() > 0) {
1416                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
1417                        : wakelocks.entrySet()) {
1418                    Uid.Wakelock wl = ent.getValue();
1419                    String linePrefix = "";
1420                    sb.setLength(0);
1421                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_FULL),
1422                            batteryRealtime, "f", which, linePrefix);
1423                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL),
1424                            batteryRealtime, "p", which, linePrefix);
1425                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_WINDOW),
1426                            batteryRealtime, "w", which, linePrefix);
1427
1428                    // Only log if we had at lease one wakelock...
1429                    if (sb.length() > 0) {
1430                        String name = ent.getKey();
1431                        if (name.indexOf(',') >= 0) {
1432                            name = name.replace(',', '_');
1433                        }
1434                        dumpLine(pw, uid, category, WAKELOCK_DATA, name, sb.toString());
1435                    }
1436                }
1437            }
1438
1439            Map<Integer, ? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
1440            if (sensors.size() > 0)  {
1441                for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> ent
1442                        : sensors.entrySet()) {
1443                    Uid.Sensor se = ent.getValue();
1444                    int sensorNumber = ent.getKey();
1445                    Timer timer = se.getSensorTime();
1446                    if (timer != null) {
1447                        // Convert from microseconds to milliseconds with rounding
1448                        long totalTime = (timer.getTotalTimeLocked(batteryRealtime, which) + 500) / 1000;
1449                        int count = timer.getCountLocked(which);
1450                        if (totalTime != 0) {
1451                            dumpLine(pw, uid, category, SENSOR_DATA, sensorNumber, totalTime, count);
1452                        }
1453                    }
1454                }
1455            }
1456
1457            Timer vibTimer = u.getVibratorOnTimer();
1458            if (vibTimer != null) {
1459                // Convert from microseconds to milliseconds with rounding
1460                long totalTime = (vibTimer.getTotalTimeLocked(batteryRealtime, which) + 500) / 1000;
1461                int count = vibTimer.getCountLocked(which);
1462                if (totalTime != 0) {
1463                    dumpLine(pw, uid, category, VIBRATOR_DATA, totalTime, count);
1464                }
1465            }
1466
1467            Timer fgTimer = u.getForegroundActivityTimer();
1468            if (fgTimer != null) {
1469                // Convert from microseconds to milliseconds with rounding
1470                long totalTime = (fgTimer.getTotalTimeLocked(batteryRealtime, which) + 500) / 1000;
1471                int count = fgTimer.getCountLocked(which);
1472                if (totalTime != 0) {
1473                    dumpLine(pw, uid, category, FOREGROUND_DATA, totalTime, count);
1474                }
1475            }
1476
1477            Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
1478            if (processStats.size() > 0) {
1479                for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
1480                        : processStats.entrySet()) {
1481                    Uid.Proc ps = ent.getValue();
1482
1483                    final long userMillis = ps.getUserTime(which) * 10;
1484                    final long systemMillis = ps.getSystemTime(which) * 10;
1485                    final long foregroundMillis = ps.getForegroundTime(which) * 10;
1486                    final long starts = ps.getStarts(which);
1487
1488                    if (userMillis != 0 || systemMillis != 0 || foregroundMillis != 0
1489                            || starts != 0) {
1490                        dumpLine(pw, uid, category, PROCESS_DATA, ent.getKey(), userMillis,
1491                                systemMillis, foregroundMillis, starts);
1492                    }
1493                }
1494            }
1495
1496            Map<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats();
1497            if (packageStats.size() > 0) {
1498                for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent
1499                        : packageStats.entrySet()) {
1500
1501                    Uid.Pkg ps = ent.getValue();
1502                    int wakeups = ps.getWakeups(which);
1503                    Map<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
1504                    for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent
1505                            : serviceStats.entrySet()) {
1506                        BatteryStats.Uid.Pkg.Serv ss = sent.getValue();
1507                        long startTime = ss.getStartTime(batteryUptime, which);
1508                        int starts = ss.getStarts(which);
1509                        int launches = ss.getLaunches(which);
1510                        if (startTime != 0 || starts != 0 || launches != 0) {
1511                            dumpLine(pw, uid, category, APK_DATA,
1512                                    wakeups, // wakeup alarms
1513                                    ent.getKey(), // Apk
1514                                    sent.getKey(), // service
1515                                    startTime / 1000, // time spent started, in ms
1516                                    starts,
1517                                    launches);
1518                        }
1519                    }
1520                }
1521            }
1522        }
1523    }
1524
1525    static final class TimerEntry {
1526        final String mName;
1527        final int mId;
1528        final BatteryStats.Timer mTimer;
1529        final long mTime;
1530        TimerEntry(String name, int id, BatteryStats.Timer timer, long time) {
1531            mName = name;
1532            mId = id;
1533            mTimer = timer;
1534            mTime = time;
1535        }
1536    }
1537
1538    private void printmAh(PrintWriter printer, double power) {
1539        printer.print(BatteryStatsHelper.makemAh(power));
1540    }
1541
1542    @SuppressWarnings("unused")
1543    public final void dumpLocked(Context context, PrintWriter pw, String prefix, final int which,
1544            int reqUid) {
1545        final long rawUptime = SystemClock.uptimeMillis() * 1000;
1546        final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
1547        final long batteryUptime = getBatteryUptime(rawUptime);
1548        final long batteryRealtime = getBatteryRealtime(rawRealtime);
1549
1550        final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
1551        final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
1552        final long totalRealtime = computeRealtime(rawRealtime, which);
1553        final long totalUptime = computeUptime(rawUptime, which);
1554
1555        StringBuilder sb = new StringBuilder(128);
1556
1557        SparseArray<? extends Uid> uidStats = getUidStats();
1558        final int NU = uidStats.size();
1559
1560        sb.setLength(0);
1561        sb.append(prefix);
1562                sb.append("  Time on battery: ");
1563                formatTimeMs(sb, whichBatteryRealtime / 1000); sb.append("(");
1564                sb.append(formatRatioLocked(whichBatteryRealtime, totalRealtime));
1565                sb.append(") realtime, ");
1566                formatTimeMs(sb, whichBatteryUptime / 1000);
1567                sb.append("("); sb.append(formatRatioLocked(whichBatteryUptime, totalRealtime));
1568                sb.append(") uptime");
1569        pw.println(sb.toString());
1570        sb.setLength(0);
1571        sb.append(prefix);
1572                sb.append("  Total run time: ");
1573                formatTimeMs(sb, totalRealtime / 1000);
1574                sb.append("realtime, ");
1575                formatTimeMs(sb, totalUptime / 1000);
1576                sb.append("uptime, ");
1577        pw.println(sb.toString());
1578
1579        final long screenOnTime = getScreenOnTime(batteryRealtime, which);
1580        final long phoneOnTime = getPhoneOnTime(batteryRealtime, which);
1581        final long wifiRunningTime = getGlobalWifiRunningTime(batteryRealtime, which);
1582        final long wifiOnTime = getWifiOnTime(batteryRealtime, which);
1583        final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which);
1584        sb.setLength(0);
1585        sb.append(prefix);
1586                sb.append("  Screen on: "); formatTimeMs(sb, screenOnTime / 1000);
1587                sb.append("("); sb.append(formatRatioLocked(screenOnTime, whichBatteryRealtime));
1588                sb.append("), Input events: "); sb.append(getInputEventCount(which));
1589                sb.append(", Active phone call: "); formatTimeMs(sb, phoneOnTime / 1000);
1590                sb.append("("); sb.append(formatRatioLocked(phoneOnTime, whichBatteryRealtime));
1591                sb.append(")");
1592        pw.println(sb.toString());
1593        sb.setLength(0);
1594        sb.append(prefix);
1595        sb.append("  Screen brightnesses: ");
1596        boolean didOne = false;
1597        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
1598            final long time = getScreenBrightnessTime(i, batteryRealtime, which);
1599            if (time == 0) {
1600                continue;
1601            }
1602            if (didOne) sb.append(", ");
1603            didOne = true;
1604            sb.append(SCREEN_BRIGHTNESS_NAMES[i]);
1605            sb.append(" ");
1606            formatTimeMs(sb, time/1000);
1607            sb.append("(");
1608            sb.append(formatRatioLocked(time, screenOnTime));
1609            sb.append(")");
1610        }
1611        if (!didOne) sb.append("No activity");
1612        pw.println(sb.toString());
1613
1614        // Calculate wakelock times across all uids.
1615        long fullWakeLockTimeTotalMicros = 0;
1616        long partialWakeLockTimeTotalMicros = 0;
1617
1618        final Comparator<TimerEntry> timerComparator = new Comparator<TimerEntry>() {
1619            @Override
1620            public int compare(TimerEntry lhs, TimerEntry rhs) {
1621                long lhsTime = lhs.mTime;
1622                long rhsTime = rhs.mTime;
1623                if (lhsTime < rhsTime) {
1624                    return 1;
1625                }
1626                if (lhsTime > rhsTime) {
1627                    return -1;
1628                }
1629                return 0;
1630            }
1631        };
1632
1633        if (reqUid < 0) {
1634            Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats();
1635            if (kernelWakelocks.size() > 0) {
1636                final ArrayList<TimerEntry> timers = new ArrayList<TimerEntry>();
1637                for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) {
1638                    BatteryStats.Timer timer = ent.getValue();
1639                    long totalTimeMillis = computeWakeLock(timer, batteryRealtime, which);
1640                    if (totalTimeMillis > 0) {
1641                        timers.add(new TimerEntry(ent.getKey(), 0, timer, totalTimeMillis));
1642                    }
1643                }
1644                Collections.sort(timers, timerComparator);
1645                for (int i=0; i<timers.size(); i++) {
1646                    TimerEntry timer = timers.get(i);
1647                    String linePrefix = ": ";
1648                    sb.setLength(0);
1649                    sb.append(prefix);
1650                    sb.append("  Kernel Wake lock ");
1651                    sb.append(timer.mName);
1652                    linePrefix = printWakeLock(sb, timer.mTimer, batteryRealtime, null,
1653                            which, linePrefix);
1654                    if (!linePrefix.equals(": ")) {
1655                        sb.append(" realtime");
1656                        // Only print out wake locks that were held
1657                        pw.println(sb.toString());
1658                    }
1659                }
1660            }
1661        }
1662
1663        final ArrayList<TimerEntry> timers = new ArrayList<TimerEntry>();
1664
1665        for (int iu = 0; iu < NU; iu++) {
1666            Uid u = uidStats.valueAt(iu);
1667
1668            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
1669            if (wakelocks.size() > 0) {
1670                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
1671                        : wakelocks.entrySet()) {
1672                    Uid.Wakelock wl = ent.getValue();
1673
1674                    Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
1675                    if (fullWakeTimer != null) {
1676                        fullWakeLockTimeTotalMicros += fullWakeTimer.getTotalTimeLocked(
1677                                batteryRealtime, which);
1678                    }
1679
1680                    Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
1681                    if (partialWakeTimer != null) {
1682                        long totalTimeMicros = partialWakeTimer.getTotalTimeLocked(
1683                                batteryRealtime, which);
1684                        if (totalTimeMicros > 0) {
1685                            if (reqUid < 0) {
1686                                // Only show the ordered list of all wake
1687                                // locks if the caller is not asking for data
1688                                // about a specific uid.
1689                                timers.add(new TimerEntry(ent.getKey(), u.getUid(),
1690                                        partialWakeTimer, totalTimeMicros));
1691                            }
1692                            partialWakeLockTimeTotalMicros += totalTimeMicros;
1693                        }
1694                    }
1695                }
1696            }
1697        }
1698
1699        long mobileRxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
1700        long mobileTxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
1701        long wifiRxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
1702        long wifiTxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
1703        long mobileRxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
1704        long mobileTxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
1705        long wifiRxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
1706        long wifiTxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
1707
1708        pw.print(prefix);
1709                pw.print("  Mobile total received: "); pw.print(formatBytesLocked(mobileRxTotalBytes));
1710                pw.print(", sent: "); pw.print(formatBytesLocked(mobileTxTotalBytes));
1711                pw.print(" (packets received "); pw.print(mobileRxTotalPackets);
1712                pw.print(", sent "); pw.print(mobileTxTotalPackets); pw.println(")");
1713        pw.print(prefix);
1714                pw.print("  Wi-Fi total received: "); pw.print(formatBytesLocked(wifiRxTotalBytes));
1715                pw.print(", sent: "); pw.print(formatBytesLocked(wifiTxTotalBytes));
1716                pw.print(" (packets received "); pw.print(wifiRxTotalPackets);
1717                pw.print(", sent "); pw.print(wifiTxTotalPackets); pw.println(")");
1718        sb.setLength(0);
1719        sb.append(prefix);
1720                sb.append("  Total full wakelock time: "); formatTimeMs(sb,
1721                        (fullWakeLockTimeTotalMicros + 500) / 1000);
1722                sb.append(", Total partial wakelock time: "); formatTimeMs(sb,
1723                        (partialWakeLockTimeTotalMicros + 500) / 1000);
1724        pw.println(sb.toString());
1725
1726        sb.setLength(0);
1727        sb.append(prefix);
1728        sb.append("  Signal levels: ");
1729        didOne = false;
1730        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
1731            final long time = getPhoneSignalStrengthTime(i, batteryRealtime, which);
1732            if (time == 0) {
1733                continue;
1734            }
1735            if (didOne) sb.append(", ");
1736            didOne = true;
1737            sb.append(SignalStrength.SIGNAL_STRENGTH_NAMES[i]);
1738            sb.append(" ");
1739            formatTimeMs(sb, time/1000);
1740            sb.append("(");
1741            sb.append(formatRatioLocked(time, whichBatteryRealtime));
1742            sb.append(") ");
1743            sb.append(getPhoneSignalStrengthCount(i, which));
1744            sb.append("x");
1745        }
1746        if (!didOne) sb.append("No activity");
1747        pw.println(sb.toString());
1748
1749        sb.setLength(0);
1750        sb.append(prefix);
1751        sb.append("  Signal scanning time: ");
1752        formatTimeMs(sb, getPhoneSignalScanningTime(batteryRealtime, which) / 1000);
1753        pw.println(sb.toString());
1754
1755        sb.setLength(0);
1756        sb.append(prefix);
1757        sb.append("  Radio types: ");
1758        didOne = false;
1759        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
1760            final long time = getPhoneDataConnectionTime(i, batteryRealtime, which);
1761            if (time == 0) {
1762                continue;
1763            }
1764            if (didOne) sb.append(", ");
1765            didOne = true;
1766            sb.append(DATA_CONNECTION_NAMES[i]);
1767            sb.append(" ");
1768            formatTimeMs(sb, time/1000);
1769            sb.append("(");
1770            sb.append(formatRatioLocked(time, whichBatteryRealtime));
1771            sb.append(") ");
1772            sb.append(getPhoneDataConnectionCount(i, which));
1773            sb.append("x");
1774        }
1775        if (!didOne) sb.append("No activity");
1776        pw.println(sb.toString());
1777
1778        sb.setLength(0);
1779        sb.append(prefix);
1780        sb.append("  Radio data uptime when unplugged: ");
1781        sb.append(getRadioDataUptime() / 1000);
1782        sb.append(" ms");
1783        pw.println(sb.toString());
1784
1785        sb.setLength(0);
1786        sb.append(prefix);
1787                sb.append("  Wifi on: "); formatTimeMs(sb, wifiOnTime / 1000);
1788                sb.append("("); sb.append(formatRatioLocked(wifiOnTime, whichBatteryRealtime));
1789                sb.append("), Wifi running: "); formatTimeMs(sb, wifiRunningTime / 1000);
1790                sb.append("("); sb.append(formatRatioLocked(wifiRunningTime, whichBatteryRealtime));
1791                sb.append("), Bluetooth on: "); formatTimeMs(sb, bluetoothOnTime / 1000);
1792                sb.append("("); sb.append(formatRatioLocked(bluetoothOnTime, whichBatteryRealtime));
1793                sb.append(")");
1794        pw.println(sb.toString());
1795
1796        pw.println(" ");
1797
1798        if (which == STATS_SINCE_UNPLUGGED) {
1799            if (getIsOnBattery()) {
1800                pw.print(prefix); pw.println("  Device is currently unplugged");
1801                pw.print(prefix); pw.print("    Discharge cycle start level: ");
1802                        pw.println(getDischargeStartLevel());
1803                pw.print(prefix); pw.print("    Discharge cycle current level: ");
1804                        pw.println(getDischargeCurrentLevel());
1805            } else {
1806                pw.print(prefix); pw.println("  Device is currently plugged into power");
1807                pw.print(prefix); pw.print("    Last discharge cycle start level: ");
1808                        pw.println(getDischargeStartLevel());
1809                pw.print(prefix); pw.print("    Last discharge cycle end level: ");
1810                        pw.println(getDischargeCurrentLevel());
1811            }
1812            pw.print(prefix); pw.print("    Amount discharged while screen on: ");
1813                    pw.println(getDischargeAmountScreenOn());
1814            pw.print(prefix); pw.print("    Amount discharged while screen off: ");
1815                    pw.println(getDischargeAmountScreenOff());
1816            pw.println(" ");
1817        } else {
1818            pw.print(prefix); pw.println("  Device battery use since last full charge");
1819            pw.print(prefix); pw.print("    Amount discharged (lower bound): ");
1820                    pw.println(getLowDischargeAmountSinceCharge());
1821            pw.print(prefix); pw.print("    Amount discharged (upper bound): ");
1822                    pw.println(getHighDischargeAmountSinceCharge());
1823            pw.print(prefix); pw.print("    Amount discharged while screen on: ");
1824                    pw.println(getDischargeAmountScreenOnSinceCharge());
1825            pw.print(prefix); pw.print("    Amount discharged while screen off: ");
1826                    pw.println(getDischargeAmountScreenOffSinceCharge());
1827            pw.println();
1828        }
1829
1830        BatteryStatsHelper helper = new BatteryStatsHelper(context);
1831        helper.create(this);
1832        helper.refreshStats(which, UserHandle.USER_ALL);
1833        List<BatterySipper> sippers = helper.getUsageList();
1834        if (sippers != null && sippers.size() > 0) {
1835            pw.print(prefix); pw.println("  Estimated power use (mAh):");
1836            pw.print(prefix); pw.print("    Capacity: ");
1837                    printmAh(pw, helper.getPowerProfile().getBatteryCapacity());
1838                    pw.print(", Computed drain: "); printmAh(pw, helper.getTotalPower());
1839                    pw.print(", Min drain: "); printmAh(pw, helper.getMinDrainedPower());
1840                    pw.print(", Max drain: "); printmAh(pw, helper.getMaxDrainedPower());
1841                    pw.println();
1842            for (int i=0; i<sippers.size(); i++) {
1843                BatterySipper bs = sippers.get(i);
1844                switch (bs.drainType) {
1845                    case IDLE:
1846                        pw.print(prefix); pw.print("    Idle: "); printmAh(pw, bs.value);
1847                        pw.println();
1848                        break;
1849                    case CELL:
1850                        pw.print(prefix); pw.print("    Cell standby: "); printmAh(pw, bs.value);
1851                        pw.println();
1852                        break;
1853                    case PHONE:
1854                        pw.print(prefix); pw.print("    Phone calls: "); printmAh(pw, bs.value);
1855                        pw.println();
1856                        break;
1857                    case WIFI:
1858                        pw.print(prefix); pw.print("    Wifi: "); printmAh(pw, bs.value);
1859                        pw.println();
1860                        break;
1861                    case BLUETOOTH:
1862                        pw.print(prefix); pw.print("    Bluetooth: "); printmAh(pw, bs.value);
1863                        pw.println();
1864                        break;
1865                    case SCREEN:
1866                        pw.print(prefix); pw.print("    Screen: "); printmAh(pw, bs.value);
1867                        pw.println();
1868                        break;
1869                    case APP:
1870                        pw.print(prefix); pw.print("    Uid "); pw.print(bs.uidObj.getUid());
1871                        pw.print(": "); printmAh(pw, bs.value); pw.println();
1872                        break;
1873                    case USER:
1874                        pw.print(prefix); pw.print("    User "); pw.print(bs.userId);
1875                        pw.print(": "); printmAh(pw, bs.value); pw.println();
1876                        break;
1877                    case UNACCOUNTED:
1878                        pw.print(prefix); pw.print("    Unaccounted: "); printmAh(pw, bs.value);
1879                        pw.println();
1880                        break;
1881                    case OVERCOUNTED:
1882                        pw.print(prefix); pw.print("    Over-counted: "); printmAh(pw, bs.value);
1883                        pw.println();
1884                        break;
1885                }
1886            }
1887        }
1888
1889        if (timers.size() > 0) {
1890            Collections.sort(timers, timerComparator);
1891            pw.print(prefix); pw.println("  All partial wake locks:");
1892            for (int i=0; i<timers.size(); i++) {
1893                TimerEntry timer = timers.get(i);
1894                sb.setLength(0);
1895                sb.append("  Wake lock ");
1896                UserHandle.formatUid(sb, timer.mId);
1897                sb.append(" ");
1898                sb.append(timer.mName);
1899                printWakeLock(sb, timer.mTimer, batteryRealtime, null, which, ": ");
1900                sb.append(" realtime");
1901                pw.println(sb.toString());
1902            }
1903            timers.clear();
1904            pw.println();
1905        }
1906
1907        for (int iu=0; iu<NU; iu++) {
1908            final int uid = uidStats.keyAt(iu);
1909            if (reqUid >= 0 && uid != reqUid && uid != Process.SYSTEM_UID) {
1910                continue;
1911            }
1912
1913            Uid u = uidStats.valueAt(iu);
1914
1915            pw.print(prefix);
1916            pw.print("  ");
1917            UserHandle.formatUid(pw, uid);
1918            pw.println(":");
1919            boolean uidActivity = false;
1920
1921            long mobileRxBytes = u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
1922            long mobileTxBytes = u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
1923            long wifiRxBytes = u.getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
1924            long wifiTxBytes = u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
1925            long mobileRxPackets = u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
1926            long mobileTxPackets = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
1927            long wifiRxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
1928            long wifiTxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
1929            long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
1930            long wifiScanTime = u.getWifiScanTime(batteryRealtime, which);
1931            long uidWifiRunningTime = u.getWifiRunningTime(batteryRealtime, which);
1932
1933            if (mobileRxBytes > 0 || mobileTxBytes > 0
1934                    || mobileRxPackets > 0 || mobileTxPackets > 0) {
1935                pw.print(prefix); pw.print("    Mobile network: ");
1936                        pw.print(formatBytesLocked(mobileRxBytes)); pw.print(" received, ");
1937                        pw.print(formatBytesLocked(mobileTxBytes));
1938                        pw.print(" sent (packets "); pw.print(mobileRxPackets);
1939                        pw.print(" received, "); pw.print(mobileTxPackets); pw.println(" sent)");
1940            }
1941            if (wifiRxBytes > 0 || wifiTxBytes > 0 || wifiRxPackets > 0 || wifiTxPackets > 0) {
1942                pw.print(prefix); pw.print("    Wi-Fi network: ");
1943                        pw.print(formatBytesLocked(wifiRxBytes)); pw.print(" received, ");
1944                        pw.print(formatBytesLocked(wifiTxBytes));
1945                        pw.print(" sent (packets "); pw.print(wifiRxPackets);
1946                        pw.print(" received, "); pw.print(wifiTxPackets); pw.println(" sent)");
1947            }
1948
1949            if (u.hasUserActivity()) {
1950                boolean hasData = false;
1951                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
1952                    int val = u.getUserActivityCount(i, which);
1953                    if (val != 0) {
1954                        if (!hasData) {
1955                            sb.setLength(0);
1956                            sb.append("    User activity: ");
1957                            hasData = true;
1958                        } else {
1959                            sb.append(", ");
1960                        }
1961                        sb.append(val);
1962                        sb.append(" ");
1963                        sb.append(Uid.USER_ACTIVITY_TYPES[i]);
1964                    }
1965                }
1966                if (hasData) {
1967                    pw.println(sb.toString());
1968                }
1969            }
1970
1971            if (fullWifiLockOnTime != 0 || wifiScanTime != 0
1972                    || uidWifiRunningTime != 0) {
1973                sb.setLength(0);
1974                sb.append(prefix); sb.append("    Wifi Running: ");
1975                        formatTimeMs(sb, uidWifiRunningTime / 1000);
1976                        sb.append("("); sb.append(formatRatioLocked(uidWifiRunningTime,
1977                                whichBatteryRealtime)); sb.append(")\n");
1978                sb.append(prefix); sb.append("    Full Wifi Lock: ");
1979                        formatTimeMs(sb, fullWifiLockOnTime / 1000);
1980                        sb.append("("); sb.append(formatRatioLocked(fullWifiLockOnTime,
1981                                whichBatteryRealtime)); sb.append(")\n");
1982                sb.append(prefix); sb.append("    Wifi Scan: ");
1983                        formatTimeMs(sb, wifiScanTime / 1000);
1984                        sb.append("("); sb.append(formatRatioLocked(wifiScanTime,
1985                                whichBatteryRealtime)); sb.append(")");
1986                pw.println(sb.toString());
1987            }
1988
1989            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
1990            if (wakelocks.size() > 0) {
1991                long totalFull = 0, totalPartial = 0, totalWindow = 0;
1992                int count = 0;
1993                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
1994                    : wakelocks.entrySet()) {
1995                    Uid.Wakelock wl = ent.getValue();
1996                    String linePrefix = ": ";
1997                    sb.setLength(0);
1998                    sb.append(prefix);
1999                    sb.append("    Wake lock ");
2000                    sb.append(ent.getKey());
2001                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_FULL), batteryRealtime,
2002                            "full", which, linePrefix);
2003                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), batteryRealtime,
2004                            "partial", which, linePrefix);
2005                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), batteryRealtime,
2006                            "window", which, linePrefix);
2007                    if (!linePrefix.equals(": ")) {
2008                        sb.append(" realtime");
2009                        // Only print out wake locks that were held
2010                        pw.println(sb.toString());
2011                        uidActivity = true;
2012                        count++;
2013                    }
2014                    totalFull += computeWakeLock(wl.getWakeTime(WAKE_TYPE_FULL),
2015                            batteryRealtime, which);
2016                    totalPartial += computeWakeLock(wl.getWakeTime(WAKE_TYPE_PARTIAL),
2017                            batteryRealtime, which);
2018                    totalWindow += computeWakeLock(wl.getWakeTime(WAKE_TYPE_WINDOW),
2019                            batteryRealtime, which);
2020                }
2021                if (count > 1) {
2022                    if (totalFull != 0 || totalPartial != 0 || totalWindow != 0) {
2023                        sb.setLength(0);
2024                        sb.append(prefix);
2025                        sb.append("    TOTAL wake: ");
2026                        boolean needComma = false;
2027                        if (totalFull != 0) {
2028                            needComma = true;
2029                            formatTimeMs(sb, totalFull);
2030                            sb.append("full");
2031                        }
2032                        if (totalPartial != 0) {
2033                            if (needComma) {
2034                                sb.append(", ");
2035                            }
2036                            needComma = true;
2037                            formatTimeMs(sb, totalPartial);
2038                            sb.append("partial");
2039                        }
2040                        if (totalWindow != 0) {
2041                            if (needComma) {
2042                                sb.append(", ");
2043                            }
2044                            needComma = true;
2045                            formatTimeMs(sb, totalWindow);
2046                            sb.append("window");
2047                        }
2048                        sb.append(" realtime");
2049                        pw.println(sb.toString());
2050                    }
2051                }
2052            }
2053
2054            Map<Integer, ? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
2055            if (sensors.size() > 0) {
2056                for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> ent
2057                    : sensors.entrySet()) {
2058                    Uid.Sensor se = ent.getValue();
2059                    int sensorNumber = ent.getKey();
2060                    sb.setLength(0);
2061                    sb.append(prefix);
2062                    sb.append("    Sensor ");
2063                    int handle = se.getHandle();
2064                    if (handle == Uid.Sensor.GPS) {
2065                        sb.append("GPS");
2066                    } else {
2067                        sb.append(handle);
2068                    }
2069                    sb.append(": ");
2070
2071                    Timer timer = se.getSensorTime();
2072                    if (timer != null) {
2073                        // Convert from microseconds to milliseconds with rounding
2074                        long totalTime = (timer.getTotalTimeLocked(
2075                                batteryRealtime, which) + 500) / 1000;
2076                        int count = timer.getCountLocked(which);
2077                        //timer.logState();
2078                        if (totalTime != 0) {
2079                            formatTimeMs(sb, totalTime);
2080                            sb.append("realtime (");
2081                            sb.append(count);
2082                            sb.append(" times)");
2083                        } else {
2084                            sb.append("(not used)");
2085                        }
2086                    } else {
2087                        sb.append("(not used)");
2088                    }
2089
2090                    pw.println(sb.toString());
2091                    uidActivity = true;
2092                }
2093            }
2094
2095            Timer vibTimer = u.getVibratorOnTimer();
2096            if (vibTimer != null) {
2097                // Convert from microseconds to milliseconds with rounding
2098                long totalTime = (vibTimer.getTotalTimeLocked(
2099                        batteryRealtime, which) + 500) / 1000;
2100                int count = vibTimer.getCountLocked(which);
2101                //timer.logState();
2102                if (totalTime != 0) {
2103                    sb.setLength(0);
2104                    sb.append(prefix);
2105                    sb.append("    Vibrator: ");
2106                    formatTimeMs(sb, totalTime);
2107                    sb.append("realtime (");
2108                    sb.append(count);
2109                    sb.append(" times)");
2110                    pw.println(sb.toString());
2111                    uidActivity = true;
2112                }
2113            }
2114
2115            Timer fgTimer = u.getForegroundActivityTimer();
2116            if (fgTimer != null) {
2117                // Convert from microseconds to milliseconds with rounding
2118                long totalTime = (fgTimer.getTotalTimeLocked(batteryRealtime, which) + 500) / 1000;
2119                int count = fgTimer.getCountLocked(which);
2120                if (totalTime != 0) {
2121                    sb.setLength(0);
2122                    sb.append(prefix);
2123                    sb.append("    Foreground activities: ");
2124                    formatTimeMs(sb, totalTime);
2125                    sb.append("realtime (");
2126                    sb.append(count);
2127                    sb.append(" times)");
2128                    pw.println(sb.toString());
2129                    uidActivity = true;
2130                }
2131            }
2132
2133            Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
2134            if (processStats.size() > 0) {
2135                for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
2136                    : processStats.entrySet()) {
2137                    Uid.Proc ps = ent.getValue();
2138                    long userTime;
2139                    long systemTime;
2140                    long foregroundTime;
2141                    int starts;
2142                    int numExcessive;
2143
2144                    userTime = ps.getUserTime(which);
2145                    systemTime = ps.getSystemTime(which);
2146                    foregroundTime = ps.getForegroundTime(which);
2147                    starts = ps.getStarts(which);
2148                    numExcessive = which == STATS_SINCE_CHARGED
2149                            ? ps.countExcessivePowers() : 0;
2150
2151                    if (userTime != 0 || systemTime != 0 || foregroundTime != 0 || starts != 0
2152                            || numExcessive != 0) {
2153                        sb.setLength(0);
2154                        sb.append(prefix); sb.append("    Proc ");
2155                                sb.append(ent.getKey()); sb.append(":\n");
2156                        sb.append(prefix); sb.append("      CPU: ");
2157                                formatTime(sb, userTime); sb.append("usr + ");
2158                                formatTime(sb, systemTime); sb.append("krn ; ");
2159                                formatTime(sb, foregroundTime); sb.append("fg");
2160                        if (starts != 0) {
2161                            sb.append("\n"); sb.append(prefix); sb.append("      ");
2162                                    sb.append(starts); sb.append(" proc starts");
2163                        }
2164                        pw.println(sb.toString());
2165                        for (int e=0; e<numExcessive; e++) {
2166                            Uid.Proc.ExcessivePower ew = ps.getExcessivePower(e);
2167                            if (ew != null) {
2168                                pw.print(prefix); pw.print("      * Killed for ");
2169                                        if (ew.type == Uid.Proc.ExcessivePower.TYPE_WAKE) {
2170                                            pw.print("wake lock");
2171                                        } else if (ew.type == Uid.Proc.ExcessivePower.TYPE_CPU) {
2172                                            pw.print("cpu");
2173                                        } else {
2174                                            pw.print("unknown");
2175                                        }
2176                                        pw.print(" use: ");
2177                                        TimeUtils.formatDuration(ew.usedTime, pw);
2178                                        pw.print(" over ");
2179                                        TimeUtils.formatDuration(ew.overTime, pw);
2180                                        if (ew.overTime != 0) {
2181                                            pw.print(" (");
2182                                            pw.print((ew.usedTime*100)/ew.overTime);
2183                                            pw.println("%)");
2184                                        }
2185                            }
2186                        }
2187                        uidActivity = true;
2188                    }
2189                }
2190            }
2191
2192            Map<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats();
2193            if (packageStats.size() > 0) {
2194                for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent
2195                    : packageStats.entrySet()) {
2196                    pw.print(prefix); pw.print("    Apk "); pw.print(ent.getKey()); pw.println(":");
2197                    boolean apkActivity = false;
2198                    Uid.Pkg ps = ent.getValue();
2199                    int wakeups = ps.getWakeups(which);
2200                    if (wakeups != 0) {
2201                        pw.print(prefix); pw.print("      ");
2202                                pw.print(wakeups); pw.println(" wakeup alarms");
2203                        apkActivity = true;
2204                    }
2205                    Map<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
2206                    if (serviceStats.size() > 0) {
2207                        for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent
2208                                : serviceStats.entrySet()) {
2209                            BatteryStats.Uid.Pkg.Serv ss = sent.getValue();
2210                            long startTime = ss.getStartTime(batteryUptime, which);
2211                            int starts = ss.getStarts(which);
2212                            int launches = ss.getLaunches(which);
2213                            if (startTime != 0 || starts != 0 || launches != 0) {
2214                                sb.setLength(0);
2215                                sb.append(prefix); sb.append("      Service ");
2216                                        sb.append(sent.getKey()); sb.append(":\n");
2217                                sb.append(prefix); sb.append("        Created for: ");
2218                                        formatTimeMs(sb, startTime / 1000);
2219                                        sb.append("uptime\n");
2220                                sb.append(prefix); sb.append("        Starts: ");
2221                                        sb.append(starts);
2222                                        sb.append(", launches: "); sb.append(launches);
2223                                pw.println(sb.toString());
2224                                apkActivity = true;
2225                            }
2226                        }
2227                    }
2228                    if (!apkActivity) {
2229                        pw.print(prefix); pw.println("      (nothing executed)");
2230                    }
2231                    uidActivity = true;
2232                }
2233            }
2234            if (!uidActivity) {
2235                pw.print(prefix); pw.println("    (nothing executed)");
2236            }
2237        }
2238    }
2239
2240    static void printBitDescriptions(PrintWriter pw, int oldval, int newval,
2241            BitDescription[] descriptions, boolean longNames) {
2242        int diff = oldval ^ newval;
2243        if (diff == 0) return;
2244        for (int i=0; i<descriptions.length; i++) {
2245            BitDescription bd = descriptions[i];
2246            if ((diff&bd.mask) != 0) {
2247                pw.print(longNames ? " " : ",");
2248                if (bd.shift < 0) {
2249                    pw.print((newval&bd.mask) != 0 ? "+" : "-");
2250                    pw.print(longNames ? bd.name : bd.shortName);
2251                } else {
2252                    pw.print(longNames ? bd.name : bd.shortName);
2253                    pw.print("=");
2254                    int val = (newval&bd.mask)>>bd.shift;
2255                    if (bd.values != null && val >= 0 && val < bd.values.length) {
2256                        pw.print(longNames? bd.values[val] : bd.shortValues[val]);
2257                    } else {
2258                        pw.print(val);
2259                    }
2260                }
2261            }
2262        }
2263    }
2264
2265    public void prepareForDumpLocked() {
2266    }
2267
2268    public static class HistoryPrinter {
2269        int oldState = 0;
2270        int oldLevel = -1;
2271        int oldStatus = -1;
2272        int oldHealth = -1;
2273        int oldPlug = -1;
2274        int oldTemp = -1;
2275        int oldVolt = -1;
2276        long lastTime = -1;
2277
2278        public void printNextItem(PrintWriter pw, HistoryItem rec, long now, boolean checkin) {
2279            if (!checkin) {
2280                pw.print("  ");
2281                TimeUtils.formatDuration(rec.time-now, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
2282                pw.print(" ");
2283            } else {
2284                if (lastTime < 0) {
2285                    pw.print("@");
2286                    pw.print(rec.time-now);
2287                } else {
2288                    pw.print(rec.time-lastTime);
2289                }
2290                lastTime = rec.time;
2291            }
2292            if (rec.cmd == HistoryItem.CMD_START) {
2293                if (checkin) {
2294                    pw.print(":");
2295                }
2296                pw.println("START");
2297            } else if (rec.cmd == HistoryItem.CMD_OVERFLOW) {
2298                if (checkin) {
2299                    pw.print(":");
2300                }
2301                pw.println("*OVERFLOW*");
2302            } else {
2303                if (!checkin) {
2304                    if (rec.batteryLevel < 10) pw.print("00");
2305                    else if (rec.batteryLevel < 100) pw.print("0");
2306                    pw.print(rec.batteryLevel);
2307                    pw.print(" ");
2308                    if (rec.states < 0x10) pw.print("0000000");
2309                    else if (rec.states < 0x100) pw.print("000000");
2310                    else if (rec.states < 0x1000) pw.print("00000");
2311                    else if (rec.states < 0x10000) pw.print("0000");
2312                    else if (rec.states < 0x100000) pw.print("000");
2313                    else if (rec.states < 0x1000000) pw.print("00");
2314                    else if (rec.states < 0x10000000) pw.print("0");
2315                    pw.print(Integer.toHexString(rec.states));
2316                } else {
2317                    if (oldLevel != rec.batteryLevel) {
2318                        oldLevel = rec.batteryLevel;
2319                        pw.print(",Bl="); pw.print(rec.batteryLevel);
2320                    }
2321                }
2322                if (oldStatus != rec.batteryStatus) {
2323                    oldStatus = rec.batteryStatus;
2324                    pw.print(checkin ? ",Bs=" : " status=");
2325                    switch (oldStatus) {
2326                        case BatteryManager.BATTERY_STATUS_UNKNOWN:
2327                            pw.print(checkin ? "?" : "unknown");
2328                            break;
2329                        case BatteryManager.BATTERY_STATUS_CHARGING:
2330                            pw.print(checkin ? "c" : "charging");
2331                            break;
2332                        case BatteryManager.BATTERY_STATUS_DISCHARGING:
2333                            pw.print(checkin ? "d" : "discharging");
2334                            break;
2335                        case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
2336                            pw.print(checkin ? "n" : "not-charging");
2337                            break;
2338                        case BatteryManager.BATTERY_STATUS_FULL:
2339                            pw.print(checkin ? "f" : "full");
2340                            break;
2341                        default:
2342                            pw.print(oldStatus);
2343                            break;
2344                    }
2345                }
2346                if (oldHealth != rec.batteryHealth) {
2347                    oldHealth = rec.batteryHealth;
2348                    pw.print(checkin ? ",Bh=" : " health=");
2349                    switch (oldHealth) {
2350                        case BatteryManager.BATTERY_HEALTH_UNKNOWN:
2351                            pw.print(checkin ? "?" : "unknown");
2352                            break;
2353                        case BatteryManager.BATTERY_HEALTH_GOOD:
2354                            pw.print(checkin ? "g" : "good");
2355                            break;
2356                        case BatteryManager.BATTERY_HEALTH_OVERHEAT:
2357                            pw.print(checkin ? "h" : "overheat");
2358                            break;
2359                        case BatteryManager.BATTERY_HEALTH_DEAD:
2360                            pw.print(checkin ? "d" : "dead");
2361                            break;
2362                        case BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE:
2363                            pw.print(checkin ? "v" : "over-voltage");
2364                            break;
2365                        case BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE:
2366                            pw.print(checkin ? "f" : "failure");
2367                            break;
2368                        default:
2369                            pw.print(oldHealth);
2370                            break;
2371                    }
2372                }
2373                if (oldPlug != rec.batteryPlugType) {
2374                    oldPlug = rec.batteryPlugType;
2375                    pw.print(checkin ? ",Bp=" : " plug=");
2376                    switch (oldPlug) {
2377                        case 0:
2378                            pw.print(checkin ? "n" : "none");
2379                            break;
2380                        case BatteryManager.BATTERY_PLUGGED_AC:
2381                            pw.print(checkin ? "a" : "ac");
2382                            break;
2383                        case BatteryManager.BATTERY_PLUGGED_USB:
2384                            pw.print(checkin ? "u" : "usb");
2385                            break;
2386                        case BatteryManager.BATTERY_PLUGGED_WIRELESS:
2387                            pw.print(checkin ? "w" : "wireless");
2388                            break;
2389                        default:
2390                            pw.print(oldPlug);
2391                            break;
2392                    }
2393                }
2394                if (oldTemp != rec.batteryTemperature) {
2395                    oldTemp = rec.batteryTemperature;
2396                    pw.print(checkin ? ",Bt=" : " temp=");
2397                    pw.print(oldTemp);
2398                }
2399                if (oldVolt != rec.batteryVoltage) {
2400                    oldVolt = rec.batteryVoltage;
2401                    pw.print(checkin ? ",Bv=" : " volt=");
2402                    pw.print(oldVolt);
2403                }
2404                printBitDescriptions(pw, oldState, rec.states,
2405                        HISTORY_STATE_DESCRIPTIONS, !checkin);
2406                pw.println();
2407            }
2408            oldState = rec.states;
2409        }
2410    }
2411
2412    /**
2413     * Dumps a human-readable summary of the battery statistics to the given PrintWriter.
2414     *
2415     * @param pw a Printer to receive the dump output.
2416     */
2417    @SuppressWarnings("unused")
2418    public void dumpLocked(Context context, PrintWriter pw, boolean isUnpluggedOnly, int reqUid) {
2419        prepareForDumpLocked();
2420
2421        long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
2422
2423        final HistoryItem rec = new HistoryItem();
2424        if (startIteratingHistoryLocked()) {
2425            pw.println("Battery History:");
2426            HistoryPrinter hprinter = new HistoryPrinter();
2427            while (getNextHistoryLocked(rec)) {
2428                hprinter.printNextItem(pw, rec, now, false);
2429            }
2430            finishIteratingHistoryLocked();
2431            pw.println("");
2432        }
2433
2434        if (startIteratingOldHistoryLocked()) {
2435            pw.println("Old battery History:");
2436            HistoryPrinter hprinter = new HistoryPrinter();
2437            while (getNextOldHistoryLocked(rec)) {
2438                hprinter.printNextItem(pw, rec, now, false);
2439            }
2440            finishIteratingOldHistoryLocked();
2441            pw.println("");
2442        }
2443
2444        SparseArray<? extends Uid> uidStats = getUidStats();
2445        final int NU = uidStats.size();
2446        boolean didPid = false;
2447        long nowRealtime = SystemClock.elapsedRealtime();
2448        for (int i=0; i<NU; i++) {
2449            Uid uid = uidStats.valueAt(i);
2450            SparseArray<? extends Uid.Pid> pids = uid.getPidStats();
2451            if (pids != null) {
2452                for (int j=0; j<pids.size(); j++) {
2453                    Uid.Pid pid = pids.valueAt(j);
2454                    if (!didPid) {
2455                        pw.println("Per-PID Stats:");
2456                        didPid = true;
2457                    }
2458                    long time = pid.mWakeSum + (pid.mWakeStart != 0
2459                            ? (nowRealtime - pid.mWakeStart) : 0);
2460                    pw.print("  PID "); pw.print(pids.keyAt(j));
2461                            pw.print(" wake time: ");
2462                            TimeUtils.formatDuration(time, pw);
2463                            pw.println("");
2464                }
2465            }
2466        }
2467        if (didPid) {
2468            pw.println("");
2469        }
2470
2471        if (!isUnpluggedOnly) {
2472            pw.println("Statistics since last charge:");
2473            pw.println("  System starts: " + getStartCount()
2474                    + ", currently on battery: " + getIsOnBattery());
2475            dumpLocked(context, pw, "", STATS_SINCE_CHARGED, reqUid);
2476            pw.println("");
2477        }
2478        pw.println("Statistics since last unplugged:");
2479        dumpLocked(context, pw, "", STATS_SINCE_UNPLUGGED, reqUid);
2480    }
2481
2482    @SuppressWarnings("unused")
2483    public void dumpCheckinLocked(Context context,
2484            PrintWriter pw, List<ApplicationInfo> apps, boolean isUnpluggedOnly,
2485            boolean includeHistory) {
2486        prepareForDumpLocked();
2487
2488        long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
2489
2490        if (includeHistory) {
2491            final HistoryItem rec = new HistoryItem();
2492            if (startIteratingHistoryLocked()) {
2493                HistoryPrinter hprinter = new HistoryPrinter();
2494                while (getNextHistoryLocked(rec)) {
2495                    pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
2496                    pw.print(HISTORY_DATA); pw.print(',');
2497                    hprinter.printNextItem(pw, rec, now, true);
2498                }
2499                finishIteratingHistoryLocked();
2500            }
2501        }
2502
2503        if (apps != null) {
2504            SparseArray<ArrayList<String>> uids = new SparseArray<ArrayList<String>>();
2505            for (int i=0; i<apps.size(); i++) {
2506                ApplicationInfo ai = apps.get(i);
2507                ArrayList<String> pkgs = uids.get(ai.uid);
2508                if (pkgs == null) {
2509                    pkgs = new ArrayList<String>();
2510                    uids.put(ai.uid, pkgs);
2511                }
2512                pkgs.add(ai.packageName);
2513            }
2514            SparseArray<? extends Uid> uidStats = getUidStats();
2515            final int NU = uidStats.size();
2516            String[] lineArgs = new String[2];
2517            for (int i=0; i<NU; i++) {
2518                int uid = uidStats.keyAt(i);
2519                ArrayList<String> pkgs = uids.get(uid);
2520                if (pkgs != null) {
2521                    for (int j=0; j<pkgs.size(); j++) {
2522                        lineArgs[0] = Integer.toString(uid);
2523                        lineArgs[1] = pkgs.get(j);
2524                        dumpLine(pw, 0 /* uid */, "i" /* category */, UID_DATA,
2525                                (Object[])lineArgs);
2526                    }
2527                }
2528            }
2529        }
2530        if (isUnpluggedOnly) {
2531            dumpCheckinLocked(context, pw, STATS_SINCE_UNPLUGGED, -1);
2532        }
2533        else {
2534            dumpCheckinLocked(context, pw, STATS_SINCE_CHARGED, -1);
2535            dumpCheckinLocked(context, pw, STATS_SINCE_UNPLUGGED, -1);
2536        }
2537    }
2538}
2539