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