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