BatteryStats.java revision c46809e9979204aa9a131d8933da23d298411441
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            pw.println();
1888        }
1889
1890        if (timers.size() > 0) {
1891            Collections.sort(timers, timerComparator);
1892            pw.print(prefix); pw.println("  All partial wake locks:");
1893            for (int i=0; i<timers.size(); i++) {
1894                TimerEntry timer = timers.get(i);
1895                sb.setLength(0);
1896                sb.append("  Wake lock ");
1897                UserHandle.formatUid(sb, timer.mId);
1898                sb.append(" ");
1899                sb.append(timer.mName);
1900                printWakeLock(sb, timer.mTimer, batteryRealtime, null, which, ": ");
1901                sb.append(" realtime");
1902                pw.println(sb.toString());
1903            }
1904            timers.clear();
1905            pw.println();
1906        }
1907
1908        for (int iu=0; iu<NU; iu++) {
1909            final int uid = uidStats.keyAt(iu);
1910            if (reqUid >= 0 && uid != reqUid && uid != Process.SYSTEM_UID) {
1911                continue;
1912            }
1913
1914            Uid u = uidStats.valueAt(iu);
1915
1916            pw.print(prefix);
1917            pw.print("  ");
1918            UserHandle.formatUid(pw, uid);
1919            pw.println(":");
1920            boolean uidActivity = false;
1921
1922            long mobileRxBytes = u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
1923            long mobileTxBytes = u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
1924            long wifiRxBytes = u.getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
1925            long wifiTxBytes = u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
1926            long mobileRxPackets = u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
1927            long mobileTxPackets = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
1928            long wifiRxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
1929            long wifiTxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
1930            long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
1931            long wifiScanTime = u.getWifiScanTime(batteryRealtime, which);
1932            long uidWifiRunningTime = u.getWifiRunningTime(batteryRealtime, which);
1933
1934            if (mobileRxBytes > 0 || mobileTxBytes > 0
1935                    || mobileRxPackets > 0 || mobileTxPackets > 0) {
1936                pw.print(prefix); pw.print("    Mobile network: ");
1937                        pw.print(formatBytesLocked(mobileRxBytes)); pw.print(" received, ");
1938                        pw.print(formatBytesLocked(mobileTxBytes));
1939                        pw.print(" sent (packets "); pw.print(mobileRxPackets);
1940                        pw.print(" received, "); pw.print(mobileTxPackets); pw.println(" sent)");
1941            }
1942            if (wifiRxBytes > 0 || wifiTxBytes > 0 || wifiRxPackets > 0 || wifiTxPackets > 0) {
1943                pw.print(prefix); pw.print("    Wi-Fi network: ");
1944                        pw.print(formatBytesLocked(wifiRxBytes)); pw.print(" received, ");
1945                        pw.print(formatBytesLocked(wifiTxBytes));
1946                        pw.print(" sent (packets "); pw.print(wifiRxPackets);
1947                        pw.print(" received, "); pw.print(wifiTxPackets); pw.println(" sent)");
1948            }
1949
1950            if (u.hasUserActivity()) {
1951                boolean hasData = false;
1952                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
1953                    int val = u.getUserActivityCount(i, which);
1954                    if (val != 0) {
1955                        if (!hasData) {
1956                            sb.setLength(0);
1957                            sb.append("    User activity: ");
1958                            hasData = true;
1959                        } else {
1960                            sb.append(", ");
1961                        }
1962                        sb.append(val);
1963                        sb.append(" ");
1964                        sb.append(Uid.USER_ACTIVITY_TYPES[i]);
1965                    }
1966                }
1967                if (hasData) {
1968                    pw.println(sb.toString());
1969                }
1970            }
1971
1972            if (fullWifiLockOnTime != 0 || wifiScanTime != 0
1973                    || uidWifiRunningTime != 0) {
1974                sb.setLength(0);
1975                sb.append(prefix); sb.append("    Wifi Running: ");
1976                        formatTimeMs(sb, uidWifiRunningTime / 1000);
1977                        sb.append("("); sb.append(formatRatioLocked(uidWifiRunningTime,
1978                                whichBatteryRealtime)); sb.append(")\n");
1979                sb.append(prefix); sb.append("    Full Wifi Lock: ");
1980                        formatTimeMs(sb, fullWifiLockOnTime / 1000);
1981                        sb.append("("); sb.append(formatRatioLocked(fullWifiLockOnTime,
1982                                whichBatteryRealtime)); sb.append(")\n");
1983                sb.append(prefix); sb.append("    Wifi Scan: ");
1984                        formatTimeMs(sb, wifiScanTime / 1000);
1985                        sb.append("("); sb.append(formatRatioLocked(wifiScanTime,
1986                                whichBatteryRealtime)); sb.append(")");
1987                pw.println(sb.toString());
1988            }
1989
1990            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
1991            if (wakelocks.size() > 0) {
1992                long totalFull = 0, totalPartial = 0, totalWindow = 0;
1993                int count = 0;
1994                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
1995                    : wakelocks.entrySet()) {
1996                    Uid.Wakelock wl = ent.getValue();
1997                    String linePrefix = ": ";
1998                    sb.setLength(0);
1999                    sb.append(prefix);
2000                    sb.append("    Wake lock ");
2001                    sb.append(ent.getKey());
2002                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_FULL), batteryRealtime,
2003                            "full", which, linePrefix);
2004                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), batteryRealtime,
2005                            "partial", which, linePrefix);
2006                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), batteryRealtime,
2007                            "window", which, linePrefix);
2008                    if (!linePrefix.equals(": ")) {
2009                        sb.append(" realtime");
2010                        // Only print out wake locks that were held
2011                        pw.println(sb.toString());
2012                        uidActivity = true;
2013                        count++;
2014                    }
2015                    totalFull += computeWakeLock(wl.getWakeTime(WAKE_TYPE_FULL),
2016                            batteryRealtime, which);
2017                    totalPartial += computeWakeLock(wl.getWakeTime(WAKE_TYPE_PARTIAL),
2018                            batteryRealtime, which);
2019                    totalWindow += computeWakeLock(wl.getWakeTime(WAKE_TYPE_WINDOW),
2020                            batteryRealtime, which);
2021                }
2022                if (count > 1) {
2023                    if (totalFull != 0 || totalPartial != 0 || totalWindow != 0) {
2024                        sb.setLength(0);
2025                        sb.append(prefix);
2026                        sb.append("    TOTAL wake: ");
2027                        boolean needComma = false;
2028                        if (totalFull != 0) {
2029                            needComma = true;
2030                            formatTimeMs(sb, totalFull);
2031                            sb.append("full");
2032                        }
2033                        if (totalPartial != 0) {
2034                            if (needComma) {
2035                                sb.append(", ");
2036                            }
2037                            needComma = true;
2038                            formatTimeMs(sb, totalPartial);
2039                            sb.append("partial");
2040                        }
2041                        if (totalWindow != 0) {
2042                            if (needComma) {
2043                                sb.append(", ");
2044                            }
2045                            needComma = true;
2046                            formatTimeMs(sb, totalWindow);
2047                            sb.append("window");
2048                        }
2049                        sb.append(" realtime");
2050                        pw.println(sb.toString());
2051                    }
2052                }
2053            }
2054
2055            Map<Integer, ? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
2056            if (sensors.size() > 0) {
2057                for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> ent
2058                    : sensors.entrySet()) {
2059                    Uid.Sensor se = ent.getValue();
2060                    int sensorNumber = ent.getKey();
2061                    sb.setLength(0);
2062                    sb.append(prefix);
2063                    sb.append("    Sensor ");
2064                    int handle = se.getHandle();
2065                    if (handle == Uid.Sensor.GPS) {
2066                        sb.append("GPS");
2067                    } else {
2068                        sb.append(handle);
2069                    }
2070                    sb.append(": ");
2071
2072                    Timer timer = se.getSensorTime();
2073                    if (timer != null) {
2074                        // Convert from microseconds to milliseconds with rounding
2075                        long totalTime = (timer.getTotalTimeLocked(
2076                                batteryRealtime, which) + 500) / 1000;
2077                        int count = timer.getCountLocked(which);
2078                        //timer.logState();
2079                        if (totalTime != 0) {
2080                            formatTimeMs(sb, totalTime);
2081                            sb.append("realtime (");
2082                            sb.append(count);
2083                            sb.append(" times)");
2084                        } else {
2085                            sb.append("(not used)");
2086                        }
2087                    } else {
2088                        sb.append("(not used)");
2089                    }
2090
2091                    pw.println(sb.toString());
2092                    uidActivity = true;
2093                }
2094            }
2095
2096            Timer vibTimer = u.getVibratorOnTimer();
2097            if (vibTimer != null) {
2098                // Convert from microseconds to milliseconds with rounding
2099                long totalTime = (vibTimer.getTotalTimeLocked(
2100                        batteryRealtime, which) + 500) / 1000;
2101                int count = vibTimer.getCountLocked(which);
2102                //timer.logState();
2103                if (totalTime != 0) {
2104                    sb.setLength(0);
2105                    sb.append(prefix);
2106                    sb.append("    Vibrator: ");
2107                    formatTimeMs(sb, totalTime);
2108                    sb.append("realtime (");
2109                    sb.append(count);
2110                    sb.append(" times)");
2111                    pw.println(sb.toString());
2112                    uidActivity = true;
2113                }
2114            }
2115
2116            Timer fgTimer = u.getForegroundActivityTimer();
2117            if (fgTimer != null) {
2118                // Convert from microseconds to milliseconds with rounding
2119                long totalTime = (fgTimer.getTotalTimeLocked(batteryRealtime, which) + 500) / 1000;
2120                int count = fgTimer.getCountLocked(which);
2121                if (totalTime != 0) {
2122                    sb.setLength(0);
2123                    sb.append(prefix);
2124                    sb.append("    Foreground activities: ");
2125                    formatTimeMs(sb, totalTime);
2126                    sb.append("realtime (");
2127                    sb.append(count);
2128                    sb.append(" times)");
2129                    pw.println(sb.toString());
2130                    uidActivity = true;
2131                }
2132            }
2133
2134            Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
2135            if (processStats.size() > 0) {
2136                for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
2137                    : processStats.entrySet()) {
2138                    Uid.Proc ps = ent.getValue();
2139                    long userTime;
2140                    long systemTime;
2141                    long foregroundTime;
2142                    int starts;
2143                    int numExcessive;
2144
2145                    userTime = ps.getUserTime(which);
2146                    systemTime = ps.getSystemTime(which);
2147                    foregroundTime = ps.getForegroundTime(which);
2148                    starts = ps.getStarts(which);
2149                    numExcessive = which == STATS_SINCE_CHARGED
2150                            ? ps.countExcessivePowers() : 0;
2151
2152                    if (userTime != 0 || systemTime != 0 || foregroundTime != 0 || starts != 0
2153                            || numExcessive != 0) {
2154                        sb.setLength(0);
2155                        sb.append(prefix); sb.append("    Proc ");
2156                                sb.append(ent.getKey()); sb.append(":\n");
2157                        sb.append(prefix); sb.append("      CPU: ");
2158                                formatTime(sb, userTime); sb.append("usr + ");
2159                                formatTime(sb, systemTime); sb.append("krn ; ");
2160                                formatTime(sb, foregroundTime); sb.append("fg");
2161                        if (starts != 0) {
2162                            sb.append("\n"); sb.append(prefix); sb.append("      ");
2163                                    sb.append(starts); sb.append(" proc starts");
2164                        }
2165                        pw.println(sb.toString());
2166                        for (int e=0; e<numExcessive; e++) {
2167                            Uid.Proc.ExcessivePower ew = ps.getExcessivePower(e);
2168                            if (ew != null) {
2169                                pw.print(prefix); pw.print("      * Killed for ");
2170                                        if (ew.type == Uid.Proc.ExcessivePower.TYPE_WAKE) {
2171                                            pw.print("wake lock");
2172                                        } else if (ew.type == Uid.Proc.ExcessivePower.TYPE_CPU) {
2173                                            pw.print("cpu");
2174                                        } else {
2175                                            pw.print("unknown");
2176                                        }
2177                                        pw.print(" use: ");
2178                                        TimeUtils.formatDuration(ew.usedTime, pw);
2179                                        pw.print(" over ");
2180                                        TimeUtils.formatDuration(ew.overTime, pw);
2181                                        if (ew.overTime != 0) {
2182                                            pw.print(" (");
2183                                            pw.print((ew.usedTime*100)/ew.overTime);
2184                                            pw.println("%)");
2185                                        }
2186                            }
2187                        }
2188                        uidActivity = true;
2189                    }
2190                }
2191            }
2192
2193            Map<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats();
2194            if (packageStats.size() > 0) {
2195                for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent
2196                    : packageStats.entrySet()) {
2197                    pw.print(prefix); pw.print("    Apk "); pw.print(ent.getKey()); pw.println(":");
2198                    boolean apkActivity = false;
2199                    Uid.Pkg ps = ent.getValue();
2200                    int wakeups = ps.getWakeups(which);
2201                    if (wakeups != 0) {
2202                        pw.print(prefix); pw.print("      ");
2203                                pw.print(wakeups); pw.println(" wakeup alarms");
2204                        apkActivity = true;
2205                    }
2206                    Map<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
2207                    if (serviceStats.size() > 0) {
2208                        for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent
2209                                : serviceStats.entrySet()) {
2210                            BatteryStats.Uid.Pkg.Serv ss = sent.getValue();
2211                            long startTime = ss.getStartTime(batteryUptime, which);
2212                            int starts = ss.getStarts(which);
2213                            int launches = ss.getLaunches(which);
2214                            if (startTime != 0 || starts != 0 || launches != 0) {
2215                                sb.setLength(0);
2216                                sb.append(prefix); sb.append("      Service ");
2217                                        sb.append(sent.getKey()); sb.append(":\n");
2218                                sb.append(prefix); sb.append("        Created for: ");
2219                                        formatTimeMs(sb, startTime / 1000);
2220                                        sb.append("uptime\n");
2221                                sb.append(prefix); sb.append("        Starts: ");
2222                                        sb.append(starts);
2223                                        sb.append(", launches: "); sb.append(launches);
2224                                pw.println(sb.toString());
2225                                apkActivity = true;
2226                            }
2227                        }
2228                    }
2229                    if (!apkActivity) {
2230                        pw.print(prefix); pw.println("      (nothing executed)");
2231                    }
2232                    uidActivity = true;
2233                }
2234            }
2235            if (!uidActivity) {
2236                pw.print(prefix); pw.println("    (nothing executed)");
2237            }
2238        }
2239    }
2240
2241    static void printBitDescriptions(PrintWriter pw, int oldval, int newval,
2242            BitDescription[] descriptions, boolean longNames) {
2243        int diff = oldval ^ newval;
2244        if (diff == 0) return;
2245        for (int i=0; i<descriptions.length; i++) {
2246            BitDescription bd = descriptions[i];
2247            if ((diff&bd.mask) != 0) {
2248                pw.print(longNames ? " " : ",");
2249                if (bd.shift < 0) {
2250                    pw.print((newval&bd.mask) != 0 ? "+" : "-");
2251                    pw.print(longNames ? bd.name : bd.shortName);
2252                } else {
2253                    pw.print(longNames ? bd.name : bd.shortName);
2254                    pw.print("=");
2255                    int val = (newval&bd.mask)>>bd.shift;
2256                    if (bd.values != null && val >= 0 && val < bd.values.length) {
2257                        pw.print(longNames? bd.values[val] : bd.shortValues[val]);
2258                    } else {
2259                        pw.print(val);
2260                    }
2261                }
2262            }
2263        }
2264    }
2265
2266    public void prepareForDumpLocked() {
2267    }
2268
2269    public static class HistoryPrinter {
2270        int oldState = 0;
2271        int oldLevel = -1;
2272        int oldStatus = -1;
2273        int oldHealth = -1;
2274        int oldPlug = -1;
2275        int oldTemp = -1;
2276        int oldVolt = -1;
2277        long lastTime = -1;
2278
2279        public void printNextItem(PrintWriter pw, HistoryItem rec, long now, boolean checkin) {
2280            if (!checkin) {
2281                pw.print("  ");
2282                TimeUtils.formatDuration(rec.time-now, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
2283                pw.print(" ");
2284            } else {
2285                if (lastTime < 0) {
2286                    pw.print("@");
2287                    pw.print(rec.time-now);
2288                } else {
2289                    pw.print(rec.time-lastTime);
2290                }
2291                lastTime = rec.time;
2292            }
2293            if (rec.cmd == HistoryItem.CMD_START) {
2294                if (checkin) {
2295                    pw.print(":");
2296                }
2297                pw.println("START");
2298            } else if (rec.cmd == HistoryItem.CMD_OVERFLOW) {
2299                if (checkin) {
2300                    pw.print(":");
2301                }
2302                pw.println("*OVERFLOW*");
2303            } else {
2304                if (!checkin) {
2305                    if (rec.batteryLevel < 10) pw.print("00");
2306                    else if (rec.batteryLevel < 100) pw.print("0");
2307                    pw.print(rec.batteryLevel);
2308                    pw.print(" ");
2309                    if (rec.states < 0x10) pw.print("0000000");
2310                    else if (rec.states < 0x100) pw.print("000000");
2311                    else if (rec.states < 0x1000) pw.print("00000");
2312                    else if (rec.states < 0x10000) pw.print("0000");
2313                    else if (rec.states < 0x100000) pw.print("000");
2314                    else if (rec.states < 0x1000000) pw.print("00");
2315                    else if (rec.states < 0x10000000) pw.print("0");
2316                    pw.print(Integer.toHexString(rec.states));
2317                } else {
2318                    if (oldLevel != rec.batteryLevel) {
2319                        oldLevel = rec.batteryLevel;
2320                        pw.print(",Bl="); pw.print(rec.batteryLevel);
2321                    }
2322                }
2323                if (oldStatus != rec.batteryStatus) {
2324                    oldStatus = rec.batteryStatus;
2325                    pw.print(checkin ? ",Bs=" : " status=");
2326                    switch (oldStatus) {
2327                        case BatteryManager.BATTERY_STATUS_UNKNOWN:
2328                            pw.print(checkin ? "?" : "unknown");
2329                            break;
2330                        case BatteryManager.BATTERY_STATUS_CHARGING:
2331                            pw.print(checkin ? "c" : "charging");
2332                            break;
2333                        case BatteryManager.BATTERY_STATUS_DISCHARGING:
2334                            pw.print(checkin ? "d" : "discharging");
2335                            break;
2336                        case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
2337                            pw.print(checkin ? "n" : "not-charging");
2338                            break;
2339                        case BatteryManager.BATTERY_STATUS_FULL:
2340                            pw.print(checkin ? "f" : "full");
2341                            break;
2342                        default:
2343                            pw.print(oldStatus);
2344                            break;
2345                    }
2346                }
2347                if (oldHealth != rec.batteryHealth) {
2348                    oldHealth = rec.batteryHealth;
2349                    pw.print(checkin ? ",Bh=" : " health=");
2350                    switch (oldHealth) {
2351                        case BatteryManager.BATTERY_HEALTH_UNKNOWN:
2352                            pw.print(checkin ? "?" : "unknown");
2353                            break;
2354                        case BatteryManager.BATTERY_HEALTH_GOOD:
2355                            pw.print(checkin ? "g" : "good");
2356                            break;
2357                        case BatteryManager.BATTERY_HEALTH_OVERHEAT:
2358                            pw.print(checkin ? "h" : "overheat");
2359                            break;
2360                        case BatteryManager.BATTERY_HEALTH_DEAD:
2361                            pw.print(checkin ? "d" : "dead");
2362                            break;
2363                        case BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE:
2364                            pw.print(checkin ? "v" : "over-voltage");
2365                            break;
2366                        case BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE:
2367                            pw.print(checkin ? "f" : "failure");
2368                            break;
2369                        default:
2370                            pw.print(oldHealth);
2371                            break;
2372                    }
2373                }
2374                if (oldPlug != rec.batteryPlugType) {
2375                    oldPlug = rec.batteryPlugType;
2376                    pw.print(checkin ? ",Bp=" : " plug=");
2377                    switch (oldPlug) {
2378                        case 0:
2379                            pw.print(checkin ? "n" : "none");
2380                            break;
2381                        case BatteryManager.BATTERY_PLUGGED_AC:
2382                            pw.print(checkin ? "a" : "ac");
2383                            break;
2384                        case BatteryManager.BATTERY_PLUGGED_USB:
2385                            pw.print(checkin ? "u" : "usb");
2386                            break;
2387                        case BatteryManager.BATTERY_PLUGGED_WIRELESS:
2388                            pw.print(checkin ? "w" : "wireless");
2389                            break;
2390                        default:
2391                            pw.print(oldPlug);
2392                            break;
2393                    }
2394                }
2395                if (oldTemp != rec.batteryTemperature) {
2396                    oldTemp = rec.batteryTemperature;
2397                    pw.print(checkin ? ",Bt=" : " temp=");
2398                    pw.print(oldTemp);
2399                }
2400                if (oldVolt != rec.batteryVoltage) {
2401                    oldVolt = rec.batteryVoltage;
2402                    pw.print(checkin ? ",Bv=" : " volt=");
2403                    pw.print(oldVolt);
2404                }
2405                printBitDescriptions(pw, oldState, rec.states,
2406                        HISTORY_STATE_DESCRIPTIONS, !checkin);
2407                pw.println();
2408            }
2409            oldState = rec.states;
2410        }
2411    }
2412
2413    /**
2414     * Dumps a human-readable summary of the battery statistics to the given PrintWriter.
2415     *
2416     * @param pw a Printer to receive the dump output.
2417     */
2418    @SuppressWarnings("unused")
2419    public void dumpLocked(Context context, PrintWriter pw, boolean isUnpluggedOnly, int reqUid) {
2420        prepareForDumpLocked();
2421
2422        long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
2423
2424        final HistoryItem rec = new HistoryItem();
2425        if (startIteratingHistoryLocked()) {
2426            pw.println("Battery History:");
2427            HistoryPrinter hprinter = new HistoryPrinter();
2428            while (getNextHistoryLocked(rec)) {
2429                hprinter.printNextItem(pw, rec, now, false);
2430            }
2431            finishIteratingHistoryLocked();
2432            pw.println("");
2433        }
2434
2435        if (startIteratingOldHistoryLocked()) {
2436            pw.println("Old battery History:");
2437            HistoryPrinter hprinter = new HistoryPrinter();
2438            while (getNextOldHistoryLocked(rec)) {
2439                hprinter.printNextItem(pw, rec, now, false);
2440            }
2441            finishIteratingOldHistoryLocked();
2442            pw.println("");
2443        }
2444
2445        SparseArray<? extends Uid> uidStats = getUidStats();
2446        final int NU = uidStats.size();
2447        boolean didPid = false;
2448        long nowRealtime = SystemClock.elapsedRealtime();
2449        for (int i=0; i<NU; i++) {
2450            Uid uid = uidStats.valueAt(i);
2451            SparseArray<? extends Uid.Pid> pids = uid.getPidStats();
2452            if (pids != null) {
2453                for (int j=0; j<pids.size(); j++) {
2454                    Uid.Pid pid = pids.valueAt(j);
2455                    if (!didPid) {
2456                        pw.println("Per-PID Stats:");
2457                        didPid = true;
2458                    }
2459                    long time = pid.mWakeSum + (pid.mWakeStart != 0
2460                            ? (nowRealtime - pid.mWakeStart) : 0);
2461                    pw.print("  PID "); pw.print(pids.keyAt(j));
2462                            pw.print(" wake time: ");
2463                            TimeUtils.formatDuration(time, pw);
2464                            pw.println("");
2465                }
2466            }
2467        }
2468        if (didPid) {
2469            pw.println("");
2470        }
2471
2472        if (!isUnpluggedOnly) {
2473            pw.println("Statistics since last charge:");
2474            pw.println("  System starts: " + getStartCount()
2475                    + ", currently on battery: " + getIsOnBattery());
2476            dumpLocked(context, pw, "", STATS_SINCE_CHARGED, reqUid);
2477            pw.println("");
2478        }
2479        pw.println("Statistics since last unplugged:");
2480        dumpLocked(context, pw, "", STATS_SINCE_UNPLUGGED, reqUid);
2481    }
2482
2483    @SuppressWarnings("unused")
2484    public void dumpCheckinLocked(Context context,
2485            PrintWriter pw, List<ApplicationInfo> apps, boolean isUnpluggedOnly,
2486            boolean includeHistory) {
2487        prepareForDumpLocked();
2488
2489        long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
2490
2491        if (includeHistory) {
2492            final HistoryItem rec = new HistoryItem();
2493            if (startIteratingHistoryLocked()) {
2494                HistoryPrinter hprinter = new HistoryPrinter();
2495                while (getNextHistoryLocked(rec)) {
2496                    pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
2497                    pw.print(HISTORY_DATA); pw.print(',');
2498                    hprinter.printNextItem(pw, rec, now, true);
2499                }
2500                finishIteratingHistoryLocked();
2501            }
2502        }
2503
2504        if (apps != null) {
2505            SparseArray<ArrayList<String>> uids = new SparseArray<ArrayList<String>>();
2506            for (int i=0; i<apps.size(); i++) {
2507                ApplicationInfo ai = apps.get(i);
2508                ArrayList<String> pkgs = uids.get(ai.uid);
2509                if (pkgs == null) {
2510                    pkgs = new ArrayList<String>();
2511                    uids.put(ai.uid, pkgs);
2512                }
2513                pkgs.add(ai.packageName);
2514            }
2515            SparseArray<? extends Uid> uidStats = getUidStats();
2516            final int NU = uidStats.size();
2517            String[] lineArgs = new String[2];
2518            for (int i=0; i<NU; i++) {
2519                int uid = uidStats.keyAt(i);
2520                ArrayList<String> pkgs = uids.get(uid);
2521                if (pkgs != null) {
2522                    for (int j=0; j<pkgs.size(); j++) {
2523                        lineArgs[0] = Integer.toString(uid);
2524                        lineArgs[1] = pkgs.get(j);
2525                        dumpLine(pw, 0 /* uid */, "i" /* category */, UID_DATA,
2526                                (Object[])lineArgs);
2527                    }
2528                }
2529            }
2530        }
2531        if (isUnpluggedOnly) {
2532            dumpCheckinLocked(context, pw, STATS_SINCE_UNPLUGGED, -1);
2533        }
2534        else {
2535            dumpCheckinLocked(context, pw, STATS_SINCE_CHARGED, -1);
2536            dumpCheckinLocked(context, pw, STATS_SINCE_UNPLUGGED, -1);
2537        }
2538    }
2539}
2540