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