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