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