BatteryStats.java revision 094c40b2cc70fefb29771fb90d7ea7437905b3a5
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 = "18";
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                dischargeCount / 1000, dischargeScreenOffCount / 1000);
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        } else {
2992            dumpLine(pw, 0 /* uid */, category, BATTERY_DISCHARGE_DATA,
2993                    getLowDischargeAmountSinceCharge(), getHighDischargeAmountSinceCharge(),
2994                    getDischargeAmountScreenOnSinceCharge(),
2995                    getDischargeAmountScreenOffSinceCharge());
2996        }
2997
2998        if (reqUid < 0) {
2999            final Map<String, ? extends Timer> kernelWakelocks = getKernelWakelockStats();
3000            if (kernelWakelocks.size() > 0) {
3001                for (Map.Entry<String, ? extends Timer> ent : kernelWakelocks.entrySet()) {
3002                    sb.setLength(0);
3003                    printWakeLockCheckin(sb, ent.getValue(), rawRealtime, null, which, "");
3004                    dumpLine(pw, 0 /* uid */, category, KERNEL_WAKELOCK_DATA, ent.getKey(),
3005                            sb.toString());
3006                }
3007            }
3008            final Map<String, ? extends Timer> wakeupReasons = getWakeupReasonStats();
3009            if (wakeupReasons.size() > 0) {
3010                for (Map.Entry<String, ? extends Timer> ent : wakeupReasons.entrySet()) {
3011                    // Not doing the regular wake lock formatting to remain compatible
3012                    // with the old checkin format.
3013                    long totalTimeMicros = ent.getValue().getTotalTimeLocked(rawRealtime, which);
3014                    int count = ent.getValue().getCountLocked(which);
3015                    dumpLine(pw, 0 /* uid */, category, WAKEUP_REASON_DATA,
3016                            "\"" + ent.getKey() + "\"", (totalTimeMicros + 500) / 1000, count);
3017                }
3018            }
3019        }
3020
3021        final BatteryStatsHelper helper = new BatteryStatsHelper(context, false, wifiOnly);
3022        helper.create(this);
3023        helper.refreshStats(which, UserHandle.USER_ALL);
3024        final List<BatterySipper> sippers = helper.getUsageList();
3025        if (sippers != null && sippers.size() > 0) {
3026            dumpLine(pw, 0 /* uid */, category, POWER_USE_SUMMARY_DATA,
3027                    BatteryStatsHelper.makemAh(helper.getPowerProfile().getBatteryCapacity()),
3028                    BatteryStatsHelper.makemAh(helper.getComputedPower()),
3029                    BatteryStatsHelper.makemAh(helper.getMinDrainedPower()),
3030                    BatteryStatsHelper.makemAh(helper.getMaxDrainedPower()));
3031            for (int i=0; i<sippers.size(); i++) {
3032                final BatterySipper bs = sippers.get(i);
3033                int uid = 0;
3034                String label;
3035                switch (bs.drainType) {
3036                    case IDLE:
3037                        label="idle";
3038                        break;
3039                    case CELL:
3040                        label="cell";
3041                        break;
3042                    case PHONE:
3043                        label="phone";
3044                        break;
3045                    case WIFI:
3046                        label="wifi";
3047                        break;
3048                    case BLUETOOTH:
3049                        label="blue";
3050                        break;
3051                    case SCREEN:
3052                        label="scrn";
3053                        break;
3054                    case FLASHLIGHT:
3055                        label="flashlight";
3056                        break;
3057                    case APP:
3058                        uid = bs.uidObj.getUid();
3059                        label = "uid";
3060                        break;
3061                    case USER:
3062                        uid = UserHandle.getUid(bs.userId, 0);
3063                        label = "user";
3064                        break;
3065                    case UNACCOUNTED:
3066                        label = "unacc";
3067                        break;
3068                    case OVERCOUNTED:
3069                        label = "over";
3070                        break;
3071                    case CAMERA:
3072                        label = "camera";
3073                        break;
3074                    default:
3075                        label = "???";
3076                }
3077                dumpLine(pw, uid, category, POWER_USE_ITEM_DATA, label,
3078                        BatteryStatsHelper.makemAh(bs.totalPowerMah));
3079            }
3080        }
3081
3082        for (int iu = 0; iu < NU; iu++) {
3083            final int uid = uidStats.keyAt(iu);
3084            if (reqUid >= 0 && uid != reqUid) {
3085                continue;
3086            }
3087            final Uid u = uidStats.valueAt(iu);
3088
3089            // Dump Network stats per uid, if any
3090            final long mobileBytesRx = u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
3091            final long mobileBytesTx = u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
3092            final long wifiBytesRx = u.getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
3093            final long wifiBytesTx = u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
3094            final long mobilePacketsRx = u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
3095            final long mobilePacketsTx = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
3096            final long mobileActiveTime = u.getMobileRadioActiveTime(which);
3097            final int mobileActiveCount = u.getMobileRadioActiveCount(which);
3098            final long wifiPacketsRx = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
3099            final long wifiPacketsTx = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
3100            final long btBytesRx = u.getNetworkActivityBytes(NETWORK_BT_RX_DATA, which);
3101            final long btBytesTx = u.getNetworkActivityBytes(NETWORK_BT_TX_DATA, which);
3102            if (mobileBytesRx > 0 || mobileBytesTx > 0 || wifiBytesRx > 0 || wifiBytesTx > 0
3103                    || mobilePacketsRx > 0 || mobilePacketsTx > 0 || wifiPacketsRx > 0
3104                    || wifiPacketsTx > 0 || mobileActiveTime > 0 || mobileActiveCount > 0
3105                    || btBytesRx > 0 || btBytesTx > 0) {
3106                dumpLine(pw, uid, category, NETWORK_DATA, mobileBytesRx, mobileBytesTx,
3107                        wifiBytesRx, wifiBytesTx,
3108                        mobilePacketsRx, mobilePacketsTx,
3109                        wifiPacketsRx, wifiPacketsTx,
3110                        mobileActiveTime, mobileActiveCount,
3111                        btBytesRx, btBytesTx);
3112            }
3113
3114            // Dump modem controller data, per UID.
3115            dumpControllerActivityLine(pw, uid, category, MODEM_CONTROLLER_DATA,
3116                    u.getModemControllerActivity(), which);
3117
3118            // Dump Wifi controller data, per UID.
3119            final long fullWifiLockOnTime = u.getFullWifiLockTime(rawRealtime, which);
3120            final long wifiScanTime = u.getWifiScanTime(rawRealtime, which);
3121            final int wifiScanCount = u.getWifiScanCount(which);
3122            final long uidWifiRunningTime = u.getWifiRunningTime(rawRealtime, which);
3123            if (fullWifiLockOnTime != 0 || wifiScanTime != 0 || wifiScanCount != 0
3124                    || uidWifiRunningTime != 0) {
3125                dumpLine(pw, uid, category, WIFI_DATA, fullWifiLockOnTime, wifiScanTime,
3126                        uidWifiRunningTime, wifiScanCount,
3127                        /* legacy fields follow, keep at 0 */ 0, 0, 0);
3128            }
3129
3130            dumpControllerActivityLine(pw, uid, category, WIFI_CONTROLLER_DATA,
3131                    u.getWifiControllerActivity(), which);
3132
3133            dumpTimer(pw, uid, category, BLUETOOTH_MISC_DATA, u.getBluetoothScanTimer(),
3134                    rawRealtime, which);
3135
3136            dumpControllerActivityLine(pw, uid, category, BLUETOOTH_CONTROLLER_DATA,
3137                    u.getBluetoothControllerActivity(), which);
3138
3139            if (u.hasUserActivity()) {
3140                args = new Object[Uid.NUM_USER_ACTIVITY_TYPES];
3141                boolean hasData = false;
3142                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
3143                    int val = u.getUserActivityCount(i, which);
3144                    args[i] = val;
3145                    if (val != 0) hasData = true;
3146                }
3147                if (hasData) {
3148                    dumpLine(pw, uid /* uid */, category, USER_ACTIVITY_DATA, args);
3149                }
3150            }
3151
3152            final ArrayMap<String, ? extends Uid.Wakelock> wakelocks = u.getWakelockStats();
3153            for (int iw=wakelocks.size()-1; iw>=0; iw--) {
3154                final Uid.Wakelock wl = wakelocks.valueAt(iw);
3155                String linePrefix = "";
3156                sb.setLength(0);
3157                linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_FULL),
3158                        rawRealtime, "f", which, linePrefix);
3159                linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL),
3160                        rawRealtime, "p", which, linePrefix);
3161                linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_WINDOW),
3162                        rawRealtime, "w", which, linePrefix);
3163
3164                // Only log if we had at lease one wakelock...
3165                if (sb.length() > 0) {
3166                    String name = wakelocks.keyAt(iw);
3167                    if (name.indexOf(',') >= 0) {
3168                        name = name.replace(',', '_');
3169                    }
3170                    dumpLine(pw, uid, category, WAKELOCK_DATA, name, sb.toString());
3171                }
3172            }
3173
3174            final ArrayMap<String, ? extends Timer> syncs = u.getSyncStats();
3175            for (int isy=syncs.size()-1; isy>=0; isy--) {
3176                final Timer timer = syncs.valueAt(isy);
3177                // Convert from microseconds to milliseconds with rounding
3178                final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
3179                final int count = timer.getCountLocked(which);
3180                if (totalTime != 0) {
3181                    dumpLine(pw, uid, category, SYNC_DATA, syncs.keyAt(isy), totalTime, count);
3182                }
3183            }
3184
3185            final ArrayMap<String, ? extends Timer> jobs = u.getJobStats();
3186            for (int ij=jobs.size()-1; ij>=0; ij--) {
3187                final Timer timer = jobs.valueAt(ij);
3188                // Convert from microseconds to milliseconds with rounding
3189                final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
3190                final int count = timer.getCountLocked(which);
3191                if (totalTime != 0) {
3192                    dumpLine(pw, uid, category, JOB_DATA, jobs.keyAt(ij), totalTime, count);
3193                }
3194            }
3195
3196            dumpTimer(pw, uid, category, FLASHLIGHT_DATA, u.getFlashlightTurnedOnTimer(),
3197                    rawRealtime, which);
3198            dumpTimer(pw, uid, category, CAMERA_DATA, u.getCameraTurnedOnTimer(),
3199                    rawRealtime, which);
3200            dumpTimer(pw, uid, category, VIDEO_DATA, u.getVideoTurnedOnTimer(),
3201                    rawRealtime, which);
3202            dumpTimer(pw, uid, category, AUDIO_DATA, u.getAudioTurnedOnTimer(),
3203                    rawRealtime, which);
3204
3205            final SparseArray<? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
3206            final int NSE = sensors.size();
3207            for (int ise=0; ise<NSE; ise++) {
3208                final Uid.Sensor se = sensors.valueAt(ise);
3209                final int sensorNumber = sensors.keyAt(ise);
3210                final Timer timer = se.getSensorTime();
3211                if (timer != null) {
3212                    // Convert from microseconds to milliseconds with rounding
3213                    final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500)
3214                            / 1000;
3215                    final int count = timer.getCountLocked(which);
3216                    if (totalTime != 0) {
3217                        dumpLine(pw, uid, category, SENSOR_DATA, sensorNumber, totalTime, count);
3218                    }
3219                }
3220            }
3221
3222            dumpTimer(pw, uid, category, VIBRATOR_DATA, u.getVibratorOnTimer(),
3223                    rawRealtime, which);
3224
3225            dumpTimer(pw, uid, category, FOREGROUND_DATA, u.getForegroundActivityTimer(),
3226                    rawRealtime, which);
3227
3228            final Object[] stateTimes = new Object[Uid.NUM_PROCESS_STATE];
3229            long totalStateTime = 0;
3230            for (int ips=0; ips<Uid.NUM_PROCESS_STATE; ips++) {
3231                final long time = u.getProcessStateTime(ips, rawRealtime, which);
3232                totalStateTime += time;
3233                stateTimes[ips] = (time + 500) / 1000;
3234            }
3235            if (totalStateTime > 0) {
3236                dumpLine(pw, uid, category, STATE_TIME_DATA, stateTimes);
3237            }
3238
3239            final long userCpuTimeUs = u.getUserCpuTimeUs(which);
3240            final long systemCpuTimeUs = u.getSystemCpuTimeUs(which);
3241            final long powerCpuMaUs = u.getCpuPowerMaUs(which);
3242            if (userCpuTimeUs > 0 || systemCpuTimeUs > 0 || powerCpuMaUs > 0) {
3243                dumpLine(pw, uid, category, CPU_DATA, userCpuTimeUs / 1000, systemCpuTimeUs / 1000,
3244                        powerCpuMaUs / 1000);
3245            }
3246
3247            final ArrayMap<String, ? extends BatteryStats.Uid.Proc> processStats
3248                    = u.getProcessStats();
3249            for (int ipr=processStats.size()-1; ipr>=0; ipr--) {
3250                final Uid.Proc ps = processStats.valueAt(ipr);
3251
3252                final long userMillis = ps.getUserTime(which);
3253                final long systemMillis = ps.getSystemTime(which);
3254                final long foregroundMillis = ps.getForegroundTime(which);
3255                final int starts = ps.getStarts(which);
3256                final int numCrashes = ps.getNumCrashes(which);
3257                final int numAnrs = ps.getNumAnrs(which);
3258
3259                if (userMillis != 0 || systemMillis != 0 || foregroundMillis != 0
3260                        || starts != 0 || numAnrs != 0 || numCrashes != 0) {
3261                    dumpLine(pw, uid, category, PROCESS_DATA, processStats.keyAt(ipr), userMillis,
3262                            systemMillis, foregroundMillis, starts, numAnrs, numCrashes);
3263                }
3264            }
3265
3266            final ArrayMap<String, ? extends BatteryStats.Uid.Pkg> packageStats
3267                    = u.getPackageStats();
3268            for (int ipkg=packageStats.size()-1; ipkg>=0; ipkg--) {
3269                final Uid.Pkg ps = packageStats.valueAt(ipkg);
3270                int wakeups = 0;
3271                final ArrayMap<String, ? extends Counter> alarms = ps.getWakeupAlarmStats();
3272                for (int iwa=alarms.size()-1; iwa>=0; iwa--) {
3273                    int count = alarms.valueAt(iwa).getCountLocked(which);
3274                    wakeups += count;
3275                    String name = alarms.keyAt(iwa).replace(',', '_');
3276                    dumpLine(pw, uid, category, WAKEUP_ALARM_DATA, name, count);
3277                }
3278                final ArrayMap<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
3279                for (int isvc=serviceStats.size()-1; isvc>=0; isvc--) {
3280                    final BatteryStats.Uid.Pkg.Serv ss = serviceStats.valueAt(isvc);
3281                    final long startTime = ss.getStartTime(batteryUptime, which);
3282                    final int starts = ss.getStarts(which);
3283                    final int launches = ss.getLaunches(which);
3284                    if (startTime != 0 || starts != 0 || launches != 0) {
3285                        dumpLine(pw, uid, category, APK_DATA,
3286                                wakeups, // wakeup alarms
3287                                packageStats.keyAt(ipkg), // Apk
3288                                serviceStats.keyAt(isvc), // service
3289                                startTime / 1000, // time spent started, in ms
3290                                starts,
3291                                launches);
3292                    }
3293                }
3294            }
3295        }
3296    }
3297
3298    static final class TimerEntry {
3299        final String mName;
3300        final int mId;
3301        final BatteryStats.Timer mTimer;
3302        final long mTime;
3303        TimerEntry(String name, int id, BatteryStats.Timer timer, long time) {
3304            mName = name;
3305            mId = id;
3306            mTimer = timer;
3307            mTime = time;
3308        }
3309    }
3310
3311    private void printmAh(PrintWriter printer, double power) {
3312        printer.print(BatteryStatsHelper.makemAh(power));
3313    }
3314
3315    private void printmAh(StringBuilder sb, double power) {
3316        sb.append(BatteryStatsHelper.makemAh(power));
3317    }
3318
3319    /**
3320     * Temporary for settings.
3321     */
3322    public final void dumpLocked(Context context, PrintWriter pw, String prefix, int which,
3323            int reqUid) {
3324        dumpLocked(context, pw, prefix, which, reqUid, BatteryStatsHelper.checkWifiOnly(context));
3325    }
3326
3327    @SuppressWarnings("unused")
3328    public final void dumpLocked(Context context, PrintWriter pw, String prefix, final int which,
3329            int reqUid, boolean wifiOnly) {
3330        final long rawUptime = SystemClock.uptimeMillis() * 1000;
3331        final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
3332        final long batteryUptime = getBatteryUptime(rawUptime);
3333
3334        final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
3335        final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
3336        final long totalRealtime = computeRealtime(rawRealtime, which);
3337        final long totalUptime = computeUptime(rawUptime, which);
3338        final long whichBatteryScreenOffUptime = computeBatteryScreenOffUptime(rawUptime, which);
3339        final long whichBatteryScreenOffRealtime = computeBatteryScreenOffRealtime(rawRealtime,
3340                which);
3341        final long batteryTimeRemaining = computeBatteryTimeRemaining(rawRealtime);
3342        final long chargeTimeRemaining = computeChargeTimeRemaining(rawRealtime);
3343
3344        final StringBuilder sb = new StringBuilder(128);
3345
3346        final SparseArray<? extends Uid> uidStats = getUidStats();
3347        final int NU = uidStats.size();
3348
3349        sb.setLength(0);
3350        sb.append(prefix);
3351                sb.append("  Time on battery: ");
3352                formatTimeMs(sb, whichBatteryRealtime / 1000); sb.append("(");
3353                sb.append(formatRatioLocked(whichBatteryRealtime, totalRealtime));
3354                sb.append(") realtime, ");
3355                formatTimeMs(sb, whichBatteryUptime / 1000);
3356                sb.append("("); sb.append(formatRatioLocked(whichBatteryUptime, totalRealtime));
3357                sb.append(") uptime");
3358        pw.println(sb.toString());
3359        sb.setLength(0);
3360        sb.append(prefix);
3361                sb.append("  Time on battery screen off: ");
3362                formatTimeMs(sb, whichBatteryScreenOffRealtime / 1000); sb.append("(");
3363                sb.append(formatRatioLocked(whichBatteryScreenOffRealtime, totalRealtime));
3364                sb.append(") realtime, ");
3365                formatTimeMs(sb, whichBatteryScreenOffUptime / 1000);
3366                sb.append("(");
3367                sb.append(formatRatioLocked(whichBatteryScreenOffUptime, totalRealtime));
3368                sb.append(") uptime");
3369        pw.println(sb.toString());
3370        sb.setLength(0);
3371        sb.append(prefix);
3372                sb.append("  Total run time: ");
3373                formatTimeMs(sb, totalRealtime / 1000);
3374                sb.append("realtime, ");
3375                formatTimeMs(sb, totalUptime / 1000);
3376                sb.append("uptime");
3377        pw.println(sb.toString());
3378        if (batteryTimeRemaining >= 0) {
3379            sb.setLength(0);
3380            sb.append(prefix);
3381                    sb.append("  Battery time remaining: ");
3382                    formatTimeMs(sb, batteryTimeRemaining / 1000);
3383            pw.println(sb.toString());
3384        }
3385        if (chargeTimeRemaining >= 0) {
3386            sb.setLength(0);
3387            sb.append(prefix);
3388                    sb.append("  Charge time remaining: ");
3389                    formatTimeMs(sb, chargeTimeRemaining / 1000);
3390            pw.println(sb.toString());
3391        }
3392
3393        final LongCounter dischargeCounter = getDischargeCoulombCounter();
3394        final long dischargeCount = dischargeCounter.getCountLocked(which);
3395        if (dischargeCount >= 0) {
3396            sb.setLength(0);
3397            sb.append(prefix);
3398                sb.append("  Discharge: ");
3399                sb.append(BatteryStatsHelper.makemAh(dischargeCount / 1000.0));
3400                sb.append(" mAh");
3401            pw.println(sb.toString());
3402        }
3403
3404        final LongCounter dischargeScreenOffCounter = getDischargeScreenOffCoulombCounter();
3405        final long dischargeScreenOffCount = dischargeScreenOffCounter.getCountLocked(which);
3406        if (dischargeScreenOffCount >= 0) {
3407            sb.setLength(0);
3408            sb.append(prefix);
3409                sb.append("  Screen off discharge: ");
3410                sb.append(BatteryStatsHelper.makemAh(dischargeScreenOffCount / 1000.0));
3411                sb.append(" mAh");
3412            pw.println(sb.toString());
3413        }
3414
3415        final long dischargeScreenOnCount = dischargeCount - dischargeScreenOffCount;
3416        if (dischargeScreenOnCount >= 0) {
3417            sb.setLength(0);
3418            sb.append(prefix);
3419                sb.append("  Screen on discharge: ");
3420                sb.append(BatteryStatsHelper.makemAh(dischargeScreenOnCount / 1000.0));
3421                sb.append(" mAh");
3422            pw.println(sb.toString());
3423        }
3424
3425        pw.print("  Start clock time: ");
3426        pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss", getStartClockTime()).toString());
3427
3428        final long screenOnTime = getScreenOnTime(rawRealtime, which);
3429        final long interactiveTime = getInteractiveTime(rawRealtime, which);
3430        final long powerSaveModeEnabledTime = getPowerSaveModeEnabledTime(rawRealtime, which);
3431        final long deviceIdleModeLightTime = getDeviceIdleModeTime(DEVICE_IDLE_MODE_LIGHT,
3432                rawRealtime, which);
3433        final long deviceIdleModeFullTime = getDeviceIdleModeTime(DEVICE_IDLE_MODE_DEEP,
3434                rawRealtime, which);
3435        final long deviceLightIdlingTime = getDeviceIdlingTime(DEVICE_IDLE_MODE_LIGHT,
3436                rawRealtime, which);
3437        final long deviceIdlingTime = getDeviceIdlingTime(DEVICE_IDLE_MODE_DEEP,
3438                rawRealtime, which);
3439        final long phoneOnTime = getPhoneOnTime(rawRealtime, which);
3440        final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which);
3441        final long wifiOnTime = getWifiOnTime(rawRealtime, which);
3442        sb.setLength(0);
3443        sb.append(prefix);
3444                sb.append("  Screen on: "); formatTimeMs(sb, screenOnTime / 1000);
3445                sb.append("("); sb.append(formatRatioLocked(screenOnTime, whichBatteryRealtime));
3446                sb.append(") "); sb.append(getScreenOnCount(which));
3447                sb.append("x, Interactive: "); formatTimeMs(sb, interactiveTime / 1000);
3448                sb.append("("); sb.append(formatRatioLocked(interactiveTime, whichBatteryRealtime));
3449                sb.append(")");
3450        pw.println(sb.toString());
3451        sb.setLength(0);
3452        sb.append(prefix);
3453        sb.append("  Screen brightnesses:");
3454        boolean didOne = false;
3455        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
3456            final long time = getScreenBrightnessTime(i, rawRealtime, which);
3457            if (time == 0) {
3458                continue;
3459            }
3460            sb.append("\n    ");
3461            sb.append(prefix);
3462            didOne = true;
3463            sb.append(SCREEN_BRIGHTNESS_NAMES[i]);
3464            sb.append(" ");
3465            formatTimeMs(sb, time/1000);
3466            sb.append("(");
3467            sb.append(formatRatioLocked(time, screenOnTime));
3468            sb.append(")");
3469        }
3470        if (!didOne) sb.append(" (no activity)");
3471        pw.println(sb.toString());
3472        if (powerSaveModeEnabledTime != 0) {
3473            sb.setLength(0);
3474            sb.append(prefix);
3475                    sb.append("  Power save mode enabled: ");
3476                    formatTimeMs(sb, powerSaveModeEnabledTime / 1000);
3477                    sb.append("(");
3478                    sb.append(formatRatioLocked(powerSaveModeEnabledTime, whichBatteryRealtime));
3479                    sb.append(")");
3480            pw.println(sb.toString());
3481        }
3482        if (deviceLightIdlingTime != 0) {
3483            sb.setLength(0);
3484            sb.append(prefix);
3485                    sb.append("  Device light idling: ");
3486                    formatTimeMs(sb, deviceLightIdlingTime / 1000);
3487                    sb.append("(");
3488                    sb.append(formatRatioLocked(deviceLightIdlingTime, whichBatteryRealtime));
3489                    sb.append(") "); sb.append(getDeviceIdlingCount(DEVICE_IDLE_MODE_LIGHT, which));
3490                    sb.append("x");
3491            pw.println(sb.toString());
3492        }
3493        if (deviceIdleModeLightTime != 0) {
3494            sb.setLength(0);
3495            sb.append(prefix);
3496                    sb.append("  Idle mode light time: ");
3497                    formatTimeMs(sb, deviceIdleModeLightTime / 1000);
3498                    sb.append("(");
3499                    sb.append(formatRatioLocked(deviceIdleModeLightTime, whichBatteryRealtime));
3500                    sb.append(") ");
3501                    sb.append(getDeviceIdleModeCount(DEVICE_IDLE_MODE_LIGHT, which));
3502                    sb.append("x");
3503                    sb.append(" -- longest ");
3504                    formatTimeMs(sb, getLongestDeviceIdleModeTime(DEVICE_IDLE_MODE_LIGHT));
3505            pw.println(sb.toString());
3506        }
3507        if (deviceIdlingTime != 0) {
3508            sb.setLength(0);
3509            sb.append(prefix);
3510                    sb.append("  Device full idling: ");
3511                    formatTimeMs(sb, deviceIdlingTime / 1000);
3512                    sb.append("(");
3513                    sb.append(formatRatioLocked(deviceIdlingTime, whichBatteryRealtime));
3514                    sb.append(") "); sb.append(getDeviceIdlingCount(DEVICE_IDLE_MODE_DEEP, which));
3515                    sb.append("x");
3516            pw.println(sb.toString());
3517        }
3518        if (deviceIdleModeFullTime != 0) {
3519            sb.setLength(0);
3520            sb.append(prefix);
3521                    sb.append("  Idle mode full time: ");
3522                    formatTimeMs(sb, deviceIdleModeFullTime / 1000);
3523                    sb.append("(");
3524                    sb.append(formatRatioLocked(deviceIdleModeFullTime, whichBatteryRealtime));
3525                    sb.append(") ");
3526                    sb.append(getDeviceIdleModeCount(DEVICE_IDLE_MODE_DEEP, which));
3527                    sb.append("x");
3528                    sb.append(" -- longest ");
3529                    formatTimeMs(sb, getLongestDeviceIdleModeTime(DEVICE_IDLE_MODE_DEEP));
3530            pw.println(sb.toString());
3531        }
3532        if (phoneOnTime != 0) {
3533            sb.setLength(0);
3534            sb.append(prefix);
3535                    sb.append("  Active phone call: "); formatTimeMs(sb, phoneOnTime / 1000);
3536                    sb.append("("); sb.append(formatRatioLocked(phoneOnTime, whichBatteryRealtime));
3537                    sb.append(") "); sb.append(getPhoneOnCount(which)); sb.append("x");
3538        }
3539        final int connChanges = getNumConnectivityChange(which);
3540        if (connChanges != 0) {
3541            pw.print(prefix);
3542            pw.print("  Connectivity changes: "); pw.println(connChanges);
3543        }
3544
3545        // Calculate wakelock times across all uids.
3546        long fullWakeLockTimeTotalMicros = 0;
3547        long partialWakeLockTimeTotalMicros = 0;
3548
3549        final ArrayList<TimerEntry> timers = new ArrayList<>();
3550
3551        for (int iu = 0; iu < NU; iu++) {
3552            final Uid u = uidStats.valueAt(iu);
3553
3554            final ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> wakelocks
3555                    = u.getWakelockStats();
3556            for (int iw=wakelocks.size()-1; iw>=0; iw--) {
3557                final Uid.Wakelock wl = wakelocks.valueAt(iw);
3558
3559                final Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
3560                if (fullWakeTimer != null) {
3561                    fullWakeLockTimeTotalMicros += fullWakeTimer.getTotalTimeLocked(
3562                            rawRealtime, which);
3563                }
3564
3565                final Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
3566                if (partialWakeTimer != null) {
3567                    final long totalTimeMicros = partialWakeTimer.getTotalTimeLocked(
3568                            rawRealtime, which);
3569                    if (totalTimeMicros > 0) {
3570                        if (reqUid < 0) {
3571                            // Only show the ordered list of all wake
3572                            // locks if the caller is not asking for data
3573                            // about a specific uid.
3574                            timers.add(new TimerEntry(wakelocks.keyAt(iw), u.getUid(),
3575                                    partialWakeTimer, totalTimeMicros));
3576                        }
3577                        partialWakeLockTimeTotalMicros += totalTimeMicros;
3578                    }
3579                }
3580            }
3581        }
3582
3583        final long mobileRxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
3584        final long mobileTxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
3585        final long wifiRxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
3586        final long wifiTxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
3587        final long mobileRxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
3588        final long mobileTxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
3589        final long wifiRxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
3590        final long wifiTxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
3591        final long btRxTotalBytes = getNetworkActivityBytes(NETWORK_BT_RX_DATA, which);
3592        final long btTxTotalBytes = getNetworkActivityBytes(NETWORK_BT_TX_DATA, which);
3593
3594        if (fullWakeLockTimeTotalMicros != 0) {
3595            sb.setLength(0);
3596            sb.append(prefix);
3597                    sb.append("  Total full wakelock time: "); formatTimeMsNoSpace(sb,
3598                            (fullWakeLockTimeTotalMicros + 500) / 1000);
3599            pw.println(sb.toString());
3600        }
3601
3602        if (partialWakeLockTimeTotalMicros != 0) {
3603            sb.setLength(0);
3604            sb.append(prefix);
3605                    sb.append("  Total partial wakelock time: "); formatTimeMsNoSpace(sb,
3606                            (partialWakeLockTimeTotalMicros + 500) / 1000);
3607            pw.println(sb.toString());
3608        }
3609
3610        pw.print(prefix);
3611                pw.print("  Mobile total received: "); pw.print(formatBytesLocked(mobileRxTotalBytes));
3612                pw.print(", sent: "); pw.print(formatBytesLocked(mobileTxTotalBytes));
3613                pw.print(" (packets received "); pw.print(mobileRxTotalPackets);
3614                pw.print(", sent "); pw.print(mobileTxTotalPackets); pw.println(")");
3615        sb.setLength(0);
3616        sb.append(prefix);
3617        sb.append("  Phone signal levels:");
3618        didOne = false;
3619        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
3620            final long time = getPhoneSignalStrengthTime(i, rawRealtime, which);
3621            if (time == 0) {
3622                continue;
3623            }
3624            sb.append("\n    ");
3625            sb.append(prefix);
3626            didOne = true;
3627            sb.append(SignalStrength.SIGNAL_STRENGTH_NAMES[i]);
3628            sb.append(" ");
3629            formatTimeMs(sb, time/1000);
3630            sb.append("(");
3631            sb.append(formatRatioLocked(time, whichBatteryRealtime));
3632            sb.append(") ");
3633            sb.append(getPhoneSignalStrengthCount(i, which));
3634            sb.append("x");
3635        }
3636        if (!didOne) sb.append(" (no activity)");
3637        pw.println(sb.toString());
3638
3639        sb.setLength(0);
3640        sb.append(prefix);
3641        sb.append("  Signal scanning time: ");
3642        formatTimeMsNoSpace(sb, getPhoneSignalScanningTime(rawRealtime, which) / 1000);
3643        pw.println(sb.toString());
3644
3645        sb.setLength(0);
3646        sb.append(prefix);
3647        sb.append("  Radio types:");
3648        didOne = false;
3649        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
3650            final long time = getPhoneDataConnectionTime(i, rawRealtime, which);
3651            if (time == 0) {
3652                continue;
3653            }
3654            sb.append("\n    ");
3655            sb.append(prefix);
3656            didOne = true;
3657            sb.append(DATA_CONNECTION_NAMES[i]);
3658            sb.append(" ");
3659            formatTimeMs(sb, time/1000);
3660            sb.append("(");
3661            sb.append(formatRatioLocked(time, whichBatteryRealtime));
3662            sb.append(") ");
3663            sb.append(getPhoneDataConnectionCount(i, which));
3664            sb.append("x");
3665        }
3666        if (!didOne) sb.append(" (no activity)");
3667        pw.println(sb.toString());
3668
3669        sb.setLength(0);
3670        sb.append(prefix);
3671        sb.append("  Mobile radio active time: ");
3672        final long mobileActiveTime = getMobileRadioActiveTime(rawRealtime, which);
3673        formatTimeMs(sb, mobileActiveTime / 1000);
3674        sb.append("("); sb.append(formatRatioLocked(mobileActiveTime, whichBatteryRealtime));
3675        sb.append(") "); sb.append(getMobileRadioActiveCount(which));
3676        sb.append("x");
3677        pw.println(sb.toString());
3678
3679        final long mobileActiveUnknownTime = getMobileRadioActiveUnknownTime(which);
3680        if (mobileActiveUnknownTime != 0) {
3681            sb.setLength(0);
3682            sb.append(prefix);
3683            sb.append("  Mobile radio active unknown time: ");
3684            formatTimeMs(sb, mobileActiveUnknownTime / 1000);
3685            sb.append("(");
3686            sb.append(formatRatioLocked(mobileActiveUnknownTime, whichBatteryRealtime));
3687            sb.append(") "); sb.append(getMobileRadioActiveUnknownCount(which));
3688            sb.append("x");
3689            pw.println(sb.toString());
3690        }
3691
3692        final long mobileActiveAdjustedTime = getMobileRadioActiveAdjustedTime(which);
3693        if (mobileActiveAdjustedTime != 0) {
3694            sb.setLength(0);
3695            sb.append(prefix);
3696            sb.append("  Mobile radio active adjusted time: ");
3697            formatTimeMs(sb, mobileActiveAdjustedTime / 1000);
3698            sb.append("(");
3699            sb.append(formatRatioLocked(mobileActiveAdjustedTime, whichBatteryRealtime));
3700            sb.append(")");
3701            pw.println(sb.toString());
3702        }
3703
3704        printControllerActivity(pw, sb, prefix, "Radio", getModemControllerActivity(), which);
3705
3706        pw.print(prefix);
3707                pw.print("  Wi-Fi total received: "); pw.print(formatBytesLocked(wifiRxTotalBytes));
3708                pw.print(", sent: "); pw.print(formatBytesLocked(wifiTxTotalBytes));
3709                pw.print(" (packets received "); pw.print(wifiRxTotalPackets);
3710                pw.print(", sent "); pw.print(wifiTxTotalPackets); pw.println(")");
3711        sb.setLength(0);
3712        sb.append(prefix);
3713                sb.append("  Wifi on: "); formatTimeMs(sb, wifiOnTime / 1000);
3714                sb.append("("); sb.append(formatRatioLocked(wifiOnTime, whichBatteryRealtime));
3715                sb.append("), Wifi running: "); formatTimeMs(sb, wifiRunningTime / 1000);
3716                sb.append("("); sb.append(formatRatioLocked(wifiRunningTime, whichBatteryRealtime));
3717                sb.append(")");
3718        pw.println(sb.toString());
3719
3720        sb.setLength(0);
3721        sb.append(prefix);
3722        sb.append("  Wifi states:");
3723        didOne = false;
3724        for (int i=0; i<NUM_WIFI_STATES; i++) {
3725            final long time = getWifiStateTime(i, rawRealtime, which);
3726            if (time == 0) {
3727                continue;
3728            }
3729            sb.append("\n    ");
3730            didOne = true;
3731            sb.append(WIFI_STATE_NAMES[i]);
3732            sb.append(" ");
3733            formatTimeMs(sb, time/1000);
3734            sb.append("(");
3735            sb.append(formatRatioLocked(time, whichBatteryRealtime));
3736            sb.append(") ");
3737            sb.append(getWifiStateCount(i, which));
3738            sb.append("x");
3739        }
3740        if (!didOne) sb.append(" (no activity)");
3741        pw.println(sb.toString());
3742
3743        sb.setLength(0);
3744        sb.append(prefix);
3745        sb.append("  Wifi supplicant states:");
3746        didOne = false;
3747        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
3748            final long time = getWifiSupplStateTime(i, rawRealtime, which);
3749            if (time == 0) {
3750                continue;
3751            }
3752            sb.append("\n    ");
3753            didOne = true;
3754            sb.append(WIFI_SUPPL_STATE_NAMES[i]);
3755            sb.append(" ");
3756            formatTimeMs(sb, time/1000);
3757            sb.append("(");
3758            sb.append(formatRatioLocked(time, whichBatteryRealtime));
3759            sb.append(") ");
3760            sb.append(getWifiSupplStateCount(i, which));
3761            sb.append("x");
3762        }
3763        if (!didOne) sb.append(" (no activity)");
3764        pw.println(sb.toString());
3765
3766        sb.setLength(0);
3767        sb.append(prefix);
3768        sb.append("  Wifi signal levels:");
3769        didOne = false;
3770        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
3771            final long time = getWifiSignalStrengthTime(i, rawRealtime, which);
3772            if (time == 0) {
3773                continue;
3774            }
3775            sb.append("\n    ");
3776            sb.append(prefix);
3777            didOne = true;
3778            sb.append("level(");
3779            sb.append(i);
3780            sb.append(") ");
3781            formatTimeMs(sb, time/1000);
3782            sb.append("(");
3783            sb.append(formatRatioLocked(time, whichBatteryRealtime));
3784            sb.append(") ");
3785            sb.append(getWifiSignalStrengthCount(i, which));
3786            sb.append("x");
3787        }
3788        if (!didOne) sb.append(" (no activity)");
3789        pw.println(sb.toString());
3790
3791        printControllerActivity(pw, sb, prefix, "WiFi", getWifiControllerActivity(), which);
3792
3793        pw.print(prefix);
3794        pw.print("  Bluetooth total received: "); pw.print(formatBytesLocked(btRxTotalBytes));
3795        pw.print(", sent: "); pw.println(formatBytesLocked(btTxTotalBytes));
3796
3797        final long bluetoothScanTimeMs = getBluetoothScanTime(rawRealtime, which) / 1000;
3798        sb.setLength(0);
3799        sb.append(prefix);
3800        sb.append("  Bluetooth scan time: "); formatTimeMs(sb, bluetoothScanTimeMs);
3801        pw.println(sb.toString());
3802
3803        printControllerActivity(pw, sb, prefix, "Bluetooth", getBluetoothControllerActivity(),
3804                which);
3805
3806        pw.println();
3807
3808        if (which == STATS_SINCE_UNPLUGGED) {
3809            if (getIsOnBattery()) {
3810                pw.print(prefix); pw.println("  Device is currently unplugged");
3811                pw.print(prefix); pw.print("    Discharge cycle start level: ");
3812                        pw.println(getDischargeStartLevel());
3813                pw.print(prefix); pw.print("    Discharge cycle current level: ");
3814                        pw.println(getDischargeCurrentLevel());
3815            } else {
3816                pw.print(prefix); pw.println("  Device is currently plugged into power");
3817                pw.print(prefix); pw.print("    Last discharge cycle start level: ");
3818                        pw.println(getDischargeStartLevel());
3819                pw.print(prefix); pw.print("    Last discharge cycle end level: ");
3820                        pw.println(getDischargeCurrentLevel());
3821            }
3822            pw.print(prefix); pw.print("    Amount discharged while screen on: ");
3823                    pw.println(getDischargeAmountScreenOn());
3824            pw.print(prefix); pw.print("    Amount discharged while screen off: ");
3825                    pw.println(getDischargeAmountScreenOff());
3826            pw.println(" ");
3827        } else {
3828            pw.print(prefix); pw.println("  Device battery use since last full charge");
3829            pw.print(prefix); pw.print("    Amount discharged (lower bound): ");
3830                    pw.println(getLowDischargeAmountSinceCharge());
3831            pw.print(prefix); pw.print("    Amount discharged (upper bound): ");
3832                    pw.println(getHighDischargeAmountSinceCharge());
3833            pw.print(prefix); pw.print("    Amount discharged while screen on: ");
3834                    pw.println(getDischargeAmountScreenOnSinceCharge());
3835            pw.print(prefix); pw.print("    Amount discharged while screen off: ");
3836                    pw.println(getDischargeAmountScreenOffSinceCharge());
3837            pw.println();
3838        }
3839
3840        final BatteryStatsHelper helper = new BatteryStatsHelper(context, false, wifiOnly);
3841        helper.create(this);
3842        helper.refreshStats(which, UserHandle.USER_ALL);
3843        List<BatterySipper> sippers = helper.getUsageList();
3844        if (sippers != null && sippers.size() > 0) {
3845            pw.print(prefix); pw.println("  Estimated power use (mAh):");
3846            pw.print(prefix); pw.print("    Capacity: ");
3847                    printmAh(pw, helper.getPowerProfile().getBatteryCapacity());
3848                    pw.print(", Computed drain: "); printmAh(pw, helper.getComputedPower());
3849                    pw.print(", actual drain: "); printmAh(pw, helper.getMinDrainedPower());
3850                    if (helper.getMinDrainedPower() != helper.getMaxDrainedPower()) {
3851                        pw.print("-"); printmAh(pw, helper.getMaxDrainedPower());
3852                    }
3853                    pw.println();
3854            for (int i=0; i<sippers.size(); i++) {
3855                final BatterySipper bs = sippers.get(i);
3856                pw.print(prefix);
3857                switch (bs.drainType) {
3858                    case IDLE:
3859                        pw.print("    Idle: ");
3860                        break;
3861                    case CELL:
3862                        pw.print("    Cell standby: ");
3863                        break;
3864                    case PHONE:
3865                        pw.print("    Phone calls: ");
3866                        break;
3867                    case WIFI:
3868                        pw.print("    Wifi: ");
3869                        break;
3870                    case BLUETOOTH:
3871                        pw.print("    Bluetooth: ");
3872                        break;
3873                    case SCREEN:
3874                        pw.print("    Screen: ");
3875                        break;
3876                    case FLASHLIGHT:
3877                        pw.print("    Flashlight: ");
3878                        break;
3879                    case APP:
3880                        pw.print("    Uid ");
3881                        UserHandle.formatUid(pw, bs.uidObj.getUid());
3882                        pw.print(": ");
3883                        break;
3884                    case USER:
3885                        pw.print("    User "); pw.print(bs.userId);
3886                        pw.print(": ");
3887                        break;
3888                    case UNACCOUNTED:
3889                        pw.print("    Unaccounted: ");
3890                        break;
3891                    case OVERCOUNTED:
3892                        pw.print("    Over-counted: ");
3893                        break;
3894                    case CAMERA:
3895                        pw.print("    Camera: ");
3896                        break;
3897                    default:
3898                        pw.print("    ???: ");
3899                        break;
3900                }
3901                printmAh(pw, bs.totalPowerMah);
3902
3903                if (bs.usagePowerMah != bs.totalPowerMah) {
3904                    // If the usage (generic power) isn't the whole amount, we list out
3905                    // what components are involved in the calculation.
3906
3907                    pw.print(" (");
3908                    if (bs.usagePowerMah != 0) {
3909                        pw.print(" usage=");
3910                        printmAh(pw, bs.usagePowerMah);
3911                    }
3912                    if (bs.cpuPowerMah != 0) {
3913                        pw.print(" cpu=");
3914                        printmAh(pw, bs.cpuPowerMah);
3915                    }
3916                    if (bs.wakeLockPowerMah != 0) {
3917                        pw.print(" wake=");
3918                        printmAh(pw, bs.wakeLockPowerMah);
3919                    }
3920                    if (bs.mobileRadioPowerMah != 0) {
3921                        pw.print(" radio=");
3922                        printmAh(pw, bs.mobileRadioPowerMah);
3923                    }
3924                    if (bs.wifiPowerMah != 0) {
3925                        pw.print(" wifi=");
3926                        printmAh(pw, bs.wifiPowerMah);
3927                    }
3928                    if (bs.bluetoothPowerMah != 0) {
3929                        pw.print(" bt=");
3930                        printmAh(pw, bs.bluetoothPowerMah);
3931                    }
3932                    if (bs.gpsPowerMah != 0) {
3933                        pw.print(" gps=");
3934                        printmAh(pw, bs.gpsPowerMah);
3935                    }
3936                    if (bs.sensorPowerMah != 0) {
3937                        pw.print(" sensor=");
3938                        printmAh(pw, bs.sensorPowerMah);
3939                    }
3940                    if (bs.cameraPowerMah != 0) {
3941                        pw.print(" camera=");
3942                        printmAh(pw, bs.cameraPowerMah);
3943                    }
3944                    if (bs.flashlightPowerMah != 0) {
3945                        pw.print(" flash=");
3946                        printmAh(pw, bs.flashlightPowerMah);
3947                    }
3948                    pw.print(" )");
3949                }
3950                pw.println();
3951            }
3952            pw.println();
3953        }
3954
3955        sippers = helper.getMobilemsppList();
3956        if (sippers != null && sippers.size() > 0) {
3957            pw.print(prefix); pw.println("  Per-app mobile ms per packet:");
3958            long totalTime = 0;
3959            for (int i=0; i<sippers.size(); i++) {
3960                final BatterySipper bs = sippers.get(i);
3961                sb.setLength(0);
3962                sb.append(prefix); sb.append("    Uid ");
3963                UserHandle.formatUid(sb, bs.uidObj.getUid());
3964                sb.append(": "); sb.append(BatteryStatsHelper.makemAh(bs.mobilemspp));
3965                sb.append(" ("); sb.append(bs.mobileRxPackets+bs.mobileTxPackets);
3966                sb.append(" packets over "); formatTimeMsNoSpace(sb, bs.mobileActive);
3967                sb.append(") "); sb.append(bs.mobileActiveCount); sb.append("x");
3968                pw.println(sb.toString());
3969                totalTime += bs.mobileActive;
3970            }
3971            sb.setLength(0);
3972            sb.append(prefix);
3973            sb.append("    TOTAL TIME: ");
3974            formatTimeMs(sb, totalTime);
3975            sb.append("("); sb.append(formatRatioLocked(totalTime, whichBatteryRealtime));
3976            sb.append(")");
3977            pw.println(sb.toString());
3978            pw.println();
3979        }
3980
3981        final Comparator<TimerEntry> timerComparator = new Comparator<TimerEntry>() {
3982            @Override
3983            public int compare(TimerEntry lhs, TimerEntry rhs) {
3984                long lhsTime = lhs.mTime;
3985                long rhsTime = rhs.mTime;
3986                if (lhsTime < rhsTime) {
3987                    return 1;
3988                }
3989                if (lhsTime > rhsTime) {
3990                    return -1;
3991                }
3992                return 0;
3993            }
3994        };
3995
3996        if (reqUid < 0) {
3997            final Map<String, ? extends BatteryStats.Timer> kernelWakelocks
3998                    = getKernelWakelockStats();
3999            if (kernelWakelocks.size() > 0) {
4000                final ArrayList<TimerEntry> ktimers = new ArrayList<>();
4001                for (Map.Entry<String, ? extends BatteryStats.Timer> ent
4002                        : kernelWakelocks.entrySet()) {
4003                    final BatteryStats.Timer timer = ent.getValue();
4004                    final long totalTimeMillis = computeWakeLock(timer, rawRealtime, which);
4005                    if (totalTimeMillis > 0) {
4006                        ktimers.add(new TimerEntry(ent.getKey(), 0, timer, totalTimeMillis));
4007                    }
4008                }
4009                if (ktimers.size() > 0) {
4010                    Collections.sort(ktimers, timerComparator);
4011                    pw.print(prefix); pw.println("  All kernel wake locks:");
4012                    for (int i=0; i<ktimers.size(); i++) {
4013                        final TimerEntry timer = ktimers.get(i);
4014                        String linePrefix = ": ";
4015                        sb.setLength(0);
4016                        sb.append(prefix);
4017                        sb.append("  Kernel Wake lock ");
4018                        sb.append(timer.mName);
4019                        linePrefix = printWakeLock(sb, timer.mTimer, rawRealtime, null,
4020                                which, linePrefix);
4021                        if (!linePrefix.equals(": ")) {
4022                            sb.append(" realtime");
4023                            // Only print out wake locks that were held
4024                            pw.println(sb.toString());
4025                        }
4026                    }
4027                    pw.println();
4028                }
4029            }
4030
4031            if (timers.size() > 0) {
4032                Collections.sort(timers, timerComparator);
4033                pw.print(prefix); pw.println("  All partial wake locks:");
4034                for (int i=0; i<timers.size(); i++) {
4035                    TimerEntry timer = timers.get(i);
4036                    sb.setLength(0);
4037                    sb.append("  Wake lock ");
4038                    UserHandle.formatUid(sb, timer.mId);
4039                    sb.append(" ");
4040                    sb.append(timer.mName);
4041                    printWakeLock(sb, timer.mTimer, rawRealtime, null, which, ": ");
4042                    sb.append(" realtime");
4043                    pw.println(sb.toString());
4044                }
4045                timers.clear();
4046                pw.println();
4047            }
4048
4049            final Map<String, ? extends Timer> wakeupReasons = getWakeupReasonStats();
4050            if (wakeupReasons.size() > 0) {
4051                pw.print(prefix); pw.println("  All wakeup reasons:");
4052                final ArrayList<TimerEntry> reasons = new ArrayList<>();
4053                for (Map.Entry<String, ? extends Timer> ent : wakeupReasons.entrySet()) {
4054                    final Timer timer = ent.getValue();
4055                    reasons.add(new TimerEntry(ent.getKey(), 0, timer,
4056                            timer.getCountLocked(which)));
4057                }
4058                Collections.sort(reasons, timerComparator);
4059                for (int i=0; i<reasons.size(); i++) {
4060                    TimerEntry timer = reasons.get(i);
4061                    String linePrefix = ": ";
4062                    sb.setLength(0);
4063                    sb.append(prefix);
4064                    sb.append("  Wakeup reason ");
4065                    sb.append(timer.mName);
4066                    printWakeLock(sb, timer.mTimer, rawRealtime, null, which, ": ");
4067                    sb.append(" realtime");
4068                    pw.println(sb.toString());
4069                }
4070                pw.println();
4071            }
4072        }
4073
4074        for (int iu=0; iu<NU; iu++) {
4075            final int uid = uidStats.keyAt(iu);
4076            if (reqUid >= 0 && uid != reqUid && uid != Process.SYSTEM_UID) {
4077                continue;
4078            }
4079
4080            final Uid u = uidStats.valueAt(iu);
4081
4082            pw.print(prefix);
4083            pw.print("  ");
4084            UserHandle.formatUid(pw, uid);
4085            pw.println(":");
4086            boolean uidActivity = false;
4087
4088            final long mobileRxBytes = u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
4089            final long mobileTxBytes = u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
4090            final long wifiRxBytes = u.getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
4091            final long wifiTxBytes = u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
4092            final long btRxBytes = u.getNetworkActivityBytes(NETWORK_BT_RX_DATA, which);
4093            final long btTxBytes = u.getNetworkActivityBytes(NETWORK_BT_TX_DATA, which);
4094
4095            final long mobileRxPackets = u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
4096            final long mobileTxPackets = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
4097            final long wifiRxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
4098            final long wifiTxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
4099
4100            final long uidMobileActiveTime = u.getMobileRadioActiveTime(which);
4101            final int uidMobileActiveCount = u.getMobileRadioActiveCount(which);
4102
4103            final long fullWifiLockOnTime = u.getFullWifiLockTime(rawRealtime, which);
4104            final long wifiScanTime = u.getWifiScanTime(rawRealtime, which);
4105            final int wifiScanCount = u.getWifiScanCount(which);
4106            final long uidWifiRunningTime = u.getWifiRunningTime(rawRealtime, which);
4107
4108            if (mobileRxBytes > 0 || mobileTxBytes > 0
4109                    || mobileRxPackets > 0 || mobileTxPackets > 0) {
4110                pw.print(prefix); pw.print("    Mobile network: ");
4111                        pw.print(formatBytesLocked(mobileRxBytes)); pw.print(" received, ");
4112                        pw.print(formatBytesLocked(mobileTxBytes));
4113                        pw.print(" sent (packets "); pw.print(mobileRxPackets);
4114                        pw.print(" received, "); pw.print(mobileTxPackets); pw.println(" sent)");
4115            }
4116            if (uidMobileActiveTime > 0 || uidMobileActiveCount > 0) {
4117                sb.setLength(0);
4118                sb.append(prefix); sb.append("    Mobile radio active: ");
4119                formatTimeMs(sb, uidMobileActiveTime / 1000);
4120                sb.append("(");
4121                sb.append(formatRatioLocked(uidMobileActiveTime, mobileActiveTime));
4122                sb.append(") "); sb.append(uidMobileActiveCount); sb.append("x");
4123                long packets = mobileRxPackets + mobileTxPackets;
4124                if (packets == 0) {
4125                    packets = 1;
4126                }
4127                sb.append(" @ ");
4128                sb.append(BatteryStatsHelper.makemAh(uidMobileActiveTime / 1000 / (double)packets));
4129                sb.append(" mspp");
4130                pw.println(sb.toString());
4131            }
4132
4133            printControllerActivityIfInteresting(pw, sb, prefix + "  ", "Modem",
4134                    u.getModemControllerActivity(), which);
4135
4136            if (wifiRxBytes > 0 || wifiTxBytes > 0 || wifiRxPackets > 0 || wifiTxPackets > 0) {
4137                pw.print(prefix); pw.print("    Wi-Fi network: ");
4138                        pw.print(formatBytesLocked(wifiRxBytes)); pw.print(" received, ");
4139                        pw.print(formatBytesLocked(wifiTxBytes));
4140                        pw.print(" sent (packets "); pw.print(wifiRxPackets);
4141                        pw.print(" received, "); pw.print(wifiTxPackets); pw.println(" sent)");
4142            }
4143
4144            if (fullWifiLockOnTime != 0 || wifiScanTime != 0 || wifiScanCount != 0
4145                    || uidWifiRunningTime != 0) {
4146                sb.setLength(0);
4147                sb.append(prefix); sb.append("    Wifi Running: ");
4148                        formatTimeMs(sb, uidWifiRunningTime / 1000);
4149                        sb.append("("); sb.append(formatRatioLocked(uidWifiRunningTime,
4150                                whichBatteryRealtime)); sb.append(")\n");
4151                sb.append(prefix); sb.append("    Full Wifi Lock: ");
4152                        formatTimeMs(sb, fullWifiLockOnTime / 1000);
4153                        sb.append("("); sb.append(formatRatioLocked(fullWifiLockOnTime,
4154                                whichBatteryRealtime)); sb.append(")\n");
4155                sb.append(prefix); sb.append("    Wifi Scan: ");
4156                        formatTimeMs(sb, wifiScanTime / 1000);
4157                        sb.append("("); sb.append(formatRatioLocked(wifiScanTime,
4158                                whichBatteryRealtime)); sb.append(") ");
4159                                sb.append(wifiScanCount);
4160                                sb.append("x");
4161                pw.println(sb.toString());
4162            }
4163
4164            printControllerActivityIfInteresting(pw, sb, prefix + "  ", "WiFi",
4165                    u.getWifiControllerActivity(), which);
4166
4167            if (btRxBytes > 0 || btTxBytes > 0) {
4168                pw.print(prefix); pw.print("    Bluetooth network: ");
4169                pw.print(formatBytesLocked(btRxBytes)); pw.print(" received, ");
4170                pw.print(formatBytesLocked(btTxBytes));
4171                pw.println(" sent");
4172            }
4173
4174            uidActivity |= printTimer(pw, sb, u.getBluetoothScanTimer(), rawRealtime, which, prefix,
4175                    "Bluetooth Scan");
4176
4177            if (u.hasUserActivity()) {
4178                boolean hasData = false;
4179                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
4180                    final int val = u.getUserActivityCount(i, which);
4181                    if (val != 0) {
4182                        if (!hasData) {
4183                            sb.setLength(0);
4184                            sb.append("    User activity: ");
4185                            hasData = true;
4186                        } else {
4187                            sb.append(", ");
4188                        }
4189                        sb.append(val);
4190                        sb.append(" ");
4191                        sb.append(Uid.USER_ACTIVITY_TYPES[i]);
4192                    }
4193                }
4194                if (hasData) {
4195                    pw.println(sb.toString());
4196                }
4197            }
4198
4199            final ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> wakelocks
4200                    = u.getWakelockStats();
4201            long totalFullWakelock = 0, totalPartialWakelock = 0, totalWindowWakelock = 0;
4202            long totalDrawWakelock = 0;
4203            int countWakelock = 0;
4204            for (int iw=wakelocks.size()-1; iw>=0; iw--) {
4205                final Uid.Wakelock wl = wakelocks.valueAt(iw);
4206                String linePrefix = ": ";
4207                sb.setLength(0);
4208                sb.append(prefix);
4209                sb.append("    Wake lock ");
4210                sb.append(wakelocks.keyAt(iw));
4211                linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_FULL), rawRealtime,
4212                        "full", which, linePrefix);
4213                linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), rawRealtime,
4214                        "partial", which, linePrefix);
4215                linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), rawRealtime,
4216                        "window", which, linePrefix);
4217                linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_DRAW), rawRealtime,
4218                        "draw", which, linePrefix);
4219                sb.append(" realtime");
4220                pw.println(sb.toString());
4221                uidActivity = true;
4222                countWakelock++;
4223
4224                totalFullWakelock += computeWakeLock(wl.getWakeTime(WAKE_TYPE_FULL),
4225                        rawRealtime, which);
4226                totalPartialWakelock += computeWakeLock(wl.getWakeTime(WAKE_TYPE_PARTIAL),
4227                        rawRealtime, which);
4228                totalWindowWakelock += computeWakeLock(wl.getWakeTime(WAKE_TYPE_WINDOW),
4229                        rawRealtime, which);
4230                totalDrawWakelock += computeWakeLock(wl.getWakeTime(WAKE_TYPE_DRAW),
4231                        rawRealtime, which);
4232            }
4233            if (countWakelock > 1) {
4234                if (totalFullWakelock != 0 || totalPartialWakelock != 0
4235                        || totalWindowWakelock != 0) {
4236                    sb.setLength(0);
4237                    sb.append(prefix);
4238                    sb.append("    TOTAL wake: ");
4239                    boolean needComma = false;
4240                    if (totalFullWakelock != 0) {
4241                        needComma = true;
4242                        formatTimeMs(sb, totalFullWakelock);
4243                        sb.append("full");
4244                    }
4245                    if (totalPartialWakelock != 0) {
4246                        if (needComma) {
4247                            sb.append(", ");
4248                        }
4249                        needComma = true;
4250                        formatTimeMs(sb, totalPartialWakelock);
4251                        sb.append("partial");
4252                    }
4253                    if (totalWindowWakelock != 0) {
4254                        if (needComma) {
4255                            sb.append(", ");
4256                        }
4257                        needComma = true;
4258                        formatTimeMs(sb, totalWindowWakelock);
4259                        sb.append("window");
4260                    }
4261                    if (totalDrawWakelock != 0) {
4262                        if (needComma) {
4263                            sb.append(",");
4264                        }
4265                        needComma = true;
4266                        formatTimeMs(sb, totalDrawWakelock);
4267                        sb.append("draw");
4268                    }
4269                    sb.append(" realtime");
4270                    pw.println(sb.toString());
4271                }
4272            }
4273
4274            final ArrayMap<String, ? extends Timer> syncs = u.getSyncStats();
4275            for (int isy=syncs.size()-1; isy>=0; isy--) {
4276                final Timer timer = syncs.valueAt(isy);
4277                // Convert from microseconds to milliseconds with rounding
4278                final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
4279                final int count = timer.getCountLocked(which);
4280                sb.setLength(0);
4281                sb.append(prefix);
4282                sb.append("    Sync ");
4283                sb.append(syncs.keyAt(isy));
4284                sb.append(": ");
4285                if (totalTime != 0) {
4286                    formatTimeMs(sb, totalTime);
4287                    sb.append("realtime (");
4288                    sb.append(count);
4289                    sb.append(" times)");
4290                } else {
4291                    sb.append("(not used)");
4292                }
4293                pw.println(sb.toString());
4294                uidActivity = true;
4295            }
4296
4297            final ArrayMap<String, ? extends Timer> jobs = u.getJobStats();
4298            for (int ij=jobs.size()-1; ij>=0; ij--) {
4299                final Timer timer = jobs.valueAt(ij);
4300                // Convert from microseconds to milliseconds with rounding
4301                final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
4302                final int count = timer.getCountLocked(which);
4303                sb.setLength(0);
4304                sb.append(prefix);
4305                sb.append("    Job ");
4306                sb.append(jobs.keyAt(ij));
4307                sb.append(": ");
4308                if (totalTime != 0) {
4309                    formatTimeMs(sb, totalTime);
4310                    sb.append("realtime (");
4311                    sb.append(count);
4312                    sb.append(" times)");
4313                } else {
4314                    sb.append("(not used)");
4315                }
4316                pw.println(sb.toString());
4317                uidActivity = true;
4318            }
4319
4320            uidActivity |= printTimer(pw, sb, u.getFlashlightTurnedOnTimer(), rawRealtime, which,
4321                    prefix, "Flashlight");
4322            uidActivity |= printTimer(pw, sb, u.getCameraTurnedOnTimer(), rawRealtime, which,
4323                    prefix, "Camera");
4324            uidActivity |= printTimer(pw, sb, u.getVideoTurnedOnTimer(), rawRealtime, which,
4325                    prefix, "Video");
4326            uidActivity |= printTimer(pw, sb, u.getAudioTurnedOnTimer(), rawRealtime, which,
4327                    prefix, "Audio");
4328
4329            final SparseArray<? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
4330            final int NSE = sensors.size();
4331            for (int ise=0; ise<NSE; ise++) {
4332                final Uid.Sensor se = sensors.valueAt(ise);
4333                final int sensorNumber = sensors.keyAt(ise);
4334                sb.setLength(0);
4335                sb.append(prefix);
4336                sb.append("    Sensor ");
4337                int handle = se.getHandle();
4338                if (handle == Uid.Sensor.GPS) {
4339                    sb.append("GPS");
4340                } else {
4341                    sb.append(handle);
4342                }
4343                sb.append(": ");
4344
4345                final Timer timer = se.getSensorTime();
4346                if (timer != null) {
4347                    // Convert from microseconds to milliseconds with rounding
4348                    final long totalTime = (timer.getTotalTimeLocked(
4349                            rawRealtime, which) + 500) / 1000;
4350                    final int count = timer.getCountLocked(which);
4351                    //timer.logState();
4352                    if (totalTime != 0) {
4353                        formatTimeMs(sb, totalTime);
4354                        sb.append("realtime (");
4355                        sb.append(count);
4356                        sb.append(" times)");
4357                    } else {
4358                        sb.append("(not used)");
4359                    }
4360                } else {
4361                    sb.append("(not used)");
4362                }
4363
4364                pw.println(sb.toString());
4365                uidActivity = true;
4366            }
4367
4368            uidActivity |= printTimer(pw, sb, u.getVibratorOnTimer(), rawRealtime, which, prefix,
4369                    "Vibrator");
4370            uidActivity |= printTimer(pw, sb, u.getForegroundActivityTimer(), rawRealtime, which,
4371                    prefix, "Foreground activities");
4372
4373            long totalStateTime = 0;
4374            for (int ips=0; ips<Uid.NUM_PROCESS_STATE; ips++) {
4375                long time = u.getProcessStateTime(ips, rawRealtime, which);
4376                if (time > 0) {
4377                    totalStateTime += time;
4378                    sb.setLength(0);
4379                    sb.append(prefix);
4380                    sb.append("    ");
4381                    sb.append(Uid.PROCESS_STATE_NAMES[ips]);
4382                    sb.append(" for: ");
4383                    formatTimeMs(sb, (time + 500) / 1000);
4384                    pw.println(sb.toString());
4385                    uidActivity = true;
4386                }
4387            }
4388            if (totalStateTime > 0) {
4389                sb.setLength(0);
4390                sb.append(prefix);
4391                sb.append("    Total running: ");
4392                formatTimeMs(sb, (totalStateTime + 500) / 1000);
4393                pw.println(sb.toString());
4394            }
4395
4396            final long userCpuTimeUs = u.getUserCpuTimeUs(which);
4397            final long systemCpuTimeUs = u.getSystemCpuTimeUs(which);
4398            final long powerCpuMaUs = u.getCpuPowerMaUs(which);
4399            if (userCpuTimeUs > 0 || systemCpuTimeUs > 0 || powerCpuMaUs > 0) {
4400                sb.setLength(0);
4401                sb.append(prefix);
4402                sb.append("    Total cpu time: u=");
4403                formatTimeMs(sb, userCpuTimeUs / 1000);
4404                sb.append("s=");
4405                formatTimeMs(sb, systemCpuTimeUs / 1000);
4406                sb.append("p=");
4407                printmAh(sb, powerCpuMaUs / (1000.0 * 1000.0 * 60.0 * 60.0));
4408                sb.append("mAh");
4409                pw.println(sb.toString());
4410            }
4411
4412            final ArrayMap<String, ? extends BatteryStats.Uid.Proc> processStats
4413                    = u.getProcessStats();
4414            for (int ipr=processStats.size()-1; ipr>=0; ipr--) {
4415                final Uid.Proc ps = processStats.valueAt(ipr);
4416                long userTime;
4417                long systemTime;
4418                long foregroundTime;
4419                int starts;
4420                int numExcessive;
4421
4422                userTime = ps.getUserTime(which);
4423                systemTime = ps.getSystemTime(which);
4424                foregroundTime = ps.getForegroundTime(which);
4425                starts = ps.getStarts(which);
4426                final int numCrashes = ps.getNumCrashes(which);
4427                final int numAnrs = ps.getNumAnrs(which);
4428                numExcessive = which == STATS_SINCE_CHARGED
4429                        ? ps.countExcessivePowers() : 0;
4430
4431                if (userTime != 0 || systemTime != 0 || foregroundTime != 0 || starts != 0
4432                        || numExcessive != 0 || numCrashes != 0 || numAnrs != 0) {
4433                    sb.setLength(0);
4434                    sb.append(prefix); sb.append("    Proc ");
4435                            sb.append(processStats.keyAt(ipr)); sb.append(":\n");
4436                    sb.append(prefix); sb.append("      CPU: ");
4437                            formatTimeMs(sb, userTime); sb.append("usr + ");
4438                            formatTimeMs(sb, systemTime); sb.append("krn ; ");
4439                            formatTimeMs(sb, foregroundTime); sb.append("fg");
4440                    if (starts != 0 || numCrashes != 0 || numAnrs != 0) {
4441                        sb.append("\n"); sb.append(prefix); sb.append("      ");
4442                        boolean hasOne = false;
4443                        if (starts != 0) {
4444                            hasOne = true;
4445                            sb.append(starts); sb.append(" starts");
4446                        }
4447                        if (numCrashes != 0) {
4448                            if (hasOne) {
4449                                sb.append(", ");
4450                            }
4451                            hasOne = true;
4452                            sb.append(numCrashes); sb.append(" crashes");
4453                        }
4454                        if (numAnrs != 0) {
4455                            if (hasOne) {
4456                                sb.append(", ");
4457                            }
4458                            sb.append(numAnrs); sb.append(" anrs");
4459                        }
4460                    }
4461                    pw.println(sb.toString());
4462                    for (int e=0; e<numExcessive; e++) {
4463                        Uid.Proc.ExcessivePower ew = ps.getExcessivePower(e);
4464                        if (ew != null) {
4465                            pw.print(prefix); pw.print("      * Killed for ");
4466                                    if (ew.type == Uid.Proc.ExcessivePower.TYPE_WAKE) {
4467                                        pw.print("wake lock");
4468                                    } else if (ew.type == Uid.Proc.ExcessivePower.TYPE_CPU) {
4469                                        pw.print("cpu");
4470                                    } else {
4471                                        pw.print("unknown");
4472                                    }
4473                                    pw.print(" use: ");
4474                                    TimeUtils.formatDuration(ew.usedTime, pw);
4475                                    pw.print(" over ");
4476                                    TimeUtils.formatDuration(ew.overTime, pw);
4477                                    if (ew.overTime != 0) {
4478                                        pw.print(" (");
4479                                        pw.print((ew.usedTime*100)/ew.overTime);
4480                                        pw.println("%)");
4481                                    }
4482                        }
4483                    }
4484                    uidActivity = true;
4485                }
4486            }
4487
4488            final ArrayMap<String, ? extends BatteryStats.Uid.Pkg> packageStats
4489                    = u.getPackageStats();
4490            for (int ipkg=packageStats.size()-1; ipkg>=0; ipkg--) {
4491                pw.print(prefix); pw.print("    Apk "); pw.print(packageStats.keyAt(ipkg));
4492                pw.println(":");
4493                boolean apkActivity = false;
4494                final Uid.Pkg ps = packageStats.valueAt(ipkg);
4495                final ArrayMap<String, ? extends Counter> alarms = ps.getWakeupAlarmStats();
4496                for (int iwa=alarms.size()-1; iwa>=0; iwa--) {
4497                    pw.print(prefix); pw.print("      Wakeup alarm ");
4498                            pw.print(alarms.keyAt(iwa)); pw.print(": ");
4499                            pw.print(alarms.valueAt(iwa).getCountLocked(which));
4500                            pw.println(" times");
4501                    apkActivity = true;
4502                }
4503                final ArrayMap<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
4504                for (int isvc=serviceStats.size()-1; isvc>=0; isvc--) {
4505                    final BatteryStats.Uid.Pkg.Serv ss = serviceStats.valueAt(isvc);
4506                    final long startTime = ss.getStartTime(batteryUptime, which);
4507                    final int starts = ss.getStarts(which);
4508                    final int launches = ss.getLaunches(which);
4509                    if (startTime != 0 || starts != 0 || launches != 0) {
4510                        sb.setLength(0);
4511                        sb.append(prefix); sb.append("      Service ");
4512                                sb.append(serviceStats.keyAt(isvc)); sb.append(":\n");
4513                        sb.append(prefix); sb.append("        Created for: ");
4514                                formatTimeMs(sb, startTime / 1000);
4515                                sb.append("uptime\n");
4516                        sb.append(prefix); sb.append("        Starts: ");
4517                                sb.append(starts);
4518                                sb.append(", launches: "); sb.append(launches);
4519                        pw.println(sb.toString());
4520                        apkActivity = true;
4521                    }
4522                }
4523                if (!apkActivity) {
4524                    pw.print(prefix); pw.println("      (nothing executed)");
4525                }
4526                uidActivity = true;
4527            }
4528            if (!uidActivity) {
4529                pw.print(prefix); pw.println("    (nothing executed)");
4530            }
4531        }
4532    }
4533
4534    static void printBitDescriptions(PrintWriter pw, int oldval, int newval, HistoryTag wakelockTag,
4535            BitDescription[] descriptions, boolean longNames) {
4536        int diff = oldval ^ newval;
4537        if (diff == 0) return;
4538        boolean didWake = false;
4539        for (int i=0; i<descriptions.length; i++) {
4540            BitDescription bd = descriptions[i];
4541            if ((diff&bd.mask) != 0) {
4542                pw.print(longNames ? " " : ",");
4543                if (bd.shift < 0) {
4544                    pw.print((newval&bd.mask) != 0 ? "+" : "-");
4545                    pw.print(longNames ? bd.name : bd.shortName);
4546                    if (bd.mask == HistoryItem.STATE_WAKE_LOCK_FLAG && wakelockTag != null) {
4547                        didWake = true;
4548                        pw.print("=");
4549                        if (longNames) {
4550                            UserHandle.formatUid(pw, wakelockTag.uid);
4551                            pw.print(":\"");
4552                            pw.print(wakelockTag.string);
4553                            pw.print("\"");
4554                        } else {
4555                            pw.print(wakelockTag.poolIdx);
4556                        }
4557                    }
4558                } else {
4559                    pw.print(longNames ? bd.name : bd.shortName);
4560                    pw.print("=");
4561                    int val = (newval&bd.mask)>>bd.shift;
4562                    if (bd.values != null && val >= 0 && val < bd.values.length) {
4563                        pw.print(longNames? bd.values[val] : bd.shortValues[val]);
4564                    } else {
4565                        pw.print(val);
4566                    }
4567                }
4568            }
4569        }
4570        if (!didWake && wakelockTag != null) {
4571            pw.print(longNames ? " wake_lock=" : ",w=");
4572            if (longNames) {
4573                UserHandle.formatUid(pw, wakelockTag.uid);
4574                pw.print(":\"");
4575                pw.print(wakelockTag.string);
4576                pw.print("\"");
4577            } else {
4578                pw.print(wakelockTag.poolIdx);
4579            }
4580        }
4581    }
4582
4583    public void prepareForDumpLocked() {
4584    }
4585
4586    public static class HistoryPrinter {
4587        int oldState = 0;
4588        int oldState2 = 0;
4589        int oldLevel = -1;
4590        int oldStatus = -1;
4591        int oldHealth = -1;
4592        int oldPlug = -1;
4593        int oldTemp = -1;
4594        int oldVolt = -1;
4595        int oldChargeMAh = -1;
4596        long lastTime = -1;
4597
4598        void reset() {
4599            oldState = oldState2 = 0;
4600            oldLevel = -1;
4601            oldStatus = -1;
4602            oldHealth = -1;
4603            oldPlug = -1;
4604            oldTemp = -1;
4605            oldVolt = -1;
4606            oldChargeMAh = -1;
4607        }
4608
4609        public void printNextItem(PrintWriter pw, HistoryItem rec, long baseTime, boolean checkin,
4610                boolean verbose) {
4611            if (!checkin) {
4612                pw.print("  ");
4613                TimeUtils.formatDuration(rec.time - baseTime, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
4614                pw.print(" (");
4615                pw.print(rec.numReadInts);
4616                pw.print(") ");
4617            } else {
4618                pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
4619                pw.print(HISTORY_DATA); pw.print(',');
4620                if (lastTime < 0) {
4621                    pw.print(rec.time - baseTime);
4622                } else {
4623                    pw.print(rec.time - lastTime);
4624                }
4625                lastTime = rec.time;
4626            }
4627            if (rec.cmd == HistoryItem.CMD_START) {
4628                if (checkin) {
4629                    pw.print(":");
4630                }
4631                pw.println("START");
4632                reset();
4633            } else if (rec.cmd == HistoryItem.CMD_CURRENT_TIME
4634                    || rec.cmd == HistoryItem.CMD_RESET) {
4635                if (checkin) {
4636                    pw.print(":");
4637                }
4638                if (rec.cmd == HistoryItem.CMD_RESET) {
4639                    pw.print("RESET:");
4640                    reset();
4641                }
4642                pw.print("TIME:");
4643                if (checkin) {
4644                    pw.println(rec.currentTime);
4645                } else {
4646                    pw.print(" ");
4647                    pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss",
4648                            rec.currentTime).toString());
4649                }
4650            } else if (rec.cmd == HistoryItem.CMD_SHUTDOWN) {
4651                if (checkin) {
4652                    pw.print(":");
4653                }
4654                pw.println("SHUTDOWN");
4655            } else if (rec.cmd == HistoryItem.CMD_OVERFLOW) {
4656                if (checkin) {
4657                    pw.print(":");
4658                }
4659                pw.println("*OVERFLOW*");
4660            } else {
4661                if (!checkin) {
4662                    if (rec.batteryLevel < 10) pw.print("00");
4663                    else if (rec.batteryLevel < 100) pw.print("0");
4664                    pw.print(rec.batteryLevel);
4665                    if (verbose) {
4666                        pw.print(" ");
4667                        if (rec.states < 0) ;
4668                        else if (rec.states < 0x10) pw.print("0000000");
4669                        else if (rec.states < 0x100) pw.print("000000");
4670                        else if (rec.states < 0x1000) pw.print("00000");
4671                        else if (rec.states < 0x10000) pw.print("0000");
4672                        else if (rec.states < 0x100000) pw.print("000");
4673                        else if (rec.states < 0x1000000) pw.print("00");
4674                        else if (rec.states < 0x10000000) pw.print("0");
4675                        pw.print(Integer.toHexString(rec.states));
4676                    }
4677                } else {
4678                    if (oldLevel != rec.batteryLevel) {
4679                        oldLevel = rec.batteryLevel;
4680                        pw.print(",Bl="); pw.print(rec.batteryLevel);
4681                    }
4682                }
4683                if (oldStatus != rec.batteryStatus) {
4684                    oldStatus = rec.batteryStatus;
4685                    pw.print(checkin ? ",Bs=" : " status=");
4686                    switch (oldStatus) {
4687                        case BatteryManager.BATTERY_STATUS_UNKNOWN:
4688                            pw.print(checkin ? "?" : "unknown");
4689                            break;
4690                        case BatteryManager.BATTERY_STATUS_CHARGING:
4691                            pw.print(checkin ? "c" : "charging");
4692                            break;
4693                        case BatteryManager.BATTERY_STATUS_DISCHARGING:
4694                            pw.print(checkin ? "d" : "discharging");
4695                            break;
4696                        case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
4697                            pw.print(checkin ? "n" : "not-charging");
4698                            break;
4699                        case BatteryManager.BATTERY_STATUS_FULL:
4700                            pw.print(checkin ? "f" : "full");
4701                            break;
4702                        default:
4703                            pw.print(oldStatus);
4704                            break;
4705                    }
4706                }
4707                if (oldHealth != rec.batteryHealth) {
4708                    oldHealth = rec.batteryHealth;
4709                    pw.print(checkin ? ",Bh=" : " health=");
4710                    switch (oldHealth) {
4711                        case BatteryManager.BATTERY_HEALTH_UNKNOWN:
4712                            pw.print(checkin ? "?" : "unknown");
4713                            break;
4714                        case BatteryManager.BATTERY_HEALTH_GOOD:
4715                            pw.print(checkin ? "g" : "good");
4716                            break;
4717                        case BatteryManager.BATTERY_HEALTH_OVERHEAT:
4718                            pw.print(checkin ? "h" : "overheat");
4719                            break;
4720                        case BatteryManager.BATTERY_HEALTH_DEAD:
4721                            pw.print(checkin ? "d" : "dead");
4722                            break;
4723                        case BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE:
4724                            pw.print(checkin ? "v" : "over-voltage");
4725                            break;
4726                        case BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE:
4727                            pw.print(checkin ? "f" : "failure");
4728                            break;
4729                        case BatteryManager.BATTERY_HEALTH_COLD:
4730                            pw.print(checkin ? "c" : "cold");
4731                            break;
4732                        default:
4733                            pw.print(oldHealth);
4734                            break;
4735                    }
4736                }
4737                if (oldPlug != rec.batteryPlugType) {
4738                    oldPlug = rec.batteryPlugType;
4739                    pw.print(checkin ? ",Bp=" : " plug=");
4740                    switch (oldPlug) {
4741                        case 0:
4742                            pw.print(checkin ? "n" : "none");
4743                            break;
4744                        case BatteryManager.BATTERY_PLUGGED_AC:
4745                            pw.print(checkin ? "a" : "ac");
4746                            break;
4747                        case BatteryManager.BATTERY_PLUGGED_USB:
4748                            pw.print(checkin ? "u" : "usb");
4749                            break;
4750                        case BatteryManager.BATTERY_PLUGGED_WIRELESS:
4751                            pw.print(checkin ? "w" : "wireless");
4752                            break;
4753                        default:
4754                            pw.print(oldPlug);
4755                            break;
4756                    }
4757                }
4758                if (oldTemp != rec.batteryTemperature) {
4759                    oldTemp = rec.batteryTemperature;
4760                    pw.print(checkin ? ",Bt=" : " temp=");
4761                    pw.print(oldTemp);
4762                }
4763                if (oldVolt != rec.batteryVoltage) {
4764                    oldVolt = rec.batteryVoltage;
4765                    pw.print(checkin ? ",Bv=" : " volt=");
4766                    pw.print(oldVolt);
4767                }
4768                final int chargeMAh = rec.batteryChargeUAh / 1000;
4769                if (oldChargeMAh != chargeMAh) {
4770                    oldChargeMAh = chargeMAh;
4771                    pw.print(checkin ? ",Bcc=" : " charge=");
4772                    pw.print(oldChargeMAh);
4773                }
4774                printBitDescriptions(pw, oldState, rec.states, rec.wakelockTag,
4775                        HISTORY_STATE_DESCRIPTIONS, !checkin);
4776                printBitDescriptions(pw, oldState2, rec.states2, null,
4777                        HISTORY_STATE2_DESCRIPTIONS, !checkin);
4778                if (rec.wakeReasonTag != null) {
4779                    if (checkin) {
4780                        pw.print(",wr=");
4781                        pw.print(rec.wakeReasonTag.poolIdx);
4782                    } else {
4783                        pw.print(" wake_reason=");
4784                        pw.print(rec.wakeReasonTag.uid);
4785                        pw.print(":\"");
4786                        pw.print(rec.wakeReasonTag.string);
4787                        pw.print("\"");
4788                    }
4789                }
4790                if (rec.eventCode != HistoryItem.EVENT_NONE) {
4791                    pw.print(checkin ? "," : " ");
4792                    if ((rec.eventCode&HistoryItem.EVENT_FLAG_START) != 0) {
4793                        pw.print("+");
4794                    } else if ((rec.eventCode&HistoryItem.EVENT_FLAG_FINISH) != 0) {
4795                        pw.print("-");
4796                    }
4797                    String[] eventNames = checkin ? HISTORY_EVENT_CHECKIN_NAMES
4798                            : HISTORY_EVENT_NAMES;
4799                    int idx = rec.eventCode & ~(HistoryItem.EVENT_FLAG_START
4800                            | HistoryItem.EVENT_FLAG_FINISH);
4801                    if (idx >= 0 && idx < eventNames.length) {
4802                        pw.print(eventNames[idx]);
4803                    } else {
4804                        pw.print(checkin ? "Ev" : "event");
4805                        pw.print(idx);
4806                    }
4807                    pw.print("=");
4808                    if (checkin) {
4809                        pw.print(rec.eventTag.poolIdx);
4810                    } else {
4811                        UserHandle.formatUid(pw, rec.eventTag.uid);
4812                        pw.print(":\"");
4813                        pw.print(rec.eventTag.string);
4814                        pw.print("\"");
4815                    }
4816                }
4817                pw.println();
4818                if (rec.stepDetails != null) {
4819                    if (!checkin) {
4820                        pw.print("                 Details: cpu=");
4821                        pw.print(rec.stepDetails.userTime);
4822                        pw.print("u+");
4823                        pw.print(rec.stepDetails.systemTime);
4824                        pw.print("s");
4825                        if (rec.stepDetails.appCpuUid1 >= 0) {
4826                            pw.print(" (");
4827                            printStepCpuUidDetails(pw, rec.stepDetails.appCpuUid1,
4828                                    rec.stepDetails.appCpuUTime1, rec.stepDetails.appCpuSTime1);
4829                            if (rec.stepDetails.appCpuUid2 >= 0) {
4830                                pw.print(", ");
4831                                printStepCpuUidDetails(pw, rec.stepDetails.appCpuUid2,
4832                                        rec.stepDetails.appCpuUTime2, rec.stepDetails.appCpuSTime2);
4833                            }
4834                            if (rec.stepDetails.appCpuUid3 >= 0) {
4835                                pw.print(", ");
4836                                printStepCpuUidDetails(pw, rec.stepDetails.appCpuUid3,
4837                                        rec.stepDetails.appCpuUTime3, rec.stepDetails.appCpuSTime3);
4838                            }
4839                            pw.print(')');
4840                        }
4841                        pw.println();
4842                        pw.print("                          /proc/stat=");
4843                        pw.print(rec.stepDetails.statUserTime);
4844                        pw.print(" usr, ");
4845                        pw.print(rec.stepDetails.statSystemTime);
4846                        pw.print(" sys, ");
4847                        pw.print(rec.stepDetails.statIOWaitTime);
4848                        pw.print(" io, ");
4849                        pw.print(rec.stepDetails.statIrqTime);
4850                        pw.print(" irq, ");
4851                        pw.print(rec.stepDetails.statSoftIrqTime);
4852                        pw.print(" sirq, ");
4853                        pw.print(rec.stepDetails.statIdlTime);
4854                        pw.print(" idle");
4855                        int totalRun = rec.stepDetails.statUserTime + rec.stepDetails.statSystemTime
4856                                + rec.stepDetails.statIOWaitTime + rec.stepDetails.statIrqTime
4857                                + rec.stepDetails.statSoftIrqTime;
4858                        int total = totalRun + rec.stepDetails.statIdlTime;
4859                        if (total > 0) {
4860                            pw.print(" (");
4861                            float perc = ((float)totalRun) / ((float)total) * 100;
4862                            pw.print(String.format("%.1f%%", perc));
4863                            pw.print(" of ");
4864                            StringBuilder sb = new StringBuilder(64);
4865                            formatTimeMsNoSpace(sb, total*10);
4866                            pw.print(sb);
4867                            pw.print(")");
4868                        }
4869                        pw.print(", PlatformIdleStat ");
4870                        pw.print(rec.stepDetails.statPlatformIdleState);
4871                        pw.println();
4872                    } else {
4873                        pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
4874                        pw.print(HISTORY_DATA); pw.print(",0,Dcpu=");
4875                        pw.print(rec.stepDetails.userTime);
4876                        pw.print(":");
4877                        pw.print(rec.stepDetails.systemTime);
4878                        if (rec.stepDetails.appCpuUid1 >= 0) {
4879                            printStepCpuUidCheckinDetails(pw, rec.stepDetails.appCpuUid1,
4880                                    rec.stepDetails.appCpuUTime1, rec.stepDetails.appCpuSTime1);
4881                            if (rec.stepDetails.appCpuUid2 >= 0) {
4882                                printStepCpuUidCheckinDetails(pw, rec.stepDetails.appCpuUid2,
4883                                        rec.stepDetails.appCpuUTime2, rec.stepDetails.appCpuSTime2);
4884                            }
4885                            if (rec.stepDetails.appCpuUid3 >= 0) {
4886                                printStepCpuUidCheckinDetails(pw, rec.stepDetails.appCpuUid3,
4887                                        rec.stepDetails.appCpuUTime3, rec.stepDetails.appCpuSTime3);
4888                            }
4889                        }
4890                        pw.println();
4891                        pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
4892                        pw.print(HISTORY_DATA); pw.print(",0,Dpst=");
4893                        pw.print(rec.stepDetails.statUserTime);
4894                        pw.print(',');
4895                        pw.print(rec.stepDetails.statSystemTime);
4896                        pw.print(',');
4897                        pw.print(rec.stepDetails.statIOWaitTime);
4898                        pw.print(',');
4899                        pw.print(rec.stepDetails.statIrqTime);
4900                        pw.print(',');
4901                        pw.print(rec.stepDetails.statSoftIrqTime);
4902                        pw.print(',');
4903                        pw.print(rec.stepDetails.statIdlTime);
4904                        pw.print(',');
4905                        pw.print(rec.stepDetails.statPlatformIdleState);
4906                        pw.println();
4907                    }
4908                }
4909                oldState = rec.states;
4910                oldState2 = rec.states2;
4911            }
4912        }
4913
4914        private void printStepCpuUidDetails(PrintWriter pw, int uid, int utime, int stime) {
4915            UserHandle.formatUid(pw, uid);
4916            pw.print("=");
4917            pw.print(utime);
4918            pw.print("u+");
4919            pw.print(stime);
4920            pw.print("s");
4921        }
4922
4923        private void printStepCpuUidCheckinDetails(PrintWriter pw, int uid, int utime, int stime) {
4924            pw.print('/');
4925            pw.print(uid);
4926            pw.print(":");
4927            pw.print(utime);
4928            pw.print(":");
4929            pw.print(stime);
4930        }
4931    }
4932
4933    private void printSizeValue(PrintWriter pw, long size) {
4934        float result = size;
4935        String suffix = "";
4936        if (result >= 10*1024) {
4937            suffix = "KB";
4938            result = result / 1024;
4939        }
4940        if (result >= 10*1024) {
4941            suffix = "MB";
4942            result = result / 1024;
4943        }
4944        if (result >= 10*1024) {
4945            suffix = "GB";
4946            result = result / 1024;
4947        }
4948        if (result >= 10*1024) {
4949            suffix = "TB";
4950            result = result / 1024;
4951        }
4952        if (result >= 10*1024) {
4953            suffix = "PB";
4954            result = result / 1024;
4955        }
4956        pw.print((int)result);
4957        pw.print(suffix);
4958    }
4959
4960    private static boolean dumpTimeEstimate(PrintWriter pw, String label1, String label2,
4961            String label3, long estimatedTime) {
4962        if (estimatedTime < 0) {
4963            return false;
4964        }
4965        pw.print(label1);
4966        pw.print(label2);
4967        pw.print(label3);
4968        StringBuilder sb = new StringBuilder(64);
4969        formatTimeMs(sb, estimatedTime);
4970        pw.print(sb);
4971        pw.println();
4972        return true;
4973    }
4974
4975    private static boolean dumpDurationSteps(PrintWriter pw, String prefix, String header,
4976            LevelStepTracker steps, boolean checkin) {
4977        if (steps == null) {
4978            return false;
4979        }
4980        int count = steps.mNumStepDurations;
4981        if (count <= 0) {
4982            return false;
4983        }
4984        if (!checkin) {
4985            pw.println(header);
4986        }
4987        String[] lineArgs = new String[5];
4988        for (int i=0; i<count; i++) {
4989            long duration = steps.getDurationAt(i);
4990            int level = steps.getLevelAt(i);
4991            long initMode = steps.getInitModeAt(i);
4992            long modMode = steps.getModModeAt(i);
4993            if (checkin) {
4994                lineArgs[0] = Long.toString(duration);
4995                lineArgs[1] = Integer.toString(level);
4996                if ((modMode&STEP_LEVEL_MODE_SCREEN_STATE) == 0) {
4997                    switch ((int)(initMode&STEP_LEVEL_MODE_SCREEN_STATE) + 1) {
4998                        case Display.STATE_OFF: lineArgs[2] = "s-"; break;
4999                        case Display.STATE_ON: lineArgs[2] = "s+"; break;
5000                        case Display.STATE_DOZE: lineArgs[2] = "sd"; break;
5001                        case Display.STATE_DOZE_SUSPEND: lineArgs[2] = "sds"; break;
5002                        default: lineArgs[2] = "?"; break;
5003                    }
5004                } else {
5005                    lineArgs[2] = "";
5006                }
5007                if ((modMode&STEP_LEVEL_MODE_POWER_SAVE) == 0) {
5008                    lineArgs[3] = (initMode&STEP_LEVEL_MODE_POWER_SAVE) != 0 ? "p+" : "p-";
5009                } else {
5010                    lineArgs[3] = "";
5011                }
5012                if ((modMode&STEP_LEVEL_MODE_DEVICE_IDLE) == 0) {
5013                    lineArgs[4] = (initMode&STEP_LEVEL_MODE_DEVICE_IDLE) != 0 ? "i+" : "i-";
5014                } else {
5015                    lineArgs[4] = "";
5016                }
5017                dumpLine(pw, 0 /* uid */, "i" /* category */, header, (Object[])lineArgs);
5018            } else {
5019                pw.print(prefix);
5020                pw.print("#"); pw.print(i); pw.print(": ");
5021                TimeUtils.formatDuration(duration, pw);
5022                pw.print(" to "); pw.print(level);
5023                boolean haveModes = false;
5024                if ((modMode&STEP_LEVEL_MODE_SCREEN_STATE) == 0) {
5025                    pw.print(" (");
5026                    switch ((int)(initMode&STEP_LEVEL_MODE_SCREEN_STATE) + 1) {
5027                        case Display.STATE_OFF: pw.print("screen-off"); break;
5028                        case Display.STATE_ON: pw.print("screen-on"); break;
5029                        case Display.STATE_DOZE: pw.print("screen-doze"); break;
5030                        case Display.STATE_DOZE_SUSPEND: pw.print("screen-doze-suspend"); break;
5031                        default: pw.print("screen-?"); break;
5032                    }
5033                    haveModes = true;
5034                }
5035                if ((modMode&STEP_LEVEL_MODE_POWER_SAVE) == 0) {
5036                    pw.print(haveModes ? ", " : " (");
5037                    pw.print((initMode&STEP_LEVEL_MODE_POWER_SAVE) != 0
5038                            ? "power-save-on" : "power-save-off");
5039                    haveModes = true;
5040                }
5041                if ((modMode&STEP_LEVEL_MODE_DEVICE_IDLE) == 0) {
5042                    pw.print(haveModes ? ", " : " (");
5043                    pw.print((initMode&STEP_LEVEL_MODE_DEVICE_IDLE) != 0
5044                            ? "device-idle-on" : "device-idle-off");
5045                    haveModes = true;
5046                }
5047                if (haveModes) {
5048                    pw.print(")");
5049                }
5050                pw.println();
5051            }
5052        }
5053        return true;
5054    }
5055
5056    public static final int DUMP_CHARGED_ONLY = 1<<1;
5057    public static final int DUMP_DAILY_ONLY = 1<<2;
5058    public static final int DUMP_HISTORY_ONLY = 1<<3;
5059    public static final int DUMP_INCLUDE_HISTORY = 1<<4;
5060    public static final int DUMP_VERBOSE = 1<<5;
5061    public static final int DUMP_DEVICE_WIFI_ONLY = 1<<6;
5062
5063    private void dumpHistoryLocked(PrintWriter pw, int flags, long histStart, boolean checkin) {
5064        final HistoryPrinter hprinter = new HistoryPrinter();
5065        final HistoryItem rec = new HistoryItem();
5066        long lastTime = -1;
5067        long baseTime = -1;
5068        boolean printed = false;
5069        HistoryEventTracker tracker = null;
5070        while (getNextHistoryLocked(rec)) {
5071            lastTime = rec.time;
5072            if (baseTime < 0) {
5073                baseTime = lastTime;
5074            }
5075            if (rec.time >= histStart) {
5076                if (histStart >= 0 && !printed) {
5077                    if (rec.cmd == HistoryItem.CMD_CURRENT_TIME
5078                            || rec.cmd == HistoryItem.CMD_RESET
5079                            || rec.cmd == HistoryItem.CMD_START
5080                            || rec.cmd == HistoryItem.CMD_SHUTDOWN) {
5081                        printed = true;
5082                        hprinter.printNextItem(pw, rec, baseTime, checkin,
5083                                (flags&DUMP_VERBOSE) != 0);
5084                        rec.cmd = HistoryItem.CMD_UPDATE;
5085                    } else if (rec.currentTime != 0) {
5086                        printed = true;
5087                        byte cmd = rec.cmd;
5088                        rec.cmd = HistoryItem.CMD_CURRENT_TIME;
5089                        hprinter.printNextItem(pw, rec, baseTime, checkin,
5090                                (flags&DUMP_VERBOSE) != 0);
5091                        rec.cmd = cmd;
5092                    }
5093                    if (tracker != null) {
5094                        if (rec.cmd != HistoryItem.CMD_UPDATE) {
5095                            hprinter.printNextItem(pw, rec, baseTime, checkin,
5096                                    (flags&DUMP_VERBOSE) != 0);
5097                            rec.cmd = HistoryItem.CMD_UPDATE;
5098                        }
5099                        int oldEventCode = rec.eventCode;
5100                        HistoryTag oldEventTag = rec.eventTag;
5101                        rec.eventTag = new HistoryTag();
5102                        for (int i=0; i<HistoryItem.EVENT_COUNT; i++) {
5103                            HashMap<String, SparseIntArray> active
5104                                    = tracker.getStateForEvent(i);
5105                            if (active == null) {
5106                                continue;
5107                            }
5108                            for (HashMap.Entry<String, SparseIntArray> ent
5109                                    : active.entrySet()) {
5110                                SparseIntArray uids = ent.getValue();
5111                                for (int j=0; j<uids.size(); j++) {
5112                                    rec.eventCode = i;
5113                                    rec.eventTag.string = ent.getKey();
5114                                    rec.eventTag.uid = uids.keyAt(j);
5115                                    rec.eventTag.poolIdx = uids.valueAt(j);
5116                                    hprinter.printNextItem(pw, rec, baseTime, checkin,
5117                                            (flags&DUMP_VERBOSE) != 0);
5118                                    rec.wakeReasonTag = null;
5119                                    rec.wakelockTag = null;
5120                                }
5121                            }
5122                        }
5123                        rec.eventCode = oldEventCode;
5124                        rec.eventTag = oldEventTag;
5125                        tracker = null;
5126                    }
5127                }
5128                hprinter.printNextItem(pw, rec, baseTime, checkin,
5129                        (flags&DUMP_VERBOSE) != 0);
5130            } else if (false && rec.eventCode != HistoryItem.EVENT_NONE) {
5131                // This is an attempt to aggregate the previous state and generate
5132                // fake events to reflect that state at the point where we start
5133                // printing real events.  It doesn't really work right, so is turned off.
5134                if (tracker == null) {
5135                    tracker = new HistoryEventTracker();
5136                }
5137                tracker.updateState(rec.eventCode, rec.eventTag.string,
5138                        rec.eventTag.uid, rec.eventTag.poolIdx);
5139            }
5140        }
5141        if (histStart >= 0) {
5142            commitCurrentHistoryBatchLocked();
5143            pw.print(checkin ? "NEXT: " : "  NEXT: "); pw.println(lastTime+1);
5144        }
5145    }
5146
5147    private void dumpDailyLevelStepSummary(PrintWriter pw, String prefix, String label,
5148            LevelStepTracker steps, StringBuilder tmpSb, int[] tmpOutInt) {
5149        if (steps == null) {
5150            return;
5151        }
5152        long timeRemaining = steps.computeTimeEstimate(0, 0, tmpOutInt);
5153        if (timeRemaining >= 0) {
5154            pw.print(prefix); pw.print(label); pw.print(" total time: ");
5155            tmpSb.setLength(0);
5156            formatTimeMs(tmpSb, timeRemaining);
5157            pw.print(tmpSb);
5158            pw.print(" (from "); pw.print(tmpOutInt[0]);
5159            pw.println(" steps)");
5160        }
5161        for (int i=0; i< STEP_LEVEL_MODES_OF_INTEREST.length; i++) {
5162            long estimatedTime = steps.computeTimeEstimate(STEP_LEVEL_MODES_OF_INTEREST[i],
5163                    STEP_LEVEL_MODE_VALUES[i], tmpOutInt);
5164            if (estimatedTime > 0) {
5165                pw.print(prefix); pw.print(label); pw.print(" ");
5166                pw.print(STEP_LEVEL_MODE_LABELS[i]);
5167                pw.print(" time: ");
5168                tmpSb.setLength(0);
5169                formatTimeMs(tmpSb, estimatedTime);
5170                pw.print(tmpSb);
5171                pw.print(" (from "); pw.print(tmpOutInt[0]);
5172                pw.println(" steps)");
5173            }
5174        }
5175    }
5176
5177    private void dumpDailyPackageChanges(PrintWriter pw, String prefix,
5178            ArrayList<PackageChange> changes) {
5179        if (changes == null) {
5180            return;
5181        }
5182        pw.print(prefix); pw.println("Package changes:");
5183        for (int i=0; i<changes.size(); i++) {
5184            PackageChange pc = changes.get(i);
5185            if (pc.mUpdate) {
5186                pw.print(prefix); pw.print("  Update "); pw.print(pc.mPackageName);
5187                pw.print(" vers="); pw.println(pc.mVersionCode);
5188            } else {
5189                pw.print(prefix); pw.print("  Uninstall "); pw.println(pc.mPackageName);
5190            }
5191        }
5192    }
5193
5194    /**
5195     * Dumps a human-readable summary of the battery statistics to the given PrintWriter.
5196     *
5197     * @param pw a Printer to receive the dump output.
5198     */
5199    @SuppressWarnings("unused")
5200    public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
5201        prepareForDumpLocked();
5202
5203        final boolean filtering = (flags
5204                & (DUMP_HISTORY_ONLY|DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) != 0;
5205
5206        if ((flags&DUMP_HISTORY_ONLY) != 0 || !filtering) {
5207            final long historyTotalSize = getHistoryTotalSize();
5208            final long historyUsedSize = getHistoryUsedSize();
5209            if (startIteratingHistoryLocked()) {
5210                try {
5211                    pw.print("Battery History (");
5212                    pw.print((100*historyUsedSize)/historyTotalSize);
5213                    pw.print("% used, ");
5214                    printSizeValue(pw, historyUsedSize);
5215                    pw.print(" used of ");
5216                    printSizeValue(pw, historyTotalSize);
5217                    pw.print(", ");
5218                    pw.print(getHistoryStringPoolSize());
5219                    pw.print(" strings using ");
5220                    printSizeValue(pw, getHistoryStringPoolBytes());
5221                    pw.println("):");
5222                    dumpHistoryLocked(pw, flags, histStart, false);
5223                    pw.println();
5224                } finally {
5225                    finishIteratingHistoryLocked();
5226                }
5227            }
5228
5229            if (startIteratingOldHistoryLocked()) {
5230                try {
5231                    final HistoryItem rec = new HistoryItem();
5232                    pw.println("Old battery History:");
5233                    HistoryPrinter hprinter = new HistoryPrinter();
5234                    long baseTime = -1;
5235                    while (getNextOldHistoryLocked(rec)) {
5236                        if (baseTime < 0) {
5237                            baseTime = rec.time;
5238                        }
5239                        hprinter.printNextItem(pw, rec, baseTime, false, (flags&DUMP_VERBOSE) != 0);
5240                    }
5241                    pw.println();
5242                } finally {
5243                    finishIteratingOldHistoryLocked();
5244                }
5245            }
5246        }
5247
5248        if (filtering && (flags&(DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) == 0) {
5249            return;
5250        }
5251
5252        if (!filtering) {
5253            SparseArray<? extends Uid> uidStats = getUidStats();
5254            final int NU = uidStats.size();
5255            boolean didPid = false;
5256            long nowRealtime = SystemClock.elapsedRealtime();
5257            for (int i=0; i<NU; i++) {
5258                Uid uid = uidStats.valueAt(i);
5259                SparseArray<? extends Uid.Pid> pids = uid.getPidStats();
5260                if (pids != null) {
5261                    for (int j=0; j<pids.size(); j++) {
5262                        Uid.Pid pid = pids.valueAt(j);
5263                        if (!didPid) {
5264                            pw.println("Per-PID Stats:");
5265                            didPid = true;
5266                        }
5267                        long time = pid.mWakeSumMs + (pid.mWakeNesting > 0
5268                                ? (nowRealtime - pid.mWakeStartMs) : 0);
5269                        pw.print("  PID "); pw.print(pids.keyAt(j));
5270                                pw.print(" wake time: ");
5271                                TimeUtils.formatDuration(time, pw);
5272                                pw.println("");
5273                    }
5274                }
5275            }
5276            if (didPid) {
5277                pw.println();
5278            }
5279        }
5280
5281        if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
5282            if (dumpDurationSteps(pw, "  ", "Discharge step durations:",
5283                    getDischargeLevelStepTracker(), false)) {
5284                long timeRemaining = computeBatteryTimeRemaining(SystemClock.elapsedRealtime());
5285                if (timeRemaining >= 0) {
5286                    pw.print("  Estimated discharge time remaining: ");
5287                    TimeUtils.formatDuration(timeRemaining / 1000, pw);
5288                    pw.println();
5289                }
5290                final LevelStepTracker steps = getDischargeLevelStepTracker();
5291                for (int i=0; i< STEP_LEVEL_MODES_OF_INTEREST.length; i++) {
5292                    dumpTimeEstimate(pw, "  Estimated ", STEP_LEVEL_MODE_LABELS[i], " time: ",
5293                            steps.computeTimeEstimate(STEP_LEVEL_MODES_OF_INTEREST[i],
5294                                    STEP_LEVEL_MODE_VALUES[i], null));
5295                }
5296                pw.println();
5297            }
5298            if (dumpDurationSteps(pw, "  ", "Charge step durations:",
5299                    getChargeLevelStepTracker(), false)) {
5300                long timeRemaining = computeChargeTimeRemaining(SystemClock.elapsedRealtime());
5301                if (timeRemaining >= 0) {
5302                    pw.print("  Estimated charge time remaining: ");
5303                    TimeUtils.formatDuration(timeRemaining / 1000, pw);
5304                    pw.println();
5305                }
5306                pw.println();
5307            }
5308        }
5309        if (!filtering || (flags&(DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) != 0) {
5310            pw.println("Daily stats:");
5311            pw.print("  Current start time: ");
5312            pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss",
5313                    getCurrentDailyStartTime()).toString());
5314            pw.print("  Next min deadline: ");
5315            pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss",
5316                    getNextMinDailyDeadline()).toString());
5317            pw.print("  Next max deadline: ");
5318            pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss",
5319                    getNextMaxDailyDeadline()).toString());
5320            StringBuilder sb = new StringBuilder(64);
5321            int[] outInt = new int[1];
5322            LevelStepTracker dsteps = getDailyDischargeLevelStepTracker();
5323            LevelStepTracker csteps = getDailyChargeLevelStepTracker();
5324            ArrayList<PackageChange> pkgc = getDailyPackageChanges();
5325            if (dsteps.mNumStepDurations > 0 || csteps.mNumStepDurations > 0 || pkgc != null) {
5326                if ((flags&DUMP_DAILY_ONLY) != 0 || !filtering) {
5327                    if (dumpDurationSteps(pw, "    ", "  Current daily discharge step durations:",
5328                            dsteps, false)) {
5329                        dumpDailyLevelStepSummary(pw, "      ", "Discharge", dsteps,
5330                                sb, outInt);
5331                    }
5332                    if (dumpDurationSteps(pw, "    ", "  Current daily charge step durations:",
5333                            csteps, false)) {
5334                        dumpDailyLevelStepSummary(pw, "      ", "Charge", csteps,
5335                                sb, outInt);
5336                    }
5337                    dumpDailyPackageChanges(pw, "    ", pkgc);
5338                } else {
5339                    pw.println("  Current daily steps:");
5340                    dumpDailyLevelStepSummary(pw, "    ", "Discharge", dsteps,
5341                            sb, outInt);
5342                    dumpDailyLevelStepSummary(pw, "    ", "Charge", csteps,
5343                            sb, outInt);
5344                }
5345            }
5346            DailyItem dit;
5347            int curIndex = 0;
5348            while ((dit=getDailyItemLocked(curIndex)) != null) {
5349                curIndex++;
5350                if ((flags&DUMP_DAILY_ONLY) != 0) {
5351                    pw.println();
5352                }
5353                pw.print("  Daily from ");
5354                pw.print(DateFormat.format("yyyy-MM-dd-HH-mm-ss", dit.mStartTime).toString());
5355                pw.print(" to ");
5356                pw.print(DateFormat.format("yyyy-MM-dd-HH-mm-ss", dit.mEndTime).toString());
5357                pw.println(":");
5358                if ((flags&DUMP_DAILY_ONLY) != 0 || !filtering) {
5359                    if (dumpDurationSteps(pw, "      ",
5360                            "    Discharge step durations:", dit.mDischargeSteps, false)) {
5361                        dumpDailyLevelStepSummary(pw, "        ", "Discharge", dit.mDischargeSteps,
5362                                sb, outInt);
5363                    }
5364                    if (dumpDurationSteps(pw, "      ",
5365                            "    Charge step durations:", dit.mChargeSteps, false)) {
5366                        dumpDailyLevelStepSummary(pw, "        ", "Charge", dit.mChargeSteps,
5367                                sb, outInt);
5368                    }
5369                    dumpDailyPackageChanges(pw, "    ", dit.mPackageChanges);
5370                } else {
5371                    dumpDailyLevelStepSummary(pw, "    ", "Discharge", dit.mDischargeSteps,
5372                            sb, outInt);
5373                    dumpDailyLevelStepSummary(pw, "    ", "Charge", dit.mChargeSteps,
5374                            sb, outInt);
5375                }
5376            }
5377            pw.println();
5378        }
5379        if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
5380            pw.println("Statistics since last charge:");
5381            pw.println("  System starts: " + getStartCount()
5382                    + ", currently on battery: " + getIsOnBattery());
5383            dumpLocked(context, pw, "", STATS_SINCE_CHARGED, reqUid,
5384                    (flags&DUMP_DEVICE_WIFI_ONLY) != 0);
5385            pw.println();
5386        }
5387    }
5388
5389    @SuppressWarnings("unused")
5390    public void dumpCheckinLocked(Context context, PrintWriter pw,
5391            List<ApplicationInfo> apps, int flags, long histStart) {
5392        prepareForDumpLocked();
5393
5394        dumpLine(pw, 0 /* uid */, "i" /* category */, VERSION_DATA,
5395                CHECKIN_VERSION, getParcelVersion(), getStartPlatformVersion(),
5396                getEndPlatformVersion());
5397
5398        long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
5399
5400        final boolean filtering = (flags &
5401                (DUMP_HISTORY_ONLY|DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) != 0;
5402
5403        if ((flags&DUMP_INCLUDE_HISTORY) != 0 || (flags&DUMP_HISTORY_ONLY) != 0) {
5404            if (startIteratingHistoryLocked()) {
5405                try {
5406                    for (int i=0; i<getHistoryStringPoolSize(); i++) {
5407                        pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
5408                        pw.print(HISTORY_STRING_POOL); pw.print(',');
5409                        pw.print(i);
5410                        pw.print(",");
5411                        pw.print(getHistoryTagPoolUid(i));
5412                        pw.print(",\"");
5413                        String str = getHistoryTagPoolString(i);
5414                        str = str.replace("\\", "\\\\");
5415                        str = str.replace("\"", "\\\"");
5416                        pw.print(str);
5417                        pw.print("\"");
5418                        pw.println();
5419                    }
5420                    dumpHistoryLocked(pw, flags, histStart, true);
5421                } finally {
5422                    finishIteratingHistoryLocked();
5423                }
5424            }
5425        }
5426
5427        if (filtering && (flags&(DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) == 0) {
5428            return;
5429        }
5430
5431        if (apps != null) {
5432            SparseArray<Pair<ArrayList<String>, MutableBoolean>> uids = new SparseArray<>();
5433            for (int i=0; i<apps.size(); i++) {
5434                ApplicationInfo ai = apps.get(i);
5435                Pair<ArrayList<String>, MutableBoolean> pkgs = uids.get(
5436                        UserHandle.getAppId(ai.uid));
5437                if (pkgs == null) {
5438                    pkgs = new Pair<>(new ArrayList<String>(), new MutableBoolean(false));
5439                    uids.put(UserHandle.getAppId(ai.uid), pkgs);
5440                }
5441                pkgs.first.add(ai.packageName);
5442            }
5443            SparseArray<? extends Uid> uidStats = getUidStats();
5444            final int NU = uidStats.size();
5445            String[] lineArgs = new String[2];
5446            for (int i=0; i<NU; i++) {
5447                int uid = UserHandle.getAppId(uidStats.keyAt(i));
5448                Pair<ArrayList<String>, MutableBoolean> pkgs = uids.get(uid);
5449                if (pkgs != null && !pkgs.second.value) {
5450                    pkgs.second.value = true;
5451                    for (int j=0; j<pkgs.first.size(); j++) {
5452                        lineArgs[0] = Integer.toString(uid);
5453                        lineArgs[1] = pkgs.first.get(j);
5454                        dumpLine(pw, 0 /* uid */, "i" /* category */, UID_DATA,
5455                                (Object[])lineArgs);
5456                    }
5457                }
5458            }
5459        }
5460        if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
5461            dumpDurationSteps(pw, "", DISCHARGE_STEP_DATA, getDischargeLevelStepTracker(), true);
5462            String[] lineArgs = new String[1];
5463            long timeRemaining = computeBatteryTimeRemaining(SystemClock.elapsedRealtime());
5464            if (timeRemaining >= 0) {
5465                lineArgs[0] = Long.toString(timeRemaining);
5466                dumpLine(pw, 0 /* uid */, "i" /* category */, DISCHARGE_TIME_REMAIN_DATA,
5467                        (Object[])lineArgs);
5468            }
5469            dumpDurationSteps(pw, "", CHARGE_STEP_DATA, getChargeLevelStepTracker(), true);
5470            timeRemaining = computeChargeTimeRemaining(SystemClock.elapsedRealtime());
5471            if (timeRemaining >= 0) {
5472                lineArgs[0] = Long.toString(timeRemaining);
5473                dumpLine(pw, 0 /* uid */, "i" /* category */, CHARGE_TIME_REMAIN_DATA,
5474                        (Object[])lineArgs);
5475            }
5476            dumpCheckinLocked(context, pw, STATS_SINCE_CHARGED, -1,
5477                    (flags&DUMP_DEVICE_WIFI_ONLY) != 0);
5478        }
5479    }
5480}
5481