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