BatteryStats.java revision 049c88b48ae4dfdf4cdc85aac85607bb4225e7c7
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 wifiPowerDrainMaMs = getWifiControllerActivity(CONTROLLER_POWER_DRAIN, which);
3286        final long wifiTotalTimeMs = wifiIdleTimeMs + wifiRxTimeMs + wifiTxTimeMs;
3287
3288        sb.setLength(0);
3289        sb.append(prefix);
3290        sb.append("  WiFi Idle time: "); formatTimeMs(sb, wifiIdleTimeMs);
3291        sb.append("(");
3292        sb.append(formatRatioLocked(wifiIdleTimeMs, wifiTotalTimeMs));
3293        sb.append(")");
3294        pw.println(sb.toString());
3295
3296        sb.setLength(0);
3297        sb.append(prefix);
3298        sb.append("  WiFi Rx time:   "); formatTimeMs(sb, wifiRxTimeMs);
3299        sb.append("(");
3300        sb.append(formatRatioLocked(wifiRxTimeMs, wifiTotalTimeMs));
3301        sb.append(")");
3302        pw.println(sb.toString());
3303
3304        sb.setLength(0);
3305        sb.append(prefix);
3306        sb.append("  WiFi Tx time:   "); formatTimeMs(sb, wifiTxTimeMs);
3307        sb.append("(");
3308        sb.append(formatRatioLocked(wifiTxTimeMs, wifiTotalTimeMs));
3309        sb.append(")");
3310        pw.println(sb.toString());
3311
3312        sb.setLength(0);
3313        sb.append(prefix);
3314        sb.append("  WiFi Power drain: ").append(
3315                BatteryStatsHelper.makemAh(wifiPowerDrainMaMs / (double) (1000*60*60)));
3316        sb.append("mAh");
3317        pw.println(sb.toString());
3318
3319        final long bluetoothIdleTimeMs =
3320                getBluetoothControllerActivity(CONTROLLER_IDLE_TIME, which);
3321        final long bluetoothRxTimeMs = getBluetoothControllerActivity(CONTROLLER_RX_TIME, which);
3322        final long bluetoothTxTimeMs = getBluetoothControllerActivity(CONTROLLER_TX_TIME, which);
3323        final long bluetoothTotalTimeMs = bluetoothIdleTimeMs + bluetoothRxTimeMs +
3324                bluetoothTxTimeMs;
3325
3326        sb.setLength(0);
3327        sb.append(prefix);
3328        sb.append("  Bluetooth Idle time: "); formatTimeMs(sb, bluetoothIdleTimeMs);
3329        sb.append("(");
3330        sb.append(formatRatioLocked(bluetoothIdleTimeMs, bluetoothTotalTimeMs));
3331        sb.append(")");
3332        pw.println(sb.toString());
3333
3334        sb.setLength(0);
3335        sb.append(prefix);
3336        sb.append("  Bluetooth Rx time:   "); formatTimeMs(sb, bluetoothRxTimeMs);
3337        sb.append("(");
3338        sb.append(formatRatioLocked(bluetoothRxTimeMs, bluetoothTotalTimeMs));
3339        sb.append(")");
3340        pw.println(sb.toString());
3341
3342        sb.setLength(0);
3343        sb.append(prefix);
3344        sb.append("  Bluetooth Tx time:   "); formatTimeMs(sb, bluetoothTxTimeMs);
3345        sb.append("(");
3346        sb.append(formatRatioLocked(bluetoothTxTimeMs, bluetoothTotalTimeMs));
3347        sb.append(")");
3348        pw.println(sb.toString());
3349
3350        sb.setLength(0);
3351        sb.append(prefix);
3352        sb.append("  Bluetooth Power drain: ").append(BatteryStatsHelper.makemAh(
3353                getBluetoothControllerActivity(CONTROLLER_POWER_DRAIN, which) /
3354                        (double)(1000*60*60)));
3355        sb.append("mAh");
3356        pw.println(sb.toString());
3357
3358        pw.println();
3359
3360        if (which == STATS_SINCE_UNPLUGGED) {
3361            if (getIsOnBattery()) {
3362                pw.print(prefix); pw.println("  Device is currently unplugged");
3363                pw.print(prefix); pw.print("    Discharge cycle start level: ");
3364                        pw.println(getDischargeStartLevel());
3365                pw.print(prefix); pw.print("    Discharge cycle current level: ");
3366                        pw.println(getDischargeCurrentLevel());
3367            } else {
3368                pw.print(prefix); pw.println("  Device is currently plugged into power");
3369                pw.print(prefix); pw.print("    Last discharge cycle start level: ");
3370                        pw.println(getDischargeStartLevel());
3371                pw.print(prefix); pw.print("    Last discharge cycle end level: ");
3372                        pw.println(getDischargeCurrentLevel());
3373            }
3374            pw.print(prefix); pw.print("    Amount discharged while screen on: ");
3375                    pw.println(getDischargeAmountScreenOn());
3376            pw.print(prefix); pw.print("    Amount discharged while screen off: ");
3377                    pw.println(getDischargeAmountScreenOff());
3378            pw.println(" ");
3379        } else {
3380            pw.print(prefix); pw.println("  Device battery use since last full charge");
3381            pw.print(prefix); pw.print("    Amount discharged (lower bound): ");
3382                    pw.println(getLowDischargeAmountSinceCharge());
3383            pw.print(prefix); pw.print("    Amount discharged (upper bound): ");
3384                    pw.println(getHighDischargeAmountSinceCharge());
3385            pw.print(prefix); pw.print("    Amount discharged while screen on: ");
3386                    pw.println(getDischargeAmountScreenOnSinceCharge());
3387            pw.print(prefix); pw.print("    Amount discharged while screen off: ");
3388                    pw.println(getDischargeAmountScreenOffSinceCharge());
3389            pw.println();
3390        }
3391
3392        final BatteryStatsHelper helper = new BatteryStatsHelper(context, false, wifiOnly);
3393        helper.create(this);
3394        helper.refreshStats(which, UserHandle.USER_ALL);
3395        List<BatterySipper> sippers = helper.getUsageList();
3396        if (sippers != null && sippers.size() > 0) {
3397            pw.print(prefix); pw.println("  Estimated power use (mAh):");
3398            pw.print(prefix); pw.print("    Capacity: ");
3399                    printmAh(pw, helper.getPowerProfile().getBatteryCapacity());
3400                    pw.print(", Computed drain: "); printmAh(pw, helper.getComputedPower());
3401                    pw.print(", actual drain: "); printmAh(pw, helper.getMinDrainedPower());
3402                    if (helper.getMinDrainedPower() != helper.getMaxDrainedPower()) {
3403                        pw.print("-"); printmAh(pw, helper.getMaxDrainedPower());
3404                    }
3405                    pw.println();
3406            for (int i=0; i<sippers.size(); i++) {
3407                final BatterySipper bs = sippers.get(i);
3408                switch (bs.drainType) {
3409                    case IDLE:
3410                        pw.print(prefix); pw.print("    Idle: "); printmAh(pw, bs.totalPowerMah);
3411                        pw.println();
3412                        break;
3413                    case CELL:
3414                        pw.print(prefix); pw.print("    Cell standby: "); printmAh(pw, bs.totalPowerMah);
3415                        pw.println();
3416                        break;
3417                    case PHONE:
3418                        pw.print(prefix); pw.print("    Phone calls: "); printmAh(pw, bs.totalPowerMah);
3419                        pw.println();
3420                        break;
3421                    case WIFI:
3422                        pw.print(prefix); pw.print("    Wifi: "); printmAh(pw, bs.totalPowerMah);
3423                        pw.println();
3424                        break;
3425                    case BLUETOOTH:
3426                        pw.print(prefix); pw.print("    Bluetooth: "); printmAh(pw, bs.totalPowerMah);
3427                        pw.println();
3428                        break;
3429                    case SCREEN:
3430                        pw.print(prefix); pw.print("    Screen: "); printmAh(pw, bs.totalPowerMah);
3431                        pw.println();
3432                        break;
3433                    case FLASHLIGHT:
3434                        pw.print(prefix); pw.print("    Flashlight: "); printmAh(pw, bs.totalPowerMah);
3435                        pw.println();
3436                        break;
3437                    case APP:
3438                        pw.print(prefix); pw.print("    Uid ");
3439                        UserHandle.formatUid(pw, bs.uidObj.getUid());
3440                        pw.print(": "); printmAh(pw, bs.totalPowerMah); pw.println();
3441                        break;
3442                    case USER:
3443                        pw.print(prefix); pw.print("    User "); pw.print(bs.userId);
3444                        pw.print(": "); printmAh(pw, bs.totalPowerMah); pw.println();
3445                        break;
3446                    case UNACCOUNTED:
3447                        pw.print(prefix); pw.print("    Unaccounted: "); printmAh(pw, bs.totalPowerMah);
3448                        pw.println();
3449                        break;
3450                    case OVERCOUNTED:
3451                        pw.print(prefix); pw.print("    Over-counted: "); printmAh(pw, bs.totalPowerMah);
3452                        pw.println();
3453                        break;
3454                }
3455            }
3456            pw.println();
3457        }
3458
3459        sippers = helper.getMobilemsppList();
3460        if (sippers != null && sippers.size() > 0) {
3461            pw.print(prefix); pw.println("  Per-app mobile ms per packet:");
3462            long totalTime = 0;
3463            for (int i=0; i<sippers.size(); i++) {
3464                final BatterySipper bs = sippers.get(i);
3465                sb.setLength(0);
3466                sb.append(prefix); sb.append("    Uid ");
3467                UserHandle.formatUid(sb, bs.uidObj.getUid());
3468                sb.append(": "); sb.append(BatteryStatsHelper.makemAh(bs.mobilemspp));
3469                sb.append(" ("); sb.append(bs.mobileRxPackets+bs.mobileTxPackets);
3470                sb.append(" packets over "); formatTimeMsNoSpace(sb, bs.mobileActive);
3471                sb.append(") "); sb.append(bs.mobileActiveCount); sb.append("x");
3472                pw.println(sb.toString());
3473                totalTime += bs.mobileActive;
3474            }
3475            sb.setLength(0);
3476            sb.append(prefix);
3477            sb.append("    TOTAL TIME: ");
3478            formatTimeMs(sb, totalTime);
3479            sb.append("("); sb.append(formatRatioLocked(totalTime, whichBatteryRealtime));
3480            sb.append(")");
3481            pw.println(sb.toString());
3482            pw.println();
3483        }
3484
3485        final Comparator<TimerEntry> timerComparator = new Comparator<TimerEntry>() {
3486            @Override
3487            public int compare(TimerEntry lhs, TimerEntry rhs) {
3488                long lhsTime = lhs.mTime;
3489                long rhsTime = rhs.mTime;
3490                if (lhsTime < rhsTime) {
3491                    return 1;
3492                }
3493                if (lhsTime > rhsTime) {
3494                    return -1;
3495                }
3496                return 0;
3497            }
3498        };
3499
3500        if (reqUid < 0) {
3501            final Map<String, ? extends BatteryStats.Timer> kernelWakelocks
3502                    = getKernelWakelockStats();
3503            if (kernelWakelocks.size() > 0) {
3504                final ArrayList<TimerEntry> ktimers = new ArrayList<>();
3505                for (Map.Entry<String, ? extends BatteryStats.Timer> ent
3506                        : kernelWakelocks.entrySet()) {
3507                    final BatteryStats.Timer timer = ent.getValue();
3508                    final long totalTimeMillis = computeWakeLock(timer, rawRealtime, which);
3509                    if (totalTimeMillis > 0) {
3510                        ktimers.add(new TimerEntry(ent.getKey(), 0, timer, totalTimeMillis));
3511                    }
3512                }
3513                if (ktimers.size() > 0) {
3514                    Collections.sort(ktimers, timerComparator);
3515                    pw.print(prefix); pw.println("  All kernel wake locks:");
3516                    for (int i=0; i<ktimers.size(); i++) {
3517                        final TimerEntry timer = ktimers.get(i);
3518                        String linePrefix = ": ";
3519                        sb.setLength(0);
3520                        sb.append(prefix);
3521                        sb.append("  Kernel Wake lock ");
3522                        sb.append(timer.mName);
3523                        linePrefix = printWakeLock(sb, timer.mTimer, rawRealtime, null,
3524                                which, linePrefix);
3525                        if (!linePrefix.equals(": ")) {
3526                            sb.append(" realtime");
3527                            // Only print out wake locks that were held
3528                            pw.println(sb.toString());
3529                        }
3530                    }
3531                    pw.println();
3532                }
3533            }
3534
3535            if (timers.size() > 0) {
3536                Collections.sort(timers, timerComparator);
3537                pw.print(prefix); pw.println("  All partial wake locks:");
3538                for (int i=0; i<timers.size(); i++) {
3539                    TimerEntry timer = timers.get(i);
3540                    sb.setLength(0);
3541                    sb.append("  Wake lock ");
3542                    UserHandle.formatUid(sb, timer.mId);
3543                    sb.append(" ");
3544                    sb.append(timer.mName);
3545                    printWakeLock(sb, timer.mTimer, rawRealtime, null, which, ": ");
3546                    sb.append(" realtime");
3547                    pw.println(sb.toString());
3548                }
3549                timers.clear();
3550                pw.println();
3551            }
3552
3553            final Map<String, ? extends Timer> wakeupReasons = getWakeupReasonStats();
3554            if (wakeupReasons.size() > 0) {
3555                pw.print(prefix); pw.println("  All wakeup reasons:");
3556                final ArrayList<TimerEntry> reasons = new ArrayList<>();
3557                for (Map.Entry<String, ? extends Timer> ent : wakeupReasons.entrySet()) {
3558                    final Timer timer = ent.getValue();
3559                    reasons.add(new TimerEntry(ent.getKey(), 0, timer,
3560                            timer.getCountLocked(which)));
3561                }
3562                Collections.sort(reasons, timerComparator);
3563                for (int i=0; i<reasons.size(); i++) {
3564                    TimerEntry timer = reasons.get(i);
3565                    String linePrefix = ": ";
3566                    sb.setLength(0);
3567                    sb.append(prefix);
3568                    sb.append("  Wakeup reason ");
3569                    sb.append(timer.mName);
3570                    printWakeLock(sb, timer.mTimer, rawRealtime, null, which, ": ");
3571                    sb.append(" realtime");
3572                    pw.println(sb.toString());
3573                }
3574                pw.println();
3575            }
3576        }
3577
3578        for (int iu=0; iu<NU; iu++) {
3579            final int uid = uidStats.keyAt(iu);
3580            if (reqUid >= 0 && uid != reqUid && uid != Process.SYSTEM_UID) {
3581                continue;
3582            }
3583
3584            final Uid u = uidStats.valueAt(iu);
3585
3586            pw.print(prefix);
3587            pw.print("  ");
3588            UserHandle.formatUid(pw, uid);
3589            pw.println(":");
3590            boolean uidActivity = false;
3591
3592            final long mobileRxBytes = u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
3593            final long mobileTxBytes = u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
3594            final long wifiRxBytes = u.getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
3595            final long wifiTxBytes = u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
3596            final long mobileRxPackets = u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
3597            final long mobileTxPackets = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
3598            final long uidMobileActiveTime = u.getMobileRadioActiveTime(which);
3599            final int uidMobileActiveCount = u.getMobileRadioActiveCount(which);
3600            final long wifiRxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
3601            final long wifiTxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
3602            final long fullWifiLockOnTime = u.getFullWifiLockTime(rawRealtime, which);
3603            final long wifiScanTime = u.getWifiScanTime(rawRealtime, which);
3604            final int wifiScanCount = u.getWifiScanCount(which);
3605            final long uidWifiRunningTime = u.getWifiRunningTime(rawRealtime, which);
3606
3607            if (mobileRxBytes > 0 || mobileTxBytes > 0
3608                    || mobileRxPackets > 0 || mobileTxPackets > 0) {
3609                pw.print(prefix); pw.print("    Mobile network: ");
3610                        pw.print(formatBytesLocked(mobileRxBytes)); pw.print(" received, ");
3611                        pw.print(formatBytesLocked(mobileTxBytes));
3612                        pw.print(" sent (packets "); pw.print(mobileRxPackets);
3613                        pw.print(" received, "); pw.print(mobileTxPackets); pw.println(" sent)");
3614            }
3615            if (uidMobileActiveTime > 0 || uidMobileActiveCount > 0) {
3616                sb.setLength(0);
3617                sb.append(prefix); sb.append("    Mobile radio active: ");
3618                formatTimeMs(sb, uidMobileActiveTime / 1000);
3619                sb.append("(");
3620                sb.append(formatRatioLocked(uidMobileActiveTime, mobileActiveTime));
3621                sb.append(") "); sb.append(uidMobileActiveCount); sb.append("x");
3622                long packets = mobileRxPackets + mobileTxPackets;
3623                if (packets == 0) {
3624                    packets = 1;
3625                }
3626                sb.append(" @ ");
3627                sb.append(BatteryStatsHelper.makemAh(uidMobileActiveTime / 1000 / (double)packets));
3628                sb.append(" mspp");
3629                pw.println(sb.toString());
3630            }
3631
3632            if (wifiRxBytes > 0 || wifiTxBytes > 0 || wifiRxPackets > 0 || wifiTxPackets > 0) {
3633                pw.print(prefix); pw.print("    Wi-Fi network: ");
3634                        pw.print(formatBytesLocked(wifiRxBytes)); pw.print(" received, ");
3635                        pw.print(formatBytesLocked(wifiTxBytes));
3636                        pw.print(" sent (packets "); pw.print(wifiRxPackets);
3637                        pw.print(" received, "); pw.print(wifiTxPackets); pw.println(" sent)");
3638            }
3639
3640            if (fullWifiLockOnTime != 0 || wifiScanTime != 0 || wifiScanCount != 0
3641                    || uidWifiRunningTime != 0) {
3642                sb.setLength(0);
3643                sb.append(prefix); sb.append("    Wifi Running: ");
3644                        formatTimeMs(sb, uidWifiRunningTime / 1000);
3645                        sb.append("("); sb.append(formatRatioLocked(uidWifiRunningTime,
3646                                whichBatteryRealtime)); sb.append(")\n");
3647                sb.append(prefix); sb.append("    Full Wifi Lock: ");
3648                        formatTimeMs(sb, fullWifiLockOnTime / 1000);
3649                        sb.append("("); sb.append(formatRatioLocked(fullWifiLockOnTime,
3650                                whichBatteryRealtime)); sb.append(")\n");
3651                sb.append(prefix); sb.append("    Wifi Scan: ");
3652                        formatTimeMs(sb, wifiScanTime / 1000);
3653                        sb.append("("); sb.append(formatRatioLocked(wifiScanTime,
3654                                whichBatteryRealtime)); sb.append(") ");
3655                                sb.append(wifiScanCount);
3656                                sb.append("x");
3657                pw.println(sb.toString());
3658            }
3659
3660            final long uidWifiIdleTimeMs = u.getWifiControllerActivity(CONTROLLER_IDLE_TIME, which);
3661            final long uidWifiRxTimeMs = u.getWifiControllerActivity(CONTROLLER_RX_TIME, which);
3662            final long uidWifiTxTimeMs = u.getWifiControllerActivity(CONTROLLER_TX_TIME, which);
3663            final long uidWifiTotalTimeMs = uidWifiIdleTimeMs + uidWifiRxTimeMs + uidWifiTxTimeMs;
3664            if (uidWifiTotalTimeMs > 0) {
3665                sb.setLength(0);
3666                sb.append(prefix).append("    WiFi Idle time: ");
3667                formatTimeMs(sb, uidWifiIdleTimeMs);
3668                sb.append("(").append(formatRatioLocked(uidWifiIdleTimeMs, uidWifiTotalTimeMs))
3669                        .append(")\n");
3670
3671                sb.append(prefix).append("    WiFi Rx time:   "); formatTimeMs(sb, uidWifiRxTimeMs);
3672                sb.append("(").append(formatRatioLocked(uidWifiRxTimeMs, uidWifiTotalTimeMs))
3673                        .append(")\n");
3674
3675                sb.append(prefix).append("    WiFi Tx time:   "); formatTimeMs(sb, uidWifiTxTimeMs);
3676                sb.append("(").append(formatRatioLocked(uidWifiTxTimeMs, uidWifiTotalTimeMs))
3677                        .append(")");
3678                pw.println(sb.toString());
3679            }
3680
3681            if (u.hasUserActivity()) {
3682                boolean hasData = false;
3683                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
3684                    final int val = u.getUserActivityCount(i, which);
3685                    if (val != 0) {
3686                        if (!hasData) {
3687                            sb.setLength(0);
3688                            sb.append("    User activity: ");
3689                            hasData = true;
3690                        } else {
3691                            sb.append(", ");
3692                        }
3693                        sb.append(val);
3694                        sb.append(" ");
3695                        sb.append(Uid.USER_ACTIVITY_TYPES[i]);
3696                    }
3697                }
3698                if (hasData) {
3699                    pw.println(sb.toString());
3700                }
3701            }
3702
3703            final ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> wakelocks
3704                    = u.getWakelockStats();
3705            long totalFullWakelock = 0, totalPartialWakelock = 0, totalWindowWakelock = 0;
3706            int countWakelock = 0;
3707            for (int iw=wakelocks.size()-1; iw>=0; iw--) {
3708                final Uid.Wakelock wl = wakelocks.valueAt(iw);
3709                String linePrefix = ": ";
3710                sb.setLength(0);
3711                sb.append(prefix);
3712                sb.append("    Wake lock ");
3713                sb.append(wakelocks.keyAt(iw));
3714                linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_FULL), rawRealtime,
3715                        "full", which, linePrefix);
3716                linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), rawRealtime,
3717                        "partial", which, linePrefix);
3718                linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), rawRealtime,
3719                        "window", which, linePrefix);
3720                if (true || !linePrefix.equals(": ")) {
3721                    sb.append(" realtime");
3722                    // Only print out wake locks that were held
3723                    pw.println(sb.toString());
3724                    uidActivity = true;
3725                    countWakelock++;
3726                }
3727                totalFullWakelock += computeWakeLock(wl.getWakeTime(WAKE_TYPE_FULL),
3728                        rawRealtime, which);
3729                totalPartialWakelock += computeWakeLock(wl.getWakeTime(WAKE_TYPE_PARTIAL),
3730                        rawRealtime, which);
3731                totalWindowWakelock += computeWakeLock(wl.getWakeTime(WAKE_TYPE_WINDOW),
3732                        rawRealtime, which);
3733            }
3734            if (countWakelock > 1) {
3735                if (totalFullWakelock != 0 || totalPartialWakelock != 0
3736                        || totalWindowWakelock != 0) {
3737                    sb.setLength(0);
3738                    sb.append(prefix);
3739                    sb.append("    TOTAL wake: ");
3740                    boolean needComma = false;
3741                    if (totalFullWakelock != 0) {
3742                        needComma = true;
3743                        formatTimeMs(sb, totalFullWakelock);
3744                        sb.append("full");
3745                    }
3746                    if (totalPartialWakelock != 0) {
3747                        if (needComma) {
3748                            sb.append(", ");
3749                        }
3750                        needComma = true;
3751                        formatTimeMs(sb, totalPartialWakelock);
3752                        sb.append("partial");
3753                    }
3754                    if (totalWindowWakelock != 0) {
3755                        if (needComma) {
3756                            sb.append(", ");
3757                        }
3758                        needComma = true;
3759                        formatTimeMs(sb, totalWindowWakelock);
3760                        sb.append("window");
3761                    }
3762                    sb.append(" realtime");
3763                    pw.println(sb.toString());
3764                }
3765            }
3766
3767            final ArrayMap<String, ? extends Timer> syncs = u.getSyncStats();
3768            for (int isy=syncs.size()-1; isy>=0; isy--) {
3769                final Timer timer = syncs.valueAt(isy);
3770                // Convert from microseconds to milliseconds with rounding
3771                final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
3772                final int count = timer.getCountLocked(which);
3773                sb.setLength(0);
3774                sb.append(prefix);
3775                sb.append("    Sync ");
3776                sb.append(syncs.keyAt(isy));
3777                sb.append(": ");
3778                if (totalTime != 0) {
3779                    formatTimeMs(sb, totalTime);
3780                    sb.append("realtime (");
3781                    sb.append(count);
3782                    sb.append(" times)");
3783                } else {
3784                    sb.append("(not used)");
3785                }
3786                pw.println(sb.toString());
3787                uidActivity = true;
3788            }
3789
3790            final ArrayMap<String, ? extends Timer> jobs = u.getJobStats();
3791            for (int ij=jobs.size()-1; ij>=0; ij--) {
3792                final Timer timer = jobs.valueAt(ij);
3793                // Convert from microseconds to milliseconds with rounding
3794                final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
3795                final int count = timer.getCountLocked(which);
3796                sb.setLength(0);
3797                sb.append(prefix);
3798                sb.append("    Job ");
3799                sb.append(jobs.keyAt(ij));
3800                sb.append(": ");
3801                if (totalTime != 0) {
3802                    formatTimeMs(sb, totalTime);
3803                    sb.append("realtime (");
3804                    sb.append(count);
3805                    sb.append(" times)");
3806                } else {
3807                    sb.append("(not used)");
3808                }
3809                pw.println(sb.toString());
3810                uidActivity = true;
3811            }
3812
3813            final SparseArray<? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
3814            final int NSE = sensors.size();
3815            for (int ise=0; ise<NSE; ise++) {
3816                final Uid.Sensor se = sensors.valueAt(ise);
3817                final int sensorNumber = sensors.keyAt(ise);
3818                sb.setLength(0);
3819                sb.append(prefix);
3820                sb.append("    Sensor ");
3821                int handle = se.getHandle();
3822                if (handle == Uid.Sensor.GPS) {
3823                    sb.append("GPS");
3824                } else {
3825                    sb.append(handle);
3826                }
3827                sb.append(": ");
3828
3829                final Timer timer = se.getSensorTime();
3830                if (timer != null) {
3831                    // Convert from microseconds to milliseconds with rounding
3832                    final long totalTime = (timer.getTotalTimeLocked(
3833                            rawRealtime, which) + 500) / 1000;
3834                    final int count = timer.getCountLocked(which);
3835                    //timer.logState();
3836                    if (totalTime != 0) {
3837                        formatTimeMs(sb, totalTime);
3838                        sb.append("realtime (");
3839                        sb.append(count);
3840                        sb.append(" times)");
3841                    } else {
3842                        sb.append("(not used)");
3843                    }
3844                } else {
3845                    sb.append("(not used)");
3846                }
3847
3848                pw.println(sb.toString());
3849                uidActivity = true;
3850            }
3851
3852            final Timer vibTimer = u.getVibratorOnTimer();
3853            if (vibTimer != null) {
3854                // Convert from microseconds to milliseconds with rounding
3855                final long totalTime = (vibTimer.getTotalTimeLocked(
3856                        rawRealtime, which) + 500) / 1000;
3857                final int count = vibTimer.getCountLocked(which);
3858                //timer.logState();
3859                if (totalTime != 0) {
3860                    sb.setLength(0);
3861                    sb.append(prefix);
3862                    sb.append("    Vibrator: ");
3863                    formatTimeMs(sb, totalTime);
3864                    sb.append("realtime (");
3865                    sb.append(count);
3866                    sb.append(" times)");
3867                    pw.println(sb.toString());
3868                    uidActivity = true;
3869                }
3870            }
3871
3872            final Timer fgTimer = u.getForegroundActivityTimer();
3873            if (fgTimer != null) {
3874                // Convert from microseconds to milliseconds with rounding
3875                final long totalTime = (fgTimer.getTotalTimeLocked(rawRealtime, which) + 500)
3876                        / 1000;
3877                final int count = fgTimer.getCountLocked(which);
3878                if (totalTime != 0) {
3879                    sb.setLength(0);
3880                    sb.append(prefix);
3881                    sb.append("    Foreground activities: ");
3882                    formatTimeMs(sb, totalTime);
3883                    sb.append("realtime (");
3884                    sb.append(count);
3885                    sb.append(" times)");
3886                    pw.println(sb.toString());
3887                    uidActivity = true;
3888                }
3889            }
3890
3891            long totalStateTime = 0;
3892            for (int ips=0; ips<Uid.NUM_PROCESS_STATE; ips++) {
3893                long time = u.getProcessStateTime(ips, rawRealtime, which);
3894                if (time > 0) {
3895                    totalStateTime += time;
3896                    sb.setLength(0);
3897                    sb.append(prefix);
3898                    sb.append("    ");
3899                    sb.append(Uid.PROCESS_STATE_NAMES[ips]);
3900                    sb.append(" for: ");
3901                    formatTimeMs(sb, (totalStateTime + 500) / 1000);
3902                    pw.println(sb.toString());
3903                    uidActivity = true;
3904                }
3905            }
3906
3907            final long userCpuTimeUs = u.getUserCpuTimeUs(which);
3908            final long systemCpuTimeUs = u.getSystemCpuTimeUs(which);
3909            if (userCpuTimeUs > 0 || systemCpuTimeUs > 0) {
3910                sb.setLength(0);
3911                sb.append(prefix);
3912                sb.append("    Total cpu time: ");
3913                formatTimeMs(sb, (userCpuTimeUs + systemCpuTimeUs) / 1000);
3914                pw.println(sb.toString());
3915            }
3916
3917            final ArrayMap<String, ? extends BatteryStats.Uid.Proc> processStats
3918                    = u.getProcessStats();
3919            for (int ipr=processStats.size()-1; ipr>=0; ipr--) {
3920                final Uid.Proc ps = processStats.valueAt(ipr);
3921                long userTime;
3922                long systemTime;
3923                long foregroundTime;
3924                int starts;
3925                int numExcessive;
3926
3927                userTime = ps.getUserTime(which);
3928                systemTime = ps.getSystemTime(which);
3929                foregroundTime = ps.getForegroundTime(which);
3930                starts = ps.getStarts(which);
3931                final int numCrashes = ps.getNumCrashes(which);
3932                final int numAnrs = ps.getNumAnrs(which);
3933                numExcessive = which == STATS_SINCE_CHARGED
3934                        ? ps.countExcessivePowers() : 0;
3935
3936                if (userTime != 0 || systemTime != 0 || foregroundTime != 0 || starts != 0
3937                        || numExcessive != 0 || numCrashes != 0 || numAnrs != 0) {
3938                    sb.setLength(0);
3939                    sb.append(prefix); sb.append("    Proc ");
3940                            sb.append(processStats.keyAt(ipr)); sb.append(":\n");
3941                    sb.append(prefix); sb.append("      CPU: ");
3942                            formatTimeMs(sb, userTime); sb.append("usr + ");
3943                            formatTimeMs(sb, systemTime); sb.append("krn ; ");
3944                            formatTimeMs(sb, foregroundTime); sb.append("fg");
3945                    if (starts != 0 || numCrashes != 0 || numAnrs != 0) {
3946                        sb.append("\n"); sb.append(prefix); sb.append("      ");
3947                        boolean hasOne = false;
3948                        if (starts != 0) {
3949                            hasOne = true;
3950                            sb.append(starts); sb.append(" starts");
3951                        }
3952                        if (numCrashes != 0) {
3953                            if (hasOne) {
3954                                sb.append(", ");
3955                            }
3956                            hasOne = true;
3957                            sb.append(numCrashes); sb.append(" crashes");
3958                        }
3959                        if (numAnrs != 0) {
3960                            if (hasOne) {
3961                                sb.append(", ");
3962                            }
3963                            sb.append(numAnrs); sb.append(" anrs");
3964                        }
3965                    }
3966                    pw.println(sb.toString());
3967                    for (int e=0; e<numExcessive; e++) {
3968                        Uid.Proc.ExcessivePower ew = ps.getExcessivePower(e);
3969                        if (ew != null) {
3970                            pw.print(prefix); pw.print("      * Killed for ");
3971                                    if (ew.type == Uid.Proc.ExcessivePower.TYPE_WAKE) {
3972                                        pw.print("wake lock");
3973                                    } else if (ew.type == Uid.Proc.ExcessivePower.TYPE_CPU) {
3974                                        pw.print("cpu");
3975                                    } else {
3976                                        pw.print("unknown");
3977                                    }
3978                                    pw.print(" use: ");
3979                                    TimeUtils.formatDuration(ew.usedTime, pw);
3980                                    pw.print(" over ");
3981                                    TimeUtils.formatDuration(ew.overTime, pw);
3982                                    if (ew.overTime != 0) {
3983                                        pw.print(" (");
3984                                        pw.print((ew.usedTime*100)/ew.overTime);
3985                                        pw.println("%)");
3986                                    }
3987                        }
3988                    }
3989                    uidActivity = true;
3990                }
3991            }
3992
3993            final ArrayMap<String, ? extends BatteryStats.Uid.Pkg> packageStats
3994                    = u.getPackageStats();
3995            for (int ipkg=packageStats.size()-1; ipkg>=0; ipkg--) {
3996                pw.print(prefix); pw.print("    Apk "); pw.print(packageStats.keyAt(ipkg));
3997                pw.println(":");
3998                boolean apkActivity = false;
3999                final Uid.Pkg ps = packageStats.valueAt(ipkg);
4000                final ArrayMap<String, ? extends Counter> alarms = ps.getWakeupAlarmStats();
4001                for (int iwa=alarms.size()-1; iwa>=0; iwa--) {
4002                    pw.print(prefix); pw.print("      Wakeup alarm ");
4003                            pw.print(alarms.keyAt(iwa)); pw.print(": ");
4004                            pw.print(alarms.valueAt(iwa).getCountLocked(which));
4005                            pw.println(" times");
4006                    apkActivity = true;
4007                }
4008                final ArrayMap<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
4009                for (int isvc=serviceStats.size()-1; isvc>=0; isvc--) {
4010                    final BatteryStats.Uid.Pkg.Serv ss = serviceStats.valueAt(isvc);
4011                    final long startTime = ss.getStartTime(batteryUptime, which);
4012                    final int starts = ss.getStarts(which);
4013                    final int launches = ss.getLaunches(which);
4014                    if (startTime != 0 || starts != 0 || launches != 0) {
4015                        sb.setLength(0);
4016                        sb.append(prefix); sb.append("      Service ");
4017                                sb.append(serviceStats.keyAt(isvc)); sb.append(":\n");
4018                        sb.append(prefix); sb.append("        Created for: ");
4019                                formatTimeMs(sb, startTime / 1000);
4020                                sb.append("uptime\n");
4021                        sb.append(prefix); sb.append("        Starts: ");
4022                                sb.append(starts);
4023                                sb.append(", launches: "); sb.append(launches);
4024                        pw.println(sb.toString());
4025                        apkActivity = true;
4026                    }
4027                }
4028                if (!apkActivity) {
4029                    pw.print(prefix); pw.println("      (nothing executed)");
4030                }
4031                uidActivity = true;
4032            }
4033            if (!uidActivity) {
4034                pw.print(prefix); pw.println("    (nothing executed)");
4035            }
4036        }
4037    }
4038
4039    static void printBitDescriptions(PrintWriter pw, int oldval, int newval, HistoryTag wakelockTag,
4040            BitDescription[] descriptions, boolean longNames) {
4041        int diff = oldval ^ newval;
4042        if (diff == 0) return;
4043        boolean didWake = false;
4044        for (int i=0; i<descriptions.length; i++) {
4045            BitDescription bd = descriptions[i];
4046            if ((diff&bd.mask) != 0) {
4047                pw.print(longNames ? " " : ",");
4048                if (bd.shift < 0) {
4049                    pw.print((newval&bd.mask) != 0 ? "+" : "-");
4050                    pw.print(longNames ? bd.name : bd.shortName);
4051                    if (bd.mask == HistoryItem.STATE_WAKE_LOCK_FLAG && wakelockTag != null) {
4052                        didWake = true;
4053                        pw.print("=");
4054                        if (longNames) {
4055                            UserHandle.formatUid(pw, wakelockTag.uid);
4056                            pw.print(":\"");
4057                            pw.print(wakelockTag.string);
4058                            pw.print("\"");
4059                        } else {
4060                            pw.print(wakelockTag.poolIdx);
4061                        }
4062                    }
4063                } else {
4064                    pw.print(longNames ? bd.name : bd.shortName);
4065                    pw.print("=");
4066                    int val = (newval&bd.mask)>>bd.shift;
4067                    if (bd.values != null && val >= 0 && val < bd.values.length) {
4068                        pw.print(longNames? bd.values[val] : bd.shortValues[val]);
4069                    } else {
4070                        pw.print(val);
4071                    }
4072                }
4073            }
4074        }
4075        if (!didWake && wakelockTag != null) {
4076            pw.print(longNames ? " wake_lock=" : ",w=");
4077            if (longNames) {
4078                UserHandle.formatUid(pw, wakelockTag.uid);
4079                pw.print(":\"");
4080                pw.print(wakelockTag.string);
4081                pw.print("\"");
4082            } else {
4083                pw.print(wakelockTag.poolIdx);
4084            }
4085        }
4086    }
4087
4088    public void prepareForDumpLocked() {
4089    }
4090
4091    public static class HistoryPrinter {
4092        int oldState = 0;
4093        int oldState2 = 0;
4094        int oldLevel = -1;
4095        int oldStatus = -1;
4096        int oldHealth = -1;
4097        int oldPlug = -1;
4098        int oldTemp = -1;
4099        int oldVolt = -1;
4100        long lastTime = -1;
4101
4102        void reset() {
4103            oldState = oldState2 = 0;
4104            oldLevel = -1;
4105            oldStatus = -1;
4106            oldHealth = -1;
4107            oldPlug = -1;
4108            oldTemp = -1;
4109            oldVolt = -1;
4110        }
4111
4112        public void printNextItem(PrintWriter pw, HistoryItem rec, long baseTime, boolean checkin,
4113                boolean verbose) {
4114            if (!checkin) {
4115                pw.print("  ");
4116                TimeUtils.formatDuration(rec.time - baseTime, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
4117                pw.print(" (");
4118                pw.print(rec.numReadInts);
4119                pw.print(") ");
4120            } else {
4121                pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
4122                pw.print(HISTORY_DATA); pw.print(',');
4123                if (lastTime < 0) {
4124                    pw.print(rec.time - baseTime);
4125                } else {
4126                    pw.print(rec.time - lastTime);
4127                }
4128                lastTime = rec.time;
4129            }
4130            if (rec.cmd == HistoryItem.CMD_START) {
4131                if (checkin) {
4132                    pw.print(":");
4133                }
4134                pw.println("START");
4135                reset();
4136            } else if (rec.cmd == HistoryItem.CMD_CURRENT_TIME
4137                    || rec.cmd == HistoryItem.CMD_RESET) {
4138                if (checkin) {
4139                    pw.print(":");
4140                }
4141                if (rec.cmd == HistoryItem.CMD_RESET) {
4142                    pw.print("RESET:");
4143                    reset();
4144                }
4145                pw.print("TIME:");
4146                if (checkin) {
4147                    pw.println(rec.currentTime);
4148                } else {
4149                    pw.print(" ");
4150                    pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss",
4151                            rec.currentTime).toString());
4152                }
4153            } else if (rec.cmd == HistoryItem.CMD_SHUTDOWN) {
4154                if (checkin) {
4155                    pw.print(":");
4156                }
4157                pw.println("SHUTDOWN");
4158            } else if (rec.cmd == HistoryItem.CMD_OVERFLOW) {
4159                if (checkin) {
4160                    pw.print(":");
4161                }
4162                pw.println("*OVERFLOW*");
4163            } else {
4164                if (!checkin) {
4165                    if (rec.batteryLevel < 10) pw.print("00");
4166                    else if (rec.batteryLevel < 100) pw.print("0");
4167                    pw.print(rec.batteryLevel);
4168                    if (verbose) {
4169                        pw.print(" ");
4170                        if (rec.states < 0) ;
4171                        else if (rec.states < 0x10) pw.print("0000000");
4172                        else if (rec.states < 0x100) pw.print("000000");
4173                        else if (rec.states < 0x1000) pw.print("00000");
4174                        else if (rec.states < 0x10000) pw.print("0000");
4175                        else if (rec.states < 0x100000) pw.print("000");
4176                        else if (rec.states < 0x1000000) pw.print("00");
4177                        else if (rec.states < 0x10000000) pw.print("0");
4178                        pw.print(Integer.toHexString(rec.states));
4179                    }
4180                } else {
4181                    if (oldLevel != rec.batteryLevel) {
4182                        oldLevel = rec.batteryLevel;
4183                        pw.print(",Bl="); pw.print(rec.batteryLevel);
4184                    }
4185                }
4186                if (oldStatus != rec.batteryStatus) {
4187                    oldStatus = rec.batteryStatus;
4188                    pw.print(checkin ? ",Bs=" : " status=");
4189                    switch (oldStatus) {
4190                        case BatteryManager.BATTERY_STATUS_UNKNOWN:
4191                            pw.print(checkin ? "?" : "unknown");
4192                            break;
4193                        case BatteryManager.BATTERY_STATUS_CHARGING:
4194                            pw.print(checkin ? "c" : "charging");
4195                            break;
4196                        case BatteryManager.BATTERY_STATUS_DISCHARGING:
4197                            pw.print(checkin ? "d" : "discharging");
4198                            break;
4199                        case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
4200                            pw.print(checkin ? "n" : "not-charging");
4201                            break;
4202                        case BatteryManager.BATTERY_STATUS_FULL:
4203                            pw.print(checkin ? "f" : "full");
4204                            break;
4205                        default:
4206                            pw.print(oldStatus);
4207                            break;
4208                    }
4209                }
4210                if (oldHealth != rec.batteryHealth) {
4211                    oldHealth = rec.batteryHealth;
4212                    pw.print(checkin ? ",Bh=" : " health=");
4213                    switch (oldHealth) {
4214                        case BatteryManager.BATTERY_HEALTH_UNKNOWN:
4215                            pw.print(checkin ? "?" : "unknown");
4216                            break;
4217                        case BatteryManager.BATTERY_HEALTH_GOOD:
4218                            pw.print(checkin ? "g" : "good");
4219                            break;
4220                        case BatteryManager.BATTERY_HEALTH_OVERHEAT:
4221                            pw.print(checkin ? "h" : "overheat");
4222                            break;
4223                        case BatteryManager.BATTERY_HEALTH_DEAD:
4224                            pw.print(checkin ? "d" : "dead");
4225                            break;
4226                        case BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE:
4227                            pw.print(checkin ? "v" : "over-voltage");
4228                            break;
4229                        case BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE:
4230                            pw.print(checkin ? "f" : "failure");
4231                            break;
4232                        case BatteryManager.BATTERY_HEALTH_COLD:
4233                            pw.print(checkin ? "c" : "cold");
4234                            break;
4235                        default:
4236                            pw.print(oldHealth);
4237                            break;
4238                    }
4239                }
4240                if (oldPlug != rec.batteryPlugType) {
4241                    oldPlug = rec.batteryPlugType;
4242                    pw.print(checkin ? ",Bp=" : " plug=");
4243                    switch (oldPlug) {
4244                        case 0:
4245                            pw.print(checkin ? "n" : "none");
4246                            break;
4247                        case BatteryManager.BATTERY_PLUGGED_AC:
4248                            pw.print(checkin ? "a" : "ac");
4249                            break;
4250                        case BatteryManager.BATTERY_PLUGGED_USB:
4251                            pw.print(checkin ? "u" : "usb");
4252                            break;
4253                        case BatteryManager.BATTERY_PLUGGED_WIRELESS:
4254                            pw.print(checkin ? "w" : "wireless");
4255                            break;
4256                        default:
4257                            pw.print(oldPlug);
4258                            break;
4259                    }
4260                }
4261                if (oldTemp != rec.batteryTemperature) {
4262                    oldTemp = rec.batteryTemperature;
4263                    pw.print(checkin ? ",Bt=" : " temp=");
4264                    pw.print(oldTemp);
4265                }
4266                if (oldVolt != rec.batteryVoltage) {
4267                    oldVolt = rec.batteryVoltage;
4268                    pw.print(checkin ? ",Bv=" : " volt=");
4269                    pw.print(oldVolt);
4270                }
4271                printBitDescriptions(pw, oldState, rec.states, rec.wakelockTag,
4272                        HISTORY_STATE_DESCRIPTIONS, !checkin);
4273                printBitDescriptions(pw, oldState2, rec.states2, null,
4274                        HISTORY_STATE2_DESCRIPTIONS, !checkin);
4275                if (rec.wakeReasonTag != null) {
4276                    if (checkin) {
4277                        pw.print(",wr=");
4278                        pw.print(rec.wakeReasonTag.poolIdx);
4279                    } else {
4280                        pw.print(" wake_reason=");
4281                        pw.print(rec.wakeReasonTag.uid);
4282                        pw.print(":\"");
4283                        pw.print(rec.wakeReasonTag.string);
4284                        pw.print("\"");
4285                    }
4286                }
4287                if (rec.eventCode != HistoryItem.EVENT_NONE) {
4288                    pw.print(checkin ? "," : " ");
4289                    if ((rec.eventCode&HistoryItem.EVENT_FLAG_START) != 0) {
4290                        pw.print("+");
4291                    } else if ((rec.eventCode&HistoryItem.EVENT_FLAG_FINISH) != 0) {
4292                        pw.print("-");
4293                    }
4294                    String[] eventNames = checkin ? HISTORY_EVENT_CHECKIN_NAMES
4295                            : HISTORY_EVENT_NAMES;
4296                    int idx = rec.eventCode & ~(HistoryItem.EVENT_FLAG_START
4297                            | HistoryItem.EVENT_FLAG_FINISH);
4298                    if (idx >= 0 && idx < eventNames.length) {
4299                        pw.print(eventNames[idx]);
4300                    } else {
4301                        pw.print(checkin ? "Ev" : "event");
4302                        pw.print(idx);
4303                    }
4304                    pw.print("=");
4305                    if (checkin) {
4306                        pw.print(rec.eventTag.poolIdx);
4307                    } else {
4308                        UserHandle.formatUid(pw, rec.eventTag.uid);
4309                        pw.print(":\"");
4310                        pw.print(rec.eventTag.string);
4311                        pw.print("\"");
4312                    }
4313                }
4314                pw.println();
4315                if (rec.stepDetails != null) {
4316                    if (!checkin) {
4317                        pw.print("                 Details: cpu=");
4318                        pw.print(rec.stepDetails.userTime);
4319                        pw.print("u+");
4320                        pw.print(rec.stepDetails.systemTime);
4321                        pw.print("s");
4322                        if (rec.stepDetails.appCpuUid1 >= 0) {
4323                            pw.print(" (");
4324                            printStepCpuUidDetails(pw, rec.stepDetails.appCpuUid1,
4325                                    rec.stepDetails.appCpuUTime1, rec.stepDetails.appCpuSTime1);
4326                            if (rec.stepDetails.appCpuUid2 >= 0) {
4327                                pw.print(", ");
4328                                printStepCpuUidDetails(pw, rec.stepDetails.appCpuUid2,
4329                                        rec.stepDetails.appCpuUTime2, rec.stepDetails.appCpuSTime2);
4330                            }
4331                            if (rec.stepDetails.appCpuUid3 >= 0) {
4332                                pw.print(", ");
4333                                printStepCpuUidDetails(pw, rec.stepDetails.appCpuUid3,
4334                                        rec.stepDetails.appCpuUTime3, rec.stepDetails.appCpuSTime3);
4335                            }
4336                            pw.print(')');
4337                        }
4338                        pw.println();
4339                        pw.print("                          /proc/stat=");
4340                        pw.print(rec.stepDetails.statUserTime);
4341                        pw.print(" usr, ");
4342                        pw.print(rec.stepDetails.statSystemTime);
4343                        pw.print(" sys, ");
4344                        pw.print(rec.stepDetails.statIOWaitTime);
4345                        pw.print(" io, ");
4346                        pw.print(rec.stepDetails.statIrqTime);
4347                        pw.print(" irq, ");
4348                        pw.print(rec.stepDetails.statSoftIrqTime);
4349                        pw.print(" sirq, ");
4350                        pw.print(rec.stepDetails.statIdlTime);
4351                        pw.print(" idle");
4352                        int totalRun = rec.stepDetails.statUserTime + rec.stepDetails.statSystemTime
4353                                + rec.stepDetails.statIOWaitTime + rec.stepDetails.statIrqTime
4354                                + rec.stepDetails.statSoftIrqTime;
4355                        int total = totalRun + rec.stepDetails.statIdlTime;
4356                        if (total > 0) {
4357                            pw.print(" (");
4358                            float perc = ((float)totalRun) / ((float)total) * 100;
4359                            pw.print(String.format("%.1f%%", perc));
4360                            pw.print(" of ");
4361                            StringBuilder sb = new StringBuilder(64);
4362                            formatTimeMsNoSpace(sb, total*10);
4363                            pw.print(sb);
4364                            pw.print(")");
4365                        }
4366                        pw.println();
4367                    } else {
4368                        pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
4369                        pw.print(HISTORY_DATA); pw.print(",0,Dcpu=");
4370                        pw.print(rec.stepDetails.userTime);
4371                        pw.print(":");
4372                        pw.print(rec.stepDetails.systemTime);
4373                        if (rec.stepDetails.appCpuUid1 >= 0) {
4374                            printStepCpuUidCheckinDetails(pw, rec.stepDetails.appCpuUid1,
4375                                    rec.stepDetails.appCpuUTime1, rec.stepDetails.appCpuSTime1);
4376                            if (rec.stepDetails.appCpuUid2 >= 0) {
4377                                printStepCpuUidCheckinDetails(pw, rec.stepDetails.appCpuUid2,
4378                                        rec.stepDetails.appCpuUTime2, rec.stepDetails.appCpuSTime2);
4379                            }
4380                            if (rec.stepDetails.appCpuUid3 >= 0) {
4381                                printStepCpuUidCheckinDetails(pw, rec.stepDetails.appCpuUid3,
4382                                        rec.stepDetails.appCpuUTime3, rec.stepDetails.appCpuSTime3);
4383                            }
4384                        }
4385                        pw.println();
4386                        pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
4387                        pw.print(HISTORY_DATA); pw.print(",0,Dpst=");
4388                        pw.print(rec.stepDetails.statUserTime);
4389                        pw.print(',');
4390                        pw.print(rec.stepDetails.statSystemTime);
4391                        pw.print(',');
4392                        pw.print(rec.stepDetails.statIOWaitTime);
4393                        pw.print(',');
4394                        pw.print(rec.stepDetails.statIrqTime);
4395                        pw.print(',');
4396                        pw.print(rec.stepDetails.statSoftIrqTime);
4397                        pw.print(',');
4398                        pw.print(rec.stepDetails.statIdlTime);
4399                        pw.println();
4400                    }
4401                }
4402                oldState = rec.states;
4403                oldState2 = rec.states2;
4404            }
4405        }
4406
4407        private void printStepCpuUidDetails(PrintWriter pw, int uid, int utime, int stime) {
4408            UserHandle.formatUid(pw, uid);
4409            pw.print("=");
4410            pw.print(utime);
4411            pw.print("u+");
4412            pw.print(stime);
4413            pw.print("s");
4414        }
4415
4416        private void printStepCpuUidCheckinDetails(PrintWriter pw, int uid, int utime, int stime) {
4417            pw.print('/');
4418            pw.print(uid);
4419            pw.print(":");
4420            pw.print(utime);
4421            pw.print(":");
4422            pw.print(stime);
4423        }
4424    }
4425
4426    private void printSizeValue(PrintWriter pw, long size) {
4427        float result = size;
4428        String suffix = "";
4429        if (result >= 10*1024) {
4430            suffix = "KB";
4431            result = result / 1024;
4432        }
4433        if (result >= 10*1024) {
4434            suffix = "MB";
4435            result = result / 1024;
4436        }
4437        if (result >= 10*1024) {
4438            suffix = "GB";
4439            result = result / 1024;
4440        }
4441        if (result >= 10*1024) {
4442            suffix = "TB";
4443            result = result / 1024;
4444        }
4445        if (result >= 10*1024) {
4446            suffix = "PB";
4447            result = result / 1024;
4448        }
4449        pw.print((int)result);
4450        pw.print(suffix);
4451    }
4452
4453    private static boolean dumpTimeEstimate(PrintWriter pw, String label1, String label2,
4454            String label3, long estimatedTime) {
4455        if (estimatedTime < 0) {
4456            return false;
4457        }
4458        pw.print(label1);
4459        pw.print(label2);
4460        pw.print(label3);
4461        StringBuilder sb = new StringBuilder(64);
4462        formatTimeMs(sb, estimatedTime);
4463        pw.print(sb);
4464        pw.println();
4465        return true;
4466    }
4467
4468    private static boolean dumpDurationSteps(PrintWriter pw, String prefix, String header,
4469            LevelStepTracker steps, boolean checkin) {
4470        if (steps == null) {
4471            return false;
4472        }
4473        int count = steps.mNumStepDurations;
4474        if (count <= 0) {
4475            return false;
4476        }
4477        if (!checkin) {
4478            pw.println(header);
4479        }
4480        String[] lineArgs = new String[5];
4481        for (int i=0; i<count; i++) {
4482            long duration = steps.getDurationAt(i);
4483            int level = steps.getLevelAt(i);
4484            long initMode = steps.getInitModeAt(i);
4485            long modMode = steps.getModModeAt(i);
4486            if (checkin) {
4487                lineArgs[0] = Long.toString(duration);
4488                lineArgs[1] = Integer.toString(level);
4489                if ((modMode&STEP_LEVEL_MODE_SCREEN_STATE) == 0) {
4490                    switch ((int)(initMode&STEP_LEVEL_MODE_SCREEN_STATE) + 1) {
4491                        case Display.STATE_OFF: lineArgs[2] = "s-"; break;
4492                        case Display.STATE_ON: lineArgs[2] = "s+"; break;
4493                        case Display.STATE_DOZE: lineArgs[2] = "sd"; break;
4494                        case Display.STATE_DOZE_SUSPEND: lineArgs[2] = "sds"; break;
4495                        default: lineArgs[2] = "?"; break;
4496                    }
4497                } else {
4498                    lineArgs[2] = "";
4499                }
4500                if ((modMode&STEP_LEVEL_MODE_POWER_SAVE) == 0) {
4501                    lineArgs[3] = (initMode&STEP_LEVEL_MODE_POWER_SAVE) != 0 ? "p+" : "p-";
4502                } else {
4503                    lineArgs[3] = "";
4504                }
4505                if ((modMode&STEP_LEVEL_MODE_DEVICE_IDLE) == 0) {
4506                    lineArgs[4] = (initMode&STEP_LEVEL_MODE_DEVICE_IDLE) != 0 ? "i+" : "i-";
4507                } else {
4508                    lineArgs[4] = "";
4509                }
4510                dumpLine(pw, 0 /* uid */, "i" /* category */, header, (Object[])lineArgs);
4511            } else {
4512                pw.print(prefix);
4513                pw.print("#"); pw.print(i); pw.print(": ");
4514                TimeUtils.formatDuration(duration, pw);
4515                pw.print(" to "); pw.print(level);
4516                boolean haveModes = false;
4517                if ((modMode&STEP_LEVEL_MODE_SCREEN_STATE) == 0) {
4518                    pw.print(" (");
4519                    switch ((int)(initMode&STEP_LEVEL_MODE_SCREEN_STATE) + 1) {
4520                        case Display.STATE_OFF: pw.print("screen-off"); break;
4521                        case Display.STATE_ON: pw.print("screen-on"); break;
4522                        case Display.STATE_DOZE: pw.print("screen-doze"); break;
4523                        case Display.STATE_DOZE_SUSPEND: pw.print("screen-doze-suspend"); break;
4524                        default: pw.print("screen-?"); break;
4525                    }
4526                    haveModes = true;
4527                }
4528                if ((modMode&STEP_LEVEL_MODE_POWER_SAVE) == 0) {
4529                    pw.print(haveModes ? ", " : " (");
4530                    pw.print((initMode&STEP_LEVEL_MODE_POWER_SAVE) != 0
4531                            ? "power-save-on" : "power-save-off");
4532                    haveModes = true;
4533                }
4534                if ((modMode&STEP_LEVEL_MODE_DEVICE_IDLE) == 0) {
4535                    pw.print(haveModes ? ", " : " (");
4536                    pw.print((initMode&STEP_LEVEL_MODE_DEVICE_IDLE) != 0
4537                            ? "device-idle-on" : "device-idle-off");
4538                    haveModes = true;
4539                }
4540                if (haveModes) {
4541                    pw.print(")");
4542                }
4543                pw.println();
4544            }
4545        }
4546        return true;
4547    }
4548
4549    public static final int DUMP_CHARGED_ONLY = 1<<1;
4550    public static final int DUMP_DAILY_ONLY = 1<<2;
4551    public static final int DUMP_HISTORY_ONLY = 1<<3;
4552    public static final int DUMP_INCLUDE_HISTORY = 1<<4;
4553    public static final int DUMP_VERBOSE = 1<<5;
4554    public static final int DUMP_DEVICE_WIFI_ONLY = 1<<6;
4555
4556    private void dumpHistoryLocked(PrintWriter pw, int flags, long histStart, boolean checkin) {
4557        final HistoryPrinter hprinter = new HistoryPrinter();
4558        final HistoryItem rec = new HistoryItem();
4559        long lastTime = -1;
4560        long baseTime = -1;
4561        boolean printed = false;
4562        HistoryEventTracker tracker = null;
4563        while (getNextHistoryLocked(rec)) {
4564            lastTime = rec.time;
4565            if (baseTime < 0) {
4566                baseTime = lastTime;
4567            }
4568            if (rec.time >= histStart) {
4569                if (histStart >= 0 && !printed) {
4570                    if (rec.cmd == HistoryItem.CMD_CURRENT_TIME
4571                            || rec.cmd == HistoryItem.CMD_RESET
4572                            || rec.cmd == HistoryItem.CMD_START
4573                            || rec.cmd == HistoryItem.CMD_SHUTDOWN) {
4574                        printed = true;
4575                        hprinter.printNextItem(pw, rec, baseTime, checkin,
4576                                (flags&DUMP_VERBOSE) != 0);
4577                        rec.cmd = HistoryItem.CMD_UPDATE;
4578                    } else if (rec.currentTime != 0) {
4579                        printed = true;
4580                        byte cmd = rec.cmd;
4581                        rec.cmd = HistoryItem.CMD_CURRENT_TIME;
4582                        hprinter.printNextItem(pw, rec, baseTime, checkin,
4583                                (flags&DUMP_VERBOSE) != 0);
4584                        rec.cmd = cmd;
4585                    }
4586                    if (tracker != null) {
4587                        if (rec.cmd != HistoryItem.CMD_UPDATE) {
4588                            hprinter.printNextItem(pw, rec, baseTime, checkin,
4589                                    (flags&DUMP_VERBOSE) != 0);
4590                            rec.cmd = HistoryItem.CMD_UPDATE;
4591                        }
4592                        int oldEventCode = rec.eventCode;
4593                        HistoryTag oldEventTag = rec.eventTag;
4594                        rec.eventTag = new HistoryTag();
4595                        for (int i=0; i<HistoryItem.EVENT_COUNT; i++) {
4596                            HashMap<String, SparseIntArray> active
4597                                    = tracker.getStateForEvent(i);
4598                            if (active == null) {
4599                                continue;
4600                            }
4601                            for (HashMap.Entry<String, SparseIntArray> ent
4602                                    : active.entrySet()) {
4603                                SparseIntArray uids = ent.getValue();
4604                                for (int j=0; j<uids.size(); j++) {
4605                                    rec.eventCode = i;
4606                                    rec.eventTag.string = ent.getKey();
4607                                    rec.eventTag.uid = uids.keyAt(j);
4608                                    rec.eventTag.poolIdx = uids.valueAt(j);
4609                                    hprinter.printNextItem(pw, rec, baseTime, checkin,
4610                                            (flags&DUMP_VERBOSE) != 0);
4611                                    rec.wakeReasonTag = null;
4612                                    rec.wakelockTag = null;
4613                                }
4614                            }
4615                        }
4616                        rec.eventCode = oldEventCode;
4617                        rec.eventTag = oldEventTag;
4618                        tracker = null;
4619                    }
4620                }
4621                hprinter.printNextItem(pw, rec, baseTime, checkin,
4622                        (flags&DUMP_VERBOSE) != 0);
4623            } else if (false && rec.eventCode != HistoryItem.EVENT_NONE) {
4624                // This is an attempt to aggregate the previous state and generate
4625                // fake events to reflect that state at the point where we start
4626                // printing real events.  It doesn't really work right, so is turned off.
4627                if (tracker == null) {
4628                    tracker = new HistoryEventTracker();
4629                }
4630                tracker.updateState(rec.eventCode, rec.eventTag.string,
4631                        rec.eventTag.uid, rec.eventTag.poolIdx);
4632            }
4633        }
4634        if (histStart >= 0) {
4635            commitCurrentHistoryBatchLocked();
4636            pw.print(checkin ? "NEXT: " : "  NEXT: "); pw.println(lastTime+1);
4637        }
4638    }
4639
4640    private void dumpDailyLevelStepSummary(PrintWriter pw, String prefix, String label,
4641            LevelStepTracker steps, StringBuilder tmpSb, int[] tmpOutInt) {
4642        if (steps == null) {
4643            return;
4644        }
4645        long timeRemaining = steps.computeTimeEstimate(0, 0, tmpOutInt);
4646        if (timeRemaining >= 0) {
4647            pw.print(prefix); pw.print(label); pw.print(" total time: ");
4648            tmpSb.setLength(0);
4649            formatTimeMs(tmpSb, timeRemaining);
4650            pw.print(tmpSb);
4651            pw.print(" (from "); pw.print(tmpOutInt[0]);
4652            pw.println(" steps)");
4653        }
4654        for (int i=0; i< STEP_LEVEL_MODES_OF_INTEREST.length; i++) {
4655            long estimatedTime = steps.computeTimeEstimate(STEP_LEVEL_MODES_OF_INTEREST[i],
4656                    STEP_LEVEL_MODE_VALUES[i], tmpOutInt);
4657            if (estimatedTime > 0) {
4658                pw.print(prefix); pw.print(label); pw.print(" ");
4659                pw.print(STEP_LEVEL_MODE_LABELS[i]);
4660                pw.print(" time: ");
4661                tmpSb.setLength(0);
4662                formatTimeMs(tmpSb, estimatedTime);
4663                pw.print(tmpSb);
4664                pw.print(" (from "); pw.print(tmpOutInt[0]);
4665                pw.println(" steps)");
4666            }
4667        }
4668    }
4669
4670    private void dumpDailyPackageChanges(PrintWriter pw, String prefix,
4671            ArrayList<PackageChange> changes) {
4672        if (changes == null) {
4673            return;
4674        }
4675        pw.print(prefix); pw.println("Package changes:");
4676        for (int i=0; i<changes.size(); i++) {
4677            PackageChange pc = changes.get(i);
4678            if (pc.mUpdate) {
4679                pw.print(prefix); pw.print("  Update "); pw.print(pc.mPackageName);
4680                pw.print(" vers="); pw.println(pc.mVersionCode);
4681            } else {
4682                pw.print(prefix); pw.print("  Uninstall "); pw.println(pc.mPackageName);
4683            }
4684        }
4685    }
4686
4687    /**
4688     * Dumps a human-readable summary of the battery statistics to the given PrintWriter.
4689     *
4690     * @param pw a Printer to receive the dump output.
4691     */
4692    @SuppressWarnings("unused")
4693    public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
4694        prepareForDumpLocked();
4695
4696        final boolean filtering = (flags
4697                & (DUMP_HISTORY_ONLY|DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) != 0;
4698
4699        if ((flags&DUMP_HISTORY_ONLY) != 0 || !filtering) {
4700            final long historyTotalSize = getHistoryTotalSize();
4701            final long historyUsedSize = getHistoryUsedSize();
4702            if (startIteratingHistoryLocked()) {
4703                try {
4704                    pw.print("Battery History (");
4705                    pw.print((100*historyUsedSize)/historyTotalSize);
4706                    pw.print("% used, ");
4707                    printSizeValue(pw, historyUsedSize);
4708                    pw.print(" used of ");
4709                    printSizeValue(pw, historyTotalSize);
4710                    pw.print(", ");
4711                    pw.print(getHistoryStringPoolSize());
4712                    pw.print(" strings using ");
4713                    printSizeValue(pw, getHistoryStringPoolBytes());
4714                    pw.println("):");
4715                    dumpHistoryLocked(pw, flags, histStart, false);
4716                    pw.println();
4717                } finally {
4718                    finishIteratingHistoryLocked();
4719                }
4720            }
4721
4722            if (startIteratingOldHistoryLocked()) {
4723                try {
4724                    final HistoryItem rec = new HistoryItem();
4725                    pw.println("Old battery History:");
4726                    HistoryPrinter hprinter = new HistoryPrinter();
4727                    long baseTime = -1;
4728                    while (getNextOldHistoryLocked(rec)) {
4729                        if (baseTime < 0) {
4730                            baseTime = rec.time;
4731                        }
4732                        hprinter.printNextItem(pw, rec, baseTime, false, (flags&DUMP_VERBOSE) != 0);
4733                    }
4734                    pw.println();
4735                } finally {
4736                    finishIteratingOldHistoryLocked();
4737                }
4738            }
4739        }
4740
4741        if (filtering && (flags&(DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) == 0) {
4742            return;
4743        }
4744
4745        if (!filtering) {
4746            SparseArray<? extends Uid> uidStats = getUidStats();
4747            final int NU = uidStats.size();
4748            boolean didPid = false;
4749            long nowRealtime = SystemClock.elapsedRealtime();
4750            for (int i=0; i<NU; i++) {
4751                Uid uid = uidStats.valueAt(i);
4752                SparseArray<? extends Uid.Pid> pids = uid.getPidStats();
4753                if (pids != null) {
4754                    for (int j=0; j<pids.size(); j++) {
4755                        Uid.Pid pid = pids.valueAt(j);
4756                        if (!didPid) {
4757                            pw.println("Per-PID Stats:");
4758                            didPid = true;
4759                        }
4760                        long time = pid.mWakeSumMs + (pid.mWakeNesting > 0
4761                                ? (nowRealtime - pid.mWakeStartMs) : 0);
4762                        pw.print("  PID "); pw.print(pids.keyAt(j));
4763                                pw.print(" wake time: ");
4764                                TimeUtils.formatDuration(time, pw);
4765                                pw.println("");
4766                    }
4767                }
4768            }
4769            if (didPid) {
4770                pw.println();
4771            }
4772        }
4773
4774        if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
4775            if (dumpDurationSteps(pw, "  ", "Discharge step durations:",
4776                    getDischargeLevelStepTracker(), false)) {
4777                long timeRemaining = computeBatteryTimeRemaining(SystemClock.elapsedRealtime());
4778                if (timeRemaining >= 0) {
4779                    pw.print("  Estimated discharge time remaining: ");
4780                    TimeUtils.formatDuration(timeRemaining / 1000, pw);
4781                    pw.println();
4782                }
4783                final LevelStepTracker steps = getDischargeLevelStepTracker();
4784                for (int i=0; i< STEP_LEVEL_MODES_OF_INTEREST.length; i++) {
4785                    dumpTimeEstimate(pw, "  Estimated ", STEP_LEVEL_MODE_LABELS[i], " time: ",
4786                            steps.computeTimeEstimate(STEP_LEVEL_MODES_OF_INTEREST[i],
4787                                    STEP_LEVEL_MODE_VALUES[i], null));
4788                }
4789                pw.println();
4790            }
4791            if (dumpDurationSteps(pw, "  ", "Charge step durations:",
4792                    getChargeLevelStepTracker(), false)) {
4793                long timeRemaining = computeChargeTimeRemaining(SystemClock.elapsedRealtime());
4794                if (timeRemaining >= 0) {
4795                    pw.print("  Estimated charge time remaining: ");
4796                    TimeUtils.formatDuration(timeRemaining / 1000, pw);
4797                    pw.println();
4798                }
4799                pw.println();
4800            }
4801        }
4802        if (!filtering || (flags&(DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) != 0) {
4803            pw.println("Daily stats:");
4804            pw.print("  Current start time: ");
4805            pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss",
4806                    getCurrentDailyStartTime()).toString());
4807            pw.print("  Next min deadline: ");
4808            pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss",
4809                    getNextMinDailyDeadline()).toString());
4810            pw.print("  Next max deadline: ");
4811            pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss",
4812                    getNextMaxDailyDeadline()).toString());
4813            StringBuilder sb = new StringBuilder(64);
4814            int[] outInt = new int[1];
4815            LevelStepTracker dsteps = getDailyDischargeLevelStepTracker();
4816            LevelStepTracker csteps = getDailyChargeLevelStepTracker();
4817            ArrayList<PackageChange> pkgc = getDailyPackageChanges();
4818            if (dsteps.mNumStepDurations > 0 || csteps.mNumStepDurations > 0 || pkgc != null) {
4819                if ((flags&DUMP_DAILY_ONLY) != 0 || !filtering) {
4820                    if (dumpDurationSteps(pw, "    ", "  Current daily discharge step durations:",
4821                            dsteps, false)) {
4822                        dumpDailyLevelStepSummary(pw, "      ", "Discharge", dsteps,
4823                                sb, outInt);
4824                    }
4825                    if (dumpDurationSteps(pw, "    ", "  Current daily charge step durations:",
4826                            csteps, false)) {
4827                        dumpDailyLevelStepSummary(pw, "      ", "Charge", csteps,
4828                                sb, outInt);
4829                    }
4830                    dumpDailyPackageChanges(pw, "    ", pkgc);
4831                } else {
4832                    pw.println("  Current daily steps:");
4833                    dumpDailyLevelStepSummary(pw, "    ", "Discharge", dsteps,
4834                            sb, outInt);
4835                    dumpDailyLevelStepSummary(pw, "    ", "Charge", csteps,
4836                            sb, outInt);
4837                }
4838            }
4839            DailyItem dit;
4840            int curIndex = 0;
4841            while ((dit=getDailyItemLocked(curIndex)) != null) {
4842                curIndex++;
4843                if ((flags&DUMP_DAILY_ONLY) != 0) {
4844                    pw.println();
4845                }
4846                pw.print("  Daily from ");
4847                pw.print(DateFormat.format("yyyy-MM-dd-HH-mm-ss", dit.mStartTime).toString());
4848                pw.print(" to ");
4849                pw.print(DateFormat.format("yyyy-MM-dd-HH-mm-ss", dit.mEndTime).toString());
4850                pw.println(":");
4851                if ((flags&DUMP_DAILY_ONLY) != 0 || !filtering) {
4852                    if (dumpDurationSteps(pw, "      ",
4853                            "    Discharge step durations:", dit.mDischargeSteps, false)) {
4854                        dumpDailyLevelStepSummary(pw, "        ", "Discharge", dit.mDischargeSteps,
4855                                sb, outInt);
4856                    }
4857                    if (dumpDurationSteps(pw, "      ",
4858                            "    Charge step durations:", dit.mChargeSteps, false)) {
4859                        dumpDailyLevelStepSummary(pw, "        ", "Charge", dit.mChargeSteps,
4860                                sb, outInt);
4861                    }
4862                    dumpDailyPackageChanges(pw, "    ", dit.mPackageChanges);
4863                } else {
4864                    dumpDailyLevelStepSummary(pw, "    ", "Discharge", dit.mDischargeSteps,
4865                            sb, outInt);
4866                    dumpDailyLevelStepSummary(pw, "    ", "Charge", dit.mChargeSteps,
4867                            sb, outInt);
4868                }
4869            }
4870            pw.println();
4871        }
4872        if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
4873            pw.println("Statistics since last charge:");
4874            pw.println("  System starts: " + getStartCount()
4875                    + ", currently on battery: " + getIsOnBattery());
4876            dumpLocked(context, pw, "", STATS_SINCE_CHARGED, reqUid,
4877                    (flags&DUMP_DEVICE_WIFI_ONLY) != 0);
4878            pw.println();
4879        }
4880    }
4881
4882    @SuppressWarnings("unused")
4883    public void dumpCheckinLocked(Context context, PrintWriter pw,
4884            List<ApplicationInfo> apps, int flags, long histStart) {
4885        prepareForDumpLocked();
4886
4887        dumpLine(pw, 0 /* uid */, "i" /* category */, VERSION_DATA,
4888                CHECKIN_VERSION, getParcelVersion(), getStartPlatformVersion(),
4889                getEndPlatformVersion());
4890
4891        long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
4892
4893        final boolean filtering = (flags &
4894                (DUMP_HISTORY_ONLY|DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) != 0;
4895
4896        if ((flags&DUMP_INCLUDE_HISTORY) != 0 || (flags&DUMP_HISTORY_ONLY) != 0) {
4897            if (startIteratingHistoryLocked()) {
4898                try {
4899                    for (int i=0; i<getHistoryStringPoolSize(); i++) {
4900                        pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
4901                        pw.print(HISTORY_STRING_POOL); pw.print(',');
4902                        pw.print(i);
4903                        pw.print(",");
4904                        pw.print(getHistoryTagPoolUid(i));
4905                        pw.print(",\"");
4906                        String str = getHistoryTagPoolString(i);
4907                        str = str.replace("\\", "\\\\");
4908                        str = str.replace("\"", "\\\"");
4909                        pw.print(str);
4910                        pw.print("\"");
4911                        pw.println();
4912                    }
4913                    dumpHistoryLocked(pw, flags, histStart, true);
4914                } finally {
4915                    finishIteratingHistoryLocked();
4916                }
4917            }
4918        }
4919
4920        if (filtering && (flags&(DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) == 0) {
4921            return;
4922        }
4923
4924        if (apps != null) {
4925            SparseArray<ArrayList<String>> uids = new SparseArray<ArrayList<String>>();
4926            for (int i=0; i<apps.size(); i++) {
4927                ApplicationInfo ai = apps.get(i);
4928                ArrayList<String> pkgs = uids.get(ai.uid);
4929                if (pkgs == null) {
4930                    pkgs = new ArrayList<String>();
4931                    uids.put(ai.uid, pkgs);
4932                }
4933                pkgs.add(ai.packageName);
4934            }
4935            SparseArray<? extends Uid> uidStats = getUidStats();
4936            final int NU = uidStats.size();
4937            String[] lineArgs = new String[2];
4938            for (int i=0; i<NU; i++) {
4939                int uid = uidStats.keyAt(i);
4940                ArrayList<String> pkgs = uids.get(uid);
4941                if (pkgs != null) {
4942                    for (int j=0; j<pkgs.size(); j++) {
4943                        lineArgs[0] = Integer.toString(uid);
4944                        lineArgs[1] = pkgs.get(j);
4945                        dumpLine(pw, 0 /* uid */, "i" /* category */, UID_DATA,
4946                                (Object[])lineArgs);
4947                    }
4948                }
4949            }
4950        }
4951        if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
4952            dumpDurationSteps(pw, "", DISCHARGE_STEP_DATA, getDischargeLevelStepTracker(), true);
4953            String[] lineArgs = new String[1];
4954            long timeRemaining = computeBatteryTimeRemaining(SystemClock.elapsedRealtime());
4955            if (timeRemaining >= 0) {
4956                lineArgs[0] = Long.toString(timeRemaining);
4957                dumpLine(pw, 0 /* uid */, "i" /* category */, DISCHARGE_TIME_REMAIN_DATA,
4958                        (Object[])lineArgs);
4959            }
4960            dumpDurationSteps(pw, "", CHARGE_STEP_DATA, getChargeLevelStepTracker(), true);
4961            timeRemaining = computeChargeTimeRemaining(SystemClock.elapsedRealtime());
4962            if (timeRemaining >= 0) {
4963                lineArgs[0] = Long.toString(timeRemaining);
4964                dumpLine(pw, 0 /* uid */, "i" /* category */, CHARGE_TIME_REMAIN_DATA,
4965                        (Object[])lineArgs);
4966            }
4967            dumpCheckinLocked(context, pw, STATS_SINCE_CHARGED, -1,
4968                    (flags&DUMP_DEVICE_WIFI_ONLY) != 0);
4969        }
4970    }
4971}
4972