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