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