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