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