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