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