BatteryStats.java revision 782327bde70bfb92352a0270baeae04361b6e9c2
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                getMobileRadioActiveCount(which),
2620                getMobileRadioActiveUnknownTime(which) / 1000);
2621
2622        // Dump screen brightness stats
2623        Object[] args = new Object[NUM_SCREEN_BRIGHTNESS_BINS];
2624        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
2625            args[i] = getScreenBrightnessTime(i, rawRealtime, which) / 1000;
2626        }
2627        dumpLine(pw, 0 /* uid */, category, SCREEN_BRIGHTNESS_DATA, args);
2628
2629        // Dump signal strength stats
2630        args = new Object[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
2631        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
2632            args[i] = getPhoneSignalStrengthTime(i, rawRealtime, which) / 1000;
2633        }
2634        dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_TIME_DATA, args);
2635        dumpLine(pw, 0 /* uid */, category, SIGNAL_SCANNING_TIME_DATA,
2636                getPhoneSignalScanningTime(rawRealtime, which) / 1000);
2637        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
2638            args[i] = getPhoneSignalStrengthCount(i, which);
2639        }
2640        dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_COUNT_DATA, args);
2641
2642        // Dump network type stats
2643        args = new Object[NUM_DATA_CONNECTION_TYPES];
2644        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
2645            args[i] = getPhoneDataConnectionTime(i, rawRealtime, which) / 1000;
2646        }
2647        dumpLine(pw, 0 /* uid */, category, DATA_CONNECTION_TIME_DATA, args);
2648        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
2649            args[i] = getPhoneDataConnectionCount(i, which);
2650        }
2651        dumpLine(pw, 0 /* uid */, category, DATA_CONNECTION_COUNT_DATA, args);
2652
2653        // Dump wifi state stats
2654        args = new Object[NUM_WIFI_STATES];
2655        for (int i=0; i<NUM_WIFI_STATES; i++) {
2656            args[i] = getWifiStateTime(i, rawRealtime, which) / 1000;
2657        }
2658        dumpLine(pw, 0 /* uid */, category, WIFI_STATE_TIME_DATA, args);
2659        for (int i=0; i<NUM_WIFI_STATES; i++) {
2660            args[i] = getWifiStateCount(i, which);
2661        }
2662        dumpLine(pw, 0 /* uid */, category, WIFI_STATE_COUNT_DATA, args);
2663
2664        // Dump wifi suppl state stats
2665        args = new Object[NUM_WIFI_SUPPL_STATES];
2666        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
2667            args[i] = getWifiSupplStateTime(i, rawRealtime, which) / 1000;
2668        }
2669        dumpLine(pw, 0 /* uid */, category, WIFI_SUPPL_STATE_TIME_DATA, args);
2670        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
2671            args[i] = getWifiSupplStateCount(i, which);
2672        }
2673        dumpLine(pw, 0 /* uid */, category, WIFI_SUPPL_STATE_COUNT_DATA, args);
2674
2675        // Dump wifi signal strength stats
2676        args = new Object[NUM_WIFI_SIGNAL_STRENGTH_BINS];
2677        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
2678            args[i] = getWifiSignalStrengthTime(i, rawRealtime, which) / 1000;
2679        }
2680        dumpLine(pw, 0 /* uid */, category, WIFI_SIGNAL_STRENGTH_TIME_DATA, args);
2681        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
2682            args[i] = getWifiSignalStrengthCount(i, which);
2683        }
2684        dumpLine(pw, 0 /* uid */, category, WIFI_SIGNAL_STRENGTH_COUNT_DATA, args);
2685
2686        if (which == STATS_SINCE_UNPLUGGED) {
2687            dumpLine(pw, 0 /* uid */, category, BATTERY_LEVEL_DATA, getDischargeStartLevel(),
2688                    getDischargeCurrentLevel());
2689        }
2690
2691        if (which == STATS_SINCE_UNPLUGGED) {
2692            dumpLine(pw, 0 /* uid */, category, BATTERY_DISCHARGE_DATA,
2693                    getDischargeStartLevel()-getDischargeCurrentLevel(),
2694                    getDischargeStartLevel()-getDischargeCurrentLevel(),
2695                    getDischargeAmountScreenOn(), getDischargeAmountScreenOff());
2696        } else {
2697            dumpLine(pw, 0 /* uid */, category, BATTERY_DISCHARGE_DATA,
2698                    getLowDischargeAmountSinceCharge(), getHighDischargeAmountSinceCharge(),
2699                    getDischargeAmountScreenOnSinceCharge(),
2700                    getDischargeAmountScreenOffSinceCharge());
2701        }
2702
2703        if (reqUid < 0) {
2704            final Map<String, ? extends Timer> kernelWakelocks = getKernelWakelockStats();
2705            if (kernelWakelocks.size() > 0) {
2706                for (Map.Entry<String, ? extends Timer> ent : kernelWakelocks.entrySet()) {
2707                    sb.setLength(0);
2708                    printWakeLockCheckin(sb, ent.getValue(), rawRealtime, null, which, "");
2709                    dumpLine(pw, 0 /* uid */, category, KERNEL_WAKELOCK_DATA, ent.getKey(),
2710                            sb.toString());
2711                }
2712            }
2713            final Map<String, ? extends Timer> wakeupReasons = getWakeupReasonStats();
2714            if (wakeupReasons.size() > 0) {
2715                for (Map.Entry<String, ? extends Timer> ent : wakeupReasons.entrySet()) {
2716                    // Not doing the regular wake lock formatting to remain compatible
2717                    // with the old checkin format.
2718                    long totalTimeMicros = ent.getValue().getTotalTimeLocked(rawRealtime, which);
2719                    int count = ent.getValue().getCountLocked(which);
2720                    dumpLine(pw, 0 /* uid */, category, WAKEUP_REASON_DATA,
2721                            "\"" + ent.getKey() + "\"", (totalTimeMicros + 500) / 1000, count);
2722                }
2723            }
2724        }
2725
2726        final BatteryStatsHelper helper = new BatteryStatsHelper(context, false, wifiOnly);
2727        helper.create(this);
2728        helper.refreshStats(which, UserHandle.USER_ALL);
2729        final List<BatterySipper> sippers = helper.getUsageList();
2730        if (sippers != null && sippers.size() > 0) {
2731            dumpLine(pw, 0 /* uid */, category, POWER_USE_SUMMARY_DATA,
2732                    BatteryStatsHelper.makemAh(helper.getPowerProfile().getBatteryCapacity()),
2733                    BatteryStatsHelper.makemAh(helper.getComputedPower()),
2734                    BatteryStatsHelper.makemAh(helper.getMinDrainedPower()),
2735                    BatteryStatsHelper.makemAh(helper.getMaxDrainedPower()));
2736            for (int i=0; i<sippers.size(); i++) {
2737                final BatterySipper bs = sippers.get(i);
2738                int uid = 0;
2739                String label;
2740                switch (bs.drainType) {
2741                    case IDLE:
2742                        label="idle";
2743                        break;
2744                    case CELL:
2745                        label="cell";
2746                        break;
2747                    case PHONE:
2748                        label="phone";
2749                        break;
2750                    case WIFI:
2751                        label="wifi";
2752                        break;
2753                    case BLUETOOTH:
2754                        label="blue";
2755                        break;
2756                    case SCREEN:
2757                        label="scrn";
2758                        break;
2759                    case FLASHLIGHT:
2760                        label="flashlight";
2761                        break;
2762                    case APP:
2763                        uid = bs.uidObj.getUid();
2764                        label = "uid";
2765                        break;
2766                    case USER:
2767                        uid = UserHandle.getUid(bs.userId, 0);
2768                        label = "user";
2769                        break;
2770                    case UNACCOUNTED:
2771                        label = "unacc";
2772                        break;
2773                    case OVERCOUNTED:
2774                        label = "over";
2775                        break;
2776                    case CAMERA:
2777                        label = "camera";
2778                        break;
2779                    default:
2780                        label = "???";
2781                }
2782                dumpLine(pw, uid, category, POWER_USE_ITEM_DATA, label,
2783                        BatteryStatsHelper.makemAh(bs.totalPowerMah));
2784            }
2785        }
2786
2787        for (int iu = 0; iu < NU; iu++) {
2788            final int uid = uidStats.keyAt(iu);
2789            if (reqUid >= 0 && uid != reqUid) {
2790                continue;
2791            }
2792            final Uid u = uidStats.valueAt(iu);
2793
2794            // Dump Network stats per uid, if any
2795            final long mobileBytesRx = u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
2796            final long mobileBytesTx = u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
2797            final long wifiBytesRx = u.getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
2798            final long wifiBytesTx = u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
2799            final long mobilePacketsRx = u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
2800            final long mobilePacketsTx = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
2801            final long mobileActiveTime = u.getMobileRadioActiveTime(which);
2802            final int mobileActiveCount = u.getMobileRadioActiveCount(which);
2803            final long wifiPacketsRx = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
2804            final long wifiPacketsTx = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
2805            if (mobileBytesRx > 0 || mobileBytesTx > 0 || wifiBytesRx > 0 || wifiBytesTx > 0
2806                    || mobilePacketsRx > 0 || mobilePacketsTx > 0 || wifiPacketsRx > 0
2807                    || wifiPacketsTx > 0 || mobileActiveTime > 0 || mobileActiveCount > 0) {
2808                dumpLine(pw, uid, category, NETWORK_DATA, mobileBytesRx, mobileBytesTx,
2809                        wifiBytesRx, wifiBytesTx,
2810                        mobilePacketsRx, mobilePacketsTx,
2811                        wifiPacketsRx, wifiPacketsTx,
2812                        mobileActiveTime, mobileActiveCount);
2813            }
2814
2815            final long fullWifiLockOnTime = u.getFullWifiLockTime(rawRealtime, which);
2816            final long wifiScanTime = u.getWifiScanTime(rawRealtime, which);
2817            final int wifiScanCount = u.getWifiScanCount(which);
2818            final long uidWifiRunningTime = u.getWifiRunningTime(rawRealtime, which);
2819            final long uidWifiIdleTimeMs = u.getWifiControllerActivity(CONTROLLER_IDLE_TIME, which);
2820            final long uidWifiRxTimeMs = u.getWifiControllerActivity(CONTROLLER_RX_TIME, which);
2821            final long uidWifiTxTimeMs = u.getWifiControllerActivity(CONTROLLER_TX_TIME, which);
2822            if (fullWifiLockOnTime != 0 || wifiScanTime != 0 || wifiScanCount != 0
2823                    || uidWifiRunningTime != 0 || uidWifiIdleTimeMs != 0 || uidWifiRxTimeMs != 0
2824                    || uidWifiTxTimeMs != 0) {
2825                dumpLine(pw, uid, category, WIFI_DATA,
2826                        fullWifiLockOnTime, wifiScanTime, uidWifiRunningTime, wifiScanCount,
2827                        uidWifiIdleTimeMs, uidWifiRxTimeMs, uidWifiTxTimeMs);
2828            }
2829
2830            if (u.hasUserActivity()) {
2831                args = new Object[Uid.NUM_USER_ACTIVITY_TYPES];
2832                boolean hasData = false;
2833                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
2834                    int val = u.getUserActivityCount(i, which);
2835                    args[i] = val;
2836                    if (val != 0) hasData = true;
2837                }
2838                if (hasData) {
2839                    dumpLine(pw, uid /* uid */, category, USER_ACTIVITY_DATA, args);
2840                }
2841            }
2842
2843            final ArrayMap<String, ? extends Uid.Wakelock> wakelocks = u.getWakelockStats();
2844            for (int iw=wakelocks.size()-1; iw>=0; iw--) {
2845                final Uid.Wakelock wl = wakelocks.valueAt(iw);
2846                String linePrefix = "";
2847                sb.setLength(0);
2848                linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_FULL),
2849                        rawRealtime, "f", which, linePrefix);
2850                linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL),
2851                        rawRealtime, "p", which, linePrefix);
2852                linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_WINDOW),
2853                        rawRealtime, "w", which, linePrefix);
2854
2855                // Only log if we had at lease one wakelock...
2856                if (sb.length() > 0) {
2857                    String name = wakelocks.keyAt(iw);
2858                    if (name.indexOf(',') >= 0) {
2859                        name = name.replace(',', '_');
2860                    }
2861                    dumpLine(pw, uid, category, WAKELOCK_DATA, name, sb.toString());
2862                }
2863            }
2864
2865            final ArrayMap<String, ? extends Timer> syncs = u.getSyncStats();
2866            for (int isy=syncs.size()-1; isy>=0; isy--) {
2867                final Timer timer = syncs.valueAt(isy);
2868                // Convert from microseconds to milliseconds with rounding
2869                final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
2870                final int count = timer.getCountLocked(which);
2871                if (totalTime != 0) {
2872                    dumpLine(pw, uid, category, SYNC_DATA, syncs.keyAt(isy), totalTime, count);
2873                }
2874            }
2875
2876            final ArrayMap<String, ? extends Timer> jobs = u.getJobStats();
2877            for (int ij=jobs.size()-1; ij>=0; ij--) {
2878                final Timer timer = jobs.valueAt(ij);
2879                // Convert from microseconds to milliseconds with rounding
2880                final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
2881                final int count = timer.getCountLocked(which);
2882                if (totalTime != 0) {
2883                    dumpLine(pw, uid, category, JOB_DATA, jobs.keyAt(ij), totalTime, count);
2884                }
2885            }
2886
2887            dumpTimer(pw, uid, category, FLASHLIGHT_DATA, u.getFlashlightTurnedOnTimer(),
2888                    rawRealtime, which);
2889            dumpTimer(pw, uid, category, CAMERA_DATA, u.getCameraTurnedOnTimer(),
2890                    rawRealtime, which);
2891            dumpTimer(pw, uid, category, VIDEO_DATA, u.getVideoTurnedOnTimer(),
2892                    rawRealtime, which);
2893            dumpTimer(pw, uid, category, AUDIO_DATA, u.getAudioTurnedOnTimer(),
2894                    rawRealtime, which);
2895
2896            final SparseArray<? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
2897            final int NSE = sensors.size();
2898            for (int ise=0; ise<NSE; ise++) {
2899                final Uid.Sensor se = sensors.valueAt(ise);
2900                final int sensorNumber = sensors.keyAt(ise);
2901                final Timer timer = se.getSensorTime();
2902                if (timer != null) {
2903                    // Convert from microseconds to milliseconds with rounding
2904                    final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500)
2905                            / 1000;
2906                    final int count = timer.getCountLocked(which);
2907                    if (totalTime != 0) {
2908                        dumpLine(pw, uid, category, SENSOR_DATA, sensorNumber, totalTime, count);
2909                    }
2910                }
2911            }
2912
2913            dumpTimer(pw, uid, category, VIBRATOR_DATA, u.getVibratorOnTimer(),
2914                    rawRealtime, which);
2915
2916            dumpTimer(pw, uid, category, FOREGROUND_DATA, u.getForegroundActivityTimer(),
2917                    rawRealtime, which);
2918
2919            final Object[] stateTimes = new Object[Uid.NUM_PROCESS_STATE];
2920            long totalStateTime = 0;
2921            for (int ips=0; ips<Uid.NUM_PROCESS_STATE; ips++) {
2922                totalStateTime += u.getProcessStateTime(ips, rawRealtime, which);
2923                stateTimes[ips] = (totalStateTime + 500) / 1000;
2924            }
2925            if (totalStateTime > 0) {
2926                dumpLine(pw, uid, category, STATE_TIME_DATA, stateTimes);
2927            }
2928
2929            final long userCpuTimeUs = u.getUserCpuTimeUs(which);
2930            final long systemCpuTimeUs = u.getSystemCpuTimeUs(which);
2931            final long powerCpuMaUs = u.getCpuPowerMaUs(which);
2932            if (userCpuTimeUs > 0 || systemCpuTimeUs > 0 || powerCpuMaUs > 0) {
2933                dumpLine(pw, uid, category, CPU_DATA, userCpuTimeUs / 1000, systemCpuTimeUs / 1000,
2934                        powerCpuMaUs / 1000);
2935            }
2936
2937            final ArrayMap<String, ? extends BatteryStats.Uid.Proc> processStats
2938                    = u.getProcessStats();
2939            for (int ipr=processStats.size()-1; ipr>=0; ipr--) {
2940                final Uid.Proc ps = processStats.valueAt(ipr);
2941
2942                final long userMillis = ps.getUserTime(which);
2943                final long systemMillis = ps.getSystemTime(which);
2944                final long foregroundMillis = ps.getForegroundTime(which);
2945                final int starts = ps.getStarts(which);
2946                final int numCrashes = ps.getNumCrashes(which);
2947                final int numAnrs = ps.getNumAnrs(which);
2948
2949                if (userMillis != 0 || systemMillis != 0 || foregroundMillis != 0
2950                        || starts != 0 || numAnrs != 0 || numCrashes != 0) {
2951                    dumpLine(pw, uid, category, PROCESS_DATA, processStats.keyAt(ipr), userMillis,
2952                            systemMillis, foregroundMillis, starts, numAnrs, numCrashes);
2953                }
2954            }
2955
2956            final ArrayMap<String, ? extends BatteryStats.Uid.Pkg> packageStats
2957                    = u.getPackageStats();
2958            for (int ipkg=packageStats.size()-1; ipkg>=0; ipkg--) {
2959                final Uid.Pkg ps = packageStats.valueAt(ipkg);
2960                int wakeups = 0;
2961                final ArrayMap<String, ? extends Counter> alarms = ps.getWakeupAlarmStats();
2962                for (int iwa=alarms.size()-1; iwa>=0; iwa--) {
2963                    wakeups += alarms.valueAt(iwa).getCountLocked(which);
2964                }
2965                final ArrayMap<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
2966                for (int isvc=serviceStats.size()-1; isvc>=0; isvc--) {
2967                    final BatteryStats.Uid.Pkg.Serv ss = serviceStats.valueAt(isvc);
2968                    final long startTime = ss.getStartTime(batteryUptime, which);
2969                    final int starts = ss.getStarts(which);
2970                    final int launches = ss.getLaunches(which);
2971                    if (startTime != 0 || starts != 0 || launches != 0) {
2972                        dumpLine(pw, uid, category, APK_DATA,
2973                                wakeups, // wakeup alarms
2974                                packageStats.keyAt(ipkg), // Apk
2975                                serviceStats.keyAt(isvc), // service
2976                                startTime / 1000, // time spent started, in ms
2977                                starts,
2978                                launches);
2979                    }
2980                }
2981            }
2982        }
2983    }
2984
2985    static final class TimerEntry {
2986        final String mName;
2987        final int mId;
2988        final BatteryStats.Timer mTimer;
2989        final long mTime;
2990        TimerEntry(String name, int id, BatteryStats.Timer timer, long time) {
2991            mName = name;
2992            mId = id;
2993            mTimer = timer;
2994            mTime = time;
2995        }
2996    }
2997
2998    private void printmAh(PrintWriter printer, double power) {
2999        printer.print(BatteryStatsHelper.makemAh(power));
3000    }
3001
3002    private void printmAh(StringBuilder sb, double power) {
3003        sb.append(BatteryStatsHelper.makemAh(power));
3004    }
3005
3006    /**
3007     * Temporary for settings.
3008     */
3009    public final void dumpLocked(Context context, PrintWriter pw, String prefix, int which,
3010            int reqUid) {
3011        dumpLocked(context, pw, prefix, which, reqUid, BatteryStatsHelper.checkWifiOnly(context));
3012    }
3013
3014    @SuppressWarnings("unused")
3015    public final void dumpLocked(Context context, PrintWriter pw, String prefix, final int which,
3016            int reqUid, boolean wifiOnly) {
3017        final long rawUptime = SystemClock.uptimeMillis() * 1000;
3018        final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
3019        final long batteryUptime = getBatteryUptime(rawUptime);
3020
3021        final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
3022        final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
3023        final long totalRealtime = computeRealtime(rawRealtime, which);
3024        final long totalUptime = computeUptime(rawUptime, which);
3025        final long whichBatteryScreenOffUptime = computeBatteryScreenOffUptime(rawUptime, which);
3026        final long whichBatteryScreenOffRealtime = computeBatteryScreenOffRealtime(rawRealtime,
3027                which);
3028        final long batteryTimeRemaining = computeBatteryTimeRemaining(rawRealtime);
3029        final long chargeTimeRemaining = computeChargeTimeRemaining(rawRealtime);
3030
3031        final StringBuilder sb = new StringBuilder(128);
3032
3033        final SparseArray<? extends Uid> uidStats = getUidStats();
3034        final int NU = uidStats.size();
3035
3036        sb.setLength(0);
3037        sb.append(prefix);
3038                sb.append("  Time on battery: ");
3039                formatTimeMs(sb, whichBatteryRealtime / 1000); sb.append("(");
3040                sb.append(formatRatioLocked(whichBatteryRealtime, totalRealtime));
3041                sb.append(") realtime, ");
3042                formatTimeMs(sb, whichBatteryUptime / 1000);
3043                sb.append("("); sb.append(formatRatioLocked(whichBatteryUptime, totalRealtime));
3044                sb.append(") uptime");
3045        pw.println(sb.toString());
3046        sb.setLength(0);
3047        sb.append(prefix);
3048                sb.append("  Time on battery screen off: ");
3049                formatTimeMs(sb, whichBatteryScreenOffRealtime / 1000); sb.append("(");
3050                sb.append(formatRatioLocked(whichBatteryScreenOffRealtime, totalRealtime));
3051                sb.append(") realtime, ");
3052                formatTimeMs(sb, whichBatteryScreenOffUptime / 1000);
3053                sb.append("(");
3054                sb.append(formatRatioLocked(whichBatteryScreenOffUptime, totalRealtime));
3055                sb.append(") uptime");
3056        pw.println(sb.toString());
3057        sb.setLength(0);
3058        sb.append(prefix);
3059                sb.append("  Total run time: ");
3060                formatTimeMs(sb, totalRealtime / 1000);
3061                sb.append("realtime, ");
3062                formatTimeMs(sb, totalUptime / 1000);
3063                sb.append("uptime");
3064        pw.println(sb.toString());
3065        if (batteryTimeRemaining >= 0) {
3066            sb.setLength(0);
3067            sb.append(prefix);
3068                    sb.append("  Battery time remaining: ");
3069                    formatTimeMs(sb, batteryTimeRemaining / 1000);
3070            pw.println(sb.toString());
3071        }
3072        if (chargeTimeRemaining >= 0) {
3073            sb.setLength(0);
3074            sb.append(prefix);
3075                    sb.append("  Charge time remaining: ");
3076                    formatTimeMs(sb, chargeTimeRemaining / 1000);
3077            pw.println(sb.toString());
3078        }
3079        pw.print("  Start clock time: ");
3080        pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss", getStartClockTime()).toString());
3081
3082        final long screenOnTime = getScreenOnTime(rawRealtime, which);
3083        final long interactiveTime = getInteractiveTime(rawRealtime, which);
3084        final long powerSaveModeEnabledTime = getPowerSaveModeEnabledTime(rawRealtime, which);
3085        final long deviceIdleModeEnabledTime = getDeviceIdleModeEnabledTime(rawRealtime, which);
3086        final long deviceIdlingTime = getDeviceIdlingTime(rawRealtime, which);
3087        final long phoneOnTime = getPhoneOnTime(rawRealtime, which);
3088        final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which);
3089        final long wifiOnTime = getWifiOnTime(rawRealtime, which);
3090        sb.setLength(0);
3091        sb.append(prefix);
3092                sb.append("  Screen on: "); formatTimeMs(sb, screenOnTime / 1000);
3093                sb.append("("); sb.append(formatRatioLocked(screenOnTime, whichBatteryRealtime));
3094                sb.append(") "); sb.append(getScreenOnCount(which));
3095                sb.append("x, Interactive: "); formatTimeMs(sb, interactiveTime / 1000);
3096                sb.append("("); sb.append(formatRatioLocked(interactiveTime, whichBatteryRealtime));
3097                sb.append(")");
3098        pw.println(sb.toString());
3099        sb.setLength(0);
3100        sb.append(prefix);
3101        sb.append("  Screen brightnesses:");
3102        boolean didOne = false;
3103        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
3104            final long time = getScreenBrightnessTime(i, rawRealtime, which);
3105            if (time == 0) {
3106                continue;
3107            }
3108            sb.append("\n    ");
3109            sb.append(prefix);
3110            didOne = true;
3111            sb.append(SCREEN_BRIGHTNESS_NAMES[i]);
3112            sb.append(" ");
3113            formatTimeMs(sb, time/1000);
3114            sb.append("(");
3115            sb.append(formatRatioLocked(time, screenOnTime));
3116            sb.append(")");
3117        }
3118        if (!didOne) sb.append(" (no activity)");
3119        pw.println(sb.toString());
3120        if (powerSaveModeEnabledTime != 0) {
3121            sb.setLength(0);
3122            sb.append(prefix);
3123                    sb.append("  Power save mode enabled: ");
3124                    formatTimeMs(sb, powerSaveModeEnabledTime / 1000);
3125                    sb.append("(");
3126                    sb.append(formatRatioLocked(powerSaveModeEnabledTime, whichBatteryRealtime));
3127                    sb.append(")");
3128            pw.println(sb.toString());
3129        }
3130        if (deviceIdlingTime != 0) {
3131            sb.setLength(0);
3132            sb.append(prefix);
3133                    sb.append("  Device idling: ");
3134                    formatTimeMs(sb, deviceIdlingTime / 1000);
3135                    sb.append("(");
3136                    sb.append(formatRatioLocked(deviceIdlingTime, whichBatteryRealtime));
3137                    sb.append(") "); sb.append(getDeviceIdlingCount(which));
3138                    sb.append("x");
3139            pw.println(sb.toString());
3140        }
3141        if (deviceIdleModeEnabledTime != 0) {
3142            sb.setLength(0);
3143            sb.append(prefix);
3144                    sb.append("  Idle mode time: ");
3145                    formatTimeMs(sb, deviceIdleModeEnabledTime / 1000);
3146                    sb.append("(");
3147                    sb.append(formatRatioLocked(deviceIdleModeEnabledTime, whichBatteryRealtime));
3148                    sb.append(") "); sb.append(getDeviceIdleModeEnabledCount(which));
3149                    sb.append("x");
3150            pw.println(sb.toString());
3151        }
3152        if (phoneOnTime != 0) {
3153            sb.setLength(0);
3154            sb.append(prefix);
3155                    sb.append("  Active phone call: "); formatTimeMs(sb, phoneOnTime / 1000);
3156                    sb.append("("); sb.append(formatRatioLocked(phoneOnTime, whichBatteryRealtime));
3157                    sb.append(") "); sb.append(getPhoneOnCount(which)); sb.append("x");
3158        }
3159        final int connChanges = getNumConnectivityChange(which);
3160        if (connChanges != 0) {
3161            pw.print(prefix);
3162            pw.print("  Connectivity changes: "); pw.println(connChanges);
3163        }
3164
3165        // Calculate wakelock times across all uids.
3166        long fullWakeLockTimeTotalMicros = 0;
3167        long partialWakeLockTimeTotalMicros = 0;
3168
3169        final ArrayList<TimerEntry> timers = new ArrayList<>();
3170
3171        for (int iu = 0; iu < NU; iu++) {
3172            final Uid u = uidStats.valueAt(iu);
3173
3174            final ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> wakelocks
3175                    = u.getWakelockStats();
3176            for (int iw=wakelocks.size()-1; iw>=0; iw--) {
3177                final Uid.Wakelock wl = wakelocks.valueAt(iw);
3178
3179                final Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
3180                if (fullWakeTimer != null) {
3181                    fullWakeLockTimeTotalMicros += fullWakeTimer.getTotalTimeLocked(
3182                            rawRealtime, which);
3183                }
3184
3185                final Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
3186                if (partialWakeTimer != null) {
3187                    final long totalTimeMicros = partialWakeTimer.getTotalTimeLocked(
3188                            rawRealtime, which);
3189                    if (totalTimeMicros > 0) {
3190                        if (reqUid < 0) {
3191                            // Only show the ordered list of all wake
3192                            // locks if the caller is not asking for data
3193                            // about a specific uid.
3194                            timers.add(new TimerEntry(wakelocks.keyAt(iw), u.getUid(),
3195                                    partialWakeTimer, totalTimeMicros));
3196                        }
3197                        partialWakeLockTimeTotalMicros += totalTimeMicros;
3198                    }
3199                }
3200            }
3201        }
3202
3203        final long mobileRxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
3204        final long mobileTxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
3205        final long wifiRxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
3206        final long wifiTxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
3207        final long mobileRxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
3208        final long mobileTxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
3209        final long wifiRxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
3210        final long wifiTxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
3211
3212        if (fullWakeLockTimeTotalMicros != 0) {
3213            sb.setLength(0);
3214            sb.append(prefix);
3215                    sb.append("  Total full wakelock time: "); formatTimeMsNoSpace(sb,
3216                            (fullWakeLockTimeTotalMicros + 500) / 1000);
3217            pw.println(sb.toString());
3218        }
3219
3220        if (partialWakeLockTimeTotalMicros != 0) {
3221            sb.setLength(0);
3222            sb.append(prefix);
3223                    sb.append("  Total partial wakelock time: "); formatTimeMsNoSpace(sb,
3224                            (partialWakeLockTimeTotalMicros + 500) / 1000);
3225            pw.println(sb.toString());
3226        }
3227
3228        pw.print(prefix);
3229                pw.print("  Mobile total received: "); pw.print(formatBytesLocked(mobileRxTotalBytes));
3230                pw.print(", sent: "); pw.print(formatBytesLocked(mobileTxTotalBytes));
3231                pw.print(" (packets received "); pw.print(mobileRxTotalPackets);
3232                pw.print(", sent "); pw.print(mobileTxTotalPackets); pw.println(")");
3233        sb.setLength(0);
3234        sb.append(prefix);
3235        sb.append("  Phone signal levels:");
3236        didOne = false;
3237        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
3238            final long time = getPhoneSignalStrengthTime(i, rawRealtime, which);
3239            if (time == 0) {
3240                continue;
3241            }
3242            sb.append("\n    ");
3243            sb.append(prefix);
3244            didOne = true;
3245            sb.append(SignalStrength.SIGNAL_STRENGTH_NAMES[i]);
3246            sb.append(" ");
3247            formatTimeMs(sb, time/1000);
3248            sb.append("(");
3249            sb.append(formatRatioLocked(time, whichBatteryRealtime));
3250            sb.append(") ");
3251            sb.append(getPhoneSignalStrengthCount(i, which));
3252            sb.append("x");
3253        }
3254        if (!didOne) sb.append(" (no activity)");
3255        pw.println(sb.toString());
3256
3257        sb.setLength(0);
3258        sb.append(prefix);
3259        sb.append("  Signal scanning time: ");
3260        formatTimeMsNoSpace(sb, getPhoneSignalScanningTime(rawRealtime, which) / 1000);
3261        pw.println(sb.toString());
3262
3263        sb.setLength(0);
3264        sb.append(prefix);
3265        sb.append("  Radio types:");
3266        didOne = false;
3267        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
3268            final long time = getPhoneDataConnectionTime(i, rawRealtime, which);
3269            if (time == 0) {
3270                continue;
3271            }
3272            sb.append("\n    ");
3273            sb.append(prefix);
3274            didOne = true;
3275            sb.append(DATA_CONNECTION_NAMES[i]);
3276            sb.append(" ");
3277            formatTimeMs(sb, time/1000);
3278            sb.append("(");
3279            sb.append(formatRatioLocked(time, whichBatteryRealtime));
3280            sb.append(") ");
3281            sb.append(getPhoneDataConnectionCount(i, which));
3282            sb.append("x");
3283        }
3284        if (!didOne) sb.append(" (no activity)");
3285        pw.println(sb.toString());
3286
3287        sb.setLength(0);
3288        sb.append(prefix);
3289        sb.append("  Mobile radio active time: ");
3290        final long mobileActiveTime = getMobileRadioActiveTime(rawRealtime, which);
3291        formatTimeMs(sb, mobileActiveTime / 1000);
3292        sb.append("("); sb.append(formatRatioLocked(mobileActiveTime, whichBatteryRealtime));
3293        sb.append(") "); sb.append(getMobileRadioActiveCount(which));
3294        sb.append("x");
3295        pw.println(sb.toString());
3296
3297        final long mobileActiveUnknownTime = getMobileRadioActiveUnknownTime(which);
3298        if (mobileActiveUnknownTime != 0) {
3299            sb.setLength(0);
3300            sb.append(prefix);
3301            sb.append("  Mobile radio active unknown time: ");
3302            formatTimeMs(sb, mobileActiveUnknownTime / 1000);
3303            sb.append("(");
3304            sb.append(formatRatioLocked(mobileActiveUnknownTime, whichBatteryRealtime));
3305            sb.append(") "); sb.append(getMobileRadioActiveUnknownCount(which));
3306            sb.append("x");
3307            pw.println(sb.toString());
3308        }
3309
3310        final long mobileActiveAdjustedTime = getMobileRadioActiveAdjustedTime(which);
3311        if (mobileActiveAdjustedTime != 0) {
3312            sb.setLength(0);
3313            sb.append(prefix);
3314            sb.append("  Mobile radio active adjusted time: ");
3315            formatTimeMs(sb, mobileActiveAdjustedTime / 1000);
3316            sb.append("(");
3317            sb.append(formatRatioLocked(mobileActiveAdjustedTime, whichBatteryRealtime));
3318            sb.append(")");
3319            pw.println(sb.toString());
3320        }
3321
3322        pw.print(prefix);
3323                pw.print("  Wi-Fi total received: "); pw.print(formatBytesLocked(wifiRxTotalBytes));
3324                pw.print(", sent: "); pw.print(formatBytesLocked(wifiTxTotalBytes));
3325                pw.print(" (packets received "); pw.print(wifiRxTotalPackets);
3326                pw.print(", sent "); pw.print(wifiTxTotalPackets); pw.println(")");
3327        sb.setLength(0);
3328        sb.append(prefix);
3329                sb.append("  Wifi on: "); formatTimeMs(sb, wifiOnTime / 1000);
3330                sb.append("("); sb.append(formatRatioLocked(wifiOnTime, whichBatteryRealtime));
3331                sb.append("), Wifi running: "); formatTimeMs(sb, wifiRunningTime / 1000);
3332                sb.append("("); sb.append(formatRatioLocked(wifiRunningTime, whichBatteryRealtime));
3333                sb.append(")");
3334        pw.println(sb.toString());
3335
3336        sb.setLength(0);
3337        sb.append(prefix);
3338        sb.append("  Wifi states:");
3339        didOne = false;
3340        for (int i=0; i<NUM_WIFI_STATES; i++) {
3341            final long time = getWifiStateTime(i, rawRealtime, which);
3342            if (time == 0) {
3343                continue;
3344            }
3345            sb.append("\n    ");
3346            didOne = true;
3347            sb.append(WIFI_STATE_NAMES[i]);
3348            sb.append(" ");
3349            formatTimeMs(sb, time/1000);
3350            sb.append("(");
3351            sb.append(formatRatioLocked(time, whichBatteryRealtime));
3352            sb.append(") ");
3353            sb.append(getWifiStateCount(i, which));
3354            sb.append("x");
3355        }
3356        if (!didOne) sb.append(" (no activity)");
3357        pw.println(sb.toString());
3358
3359        sb.setLength(0);
3360        sb.append(prefix);
3361        sb.append("  Wifi supplicant states:");
3362        didOne = false;
3363        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
3364            final long time = getWifiSupplStateTime(i, rawRealtime, which);
3365            if (time == 0) {
3366                continue;
3367            }
3368            sb.append("\n    ");
3369            didOne = true;
3370            sb.append(WIFI_SUPPL_STATE_NAMES[i]);
3371            sb.append(" ");
3372            formatTimeMs(sb, time/1000);
3373            sb.append("(");
3374            sb.append(formatRatioLocked(time, whichBatteryRealtime));
3375            sb.append(") ");
3376            sb.append(getWifiSupplStateCount(i, which));
3377            sb.append("x");
3378        }
3379        if (!didOne) sb.append(" (no activity)");
3380        pw.println(sb.toString());
3381
3382        sb.setLength(0);
3383        sb.append(prefix);
3384        sb.append("  Wifi signal levels:");
3385        didOne = false;
3386        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
3387            final long time = getWifiSignalStrengthTime(i, rawRealtime, which);
3388            if (time == 0) {
3389                continue;
3390            }
3391            sb.append("\n    ");
3392            sb.append(prefix);
3393            didOne = true;
3394            sb.append("level(");
3395            sb.append(i);
3396            sb.append(") ");
3397            formatTimeMs(sb, time/1000);
3398            sb.append("(");
3399            sb.append(formatRatioLocked(time, whichBatteryRealtime));
3400            sb.append(") ");
3401            sb.append(getWifiSignalStrengthCount(i, which));
3402            sb.append("x");
3403        }
3404        if (!didOne) sb.append(" (no activity)");
3405        pw.println(sb.toString());
3406
3407        final long wifiIdleTimeMs = getWifiControllerActivity(CONTROLLER_IDLE_TIME, which);
3408        final long wifiRxTimeMs = getWifiControllerActivity(CONTROLLER_RX_TIME, which);
3409        final long wifiTxTimeMs = getWifiControllerActivity(CONTROLLER_TX_TIME, which);
3410        final long wifiPowerDrainMaMs = getWifiControllerActivity(CONTROLLER_POWER_DRAIN, which);
3411        final long wifiTotalTimeMs = wifiIdleTimeMs + wifiRxTimeMs + wifiTxTimeMs;
3412
3413        sb.setLength(0);
3414        sb.append(prefix);
3415        sb.append("  WiFi Idle time: "); formatTimeMs(sb, wifiIdleTimeMs);
3416        sb.append("(");
3417        sb.append(formatRatioLocked(wifiIdleTimeMs, wifiTotalTimeMs));
3418        sb.append(")");
3419        pw.println(sb.toString());
3420
3421        sb.setLength(0);
3422        sb.append(prefix);
3423        sb.append("  WiFi Rx time:   "); formatTimeMs(sb, wifiRxTimeMs);
3424        sb.append("(");
3425        sb.append(formatRatioLocked(wifiRxTimeMs, wifiTotalTimeMs));
3426        sb.append(")");
3427        pw.println(sb.toString());
3428
3429        sb.setLength(0);
3430        sb.append(prefix);
3431        sb.append("  WiFi Tx time:   "); formatTimeMs(sb, wifiTxTimeMs);
3432        sb.append("(");
3433        sb.append(formatRatioLocked(wifiTxTimeMs, wifiTotalTimeMs));
3434        sb.append(")");
3435        pw.println(sb.toString());
3436
3437        sb.setLength(0);
3438        sb.append(prefix);
3439        sb.append("  WiFi Power drain: ").append(
3440                BatteryStatsHelper.makemAh(wifiPowerDrainMaMs / (double) (1000*60*60)));
3441        sb.append("mAh");
3442        pw.println(sb.toString());
3443
3444        final long bluetoothIdleTimeMs =
3445                getBluetoothControllerActivity(CONTROLLER_IDLE_TIME, which);
3446        final long bluetoothRxTimeMs = getBluetoothControllerActivity(CONTROLLER_RX_TIME, which);
3447        final long bluetoothTxTimeMs = getBluetoothControllerActivity(CONTROLLER_TX_TIME, which);
3448        final long bluetoothTotalTimeMs = bluetoothIdleTimeMs + bluetoothRxTimeMs +
3449                bluetoothTxTimeMs;
3450
3451        sb.setLength(0);
3452        sb.append(prefix);
3453        sb.append("  Bluetooth Idle time: "); formatTimeMs(sb, bluetoothIdleTimeMs);
3454        sb.append("(");
3455        sb.append(formatRatioLocked(bluetoothIdleTimeMs, bluetoothTotalTimeMs));
3456        sb.append(")");
3457        pw.println(sb.toString());
3458
3459        sb.setLength(0);
3460        sb.append(prefix);
3461        sb.append("  Bluetooth Rx time:   "); formatTimeMs(sb, bluetoothRxTimeMs);
3462        sb.append("(");
3463        sb.append(formatRatioLocked(bluetoothRxTimeMs, bluetoothTotalTimeMs));
3464        sb.append(")");
3465        pw.println(sb.toString());
3466
3467        sb.setLength(0);
3468        sb.append(prefix);
3469        sb.append("  Bluetooth Tx time:   "); formatTimeMs(sb, bluetoothTxTimeMs);
3470        sb.append("(");
3471        sb.append(formatRatioLocked(bluetoothTxTimeMs, bluetoothTotalTimeMs));
3472        sb.append(")");
3473        pw.println(sb.toString());
3474
3475        sb.setLength(0);
3476        sb.append(prefix);
3477        sb.append("  Bluetooth Power drain: ").append(BatteryStatsHelper.makemAh(
3478                getBluetoothControllerActivity(CONTROLLER_POWER_DRAIN, which) /
3479                        (double)(1000*60*60)));
3480        sb.append("mAh");
3481        pw.println(sb.toString());
3482
3483        pw.println();
3484
3485        if (which == STATS_SINCE_UNPLUGGED) {
3486            if (getIsOnBattery()) {
3487                pw.print(prefix); pw.println("  Device is currently unplugged");
3488                pw.print(prefix); pw.print("    Discharge cycle start level: ");
3489                        pw.println(getDischargeStartLevel());
3490                pw.print(prefix); pw.print("    Discharge cycle current level: ");
3491                        pw.println(getDischargeCurrentLevel());
3492            } else {
3493                pw.print(prefix); pw.println("  Device is currently plugged into power");
3494                pw.print(prefix); pw.print("    Last discharge cycle start level: ");
3495                        pw.println(getDischargeStartLevel());
3496                pw.print(prefix); pw.print("    Last discharge cycle end level: ");
3497                        pw.println(getDischargeCurrentLevel());
3498            }
3499            pw.print(prefix); pw.print("    Amount discharged while screen on: ");
3500                    pw.println(getDischargeAmountScreenOn());
3501            pw.print(prefix); pw.print("    Amount discharged while screen off: ");
3502                    pw.println(getDischargeAmountScreenOff());
3503            pw.println(" ");
3504        } else {
3505            pw.print(prefix); pw.println("  Device battery use since last full charge");
3506            pw.print(prefix); pw.print("    Amount discharged (lower bound): ");
3507                    pw.println(getLowDischargeAmountSinceCharge());
3508            pw.print(prefix); pw.print("    Amount discharged (upper bound): ");
3509                    pw.println(getHighDischargeAmountSinceCharge());
3510            pw.print(prefix); pw.print("    Amount discharged while screen on: ");
3511                    pw.println(getDischargeAmountScreenOnSinceCharge());
3512            pw.print(prefix); pw.print("    Amount discharged while screen off: ");
3513                    pw.println(getDischargeAmountScreenOffSinceCharge());
3514            pw.println();
3515        }
3516
3517        final BatteryStatsHelper helper = new BatteryStatsHelper(context, false, wifiOnly);
3518        helper.create(this);
3519        helper.refreshStats(which, UserHandle.USER_ALL);
3520        List<BatterySipper> sippers = helper.getUsageList();
3521        if (sippers != null && sippers.size() > 0) {
3522            pw.print(prefix); pw.println("  Estimated power use (mAh):");
3523            pw.print(prefix); pw.print("    Capacity: ");
3524                    printmAh(pw, helper.getPowerProfile().getBatteryCapacity());
3525                    pw.print(", Computed drain: "); printmAh(pw, helper.getComputedPower());
3526                    pw.print(", actual drain: "); printmAh(pw, helper.getMinDrainedPower());
3527                    if (helper.getMinDrainedPower() != helper.getMaxDrainedPower()) {
3528                        pw.print("-"); printmAh(pw, helper.getMaxDrainedPower());
3529                    }
3530                    pw.println();
3531            for (int i=0; i<sippers.size(); i++) {
3532                final BatterySipper bs = sippers.get(i);
3533                pw.print(prefix);
3534                switch (bs.drainType) {
3535                    case IDLE:
3536                        pw.print("    Idle: ");
3537                        break;
3538                    case CELL:
3539                        pw.print("    Cell standby: ");
3540                        break;
3541                    case PHONE:
3542                        pw.print("    Phone calls: ");
3543                        break;
3544                    case WIFI:
3545                        pw.print("    Wifi: ");
3546                        break;
3547                    case BLUETOOTH:
3548                        pw.print("    Bluetooth: ");
3549                        break;
3550                    case SCREEN:
3551                        pw.print("    Screen: ");
3552                        break;
3553                    case FLASHLIGHT:
3554                        pw.print("    Flashlight: ");
3555                        break;
3556                    case APP:
3557                        pw.print("    Uid ");
3558                        UserHandle.formatUid(pw, bs.uidObj.getUid());
3559                        pw.print(": ");
3560                        break;
3561                    case USER:
3562                        pw.print("    User "); pw.print(bs.userId);
3563                        pw.print(": ");
3564                        break;
3565                    case UNACCOUNTED:
3566                        pw.print("    Unaccounted: ");
3567                        break;
3568                    case OVERCOUNTED:
3569                        pw.print("    Over-counted: ");
3570                        break;
3571                    case CAMERA:
3572                        pw.print("    Camera: ");
3573                        break;
3574                    default:
3575                        pw.print("    ???: ");
3576                        break;
3577                }
3578                printmAh(pw, bs.totalPowerMah);
3579
3580                if (bs.usagePowerMah != bs.totalPowerMah) {
3581                    // If the usage (generic power) isn't the whole amount, we list out
3582                    // what components are involved in the calculation.
3583
3584                    pw.print(" (");
3585                    if (bs.usagePowerMah != 0) {
3586                        pw.print(" usage=");
3587                        printmAh(pw, bs.usagePowerMah);
3588                    }
3589                    if (bs.cpuPowerMah != 0) {
3590                        pw.print(" cpu=");
3591                        printmAh(pw, bs.cpuPowerMah);
3592                    }
3593                    if (bs.wakeLockPowerMah != 0) {
3594                        pw.print(" wake=");
3595                        printmAh(pw, bs.wakeLockPowerMah);
3596                    }
3597                    if (bs.mobileRadioPowerMah != 0) {
3598                        pw.print(" radio=");
3599                        printmAh(pw, bs.mobileRadioPowerMah);
3600                    }
3601                    if (bs.wifiPowerMah != 0) {
3602                        pw.print(" wifi=");
3603                        printmAh(pw, bs.wifiPowerMah);
3604                    }
3605                    if (bs.gpsPowerMah != 0) {
3606                        pw.print(" gps=");
3607                        printmAh(pw, bs.gpsPowerMah);
3608                    }
3609                    if (bs.sensorPowerMah != 0) {
3610                        pw.print(" sensor=");
3611                        printmAh(pw, bs.sensorPowerMah);
3612                    }
3613                    if (bs.cameraPowerMah != 0) {
3614                        pw.print(" camera=");
3615                        printmAh(pw, bs.cameraPowerMah);
3616                    }
3617                    if (bs.flashlightPowerMah != 0) {
3618                        pw.print(" flash=");
3619                        printmAh(pw, bs.flashlightPowerMah);
3620                    }
3621                    pw.print(" )");
3622                }
3623                pw.println();
3624            }
3625            pw.println();
3626        }
3627
3628        sippers = helper.getMobilemsppList();
3629        if (sippers != null && sippers.size() > 0) {
3630            pw.print(prefix); pw.println("  Per-app mobile ms per packet:");
3631            long totalTime = 0;
3632            for (int i=0; i<sippers.size(); i++) {
3633                final BatterySipper bs = sippers.get(i);
3634                sb.setLength(0);
3635                sb.append(prefix); sb.append("    Uid ");
3636                UserHandle.formatUid(sb, bs.uidObj.getUid());
3637                sb.append(": "); sb.append(BatteryStatsHelper.makemAh(bs.mobilemspp));
3638                sb.append(" ("); sb.append(bs.mobileRxPackets+bs.mobileTxPackets);
3639                sb.append(" packets over "); formatTimeMsNoSpace(sb, bs.mobileActive);
3640                sb.append(") "); sb.append(bs.mobileActiveCount); sb.append("x");
3641                pw.println(sb.toString());
3642                totalTime += bs.mobileActive;
3643            }
3644            sb.setLength(0);
3645            sb.append(prefix);
3646            sb.append("    TOTAL TIME: ");
3647            formatTimeMs(sb, totalTime);
3648            sb.append("("); sb.append(formatRatioLocked(totalTime, whichBatteryRealtime));
3649            sb.append(")");
3650            pw.println(sb.toString());
3651            pw.println();
3652        }
3653
3654        final Comparator<TimerEntry> timerComparator = new Comparator<TimerEntry>() {
3655            @Override
3656            public int compare(TimerEntry lhs, TimerEntry rhs) {
3657                long lhsTime = lhs.mTime;
3658                long rhsTime = rhs.mTime;
3659                if (lhsTime < rhsTime) {
3660                    return 1;
3661                }
3662                if (lhsTime > rhsTime) {
3663                    return -1;
3664                }
3665                return 0;
3666            }
3667        };
3668
3669        if (reqUid < 0) {
3670            final Map<String, ? extends BatteryStats.Timer> kernelWakelocks
3671                    = getKernelWakelockStats();
3672            if (kernelWakelocks.size() > 0) {
3673                final ArrayList<TimerEntry> ktimers = new ArrayList<>();
3674                for (Map.Entry<String, ? extends BatteryStats.Timer> ent
3675                        : kernelWakelocks.entrySet()) {
3676                    final BatteryStats.Timer timer = ent.getValue();
3677                    final long totalTimeMillis = computeWakeLock(timer, rawRealtime, which);
3678                    if (totalTimeMillis > 0) {
3679                        ktimers.add(new TimerEntry(ent.getKey(), 0, timer, totalTimeMillis));
3680                    }
3681                }
3682                if (ktimers.size() > 0) {
3683                    Collections.sort(ktimers, timerComparator);
3684                    pw.print(prefix); pw.println("  All kernel wake locks:");
3685                    for (int i=0; i<ktimers.size(); i++) {
3686                        final TimerEntry timer = ktimers.get(i);
3687                        String linePrefix = ": ";
3688                        sb.setLength(0);
3689                        sb.append(prefix);
3690                        sb.append("  Kernel Wake lock ");
3691                        sb.append(timer.mName);
3692                        linePrefix = printWakeLock(sb, timer.mTimer, rawRealtime, null,
3693                                which, linePrefix);
3694                        if (!linePrefix.equals(": ")) {
3695                            sb.append(" realtime");
3696                            // Only print out wake locks that were held
3697                            pw.println(sb.toString());
3698                        }
3699                    }
3700                    pw.println();
3701                }
3702            }
3703
3704            if (timers.size() > 0) {
3705                Collections.sort(timers, timerComparator);
3706                pw.print(prefix); pw.println("  All partial wake locks:");
3707                for (int i=0; i<timers.size(); i++) {
3708                    TimerEntry timer = timers.get(i);
3709                    sb.setLength(0);
3710                    sb.append("  Wake lock ");
3711                    UserHandle.formatUid(sb, timer.mId);
3712                    sb.append(" ");
3713                    sb.append(timer.mName);
3714                    printWakeLock(sb, timer.mTimer, rawRealtime, null, which, ": ");
3715                    sb.append(" realtime");
3716                    pw.println(sb.toString());
3717                }
3718                timers.clear();
3719                pw.println();
3720            }
3721
3722            final Map<String, ? extends Timer> wakeupReasons = getWakeupReasonStats();
3723            if (wakeupReasons.size() > 0) {
3724                pw.print(prefix); pw.println("  All wakeup reasons:");
3725                final ArrayList<TimerEntry> reasons = new ArrayList<>();
3726                for (Map.Entry<String, ? extends Timer> ent : wakeupReasons.entrySet()) {
3727                    final Timer timer = ent.getValue();
3728                    reasons.add(new TimerEntry(ent.getKey(), 0, timer,
3729                            timer.getCountLocked(which)));
3730                }
3731                Collections.sort(reasons, timerComparator);
3732                for (int i=0; i<reasons.size(); i++) {
3733                    TimerEntry timer = reasons.get(i);
3734                    String linePrefix = ": ";
3735                    sb.setLength(0);
3736                    sb.append(prefix);
3737                    sb.append("  Wakeup reason ");
3738                    sb.append(timer.mName);
3739                    printWakeLock(sb, timer.mTimer, rawRealtime, null, which, ": ");
3740                    sb.append(" realtime");
3741                    pw.println(sb.toString());
3742                }
3743                pw.println();
3744            }
3745        }
3746
3747        for (int iu=0; iu<NU; iu++) {
3748            final int uid = uidStats.keyAt(iu);
3749            if (reqUid >= 0 && uid != reqUid && uid != Process.SYSTEM_UID) {
3750                continue;
3751            }
3752
3753            final Uid u = uidStats.valueAt(iu);
3754
3755            pw.print(prefix);
3756            pw.print("  ");
3757            UserHandle.formatUid(pw, uid);
3758            pw.println(":");
3759            boolean uidActivity = false;
3760
3761            final long mobileRxBytes = u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
3762            final long mobileTxBytes = u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
3763            final long wifiRxBytes = u.getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
3764            final long wifiTxBytes = u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
3765            final long mobileRxPackets = u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
3766            final long mobileTxPackets = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
3767            final long uidMobileActiveTime = u.getMobileRadioActiveTime(which);
3768            final int uidMobileActiveCount = u.getMobileRadioActiveCount(which);
3769            final long wifiRxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
3770            final long wifiTxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
3771            final long fullWifiLockOnTime = u.getFullWifiLockTime(rawRealtime, which);
3772            final long wifiScanTime = u.getWifiScanTime(rawRealtime, which);
3773            final int wifiScanCount = u.getWifiScanCount(which);
3774            final long uidWifiRunningTime = u.getWifiRunningTime(rawRealtime, which);
3775
3776            if (mobileRxBytes > 0 || mobileTxBytes > 0
3777                    || mobileRxPackets > 0 || mobileTxPackets > 0) {
3778                pw.print(prefix); pw.print("    Mobile network: ");
3779                        pw.print(formatBytesLocked(mobileRxBytes)); pw.print(" received, ");
3780                        pw.print(formatBytesLocked(mobileTxBytes));
3781                        pw.print(" sent (packets "); pw.print(mobileRxPackets);
3782                        pw.print(" received, "); pw.print(mobileTxPackets); pw.println(" sent)");
3783            }
3784            if (uidMobileActiveTime > 0 || uidMobileActiveCount > 0) {
3785                sb.setLength(0);
3786                sb.append(prefix); sb.append("    Mobile radio active: ");
3787                formatTimeMs(sb, uidMobileActiveTime / 1000);
3788                sb.append("(");
3789                sb.append(formatRatioLocked(uidMobileActiveTime, mobileActiveTime));
3790                sb.append(") "); sb.append(uidMobileActiveCount); sb.append("x");
3791                long packets = mobileRxPackets + mobileTxPackets;
3792                if (packets == 0) {
3793                    packets = 1;
3794                }
3795                sb.append(" @ ");
3796                sb.append(BatteryStatsHelper.makemAh(uidMobileActiveTime / 1000 / (double)packets));
3797                sb.append(" mspp");
3798                pw.println(sb.toString());
3799            }
3800
3801            if (wifiRxBytes > 0 || wifiTxBytes > 0 || wifiRxPackets > 0 || wifiTxPackets > 0) {
3802                pw.print(prefix); pw.print("    Wi-Fi network: ");
3803                        pw.print(formatBytesLocked(wifiRxBytes)); pw.print(" received, ");
3804                        pw.print(formatBytesLocked(wifiTxBytes));
3805                        pw.print(" sent (packets "); pw.print(wifiRxPackets);
3806                        pw.print(" received, "); pw.print(wifiTxPackets); pw.println(" sent)");
3807            }
3808
3809            if (fullWifiLockOnTime != 0 || wifiScanTime != 0 || wifiScanCount != 0
3810                    || uidWifiRunningTime != 0) {
3811                sb.setLength(0);
3812                sb.append(prefix); sb.append("    Wifi Running: ");
3813                        formatTimeMs(sb, uidWifiRunningTime / 1000);
3814                        sb.append("("); sb.append(formatRatioLocked(uidWifiRunningTime,
3815                                whichBatteryRealtime)); sb.append(")\n");
3816                sb.append(prefix); sb.append("    Full Wifi Lock: ");
3817                        formatTimeMs(sb, fullWifiLockOnTime / 1000);
3818                        sb.append("("); sb.append(formatRatioLocked(fullWifiLockOnTime,
3819                                whichBatteryRealtime)); sb.append(")\n");
3820                sb.append(prefix); sb.append("    Wifi Scan: ");
3821                        formatTimeMs(sb, wifiScanTime / 1000);
3822                        sb.append("("); sb.append(formatRatioLocked(wifiScanTime,
3823                                whichBatteryRealtime)); sb.append(") ");
3824                                sb.append(wifiScanCount);
3825                                sb.append("x");
3826                pw.println(sb.toString());
3827            }
3828
3829            final long uidWifiIdleTimeMs = u.getWifiControllerActivity(CONTROLLER_IDLE_TIME, which);
3830            final long uidWifiRxTimeMs = u.getWifiControllerActivity(CONTROLLER_RX_TIME, which);
3831            final long uidWifiTxTimeMs = u.getWifiControllerActivity(CONTROLLER_TX_TIME, which);
3832            final long uidWifiTotalTimeMs = uidWifiIdleTimeMs + uidWifiRxTimeMs + uidWifiTxTimeMs;
3833            if (uidWifiTotalTimeMs > 0) {
3834                sb.setLength(0);
3835                sb.append(prefix).append("    WiFi Idle time: ");
3836                formatTimeMs(sb, uidWifiIdleTimeMs);
3837                sb.append("(").append(formatRatioLocked(uidWifiIdleTimeMs, uidWifiTotalTimeMs))
3838                        .append(")\n");
3839
3840                sb.append(prefix).append("    WiFi Rx time:   "); formatTimeMs(sb, uidWifiRxTimeMs);
3841                sb.append("(").append(formatRatioLocked(uidWifiRxTimeMs, uidWifiTotalTimeMs))
3842                        .append(")\n");
3843
3844                sb.append(prefix).append("    WiFi Tx time:   "); formatTimeMs(sb, uidWifiTxTimeMs);
3845                sb.append("(").append(formatRatioLocked(uidWifiTxTimeMs, uidWifiTotalTimeMs))
3846                        .append(")");
3847                pw.println(sb.toString());
3848            }
3849
3850            if (u.hasUserActivity()) {
3851                boolean hasData = false;
3852                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
3853                    final int val = u.getUserActivityCount(i, which);
3854                    if (val != 0) {
3855                        if (!hasData) {
3856                            sb.setLength(0);
3857                            sb.append("    User activity: ");
3858                            hasData = true;
3859                        } else {
3860                            sb.append(", ");
3861                        }
3862                        sb.append(val);
3863                        sb.append(" ");
3864                        sb.append(Uid.USER_ACTIVITY_TYPES[i]);
3865                    }
3866                }
3867                if (hasData) {
3868                    pw.println(sb.toString());
3869                }
3870            }
3871
3872            final ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> wakelocks
3873                    = u.getWakelockStats();
3874            long totalFullWakelock = 0, totalPartialWakelock = 0, totalWindowWakelock = 0;
3875            long totalDrawWakelock = 0;
3876            int countWakelock = 0;
3877            for (int iw=wakelocks.size()-1; iw>=0; iw--) {
3878                final Uid.Wakelock wl = wakelocks.valueAt(iw);
3879                String linePrefix = ": ";
3880                sb.setLength(0);
3881                sb.append(prefix);
3882                sb.append("    Wake lock ");
3883                sb.append(wakelocks.keyAt(iw));
3884                linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_FULL), rawRealtime,
3885                        "full", which, linePrefix);
3886                linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), rawRealtime,
3887                        "partial", which, linePrefix);
3888                linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), rawRealtime,
3889                        "window", which, linePrefix);
3890                linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_DRAW), rawRealtime,
3891                        "draw", which, linePrefix);
3892                sb.append(" realtime");
3893                pw.println(sb.toString());
3894                uidActivity = true;
3895                countWakelock++;
3896
3897                totalFullWakelock += computeWakeLock(wl.getWakeTime(WAKE_TYPE_FULL),
3898                        rawRealtime, which);
3899                totalPartialWakelock += computeWakeLock(wl.getWakeTime(WAKE_TYPE_PARTIAL),
3900                        rawRealtime, which);
3901                totalWindowWakelock += computeWakeLock(wl.getWakeTime(WAKE_TYPE_WINDOW),
3902                        rawRealtime, which);
3903                totalDrawWakelock += computeWakeLock(wl.getWakeTime(WAKE_TYPE_DRAW),
3904                        rawRealtime, which);
3905            }
3906            if (countWakelock > 1) {
3907                if (totalFullWakelock != 0 || totalPartialWakelock != 0
3908                        || totalWindowWakelock != 0) {
3909                    sb.setLength(0);
3910                    sb.append(prefix);
3911                    sb.append("    TOTAL wake: ");
3912                    boolean needComma = false;
3913                    if (totalFullWakelock != 0) {
3914                        needComma = true;
3915                        formatTimeMs(sb, totalFullWakelock);
3916                        sb.append("full");
3917                    }
3918                    if (totalPartialWakelock != 0) {
3919                        if (needComma) {
3920                            sb.append(", ");
3921                        }
3922                        needComma = true;
3923                        formatTimeMs(sb, totalPartialWakelock);
3924                        sb.append("partial");
3925                    }
3926                    if (totalWindowWakelock != 0) {
3927                        if (needComma) {
3928                            sb.append(", ");
3929                        }
3930                        needComma = true;
3931                        formatTimeMs(sb, totalWindowWakelock);
3932                        sb.append("window");
3933                    }
3934                    if (totalDrawWakelock != 0) {
3935                        if (needComma) {
3936                            sb.append(",");
3937                        }
3938                        needComma = true;
3939                        formatTimeMs(sb, totalDrawWakelock);
3940                        sb.append("draw");
3941                    }
3942                    sb.append(" realtime");
3943                    pw.println(sb.toString());
3944                }
3945            }
3946
3947            final ArrayMap<String, ? extends Timer> syncs = u.getSyncStats();
3948            for (int isy=syncs.size()-1; isy>=0; isy--) {
3949                final Timer timer = syncs.valueAt(isy);
3950                // Convert from microseconds to milliseconds with rounding
3951                final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
3952                final int count = timer.getCountLocked(which);
3953                sb.setLength(0);
3954                sb.append(prefix);
3955                sb.append("    Sync ");
3956                sb.append(syncs.keyAt(isy));
3957                sb.append(": ");
3958                if (totalTime != 0) {
3959                    formatTimeMs(sb, totalTime);
3960                    sb.append("realtime (");
3961                    sb.append(count);
3962                    sb.append(" times)");
3963                } else {
3964                    sb.append("(not used)");
3965                }
3966                pw.println(sb.toString());
3967                uidActivity = true;
3968            }
3969
3970            final ArrayMap<String, ? extends Timer> jobs = u.getJobStats();
3971            for (int ij=jobs.size()-1; ij>=0; ij--) {
3972                final Timer timer = jobs.valueAt(ij);
3973                // Convert from microseconds to milliseconds with rounding
3974                final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
3975                final int count = timer.getCountLocked(which);
3976                sb.setLength(0);
3977                sb.append(prefix);
3978                sb.append("    Job ");
3979                sb.append(jobs.keyAt(ij));
3980                sb.append(": ");
3981                if (totalTime != 0) {
3982                    formatTimeMs(sb, totalTime);
3983                    sb.append("realtime (");
3984                    sb.append(count);
3985                    sb.append(" times)");
3986                } else {
3987                    sb.append("(not used)");
3988                }
3989                pw.println(sb.toString());
3990                uidActivity = true;
3991            }
3992
3993            uidActivity |= printTimer(pw, sb, u.getFlashlightTurnedOnTimer(), rawRealtime, which,
3994                    prefix, "Flashlight");
3995            uidActivity |= printTimer(pw, sb, u.getCameraTurnedOnTimer(), rawRealtime, which,
3996                    prefix, "Camera");
3997            uidActivity |= printTimer(pw, sb, u.getVideoTurnedOnTimer(), rawRealtime, which,
3998                    prefix, "Video");
3999            uidActivity |= printTimer(pw, sb, u.getAudioTurnedOnTimer(), rawRealtime, which,
4000                    prefix, "Audio");
4001
4002            final SparseArray<? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
4003            final int NSE = sensors.size();
4004            for (int ise=0; ise<NSE; ise++) {
4005                final Uid.Sensor se = sensors.valueAt(ise);
4006                final int sensorNumber = sensors.keyAt(ise);
4007                sb.setLength(0);
4008                sb.append(prefix);
4009                sb.append("    Sensor ");
4010                int handle = se.getHandle();
4011                if (handle == Uid.Sensor.GPS) {
4012                    sb.append("GPS");
4013                } else {
4014                    sb.append(handle);
4015                }
4016                sb.append(": ");
4017
4018                final Timer timer = se.getSensorTime();
4019                if (timer != null) {
4020                    // Convert from microseconds to milliseconds with rounding
4021                    final long totalTime = (timer.getTotalTimeLocked(
4022                            rawRealtime, which) + 500) / 1000;
4023                    final int count = timer.getCountLocked(which);
4024                    //timer.logState();
4025                    if (totalTime != 0) {
4026                        formatTimeMs(sb, totalTime);
4027                        sb.append("realtime (");
4028                        sb.append(count);
4029                        sb.append(" times)");
4030                    } else {
4031                        sb.append("(not used)");
4032                    }
4033                } else {
4034                    sb.append("(not used)");
4035                }
4036
4037                pw.println(sb.toString());
4038                uidActivity = true;
4039            }
4040
4041            uidActivity |= printTimer(pw, sb, u.getVibratorOnTimer(), rawRealtime, which, prefix,
4042                    "Vibrator");
4043            uidActivity |= printTimer(pw, sb, u.getForegroundActivityTimer(), rawRealtime, which,
4044                    prefix, "Foreground activities");
4045
4046            long totalStateTime = 0;
4047            for (int ips=0; ips<Uid.NUM_PROCESS_STATE; ips++) {
4048                long time = u.getProcessStateTime(ips, rawRealtime, which);
4049                if (time > 0) {
4050                    totalStateTime += time;
4051                    sb.setLength(0);
4052                    sb.append(prefix);
4053                    sb.append("    ");
4054                    sb.append(Uid.PROCESS_STATE_NAMES[ips]);
4055                    sb.append(" for: ");
4056                    formatTimeMs(sb, (totalStateTime + 500) / 1000);
4057                    pw.println(sb.toString());
4058                    uidActivity = true;
4059                }
4060            }
4061
4062            final long userCpuTimeUs = u.getUserCpuTimeUs(which);
4063            final long systemCpuTimeUs = u.getSystemCpuTimeUs(which);
4064            final long powerCpuMaUs = u.getCpuPowerMaUs(which);
4065            if (userCpuTimeUs > 0 || systemCpuTimeUs > 0 || powerCpuMaUs > 0) {
4066                sb.setLength(0);
4067                sb.append(prefix);
4068                sb.append("    Total cpu time: u=");
4069                formatTimeMs(sb, userCpuTimeUs / 1000);
4070                sb.append("s=");
4071                formatTimeMs(sb, systemCpuTimeUs / 1000);
4072                sb.append("p=");
4073                printmAh(sb, powerCpuMaUs / (1000.0 * 1000.0 * 60.0 * 60.0));
4074                sb.append("mAh");
4075                pw.println(sb.toString());
4076            }
4077
4078            final ArrayMap<String, ? extends BatteryStats.Uid.Proc> processStats
4079                    = u.getProcessStats();
4080            for (int ipr=processStats.size()-1; ipr>=0; ipr--) {
4081                final Uid.Proc ps = processStats.valueAt(ipr);
4082                long userTime;
4083                long systemTime;
4084                long foregroundTime;
4085                int starts;
4086                int numExcessive;
4087
4088                userTime = ps.getUserTime(which);
4089                systemTime = ps.getSystemTime(which);
4090                foregroundTime = ps.getForegroundTime(which);
4091                starts = ps.getStarts(which);
4092                final int numCrashes = ps.getNumCrashes(which);
4093                final int numAnrs = ps.getNumAnrs(which);
4094                numExcessive = which == STATS_SINCE_CHARGED
4095                        ? ps.countExcessivePowers() : 0;
4096
4097                if (userTime != 0 || systemTime != 0 || foregroundTime != 0 || starts != 0
4098                        || numExcessive != 0 || numCrashes != 0 || numAnrs != 0) {
4099                    sb.setLength(0);
4100                    sb.append(prefix); sb.append("    Proc ");
4101                            sb.append(processStats.keyAt(ipr)); sb.append(":\n");
4102                    sb.append(prefix); sb.append("      CPU: ");
4103                            formatTimeMs(sb, userTime); sb.append("usr + ");
4104                            formatTimeMs(sb, systemTime); sb.append("krn ; ");
4105                            formatTimeMs(sb, foregroundTime); sb.append("fg");
4106                    if (starts != 0 || numCrashes != 0 || numAnrs != 0) {
4107                        sb.append("\n"); sb.append(prefix); sb.append("      ");
4108                        boolean hasOne = false;
4109                        if (starts != 0) {
4110                            hasOne = true;
4111                            sb.append(starts); sb.append(" starts");
4112                        }
4113                        if (numCrashes != 0) {
4114                            if (hasOne) {
4115                                sb.append(", ");
4116                            }
4117                            hasOne = true;
4118                            sb.append(numCrashes); sb.append(" crashes");
4119                        }
4120                        if (numAnrs != 0) {
4121                            if (hasOne) {
4122                                sb.append(", ");
4123                            }
4124                            sb.append(numAnrs); sb.append(" anrs");
4125                        }
4126                    }
4127                    pw.println(sb.toString());
4128                    for (int e=0; e<numExcessive; e++) {
4129                        Uid.Proc.ExcessivePower ew = ps.getExcessivePower(e);
4130                        if (ew != null) {
4131                            pw.print(prefix); pw.print("      * Killed for ");
4132                                    if (ew.type == Uid.Proc.ExcessivePower.TYPE_WAKE) {
4133                                        pw.print("wake lock");
4134                                    } else if (ew.type == Uid.Proc.ExcessivePower.TYPE_CPU) {
4135                                        pw.print("cpu");
4136                                    } else {
4137                                        pw.print("unknown");
4138                                    }
4139                                    pw.print(" use: ");
4140                                    TimeUtils.formatDuration(ew.usedTime, pw);
4141                                    pw.print(" over ");
4142                                    TimeUtils.formatDuration(ew.overTime, pw);
4143                                    if (ew.overTime != 0) {
4144                                        pw.print(" (");
4145                                        pw.print((ew.usedTime*100)/ew.overTime);
4146                                        pw.println("%)");
4147                                    }
4148                        }
4149                    }
4150                    uidActivity = true;
4151                }
4152            }
4153
4154            final ArrayMap<String, ? extends BatteryStats.Uid.Pkg> packageStats
4155                    = u.getPackageStats();
4156            for (int ipkg=packageStats.size()-1; ipkg>=0; ipkg--) {
4157                pw.print(prefix); pw.print("    Apk "); pw.print(packageStats.keyAt(ipkg));
4158                pw.println(":");
4159                boolean apkActivity = false;
4160                final Uid.Pkg ps = packageStats.valueAt(ipkg);
4161                final ArrayMap<String, ? extends Counter> alarms = ps.getWakeupAlarmStats();
4162                for (int iwa=alarms.size()-1; iwa>=0; iwa--) {
4163                    pw.print(prefix); pw.print("      Wakeup alarm ");
4164                            pw.print(alarms.keyAt(iwa)); pw.print(": ");
4165                            pw.print(alarms.valueAt(iwa).getCountLocked(which));
4166                            pw.println(" times");
4167                    apkActivity = true;
4168                }
4169                final ArrayMap<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
4170                for (int isvc=serviceStats.size()-1; isvc>=0; isvc--) {
4171                    final BatteryStats.Uid.Pkg.Serv ss = serviceStats.valueAt(isvc);
4172                    final long startTime = ss.getStartTime(batteryUptime, which);
4173                    final int starts = ss.getStarts(which);
4174                    final int launches = ss.getLaunches(which);
4175                    if (startTime != 0 || starts != 0 || launches != 0) {
4176                        sb.setLength(0);
4177                        sb.append(prefix); sb.append("      Service ");
4178                                sb.append(serviceStats.keyAt(isvc)); sb.append(":\n");
4179                        sb.append(prefix); sb.append("        Created for: ");
4180                                formatTimeMs(sb, startTime / 1000);
4181                                sb.append("uptime\n");
4182                        sb.append(prefix); sb.append("        Starts: ");
4183                                sb.append(starts);
4184                                sb.append(", launches: "); sb.append(launches);
4185                        pw.println(sb.toString());
4186                        apkActivity = true;
4187                    }
4188                }
4189                if (!apkActivity) {
4190                    pw.print(prefix); pw.println("      (nothing executed)");
4191                }
4192                uidActivity = true;
4193            }
4194            if (!uidActivity) {
4195                pw.print(prefix); pw.println("    (nothing executed)");
4196            }
4197        }
4198    }
4199
4200    static void printBitDescriptions(PrintWriter pw, int oldval, int newval, HistoryTag wakelockTag,
4201            BitDescription[] descriptions, boolean longNames) {
4202        int diff = oldval ^ newval;
4203        if (diff == 0) return;
4204        boolean didWake = false;
4205        for (int i=0; i<descriptions.length; i++) {
4206            BitDescription bd = descriptions[i];
4207            if ((diff&bd.mask) != 0) {
4208                pw.print(longNames ? " " : ",");
4209                if (bd.shift < 0) {
4210                    pw.print((newval&bd.mask) != 0 ? "+" : "-");
4211                    pw.print(longNames ? bd.name : bd.shortName);
4212                    if (bd.mask == HistoryItem.STATE_WAKE_LOCK_FLAG && wakelockTag != null) {
4213                        didWake = true;
4214                        pw.print("=");
4215                        if (longNames) {
4216                            UserHandle.formatUid(pw, wakelockTag.uid);
4217                            pw.print(":\"");
4218                            pw.print(wakelockTag.string);
4219                            pw.print("\"");
4220                        } else {
4221                            pw.print(wakelockTag.poolIdx);
4222                        }
4223                    }
4224                } else {
4225                    pw.print(longNames ? bd.name : bd.shortName);
4226                    pw.print("=");
4227                    int val = (newval&bd.mask)>>bd.shift;
4228                    if (bd.values != null && val >= 0 && val < bd.values.length) {
4229                        pw.print(longNames? bd.values[val] : bd.shortValues[val]);
4230                    } else {
4231                        pw.print(val);
4232                    }
4233                }
4234            }
4235        }
4236        if (!didWake && wakelockTag != null) {
4237            pw.print(longNames ? " wake_lock=" : ",w=");
4238            if (longNames) {
4239                UserHandle.formatUid(pw, wakelockTag.uid);
4240                pw.print(":\"");
4241                pw.print(wakelockTag.string);
4242                pw.print("\"");
4243            } else {
4244                pw.print(wakelockTag.poolIdx);
4245            }
4246        }
4247    }
4248
4249    public void prepareForDumpLocked() {
4250    }
4251
4252    public static class HistoryPrinter {
4253        int oldState = 0;
4254        int oldState2 = 0;
4255        int oldLevel = -1;
4256        int oldStatus = -1;
4257        int oldHealth = -1;
4258        int oldPlug = -1;
4259        int oldTemp = -1;
4260        int oldVolt = -1;
4261        long lastTime = -1;
4262
4263        void reset() {
4264            oldState = oldState2 = 0;
4265            oldLevel = -1;
4266            oldStatus = -1;
4267            oldHealth = -1;
4268            oldPlug = -1;
4269            oldTemp = -1;
4270            oldVolt = -1;
4271        }
4272
4273        public void printNextItem(PrintWriter pw, HistoryItem rec, long baseTime, boolean checkin,
4274                boolean verbose) {
4275            if (!checkin) {
4276                pw.print("  ");
4277                TimeUtils.formatDuration(rec.time - baseTime, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
4278                pw.print(" (");
4279                pw.print(rec.numReadInts);
4280                pw.print(") ");
4281            } else {
4282                pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
4283                pw.print(HISTORY_DATA); pw.print(',');
4284                if (lastTime < 0) {
4285                    pw.print(rec.time - baseTime);
4286                } else {
4287                    pw.print(rec.time - lastTime);
4288                }
4289                lastTime = rec.time;
4290            }
4291            if (rec.cmd == HistoryItem.CMD_START) {
4292                if (checkin) {
4293                    pw.print(":");
4294                }
4295                pw.println("START");
4296                reset();
4297            } else if (rec.cmd == HistoryItem.CMD_CURRENT_TIME
4298                    || rec.cmd == HistoryItem.CMD_RESET) {
4299                if (checkin) {
4300                    pw.print(":");
4301                }
4302                if (rec.cmd == HistoryItem.CMD_RESET) {
4303                    pw.print("RESET:");
4304                    reset();
4305                }
4306                pw.print("TIME:");
4307                if (checkin) {
4308                    pw.println(rec.currentTime);
4309                } else {
4310                    pw.print(" ");
4311                    pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss",
4312                            rec.currentTime).toString());
4313                }
4314            } else if (rec.cmd == HistoryItem.CMD_SHUTDOWN) {
4315                if (checkin) {
4316                    pw.print(":");
4317                }
4318                pw.println("SHUTDOWN");
4319            } else if (rec.cmd == HistoryItem.CMD_OVERFLOW) {
4320                if (checkin) {
4321                    pw.print(":");
4322                }
4323                pw.println("*OVERFLOW*");
4324            } else {
4325                if (!checkin) {
4326                    if (rec.batteryLevel < 10) pw.print("00");
4327                    else if (rec.batteryLevel < 100) pw.print("0");
4328                    pw.print(rec.batteryLevel);
4329                    if (verbose) {
4330                        pw.print(" ");
4331                        if (rec.states < 0) ;
4332                        else if (rec.states < 0x10) pw.print("0000000");
4333                        else if (rec.states < 0x100) pw.print("000000");
4334                        else if (rec.states < 0x1000) pw.print("00000");
4335                        else if (rec.states < 0x10000) pw.print("0000");
4336                        else if (rec.states < 0x100000) pw.print("000");
4337                        else if (rec.states < 0x1000000) pw.print("00");
4338                        else if (rec.states < 0x10000000) pw.print("0");
4339                        pw.print(Integer.toHexString(rec.states));
4340                    }
4341                } else {
4342                    if (oldLevel != rec.batteryLevel) {
4343                        oldLevel = rec.batteryLevel;
4344                        pw.print(",Bl="); pw.print(rec.batteryLevel);
4345                    }
4346                }
4347                if (oldStatus != rec.batteryStatus) {
4348                    oldStatus = rec.batteryStatus;
4349                    pw.print(checkin ? ",Bs=" : " status=");
4350                    switch (oldStatus) {
4351                        case BatteryManager.BATTERY_STATUS_UNKNOWN:
4352                            pw.print(checkin ? "?" : "unknown");
4353                            break;
4354                        case BatteryManager.BATTERY_STATUS_CHARGING:
4355                            pw.print(checkin ? "c" : "charging");
4356                            break;
4357                        case BatteryManager.BATTERY_STATUS_DISCHARGING:
4358                            pw.print(checkin ? "d" : "discharging");
4359                            break;
4360                        case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
4361                            pw.print(checkin ? "n" : "not-charging");
4362                            break;
4363                        case BatteryManager.BATTERY_STATUS_FULL:
4364                            pw.print(checkin ? "f" : "full");
4365                            break;
4366                        default:
4367                            pw.print(oldStatus);
4368                            break;
4369                    }
4370                }
4371                if (oldHealth != rec.batteryHealth) {
4372                    oldHealth = rec.batteryHealth;
4373                    pw.print(checkin ? ",Bh=" : " health=");
4374                    switch (oldHealth) {
4375                        case BatteryManager.BATTERY_HEALTH_UNKNOWN:
4376                            pw.print(checkin ? "?" : "unknown");
4377                            break;
4378                        case BatteryManager.BATTERY_HEALTH_GOOD:
4379                            pw.print(checkin ? "g" : "good");
4380                            break;
4381                        case BatteryManager.BATTERY_HEALTH_OVERHEAT:
4382                            pw.print(checkin ? "h" : "overheat");
4383                            break;
4384                        case BatteryManager.BATTERY_HEALTH_DEAD:
4385                            pw.print(checkin ? "d" : "dead");
4386                            break;
4387                        case BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE:
4388                            pw.print(checkin ? "v" : "over-voltage");
4389                            break;
4390                        case BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE:
4391                            pw.print(checkin ? "f" : "failure");
4392                            break;
4393                        case BatteryManager.BATTERY_HEALTH_COLD:
4394                            pw.print(checkin ? "c" : "cold");
4395                            break;
4396                        default:
4397                            pw.print(oldHealth);
4398                            break;
4399                    }
4400                }
4401                if (oldPlug != rec.batteryPlugType) {
4402                    oldPlug = rec.batteryPlugType;
4403                    pw.print(checkin ? ",Bp=" : " plug=");
4404                    switch (oldPlug) {
4405                        case 0:
4406                            pw.print(checkin ? "n" : "none");
4407                            break;
4408                        case BatteryManager.BATTERY_PLUGGED_AC:
4409                            pw.print(checkin ? "a" : "ac");
4410                            break;
4411                        case BatteryManager.BATTERY_PLUGGED_USB:
4412                            pw.print(checkin ? "u" : "usb");
4413                            break;
4414                        case BatteryManager.BATTERY_PLUGGED_WIRELESS:
4415                            pw.print(checkin ? "w" : "wireless");
4416                            break;
4417                        default:
4418                            pw.print(oldPlug);
4419                            break;
4420                    }
4421                }
4422                if (oldTemp != rec.batteryTemperature) {
4423                    oldTemp = rec.batteryTemperature;
4424                    pw.print(checkin ? ",Bt=" : " temp=");
4425                    pw.print(oldTemp);
4426                }
4427                if (oldVolt != rec.batteryVoltage) {
4428                    oldVolt = rec.batteryVoltage;
4429                    pw.print(checkin ? ",Bv=" : " volt=");
4430                    pw.print(oldVolt);
4431                }
4432                printBitDescriptions(pw, oldState, rec.states, rec.wakelockTag,
4433                        HISTORY_STATE_DESCRIPTIONS, !checkin);
4434                printBitDescriptions(pw, oldState2, rec.states2, null,
4435                        HISTORY_STATE2_DESCRIPTIONS, !checkin);
4436                if (rec.wakeReasonTag != null) {
4437                    if (checkin) {
4438                        pw.print(",wr=");
4439                        pw.print(rec.wakeReasonTag.poolIdx);
4440                    } else {
4441                        pw.print(" wake_reason=");
4442                        pw.print(rec.wakeReasonTag.uid);
4443                        pw.print(":\"");
4444                        pw.print(rec.wakeReasonTag.string);
4445                        pw.print("\"");
4446                    }
4447                }
4448                if (rec.eventCode != HistoryItem.EVENT_NONE) {
4449                    pw.print(checkin ? "," : " ");
4450                    if ((rec.eventCode&HistoryItem.EVENT_FLAG_START) != 0) {
4451                        pw.print("+");
4452                    } else if ((rec.eventCode&HistoryItem.EVENT_FLAG_FINISH) != 0) {
4453                        pw.print("-");
4454                    }
4455                    String[] eventNames = checkin ? HISTORY_EVENT_CHECKIN_NAMES
4456                            : HISTORY_EVENT_NAMES;
4457                    int idx = rec.eventCode & ~(HistoryItem.EVENT_FLAG_START
4458                            | HistoryItem.EVENT_FLAG_FINISH);
4459                    if (idx >= 0 && idx < eventNames.length) {
4460                        pw.print(eventNames[idx]);
4461                    } else {
4462                        pw.print(checkin ? "Ev" : "event");
4463                        pw.print(idx);
4464                    }
4465                    pw.print("=");
4466                    if (checkin) {
4467                        pw.print(rec.eventTag.poolIdx);
4468                    } else {
4469                        UserHandle.formatUid(pw, rec.eventTag.uid);
4470                        pw.print(":\"");
4471                        pw.print(rec.eventTag.string);
4472                        pw.print("\"");
4473                    }
4474                }
4475                pw.println();
4476                if (rec.stepDetails != null) {
4477                    if (!checkin) {
4478                        pw.print("                 Details: cpu=");
4479                        pw.print(rec.stepDetails.userTime);
4480                        pw.print("u+");
4481                        pw.print(rec.stepDetails.systemTime);
4482                        pw.print("s");
4483                        if (rec.stepDetails.appCpuUid1 >= 0) {
4484                            pw.print(" (");
4485                            printStepCpuUidDetails(pw, rec.stepDetails.appCpuUid1,
4486                                    rec.stepDetails.appCpuUTime1, rec.stepDetails.appCpuSTime1);
4487                            if (rec.stepDetails.appCpuUid2 >= 0) {
4488                                pw.print(", ");
4489                                printStepCpuUidDetails(pw, rec.stepDetails.appCpuUid2,
4490                                        rec.stepDetails.appCpuUTime2, rec.stepDetails.appCpuSTime2);
4491                            }
4492                            if (rec.stepDetails.appCpuUid3 >= 0) {
4493                                pw.print(", ");
4494                                printStepCpuUidDetails(pw, rec.stepDetails.appCpuUid3,
4495                                        rec.stepDetails.appCpuUTime3, rec.stepDetails.appCpuSTime3);
4496                            }
4497                            pw.print(')');
4498                        }
4499                        pw.println();
4500                        pw.print("                          /proc/stat=");
4501                        pw.print(rec.stepDetails.statUserTime);
4502                        pw.print(" usr, ");
4503                        pw.print(rec.stepDetails.statSystemTime);
4504                        pw.print(" sys, ");
4505                        pw.print(rec.stepDetails.statIOWaitTime);
4506                        pw.print(" io, ");
4507                        pw.print(rec.stepDetails.statIrqTime);
4508                        pw.print(" irq, ");
4509                        pw.print(rec.stepDetails.statSoftIrqTime);
4510                        pw.print(" sirq, ");
4511                        pw.print(rec.stepDetails.statIdlTime);
4512                        pw.print(" idle");
4513                        int totalRun = rec.stepDetails.statUserTime + rec.stepDetails.statSystemTime
4514                                + rec.stepDetails.statIOWaitTime + rec.stepDetails.statIrqTime
4515                                + rec.stepDetails.statSoftIrqTime;
4516                        int total = totalRun + rec.stepDetails.statIdlTime;
4517                        if (total > 0) {
4518                            pw.print(" (");
4519                            float perc = ((float)totalRun) / ((float)total) * 100;
4520                            pw.print(String.format("%.1f%%", perc));
4521                            pw.print(" of ");
4522                            StringBuilder sb = new StringBuilder(64);
4523                            formatTimeMsNoSpace(sb, total*10);
4524                            pw.print(sb);
4525                            pw.print(")");
4526                        }
4527                        pw.println();
4528                    } else {
4529                        pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
4530                        pw.print(HISTORY_DATA); pw.print(",0,Dcpu=");
4531                        pw.print(rec.stepDetails.userTime);
4532                        pw.print(":");
4533                        pw.print(rec.stepDetails.systemTime);
4534                        if (rec.stepDetails.appCpuUid1 >= 0) {
4535                            printStepCpuUidCheckinDetails(pw, rec.stepDetails.appCpuUid1,
4536                                    rec.stepDetails.appCpuUTime1, rec.stepDetails.appCpuSTime1);
4537                            if (rec.stepDetails.appCpuUid2 >= 0) {
4538                                printStepCpuUidCheckinDetails(pw, rec.stepDetails.appCpuUid2,
4539                                        rec.stepDetails.appCpuUTime2, rec.stepDetails.appCpuSTime2);
4540                            }
4541                            if (rec.stepDetails.appCpuUid3 >= 0) {
4542                                printStepCpuUidCheckinDetails(pw, rec.stepDetails.appCpuUid3,
4543                                        rec.stepDetails.appCpuUTime3, rec.stepDetails.appCpuSTime3);
4544                            }
4545                        }
4546                        pw.println();
4547                        pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
4548                        pw.print(HISTORY_DATA); pw.print(",0,Dpst=");
4549                        pw.print(rec.stepDetails.statUserTime);
4550                        pw.print(',');
4551                        pw.print(rec.stepDetails.statSystemTime);
4552                        pw.print(',');
4553                        pw.print(rec.stepDetails.statIOWaitTime);
4554                        pw.print(',');
4555                        pw.print(rec.stepDetails.statIrqTime);
4556                        pw.print(',');
4557                        pw.print(rec.stepDetails.statSoftIrqTime);
4558                        pw.print(',');
4559                        pw.print(rec.stepDetails.statIdlTime);
4560                        pw.println();
4561                    }
4562                }
4563                oldState = rec.states;
4564                oldState2 = rec.states2;
4565            }
4566        }
4567
4568        private void printStepCpuUidDetails(PrintWriter pw, int uid, int utime, int stime) {
4569            UserHandle.formatUid(pw, uid);
4570            pw.print("=");
4571            pw.print(utime);
4572            pw.print("u+");
4573            pw.print(stime);
4574            pw.print("s");
4575        }
4576
4577        private void printStepCpuUidCheckinDetails(PrintWriter pw, int uid, int utime, int stime) {
4578            pw.print('/');
4579            pw.print(uid);
4580            pw.print(":");
4581            pw.print(utime);
4582            pw.print(":");
4583            pw.print(stime);
4584        }
4585    }
4586
4587    private void printSizeValue(PrintWriter pw, long size) {
4588        float result = size;
4589        String suffix = "";
4590        if (result >= 10*1024) {
4591            suffix = "KB";
4592            result = result / 1024;
4593        }
4594        if (result >= 10*1024) {
4595            suffix = "MB";
4596            result = result / 1024;
4597        }
4598        if (result >= 10*1024) {
4599            suffix = "GB";
4600            result = result / 1024;
4601        }
4602        if (result >= 10*1024) {
4603            suffix = "TB";
4604            result = result / 1024;
4605        }
4606        if (result >= 10*1024) {
4607            suffix = "PB";
4608            result = result / 1024;
4609        }
4610        pw.print((int)result);
4611        pw.print(suffix);
4612    }
4613
4614    private static boolean dumpTimeEstimate(PrintWriter pw, String label1, String label2,
4615            String label3, long estimatedTime) {
4616        if (estimatedTime < 0) {
4617            return false;
4618        }
4619        pw.print(label1);
4620        pw.print(label2);
4621        pw.print(label3);
4622        StringBuilder sb = new StringBuilder(64);
4623        formatTimeMs(sb, estimatedTime);
4624        pw.print(sb);
4625        pw.println();
4626        return true;
4627    }
4628
4629    private static boolean dumpDurationSteps(PrintWriter pw, String prefix, String header,
4630            LevelStepTracker steps, boolean checkin) {
4631        if (steps == null) {
4632            return false;
4633        }
4634        int count = steps.mNumStepDurations;
4635        if (count <= 0) {
4636            return false;
4637        }
4638        if (!checkin) {
4639            pw.println(header);
4640        }
4641        String[] lineArgs = new String[5];
4642        for (int i=0; i<count; i++) {
4643            long duration = steps.getDurationAt(i);
4644            int level = steps.getLevelAt(i);
4645            long initMode = steps.getInitModeAt(i);
4646            long modMode = steps.getModModeAt(i);
4647            if (checkin) {
4648                lineArgs[0] = Long.toString(duration);
4649                lineArgs[1] = Integer.toString(level);
4650                if ((modMode&STEP_LEVEL_MODE_SCREEN_STATE) == 0) {
4651                    switch ((int)(initMode&STEP_LEVEL_MODE_SCREEN_STATE) + 1) {
4652                        case Display.STATE_OFF: lineArgs[2] = "s-"; break;
4653                        case Display.STATE_ON: lineArgs[2] = "s+"; break;
4654                        case Display.STATE_DOZE: lineArgs[2] = "sd"; break;
4655                        case Display.STATE_DOZE_SUSPEND: lineArgs[2] = "sds"; break;
4656                        default: lineArgs[2] = "?"; break;
4657                    }
4658                } else {
4659                    lineArgs[2] = "";
4660                }
4661                if ((modMode&STEP_LEVEL_MODE_POWER_SAVE) == 0) {
4662                    lineArgs[3] = (initMode&STEP_LEVEL_MODE_POWER_SAVE) != 0 ? "p+" : "p-";
4663                } else {
4664                    lineArgs[3] = "";
4665                }
4666                if ((modMode&STEP_LEVEL_MODE_DEVICE_IDLE) == 0) {
4667                    lineArgs[4] = (initMode&STEP_LEVEL_MODE_DEVICE_IDLE) != 0 ? "i+" : "i-";
4668                } else {
4669                    lineArgs[4] = "";
4670                }
4671                dumpLine(pw, 0 /* uid */, "i" /* category */, header, (Object[])lineArgs);
4672            } else {
4673                pw.print(prefix);
4674                pw.print("#"); pw.print(i); pw.print(": ");
4675                TimeUtils.formatDuration(duration, pw);
4676                pw.print(" to "); pw.print(level);
4677                boolean haveModes = false;
4678                if ((modMode&STEP_LEVEL_MODE_SCREEN_STATE) == 0) {
4679                    pw.print(" (");
4680                    switch ((int)(initMode&STEP_LEVEL_MODE_SCREEN_STATE) + 1) {
4681                        case Display.STATE_OFF: pw.print("screen-off"); break;
4682                        case Display.STATE_ON: pw.print("screen-on"); break;
4683                        case Display.STATE_DOZE: pw.print("screen-doze"); break;
4684                        case Display.STATE_DOZE_SUSPEND: pw.print("screen-doze-suspend"); break;
4685                        default: pw.print("screen-?"); break;
4686                    }
4687                    haveModes = true;
4688                }
4689                if ((modMode&STEP_LEVEL_MODE_POWER_SAVE) == 0) {
4690                    pw.print(haveModes ? ", " : " (");
4691                    pw.print((initMode&STEP_LEVEL_MODE_POWER_SAVE) != 0
4692                            ? "power-save-on" : "power-save-off");
4693                    haveModes = true;
4694                }
4695                if ((modMode&STEP_LEVEL_MODE_DEVICE_IDLE) == 0) {
4696                    pw.print(haveModes ? ", " : " (");
4697                    pw.print((initMode&STEP_LEVEL_MODE_DEVICE_IDLE) != 0
4698                            ? "device-idle-on" : "device-idle-off");
4699                    haveModes = true;
4700                }
4701                if (haveModes) {
4702                    pw.print(")");
4703                }
4704                pw.println();
4705            }
4706        }
4707        return true;
4708    }
4709
4710    public static final int DUMP_CHARGED_ONLY = 1<<1;
4711    public static final int DUMP_DAILY_ONLY = 1<<2;
4712    public static final int DUMP_HISTORY_ONLY = 1<<3;
4713    public static final int DUMP_INCLUDE_HISTORY = 1<<4;
4714    public static final int DUMP_VERBOSE = 1<<5;
4715    public static final int DUMP_DEVICE_WIFI_ONLY = 1<<6;
4716
4717    private void dumpHistoryLocked(PrintWriter pw, int flags, long histStart, boolean checkin) {
4718        final HistoryPrinter hprinter = new HistoryPrinter();
4719        final HistoryItem rec = new HistoryItem();
4720        long lastTime = -1;
4721        long baseTime = -1;
4722        boolean printed = false;
4723        HistoryEventTracker tracker = null;
4724        while (getNextHistoryLocked(rec)) {
4725            lastTime = rec.time;
4726            if (baseTime < 0) {
4727                baseTime = lastTime;
4728            }
4729            if (rec.time >= histStart) {
4730                if (histStart >= 0 && !printed) {
4731                    if (rec.cmd == HistoryItem.CMD_CURRENT_TIME
4732                            || rec.cmd == HistoryItem.CMD_RESET
4733                            || rec.cmd == HistoryItem.CMD_START
4734                            || rec.cmd == HistoryItem.CMD_SHUTDOWN) {
4735                        printed = true;
4736                        hprinter.printNextItem(pw, rec, baseTime, checkin,
4737                                (flags&DUMP_VERBOSE) != 0);
4738                        rec.cmd = HistoryItem.CMD_UPDATE;
4739                    } else if (rec.currentTime != 0) {
4740                        printed = true;
4741                        byte cmd = rec.cmd;
4742                        rec.cmd = HistoryItem.CMD_CURRENT_TIME;
4743                        hprinter.printNextItem(pw, rec, baseTime, checkin,
4744                                (flags&DUMP_VERBOSE) != 0);
4745                        rec.cmd = cmd;
4746                    }
4747                    if (tracker != null) {
4748                        if (rec.cmd != HistoryItem.CMD_UPDATE) {
4749                            hprinter.printNextItem(pw, rec, baseTime, checkin,
4750                                    (flags&DUMP_VERBOSE) != 0);
4751                            rec.cmd = HistoryItem.CMD_UPDATE;
4752                        }
4753                        int oldEventCode = rec.eventCode;
4754                        HistoryTag oldEventTag = rec.eventTag;
4755                        rec.eventTag = new HistoryTag();
4756                        for (int i=0; i<HistoryItem.EVENT_COUNT; i++) {
4757                            HashMap<String, SparseIntArray> active
4758                                    = tracker.getStateForEvent(i);
4759                            if (active == null) {
4760                                continue;
4761                            }
4762                            for (HashMap.Entry<String, SparseIntArray> ent
4763                                    : active.entrySet()) {
4764                                SparseIntArray uids = ent.getValue();
4765                                for (int j=0; j<uids.size(); j++) {
4766                                    rec.eventCode = i;
4767                                    rec.eventTag.string = ent.getKey();
4768                                    rec.eventTag.uid = uids.keyAt(j);
4769                                    rec.eventTag.poolIdx = uids.valueAt(j);
4770                                    hprinter.printNextItem(pw, rec, baseTime, checkin,
4771                                            (flags&DUMP_VERBOSE) != 0);
4772                                    rec.wakeReasonTag = null;
4773                                    rec.wakelockTag = null;
4774                                }
4775                            }
4776                        }
4777                        rec.eventCode = oldEventCode;
4778                        rec.eventTag = oldEventTag;
4779                        tracker = null;
4780                    }
4781                }
4782                hprinter.printNextItem(pw, rec, baseTime, checkin,
4783                        (flags&DUMP_VERBOSE) != 0);
4784            } else if (false && rec.eventCode != HistoryItem.EVENT_NONE) {
4785                // This is an attempt to aggregate the previous state and generate
4786                // fake events to reflect that state at the point where we start
4787                // printing real events.  It doesn't really work right, so is turned off.
4788                if (tracker == null) {
4789                    tracker = new HistoryEventTracker();
4790                }
4791                tracker.updateState(rec.eventCode, rec.eventTag.string,
4792                        rec.eventTag.uid, rec.eventTag.poolIdx);
4793            }
4794        }
4795        if (histStart >= 0) {
4796            commitCurrentHistoryBatchLocked();
4797            pw.print(checkin ? "NEXT: " : "  NEXT: "); pw.println(lastTime+1);
4798        }
4799    }
4800
4801    private void dumpDailyLevelStepSummary(PrintWriter pw, String prefix, String label,
4802            LevelStepTracker steps, StringBuilder tmpSb, int[] tmpOutInt) {
4803        if (steps == null) {
4804            return;
4805        }
4806        long timeRemaining = steps.computeTimeEstimate(0, 0, tmpOutInt);
4807        if (timeRemaining >= 0) {
4808            pw.print(prefix); pw.print(label); pw.print(" total time: ");
4809            tmpSb.setLength(0);
4810            formatTimeMs(tmpSb, timeRemaining);
4811            pw.print(tmpSb);
4812            pw.print(" (from "); pw.print(tmpOutInt[0]);
4813            pw.println(" steps)");
4814        }
4815        for (int i=0; i< STEP_LEVEL_MODES_OF_INTEREST.length; i++) {
4816            long estimatedTime = steps.computeTimeEstimate(STEP_LEVEL_MODES_OF_INTEREST[i],
4817                    STEP_LEVEL_MODE_VALUES[i], tmpOutInt);
4818            if (estimatedTime > 0) {
4819                pw.print(prefix); pw.print(label); pw.print(" ");
4820                pw.print(STEP_LEVEL_MODE_LABELS[i]);
4821                pw.print(" time: ");
4822                tmpSb.setLength(0);
4823                formatTimeMs(tmpSb, estimatedTime);
4824                pw.print(tmpSb);
4825                pw.print(" (from "); pw.print(tmpOutInt[0]);
4826                pw.println(" steps)");
4827            }
4828        }
4829    }
4830
4831    private void dumpDailyPackageChanges(PrintWriter pw, String prefix,
4832            ArrayList<PackageChange> changes) {
4833        if (changes == null) {
4834            return;
4835        }
4836        pw.print(prefix); pw.println("Package changes:");
4837        for (int i=0; i<changes.size(); i++) {
4838            PackageChange pc = changes.get(i);
4839            if (pc.mUpdate) {
4840                pw.print(prefix); pw.print("  Update "); pw.print(pc.mPackageName);
4841                pw.print(" vers="); pw.println(pc.mVersionCode);
4842            } else {
4843                pw.print(prefix); pw.print("  Uninstall "); pw.println(pc.mPackageName);
4844            }
4845        }
4846    }
4847
4848    /**
4849     * Dumps a human-readable summary of the battery statistics to the given PrintWriter.
4850     *
4851     * @param pw a Printer to receive the dump output.
4852     */
4853    @SuppressWarnings("unused")
4854    public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
4855        prepareForDumpLocked();
4856
4857        final boolean filtering = (flags
4858                & (DUMP_HISTORY_ONLY|DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) != 0;
4859
4860        if ((flags&DUMP_HISTORY_ONLY) != 0 || !filtering) {
4861            final long historyTotalSize = getHistoryTotalSize();
4862            final long historyUsedSize = getHistoryUsedSize();
4863            if (startIteratingHistoryLocked()) {
4864                try {
4865                    pw.print("Battery History (");
4866                    pw.print((100*historyUsedSize)/historyTotalSize);
4867                    pw.print("% used, ");
4868                    printSizeValue(pw, historyUsedSize);
4869                    pw.print(" used of ");
4870                    printSizeValue(pw, historyTotalSize);
4871                    pw.print(", ");
4872                    pw.print(getHistoryStringPoolSize());
4873                    pw.print(" strings using ");
4874                    printSizeValue(pw, getHistoryStringPoolBytes());
4875                    pw.println("):");
4876                    dumpHistoryLocked(pw, flags, histStart, false);
4877                    pw.println();
4878                } finally {
4879                    finishIteratingHistoryLocked();
4880                }
4881            }
4882
4883            if (startIteratingOldHistoryLocked()) {
4884                try {
4885                    final HistoryItem rec = new HistoryItem();
4886                    pw.println("Old battery History:");
4887                    HistoryPrinter hprinter = new HistoryPrinter();
4888                    long baseTime = -1;
4889                    while (getNextOldHistoryLocked(rec)) {
4890                        if (baseTime < 0) {
4891                            baseTime = rec.time;
4892                        }
4893                        hprinter.printNextItem(pw, rec, baseTime, false, (flags&DUMP_VERBOSE) != 0);
4894                    }
4895                    pw.println();
4896                } finally {
4897                    finishIteratingOldHistoryLocked();
4898                }
4899            }
4900        }
4901
4902        if (filtering && (flags&(DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) == 0) {
4903            return;
4904        }
4905
4906        if (!filtering) {
4907            SparseArray<? extends Uid> uidStats = getUidStats();
4908            final int NU = uidStats.size();
4909            boolean didPid = false;
4910            long nowRealtime = SystemClock.elapsedRealtime();
4911            for (int i=0; i<NU; i++) {
4912                Uid uid = uidStats.valueAt(i);
4913                SparseArray<? extends Uid.Pid> pids = uid.getPidStats();
4914                if (pids != null) {
4915                    for (int j=0; j<pids.size(); j++) {
4916                        Uid.Pid pid = pids.valueAt(j);
4917                        if (!didPid) {
4918                            pw.println("Per-PID Stats:");
4919                            didPid = true;
4920                        }
4921                        long time = pid.mWakeSumMs + (pid.mWakeNesting > 0
4922                                ? (nowRealtime - pid.mWakeStartMs) : 0);
4923                        pw.print("  PID "); pw.print(pids.keyAt(j));
4924                                pw.print(" wake time: ");
4925                                TimeUtils.formatDuration(time, pw);
4926                                pw.println("");
4927                    }
4928                }
4929            }
4930            if (didPid) {
4931                pw.println();
4932            }
4933        }
4934
4935        if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
4936            if (dumpDurationSteps(pw, "  ", "Discharge step durations:",
4937                    getDischargeLevelStepTracker(), false)) {
4938                long timeRemaining = computeBatteryTimeRemaining(SystemClock.elapsedRealtime());
4939                if (timeRemaining >= 0) {
4940                    pw.print("  Estimated discharge time remaining: ");
4941                    TimeUtils.formatDuration(timeRemaining / 1000, pw);
4942                    pw.println();
4943                }
4944                final LevelStepTracker steps = getDischargeLevelStepTracker();
4945                for (int i=0; i< STEP_LEVEL_MODES_OF_INTEREST.length; i++) {
4946                    dumpTimeEstimate(pw, "  Estimated ", STEP_LEVEL_MODE_LABELS[i], " time: ",
4947                            steps.computeTimeEstimate(STEP_LEVEL_MODES_OF_INTEREST[i],
4948                                    STEP_LEVEL_MODE_VALUES[i], null));
4949                }
4950                pw.println();
4951            }
4952            if (dumpDurationSteps(pw, "  ", "Charge step durations:",
4953                    getChargeLevelStepTracker(), false)) {
4954                long timeRemaining = computeChargeTimeRemaining(SystemClock.elapsedRealtime());
4955                if (timeRemaining >= 0) {
4956                    pw.print("  Estimated charge time remaining: ");
4957                    TimeUtils.formatDuration(timeRemaining / 1000, pw);
4958                    pw.println();
4959                }
4960                pw.println();
4961            }
4962        }
4963        if (!filtering || (flags&(DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) != 0) {
4964            pw.println("Daily stats:");
4965            pw.print("  Current start time: ");
4966            pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss",
4967                    getCurrentDailyStartTime()).toString());
4968            pw.print("  Next min deadline: ");
4969            pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss",
4970                    getNextMinDailyDeadline()).toString());
4971            pw.print("  Next max deadline: ");
4972            pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss",
4973                    getNextMaxDailyDeadline()).toString());
4974            StringBuilder sb = new StringBuilder(64);
4975            int[] outInt = new int[1];
4976            LevelStepTracker dsteps = getDailyDischargeLevelStepTracker();
4977            LevelStepTracker csteps = getDailyChargeLevelStepTracker();
4978            ArrayList<PackageChange> pkgc = getDailyPackageChanges();
4979            if (dsteps.mNumStepDurations > 0 || csteps.mNumStepDurations > 0 || pkgc != null) {
4980                if ((flags&DUMP_DAILY_ONLY) != 0 || !filtering) {
4981                    if (dumpDurationSteps(pw, "    ", "  Current daily discharge step durations:",
4982                            dsteps, false)) {
4983                        dumpDailyLevelStepSummary(pw, "      ", "Discharge", dsteps,
4984                                sb, outInt);
4985                    }
4986                    if (dumpDurationSteps(pw, "    ", "  Current daily charge step durations:",
4987                            csteps, false)) {
4988                        dumpDailyLevelStepSummary(pw, "      ", "Charge", csteps,
4989                                sb, outInt);
4990                    }
4991                    dumpDailyPackageChanges(pw, "    ", pkgc);
4992                } else {
4993                    pw.println("  Current daily steps:");
4994                    dumpDailyLevelStepSummary(pw, "    ", "Discharge", dsteps,
4995                            sb, outInt);
4996                    dumpDailyLevelStepSummary(pw, "    ", "Charge", csteps,
4997                            sb, outInt);
4998                }
4999            }
5000            DailyItem dit;
5001            int curIndex = 0;
5002            while ((dit=getDailyItemLocked(curIndex)) != null) {
5003                curIndex++;
5004                if ((flags&DUMP_DAILY_ONLY) != 0) {
5005                    pw.println();
5006                }
5007                pw.print("  Daily from ");
5008                pw.print(DateFormat.format("yyyy-MM-dd-HH-mm-ss", dit.mStartTime).toString());
5009                pw.print(" to ");
5010                pw.print(DateFormat.format("yyyy-MM-dd-HH-mm-ss", dit.mEndTime).toString());
5011                pw.println(":");
5012                if ((flags&DUMP_DAILY_ONLY) != 0 || !filtering) {
5013                    if (dumpDurationSteps(pw, "      ",
5014                            "    Discharge step durations:", dit.mDischargeSteps, false)) {
5015                        dumpDailyLevelStepSummary(pw, "        ", "Discharge", dit.mDischargeSteps,
5016                                sb, outInt);
5017                    }
5018                    if (dumpDurationSteps(pw, "      ",
5019                            "    Charge step durations:", dit.mChargeSteps, false)) {
5020                        dumpDailyLevelStepSummary(pw, "        ", "Charge", dit.mChargeSteps,
5021                                sb, outInt);
5022                    }
5023                    dumpDailyPackageChanges(pw, "    ", dit.mPackageChanges);
5024                } else {
5025                    dumpDailyLevelStepSummary(pw, "    ", "Discharge", dit.mDischargeSteps,
5026                            sb, outInt);
5027                    dumpDailyLevelStepSummary(pw, "    ", "Charge", dit.mChargeSteps,
5028                            sb, outInt);
5029                }
5030            }
5031            pw.println();
5032        }
5033        if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
5034            pw.println("Statistics since last charge:");
5035            pw.println("  System starts: " + getStartCount()
5036                    + ", currently on battery: " + getIsOnBattery());
5037            dumpLocked(context, pw, "", STATS_SINCE_CHARGED, reqUid,
5038                    (flags&DUMP_DEVICE_WIFI_ONLY) != 0);
5039            pw.println();
5040        }
5041    }
5042
5043    @SuppressWarnings("unused")
5044    public void dumpCheckinLocked(Context context, PrintWriter pw,
5045            List<ApplicationInfo> apps, int flags, long histStart) {
5046        prepareForDumpLocked();
5047
5048        dumpLine(pw, 0 /* uid */, "i" /* category */, VERSION_DATA,
5049                CHECKIN_VERSION, getParcelVersion(), getStartPlatformVersion(),
5050                getEndPlatformVersion());
5051
5052        long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
5053
5054        final boolean filtering = (flags &
5055                (DUMP_HISTORY_ONLY|DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) != 0;
5056
5057        if ((flags&DUMP_INCLUDE_HISTORY) != 0 || (flags&DUMP_HISTORY_ONLY) != 0) {
5058            if (startIteratingHistoryLocked()) {
5059                try {
5060                    for (int i=0; i<getHistoryStringPoolSize(); i++) {
5061                        pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
5062                        pw.print(HISTORY_STRING_POOL); pw.print(',');
5063                        pw.print(i);
5064                        pw.print(",");
5065                        pw.print(getHistoryTagPoolUid(i));
5066                        pw.print(",\"");
5067                        String str = getHistoryTagPoolString(i);
5068                        str = str.replace("\\", "\\\\");
5069                        str = str.replace("\"", "\\\"");
5070                        pw.print(str);
5071                        pw.print("\"");
5072                        pw.println();
5073                    }
5074                    dumpHistoryLocked(pw, flags, histStart, true);
5075                } finally {
5076                    finishIteratingHistoryLocked();
5077                }
5078            }
5079        }
5080
5081        if (filtering && (flags&(DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) == 0) {
5082            return;
5083        }
5084
5085        if (apps != null) {
5086            SparseArray<ArrayList<String>> uids = new SparseArray<ArrayList<String>>();
5087            for (int i=0; i<apps.size(); i++) {
5088                ApplicationInfo ai = apps.get(i);
5089                ArrayList<String> pkgs = uids.get(ai.uid);
5090                if (pkgs == null) {
5091                    pkgs = new ArrayList<String>();
5092                    uids.put(ai.uid, pkgs);
5093                }
5094                pkgs.add(ai.packageName);
5095            }
5096            SparseArray<? extends Uid> uidStats = getUidStats();
5097            final int NU = uidStats.size();
5098            String[] lineArgs = new String[2];
5099            for (int i=0; i<NU; i++) {
5100                int uid = uidStats.keyAt(i);
5101                ArrayList<String> pkgs = uids.get(uid);
5102                if (pkgs != null) {
5103                    for (int j=0; j<pkgs.size(); j++) {
5104                        lineArgs[0] = Integer.toString(uid);
5105                        lineArgs[1] = pkgs.get(j);
5106                        dumpLine(pw, 0 /* uid */, "i" /* category */, UID_DATA,
5107                                (Object[])lineArgs);
5108                    }
5109                }
5110            }
5111        }
5112        if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
5113            dumpDurationSteps(pw, "", DISCHARGE_STEP_DATA, getDischargeLevelStepTracker(), true);
5114            String[] lineArgs = new String[1];
5115            long timeRemaining = computeBatteryTimeRemaining(SystemClock.elapsedRealtime());
5116            if (timeRemaining >= 0) {
5117                lineArgs[0] = Long.toString(timeRemaining);
5118                dumpLine(pw, 0 /* uid */, "i" /* category */, DISCHARGE_TIME_REMAIN_DATA,
5119                        (Object[])lineArgs);
5120            }
5121            dumpDurationSteps(pw, "", CHARGE_STEP_DATA, getChargeLevelStepTracker(), true);
5122            timeRemaining = computeChargeTimeRemaining(SystemClock.elapsedRealtime());
5123            if (timeRemaining >= 0) {
5124                lineArgs[0] = Long.toString(timeRemaining);
5125                dumpLine(pw, 0 /* uid */, "i" /* category */, CHARGE_TIME_REMAIN_DATA,
5126                        (Object[])lineArgs);
5127            }
5128            dumpCheckinLocked(context, pw, STATS_SINCE_CHARGED, -1,
5129                    (flags&DUMP_DEVICE_WIFI_ONLY) != 0);
5130        }
5131    }
5132}
5133