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