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