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