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