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