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