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