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