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