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