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