BatteryStats.java revision 99009ea7dcc196cd97756d70ed69499025229bd9
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.text.format.DateFormat;
31import android.util.Printer;
32import android.util.SparseArray;
33import android.util.TimeUtils;
34import com.android.internal.os.BatterySipper;
35import com.android.internal.os.BatteryStatsHelper;
36
37/**
38 * A class providing access to battery usage statistics, including information on
39 * wakelocks, processes, packages, and services.  All times are represented in microseconds
40 * except where indicated otherwise.
41 * @hide
42 */
43public abstract class BatteryStats implements Parcelable {
44
45    private static final boolean LOCAL_LOGV = false;
46
47    /** @hide */
48    public static final String SERVICE_NAME = "batterystats";
49
50    /**
51     * A constant indicating a partial wake lock timer.
52     */
53    public static final int WAKE_TYPE_PARTIAL = 0;
54
55    /**
56     * A constant indicating a full wake lock timer.
57     */
58    public static final int WAKE_TYPE_FULL = 1;
59
60    /**
61     * A constant indicating a window wake lock timer.
62     */
63    public static final int WAKE_TYPE_WINDOW = 2;
64
65    /**
66     * A constant indicating a sensor timer.
67     */
68    public static final int SENSOR = 3;
69
70    /**
71     * A constant indicating a a wifi running timer
72     */
73    public static final int WIFI_RUNNING = 4;
74
75    /**
76     * A constant indicating a full wifi lock timer
77     */
78    public static final int FULL_WIFI_LOCK = 5;
79
80    /**
81     * A constant indicating a wifi scan
82     */
83    public static final int WIFI_SCAN = 6;
84
85     /**
86      * A constant indicating a wifi multicast timer
87      */
88     public static final int WIFI_MULTICAST_ENABLED = 7;
89
90    /**
91     * A constant indicating an audio turn on timer
92     */
93    public static final int AUDIO_TURNED_ON = 7;
94
95    /**
96     * A constant indicating a video turn on timer
97     */
98    public static final int VIDEO_TURNED_ON = 8;
99
100    /**
101     * A constant indicating a vibrator on timer
102     */
103    public static final int VIBRATOR_ON = 9;
104
105    /**
106     * A constant indicating a foreground activity timer
107     */
108    public static final int FOREGROUND_ACTIVITY = 10;
109
110    /**
111     * A constant indicating a wifi batched scan is active
112     */
113    public static final int WIFI_BATCHED_SCAN = 11;
114
115    /**
116     * Include all of the data in the stats, including previously saved data.
117     */
118    public static final int STATS_SINCE_CHARGED = 0;
119
120    /**
121     * Include only the current run in the stats.
122     */
123    public static final int STATS_CURRENT = 1;
124
125    /**
126     * Include only the run since the last time the device was unplugged in the stats.
127     */
128    public static final int STATS_SINCE_UNPLUGGED = 2;
129
130    // NOTE: Update this list if you add/change any stats above.
131    // These characters are supposed to represent "total", "last", "current",
132    // and "unplugged". They were shortened for efficiency sake.
133    private static final String[] STAT_NAMES = { "t", "l", "c", "u" };
134
135    /**
136     * Bump the version on this if the checkin format changes.
137     */
138    private static final int BATTERY_STATS_CHECKIN_VERSION = 7;
139
140    private static final long BYTES_PER_KB = 1024;
141    private static final long BYTES_PER_MB = 1048576; // 1024^2
142    private static final long BYTES_PER_GB = 1073741824; //1024^3
143
144
145    private static final String UID_DATA = "uid";
146    private static final String APK_DATA = "apk";
147    private static final String PROCESS_DATA = "pr";
148    private static final String SENSOR_DATA = "sr";
149    private static final String VIBRATOR_DATA = "vib";
150    private static final String FOREGROUND_DATA = "fg";
151    private static final String WAKELOCK_DATA = "wl";
152    private static final String KERNEL_WAKELOCK_DATA = "kwl";
153    private static final String WAKEUP_REASON_DATA = "wr";
154    private static final String NETWORK_DATA = "nt";
155    private static final String USER_ACTIVITY_DATA = "ua";
156    private static final String BATTERY_DATA = "bt";
157    private static final String BATTERY_DISCHARGE_DATA = "dc";
158    private static final String BATTERY_LEVEL_DATA = "lv";
159    private static final String WIFI_DATA = "wfl";
160    private static final String MISC_DATA = "m";
161    private static final String GLOBAL_NETWORK_DATA = "gn";
162    private static final String HISTORY_STRING_POOL = "hsp";
163    private static final String HISTORY_DATA = "h";
164    private static final String SCREEN_BRIGHTNESS_DATA = "br";
165    private static final String SIGNAL_STRENGTH_TIME_DATA = "sgt";
166    private static final String SIGNAL_SCANNING_TIME_DATA = "sst";
167    private static final String SIGNAL_STRENGTH_COUNT_DATA = "sgc";
168    private static final String DATA_CONNECTION_TIME_DATA = "dct";
169    private static final String DATA_CONNECTION_COUNT_DATA = "dcc";
170    private static final String WIFI_STATE_TIME_DATA = "wst";
171    private static final String WIFI_STATE_COUNT_DATA = "wsc";
172    private static final String BLUETOOTH_STATE_TIME_DATA = "bst";
173    private static final String BLUETOOTH_STATE_COUNT_DATA = "bsc";
174    private static final String POWER_USE_SUMMARY_DATA = "pws";
175    private static final String POWER_USE_ITEM_DATA = "pwi";
176
177    private final StringBuilder mFormatBuilder = new StringBuilder(32);
178    private final Formatter mFormatter = new Formatter(mFormatBuilder);
179
180    /**
181     * State for keeping track of counting information.
182     */
183    public static abstract class Counter {
184
185        /**
186         * Returns the count associated with this Counter for the
187         * selected type of statistics.
188         *
189         * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT
190         */
191        public abstract int getCountLocked(int which);
192
193        /**
194         * Temporary for debugging.
195         */
196        public abstract void logState(Printer pw, String prefix);
197    }
198
199    /**
200     * State for keeping track of long counting information.
201     */
202    public static abstract class LongCounter {
203
204        /**
205         * Returns the count associated with this Counter for the
206         * selected type of statistics.
207         *
208         * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT
209         */
210        public abstract long getCountLocked(int which);
211
212        /**
213         * Temporary for debugging.
214         */
215        public abstract void logState(Printer pw, String prefix);
216    }
217
218    /**
219     * State for keeping track of timing information.
220     */
221    public static abstract class Timer {
222
223        /**
224         * Returns the count associated with this Timer for the
225         * selected type of statistics.
226         *
227         * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT
228         */
229        public abstract int getCountLocked(int which);
230
231        /**
232         * Returns the total time in microseconds associated with this Timer for the
233         * selected type of statistics.
234         *
235         * @param elapsedRealtimeUs current elapsed realtime of system in microseconds
236         * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT
237         * @return a time in microseconds
238         */
239        public abstract long getTotalTimeLocked(long elapsedRealtimeUs, int which);
240
241        /**
242         * Temporary for debugging.
243         */
244        public abstract void logState(Printer pw, String prefix);
245    }
246
247    /**
248     * The statistics associated with a particular uid.
249     */
250    public static abstract class Uid {
251
252        /**
253         * Returns a mapping containing wakelock statistics.
254         *
255         * @return a Map from Strings to Uid.Wakelock objects.
256         */
257        public abstract Map<String, ? extends Wakelock> getWakelockStats();
258
259        /**
260         * The statistics associated with a particular wake lock.
261         */
262        public static abstract class Wakelock {
263            public abstract Timer getWakeTime(int type);
264        }
265
266        /**
267         * Returns a mapping containing sensor statistics.
268         *
269         * @return a Map from Integer sensor ids to Uid.Sensor objects.
270         */
271        public abstract Map<Integer, ? extends Sensor> getSensorStats();
272
273        /**
274         * Returns a mapping containing active process data.
275         */
276        public abstract SparseArray<? extends Pid> getPidStats();
277
278        /**
279         * Returns a mapping containing process statistics.
280         *
281         * @return a Map from Strings to Uid.Proc objects.
282         */
283        public abstract Map<String, ? extends Proc> getProcessStats();
284
285        /**
286         * Returns a mapping containing package statistics.
287         *
288         * @return a Map from Strings to Uid.Pkg objects.
289         */
290        public abstract Map<String, ? extends Pkg> getPackageStats();
291
292        /**
293         * {@hide}
294         */
295        public abstract int getUid();
296
297        public abstract void noteWifiRunningLocked(long elapsedRealtime);
298        public abstract void noteWifiStoppedLocked(long elapsedRealtime);
299        public abstract void noteFullWifiLockAcquiredLocked(long elapsedRealtime);
300        public abstract void noteFullWifiLockReleasedLocked(long elapsedRealtime);
301        public abstract void noteWifiScanStartedLocked(long elapsedRealtime);
302        public abstract void noteWifiScanStoppedLocked(long elapsedRealtime);
303        public abstract void noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtime);
304        public abstract void noteWifiBatchedScanStoppedLocked(long elapsedRealtime);
305        public abstract void noteWifiMulticastEnabledLocked(long elapsedRealtime);
306        public abstract void noteWifiMulticastDisabledLocked(long elapsedRealtime);
307        public abstract void noteAudioTurnedOnLocked(long elapsedRealtime);
308        public abstract void noteAudioTurnedOffLocked(long elapsedRealtime);
309        public abstract void noteVideoTurnedOnLocked(long elapsedRealtime);
310        public abstract void noteVideoTurnedOffLocked(long elapsedRealtime);
311        public abstract void noteActivityResumedLocked(long elapsedRealtime);
312        public abstract void noteActivityPausedLocked(long elapsedRealtime);
313        public abstract long getWifiRunningTime(long elapsedRealtimeUs, int which);
314        public abstract long getFullWifiLockTime(long elapsedRealtimeUs, int which);
315        public abstract long getWifiScanTime(long elapsedRealtimeUs, int which);
316        public abstract long getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which);
317        public abstract long getWifiMulticastTime(long elapsedRealtimeUs, int which);
318        public abstract long getAudioTurnedOnTime(long elapsedRealtimeUs, int which);
319        public abstract long getVideoTurnedOnTime(long elapsedRealtimeUs, int which);
320        public abstract Timer getForegroundActivityTimer();
321        public abstract Timer getVibratorOnTimer();
322
323        public static final int NUM_WIFI_BATCHED_SCAN_BINS = 5;
324
325        /**
326         * Note that these must match the constants in android.os.PowerManager.
327         * Also, if the user activity types change, the BatteryStatsImpl.VERSION must
328         * also be bumped.
329         */
330        static final String[] USER_ACTIVITY_TYPES = {
331            "other", "button", "touch"
332        };
333
334        public static final int NUM_USER_ACTIVITY_TYPES = 3;
335
336        public abstract void noteUserActivityLocked(int type);
337        public abstract boolean hasUserActivity();
338        public abstract int getUserActivityCount(int type, int which);
339
340        public abstract boolean hasNetworkActivity();
341        public abstract long getNetworkActivityBytes(int type, int which);
342        public abstract long getNetworkActivityPackets(int type, int which);
343        public abstract long getMobileRadioActiveTime(int which);
344        public abstract int getMobileRadioActiveCount(int which);
345
346        public static abstract class Sensor {
347            /*
348             * FIXME: it's not correct to use this magic value because it
349             * could clash with a sensor handle (which are defined by
350             * the sensor HAL, and therefore out of our control
351             */
352            // Magic sensor number for the GPS.
353            public static final int GPS = -10000;
354
355            public abstract int getHandle();
356
357            public abstract Timer getSensorTime();
358        }
359
360        public class Pid {
361            public int mWakeNesting;
362            public long mWakeSumMs;
363            public long mWakeStartMs;
364        }
365
366        /**
367         * The statistics associated with a particular process.
368         */
369        public static abstract class Proc {
370
371            public static class ExcessivePower {
372                public static final int TYPE_WAKE = 1;
373                public static final int TYPE_CPU = 2;
374
375                public int type;
376                public long overTime;
377                public long usedTime;
378            }
379
380            /**
381             * Returns true if this process is still active in the battery stats.
382             */
383            public abstract boolean isActive();
384
385            /**
386             * Returns the total time (in 1/100 sec) spent executing in user code.
387             *
388             * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
389             */
390            public abstract long getUserTime(int which);
391
392            /**
393             * Returns the total time (in 1/100 sec) spent executing in system code.
394             *
395             * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
396             */
397            public abstract long getSystemTime(int which);
398
399            /**
400             * Returns the number of times the process has been started.
401             *
402             * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
403             */
404            public abstract int getStarts(int which);
405
406            /**
407             * Returns the cpu time spent in microseconds while the process was in the foreground.
408             * @param which one of STATS_TOTAL, STATS_LAST, STATS_CURRENT or STATS_UNPLUGGED
409             * @return foreground cpu time in microseconds
410             */
411            public abstract long getForegroundTime(int which);
412
413            /**
414             * Returns the approximate cpu time spent in microseconds, at a certain CPU speed.
415             * @param speedStep the index of the CPU speed. This is not the actual speed of the
416             * CPU.
417             * @param which one of STATS_TOTAL, STATS_LAST, STATS_CURRENT or STATS_UNPLUGGED
418             * @see BatteryStats#getCpuSpeedSteps()
419             */
420            public abstract long getTimeAtCpuSpeedStep(int speedStep, int which);
421
422            public abstract int countExcessivePowers();
423
424            public abstract ExcessivePower getExcessivePower(int i);
425        }
426
427        /**
428         * The statistics associated with a particular package.
429         */
430        public static abstract class Pkg {
431
432            /**
433             * Returns the number of times this package has done something that could wake up the
434             * device from sleep.
435             *
436             * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
437             */
438            public abstract int getWakeups(int which);
439
440            /**
441             * Returns a mapping containing service statistics.
442             */
443            public abstract Map<String, ? extends Serv> getServiceStats();
444
445            /**
446             * The statistics associated with a particular service.
447             */
448            public abstract class Serv {
449
450                /**
451                 * Returns the amount of time spent started.
452                 *
453                 * @param batteryUptime elapsed uptime on battery in microseconds.
454                 * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
455                 * @return
456                 */
457                public abstract long getStartTime(long batteryUptime, int which);
458
459                /**
460                 * Returns the total number of times startService() has been called.
461                 *
462                 * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
463                 */
464                public abstract int getStarts(int which);
465
466                /**
467                 * Returns the total number times the service has been launched.
468                 *
469                 * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
470                 */
471                public abstract int getLaunches(int which);
472            }
473        }
474    }
475
476    public final static class HistoryTag {
477        public String string;
478        public int uid;
479
480        public int poolIdx;
481
482        public void setTo(HistoryTag o) {
483            string = o.string;
484            uid = o.uid;
485            poolIdx = o.poolIdx;
486        }
487
488        public void setTo(String _string, int _uid) {
489            string = _string;
490            uid = _uid;
491            poolIdx = -1;
492        }
493
494        public void writeToParcel(Parcel dest, int flags) {
495            dest.writeString(string);
496            dest.writeInt(uid);
497        }
498
499        public void readFromParcel(Parcel src) {
500            string = src.readString();
501            uid = src.readInt();
502            poolIdx = -1;
503        }
504
505        @Override
506        public boolean equals(Object o) {
507            if (this == o) return true;
508            if (o == null || getClass() != o.getClass()) return false;
509
510            HistoryTag that = (HistoryTag) o;
511
512            if (uid != that.uid) return false;
513            if (!string.equals(that.string)) return false;
514
515            return true;
516        }
517
518        @Override
519        public int hashCode() {
520            int result = string.hashCode();
521            result = 31 * result + uid;
522            return result;
523        }
524    }
525
526    public final static class HistoryItem implements Parcelable {
527        public HistoryItem next;
528
529        public long time;
530
531        public static final byte CMD_UPDATE = 0;        // These can be written as deltas
532        public static final byte CMD_NULL = -1;
533        public static final byte CMD_START = 4;
534        public static final byte CMD_CURRENT_TIME = 5;
535        public static final byte CMD_OVERFLOW = 6;
536
537        public byte cmd = CMD_NULL;
538
539        /**
540         * Return whether the command code is a delta data update.
541         */
542        public boolean isDeltaData() {
543            return cmd == CMD_UPDATE;
544        }
545
546        public byte batteryLevel;
547        public byte batteryStatus;
548        public byte batteryHealth;
549        public byte batteryPlugType;
550
551        public short batteryTemperature;
552        public char batteryVoltage;
553
554        // Constants from SCREEN_BRIGHTNESS_*
555        public static final int STATE_BRIGHTNESS_SHIFT = 0;
556        public static final int STATE_BRIGHTNESS_MASK = 0x7;
557        // Constants from SIGNAL_STRENGTH_*
558        public static final int STATE_SIGNAL_STRENGTH_SHIFT = 3;
559        public static final int STATE_SIGNAL_STRENGTH_MASK = 0x7 << STATE_SIGNAL_STRENGTH_SHIFT;
560        // Constants from ServiceState.STATE_*
561        public static final int STATE_PHONE_STATE_SHIFT = 6;
562        public static final int STATE_PHONE_STATE_MASK = 0x7 << STATE_PHONE_STATE_SHIFT;
563        // Constants from DATA_CONNECTION_*
564        public static final int STATE_DATA_CONNECTION_SHIFT = 9;
565        public static final int STATE_DATA_CONNECTION_MASK = 0x1f << STATE_DATA_CONNECTION_SHIFT;
566
567        // These states always appear directly in the first int token
568        // of a delta change; they should be ones that change relatively
569        // frequently.
570        public static final int STATE_CPU_RUNNING_FLAG = 1<<31;
571        public static final int STATE_WAKE_LOCK_FLAG = 1<<30;
572        public static final int STATE_GPS_ON_FLAG = 1<<29;
573        public static final int STATE_WIFI_FULL_LOCK_FLAG = 1<<28;
574        public static final int STATE_WIFI_SCAN_FLAG = 1<<27;
575        public static final int STATE_WIFI_MULTICAST_ON_FLAG = 1<<26;
576        public static final int STATE_MOBILE_RADIO_ACTIVE_FLAG = 1<<25;
577        public static final int STATE_WIFI_RUNNING_FLAG = 1<<24;
578        // These are on the lower bits used for the command; if they change
579        // we need to write another int of data.
580        public static final int STATE_SENSOR_ON_FLAG = 1<<23;
581        public static final int STATE_AUDIO_ON_FLAG = 1<<22;
582        public static final int STATE_PHONE_SCANNING_FLAG = 1<<21;
583        public static final int STATE_SCREEN_ON_FLAG = 1<<20;
584        public static final int STATE_BATTERY_PLUGGED_FLAG = 1<<19;
585        public static final int STATE_PHONE_IN_CALL_FLAG = 1<<18;
586        public static final int STATE_WIFI_ON_FLAG = 1<<17;
587        public static final int STATE_BLUETOOTH_ON_FLAG = 1<<16;
588
589        public static final int MOST_INTERESTING_STATES =
590            STATE_BATTERY_PLUGGED_FLAG | STATE_SCREEN_ON_FLAG
591            | STATE_GPS_ON_FLAG | STATE_PHONE_IN_CALL_FLAG;
592
593        public int states;
594
595        public static final int STATE2_VIDEO_ON_FLAG = 1<<0;
596        public int states2;
597
598        // The wake lock that was acquired at this point.
599        public HistoryTag wakelockTag;
600
601        // Kernel wakeup reason at this point.
602        public HistoryTag wakeReasonTag;
603
604        public static final int EVENT_FLAG_START = 0x8000;
605        public static final int EVENT_FLAG_FINISH = 0x4000;
606
607        // No event in this item.
608        public static final int EVENT_NONE = 0x0000;
609        // Event is about a process that is running.
610        public static final int EVENT_PROC = 0x0001;
611        // Event is about an application package that is in the foreground.
612        public static final int EVENT_FOREGROUND = 0x0002;
613        // Event is about an application package that is at the top of the screen.
614        public static final int EVENT_TOP = 0x0003;
615        // Event is about an application package that is at the top of the screen.
616        public static final int EVENT_SYNC = 0x0004;
617        // Number of event types.
618        public static final int EVENT_COUNT = 0x0005;
619
620        public static final int EVENT_PROC_START = EVENT_PROC | EVENT_FLAG_START;
621        public static final int EVENT_PROC_FINISH = EVENT_PROC | EVENT_FLAG_FINISH;
622        public static final int EVENT_FOREGROUND_START = EVENT_FOREGROUND | EVENT_FLAG_START;
623        public static final int EVENT_FOREGROUND_FINISH = EVENT_FOREGROUND | EVENT_FLAG_FINISH;
624        public static final int EVENT_TOP_START = EVENT_TOP | EVENT_FLAG_START;
625        public static final int EVENT_TOP_FINISH = EVENT_TOP | EVENT_FLAG_FINISH;
626        public static final int EVENT_SYNC_START = EVENT_SYNC | EVENT_FLAG_START;
627        public static final int EVENT_SYNC_FINISH = EVENT_SYNC | EVENT_FLAG_FINISH;
628
629        // For CMD_EVENT.
630        public int eventCode;
631        public HistoryTag eventTag;
632
633        // Only set for CMD_CURRENT_TIME.
634        public long currentTime;
635
636        // Meta-data when reading.
637        public int numReadInts;
638
639        // Pre-allocated objects.
640        public final HistoryTag localWakelockTag = new HistoryTag();
641        public final HistoryTag localWakeReasonTag = new HistoryTag();
642        public final HistoryTag localEventTag = new HistoryTag();
643
644        public HistoryItem() {
645        }
646
647        public HistoryItem(long time, Parcel src) {
648            this.time = time;
649            numReadInts = 2;
650            readFromParcel(src);
651        }
652
653        public int describeContents() {
654            return 0;
655        }
656
657        public void writeToParcel(Parcel dest, int flags) {
658            dest.writeLong(time);
659            int bat = (((int)cmd)&0xff)
660                    | ((((int)batteryLevel)<<8)&0xff00)
661                    | ((((int)batteryStatus)<<16)&0xf0000)
662                    | ((((int)batteryHealth)<<20)&0xf00000)
663                    | ((((int)batteryPlugType)<<24)&0xf000000)
664                    | (wakelockTag != null ? 0x10000000 : 0)
665                    | (wakeReasonTag != null ? 0x20000000 : 0)
666                    | (eventCode != EVENT_NONE ? 0x40000000 : 0);
667            dest.writeInt(bat);
668            bat = (((int)batteryTemperature)&0xffff)
669                    | ((((int)batteryVoltage)<<16)&0xffff0000);
670            dest.writeInt(bat);
671            dest.writeInt(states);
672            dest.writeInt(states2);
673            if (wakelockTag != null) {
674                wakelockTag.writeToParcel(dest, flags);
675            }
676            if (wakeReasonTag != null) {
677                wakeReasonTag.writeToParcel(dest, flags);
678            }
679            if (eventCode != EVENT_NONE) {
680                dest.writeInt(eventCode);
681                eventTag.writeToParcel(dest, flags);
682            }
683            if (cmd == CMD_CURRENT_TIME) {
684                dest.writeLong(currentTime);
685            }
686        }
687
688        public void readFromParcel(Parcel src) {
689            int start = src.dataPosition();
690            int bat = src.readInt();
691            cmd = (byte)(bat&0xff);
692            batteryLevel = (byte)((bat>>8)&0xff);
693            batteryStatus = (byte)((bat>>16)&0xf);
694            batteryHealth = (byte)((bat>>20)&0xf);
695            batteryPlugType = (byte)((bat>>24)&0xf);
696            int bat2 = src.readInt();
697            batteryTemperature = (short)(bat2&0xffff);
698            batteryVoltage = (char)((bat2>>16)&0xffff);
699            states = src.readInt();
700            states2 = src.readInt();
701            if ((bat&0x10000000) != 0) {
702                wakelockTag = localWakelockTag;
703                wakelockTag.readFromParcel(src);
704            } else {
705                wakelockTag = null;
706            }
707            if ((bat&0x20000000) != 0) {
708                wakeReasonTag = localWakeReasonTag;
709                wakeReasonTag.readFromParcel(src);
710            } else {
711                wakeReasonTag = null;
712            }
713            if ((bat&0x40000000) != 0) {
714                eventCode = src.readInt();
715                eventTag = localEventTag;
716                eventTag.readFromParcel(src);
717            } else {
718                eventCode = EVENT_NONE;
719                eventTag = null;
720            }
721            if (cmd == CMD_CURRENT_TIME) {
722                currentTime = src.readLong();
723            } else {
724                currentTime = 0;
725            }
726            numReadInts += (src.dataPosition()-start)/4;
727        }
728
729        public void clear() {
730            time = 0;
731            cmd = CMD_NULL;
732            batteryLevel = 0;
733            batteryStatus = 0;
734            batteryHealth = 0;
735            batteryPlugType = 0;
736            batteryTemperature = 0;
737            batteryVoltage = 0;
738            states = 0;
739            states2 = 0;
740            wakelockTag = null;
741            wakeReasonTag = null;
742            eventCode = EVENT_NONE;
743            eventTag = null;
744        }
745
746        public void setTo(HistoryItem o) {
747            time = o.time;
748            cmd = o.cmd;
749            setToCommon(o);
750        }
751
752        public void setTo(long time, byte cmd, HistoryItem o) {
753            this.time = time;
754            this.cmd = cmd;
755            setToCommon(o);
756        }
757
758        private void setToCommon(HistoryItem o) {
759            batteryLevel = o.batteryLevel;
760            batteryStatus = o.batteryStatus;
761            batteryHealth = o.batteryHealth;
762            batteryPlugType = o.batteryPlugType;
763            batteryTemperature = o.batteryTemperature;
764            batteryVoltage = o.batteryVoltage;
765            states = o.states;
766            states2 = o.states2;
767            if (o.wakelockTag != null) {
768                wakelockTag = localWakelockTag;
769                wakelockTag.setTo(o.wakelockTag);
770            } else {
771                wakelockTag = null;
772            }
773            if (o.wakeReasonTag != null) {
774                wakeReasonTag = localWakeReasonTag;
775                wakeReasonTag.setTo(o.wakeReasonTag);
776            } else {
777                wakeReasonTag = null;
778            }
779            eventCode = o.eventCode;
780            if (o.eventTag != null) {
781                eventTag = localEventTag;
782                eventTag.setTo(o.eventTag);
783            } else {
784                eventTag = null;
785            }
786            currentTime = o.currentTime;
787        }
788
789        public boolean sameNonEvent(HistoryItem o) {
790            return batteryLevel == o.batteryLevel
791                    && batteryStatus == o.batteryStatus
792                    && batteryHealth == o.batteryHealth
793                    && batteryPlugType == o.batteryPlugType
794                    && batteryTemperature == o.batteryTemperature
795                    && batteryVoltage == o.batteryVoltage
796                    && states == o.states
797                    && states2 == o.states2
798                    && currentTime == o.currentTime;
799        }
800
801        public boolean same(HistoryItem o) {
802            if (!sameNonEvent(o) || eventCode != o.eventCode) {
803                return false;
804            }
805            if (wakelockTag != o.wakelockTag) {
806                if (wakelockTag == null || o.wakelockTag == null) {
807                    return false;
808                }
809                if (!wakelockTag.equals(o.wakelockTag)) {
810                    return false;
811                }
812            }
813            if (wakeReasonTag != o.wakeReasonTag) {
814                if (wakeReasonTag == null || o.wakeReasonTag == null) {
815                    return false;
816                }
817                if (!wakeReasonTag.equals(o.wakeReasonTag)) {
818                    return false;
819                }
820            }
821            if (eventTag != o.eventTag) {
822                if (eventTag == null || o.eventTag == null) {
823                    return false;
824                }
825                if (!eventTag.equals(o.eventTag)) {
826                    return false;
827                }
828            }
829            return true;
830        }
831    }
832
833    public static final class BitDescription {
834        public final int mask;
835        public final int shift;
836        public final String name;
837        public final String shortName;
838        public final String[] values;
839        public final String[] shortValues;
840
841        public BitDescription(int mask, String name, String shortName) {
842            this.mask = mask;
843            this.shift = -1;
844            this.name = name;
845            this.shortName = shortName;
846            this.values = null;
847            this.shortValues = null;
848        }
849
850        public BitDescription(int mask, int shift, String name, String shortName,
851                String[] values, String[] shortValues) {
852            this.mask = mask;
853            this.shift = shift;
854            this.name = name;
855            this.shortName = shortName;
856            this.values = values;
857            this.shortValues = shortValues;
858        }
859    }
860
861    public abstract int getHistoryTotalSize();
862
863    public abstract int getHistoryUsedSize();
864
865    public abstract boolean startIteratingHistoryLocked();
866
867    public abstract int getHistoryStringPoolSize();
868
869    public abstract int getHistoryStringPoolBytes();
870
871    public abstract String getHistoryTagPoolString(int index);
872
873    public abstract int getHistoryTagPoolUid(int index);
874
875    public abstract boolean getNextHistoryLocked(HistoryItem out);
876
877    public abstract void finishIteratingHistoryLocked();
878
879    public abstract boolean startIteratingOldHistoryLocked();
880
881    public abstract boolean getNextOldHistoryLocked(HistoryItem out);
882
883    public abstract void finishIteratingOldHistoryLocked();
884
885    /**
886     * Return the base time offset for the battery history.
887     */
888    public abstract long getHistoryBaseTime();
889
890    /**
891     * Returns the number of times the device has been started.
892     */
893    public abstract int getStartCount();
894
895    /**
896     * Returns the time in microseconds that the screen has been on while the device was
897     * running on battery.
898     *
899     * {@hide}
900     */
901    public abstract long getScreenOnTime(long elapsedRealtimeUs, int which);
902
903    /**
904     * Returns the number of times the screen was turned on.
905     *
906     * {@hide}
907     */
908    public abstract int getScreenOnCount(int which);
909
910    public static final int SCREEN_BRIGHTNESS_DARK = 0;
911    public static final int SCREEN_BRIGHTNESS_DIM = 1;
912    public static final int SCREEN_BRIGHTNESS_MEDIUM = 2;
913    public static final int SCREEN_BRIGHTNESS_LIGHT = 3;
914    public static final int SCREEN_BRIGHTNESS_BRIGHT = 4;
915
916    static final String[] SCREEN_BRIGHTNESS_NAMES = {
917        "dark", "dim", "medium", "light", "bright"
918    };
919
920    static final String[] SCREEN_BRIGHTNESS_SHORT_NAMES = {
921        "0", "1", "2", "3", "4"
922    };
923
924    public static final int NUM_SCREEN_BRIGHTNESS_BINS = 5;
925
926    /**
927     * Returns the time in microseconds that the screen has been on with
928     * the given brightness
929     *
930     * {@hide}
931     */
932    public abstract long getScreenBrightnessTime(int brightnessBin,
933            long elapsedRealtimeUs, int which);
934
935    public abstract int getInputEventCount(int which);
936
937    /**
938     * Returns the time in microseconds that the phone has been on while the device was
939     * running on battery.
940     *
941     * {@hide}
942     */
943    public abstract long getPhoneOnTime(long elapsedRealtimeUs, int which);
944
945    /**
946     * Returns the number of times a phone call was activated.
947     *
948     * {@hide}
949     */
950    public abstract int getPhoneOnCount(int which);
951
952    /**
953     * Returns the time in microseconds that the phone has been running with
954     * the given signal strength.
955     *
956     * {@hide}
957     */
958    public abstract long getPhoneSignalStrengthTime(int strengthBin,
959            long elapsedRealtimeUs, int which);
960
961    /**
962     * Returns the time in microseconds that the phone has been trying to
963     * acquire a signal.
964     *
965     * {@hide}
966     */
967    public abstract long getPhoneSignalScanningTime(
968            long elapsedRealtimeUs, int which);
969
970    /**
971     * Returns the number of times the phone has entered the given signal strength.
972     *
973     * {@hide}
974     */
975    public abstract int getPhoneSignalStrengthCount(int strengthBin, int which);
976
977    /**
978     * Returns the time in microseconds that the mobile network has been active
979     * (in a high power state).
980     *
981     * {@hide}
982     */
983    public abstract long getMobileRadioActiveTime(long elapsedRealtimeUs, int which);
984
985    /**
986     * Returns the number of times that the mobile network has transitioned to the
987     * active state.
988     *
989     * {@hide}
990     */
991    public abstract int getMobileRadioActiveCount(int which);
992
993    /**
994     * Returns the time in microseconds that is the difference between the mobile radio
995     * time we saw based on the elapsed timestamp when going down vs. the given time stamp
996     * from the radio.
997     *
998     * {@hide}
999     */
1000    public abstract long getMobileRadioActiveAdjustedTime(int which);
1001
1002    /**
1003     * Returns the time in microseconds that the mobile network has been active
1004     * (in a high power state) but not being able to blame on an app.
1005     *
1006     * {@hide}
1007     */
1008    public abstract long getMobileRadioActiveUnknownTime(int which);
1009
1010    /**
1011     * Return count of number of times radio was up that could not be blamed on apps.
1012     *
1013     * {@hide}
1014     */
1015    public abstract int getMobileRadioActiveUnknownCount(int which);
1016
1017    public static final int DATA_CONNECTION_NONE = 0;
1018    public static final int DATA_CONNECTION_GPRS = 1;
1019    public static final int DATA_CONNECTION_EDGE = 2;
1020    public static final int DATA_CONNECTION_UMTS = 3;
1021    public static final int DATA_CONNECTION_CDMA = 4;
1022    public static final int DATA_CONNECTION_EVDO_0 = 5;
1023    public static final int DATA_CONNECTION_EVDO_A = 6;
1024    public static final int DATA_CONNECTION_1xRTT = 7;
1025    public static final int DATA_CONNECTION_HSDPA = 8;
1026    public static final int DATA_CONNECTION_HSUPA = 9;
1027    public static final int DATA_CONNECTION_HSPA = 10;
1028    public static final int DATA_CONNECTION_IDEN = 11;
1029    public static final int DATA_CONNECTION_EVDO_B = 12;
1030    public static final int DATA_CONNECTION_LTE = 13;
1031    public static final int DATA_CONNECTION_EHRPD = 14;
1032    public static final int DATA_CONNECTION_HSPAP = 15;
1033    public static final int DATA_CONNECTION_OTHER = 16;
1034
1035    static final String[] DATA_CONNECTION_NAMES = {
1036        "none", "gprs", "edge", "umts", "cdma", "evdo_0", "evdo_A",
1037        "1xrtt", "hsdpa", "hsupa", "hspa", "iden", "evdo_b", "lte",
1038        "ehrpd", "hspap", "other"
1039    };
1040
1041    public static final int NUM_DATA_CONNECTION_TYPES = DATA_CONNECTION_OTHER+1;
1042
1043    /**
1044     * Returns the time in microseconds that the phone has been running with
1045     * the given data connection.
1046     *
1047     * {@hide}
1048     */
1049    public abstract long getPhoneDataConnectionTime(int dataType,
1050            long elapsedRealtimeUs, int which);
1051
1052    /**
1053     * Returns the number of times the phone has entered the given data
1054     * connection type.
1055     *
1056     * {@hide}
1057     */
1058    public abstract int getPhoneDataConnectionCount(int dataType, int which);
1059
1060    public static final BitDescription[] HISTORY_STATE_DESCRIPTIONS
1061            = new BitDescription[] {
1062        new BitDescription(HistoryItem.STATE_CPU_RUNNING_FLAG, "running", "r"),
1063        new BitDescription(HistoryItem.STATE_WAKE_LOCK_FLAG, "wake_lock", "w"),
1064        new BitDescription(HistoryItem.STATE_SENSOR_ON_FLAG, "sensor", "s"),
1065        new BitDescription(HistoryItem.STATE_GPS_ON_FLAG, "gps", "g"),
1066        new BitDescription(HistoryItem.STATE_WIFI_FULL_LOCK_FLAG, "wifi_full_lock", "Wl"),
1067        new BitDescription(HistoryItem.STATE_WIFI_SCAN_FLAG, "wifi_scan", "Ws"),
1068        new BitDescription(HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG, "wifi_multicast", "Wm"),
1069        new BitDescription(HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG, "mobile_radio", "Pr"),
1070        new BitDescription(HistoryItem.STATE_WIFI_RUNNING_FLAG, "wifi_running", "Wr"),
1071        new BitDescription(HistoryItem.STATE_PHONE_SCANNING_FLAG, "phone_scanning", "Psc"),
1072        new BitDescription(HistoryItem.STATE_AUDIO_ON_FLAG, "audio", "a"),
1073        new BitDescription(HistoryItem.STATE_SCREEN_ON_FLAG, "screen", "S"),
1074        new BitDescription(HistoryItem.STATE_BATTERY_PLUGGED_FLAG, "plugged", "BP"),
1075        new BitDescription(HistoryItem.STATE_PHONE_IN_CALL_FLAG, "phone_in_call", "Pcl"),
1076        new BitDescription(HistoryItem.STATE_WIFI_ON_FLAG, "wifi", "W"),
1077        new BitDescription(HistoryItem.STATE_BLUETOOTH_ON_FLAG, "bluetooth", "b"),
1078        new BitDescription(HistoryItem.STATE_DATA_CONNECTION_MASK,
1079                HistoryItem.STATE_DATA_CONNECTION_SHIFT, "data_conn", "Pcn",
1080                DATA_CONNECTION_NAMES, DATA_CONNECTION_NAMES),
1081        new BitDescription(HistoryItem.STATE_PHONE_STATE_MASK,
1082                HistoryItem.STATE_PHONE_STATE_SHIFT, "phone_state", "Pst",
1083                new String[] {"in", "out", "emergency", "off"},
1084                new String[] {"in", "out", "em", "off"}),
1085        new BitDescription(HistoryItem.STATE_SIGNAL_STRENGTH_MASK,
1086                HistoryItem.STATE_SIGNAL_STRENGTH_SHIFT, "signal_strength", "Pss",
1087                SignalStrength.SIGNAL_STRENGTH_NAMES, new String[] {
1088                    "0", "1", "2", "3", "4"
1089        }),
1090        new BitDescription(HistoryItem.STATE_BRIGHTNESS_MASK,
1091                HistoryItem.STATE_BRIGHTNESS_SHIFT, "brightness", "Sb",
1092                SCREEN_BRIGHTNESS_NAMES, SCREEN_BRIGHTNESS_SHORT_NAMES),
1093    };
1094
1095    public static final BitDescription[] HISTORY_STATE2_DESCRIPTIONS
1096            = new BitDescription[] {
1097        new BitDescription(HistoryItem.STATE2_VIDEO_ON_FLAG, "video", "v"),
1098    };
1099
1100    public static final String[] HISTORY_EVENT_NAMES = new String[] {
1101            "null", "proc", "fg", "top", "sync"
1102    };
1103
1104    public static final String[] HISTORY_EVENT_CHECKIN_NAMES = new String[] {
1105            "Enl", "Epr", "Efg", "Etp", "Esy"
1106    };
1107
1108    /**
1109     * Returns the time in microseconds that wifi has been on while the device was
1110     * running on battery.
1111     *
1112     * {@hide}
1113     */
1114    public abstract long getWifiOnTime(long elapsedRealtimeUs, int which);
1115
1116    /**
1117     * Returns the time in microseconds that wifi has been on and the driver has
1118     * been in the running state while the device was running on battery.
1119     *
1120     * {@hide}
1121     */
1122    public abstract long getGlobalWifiRunningTime(long elapsedRealtimeUs, int which);
1123
1124    public static final int WIFI_STATE_OFF = 0;
1125    public static final int WIFI_STATE_OFF_SCANNING = 1;
1126    public static final int WIFI_STATE_ON_NO_NETWORKS = 2;
1127    public static final int WIFI_STATE_ON_DISCONNECTED = 3;
1128    public static final int WIFI_STATE_ON_CONNECTED_STA = 4;
1129    public static final int WIFI_STATE_ON_CONNECTED_P2P = 5;
1130    public static final int WIFI_STATE_ON_CONNECTED_STA_P2P = 6;
1131    public static final int WIFI_STATE_SOFT_AP = 7;
1132
1133    static final String[] WIFI_STATE_NAMES = {
1134        "off", "scanning", "no_net", "disconn",
1135        "sta", "p2p", "sta_p2p", "soft_ap"
1136    };
1137
1138    public static final int NUM_WIFI_STATES = WIFI_STATE_SOFT_AP+1;
1139
1140    /**
1141     * Returns the time in microseconds that WiFi has been running in the given state.
1142     *
1143     * {@hide}
1144     */
1145    public abstract long getWifiStateTime(int wifiState,
1146            long elapsedRealtimeUs, int which);
1147
1148    /**
1149     * Returns the number of times that WiFi has entered the given state.
1150     *
1151     * {@hide}
1152     */
1153    public abstract int getWifiStateCount(int wifiState, int which);
1154
1155    /**
1156     * Returns the time in microseconds that bluetooth has been on while the device was
1157     * running on battery.
1158     *
1159     * {@hide}
1160     */
1161    public abstract long getBluetoothOnTime(long elapsedRealtimeUs, int which);
1162
1163    public abstract int getBluetoothPingCount();
1164
1165    public static final int BLUETOOTH_STATE_INACTIVE = 0;
1166    public static final int BLUETOOTH_STATE_LOW = 1;
1167    public static final int BLUETOOTH_STATE_MEDIUM = 2;
1168    public static final int BLUETOOTH_STATE_HIGH = 3;
1169
1170    static final String[] BLUETOOTH_STATE_NAMES = {
1171        "inactive", "low", "med", "high"
1172    };
1173
1174    public static final int NUM_BLUETOOTH_STATES = BLUETOOTH_STATE_HIGH +1;
1175
1176    /**
1177     * Returns the time in microseconds that Bluetooth has been running in the
1178     * given active state.
1179     *
1180     * {@hide}
1181     */
1182    public abstract long getBluetoothStateTime(int bluetoothState,
1183            long elapsedRealtimeUs, int which);
1184
1185    /**
1186     * Returns the number of times that Bluetooth has entered the given active state.
1187     *
1188     * {@hide}
1189     */
1190    public abstract int getBluetoothStateCount(int bluetoothState, int which);
1191
1192    public static final int NETWORK_MOBILE_RX_DATA = 0;
1193    public static final int NETWORK_MOBILE_TX_DATA = 1;
1194    public static final int NETWORK_WIFI_RX_DATA = 2;
1195    public static final int NETWORK_WIFI_TX_DATA = 3;
1196
1197    public static final int NUM_NETWORK_ACTIVITY_TYPES = NETWORK_WIFI_TX_DATA + 1;
1198
1199    public abstract long getNetworkActivityBytes(int type, int which);
1200    public abstract long getNetworkActivityPackets(int type, int which);
1201
1202    /**
1203     * Return the wall clock time when battery stats data collection started.
1204     */
1205    public abstract long getStartClockTime();
1206
1207    /**
1208     * Return whether we are currently running on battery.
1209     */
1210    public abstract boolean getIsOnBattery();
1211
1212    /**
1213     * Returns a SparseArray containing the statistics for each uid.
1214     */
1215    public abstract SparseArray<? extends Uid> getUidStats();
1216
1217    /**
1218     * Returns the current battery uptime in microseconds.
1219     *
1220     * @param curTime the amount of elapsed realtime in microseconds.
1221     */
1222    public abstract long getBatteryUptime(long curTime);
1223
1224    /**
1225     * Returns the current battery realtime in microseconds.
1226     *
1227     * @param curTime the amount of elapsed realtime in microseconds.
1228     */
1229    public abstract long getBatteryRealtime(long curTime);
1230
1231    /**
1232     * Returns the battery percentage level at the last time the device was unplugged from power, or
1233     * the last time it booted on battery power.
1234     */
1235    public abstract int getDischargeStartLevel();
1236
1237    /**
1238     * Returns the current battery percentage level if we are in a discharge cycle, otherwise
1239     * returns the level at the last plug event.
1240     */
1241    public abstract int getDischargeCurrentLevel();
1242
1243    /**
1244     * Get the amount the battery has discharged since the stats were
1245     * last reset after charging, as a lower-end approximation.
1246     */
1247    public abstract int getLowDischargeAmountSinceCharge();
1248
1249    /**
1250     * Get the amount the battery has discharged since the stats were
1251     * last reset after charging, as an upper-end approximation.
1252     */
1253    public abstract int getHighDischargeAmountSinceCharge();
1254
1255    /**
1256     * Retrieve the discharge amount over the selected discharge period <var>which</var>.
1257     */
1258    public abstract int getDischargeAmount(int which);
1259
1260    /**
1261     * Get the amount the battery has discharged while the screen was on,
1262     * since the last time power was unplugged.
1263     */
1264    public abstract int getDischargeAmountScreenOn();
1265
1266    /**
1267     * Get the amount the battery has discharged while the screen was on,
1268     * since the last time the device was charged.
1269     */
1270    public abstract int getDischargeAmountScreenOnSinceCharge();
1271
1272    /**
1273     * Get the amount the battery has discharged while the screen was off,
1274     * since the last time power was unplugged.
1275     */
1276    public abstract int getDischargeAmountScreenOff();
1277
1278    /**
1279     * Get the amount the battery has discharged while the screen was off,
1280     * since the last time the device was charged.
1281     */
1282    public abstract int getDischargeAmountScreenOffSinceCharge();
1283
1284    /**
1285     * Returns the total, last, or current battery uptime in microseconds.
1286     *
1287     * @param curTime the elapsed realtime in microseconds.
1288     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
1289     */
1290    public abstract long computeBatteryUptime(long curTime, int which);
1291
1292    /**
1293     * Returns the total, last, or current battery realtime in microseconds.
1294     *
1295     * @param curTime the current elapsed realtime in microseconds.
1296     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
1297     */
1298    public abstract long computeBatteryRealtime(long curTime, int which);
1299
1300    /**
1301     * Returns the total, last, or current battery screen off uptime in microseconds.
1302     *
1303     * @param curTime the elapsed realtime in microseconds.
1304     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
1305     */
1306    public abstract long computeBatteryScreenOffUptime(long curTime, int which);
1307
1308    /**
1309     * Returns the total, last, or current battery screen off realtime in microseconds.
1310     *
1311     * @param curTime the current elapsed realtime in microseconds.
1312     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
1313     */
1314    public abstract long computeBatteryScreenOffRealtime(long curTime, int which);
1315
1316    /**
1317     * Returns the total, last, or current uptime in microseconds.
1318     *
1319     * @param curTime the current elapsed realtime in microseconds.
1320     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
1321     */
1322    public abstract long computeUptime(long curTime, int which);
1323
1324    /**
1325     * Returns the total, last, or current realtime in microseconds.
1326     * *
1327     * @param curTime the current elapsed realtime in microseconds.
1328     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
1329     */
1330    public abstract long computeRealtime(long curTime, int which);
1331
1332    public abstract Map<String, ? extends LongCounter> getWakeupReasonStats();
1333
1334    public abstract Map<String, ? extends Timer> getKernelWakelockStats();
1335
1336    /** Returns the number of different speeds that the CPU can run at */
1337    public abstract int getCpuSpeedSteps();
1338
1339    public abstract void writeToParcelWithoutUids(Parcel out, int flags);
1340
1341    private final static void formatTimeRaw(StringBuilder out, long seconds) {
1342        long days = seconds / (60 * 60 * 24);
1343        if (days != 0) {
1344            out.append(days);
1345            out.append("d ");
1346        }
1347        long used = days * 60 * 60 * 24;
1348
1349        long hours = (seconds - used) / (60 * 60);
1350        if (hours != 0 || used != 0) {
1351            out.append(hours);
1352            out.append("h ");
1353        }
1354        used += hours * 60 * 60;
1355
1356        long mins = (seconds-used) / 60;
1357        if (mins != 0 || used != 0) {
1358            out.append(mins);
1359            out.append("m ");
1360        }
1361        used += mins * 60;
1362
1363        if (seconds != 0 || used != 0) {
1364            out.append(seconds-used);
1365            out.append("s ");
1366        }
1367    }
1368
1369    public final static void formatTime(StringBuilder sb, long time) {
1370        long sec = time / 100;
1371        formatTimeRaw(sb, sec);
1372        sb.append((time - (sec * 100)) * 10);
1373        sb.append("ms ");
1374    }
1375
1376    public final static void formatTimeMs(StringBuilder sb, long time) {
1377        long sec = time / 1000;
1378        formatTimeRaw(sb, sec);
1379        sb.append(time - (sec * 1000));
1380        sb.append("ms ");
1381    }
1382
1383    public final static void formatTimeMsNoSpace(StringBuilder sb, long time) {
1384        long sec = time / 1000;
1385        formatTimeRaw(sb, sec);
1386        sb.append(time - (sec * 1000));
1387        sb.append("ms");
1388    }
1389
1390    public final String formatRatioLocked(long num, long den) {
1391        if (den == 0L) {
1392            return "--%";
1393        }
1394        float perc = ((float)num) / ((float)den) * 100;
1395        mFormatBuilder.setLength(0);
1396        mFormatter.format("%.1f%%", perc);
1397        return mFormatBuilder.toString();
1398    }
1399
1400    final String formatBytesLocked(long bytes) {
1401        mFormatBuilder.setLength(0);
1402
1403        if (bytes < BYTES_PER_KB) {
1404            return bytes + "B";
1405        } else if (bytes < BYTES_PER_MB) {
1406            mFormatter.format("%.2fKB", bytes / (double) BYTES_PER_KB);
1407            return mFormatBuilder.toString();
1408        } else if (bytes < BYTES_PER_GB){
1409            mFormatter.format("%.2fMB", bytes / (double) BYTES_PER_MB);
1410            return mFormatBuilder.toString();
1411        } else {
1412            mFormatter.format("%.2fGB", bytes / (double) BYTES_PER_GB);
1413            return mFormatBuilder.toString();
1414        }
1415    }
1416
1417    private static long computeWakeLock(Timer timer, long elapsedRealtimeUs, int which) {
1418        if (timer != null) {
1419            // Convert from microseconds to milliseconds with rounding
1420            long totalTimeMicros = timer.getTotalTimeLocked(elapsedRealtimeUs, which);
1421            long totalTimeMillis = (totalTimeMicros + 500) / 1000;
1422            return totalTimeMillis;
1423        }
1424        return 0;
1425    }
1426
1427    /**
1428     *
1429     * @param sb a StringBuilder object.
1430     * @param timer a Timer object contining the wakelock times.
1431     * @param elapsedRealtimeUs the current on-battery time in microseconds.
1432     * @param name the name of the wakelock.
1433     * @param which which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
1434     * @param linePrefix a String to be prepended to each line of output.
1435     * @return the line prefix
1436     */
1437    private static final String printWakeLock(StringBuilder sb, Timer timer,
1438            long elapsedRealtimeUs, String name, int which, String linePrefix) {
1439
1440        if (timer != null) {
1441            long totalTimeMillis = computeWakeLock(timer, elapsedRealtimeUs, which);
1442
1443            int count = timer.getCountLocked(which);
1444            if (totalTimeMillis != 0) {
1445                sb.append(linePrefix);
1446                formatTimeMs(sb, totalTimeMillis);
1447                if (name != null) {
1448                    sb.append(name);
1449                    sb.append(' ');
1450                }
1451                sb.append('(');
1452                sb.append(count);
1453                sb.append(" times)");
1454                return ", ";
1455            }
1456        }
1457        return linePrefix;
1458    }
1459
1460    /**
1461     * Checkin version of wakelock printer. Prints simple comma-separated list.
1462     *
1463     * @param sb a StringBuilder object.
1464     * @param timer a Timer object contining the wakelock times.
1465     * @param elapsedRealtimeUs the current time in microseconds.
1466     * @param name the name of the wakelock.
1467     * @param which which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
1468     * @param linePrefix a String to be prepended to each line of output.
1469     * @return the line prefix
1470     */
1471    private static final String printWakeLockCheckin(StringBuilder sb, Timer timer,
1472            long elapsedRealtimeUs, String name, int which, String linePrefix) {
1473        long totalTimeMicros = 0;
1474        int count = 0;
1475        if (timer != null) {
1476            totalTimeMicros = timer.getTotalTimeLocked(elapsedRealtimeUs, which);
1477            count = timer.getCountLocked(which);
1478        }
1479        sb.append(linePrefix);
1480        sb.append((totalTimeMicros + 500) / 1000); // microseconds to milliseconds with rounding
1481        sb.append(',');
1482        sb.append(name != null ? name + "," : "");
1483        sb.append(count);
1484        return ",";
1485    }
1486
1487    /**
1488     * Dump a comma-separated line of values for terse checkin mode.
1489     *
1490     * @param pw the PageWriter to dump log to
1491     * @param category category of data (e.g. "total", "last", "unplugged", "current" )
1492     * @param type type of data (e.g. "wakelock", "sensor", "process", "apk" ,  "process", "network")
1493     * @param args type-dependent data arguments
1494     */
1495    private static final void dumpLine(PrintWriter pw, int uid, String category, String type,
1496           Object... args ) {
1497        pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
1498        pw.print(uid); pw.print(',');
1499        pw.print(category); pw.print(',');
1500        pw.print(type);
1501
1502        for (Object arg : args) {
1503            pw.print(',');
1504            pw.print(arg);
1505        }
1506        pw.println();
1507    }
1508
1509    /**
1510     * Checkin server version of dump to produce more compact, computer-readable log.
1511     *
1512     * NOTE: all times are expressed in 'ms'.
1513     */
1514    public final void dumpCheckinLocked(Context context, PrintWriter pw, int which, int reqUid) {
1515        final long rawUptime = SystemClock.uptimeMillis() * 1000;
1516        final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
1517        final long batteryUptime = getBatteryUptime(rawUptime);
1518        final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
1519        final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
1520        final long whichBatteryScreenOffUptime = computeBatteryScreenOffUptime(rawUptime, which);
1521        final long whichBatteryScreenOffRealtime = computeBatteryScreenOffRealtime(rawRealtime,
1522                which);
1523        final long totalRealtime = computeRealtime(rawRealtime, which);
1524        final long totalUptime = computeUptime(rawUptime, which);
1525        final long screenOnTime = getScreenOnTime(rawRealtime, which);
1526        final long phoneOnTime = getPhoneOnTime(rawRealtime, which);
1527        final long wifiOnTime = getWifiOnTime(rawRealtime, which);
1528        final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which);
1529        final long bluetoothOnTime = getBluetoothOnTime(rawRealtime, which);
1530
1531        StringBuilder sb = new StringBuilder(128);
1532
1533        SparseArray<? extends Uid> uidStats = getUidStats();
1534        final int NU = uidStats.size();
1535
1536        String category = STAT_NAMES[which];
1537
1538        // Dump "battery" stat
1539        dumpLine(pw, 0 /* uid */, category, BATTERY_DATA,
1540                which == STATS_SINCE_CHARGED ? getStartCount() : "N/A",
1541                whichBatteryRealtime / 1000, whichBatteryUptime / 1000,
1542                totalRealtime / 1000, totalUptime / 1000,
1543                getStartClockTime(),
1544                whichBatteryScreenOffRealtime / 1000, whichBatteryScreenOffUptime / 1000);
1545
1546        // Calculate wakelock times across all uids.
1547        long fullWakeLockTimeTotal = 0;
1548        long partialWakeLockTimeTotal = 0;
1549
1550        for (int iu = 0; iu < NU; iu++) {
1551            Uid u = uidStats.valueAt(iu);
1552
1553            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
1554            if (wakelocks.size() > 0) {
1555                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
1556                        : wakelocks.entrySet()) {
1557                    Uid.Wakelock wl = ent.getValue();
1558
1559                    Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
1560                    if (fullWakeTimer != null) {
1561                        fullWakeLockTimeTotal += fullWakeTimer.getTotalTimeLocked(rawRealtime,
1562                                which);
1563                    }
1564
1565                    Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
1566                    if (partialWakeTimer != null) {
1567                        partialWakeLockTimeTotal += partialWakeTimer.getTotalTimeLocked(
1568                            rawRealtime, which);
1569                    }
1570                }
1571            }
1572        }
1573
1574        long mobileRxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
1575        long mobileTxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
1576        long wifiRxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
1577        long wifiTxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
1578        long mobileRxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
1579        long mobileTxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
1580        long wifiRxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
1581        long wifiTxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
1582
1583        // Dump network stats
1584        dumpLine(pw, 0 /* uid */, category, GLOBAL_NETWORK_DATA,
1585                mobileRxTotalBytes, mobileTxTotalBytes, wifiRxTotalBytes, wifiTxTotalBytes,
1586                mobileRxTotalPackets, mobileTxTotalPackets, wifiRxTotalPackets, wifiTxTotalPackets);
1587
1588        // Dump misc stats
1589        dumpLine(pw, 0 /* uid */, category, MISC_DATA,
1590                screenOnTime / 1000, phoneOnTime / 1000, wifiOnTime / 1000,
1591                wifiRunningTime / 1000, bluetoothOnTime / 1000,
1592                mobileRxTotalBytes, mobileTxTotalBytes, wifiRxTotalBytes, wifiTxTotalBytes,
1593                fullWakeLockTimeTotal, partialWakeLockTimeTotal,
1594                getInputEventCount(which), getMobileRadioActiveTime(rawRealtime, which),
1595                getMobileRadioActiveAdjustedTime(which));
1596
1597        // Dump screen brightness stats
1598        Object[] args = new Object[NUM_SCREEN_BRIGHTNESS_BINS];
1599        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
1600            args[i] = getScreenBrightnessTime(i, rawRealtime, which) / 1000;
1601        }
1602        dumpLine(pw, 0 /* uid */, category, SCREEN_BRIGHTNESS_DATA, args);
1603
1604        // Dump signal strength stats
1605        args = new Object[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
1606        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
1607            args[i] = getPhoneSignalStrengthTime(i, rawRealtime, which) / 1000;
1608        }
1609        dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_TIME_DATA, args);
1610        dumpLine(pw, 0 /* uid */, category, SIGNAL_SCANNING_TIME_DATA,
1611                getPhoneSignalScanningTime(rawRealtime, which) / 1000);
1612        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
1613            args[i] = getPhoneSignalStrengthCount(i, which);
1614        }
1615        dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_COUNT_DATA, args);
1616
1617        // Dump network type stats
1618        args = new Object[NUM_DATA_CONNECTION_TYPES];
1619        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
1620            args[i] = getPhoneDataConnectionTime(i, rawRealtime, which) / 1000;
1621        }
1622        dumpLine(pw, 0 /* uid */, category, DATA_CONNECTION_TIME_DATA, args);
1623        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
1624            args[i] = getPhoneDataConnectionCount(i, which);
1625        }
1626        dumpLine(pw, 0 /* uid */, category, DATA_CONNECTION_COUNT_DATA, args);
1627
1628        // Dump wifi state stats
1629        args = new Object[NUM_WIFI_STATES];
1630        for (int i=0; i<NUM_WIFI_STATES; i++) {
1631            args[i] = getWifiStateTime(i, rawRealtime, which) / 1000;
1632        }
1633        dumpLine(pw, 0 /* uid */, category, WIFI_STATE_TIME_DATA, args);
1634        for (int i=0; i<NUM_WIFI_STATES; i++) {
1635            args[i] = getWifiStateCount(i, which);
1636        }
1637        dumpLine(pw, 0 /* uid */, category, WIFI_STATE_COUNT_DATA, args);
1638
1639        // Dump bluetooth state stats
1640        args = new Object[NUM_BLUETOOTH_STATES];
1641        for (int i=0; i<NUM_BLUETOOTH_STATES; i++) {
1642            args[i] = getBluetoothStateTime(i, rawRealtime, which) / 1000;
1643        }
1644        dumpLine(pw, 0 /* uid */, category, BLUETOOTH_STATE_TIME_DATA, args);
1645        for (int i=0; i<NUM_BLUETOOTH_STATES; i++) {
1646            args[i] = getBluetoothStateCount(i, which);
1647        }
1648        dumpLine(pw, 0 /* uid */, category, BLUETOOTH_STATE_COUNT_DATA, args);
1649
1650        if (which == STATS_SINCE_UNPLUGGED) {
1651            dumpLine(pw, 0 /* uid */, category, BATTERY_LEVEL_DATA, getDischargeStartLevel(),
1652                    getDischargeCurrentLevel());
1653        }
1654
1655        if (which == STATS_SINCE_UNPLUGGED) {
1656            dumpLine(pw, 0 /* uid */, category, BATTERY_DISCHARGE_DATA,
1657                    getDischargeStartLevel()-getDischargeCurrentLevel(),
1658                    getDischargeStartLevel()-getDischargeCurrentLevel(),
1659                    getDischargeAmountScreenOn(), getDischargeAmountScreenOff());
1660        } else {
1661            dumpLine(pw, 0 /* uid */, category, BATTERY_DISCHARGE_DATA,
1662                    getLowDischargeAmountSinceCharge(), getHighDischargeAmountSinceCharge(),
1663                    getDischargeAmountScreenOn(), getDischargeAmountScreenOff());
1664        }
1665
1666        if (reqUid < 0) {
1667            Map<String, ? extends Timer> kernelWakelocks = getKernelWakelockStats();
1668            if (kernelWakelocks.size() > 0) {
1669                for (Map.Entry<String, ? extends Timer> ent : kernelWakelocks.entrySet()) {
1670                    sb.setLength(0);
1671                    printWakeLockCheckin(sb, ent.getValue(), rawRealtime, null, which, "");
1672                    dumpLine(pw, 0 /* uid */, category, KERNEL_WAKELOCK_DATA, ent.getKey(),
1673                            sb.toString());
1674                }
1675            }
1676            Map<String, ? extends LongCounter> wakeupReasons = getWakeupReasonStats();
1677            if (wakeupReasons.size() > 0) {
1678                for (Map.Entry<String, ? extends LongCounter> ent : wakeupReasons.entrySet()) {
1679                    dumpLine(pw, 0 /* uid */, category, WAKEUP_REASON_DATA,
1680                            "\"" + ent.getKey() + "\"", ent.getValue().getCountLocked(which));
1681                }
1682            }
1683        }
1684
1685        BatteryStatsHelper helper = new BatteryStatsHelper(context);
1686        helper.create(this);
1687        helper.refreshStats(which, UserHandle.USER_ALL);
1688        List<BatterySipper> sippers = helper.getUsageList();
1689        if (sippers != null && sippers.size() > 0) {
1690            dumpLine(pw, 0 /* uid */, category, POWER_USE_SUMMARY_DATA,
1691                    BatteryStatsHelper.makemAh(helper.getPowerProfile().getBatteryCapacity()),
1692                    BatteryStatsHelper.makemAh(helper.getComputedPower()),
1693                    BatteryStatsHelper.makemAh(helper.getMinDrainedPower()),
1694                    BatteryStatsHelper.makemAh(helper.getMaxDrainedPower()));
1695            for (int i=0; i<sippers.size(); i++) {
1696                BatterySipper bs = sippers.get(i);
1697                int uid = 0;
1698                String label;
1699                switch (bs.drainType) {
1700                    case IDLE:
1701                        label="idle";
1702                        break;
1703                    case CELL:
1704                        label="cell";
1705                        break;
1706                    case PHONE:
1707                        label="phone";
1708                        break;
1709                    case WIFI:
1710                        label="wifi";
1711                        break;
1712                    case BLUETOOTH:
1713                        label="blue";
1714                        break;
1715                    case SCREEN:
1716                        label="scrn";
1717                        break;
1718                    case APP:
1719                        uid = bs.uidObj.getUid();
1720                        label = "uid";
1721                        break;
1722                    case USER:
1723                        uid = UserHandle.getUid(bs.userId, 0);
1724                        label = "user";
1725                        break;
1726                    case UNACCOUNTED:
1727                        label = "unacc";
1728                        break;
1729                    case OVERCOUNTED:
1730                        label = "over";
1731                        break;
1732                    default:
1733                        label = "???";
1734                }
1735                dumpLine(pw, uid, category, POWER_USE_ITEM_DATA, label,
1736                        BatteryStatsHelper.makemAh(bs.value));
1737            }
1738        }
1739
1740        for (int iu = 0; iu < NU; iu++) {
1741            final int uid = uidStats.keyAt(iu);
1742            if (reqUid >= 0 && uid != reqUid) {
1743                continue;
1744            }
1745            Uid u = uidStats.valueAt(iu);
1746            // Dump Network stats per uid, if any
1747            long mobileBytesRx = u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
1748            long mobileBytesTx = u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
1749            long wifiBytesRx = u.getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
1750            long wifiBytesTx = u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
1751            long mobilePacketsRx = u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
1752            long mobilePacketsTx = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
1753            long mobileActiveTime = u.getMobileRadioActiveTime(which);
1754            int mobileActiveCount = u.getMobileRadioActiveCount(which);
1755            long wifiPacketsRx = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
1756            long wifiPacketsTx = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
1757            long fullWifiLockOnTime = u.getFullWifiLockTime(rawRealtime, which);
1758            long wifiScanTime = u.getWifiScanTime(rawRealtime, which);
1759            long uidWifiRunningTime = u.getWifiRunningTime(rawRealtime, which);
1760
1761            if (mobileBytesRx > 0 || mobileBytesTx > 0 || wifiBytesRx > 0 || wifiBytesTx > 0
1762                    || mobilePacketsRx > 0 || mobilePacketsTx > 0 || wifiPacketsRx > 0
1763                    || wifiPacketsTx > 0 || mobileActiveTime > 0 || mobileActiveCount > 0) {
1764                dumpLine(pw, uid, category, NETWORK_DATA, mobileBytesRx, mobileBytesTx,
1765                        wifiBytesRx, wifiBytesTx,
1766                        mobilePacketsRx, mobilePacketsTx,
1767                        wifiPacketsRx, wifiPacketsTx,
1768                        mobileActiveTime, mobileActiveCount);
1769            }
1770
1771            if (fullWifiLockOnTime != 0 || wifiScanTime != 0
1772                    || uidWifiRunningTime != 0) {
1773                dumpLine(pw, uid, category, WIFI_DATA,
1774                        fullWifiLockOnTime, wifiScanTime, uidWifiRunningTime);
1775            }
1776
1777            if (u.hasUserActivity()) {
1778                args = new Object[Uid.NUM_USER_ACTIVITY_TYPES];
1779                boolean hasData = false;
1780                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
1781                    int val = u.getUserActivityCount(i, which);
1782                    args[i] = val;
1783                    if (val != 0) hasData = true;
1784                }
1785                if (hasData) {
1786                    dumpLine(pw, 0 /* uid */, category, USER_ACTIVITY_DATA, args);
1787                }
1788            }
1789
1790            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
1791            if (wakelocks.size() > 0) {
1792                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
1793                        : wakelocks.entrySet()) {
1794                    Uid.Wakelock wl = ent.getValue();
1795                    String linePrefix = "";
1796                    sb.setLength(0);
1797                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_FULL),
1798                            rawRealtime, "f", which, linePrefix);
1799                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL),
1800                            rawRealtime, "p", which, linePrefix);
1801                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_WINDOW),
1802                            rawRealtime, "w", which, linePrefix);
1803
1804                    // Only log if we had at lease one wakelock...
1805                    if (sb.length() > 0) {
1806                        String name = ent.getKey();
1807                        if (name.indexOf(',') >= 0) {
1808                            name = name.replace(',', '_');
1809                        }
1810                        dumpLine(pw, uid, category, WAKELOCK_DATA, name, sb.toString());
1811                    }
1812                }
1813            }
1814
1815            Map<Integer, ? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
1816            if (sensors.size() > 0)  {
1817                for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> ent
1818                        : sensors.entrySet()) {
1819                    Uid.Sensor se = ent.getValue();
1820                    int sensorNumber = ent.getKey();
1821                    Timer timer = se.getSensorTime();
1822                    if (timer != null) {
1823                        // Convert from microseconds to milliseconds with rounding
1824                        long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
1825                        int count = timer.getCountLocked(which);
1826                        if (totalTime != 0) {
1827                            dumpLine(pw, uid, category, SENSOR_DATA, sensorNumber, totalTime, count);
1828                        }
1829                    }
1830                }
1831            }
1832
1833            Timer vibTimer = u.getVibratorOnTimer();
1834            if (vibTimer != null) {
1835                // Convert from microseconds to milliseconds with rounding
1836                long totalTime = (vibTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
1837                int count = vibTimer.getCountLocked(which);
1838                if (totalTime != 0) {
1839                    dumpLine(pw, uid, category, VIBRATOR_DATA, totalTime, count);
1840                }
1841            }
1842
1843            Timer fgTimer = u.getForegroundActivityTimer();
1844            if (fgTimer != null) {
1845                // Convert from microseconds to milliseconds with rounding
1846                long totalTime = (fgTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
1847                int count = fgTimer.getCountLocked(which);
1848                if (totalTime != 0) {
1849                    dumpLine(pw, uid, category, FOREGROUND_DATA, totalTime, count);
1850                }
1851            }
1852
1853            Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
1854            if (processStats.size() > 0) {
1855                for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
1856                        : processStats.entrySet()) {
1857                    Uid.Proc ps = ent.getValue();
1858
1859                    final long userMillis = ps.getUserTime(which) * 10;
1860                    final long systemMillis = ps.getSystemTime(which) * 10;
1861                    final long foregroundMillis = ps.getForegroundTime(which) * 10;
1862                    final long starts = ps.getStarts(which);
1863
1864                    if (userMillis != 0 || systemMillis != 0 || foregroundMillis != 0
1865                            || starts != 0) {
1866                        dumpLine(pw, uid, category, PROCESS_DATA, ent.getKey(), userMillis,
1867                                systemMillis, foregroundMillis, starts);
1868                    }
1869                }
1870            }
1871
1872            Map<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats();
1873            if (packageStats.size() > 0) {
1874                for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent
1875                        : packageStats.entrySet()) {
1876
1877                    Uid.Pkg ps = ent.getValue();
1878                    int wakeups = ps.getWakeups(which);
1879                    Map<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
1880                    for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent
1881                            : serviceStats.entrySet()) {
1882                        BatteryStats.Uid.Pkg.Serv ss = sent.getValue();
1883                        long startTime = ss.getStartTime(batteryUptime, which);
1884                        int starts = ss.getStarts(which);
1885                        int launches = ss.getLaunches(which);
1886                        if (startTime != 0 || starts != 0 || launches != 0) {
1887                            dumpLine(pw, uid, category, APK_DATA,
1888                                    wakeups, // wakeup alarms
1889                                    ent.getKey(), // Apk
1890                                    sent.getKey(), // service
1891                                    startTime / 1000, // time spent started, in ms
1892                                    starts,
1893                                    launches);
1894                        }
1895                    }
1896                }
1897            }
1898        }
1899    }
1900
1901    static final class TimerEntry {
1902        final String mName;
1903        final int mId;
1904        final BatteryStats.Timer mTimer;
1905        final long mTime;
1906        TimerEntry(String name, int id, BatteryStats.Timer timer, long time) {
1907            mName = name;
1908            mId = id;
1909            mTimer = timer;
1910            mTime = time;
1911        }
1912    }
1913
1914    private void printmAh(PrintWriter printer, double power) {
1915        printer.print(BatteryStatsHelper.makemAh(power));
1916    }
1917
1918    @SuppressWarnings("unused")
1919    public final void dumpLocked(Context context, PrintWriter pw, String prefix, final int which,
1920            int reqUid) {
1921        final long rawUptime = SystemClock.uptimeMillis() * 1000;
1922        final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
1923        final long batteryUptime = getBatteryUptime(rawUptime);
1924
1925        final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
1926        final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
1927        final long totalRealtime = computeRealtime(rawRealtime, which);
1928        final long totalUptime = computeUptime(rawUptime, which);
1929        final long whichBatteryScreenOffUptime = computeBatteryScreenOffUptime(rawUptime, which);
1930        final long whichBatteryScreenOffRealtime = computeBatteryScreenOffRealtime(rawRealtime,
1931                which);
1932
1933        StringBuilder sb = new StringBuilder(128);
1934
1935        SparseArray<? extends Uid> uidStats = getUidStats();
1936        final int NU = uidStats.size();
1937
1938        sb.setLength(0);
1939        sb.append(prefix);
1940                sb.append("  Time on battery: ");
1941                formatTimeMs(sb, whichBatteryRealtime / 1000); sb.append("(");
1942                sb.append(formatRatioLocked(whichBatteryRealtime, totalRealtime));
1943                sb.append(") realtime, ");
1944                formatTimeMs(sb, whichBatteryUptime / 1000);
1945                sb.append("("); sb.append(formatRatioLocked(whichBatteryUptime, totalRealtime));
1946                sb.append(") uptime");
1947        pw.println(sb.toString());
1948        sb.setLength(0);
1949        sb.append(prefix);
1950                sb.append("  Time on battery screen off: ");
1951                formatTimeMs(sb, whichBatteryScreenOffRealtime / 1000); sb.append("(");
1952                sb.append(formatRatioLocked(whichBatteryScreenOffRealtime, totalRealtime));
1953                sb.append(") realtime, ");
1954                formatTimeMs(sb, whichBatteryScreenOffUptime / 1000);
1955                sb.append("(");
1956                sb.append(formatRatioLocked(whichBatteryScreenOffUptime, totalRealtime));
1957                sb.append(") uptime");
1958        pw.println(sb.toString());
1959        sb.setLength(0);
1960        sb.append(prefix);
1961                sb.append("  Total run time: ");
1962                formatTimeMs(sb, totalRealtime / 1000);
1963                sb.append("realtime, ");
1964                formatTimeMs(sb, totalUptime / 1000);
1965                sb.append("uptime");
1966        pw.println(sb.toString());
1967        pw.print("  Start clock time: ");
1968        pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss", getStartClockTime()).toString());
1969
1970        final long screenOnTime = getScreenOnTime(rawRealtime, which);
1971        final long phoneOnTime = getPhoneOnTime(rawRealtime, which);
1972        final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which);
1973        final long wifiOnTime = getWifiOnTime(rawRealtime, which);
1974        final long bluetoothOnTime = getBluetoothOnTime(rawRealtime, which);
1975        sb.setLength(0);
1976        sb.append(prefix);
1977                sb.append("  Screen on: "); formatTimeMs(sb, screenOnTime / 1000);
1978                sb.append("("); sb.append(formatRatioLocked(screenOnTime, whichBatteryRealtime));
1979                sb.append(") "); sb.append(getScreenOnCount(which));
1980                sb.append("x, Input events: "); sb.append(getInputEventCount(which));
1981        pw.println(sb.toString());
1982        if (phoneOnTime != 0) {
1983            sb.setLength(0);
1984            sb.append(prefix);
1985                    sb.append("  Active phone call: "); formatTimeMs(sb, phoneOnTime / 1000);
1986                    sb.append("("); sb.append(formatRatioLocked(phoneOnTime, whichBatteryRealtime));
1987                    sb.append(") "); sb.append(getPhoneOnCount(which));
1988        }
1989        sb.setLength(0);
1990        sb.append(prefix);
1991        sb.append("  Screen brightnesses:");
1992        boolean didOne = false;
1993        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
1994            final long time = getScreenBrightnessTime(i, rawRealtime, which);
1995            if (time == 0) {
1996                continue;
1997            }
1998            sb.append("\n    ");
1999            sb.append(prefix);
2000            didOne = true;
2001            sb.append(SCREEN_BRIGHTNESS_NAMES[i]);
2002            sb.append(" ");
2003            formatTimeMs(sb, time/1000);
2004            sb.append("(");
2005            sb.append(formatRatioLocked(time, screenOnTime));
2006            sb.append(")");
2007        }
2008        if (!didOne) sb.append(" (no activity)");
2009        pw.println(sb.toString());
2010
2011        // Calculate wakelock times across all uids.
2012        long fullWakeLockTimeTotalMicros = 0;
2013        long partialWakeLockTimeTotalMicros = 0;
2014
2015        final ArrayList<TimerEntry> timers = new ArrayList<TimerEntry>();
2016
2017        for (int iu = 0; iu < NU; iu++) {
2018            Uid u = uidStats.valueAt(iu);
2019
2020            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
2021            if (wakelocks.size() > 0) {
2022                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
2023                        : wakelocks.entrySet()) {
2024                    Uid.Wakelock wl = ent.getValue();
2025
2026                    Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
2027                    if (fullWakeTimer != null) {
2028                        fullWakeLockTimeTotalMicros += fullWakeTimer.getTotalTimeLocked(
2029                                rawRealtime, which);
2030                    }
2031
2032                    Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
2033                    if (partialWakeTimer != null) {
2034                        long totalTimeMicros = partialWakeTimer.getTotalTimeLocked(
2035                                rawRealtime, which);
2036                        if (totalTimeMicros > 0) {
2037                            if (reqUid < 0) {
2038                                // Only show the ordered list of all wake
2039                                // locks if the caller is not asking for data
2040                                // about a specific uid.
2041                                timers.add(new TimerEntry(ent.getKey(), u.getUid(),
2042                                        partialWakeTimer, totalTimeMicros));
2043                            }
2044                            partialWakeLockTimeTotalMicros += totalTimeMicros;
2045                        }
2046                    }
2047                }
2048            }
2049        }
2050
2051        long mobileRxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
2052        long mobileTxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
2053        long wifiRxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
2054        long wifiTxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
2055        long mobileRxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
2056        long mobileTxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
2057        long wifiRxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
2058        long wifiTxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
2059
2060        if (fullWakeLockTimeTotalMicros != 0) {
2061            sb.setLength(0);
2062            sb.append(prefix);
2063                    sb.append("  Total full wakelock time: "); formatTimeMsNoSpace(sb,
2064                            (fullWakeLockTimeTotalMicros + 500) / 1000);
2065            pw.println(sb.toString());
2066        }
2067
2068        if (partialWakeLockTimeTotalMicros != 0) {
2069            sb.setLength(0);
2070            sb.append(prefix);
2071                    sb.append("  Total partial wakelock time: "); formatTimeMsNoSpace(sb,
2072                            (partialWakeLockTimeTotalMicros + 500) / 1000);
2073            pw.println(sb.toString());
2074        }
2075
2076        pw.print(prefix);
2077                pw.print("  Mobile total received: "); pw.print(formatBytesLocked(mobileRxTotalBytes));
2078                pw.print(", sent: "); pw.print(formatBytesLocked(mobileTxTotalBytes));
2079                pw.print(" (packets received "); pw.print(mobileRxTotalPackets);
2080                pw.print(", sent "); pw.print(mobileTxTotalPackets); pw.println(")");
2081        sb.setLength(0);
2082        sb.append(prefix);
2083        sb.append("  Signal levels:");
2084        didOne = false;
2085        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
2086            final long time = getPhoneSignalStrengthTime(i, rawRealtime, which);
2087            if (time == 0) {
2088                continue;
2089            }
2090            sb.append("\n    ");
2091            sb.append(prefix);
2092            didOne = true;
2093            sb.append(SignalStrength.SIGNAL_STRENGTH_NAMES[i]);
2094            sb.append(" ");
2095            formatTimeMs(sb, time/1000);
2096            sb.append("(");
2097            sb.append(formatRatioLocked(time, whichBatteryRealtime));
2098            sb.append(") ");
2099            sb.append(getPhoneSignalStrengthCount(i, which));
2100            sb.append("x");
2101        }
2102        if (!didOne) sb.append(" (no activity)");
2103        pw.println(sb.toString());
2104
2105        sb.setLength(0);
2106        sb.append(prefix);
2107        sb.append("  Signal scanning time: ");
2108        formatTimeMsNoSpace(sb, getPhoneSignalScanningTime(rawRealtime, which) / 1000);
2109        pw.println(sb.toString());
2110
2111        sb.setLength(0);
2112        sb.append(prefix);
2113        sb.append("  Radio types:");
2114        didOne = false;
2115        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
2116            final long time = getPhoneDataConnectionTime(i, rawRealtime, which);
2117            if (time == 0) {
2118                continue;
2119            }
2120            sb.append("\n    ");
2121            sb.append(prefix);
2122            didOne = true;
2123            sb.append(DATA_CONNECTION_NAMES[i]);
2124            sb.append(" ");
2125            formatTimeMs(sb, time/1000);
2126            sb.append("(");
2127            sb.append(formatRatioLocked(time, whichBatteryRealtime));
2128            sb.append(") ");
2129            sb.append(getPhoneDataConnectionCount(i, which));
2130            sb.append("x");
2131        }
2132        if (!didOne) sb.append(" (no activity)");
2133        pw.println(sb.toString());
2134
2135        sb.setLength(0);
2136        sb.append(prefix);
2137        sb.append("  Mobile radio active time: ");
2138        final long mobileActiveTime = getMobileRadioActiveTime(rawRealtime, which);
2139        formatTimeMs(sb, mobileActiveTime / 1000);
2140        sb.append("("); sb.append(formatRatioLocked(mobileActiveTime, whichBatteryRealtime));
2141        sb.append(") "); sb.append(getMobileRadioActiveCount(which));
2142        sb.append("x");
2143        pw.println(sb.toString());
2144
2145        final long mobileActiveUnknownTime = getMobileRadioActiveUnknownTime(which);
2146        if (mobileActiveUnknownTime != 0) {
2147            sb.setLength(0);
2148            sb.append(prefix);
2149            sb.append("  Mobile radio active unknown time: ");
2150            formatTimeMs(sb, mobileActiveUnknownTime / 1000);
2151            sb.append("(");
2152            sb.append(formatRatioLocked(mobileActiveUnknownTime, whichBatteryRealtime));
2153            sb.append(") "); sb.append(getMobileRadioActiveUnknownCount(which));
2154            sb.append("x");
2155            pw.println(sb.toString());
2156        }
2157
2158        final long mobileActiveAdjustedTime = getMobileRadioActiveAdjustedTime(which);
2159        if (mobileActiveAdjustedTime != 0) {
2160            sb.setLength(0);
2161            sb.append(prefix);
2162            sb.append("  Mobile radio active adjusted time: ");
2163            formatTimeMs(sb, mobileActiveAdjustedTime / 1000);
2164            sb.append("(");
2165            sb.append(formatRatioLocked(mobileActiveAdjustedTime, whichBatteryRealtime));
2166            sb.append(")");
2167            pw.println(sb.toString());
2168        }
2169
2170        pw.print(prefix);
2171                pw.print("  Wi-Fi total received: "); pw.print(formatBytesLocked(wifiRxTotalBytes));
2172                pw.print(", sent: "); pw.print(formatBytesLocked(wifiTxTotalBytes));
2173                pw.print(" (packets received "); pw.print(wifiRxTotalPackets);
2174                pw.print(", sent "); pw.print(wifiTxTotalPackets); pw.println(")");
2175        sb.setLength(0);
2176        sb.append(prefix);
2177                sb.append("  Wifi on: "); formatTimeMs(sb, wifiOnTime / 1000);
2178                sb.append("("); sb.append(formatRatioLocked(wifiOnTime, whichBatteryRealtime));
2179                sb.append("), Wifi running: "); formatTimeMs(sb, wifiRunningTime / 1000);
2180                sb.append("("); sb.append(formatRatioLocked(wifiRunningTime, whichBatteryRealtime));
2181                sb.append(")");
2182        pw.println(sb.toString());
2183
2184        sb.setLength(0);
2185        sb.append(prefix);
2186        sb.append("  Wifi states:");
2187        didOne = false;
2188        for (int i=0; i<NUM_WIFI_STATES; i++) {
2189            final long time = getWifiStateTime(i, rawRealtime, which);
2190            if (time == 0) {
2191                continue;
2192            }
2193            sb.append("\n    ");
2194            didOne = true;
2195            sb.append(WIFI_STATE_NAMES[i]);
2196            sb.append(" ");
2197            formatTimeMs(sb, time/1000);
2198            sb.append("(");
2199            sb.append(formatRatioLocked(time, whichBatteryRealtime));
2200            sb.append(") ");
2201            sb.append(getPhoneDataConnectionCount(i, which));
2202            sb.append("x");
2203        }
2204        if (!didOne) sb.append(" (no activity)");
2205        pw.println(sb.toString());
2206
2207        sb.setLength(0);
2208        sb.append(prefix);
2209                sb.append("  Bluetooth on: "); formatTimeMs(sb, bluetoothOnTime / 1000);
2210                sb.append("("); sb.append(formatRatioLocked(bluetoothOnTime, whichBatteryRealtime));
2211                sb.append(")");
2212        pw.println(sb.toString());
2213
2214        sb.setLength(0);
2215        sb.append(prefix);
2216        sb.append("  Bluetooth states:");
2217        didOne = false;
2218        for (int i=0; i<NUM_BLUETOOTH_STATES; i++) {
2219            final long time = getBluetoothStateTime(i, rawRealtime, which);
2220            if (time == 0) {
2221                continue;
2222            }
2223            sb.append("\n    ");
2224            didOne = true;
2225            sb.append(BLUETOOTH_STATE_NAMES[i]);
2226            sb.append(" ");
2227            formatTimeMs(sb, time/1000);
2228            sb.append("(");
2229            sb.append(formatRatioLocked(time, whichBatteryRealtime));
2230            sb.append(") ");
2231            sb.append(getPhoneDataConnectionCount(i, which));
2232            sb.append("x");
2233        }
2234        if (!didOne) sb.append(" (no activity)");
2235        pw.println(sb.toString());
2236
2237        pw.println();
2238
2239        if (which == STATS_SINCE_UNPLUGGED) {
2240            if (getIsOnBattery()) {
2241                pw.print(prefix); pw.println("  Device is currently unplugged");
2242                pw.print(prefix); pw.print("    Discharge cycle start level: ");
2243                        pw.println(getDischargeStartLevel());
2244                pw.print(prefix); pw.print("    Discharge cycle current level: ");
2245                        pw.println(getDischargeCurrentLevel());
2246            } else {
2247                pw.print(prefix); pw.println("  Device is currently plugged into power");
2248                pw.print(prefix); pw.print("    Last discharge cycle start level: ");
2249                        pw.println(getDischargeStartLevel());
2250                pw.print(prefix); pw.print("    Last discharge cycle end level: ");
2251                        pw.println(getDischargeCurrentLevel());
2252            }
2253            pw.print(prefix); pw.print("    Amount discharged while screen on: ");
2254                    pw.println(getDischargeAmountScreenOn());
2255            pw.print(prefix); pw.print("    Amount discharged while screen off: ");
2256                    pw.println(getDischargeAmountScreenOff());
2257            pw.println(" ");
2258        } else {
2259            pw.print(prefix); pw.println("  Device battery use since last full charge");
2260            pw.print(prefix); pw.print("    Amount discharged (lower bound): ");
2261                    pw.println(getLowDischargeAmountSinceCharge());
2262            pw.print(prefix); pw.print("    Amount discharged (upper bound): ");
2263                    pw.println(getHighDischargeAmountSinceCharge());
2264            pw.print(prefix); pw.print("    Amount discharged while screen on: ");
2265                    pw.println(getDischargeAmountScreenOnSinceCharge());
2266            pw.print(prefix); pw.print("    Amount discharged while screen off: ");
2267                    pw.println(getDischargeAmountScreenOffSinceCharge());
2268            pw.println();
2269        }
2270
2271        BatteryStatsHelper helper = new BatteryStatsHelper(context);
2272        helper.create(this);
2273        helper.refreshStats(which, UserHandle.USER_ALL);
2274        List<BatterySipper> sippers = helper.getUsageList();
2275        if (sippers != null && sippers.size() > 0) {
2276            pw.print(prefix); pw.println("  Estimated power use (mAh):");
2277            pw.print(prefix); pw.print("    Capacity: ");
2278                    printmAh(pw, helper.getPowerProfile().getBatteryCapacity());
2279                    pw.print(", Computed drain: "); printmAh(pw, helper.getComputedPower());
2280                    pw.print(", Min drain: "); printmAh(pw, helper.getMinDrainedPower());
2281                    pw.print(", Max drain: "); printmAh(pw, helper.getMaxDrainedPower());
2282                    pw.println();
2283            for (int i=0; i<sippers.size(); i++) {
2284                BatterySipper bs = sippers.get(i);
2285                switch (bs.drainType) {
2286                    case IDLE:
2287                        pw.print(prefix); pw.print("    Idle: "); printmAh(pw, bs.value);
2288                        pw.println();
2289                        break;
2290                    case CELL:
2291                        pw.print(prefix); pw.print("    Cell standby: "); printmAh(pw, bs.value);
2292                        pw.println();
2293                        break;
2294                    case PHONE:
2295                        pw.print(prefix); pw.print("    Phone calls: "); printmAh(pw, bs.value);
2296                        pw.println();
2297                        break;
2298                    case WIFI:
2299                        pw.print(prefix); pw.print("    Wifi: "); printmAh(pw, bs.value);
2300                        pw.println();
2301                        break;
2302                    case BLUETOOTH:
2303                        pw.print(prefix); pw.print("    Bluetooth: "); printmAh(pw, bs.value);
2304                        pw.println();
2305                        break;
2306                    case SCREEN:
2307                        pw.print(prefix); pw.print("    Screen: "); printmAh(pw, bs.value);
2308                        pw.println();
2309                        break;
2310                    case APP:
2311                        pw.print(prefix); pw.print("    Uid ");
2312                        UserHandle.formatUid(pw, bs.uidObj.getUid());
2313                        pw.print(": "); printmAh(pw, bs.value); pw.println();
2314                        break;
2315                    case USER:
2316                        pw.print(prefix); pw.print("    User "); pw.print(bs.userId);
2317                        pw.print(": "); printmAh(pw, bs.value); pw.println();
2318                        break;
2319                    case UNACCOUNTED:
2320                        pw.print(prefix); pw.print("    Unaccounted: "); printmAh(pw, bs.value);
2321                        pw.println();
2322                        break;
2323                    case OVERCOUNTED:
2324                        pw.print(prefix); pw.print("    Over-counted: "); printmAh(pw, bs.value);
2325                        pw.println();
2326                        break;
2327                }
2328            }
2329            pw.println();
2330        }
2331
2332        sippers = helper.getMobilemsppList();
2333        if (sippers != null && sippers.size() > 0) {
2334            pw.print(prefix); pw.println("  Per-app mobile ms per packet:");
2335            long totalTime = 0;
2336            for (int i=0; i<sippers.size(); i++) {
2337                BatterySipper bs = sippers.get(i);
2338                sb.setLength(0);
2339                sb.append(prefix); sb.append("    Uid ");
2340                UserHandle.formatUid(sb, bs.uidObj.getUid());
2341                sb.append(": "); sb.append(BatteryStatsHelper.makemAh(bs.mobilemspp));
2342                sb.append(" ("); sb.append(bs.mobileRxPackets+bs.mobileTxPackets);
2343                sb.append(" packets over "); formatTimeMsNoSpace(sb, bs.mobileActive);
2344                sb.append(") "); sb.append(bs.mobileActiveCount); sb.append("x");
2345                pw.println(sb.toString());
2346                totalTime += bs.mobileActive;
2347            }
2348            sb.setLength(0);
2349            sb.append(prefix);
2350            sb.append("    TOTAL TIME: ");
2351            formatTimeMs(sb, totalTime);
2352            sb.append("("); sb.append(formatRatioLocked(totalTime, whichBatteryRealtime));
2353            sb.append(")");
2354            pw.println(sb.toString());
2355            pw.println();
2356        }
2357
2358        final Comparator<TimerEntry> timerComparator = new Comparator<TimerEntry>() {
2359            @Override
2360            public int compare(TimerEntry lhs, TimerEntry rhs) {
2361                long lhsTime = lhs.mTime;
2362                long rhsTime = rhs.mTime;
2363                if (lhsTime < rhsTime) {
2364                    return 1;
2365                }
2366                if (lhsTime > rhsTime) {
2367                    return -1;
2368                }
2369                return 0;
2370            }
2371        };
2372
2373        if (reqUid < 0) {
2374            Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats();
2375            if (kernelWakelocks.size() > 0) {
2376                final ArrayList<TimerEntry> ktimers = new ArrayList<TimerEntry>();
2377                for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) {
2378                    BatteryStats.Timer timer = ent.getValue();
2379                    long totalTimeMillis = computeWakeLock(timer, rawRealtime, which);
2380                    if (totalTimeMillis > 0) {
2381                        ktimers.add(new TimerEntry(ent.getKey(), 0, timer, totalTimeMillis));
2382                    }
2383                }
2384                if (ktimers.size() > 0) {
2385                    Collections.sort(ktimers, timerComparator);
2386                    pw.print(prefix); pw.println("  All kernel wake locks:");
2387                    for (int i=0; i<ktimers.size(); i++) {
2388                        TimerEntry timer = ktimers.get(i);
2389                        String linePrefix = ": ";
2390                        sb.setLength(0);
2391                        sb.append(prefix);
2392                        sb.append("  Kernel Wake lock ");
2393                        sb.append(timer.mName);
2394                        linePrefix = printWakeLock(sb, timer.mTimer, rawRealtime, null,
2395                                which, linePrefix);
2396                        if (!linePrefix.equals(": ")) {
2397                            sb.append(" realtime");
2398                            // Only print out wake locks that were held
2399                            pw.println(sb.toString());
2400                        }
2401                    }
2402                    pw.println();
2403                }
2404            }
2405
2406            if (timers.size() > 0) {
2407                Collections.sort(timers, timerComparator);
2408                pw.print(prefix); pw.println("  All partial wake locks:");
2409                for (int i=0; i<timers.size(); i++) {
2410                    TimerEntry timer = timers.get(i);
2411                    sb.setLength(0);
2412                    sb.append("  Wake lock ");
2413                    UserHandle.formatUid(sb, timer.mId);
2414                    sb.append(" ");
2415                    sb.append(timer.mName);
2416                    printWakeLock(sb, timer.mTimer, rawRealtime, null, which, ": ");
2417                    sb.append(" realtime");
2418                    pw.println(sb.toString());
2419                }
2420                timers.clear();
2421                pw.println();
2422            }
2423
2424            Map<String, ? extends LongCounter> wakeupReasons = getWakeupReasonStats();
2425            if (wakeupReasons.size() > 0) {
2426                pw.print(prefix); pw.println("  All wakeup reasons:");
2427                final ArrayList<TimerEntry> reasons = new ArrayList<TimerEntry>();
2428                for (Map.Entry<String, ? extends LongCounter> ent : wakeupReasons.entrySet()) {
2429                    BatteryStats.LongCounter counter = ent.getValue();
2430                    reasons.add(new TimerEntry(ent.getKey(), 0, null,
2431                            ent.getValue().getCountLocked(which)));
2432                }
2433                Collections.sort(reasons, timerComparator);
2434                for (int i=0; i<reasons.size(); i++) {
2435                    TimerEntry timer = reasons.get(i);
2436                    String linePrefix = ": ";
2437                    sb.setLength(0);
2438                    sb.append(prefix);
2439                    sb.append("  Wakeup reason ");
2440                    sb.append(timer.mName);
2441                    sb.append(": ");
2442                    formatTimeMs(sb, timer.mTime);
2443                    sb.append("realtime");
2444                    pw.println(sb.toString());
2445                }
2446                pw.println();
2447            }
2448        }
2449
2450        for (int iu=0; iu<NU; iu++) {
2451            final int uid = uidStats.keyAt(iu);
2452            if (reqUid >= 0 && uid != reqUid && uid != Process.SYSTEM_UID) {
2453                continue;
2454            }
2455
2456            Uid u = uidStats.valueAt(iu);
2457
2458            pw.print(prefix);
2459            pw.print("  ");
2460            UserHandle.formatUid(pw, uid);
2461            pw.println(":");
2462            boolean uidActivity = false;
2463
2464            long mobileRxBytes = u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
2465            long mobileTxBytes = u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
2466            long wifiRxBytes = u.getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
2467            long wifiTxBytes = u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
2468            long mobileRxPackets = u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
2469            long mobileTxPackets = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
2470            long uidMobileActiveTime = u.getMobileRadioActiveTime(which);
2471            int uidMobileActiveCount = u.getMobileRadioActiveCount(which);
2472            long wifiRxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
2473            long wifiTxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
2474            long fullWifiLockOnTime = u.getFullWifiLockTime(rawRealtime, which);
2475            long wifiScanTime = u.getWifiScanTime(rawRealtime, which);
2476            long uidWifiRunningTime = u.getWifiRunningTime(rawRealtime, which);
2477
2478            if (mobileRxBytes > 0 || mobileTxBytes > 0
2479                    || mobileRxPackets > 0 || mobileTxPackets > 0) {
2480                pw.print(prefix); pw.print("    Mobile network: ");
2481                        pw.print(formatBytesLocked(mobileRxBytes)); pw.print(" received, ");
2482                        pw.print(formatBytesLocked(mobileTxBytes));
2483                        pw.print(" sent (packets "); pw.print(mobileRxPackets);
2484                        pw.print(" received, "); pw.print(mobileTxPackets); pw.println(" sent)");
2485            }
2486            if (uidMobileActiveTime > 0 || uidMobileActiveCount > 0) {
2487                sb.setLength(0);
2488                sb.append(prefix); sb.append("    Mobile radio active: ");
2489                formatTimeMs(sb, uidMobileActiveTime / 1000);
2490                sb.append("(");
2491                sb.append(formatRatioLocked(uidMobileActiveTime, mobileActiveTime));
2492                sb.append(") "); sb.append(uidMobileActiveCount); sb.append("x");
2493                long packets = mobileRxPackets + mobileTxPackets;
2494                if (packets == 0) {
2495                    packets = 1;
2496                }
2497                sb.append(" @ ");
2498                sb.append(BatteryStatsHelper.makemAh(uidMobileActiveTime / 1000 / (double)packets));
2499                sb.append(" mspp");
2500                pw.println(sb.toString());
2501            }
2502
2503            if (wifiRxBytes > 0 || wifiTxBytes > 0 || wifiRxPackets > 0 || wifiTxPackets > 0) {
2504                pw.print(prefix); pw.print("    Wi-Fi network: ");
2505                        pw.print(formatBytesLocked(wifiRxBytes)); pw.print(" received, ");
2506                        pw.print(formatBytesLocked(wifiTxBytes));
2507                        pw.print(" sent (packets "); pw.print(wifiRxPackets);
2508                        pw.print(" received, "); pw.print(wifiTxPackets); pw.println(" sent)");
2509            }
2510
2511            if (fullWifiLockOnTime != 0 || wifiScanTime != 0
2512                    || uidWifiRunningTime != 0) {
2513                sb.setLength(0);
2514                sb.append(prefix); sb.append("    Wifi Running: ");
2515                        formatTimeMs(sb, uidWifiRunningTime / 1000);
2516                        sb.append("("); sb.append(formatRatioLocked(uidWifiRunningTime,
2517                                whichBatteryRealtime)); sb.append(")\n");
2518                sb.append(prefix); sb.append("    Full Wifi Lock: ");
2519                        formatTimeMs(sb, fullWifiLockOnTime / 1000);
2520                        sb.append("("); sb.append(formatRatioLocked(fullWifiLockOnTime,
2521                                whichBatteryRealtime)); sb.append(")\n");
2522                sb.append(prefix); sb.append("    Wifi Scan: ");
2523                        formatTimeMs(sb, wifiScanTime / 1000);
2524                        sb.append("("); sb.append(formatRatioLocked(wifiScanTime,
2525                                whichBatteryRealtime)); sb.append(")");
2526                pw.println(sb.toString());
2527            }
2528
2529            if (u.hasUserActivity()) {
2530                boolean hasData = false;
2531                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
2532                    int val = u.getUserActivityCount(i, which);
2533                    if (val != 0) {
2534                        if (!hasData) {
2535                            sb.setLength(0);
2536                            sb.append("    User activity: ");
2537                            hasData = true;
2538                        } else {
2539                            sb.append(", ");
2540                        }
2541                        sb.append(val);
2542                        sb.append(" ");
2543                        sb.append(Uid.USER_ACTIVITY_TYPES[i]);
2544                    }
2545                }
2546                if (hasData) {
2547                    pw.println(sb.toString());
2548                }
2549            }
2550
2551            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
2552            if (wakelocks.size() > 0) {
2553                long totalFull = 0, totalPartial = 0, totalWindow = 0;
2554                int count = 0;
2555                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
2556                    : wakelocks.entrySet()) {
2557                    Uid.Wakelock wl = ent.getValue();
2558                    String linePrefix = ": ";
2559                    sb.setLength(0);
2560                    sb.append(prefix);
2561                    sb.append("    Wake lock ");
2562                    sb.append(ent.getKey());
2563                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_FULL), rawRealtime,
2564                            "full", which, linePrefix);
2565                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), rawRealtime,
2566                            "partial", which, linePrefix);
2567                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), rawRealtime,
2568                            "window", which, linePrefix);
2569                    if (!linePrefix.equals(": ")) {
2570                        sb.append(" realtime");
2571                        // Only print out wake locks that were held
2572                        pw.println(sb.toString());
2573                        uidActivity = true;
2574                        count++;
2575                    }
2576                    totalFull += computeWakeLock(wl.getWakeTime(WAKE_TYPE_FULL),
2577                            rawRealtime, which);
2578                    totalPartial += computeWakeLock(wl.getWakeTime(WAKE_TYPE_PARTIAL),
2579                            rawRealtime, which);
2580                    totalWindow += computeWakeLock(wl.getWakeTime(WAKE_TYPE_WINDOW),
2581                            rawRealtime, which);
2582                }
2583                if (count > 1) {
2584                    if (totalFull != 0 || totalPartial != 0 || totalWindow != 0) {
2585                        sb.setLength(0);
2586                        sb.append(prefix);
2587                        sb.append("    TOTAL wake: ");
2588                        boolean needComma = false;
2589                        if (totalFull != 0) {
2590                            needComma = true;
2591                            formatTimeMs(sb, totalFull);
2592                            sb.append("full");
2593                        }
2594                        if (totalPartial != 0) {
2595                            if (needComma) {
2596                                sb.append(", ");
2597                            }
2598                            needComma = true;
2599                            formatTimeMs(sb, totalPartial);
2600                            sb.append("partial");
2601                        }
2602                        if (totalWindow != 0) {
2603                            if (needComma) {
2604                                sb.append(", ");
2605                            }
2606                            needComma = true;
2607                            formatTimeMs(sb, totalWindow);
2608                            sb.append("window");
2609                        }
2610                        sb.append(" realtime");
2611                        pw.println(sb.toString());
2612                    }
2613                }
2614            }
2615
2616            Map<Integer, ? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
2617            if (sensors.size() > 0) {
2618                for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> ent
2619                    : sensors.entrySet()) {
2620                    Uid.Sensor se = ent.getValue();
2621                    int sensorNumber = ent.getKey();
2622                    sb.setLength(0);
2623                    sb.append(prefix);
2624                    sb.append("    Sensor ");
2625                    int handle = se.getHandle();
2626                    if (handle == Uid.Sensor.GPS) {
2627                        sb.append("GPS");
2628                    } else {
2629                        sb.append(handle);
2630                    }
2631                    sb.append(": ");
2632
2633                    Timer timer = se.getSensorTime();
2634                    if (timer != null) {
2635                        // Convert from microseconds to milliseconds with rounding
2636                        long totalTime = (timer.getTotalTimeLocked(
2637                                rawRealtime, which) + 500) / 1000;
2638                        int count = timer.getCountLocked(which);
2639                        //timer.logState();
2640                        if (totalTime != 0) {
2641                            formatTimeMs(sb, totalTime);
2642                            sb.append("realtime (");
2643                            sb.append(count);
2644                            sb.append(" times)");
2645                        } else {
2646                            sb.append("(not used)");
2647                        }
2648                    } else {
2649                        sb.append("(not used)");
2650                    }
2651
2652                    pw.println(sb.toString());
2653                    uidActivity = true;
2654                }
2655            }
2656
2657            Timer vibTimer = u.getVibratorOnTimer();
2658            if (vibTimer != null) {
2659                // Convert from microseconds to milliseconds with rounding
2660                long totalTime = (vibTimer.getTotalTimeLocked(
2661                        rawRealtime, which) + 500) / 1000;
2662                int count = vibTimer.getCountLocked(which);
2663                //timer.logState();
2664                if (totalTime != 0) {
2665                    sb.setLength(0);
2666                    sb.append(prefix);
2667                    sb.append("    Vibrator: ");
2668                    formatTimeMs(sb, totalTime);
2669                    sb.append("realtime (");
2670                    sb.append(count);
2671                    sb.append(" times)");
2672                    pw.println(sb.toString());
2673                    uidActivity = true;
2674                }
2675            }
2676
2677            Timer fgTimer = u.getForegroundActivityTimer();
2678            if (fgTimer != null) {
2679                // Convert from microseconds to milliseconds with rounding
2680                long totalTime = (fgTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
2681                int count = fgTimer.getCountLocked(which);
2682                if (totalTime != 0) {
2683                    sb.setLength(0);
2684                    sb.append(prefix);
2685                    sb.append("    Foreground activities: ");
2686                    formatTimeMs(sb, totalTime);
2687                    sb.append("realtime (");
2688                    sb.append(count);
2689                    sb.append(" times)");
2690                    pw.println(sb.toString());
2691                    uidActivity = true;
2692                }
2693            }
2694
2695            Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
2696            if (processStats.size() > 0) {
2697                for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
2698                    : processStats.entrySet()) {
2699                    Uid.Proc ps = ent.getValue();
2700                    long userTime;
2701                    long systemTime;
2702                    long foregroundTime;
2703                    int starts;
2704                    int numExcessive;
2705
2706                    userTime = ps.getUserTime(which);
2707                    systemTime = ps.getSystemTime(which);
2708                    foregroundTime = ps.getForegroundTime(which);
2709                    starts = ps.getStarts(which);
2710                    numExcessive = which == STATS_SINCE_CHARGED
2711                            ? ps.countExcessivePowers() : 0;
2712
2713                    if (userTime != 0 || systemTime != 0 || foregroundTime != 0 || starts != 0
2714                            || numExcessive != 0) {
2715                        sb.setLength(0);
2716                        sb.append(prefix); sb.append("    Proc ");
2717                                sb.append(ent.getKey()); sb.append(":\n");
2718                        sb.append(prefix); sb.append("      CPU: ");
2719                                formatTime(sb, userTime); sb.append("usr + ");
2720                                formatTime(sb, systemTime); sb.append("krn ; ");
2721                                formatTime(sb, foregroundTime); sb.append("fg");
2722                        if (starts != 0) {
2723                            sb.append("\n"); sb.append(prefix); sb.append("      ");
2724                                    sb.append(starts); sb.append(" proc starts");
2725                        }
2726                        pw.println(sb.toString());
2727                        for (int e=0; e<numExcessive; e++) {
2728                            Uid.Proc.ExcessivePower ew = ps.getExcessivePower(e);
2729                            if (ew != null) {
2730                                pw.print(prefix); pw.print("      * Killed for ");
2731                                        if (ew.type == Uid.Proc.ExcessivePower.TYPE_WAKE) {
2732                                            pw.print("wake lock");
2733                                        } else if (ew.type == Uid.Proc.ExcessivePower.TYPE_CPU) {
2734                                            pw.print("cpu");
2735                                        } else {
2736                                            pw.print("unknown");
2737                                        }
2738                                        pw.print(" use: ");
2739                                        TimeUtils.formatDuration(ew.usedTime, pw);
2740                                        pw.print(" over ");
2741                                        TimeUtils.formatDuration(ew.overTime, pw);
2742                                        if (ew.overTime != 0) {
2743                                            pw.print(" (");
2744                                            pw.print((ew.usedTime*100)/ew.overTime);
2745                                            pw.println("%)");
2746                                        }
2747                            }
2748                        }
2749                        uidActivity = true;
2750                    }
2751                }
2752            }
2753
2754            Map<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats();
2755            if (packageStats.size() > 0) {
2756                for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent
2757                    : packageStats.entrySet()) {
2758                    pw.print(prefix); pw.print("    Apk "); pw.print(ent.getKey()); pw.println(":");
2759                    boolean apkActivity = false;
2760                    Uid.Pkg ps = ent.getValue();
2761                    int wakeups = ps.getWakeups(which);
2762                    if (wakeups != 0) {
2763                        pw.print(prefix); pw.print("      ");
2764                                pw.print(wakeups); pw.println(" wakeup alarms");
2765                        apkActivity = true;
2766                    }
2767                    Map<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
2768                    if (serviceStats.size() > 0) {
2769                        for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent
2770                                : serviceStats.entrySet()) {
2771                            BatteryStats.Uid.Pkg.Serv ss = sent.getValue();
2772                            long startTime = ss.getStartTime(batteryUptime, which);
2773                            int starts = ss.getStarts(which);
2774                            int launches = ss.getLaunches(which);
2775                            if (startTime != 0 || starts != 0 || launches != 0) {
2776                                sb.setLength(0);
2777                                sb.append(prefix); sb.append("      Service ");
2778                                        sb.append(sent.getKey()); sb.append(":\n");
2779                                sb.append(prefix); sb.append("        Created for: ");
2780                                        formatTimeMs(sb, startTime / 1000);
2781                                        sb.append("uptime\n");
2782                                sb.append(prefix); sb.append("        Starts: ");
2783                                        sb.append(starts);
2784                                        sb.append(", launches: "); sb.append(launches);
2785                                pw.println(sb.toString());
2786                                apkActivity = true;
2787                            }
2788                        }
2789                    }
2790                    if (!apkActivity) {
2791                        pw.print(prefix); pw.println("      (nothing executed)");
2792                    }
2793                    uidActivity = true;
2794                }
2795            }
2796            if (!uidActivity) {
2797                pw.print(prefix); pw.println("    (nothing executed)");
2798            }
2799        }
2800    }
2801
2802    static void printBitDescriptions(PrintWriter pw, int oldval, int newval, HistoryTag wakelockTag,
2803            BitDescription[] descriptions, boolean longNames) {
2804        int diff = oldval ^ newval;
2805        if (diff == 0) return;
2806        boolean didWake = false;
2807        for (int i=0; i<descriptions.length; i++) {
2808            BitDescription bd = descriptions[i];
2809            if ((diff&bd.mask) != 0) {
2810                pw.print(longNames ? " " : ",");
2811                if (bd.shift < 0) {
2812                    pw.print((newval&bd.mask) != 0 ? "+" : "-");
2813                    pw.print(longNames ? bd.name : bd.shortName);
2814                    if (bd.mask == HistoryItem.STATE_WAKE_LOCK_FLAG && wakelockTag != null) {
2815                        didWake = true;
2816                        pw.print("=");
2817                        if (longNames) {
2818                            UserHandle.formatUid(pw, wakelockTag.uid);
2819                            pw.print(":\"");
2820                            pw.print(wakelockTag.string);
2821                            pw.print("\"");
2822                        } else {
2823                            pw.print(wakelockTag.poolIdx);
2824                        }
2825                    }
2826                } else {
2827                    pw.print(longNames ? bd.name : bd.shortName);
2828                    pw.print("=");
2829                    int val = (newval&bd.mask)>>bd.shift;
2830                    if (bd.values != null && val >= 0 && val < bd.values.length) {
2831                        pw.print(longNames? bd.values[val] : bd.shortValues[val]);
2832                    } else {
2833                        pw.print(val);
2834                    }
2835                }
2836            }
2837        }
2838        if (!didWake && wakelockTag != null) {
2839            pw.print(longNames ? "wake_lock=" : "w=");
2840            if (longNames) {
2841                UserHandle.formatUid(pw, wakelockTag.uid);
2842                pw.print(":\"");
2843                pw.print(wakelockTag.string);
2844                pw.print("\"");
2845            } else {
2846                pw.print(wakelockTag.poolIdx);
2847            }
2848        }
2849    }
2850
2851    public void prepareForDumpLocked() {
2852    }
2853
2854    public static class HistoryPrinter {
2855        int oldState = 0;
2856        int oldState2 = 0;
2857        int oldLevel = -1;
2858        int oldStatus = -1;
2859        int oldHealth = -1;
2860        int oldPlug = -1;
2861        int oldTemp = -1;
2862        int oldVolt = -1;
2863        long lastTime = -1;
2864        long firstTime = -1;
2865
2866        public void printNextItem(PrintWriter pw, HistoryItem rec, long baseTime, boolean checkin,
2867                boolean verbose) {
2868            if (!checkin) {
2869                pw.print("  ");
2870                TimeUtils.formatDuration(rec.time - baseTime, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
2871                pw.print(" (");
2872                pw.print(rec.numReadInts);
2873                pw.print(") ");
2874            } else {
2875                if (lastTime < 0) {
2876                    pw.print(rec.time - baseTime);
2877                } else {
2878                    pw.print(rec.time - lastTime);
2879                }
2880                lastTime = rec.time;
2881            }
2882            if (rec.cmd == HistoryItem.CMD_START) {
2883                if (checkin) {
2884                    pw.print(":");
2885                }
2886                pw.println("START");
2887            } else if (rec.cmd == HistoryItem.CMD_CURRENT_TIME) {
2888                if (checkin) {
2889                    pw.print(":");
2890                }
2891                pw.print("TIME:");
2892                if (checkin) {
2893                    pw.println(rec.currentTime);
2894                } else {
2895                    pw.print(" ");
2896                    pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss",
2897                            rec.currentTime).toString());
2898                }
2899            } else if (rec.cmd == HistoryItem.CMD_OVERFLOW) {
2900                if (checkin) {
2901                    pw.print(":");
2902                }
2903                pw.println("*OVERFLOW*");
2904            } else {
2905                if (!checkin) {
2906                    if (rec.batteryLevel < 10) pw.print("00");
2907                    else if (rec.batteryLevel < 100) pw.print("0");
2908                    pw.print(rec.batteryLevel);
2909                    if (verbose) {
2910                        pw.print(" ");
2911                        if (rec.states < 0) ;
2912                        else if (rec.states < 0x10) pw.print("0000000");
2913                        else if (rec.states < 0x100) pw.print("000000");
2914                        else if (rec.states < 0x1000) pw.print("00000");
2915                        else if (rec.states < 0x10000) pw.print("0000");
2916                        else if (rec.states < 0x100000) pw.print("000");
2917                        else if (rec.states < 0x1000000) pw.print("00");
2918                        else if (rec.states < 0x10000000) pw.print("0");
2919                        pw.print(Integer.toHexString(rec.states));
2920                    }
2921                } else {
2922                    if (oldLevel != rec.batteryLevel) {
2923                        oldLevel = rec.batteryLevel;
2924                        pw.print(",Bl="); pw.print(rec.batteryLevel);
2925                    }
2926                }
2927                if (oldStatus != rec.batteryStatus) {
2928                    oldStatus = rec.batteryStatus;
2929                    pw.print(checkin ? ",Bs=" : " status=");
2930                    switch (oldStatus) {
2931                        case BatteryManager.BATTERY_STATUS_UNKNOWN:
2932                            pw.print(checkin ? "?" : "unknown");
2933                            break;
2934                        case BatteryManager.BATTERY_STATUS_CHARGING:
2935                            pw.print(checkin ? "c" : "charging");
2936                            break;
2937                        case BatteryManager.BATTERY_STATUS_DISCHARGING:
2938                            pw.print(checkin ? "d" : "discharging");
2939                            break;
2940                        case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
2941                            pw.print(checkin ? "n" : "not-charging");
2942                            break;
2943                        case BatteryManager.BATTERY_STATUS_FULL:
2944                            pw.print(checkin ? "f" : "full");
2945                            break;
2946                        default:
2947                            pw.print(oldStatus);
2948                            break;
2949                    }
2950                }
2951                if (oldHealth != rec.batteryHealth) {
2952                    oldHealth = rec.batteryHealth;
2953                    pw.print(checkin ? ",Bh=" : " health=");
2954                    switch (oldHealth) {
2955                        case BatteryManager.BATTERY_HEALTH_UNKNOWN:
2956                            pw.print(checkin ? "?" : "unknown");
2957                            break;
2958                        case BatteryManager.BATTERY_HEALTH_GOOD:
2959                            pw.print(checkin ? "g" : "good");
2960                            break;
2961                        case BatteryManager.BATTERY_HEALTH_OVERHEAT:
2962                            pw.print(checkin ? "h" : "overheat");
2963                            break;
2964                        case BatteryManager.BATTERY_HEALTH_DEAD:
2965                            pw.print(checkin ? "d" : "dead");
2966                            break;
2967                        case BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE:
2968                            pw.print(checkin ? "v" : "over-voltage");
2969                            break;
2970                        case BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE:
2971                            pw.print(checkin ? "f" : "failure");
2972                            break;
2973                        case BatteryManager.BATTERY_HEALTH_COLD:
2974                            pw.print(checkin ? "c" : "cold");
2975                            break;
2976                        default:
2977                            pw.print(oldHealth);
2978                            break;
2979                    }
2980                }
2981                if (oldPlug != rec.batteryPlugType) {
2982                    oldPlug = rec.batteryPlugType;
2983                    pw.print(checkin ? ",Bp=" : " plug=");
2984                    switch (oldPlug) {
2985                        case 0:
2986                            pw.print(checkin ? "n" : "none");
2987                            break;
2988                        case BatteryManager.BATTERY_PLUGGED_AC:
2989                            pw.print(checkin ? "a" : "ac");
2990                            break;
2991                        case BatteryManager.BATTERY_PLUGGED_USB:
2992                            pw.print(checkin ? "u" : "usb");
2993                            break;
2994                        case BatteryManager.BATTERY_PLUGGED_WIRELESS:
2995                            pw.print(checkin ? "w" : "wireless");
2996                            break;
2997                        default:
2998                            pw.print(oldPlug);
2999                            break;
3000                    }
3001                }
3002                if (oldTemp != rec.batteryTemperature) {
3003                    oldTemp = rec.batteryTemperature;
3004                    pw.print(checkin ? ",Bt=" : " temp=");
3005                    pw.print(oldTemp);
3006                }
3007                if (oldVolt != rec.batteryVoltage) {
3008                    oldVolt = rec.batteryVoltage;
3009                    pw.print(checkin ? ",Bv=" : " volt=");
3010                    pw.print(oldVolt);
3011                }
3012                printBitDescriptions(pw, oldState, rec.states, rec.wakelockTag,
3013                        HISTORY_STATE_DESCRIPTIONS, !checkin);
3014                printBitDescriptions(pw, oldState2, rec.states2, null,
3015                        HISTORY_STATE2_DESCRIPTIONS, !checkin);
3016                if (rec.wakeReasonTag != null) {
3017                    if (checkin) {
3018                        pw.print(",Wr=");
3019                        pw.print(rec.wakeReasonTag.poolIdx);
3020                    } else {
3021                        pw.print(" wake_reason=");
3022                        pw.print(rec.wakeReasonTag.uid);
3023                        pw.print(":\"");
3024                        pw.print(rec.wakeReasonTag.string);
3025                        pw.print("\"");
3026                    }
3027                }
3028                if (rec.eventCode != HistoryItem.EVENT_NONE) {
3029                    pw.print(checkin ? "," : " ");
3030                    if ((rec.eventCode&HistoryItem.EVENT_FLAG_START) != 0) {
3031                        pw.print("+");
3032                    } else if ((rec.eventCode&HistoryItem.EVENT_FLAG_FINISH) != 0) {
3033                        pw.print("-");
3034                    }
3035                    String[] eventNames = checkin ? HISTORY_EVENT_CHECKIN_NAMES
3036                            : HISTORY_EVENT_NAMES;
3037                    int idx = rec.eventCode & ~(HistoryItem.EVENT_FLAG_START
3038                            | HistoryItem.EVENT_FLAG_FINISH);
3039                    if (idx >= 0 && idx < eventNames.length) {
3040                        pw.print(eventNames[idx]);
3041                    } else {
3042                        pw.print(checkin ? "Ev" : "event");
3043                        pw.print(idx);
3044                    }
3045                    pw.print("=");
3046                    if (checkin) {
3047                        pw.print(rec.eventTag.poolIdx);
3048                    } else {
3049                        UserHandle.formatUid(pw, rec.eventTag.uid);
3050                        pw.print(":\"");
3051                        pw.print(rec.eventTag.string);
3052                        pw.print("\"");
3053                    }
3054                }
3055                pw.println();
3056                oldState = rec.states;
3057            }
3058        }
3059    }
3060
3061    private void printSizeValue(PrintWriter pw, long size) {
3062        float result = size;
3063        String suffix = "";
3064        if (result >= 10*1024) {
3065            suffix = "KB";
3066            result = result / 1024;
3067        }
3068        if (result >= 10*1024) {
3069            suffix = "MB";
3070            result = result / 1024;
3071        }
3072        if (result >= 10*1024) {
3073            suffix = "GB";
3074            result = result / 1024;
3075        }
3076        if (result >= 10*1024) {
3077            suffix = "TB";
3078            result = result / 1024;
3079        }
3080        if (result >= 10*1024) {
3081            suffix = "PB";
3082            result = result / 1024;
3083        }
3084        pw.print((int)result);
3085        pw.print(suffix);
3086    }
3087
3088    public static final int DUMP_UNPLUGGED_ONLY = 1<<0;
3089    public static final int DUMP_CHARGED_ONLY = 1<<1;
3090    public static final int DUMP_HISTORY_ONLY = 1<<2;
3091    public static final int DUMP_INCLUDE_HISTORY = 1<<3;
3092    public static final int DUMP_VERBOSE = 1<<4;
3093
3094    /**
3095     * Dumps a human-readable summary of the battery statistics to the given PrintWriter.
3096     *
3097     * @param pw a Printer to receive the dump output.
3098     */
3099    @SuppressWarnings("unused")
3100    public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
3101        prepareForDumpLocked();
3102
3103        final boolean filtering =
3104                (flags&(DUMP_HISTORY_ONLY|DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY)) != 0;
3105
3106        if ((flags&DUMP_HISTORY_ONLY) != 0 || !filtering) {
3107            long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
3108
3109            final HistoryItem rec = new HistoryItem();
3110            final long historyTotalSize = getHistoryTotalSize();
3111            final long historyUsedSize = getHistoryUsedSize();
3112            if (startIteratingHistoryLocked()) {
3113                try {
3114                    pw.print("Battery History (");
3115                    pw.print((100*historyUsedSize)/historyTotalSize);
3116                    pw.print("% used, ");
3117                    printSizeValue(pw, historyUsedSize);
3118                    pw.print(" used of ");
3119                    printSizeValue(pw, historyTotalSize);
3120                    pw.print(", ");
3121                    pw.print(getHistoryStringPoolSize());
3122                    pw.print(" strings using ");
3123                    printSizeValue(pw, getHistoryStringPoolBytes());
3124                    pw.println("):");
3125                    HistoryPrinter hprinter = new HistoryPrinter();
3126                    long lastTime = -1;
3127                    long baseTime = -1;
3128                    boolean printed = false;
3129                    while (getNextHistoryLocked(rec)) {
3130                        lastTime = rec.time;
3131                        if (baseTime < 0) {
3132                            baseTime = lastTime;
3133                        }
3134                        if (rec.time >= histStart) {
3135                            if (histStart >= 0 && !printed) {
3136                                if (rec.cmd == HistoryItem.CMD_CURRENT_TIME) {
3137                                    printed = true;
3138                                } else if (rec.currentTime != 0) {
3139                                    printed = true;
3140                                    byte cmd = rec.cmd;
3141                                    rec.cmd = HistoryItem.CMD_CURRENT_TIME;
3142                                    hprinter.printNextItem(pw, rec, baseTime, false,
3143                                            (flags&DUMP_VERBOSE) != 0);
3144                                    rec.cmd = cmd;
3145                                }
3146                            }
3147                            hprinter.printNextItem(pw, rec, baseTime, false,
3148                                    (flags&DUMP_VERBOSE) != 0);
3149                        }
3150                    }
3151                    if (histStart >= 0) {
3152                        pw.print("  NEXT: "); pw.println(lastTime+1);
3153                    }
3154                    pw.println();
3155                } finally {
3156                    finishIteratingHistoryLocked();
3157                }
3158            }
3159
3160            if (startIteratingOldHistoryLocked()) {
3161                try {
3162                    pw.println("Old battery History:");
3163                    HistoryPrinter hprinter = new HistoryPrinter();
3164                    long baseTime = -1;
3165                    while (getNextOldHistoryLocked(rec)) {
3166                        if (baseTime < 0) {
3167                            baseTime = rec.time;
3168                        }
3169                        hprinter.printNextItem(pw, rec, baseTime, false, (flags&DUMP_VERBOSE) != 0);
3170                    }
3171                    pw.println();
3172                } finally {
3173                    finishIteratingOldHistoryLocked();
3174                }
3175            }
3176        }
3177
3178        if (filtering && (flags&(DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY)) == 0) {
3179            return;
3180        }
3181
3182        if (!filtering) {
3183            SparseArray<? extends Uid> uidStats = getUidStats();
3184            final int NU = uidStats.size();
3185            boolean didPid = false;
3186            long nowRealtime = SystemClock.elapsedRealtime();
3187            for (int i=0; i<NU; i++) {
3188                Uid uid = uidStats.valueAt(i);
3189                SparseArray<? extends Uid.Pid> pids = uid.getPidStats();
3190                if (pids != null) {
3191                    for (int j=0; j<pids.size(); j++) {
3192                        Uid.Pid pid = pids.valueAt(j);
3193                        if (!didPid) {
3194                            pw.println("Per-PID Stats:");
3195                            didPid = true;
3196                        }
3197                        long time = pid.mWakeSumMs + (pid.mWakeNesting > 0
3198                                ? (nowRealtime - pid.mWakeStartMs) : 0);
3199                        pw.print("  PID "); pw.print(pids.keyAt(j));
3200                                pw.print(" wake time: ");
3201                                TimeUtils.formatDuration(time, pw);
3202                                pw.println("");
3203                    }
3204                }
3205            }
3206            if (didPid) {
3207                pw.println("");
3208            }
3209        }
3210
3211        if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
3212            pw.println("Statistics since last charge:");
3213            pw.println("  System starts: " + getStartCount()
3214                    + ", currently on battery: " + getIsOnBattery());
3215            dumpLocked(context, pw, "", STATS_SINCE_CHARGED, reqUid);
3216            pw.println("");
3217        }
3218        if (!filtering || (flags&DUMP_UNPLUGGED_ONLY) != 0) {
3219            pw.println("Statistics since last unplugged:");
3220            dumpLocked(context, pw, "", STATS_SINCE_UNPLUGGED, reqUid);
3221        }
3222    }
3223
3224    @SuppressWarnings("unused")
3225    public void dumpCheckinLocked(Context context, PrintWriter pw,
3226            List<ApplicationInfo> apps, int flags, long histStart) {
3227        prepareForDumpLocked();
3228
3229        long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
3230
3231        final boolean filtering =
3232                (flags&(DUMP_HISTORY_ONLY|DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY)) != 0;
3233
3234        if ((flags&DUMP_INCLUDE_HISTORY) != 0 || (flags&DUMP_HISTORY_ONLY) != 0) {
3235            final HistoryItem rec = new HistoryItem();
3236            if (startIteratingHistoryLocked()) {
3237                try {
3238                    for (int i=0; i<getHistoryStringPoolSize(); i++) {
3239                        pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
3240                        pw.print(HISTORY_STRING_POOL); pw.print(',');
3241                        pw.print(i);
3242                        pw.print(",");
3243                        pw.print(getHistoryTagPoolUid(i));
3244                        pw.print(",\"");
3245                        String str = getHistoryTagPoolString(i);
3246                        str = str.replace("\\", "\\\\");
3247                        str = str.replace("\"", "\\\"");
3248                        pw.print(str);
3249                        pw.print("\"");
3250                        pw.println();
3251                    }
3252                    HistoryPrinter hprinter = new HistoryPrinter();
3253                    long lastTime = -1;
3254                    long baseTime = -1;
3255                    boolean printed = false;
3256                    while (getNextHistoryLocked(rec)) {
3257                        lastTime = rec.time;
3258                        if (baseTime < 0) {
3259                            baseTime = lastTime;
3260                        }
3261                        if (rec.time >= histStart) {
3262                            if (histStart >= 0 && !printed) {
3263                                if (rec.cmd == HistoryItem.CMD_CURRENT_TIME) {
3264                                    printed = true;
3265                                } else if (rec.currentTime != 0) {
3266                                    printed = true;
3267                                    byte cmd = rec.cmd;
3268                                    rec.cmd = HistoryItem.CMD_CURRENT_TIME;
3269                                    pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
3270                                    pw.print(HISTORY_DATA); pw.print(',');
3271                                    hprinter.printNextItem(pw, rec, baseTime, true, false);
3272                                    rec.cmd = cmd;
3273                                }
3274                            }
3275                            pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
3276                            pw.print(HISTORY_DATA); pw.print(',');
3277                            hprinter.printNextItem(pw, rec, baseTime, true, false);
3278                        }
3279                    }
3280                    if (histStart >= 0) {
3281                        pw.print("NEXT: "); pw.println(lastTime+1);
3282                    }
3283                } finally {
3284                    finishIteratingHistoryLocked();
3285                }
3286            }
3287        }
3288
3289        if (filtering && (flags&(DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY)) == 0) {
3290            return;
3291        }
3292
3293        if (apps != null) {
3294            SparseArray<ArrayList<String>> uids = new SparseArray<ArrayList<String>>();
3295            for (int i=0; i<apps.size(); i++) {
3296                ApplicationInfo ai = apps.get(i);
3297                ArrayList<String> pkgs = uids.get(ai.uid);
3298                if (pkgs == null) {
3299                    pkgs = new ArrayList<String>();
3300                    uids.put(ai.uid, pkgs);
3301                }
3302                pkgs.add(ai.packageName);
3303            }
3304            SparseArray<? extends Uid> uidStats = getUidStats();
3305            final int NU = uidStats.size();
3306            String[] lineArgs = new String[2];
3307            for (int i=0; i<NU; i++) {
3308                int uid = uidStats.keyAt(i);
3309                ArrayList<String> pkgs = uids.get(uid);
3310                if (pkgs != null) {
3311                    for (int j=0; j<pkgs.size(); j++) {
3312                        lineArgs[0] = Integer.toString(uid);
3313                        lineArgs[1] = pkgs.get(j);
3314                        dumpLine(pw, 0 /* uid */, "i" /* category */, UID_DATA,
3315                                (Object[])lineArgs);
3316                    }
3317                }
3318            }
3319        }
3320        if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
3321            dumpCheckinLocked(context, pw, STATS_SINCE_CHARGED, -1);
3322        }
3323        if (!filtering || (flags&DUMP_UNPLUGGED_ONLY) != 0) {
3324            dumpCheckinLocked(context, pw, STATS_SINCE_UNPLUGGED, -1);
3325        }
3326    }
3327}
3328