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