BatteryStats.java revision 6d2c363fd59af805380622ff7a3ce4c34975aab2
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    public static final int NETWORK_MOBILE_RX_DATA = 0;
1944    public static final int NETWORK_MOBILE_TX_DATA = 1;
1945    public static final int NETWORK_WIFI_RX_DATA = 2;
1946    public static final int NETWORK_WIFI_TX_DATA = 3;
1947    public static final int NUM_NETWORK_ACTIVITY_TYPES = NETWORK_WIFI_TX_DATA + 1;
1948
1949    public abstract long getNetworkActivityBytes(int type, int which);
1950    public abstract long getNetworkActivityPackets(int type, int which);
1951
1952    public static final int CONTROLLER_IDLE_TIME = 0;
1953    public static final int CONTROLLER_RX_TIME = 1;
1954    public static final int CONTROLLER_TX_TIME = 2;
1955    public static final int CONTROLLER_POWER_DRAIN = 3;
1956    public static final int NUM_CONTROLLER_ACTIVITY_TYPES = CONTROLLER_POWER_DRAIN + 1;
1957
1958    /**
1959     * Returns true if the BatteryStats object has detailed bluetooth power reports.
1960     * When true, calling {@link #getBluetoothControllerActivity(int, int)} will yield the
1961     * actual power data.
1962     */
1963    public abstract boolean hasBluetoothActivityReporting();
1964
1965    /**
1966     * For {@link #CONTROLLER_IDLE_TIME}, {@link #CONTROLLER_RX_TIME}, and
1967     * {@link #CONTROLLER_TX_TIME}, returns the time spent (in milliseconds) in the
1968     * respective state.
1969     * For {@link #CONTROLLER_POWER_DRAIN}, returns the power used by the controller in
1970     * milli-ampere-milliseconds (mAms).
1971     */
1972    public abstract long getBluetoothControllerActivity(int type, int which);
1973
1974    /**
1975     * Returns true if the BatteryStats object has detailed WiFi power reports.
1976     * When true, calling {@link #getWifiControllerActivity(int, int)} will yield the
1977     * actual power data.
1978     */
1979    public abstract boolean hasWifiActivityReporting();
1980
1981    /**
1982     * For {@link #CONTROLLER_IDLE_TIME}, {@link #CONTROLLER_RX_TIME}, and
1983     * {@link #CONTROLLER_TX_TIME}, returns the time spent (in milliseconds) in the
1984     * respective state.
1985     * For {@link #CONTROLLER_POWER_DRAIN}, returns the power used by the controller in
1986     * milli-ampere-milliseconds (mAms).
1987     */
1988    public abstract long getWifiControllerActivity(int type, int which);
1989
1990    /**
1991     * Return the wall clock time when battery stats data collection started.
1992     */
1993    public abstract long getStartClockTime();
1994
1995    /**
1996     * Return platform version tag that we were running in when the battery stats started.
1997     */
1998    public abstract String getStartPlatformVersion();
1999
2000    /**
2001     * Return platform version tag that we were running in when the battery stats ended.
2002     */
2003    public abstract String getEndPlatformVersion();
2004
2005    /**
2006     * Return the internal version code of the parcelled format.
2007     */
2008    public abstract int getParcelVersion();
2009
2010    /**
2011     * Return whether we are currently running on battery.
2012     */
2013    public abstract boolean getIsOnBattery();
2014
2015    /**
2016     * Returns a SparseArray containing the statistics for each uid.
2017     */
2018    public abstract SparseArray<? extends Uid> getUidStats();
2019
2020    /**
2021     * Returns the current battery uptime in microseconds.
2022     *
2023     * @param curTime the amount of elapsed realtime in microseconds.
2024     */
2025    public abstract long getBatteryUptime(long curTime);
2026
2027    /**
2028     * Returns the current battery realtime in microseconds.
2029     *
2030     * @param curTime the amount of elapsed realtime in microseconds.
2031     */
2032    public abstract long getBatteryRealtime(long curTime);
2033
2034    /**
2035     * Returns the battery percentage level at the last time the device was unplugged from power, or
2036     * the last time it booted on battery power.
2037     */
2038    public abstract int getDischargeStartLevel();
2039
2040    /**
2041     * Returns the current battery percentage level if we are in a discharge cycle, otherwise
2042     * returns the level at the last plug event.
2043     */
2044    public abstract int getDischargeCurrentLevel();
2045
2046    /**
2047     * Get the amount the battery has discharged since the stats were
2048     * last reset after charging, as a lower-end approximation.
2049     */
2050    public abstract int getLowDischargeAmountSinceCharge();
2051
2052    /**
2053     * Get the amount the battery has discharged since the stats were
2054     * last reset after charging, as an upper-end approximation.
2055     */
2056    public abstract int getHighDischargeAmountSinceCharge();
2057
2058    /**
2059     * Retrieve the discharge amount over the selected discharge period <var>which</var>.
2060     */
2061    public abstract int getDischargeAmount(int which);
2062
2063    /**
2064     * Get the amount the battery has discharged while the screen was on,
2065     * since the last time power was unplugged.
2066     */
2067    public abstract int getDischargeAmountScreenOn();
2068
2069    /**
2070     * Get the amount the battery has discharged while the screen was on,
2071     * since the last time the device was charged.
2072     */
2073    public abstract int getDischargeAmountScreenOnSinceCharge();
2074
2075    /**
2076     * Get the amount the battery has discharged while the screen was off,
2077     * since the last time power was unplugged.
2078     */
2079    public abstract int getDischargeAmountScreenOff();
2080
2081    /**
2082     * Get the amount the battery has discharged while the screen was off,
2083     * since the last time the device was charged.
2084     */
2085    public abstract int getDischargeAmountScreenOffSinceCharge();
2086
2087    /**
2088     * Returns the total, last, or current battery uptime in microseconds.
2089     *
2090     * @param curTime the elapsed realtime in microseconds.
2091     * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
2092     */
2093    public abstract long computeBatteryUptime(long curTime, int which);
2094
2095    /**
2096     * Returns the total, last, or current battery realtime in microseconds.
2097     *
2098     * @param curTime the current elapsed realtime in microseconds.
2099     * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
2100     */
2101    public abstract long computeBatteryRealtime(long curTime, int which);
2102
2103    /**
2104     * Returns the total, last, or current battery screen off uptime in microseconds.
2105     *
2106     * @param curTime the elapsed realtime in microseconds.
2107     * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
2108     */
2109    public abstract long computeBatteryScreenOffUptime(long curTime, int which);
2110
2111    /**
2112     * Returns the total, last, or current battery screen off realtime in microseconds.
2113     *
2114     * @param curTime the current elapsed realtime in microseconds.
2115     * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
2116     */
2117    public abstract long computeBatteryScreenOffRealtime(long curTime, int which);
2118
2119    /**
2120     * Returns the total, last, or current uptime in microseconds.
2121     *
2122     * @param curTime the current elapsed realtime in microseconds.
2123     * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
2124     */
2125    public abstract long computeUptime(long curTime, int which);
2126
2127    /**
2128     * Returns the total, last, or current realtime in microseconds.
2129     *
2130     * @param curTime the current elapsed realtime in microseconds.
2131     * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
2132     */
2133    public abstract long computeRealtime(long curTime, int which);
2134
2135    /**
2136     * Compute an approximation for how much run time (in microseconds) is remaining on
2137     * the battery.  Returns -1 if no time can be computed: either there is not
2138     * enough current data to make a decision, or the battery is currently
2139     * charging.
2140     *
2141     * @param curTime The current elepsed realtime in microseconds.
2142     */
2143    public abstract long computeBatteryTimeRemaining(long curTime);
2144
2145    // The part of a step duration that is the actual time.
2146    public static final long STEP_LEVEL_TIME_MASK = 0x000000ffffffffffL;
2147
2148    // Bits in a step duration that are the new battery level we are at.
2149    public static final long STEP_LEVEL_LEVEL_MASK = 0x0000ff0000000000L;
2150    public static final int STEP_LEVEL_LEVEL_SHIFT = 40;
2151
2152    // Bits in a step duration that are the initial mode we were in at that step.
2153    public static final long STEP_LEVEL_INITIAL_MODE_MASK = 0x00ff000000000000L;
2154    public static final int STEP_LEVEL_INITIAL_MODE_SHIFT = 48;
2155
2156    // Bits in a step duration that indicate which modes changed during that step.
2157    public static final long STEP_LEVEL_MODIFIED_MODE_MASK = 0xff00000000000000L;
2158    public static final int STEP_LEVEL_MODIFIED_MODE_SHIFT = 56;
2159
2160    // Step duration mode: the screen is on, off, dozed, etc; value is Display.STATE_* - 1.
2161    public static final int STEP_LEVEL_MODE_SCREEN_STATE = 0x03;
2162
2163    // Step duration mode: power save is on.
2164    public static final int STEP_LEVEL_MODE_POWER_SAVE = 0x04;
2165
2166    // Step duration mode: device is currently in idle mode.
2167    public static final int STEP_LEVEL_MODE_DEVICE_IDLE = 0x08;
2168
2169    public static final int[] STEP_LEVEL_MODES_OF_INTEREST = new int[] {
2170            STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
2171            STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE|STEP_LEVEL_MODE_DEVICE_IDLE,
2172            STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_DEVICE_IDLE,
2173            STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
2174            STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
2175            STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
2176            STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
2177            STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
2178            STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE|STEP_LEVEL_MODE_DEVICE_IDLE,
2179            STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_DEVICE_IDLE,
2180    };
2181    public static final int[] STEP_LEVEL_MODE_VALUES = new int[] {
2182            (Display.STATE_OFF-1),
2183            (Display.STATE_OFF-1)|STEP_LEVEL_MODE_POWER_SAVE,
2184            (Display.STATE_OFF-1)|STEP_LEVEL_MODE_DEVICE_IDLE,
2185            (Display.STATE_ON-1),
2186            (Display.STATE_ON-1)|STEP_LEVEL_MODE_POWER_SAVE,
2187            (Display.STATE_DOZE-1),
2188            (Display.STATE_DOZE-1)|STEP_LEVEL_MODE_POWER_SAVE,
2189            (Display.STATE_DOZE_SUSPEND-1),
2190            (Display.STATE_DOZE_SUSPEND-1)|STEP_LEVEL_MODE_POWER_SAVE,
2191            (Display.STATE_DOZE_SUSPEND-1)|STEP_LEVEL_MODE_DEVICE_IDLE,
2192    };
2193    public static final String[] STEP_LEVEL_MODE_LABELS = new String[] {
2194            "screen off",
2195            "screen off power save",
2196            "screen off device idle",
2197            "screen on",
2198            "screen on power save",
2199            "screen doze",
2200            "screen doze power save",
2201            "screen doze-suspend",
2202            "screen doze-suspend power save",
2203            "screen doze-suspend device idle",
2204    };
2205
2206    /**
2207     * Return the array of discharge step durations.
2208     */
2209    public abstract LevelStepTracker getDischargeLevelStepTracker();
2210
2211    /**
2212     * Return the array of daily discharge step durations.
2213     */
2214    public abstract LevelStepTracker getDailyDischargeLevelStepTracker();
2215
2216    /**
2217     * Compute an approximation for how much time (in microseconds) remains until the battery
2218     * is fully charged.  Returns -1 if no time can be computed: either there is not
2219     * enough current data to make a decision, or the battery is currently
2220     * discharging.
2221     *
2222     * @param curTime The current elepsed realtime in microseconds.
2223     */
2224    public abstract long computeChargeTimeRemaining(long curTime);
2225
2226    /**
2227     * Return the array of charge step durations.
2228     */
2229    public abstract LevelStepTracker getChargeLevelStepTracker();
2230
2231    /**
2232     * Return the array of daily charge step durations.
2233     */
2234    public abstract LevelStepTracker getDailyChargeLevelStepTracker();
2235
2236    public abstract ArrayList<PackageChange> getDailyPackageChanges();
2237
2238    public abstract Map<String, ? extends Timer> getWakeupReasonStats();
2239
2240    public abstract Map<String, ? extends Timer> getKernelWakelockStats();
2241
2242    /** Returns the number of different speeds that the CPU can run at */
2243    public abstract int getCpuSpeedSteps();
2244
2245    public abstract void writeToParcelWithoutUids(Parcel out, int flags);
2246
2247    private final static void formatTimeRaw(StringBuilder out, long seconds) {
2248        long days = seconds / (60 * 60 * 24);
2249        if (days != 0) {
2250            out.append(days);
2251            out.append("d ");
2252        }
2253        long used = days * 60 * 60 * 24;
2254
2255        long hours = (seconds - used) / (60 * 60);
2256        if (hours != 0 || used != 0) {
2257            out.append(hours);
2258            out.append("h ");
2259        }
2260        used += hours * 60 * 60;
2261
2262        long mins = (seconds-used) / 60;
2263        if (mins != 0 || used != 0) {
2264            out.append(mins);
2265            out.append("m ");
2266        }
2267        used += mins * 60;
2268
2269        if (seconds != 0 || used != 0) {
2270            out.append(seconds-used);
2271            out.append("s ");
2272        }
2273    }
2274
2275    public final static void formatTimeMs(StringBuilder sb, long time) {
2276        long sec = time / 1000;
2277        formatTimeRaw(sb, sec);
2278        sb.append(time - (sec * 1000));
2279        sb.append("ms ");
2280    }
2281
2282    public final static void formatTimeMsNoSpace(StringBuilder sb, long time) {
2283        long sec = time / 1000;
2284        formatTimeRaw(sb, sec);
2285        sb.append(time - (sec * 1000));
2286        sb.append("ms");
2287    }
2288
2289    public final String formatRatioLocked(long num, long den) {
2290        if (den == 0L) {
2291            return "--%";
2292        }
2293        float perc = ((float)num) / ((float)den) * 100;
2294        mFormatBuilder.setLength(0);
2295        mFormatter.format("%.1f%%", perc);
2296        return mFormatBuilder.toString();
2297    }
2298
2299    final String formatBytesLocked(long bytes) {
2300        mFormatBuilder.setLength(0);
2301
2302        if (bytes < BYTES_PER_KB) {
2303            return bytes + "B";
2304        } else if (bytes < BYTES_PER_MB) {
2305            mFormatter.format("%.2fKB", bytes / (double) BYTES_PER_KB);
2306            return mFormatBuilder.toString();
2307        } else if (bytes < BYTES_PER_GB){
2308            mFormatter.format("%.2fMB", bytes / (double) BYTES_PER_MB);
2309            return mFormatBuilder.toString();
2310        } else {
2311            mFormatter.format("%.2fGB", bytes / (double) BYTES_PER_GB);
2312            return mFormatBuilder.toString();
2313        }
2314    }
2315
2316    private static long computeWakeLock(Timer timer, long elapsedRealtimeUs, int which) {
2317        if (timer != null) {
2318            // Convert from microseconds to milliseconds with rounding
2319            long totalTimeMicros = timer.getTotalTimeLocked(elapsedRealtimeUs, which);
2320            long totalTimeMillis = (totalTimeMicros + 500) / 1000;
2321            return totalTimeMillis;
2322        }
2323        return 0;
2324    }
2325
2326    /**
2327     *
2328     * @param sb a StringBuilder object.
2329     * @param timer a Timer object contining the wakelock times.
2330     * @param elapsedRealtimeUs the current on-battery time in microseconds.
2331     * @param name the name of the wakelock.
2332     * @param which which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
2333     * @param linePrefix a String to be prepended to each line of output.
2334     * @return the line prefix
2335     */
2336    private static final String printWakeLock(StringBuilder sb, Timer timer,
2337            long elapsedRealtimeUs, String name, int which, String linePrefix) {
2338
2339        if (timer != null) {
2340            long totalTimeMillis = computeWakeLock(timer, elapsedRealtimeUs, which);
2341
2342            int count = timer.getCountLocked(which);
2343            if (totalTimeMillis != 0) {
2344                sb.append(linePrefix);
2345                formatTimeMs(sb, totalTimeMillis);
2346                if (name != null) {
2347                    sb.append(name);
2348                    sb.append(' ');
2349                }
2350                sb.append('(');
2351                sb.append(count);
2352                sb.append(" times)");
2353                return ", ";
2354            }
2355        }
2356        return linePrefix;
2357    }
2358
2359    /**
2360     *
2361     * @param pw a PrintWriter object to print to.
2362     * @param sb a StringBuilder object.
2363     * @param timer a Timer object contining the wakelock times.
2364     * @param rawRealtime the current on-battery time in microseconds.
2365     * @param which which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
2366     * @param prefix a String to be prepended to each line of output.
2367     * @param type the name of the timer.
2368     */
2369    private static final boolean printTimer(PrintWriter pw, StringBuilder sb, Timer timer,
2370            long rawRealtime, int which, String prefix, String type) {
2371        if (timer != null) {
2372            // Convert from microseconds to milliseconds with rounding
2373            final long totalTime = (timer.getTotalTimeLocked(
2374                    rawRealtime, which) + 500) / 1000;
2375            final int count = timer.getCountLocked(which);
2376            if (totalTime != 0) {
2377                sb.setLength(0);
2378                sb.append(prefix);
2379                sb.append("    ");
2380                sb.append(type);
2381                sb.append(": ");
2382                formatTimeMs(sb, totalTime);
2383                sb.append("realtime (");
2384                sb.append(count);
2385                sb.append(" times)");
2386                pw.println(sb.toString());
2387                return true;
2388            }
2389        }
2390        return false;
2391    }
2392
2393    /**
2394     * Checkin version of wakelock printer. Prints simple comma-separated list.
2395     *
2396     * @param sb a StringBuilder object.
2397     * @param timer a Timer object contining the wakelock times.
2398     * @param elapsedRealtimeUs the current time in microseconds.
2399     * @param name the name of the wakelock.
2400     * @param which which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
2401     * @param linePrefix a String to be prepended to each line of output.
2402     * @return the line prefix
2403     */
2404    private static final String printWakeLockCheckin(StringBuilder sb, Timer timer,
2405            long elapsedRealtimeUs, String name, int which, String linePrefix) {
2406        long totalTimeMicros = 0;
2407        int count = 0;
2408        if (timer != null) {
2409            totalTimeMicros = timer.getTotalTimeLocked(elapsedRealtimeUs, which);
2410            count = timer.getCountLocked(which);
2411        }
2412        sb.append(linePrefix);
2413        sb.append((totalTimeMicros + 500) / 1000); // microseconds to milliseconds with rounding
2414        sb.append(',');
2415        sb.append(name != null ? name + "," : "");
2416        sb.append(count);
2417        return ",";
2418    }
2419
2420    /**
2421     * Dump a comma-separated line of values for terse checkin mode.
2422     *
2423     * @param pw the PageWriter to dump log to
2424     * @param category category of data (e.g. "total", "last", "unplugged", "current" )
2425     * @param type type of data (e.g. "wakelock", "sensor", "process", "apk" ,  "process", "network")
2426     * @param args type-dependent data arguments
2427     */
2428    private static final void dumpLine(PrintWriter pw, int uid, String category, String type,
2429           Object... args ) {
2430        pw.print(BATTERY_STATS_CHECKIN_VERSION);
2431        pw.print(',');
2432        pw.print(uid);
2433        pw.print(',');
2434        pw.print(category);
2435        pw.print(',');
2436        pw.print(type);
2437
2438        for (Object arg : args) {
2439            pw.print(',');
2440            pw.print(arg);
2441        }
2442        pw.println();
2443    }
2444
2445    /**
2446     * Dump a given timer stat for terse checkin mode.
2447     *
2448     * @param pw the PageWriter to dump log to
2449     * @param uid the UID to log
2450     * @param category category of data (e.g. "total", "last", "unplugged", "current" )
2451     * @param type type of data (e.g. "wakelock", "sensor", "process", "apk" ,  "process", "network")
2452     * @param timer a {@link Timer} to dump stats for
2453     * @param rawRealtime the current elapsed realtime of the system in microseconds
2454     * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT
2455     */
2456    private static final void dumpTimer(PrintWriter pw, int uid, String category, String type,
2457                                        Timer timer, long rawRealtime, int which) {
2458        if (timer != null) {
2459            // Convert from microseconds to milliseconds with rounding
2460            final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500)
2461                    / 1000;
2462            final int count = timer.getCountLocked(which);
2463            if (totalTime != 0) {
2464                dumpLine(pw, uid, category, type, totalTime, count);
2465            }
2466        }
2467    }
2468
2469    /**
2470     * Temporary for settings.
2471     */
2472    public final void dumpCheckinLocked(Context context, PrintWriter pw, int which, int reqUid) {
2473        dumpCheckinLocked(context, pw, which, reqUid, BatteryStatsHelper.checkWifiOnly(context));
2474    }
2475
2476    /**
2477     * Checkin server version of dump to produce more compact, computer-readable log.
2478     *
2479     * NOTE: all times are expressed in 'ms'.
2480     */
2481    public final void dumpCheckinLocked(Context context, PrintWriter pw, int which, int reqUid,
2482            boolean wifiOnly) {
2483        final long rawUptime = SystemClock.uptimeMillis() * 1000;
2484        final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
2485        final long batteryUptime = getBatteryUptime(rawUptime);
2486        final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
2487        final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
2488        final long whichBatteryScreenOffUptime = computeBatteryScreenOffUptime(rawUptime, which);
2489        final long whichBatteryScreenOffRealtime = computeBatteryScreenOffRealtime(rawRealtime,
2490                which);
2491        final long totalRealtime = computeRealtime(rawRealtime, which);
2492        final long totalUptime = computeUptime(rawUptime, which);
2493        final long screenOnTime = getScreenOnTime(rawRealtime, which);
2494        final long interactiveTime = getInteractiveTime(rawRealtime, which);
2495        final long powerSaveModeEnabledTime = getPowerSaveModeEnabledTime(rawRealtime, which);
2496        final long deviceIdleModeEnabledTime = getDeviceIdleModeEnabledTime(rawRealtime, which);
2497        final long deviceIdlingTime = getDeviceIdlingTime(rawRealtime, which);
2498        final int connChanges = getNumConnectivityChange(which);
2499        final long phoneOnTime = getPhoneOnTime(rawRealtime, which);
2500
2501        final StringBuilder sb = new StringBuilder(128);
2502
2503        final SparseArray<? extends Uid> uidStats = getUidStats();
2504        final int NU = uidStats.size();
2505
2506        final String category = STAT_NAMES[which];
2507
2508        // Dump "battery" stat
2509        dumpLine(pw, 0 /* uid */, category, BATTERY_DATA,
2510                which == STATS_SINCE_CHARGED ? getStartCount() : "N/A",
2511                whichBatteryRealtime / 1000, whichBatteryUptime / 1000,
2512                totalRealtime / 1000, totalUptime / 1000,
2513                getStartClockTime(),
2514                whichBatteryScreenOffRealtime / 1000, whichBatteryScreenOffUptime / 1000);
2515
2516        // Calculate wakelock times across all uids.
2517        long fullWakeLockTimeTotal = 0;
2518        long partialWakeLockTimeTotal = 0;
2519
2520        for (int iu = 0; iu < NU; iu++) {
2521            final Uid u = uidStats.valueAt(iu);
2522
2523            final ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> wakelocks
2524                    = u.getWakelockStats();
2525            for (int iw=wakelocks.size()-1; iw>=0; iw--) {
2526                final Uid.Wakelock wl = wakelocks.valueAt(iw);
2527
2528                final Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
2529                if (fullWakeTimer != null) {
2530                    fullWakeLockTimeTotal += fullWakeTimer.getTotalTimeLocked(rawRealtime,
2531                            which);
2532                }
2533
2534                final Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
2535                if (partialWakeTimer != null) {
2536                    partialWakeLockTimeTotal += partialWakeTimer.getTotalTimeLocked(
2537                        rawRealtime, which);
2538                }
2539            }
2540        }
2541
2542        // Dump network stats
2543        final long mobileRxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
2544        final long mobileTxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
2545        final long wifiRxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
2546        final long wifiTxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
2547        final long mobileRxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
2548        final long mobileTxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
2549        final long wifiRxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
2550        final long wifiTxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
2551        dumpLine(pw, 0 /* uid */, category, GLOBAL_NETWORK_DATA,
2552                mobileRxTotalBytes, mobileTxTotalBytes, wifiRxTotalBytes, wifiTxTotalBytes,
2553                mobileRxTotalPackets, mobileTxTotalPackets, wifiRxTotalPackets, wifiTxTotalPackets);
2554
2555        // Dump Wifi controller stats
2556        final long wifiOnTime = getWifiOnTime(rawRealtime, which);
2557        final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which);
2558        final long wifiIdleTimeMs = getWifiControllerActivity(CONTROLLER_IDLE_TIME, which);
2559        final long wifiRxTimeMs = getWifiControllerActivity(CONTROLLER_RX_TIME, which);
2560        final long wifiTxTimeMs = getWifiControllerActivity(CONTROLLER_TX_TIME, which);
2561        final long wifiPowerMaMs = getWifiControllerActivity(CONTROLLER_POWER_DRAIN, which);
2562        dumpLine(pw, 0 /* uid */, category, GLOBAL_WIFI_DATA,
2563                wifiOnTime / 1000, wifiRunningTime / 1000,
2564                wifiIdleTimeMs, wifiRxTimeMs, wifiTxTimeMs, wifiPowerMaMs / (1000*60*60));
2565
2566        // Dump Bluetooth controller stats
2567        final long btIdleTimeMs = getBluetoothControllerActivity(CONTROLLER_IDLE_TIME, which);
2568        final long btRxTimeMs = getBluetoothControllerActivity(CONTROLLER_RX_TIME, which);
2569        final long btTxTimeMs = getBluetoothControllerActivity(CONTROLLER_TX_TIME, which);
2570        final long btPowerMaMs = getBluetoothControllerActivity(CONTROLLER_POWER_DRAIN, which);
2571        dumpLine(pw, 0 /* uid */, category, GLOBAL_BLUETOOTH_DATA,
2572                btIdleTimeMs, btRxTimeMs, btTxTimeMs, btPowerMaMs / (1000*60*60));
2573
2574        // Dump misc stats
2575        dumpLine(pw, 0 /* uid */, category, MISC_DATA,
2576                screenOnTime / 1000, phoneOnTime / 1000,
2577                fullWakeLockTimeTotal / 1000, partialWakeLockTimeTotal / 1000,
2578                getMobileRadioActiveTime(rawRealtime, which) / 1000,
2579                getMobileRadioActiveAdjustedTime(which) / 1000, interactiveTime / 1000,
2580                powerSaveModeEnabledTime / 1000, connChanges, deviceIdleModeEnabledTime / 1000,
2581                getDeviceIdleModeEnabledCount(which), deviceIdlingTime / 1000,
2582                getDeviceIdlingCount(which));
2583
2584        // Dump screen brightness stats
2585        Object[] args = new Object[NUM_SCREEN_BRIGHTNESS_BINS];
2586        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
2587            args[i] = getScreenBrightnessTime(i, rawRealtime, which) / 1000;
2588        }
2589        dumpLine(pw, 0 /* uid */, category, SCREEN_BRIGHTNESS_DATA, args);
2590
2591        // Dump signal strength stats
2592        args = new Object[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
2593        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
2594            args[i] = getPhoneSignalStrengthTime(i, rawRealtime, which) / 1000;
2595        }
2596        dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_TIME_DATA, args);
2597        dumpLine(pw, 0 /* uid */, category, SIGNAL_SCANNING_TIME_DATA,
2598                getPhoneSignalScanningTime(rawRealtime, which) / 1000);
2599        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
2600            args[i] = getPhoneSignalStrengthCount(i, which);
2601        }
2602        dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_COUNT_DATA, args);
2603
2604        // Dump network type stats
2605        args = new Object[NUM_DATA_CONNECTION_TYPES];
2606        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
2607            args[i] = getPhoneDataConnectionTime(i, rawRealtime, which) / 1000;
2608        }
2609        dumpLine(pw, 0 /* uid */, category, DATA_CONNECTION_TIME_DATA, args);
2610        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
2611            args[i] = getPhoneDataConnectionCount(i, which);
2612        }
2613        dumpLine(pw, 0 /* uid */, category, DATA_CONNECTION_COUNT_DATA, args);
2614
2615        // Dump wifi state stats
2616        args = new Object[NUM_WIFI_STATES];
2617        for (int i=0; i<NUM_WIFI_STATES; i++) {
2618            args[i] = getWifiStateTime(i, rawRealtime, which) / 1000;
2619        }
2620        dumpLine(pw, 0 /* uid */, category, WIFI_STATE_TIME_DATA, args);
2621        for (int i=0; i<NUM_WIFI_STATES; i++) {
2622            args[i] = getWifiStateCount(i, which);
2623        }
2624        dumpLine(pw, 0 /* uid */, category, WIFI_STATE_COUNT_DATA, args);
2625
2626        // Dump wifi suppl state stats
2627        args = new Object[NUM_WIFI_SUPPL_STATES];
2628        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
2629            args[i] = getWifiSupplStateTime(i, rawRealtime, which) / 1000;
2630        }
2631        dumpLine(pw, 0 /* uid */, category, WIFI_SUPPL_STATE_TIME_DATA, args);
2632        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
2633            args[i] = getWifiSupplStateCount(i, which);
2634        }
2635        dumpLine(pw, 0 /* uid */, category, WIFI_SUPPL_STATE_COUNT_DATA, args);
2636
2637        // Dump wifi signal strength stats
2638        args = new Object[NUM_WIFI_SIGNAL_STRENGTH_BINS];
2639        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
2640            args[i] = getWifiSignalStrengthTime(i, rawRealtime, which) / 1000;
2641        }
2642        dumpLine(pw, 0 /* uid */, category, WIFI_SIGNAL_STRENGTH_TIME_DATA, args);
2643        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
2644            args[i] = getWifiSignalStrengthCount(i, which);
2645        }
2646        dumpLine(pw, 0 /* uid */, category, WIFI_SIGNAL_STRENGTH_COUNT_DATA, args);
2647
2648        if (which == STATS_SINCE_UNPLUGGED) {
2649            dumpLine(pw, 0 /* uid */, category, BATTERY_LEVEL_DATA, getDischargeStartLevel(),
2650                    getDischargeCurrentLevel());
2651        }
2652
2653        if (which == STATS_SINCE_UNPLUGGED) {
2654            dumpLine(pw, 0 /* uid */, category, BATTERY_DISCHARGE_DATA,
2655                    getDischargeStartLevel()-getDischargeCurrentLevel(),
2656                    getDischargeStartLevel()-getDischargeCurrentLevel(),
2657                    getDischargeAmountScreenOn(), getDischargeAmountScreenOff());
2658        } else {
2659            dumpLine(pw, 0 /* uid */, category, BATTERY_DISCHARGE_DATA,
2660                    getLowDischargeAmountSinceCharge(), getHighDischargeAmountSinceCharge(),
2661                    getDischargeAmountScreenOnSinceCharge(),
2662                    getDischargeAmountScreenOffSinceCharge());
2663        }
2664
2665        if (reqUid < 0) {
2666            final Map<String, ? extends Timer> kernelWakelocks = getKernelWakelockStats();
2667            if (kernelWakelocks.size() > 0) {
2668                for (Map.Entry<String, ? extends Timer> ent : kernelWakelocks.entrySet()) {
2669                    sb.setLength(0);
2670                    printWakeLockCheckin(sb, ent.getValue(), rawRealtime, null, which, "");
2671                    dumpLine(pw, 0 /* uid */, category, KERNEL_WAKELOCK_DATA, ent.getKey(),
2672                            sb.toString());
2673                }
2674            }
2675            final Map<String, ? extends Timer> wakeupReasons = getWakeupReasonStats();
2676            if (wakeupReasons.size() > 0) {
2677                for (Map.Entry<String, ? extends Timer> ent : wakeupReasons.entrySet()) {
2678                    // Not doing the regular wake lock formatting to remain compatible
2679                    // with the old checkin format.
2680                    long totalTimeMicros = ent.getValue().getTotalTimeLocked(rawRealtime, which);
2681                    int count = ent.getValue().getCountLocked(which);
2682                    dumpLine(pw, 0 /* uid */, category, WAKEUP_REASON_DATA,
2683                            "\"" + ent.getKey() + "\"", (totalTimeMicros + 500) / 1000, count);
2684                }
2685            }
2686        }
2687
2688        final BatteryStatsHelper helper = new BatteryStatsHelper(context, false, wifiOnly);
2689        helper.create(this);
2690        helper.refreshStats(which, UserHandle.USER_ALL);
2691        final List<BatterySipper> sippers = helper.getUsageList();
2692        if (sippers != null && sippers.size() > 0) {
2693            dumpLine(pw, 0 /* uid */, category, POWER_USE_SUMMARY_DATA,
2694                    BatteryStatsHelper.makemAh(helper.getPowerProfile().getBatteryCapacity()),
2695                    BatteryStatsHelper.makemAh(helper.getComputedPower()),
2696                    BatteryStatsHelper.makemAh(helper.getMinDrainedPower()),
2697                    BatteryStatsHelper.makemAh(helper.getMaxDrainedPower()));
2698            for (int i=0; i<sippers.size(); i++) {
2699                final BatterySipper bs = sippers.get(i);
2700                int uid = 0;
2701                String label;
2702                switch (bs.drainType) {
2703                    case IDLE:
2704                        label="idle";
2705                        break;
2706                    case CELL:
2707                        label="cell";
2708                        break;
2709                    case PHONE:
2710                        label="phone";
2711                        break;
2712                    case WIFI:
2713                        label="wifi";
2714                        break;
2715                    case BLUETOOTH:
2716                        label="blue";
2717                        break;
2718                    case SCREEN:
2719                        label="scrn";
2720                        break;
2721                    case FLASHLIGHT:
2722                        label="flashlight";
2723                        break;
2724                    case APP:
2725                        uid = bs.uidObj.getUid();
2726                        label = "uid";
2727                        break;
2728                    case USER:
2729                        uid = UserHandle.getUid(bs.userId, 0);
2730                        label = "user";
2731                        break;
2732                    case UNACCOUNTED:
2733                        label = "unacc";
2734                        break;
2735                    case OVERCOUNTED:
2736                        label = "over";
2737                        break;
2738                    default:
2739                        label = "???";
2740                }
2741                dumpLine(pw, uid, category, POWER_USE_ITEM_DATA, label,
2742                        BatteryStatsHelper.makemAh(bs.totalPowerMah));
2743            }
2744        }
2745
2746        for (int iu = 0; iu < NU; iu++) {
2747            final int uid = uidStats.keyAt(iu);
2748            if (reqUid >= 0 && uid != reqUid) {
2749                continue;
2750            }
2751            final Uid u = uidStats.valueAt(iu);
2752
2753            // Dump Network stats per uid, if any
2754            final long mobileBytesRx = u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
2755            final long mobileBytesTx = u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
2756            final long wifiBytesRx = u.getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
2757            final long wifiBytesTx = u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
2758            final long mobilePacketsRx = u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
2759            final long mobilePacketsTx = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
2760            final long mobileActiveTime = u.getMobileRadioActiveTime(which);
2761            final int mobileActiveCount = u.getMobileRadioActiveCount(which);
2762            final long wifiPacketsRx = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
2763            final long wifiPacketsTx = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
2764            if (mobileBytesRx > 0 || mobileBytesTx > 0 || wifiBytesRx > 0 || wifiBytesTx > 0
2765                    || mobilePacketsRx > 0 || mobilePacketsTx > 0 || wifiPacketsRx > 0
2766                    || wifiPacketsTx > 0 || mobileActiveTime > 0 || mobileActiveCount > 0) {
2767                dumpLine(pw, uid, category, NETWORK_DATA, mobileBytesRx, mobileBytesTx,
2768                        wifiBytesRx, wifiBytesTx,
2769                        mobilePacketsRx, mobilePacketsTx,
2770                        wifiPacketsRx, wifiPacketsTx,
2771                        mobileActiveTime, mobileActiveCount);
2772            }
2773
2774            final long fullWifiLockOnTime = u.getFullWifiLockTime(rawRealtime, which);
2775            final long wifiScanTime = u.getWifiScanTime(rawRealtime, which);
2776            final int wifiScanCount = u.getWifiScanCount(which);
2777            final long uidWifiRunningTime = u.getWifiRunningTime(rawRealtime, which);
2778            final long uidWifiIdleTimeMs = u.getWifiControllerActivity(CONTROLLER_IDLE_TIME, which);
2779            final long uidWifiRxTimeMs = u.getWifiControllerActivity(CONTROLLER_RX_TIME, which);
2780            final long uidWifiTxTimeMs = u.getWifiControllerActivity(CONTROLLER_TX_TIME, which);
2781            if (fullWifiLockOnTime != 0 || wifiScanTime != 0 || wifiScanCount != 0
2782                    || uidWifiRunningTime != 0 || uidWifiIdleTimeMs != 0 || uidWifiRxTimeMs != 0
2783                    || uidWifiTxTimeMs != 0) {
2784                dumpLine(pw, uid, category, WIFI_DATA,
2785                        fullWifiLockOnTime, wifiScanTime, uidWifiRunningTime, wifiScanCount,
2786                        uidWifiIdleTimeMs, uidWifiRxTimeMs, uidWifiTxTimeMs);
2787            }
2788
2789            if (u.hasUserActivity()) {
2790                args = new Object[Uid.NUM_USER_ACTIVITY_TYPES];
2791                boolean hasData = false;
2792                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
2793                    int val = u.getUserActivityCount(i, which);
2794                    args[i] = val;
2795                    if (val != 0) hasData = true;
2796                }
2797                if (hasData) {
2798                    dumpLine(pw, uid /* uid */, category, USER_ACTIVITY_DATA, args);
2799                }
2800            }
2801
2802            final ArrayMap<String, ? extends Uid.Wakelock> wakelocks = u.getWakelockStats();
2803            for (int iw=wakelocks.size()-1; iw>=0; iw--) {
2804                final Uid.Wakelock wl = wakelocks.valueAt(iw);
2805                String linePrefix = "";
2806                sb.setLength(0);
2807                linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_FULL),
2808                        rawRealtime, "f", which, linePrefix);
2809                linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL),
2810                        rawRealtime, "p", which, linePrefix);
2811                linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_WINDOW),
2812                        rawRealtime, "w", which, linePrefix);
2813
2814                // Only log if we had at lease one wakelock...
2815                if (sb.length() > 0) {
2816                    String name = wakelocks.keyAt(iw);
2817                    if (name.indexOf(',') >= 0) {
2818                        name = name.replace(',', '_');
2819                    }
2820                    dumpLine(pw, uid, category, WAKELOCK_DATA, name, sb.toString());
2821                }
2822            }
2823
2824            final ArrayMap<String, ? extends Timer> syncs = u.getSyncStats();
2825            for (int isy=syncs.size()-1; isy>=0; isy--) {
2826                final Timer timer = syncs.valueAt(isy);
2827                // Convert from microseconds to milliseconds with rounding
2828                final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
2829                final int count = timer.getCountLocked(which);
2830                if (totalTime != 0) {
2831                    dumpLine(pw, uid, category, SYNC_DATA, syncs.keyAt(isy), totalTime, count);
2832                }
2833            }
2834
2835            final ArrayMap<String, ? extends Timer> jobs = u.getJobStats();
2836            for (int ij=jobs.size()-1; ij>=0; ij--) {
2837                final Timer timer = jobs.valueAt(ij);
2838                // Convert from microseconds to milliseconds with rounding
2839                final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
2840                final int count = timer.getCountLocked(which);
2841                if (totalTime != 0) {
2842                    dumpLine(pw, uid, category, JOB_DATA, jobs.keyAt(ij), totalTime, count);
2843                }
2844            }
2845
2846            dumpTimer(pw, uid, category, FLASHLIGHT_DATA, u.getFlashlightTurnedOnTimer(),
2847                    rawRealtime, which);
2848            dumpTimer(pw, uid, category, CAMERA_DATA, u.getCameraTurnedOnTimer(),
2849                    rawRealtime, which);
2850            dumpTimer(pw, uid, category, VIDEO_DATA, u.getVideoTurnedOnTimer(),
2851                    rawRealtime, which);
2852            dumpTimer(pw, uid, category, AUDIO_DATA, u.getAudioTurnedOnTimer(),
2853                    rawRealtime, which);
2854
2855            final SparseArray<? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
2856            final int NSE = sensors.size();
2857            for (int ise=0; ise<NSE; ise++) {
2858                final Uid.Sensor se = sensors.valueAt(ise);
2859                final int sensorNumber = sensors.keyAt(ise);
2860                final Timer timer = se.getSensorTime();
2861                if (timer != null) {
2862                    // Convert from microseconds to milliseconds with rounding
2863                    final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500)
2864                            / 1000;
2865                    final int count = timer.getCountLocked(which);
2866                    if (totalTime != 0) {
2867                        dumpLine(pw, uid, category, SENSOR_DATA, sensorNumber, totalTime, count);
2868                    }
2869                }
2870            }
2871
2872            dumpTimer(pw, uid, category, VIBRATOR_DATA, u.getVibratorOnTimer(),
2873                    rawRealtime, which);
2874
2875            dumpTimer(pw, uid, category, FOREGROUND_DATA, u.getForegroundActivityTimer(),
2876                    rawRealtime, which);
2877
2878            final Object[] stateTimes = new Object[Uid.NUM_PROCESS_STATE];
2879            long totalStateTime = 0;
2880            for (int ips=0; ips<Uid.NUM_PROCESS_STATE; ips++) {
2881                totalStateTime += u.getProcessStateTime(ips, rawRealtime, which);
2882                stateTimes[ips] = (totalStateTime + 500) / 1000;
2883            }
2884            if (totalStateTime > 0) {
2885                dumpLine(pw, uid, category, STATE_TIME_DATA, stateTimes);
2886            }
2887
2888            final ArrayMap<String, ? extends BatteryStats.Uid.Proc> processStats
2889                    = u.getProcessStats();
2890            for (int ipr=processStats.size()-1; ipr>=0; ipr--) {
2891                final Uid.Proc ps = processStats.valueAt(ipr);
2892
2893                final long userMillis = ps.getUserTime(which);
2894                final long systemMillis = ps.getSystemTime(which);
2895                final long foregroundMillis = ps.getForegroundTime(which);
2896                final int starts = ps.getStarts(which);
2897                final int numCrashes = ps.getNumCrashes(which);
2898                final int numAnrs = ps.getNumAnrs(which);
2899
2900                if (userMillis != 0 || systemMillis != 0 || foregroundMillis != 0
2901                        || starts != 0 || numAnrs != 0 || numCrashes != 0) {
2902                    dumpLine(pw, uid, category, PROCESS_DATA, processStats.keyAt(ipr), userMillis,
2903                            systemMillis, foregroundMillis, starts, numAnrs, numCrashes);
2904                }
2905            }
2906
2907            final ArrayMap<String, ? extends BatteryStats.Uid.Pkg> packageStats
2908                    = u.getPackageStats();
2909            for (int ipkg=packageStats.size()-1; ipkg>=0; ipkg--) {
2910                final Uid.Pkg ps = packageStats.valueAt(ipkg);
2911                int wakeups = 0;
2912                final ArrayMap<String, ? extends Counter> alarms = ps.getWakeupAlarmStats();
2913                for (int iwa=alarms.size()-1; iwa>=0; iwa--) {
2914                    wakeups += alarms.valueAt(iwa).getCountLocked(which);
2915                }
2916                final ArrayMap<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
2917                for (int isvc=serviceStats.size()-1; isvc>=0; isvc--) {
2918                    final BatteryStats.Uid.Pkg.Serv ss = serviceStats.valueAt(isvc);
2919                    final long startTime = ss.getStartTime(batteryUptime, which);
2920                    final int starts = ss.getStarts(which);
2921                    final int launches = ss.getLaunches(which);
2922                    if (startTime != 0 || starts != 0 || launches != 0) {
2923                        dumpLine(pw, uid, category, APK_DATA,
2924                                wakeups, // wakeup alarms
2925                                packageStats.keyAt(ipkg), // Apk
2926                                serviceStats.keyAt(isvc), // service
2927                                startTime / 1000, // time spent started, in ms
2928                                starts,
2929                                launches);
2930                    }
2931                }
2932            }
2933        }
2934    }
2935
2936    static final class TimerEntry {
2937        final String mName;
2938        final int mId;
2939        final BatteryStats.Timer mTimer;
2940        final long mTime;
2941        TimerEntry(String name, int id, BatteryStats.Timer timer, long time) {
2942            mName = name;
2943            mId = id;
2944            mTimer = timer;
2945            mTime = time;
2946        }
2947    }
2948
2949    private void printmAh(PrintWriter printer, double power) {
2950        printer.print(BatteryStatsHelper.makemAh(power));
2951    }
2952
2953    /**
2954     * Temporary for settings.
2955     */
2956    public final void dumpLocked(Context context, PrintWriter pw, String prefix, int which,
2957            int reqUid) {
2958        dumpLocked(context, pw, prefix, which, reqUid, BatteryStatsHelper.checkWifiOnly(context));
2959    }
2960
2961    @SuppressWarnings("unused")
2962    public final void dumpLocked(Context context, PrintWriter pw, String prefix, final int which,
2963            int reqUid, boolean wifiOnly) {
2964        final long rawUptime = SystemClock.uptimeMillis() * 1000;
2965        final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
2966        final long batteryUptime = getBatteryUptime(rawUptime);
2967
2968        final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
2969        final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
2970        final long totalRealtime = computeRealtime(rawRealtime, which);
2971        final long totalUptime = computeUptime(rawUptime, which);
2972        final long whichBatteryScreenOffUptime = computeBatteryScreenOffUptime(rawUptime, which);
2973        final long whichBatteryScreenOffRealtime = computeBatteryScreenOffRealtime(rawRealtime,
2974                which);
2975        final long batteryTimeRemaining = computeBatteryTimeRemaining(rawRealtime);
2976        final long chargeTimeRemaining = computeChargeTimeRemaining(rawRealtime);
2977
2978        final StringBuilder sb = new StringBuilder(128);
2979
2980        final SparseArray<? extends Uid> uidStats = getUidStats();
2981        final int NU = uidStats.size();
2982
2983        sb.setLength(0);
2984        sb.append(prefix);
2985                sb.append("  Time on battery: ");
2986                formatTimeMs(sb, whichBatteryRealtime / 1000); sb.append("(");
2987                sb.append(formatRatioLocked(whichBatteryRealtime, totalRealtime));
2988                sb.append(") realtime, ");
2989                formatTimeMs(sb, whichBatteryUptime / 1000);
2990                sb.append("("); sb.append(formatRatioLocked(whichBatteryUptime, totalRealtime));
2991                sb.append(") uptime");
2992        pw.println(sb.toString());
2993        sb.setLength(0);
2994        sb.append(prefix);
2995                sb.append("  Time on battery screen off: ");
2996                formatTimeMs(sb, whichBatteryScreenOffRealtime / 1000); sb.append("(");
2997                sb.append(formatRatioLocked(whichBatteryScreenOffRealtime, totalRealtime));
2998                sb.append(") realtime, ");
2999                formatTimeMs(sb, whichBatteryScreenOffUptime / 1000);
3000                sb.append("(");
3001                sb.append(formatRatioLocked(whichBatteryScreenOffUptime, totalRealtime));
3002                sb.append(") uptime");
3003        pw.println(sb.toString());
3004        sb.setLength(0);
3005        sb.append(prefix);
3006                sb.append("  Total run time: ");
3007                formatTimeMs(sb, totalRealtime / 1000);
3008                sb.append("realtime, ");
3009                formatTimeMs(sb, totalUptime / 1000);
3010                sb.append("uptime");
3011        pw.println(sb.toString());
3012        if (batteryTimeRemaining >= 0) {
3013            sb.setLength(0);
3014            sb.append(prefix);
3015                    sb.append("  Battery time remaining: ");
3016                    formatTimeMs(sb, batteryTimeRemaining / 1000);
3017            pw.println(sb.toString());
3018        }
3019        if (chargeTimeRemaining >= 0) {
3020            sb.setLength(0);
3021            sb.append(prefix);
3022                    sb.append("  Charge time remaining: ");
3023                    formatTimeMs(sb, chargeTimeRemaining / 1000);
3024            pw.println(sb.toString());
3025        }
3026        pw.print("  Start clock time: ");
3027        pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss", getStartClockTime()).toString());
3028
3029        final long screenOnTime = getScreenOnTime(rawRealtime, which);
3030        final long interactiveTime = getInteractiveTime(rawRealtime, which);
3031        final long powerSaveModeEnabledTime = getPowerSaveModeEnabledTime(rawRealtime, which);
3032        final long deviceIdleModeEnabledTime = getDeviceIdleModeEnabledTime(rawRealtime, which);
3033        final long deviceIdlingTime = getDeviceIdlingTime(rawRealtime, which);
3034        final long phoneOnTime = getPhoneOnTime(rawRealtime, which);
3035        final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which);
3036        final long wifiOnTime = getWifiOnTime(rawRealtime, which);
3037        sb.setLength(0);
3038        sb.append(prefix);
3039                sb.append("  Screen on: "); formatTimeMs(sb, screenOnTime / 1000);
3040                sb.append("("); sb.append(formatRatioLocked(screenOnTime, whichBatteryRealtime));
3041                sb.append(") "); sb.append(getScreenOnCount(which));
3042                sb.append("x, Interactive: "); formatTimeMs(sb, interactiveTime / 1000);
3043                sb.append("("); sb.append(formatRatioLocked(interactiveTime, whichBatteryRealtime));
3044                sb.append(")");
3045        pw.println(sb.toString());
3046        sb.setLength(0);
3047        sb.append(prefix);
3048        sb.append("  Screen brightnesses:");
3049        boolean didOne = false;
3050        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
3051            final long time = getScreenBrightnessTime(i, rawRealtime, which);
3052            if (time == 0) {
3053                continue;
3054            }
3055            sb.append("\n    ");
3056            sb.append(prefix);
3057            didOne = true;
3058            sb.append(SCREEN_BRIGHTNESS_NAMES[i]);
3059            sb.append(" ");
3060            formatTimeMs(sb, time/1000);
3061            sb.append("(");
3062            sb.append(formatRatioLocked(time, screenOnTime));
3063            sb.append(")");
3064        }
3065        if (!didOne) sb.append(" (no activity)");
3066        pw.println(sb.toString());
3067        if (powerSaveModeEnabledTime != 0) {
3068            sb.setLength(0);
3069            sb.append(prefix);
3070                    sb.append("  Power save mode enabled: ");
3071                    formatTimeMs(sb, powerSaveModeEnabledTime / 1000);
3072                    sb.append("(");
3073                    sb.append(formatRatioLocked(powerSaveModeEnabledTime, whichBatteryRealtime));
3074                    sb.append(")");
3075            pw.println(sb.toString());
3076        }
3077        if (deviceIdlingTime != 0) {
3078            sb.setLength(0);
3079            sb.append(prefix);
3080                    sb.append("  Device idling: ");
3081                    formatTimeMs(sb, deviceIdlingTime / 1000);
3082                    sb.append("(");
3083                    sb.append(formatRatioLocked(deviceIdlingTime, whichBatteryRealtime));
3084                    sb.append(") "); sb.append(getDeviceIdlingCount(which));
3085                    sb.append("x");
3086            pw.println(sb.toString());
3087        }
3088        if (deviceIdleModeEnabledTime != 0) {
3089            sb.setLength(0);
3090            sb.append(prefix);
3091                    sb.append("  Idle mode time: ");
3092                    formatTimeMs(sb, deviceIdleModeEnabledTime / 1000);
3093                    sb.append("(");
3094                    sb.append(formatRatioLocked(deviceIdleModeEnabledTime, whichBatteryRealtime));
3095                    sb.append(") "); sb.append(getDeviceIdleModeEnabledCount(which));
3096                    sb.append("x");
3097            pw.println(sb.toString());
3098        }
3099        if (phoneOnTime != 0) {
3100            sb.setLength(0);
3101            sb.append(prefix);
3102                    sb.append("  Active phone call: "); formatTimeMs(sb, phoneOnTime / 1000);
3103                    sb.append("("); sb.append(formatRatioLocked(phoneOnTime, whichBatteryRealtime));
3104                    sb.append(") "); sb.append(getPhoneOnCount(which)); sb.append("x");
3105        }
3106        final int connChanges = getNumConnectivityChange(which);
3107        if (connChanges != 0) {
3108            pw.print(prefix);
3109            pw.print("  Connectivity changes: "); pw.println(connChanges);
3110        }
3111
3112        // Calculate wakelock times across all uids.
3113        long fullWakeLockTimeTotalMicros = 0;
3114        long partialWakeLockTimeTotalMicros = 0;
3115
3116        final ArrayList<TimerEntry> timers = new ArrayList<>();
3117
3118        for (int iu = 0; iu < NU; iu++) {
3119            final Uid u = uidStats.valueAt(iu);
3120
3121            final ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> wakelocks
3122                    = u.getWakelockStats();
3123            for (int iw=wakelocks.size()-1; iw>=0; iw--) {
3124                final Uid.Wakelock wl = wakelocks.valueAt(iw);
3125
3126                final Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
3127                if (fullWakeTimer != null) {
3128                    fullWakeLockTimeTotalMicros += fullWakeTimer.getTotalTimeLocked(
3129                            rawRealtime, which);
3130                }
3131
3132                final Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
3133                if (partialWakeTimer != null) {
3134                    final long totalTimeMicros = partialWakeTimer.getTotalTimeLocked(
3135                            rawRealtime, which);
3136                    if (totalTimeMicros > 0) {
3137                        if (reqUid < 0) {
3138                            // Only show the ordered list of all wake
3139                            // locks if the caller is not asking for data
3140                            // about a specific uid.
3141                            timers.add(new TimerEntry(wakelocks.keyAt(iw), u.getUid(),
3142                                    partialWakeTimer, totalTimeMicros));
3143                        }
3144                        partialWakeLockTimeTotalMicros += totalTimeMicros;
3145                    }
3146                }
3147            }
3148        }
3149
3150        final long mobileRxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
3151        final long mobileTxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
3152        final long wifiRxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
3153        final long wifiTxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
3154        final long mobileRxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
3155        final long mobileTxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
3156        final long wifiRxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
3157        final long wifiTxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
3158
3159        if (fullWakeLockTimeTotalMicros != 0) {
3160            sb.setLength(0);
3161            sb.append(prefix);
3162                    sb.append("  Total full wakelock time: "); formatTimeMsNoSpace(sb,
3163                            (fullWakeLockTimeTotalMicros + 500) / 1000);
3164            pw.println(sb.toString());
3165        }
3166
3167        if (partialWakeLockTimeTotalMicros != 0) {
3168            sb.setLength(0);
3169            sb.append(prefix);
3170                    sb.append("  Total partial wakelock time: "); formatTimeMsNoSpace(sb,
3171                            (partialWakeLockTimeTotalMicros + 500) / 1000);
3172            pw.println(sb.toString());
3173        }
3174
3175        pw.print(prefix);
3176                pw.print("  Mobile total received: "); pw.print(formatBytesLocked(mobileRxTotalBytes));
3177                pw.print(", sent: "); pw.print(formatBytesLocked(mobileTxTotalBytes));
3178                pw.print(" (packets received "); pw.print(mobileRxTotalPackets);
3179                pw.print(", sent "); pw.print(mobileTxTotalPackets); pw.println(")");
3180        sb.setLength(0);
3181        sb.append(prefix);
3182        sb.append("  Phone signal levels:");
3183        didOne = false;
3184        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
3185            final long time = getPhoneSignalStrengthTime(i, rawRealtime, which);
3186            if (time == 0) {
3187                continue;
3188            }
3189            sb.append("\n    ");
3190            sb.append(prefix);
3191            didOne = true;
3192            sb.append(SignalStrength.SIGNAL_STRENGTH_NAMES[i]);
3193            sb.append(" ");
3194            formatTimeMs(sb, time/1000);
3195            sb.append("(");
3196            sb.append(formatRatioLocked(time, whichBatteryRealtime));
3197            sb.append(") ");
3198            sb.append(getPhoneSignalStrengthCount(i, which));
3199            sb.append("x");
3200        }
3201        if (!didOne) sb.append(" (no activity)");
3202        pw.println(sb.toString());
3203
3204        sb.setLength(0);
3205        sb.append(prefix);
3206        sb.append("  Signal scanning time: ");
3207        formatTimeMsNoSpace(sb, getPhoneSignalScanningTime(rawRealtime, which) / 1000);
3208        pw.println(sb.toString());
3209
3210        sb.setLength(0);
3211        sb.append(prefix);
3212        sb.append("  Radio types:");
3213        didOne = false;
3214        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
3215            final long time = getPhoneDataConnectionTime(i, rawRealtime, which);
3216            if (time == 0) {
3217                continue;
3218            }
3219            sb.append("\n    ");
3220            sb.append(prefix);
3221            didOne = true;
3222            sb.append(DATA_CONNECTION_NAMES[i]);
3223            sb.append(" ");
3224            formatTimeMs(sb, time/1000);
3225            sb.append("(");
3226            sb.append(formatRatioLocked(time, whichBatteryRealtime));
3227            sb.append(") ");
3228            sb.append(getPhoneDataConnectionCount(i, which));
3229            sb.append("x");
3230        }
3231        if (!didOne) sb.append(" (no activity)");
3232        pw.println(sb.toString());
3233
3234        sb.setLength(0);
3235        sb.append(prefix);
3236        sb.append("  Mobile radio active time: ");
3237        final long mobileActiveTime = getMobileRadioActiveTime(rawRealtime, which);
3238        formatTimeMs(sb, mobileActiveTime / 1000);
3239        sb.append("("); sb.append(formatRatioLocked(mobileActiveTime, whichBatteryRealtime));
3240        sb.append(") "); sb.append(getMobileRadioActiveCount(which));
3241        sb.append("x");
3242        pw.println(sb.toString());
3243
3244        final long mobileActiveUnknownTime = getMobileRadioActiveUnknownTime(which);
3245        if (mobileActiveUnknownTime != 0) {
3246            sb.setLength(0);
3247            sb.append(prefix);
3248            sb.append("  Mobile radio active unknown time: ");
3249            formatTimeMs(sb, mobileActiveUnknownTime / 1000);
3250            sb.append("(");
3251            sb.append(formatRatioLocked(mobileActiveUnknownTime, whichBatteryRealtime));
3252            sb.append(") "); sb.append(getMobileRadioActiveUnknownCount(which));
3253            sb.append("x");
3254            pw.println(sb.toString());
3255        }
3256
3257        final long mobileActiveAdjustedTime = getMobileRadioActiveAdjustedTime(which);
3258        if (mobileActiveAdjustedTime != 0) {
3259            sb.setLength(0);
3260            sb.append(prefix);
3261            sb.append("  Mobile radio active adjusted time: ");
3262            formatTimeMs(sb, mobileActiveAdjustedTime / 1000);
3263            sb.append("(");
3264            sb.append(formatRatioLocked(mobileActiveAdjustedTime, whichBatteryRealtime));
3265            sb.append(")");
3266            pw.println(sb.toString());
3267        }
3268
3269        pw.print(prefix);
3270                pw.print("  Wi-Fi total received: "); pw.print(formatBytesLocked(wifiRxTotalBytes));
3271                pw.print(", sent: "); pw.print(formatBytesLocked(wifiTxTotalBytes));
3272                pw.print(" (packets received "); pw.print(wifiRxTotalPackets);
3273                pw.print(", sent "); pw.print(wifiTxTotalPackets); pw.println(")");
3274        sb.setLength(0);
3275        sb.append(prefix);
3276                sb.append("  Wifi on: "); formatTimeMs(sb, wifiOnTime / 1000);
3277                sb.append("("); sb.append(formatRatioLocked(wifiOnTime, whichBatteryRealtime));
3278                sb.append("), Wifi running: "); formatTimeMs(sb, wifiRunningTime / 1000);
3279                sb.append("("); sb.append(formatRatioLocked(wifiRunningTime, whichBatteryRealtime));
3280                sb.append(")");
3281        pw.println(sb.toString());
3282
3283        sb.setLength(0);
3284        sb.append(prefix);
3285        sb.append("  Wifi states:");
3286        didOne = false;
3287        for (int i=0; i<NUM_WIFI_STATES; i++) {
3288            final long time = getWifiStateTime(i, rawRealtime, which);
3289            if (time == 0) {
3290                continue;
3291            }
3292            sb.append("\n    ");
3293            didOne = true;
3294            sb.append(WIFI_STATE_NAMES[i]);
3295            sb.append(" ");
3296            formatTimeMs(sb, time/1000);
3297            sb.append("(");
3298            sb.append(formatRatioLocked(time, whichBatteryRealtime));
3299            sb.append(") ");
3300            sb.append(getWifiStateCount(i, which));
3301            sb.append("x");
3302        }
3303        if (!didOne) sb.append(" (no activity)");
3304        pw.println(sb.toString());
3305
3306        sb.setLength(0);
3307        sb.append(prefix);
3308        sb.append("  Wifi supplicant states:");
3309        didOne = false;
3310        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
3311            final long time = getWifiSupplStateTime(i, rawRealtime, which);
3312            if (time == 0) {
3313                continue;
3314            }
3315            sb.append("\n    ");
3316            didOne = true;
3317            sb.append(WIFI_SUPPL_STATE_NAMES[i]);
3318            sb.append(" ");
3319            formatTimeMs(sb, time/1000);
3320            sb.append("(");
3321            sb.append(formatRatioLocked(time, whichBatteryRealtime));
3322            sb.append(") ");
3323            sb.append(getWifiSupplStateCount(i, which));
3324            sb.append("x");
3325        }
3326        if (!didOne) sb.append(" (no activity)");
3327        pw.println(sb.toString());
3328
3329        sb.setLength(0);
3330        sb.append(prefix);
3331        sb.append("  Wifi signal levels:");
3332        didOne = false;
3333        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
3334            final long time = getWifiSignalStrengthTime(i, rawRealtime, which);
3335            if (time == 0) {
3336                continue;
3337            }
3338            sb.append("\n    ");
3339            sb.append(prefix);
3340            didOne = true;
3341            sb.append("level(");
3342            sb.append(i);
3343            sb.append(") ");
3344            formatTimeMs(sb, time/1000);
3345            sb.append("(");
3346            sb.append(formatRatioLocked(time, whichBatteryRealtime));
3347            sb.append(") ");
3348            sb.append(getWifiSignalStrengthCount(i, which));
3349            sb.append("x");
3350        }
3351        if (!didOne) sb.append(" (no activity)");
3352        pw.println(sb.toString());
3353
3354        final long wifiIdleTimeMs = getWifiControllerActivity(CONTROLLER_IDLE_TIME, which);
3355        final long wifiRxTimeMs = getWifiControllerActivity(CONTROLLER_RX_TIME, which);
3356        final long wifiTxTimeMs = getWifiControllerActivity(CONTROLLER_TX_TIME, which);
3357        final long wifiTotalTimeMs = wifiIdleTimeMs + wifiRxTimeMs + wifiTxTimeMs;
3358
3359        sb.setLength(0);
3360        sb.append(prefix);
3361        sb.append("  WiFi Idle time: "); formatTimeMs(sb, wifiIdleTimeMs);
3362        sb.append(" (");
3363        sb.append(formatRatioLocked(wifiIdleTimeMs, wifiTotalTimeMs));
3364        sb.append(")");
3365        pw.println(sb.toString());
3366
3367        sb.setLength(0);
3368        sb.append(prefix);
3369        sb.append("  WiFi Rx time:   "); formatTimeMs(sb, wifiRxTimeMs);
3370        sb.append(" (");
3371        sb.append(formatRatioLocked(wifiRxTimeMs, wifiTotalTimeMs));
3372        sb.append(")");
3373        pw.println(sb.toString());
3374
3375        sb.setLength(0);
3376        sb.append(prefix);
3377        sb.append("  WiFi Tx time:   "); formatTimeMs(sb, wifiTxTimeMs);
3378        sb.append(" (");
3379        sb.append(formatRatioLocked(wifiTxTimeMs, wifiTotalTimeMs));
3380        sb.append(")");
3381        pw.println(sb.toString());
3382
3383        sb.setLength(0);
3384        sb.append(prefix);
3385        sb.append("  WiFi Power drain: ").append(BatteryStatsHelper.makemAh(
3386                getWifiControllerActivity(CONTROLLER_POWER_DRAIN, which) / (double)(1000*60*60)));
3387        sb.append(" mAh");
3388        pw.println(sb.toString());
3389
3390        final long bluetoothIdleTimeMs =
3391                getBluetoothControllerActivity(CONTROLLER_IDLE_TIME, which);
3392        final long bluetoothRxTimeMs = getBluetoothControllerActivity(CONTROLLER_RX_TIME, which);
3393        final long bluetoothTxTimeMs = getBluetoothControllerActivity(CONTROLLER_TX_TIME, which);
3394        final long bluetoothTotalTimeMs = bluetoothIdleTimeMs + bluetoothRxTimeMs +
3395                bluetoothTxTimeMs;
3396
3397        sb.setLength(0);
3398        sb.append(prefix);
3399        sb.append("  Bluetooth Idle time: "); formatTimeMs(sb, bluetoothIdleTimeMs);
3400        sb.append(" (");
3401        sb.append(formatRatioLocked(bluetoothIdleTimeMs, bluetoothTotalTimeMs));
3402        sb.append(")");
3403        pw.println(sb.toString());
3404
3405        sb.setLength(0);
3406        sb.append(prefix);
3407        sb.append("  Bluetooth Rx time:   "); formatTimeMs(sb, bluetoothRxTimeMs);
3408        sb.append(" (");
3409        sb.append(formatRatioLocked(bluetoothRxTimeMs, bluetoothTotalTimeMs));
3410        sb.append(")");
3411        pw.println(sb.toString());
3412
3413        sb.setLength(0);
3414        sb.append(prefix);
3415        sb.append("  Bluetooth Tx time:   "); formatTimeMs(sb, bluetoothTxTimeMs);
3416        sb.append(" (");
3417        sb.append(formatRatioLocked(bluetoothTxTimeMs, bluetoothTotalTimeMs));
3418        sb.append(")");
3419        pw.println(sb.toString());
3420
3421        sb.setLength(0);
3422        sb.append(prefix);
3423        sb.append("  Bluetooth Power drain: ").append(BatteryStatsHelper.makemAh(
3424                getBluetoothControllerActivity(CONTROLLER_POWER_DRAIN, which) /
3425                        (double)(1000*60*60)));
3426        sb.append(" mAh");
3427        pw.println(sb.toString());
3428
3429        pw.println();
3430
3431        if (which == STATS_SINCE_UNPLUGGED) {
3432            if (getIsOnBattery()) {
3433                pw.print(prefix); pw.println("  Device is currently unplugged");
3434                pw.print(prefix); pw.print("    Discharge cycle start level: ");
3435                        pw.println(getDischargeStartLevel());
3436                pw.print(prefix); pw.print("    Discharge cycle current level: ");
3437                        pw.println(getDischargeCurrentLevel());
3438            } else {
3439                pw.print(prefix); pw.println("  Device is currently plugged into power");
3440                pw.print(prefix); pw.print("    Last discharge cycle start level: ");
3441                        pw.println(getDischargeStartLevel());
3442                pw.print(prefix); pw.print("    Last discharge cycle end level: ");
3443                        pw.println(getDischargeCurrentLevel());
3444            }
3445            pw.print(prefix); pw.print("    Amount discharged while screen on: ");
3446                    pw.println(getDischargeAmountScreenOn());
3447            pw.print(prefix); pw.print("    Amount discharged while screen off: ");
3448                    pw.println(getDischargeAmountScreenOff());
3449            pw.println(" ");
3450        } else {
3451            pw.print(prefix); pw.println("  Device battery use since last full charge");
3452            pw.print(prefix); pw.print("    Amount discharged (lower bound): ");
3453                    pw.println(getLowDischargeAmountSinceCharge());
3454            pw.print(prefix); pw.print("    Amount discharged (upper bound): ");
3455                    pw.println(getHighDischargeAmountSinceCharge());
3456            pw.print(prefix); pw.print("    Amount discharged while screen on: ");
3457                    pw.println(getDischargeAmountScreenOnSinceCharge());
3458            pw.print(prefix); pw.print("    Amount discharged while screen off: ");
3459                    pw.println(getDischargeAmountScreenOffSinceCharge());
3460            pw.println();
3461        }
3462
3463        final BatteryStatsHelper helper = new BatteryStatsHelper(context, false, wifiOnly);
3464        helper.create(this);
3465        helper.refreshStats(which, UserHandle.USER_ALL);
3466        List<BatterySipper> sippers = helper.getUsageList();
3467        if (sippers != null && sippers.size() > 0) {
3468            pw.print(prefix); pw.println("  Estimated power use (mAh):");
3469            pw.print(prefix); pw.print("    Capacity: ");
3470                    printmAh(pw, helper.getPowerProfile().getBatteryCapacity());
3471                    pw.print(", Computed drain: "); printmAh(pw, helper.getComputedPower());
3472                    pw.print(", actual drain: "); printmAh(pw, helper.getMinDrainedPower());
3473                    if (helper.getMinDrainedPower() != helper.getMaxDrainedPower()) {
3474                        pw.print("-"); printmAh(pw, helper.getMaxDrainedPower());
3475                    }
3476                    pw.println();
3477            for (int i=0; i<sippers.size(); i++) {
3478                final BatterySipper bs = sippers.get(i);
3479                switch (bs.drainType) {
3480                    case IDLE:
3481                        pw.print(prefix); pw.print("    Idle: "); printmAh(pw, bs.totalPowerMah);
3482                        pw.println();
3483                        break;
3484                    case CELL:
3485                        pw.print(prefix); pw.print("    Cell standby: "); printmAh(pw, bs.totalPowerMah);
3486                        pw.println();
3487                        break;
3488                    case PHONE:
3489                        pw.print(prefix); pw.print("    Phone calls: "); printmAh(pw, bs.totalPowerMah);
3490                        pw.println();
3491                        break;
3492                    case WIFI:
3493                        pw.print(prefix); pw.print("    Wifi: "); printmAh(pw, bs.totalPowerMah);
3494                        pw.println();
3495                        break;
3496                    case BLUETOOTH:
3497                        pw.print(prefix); pw.print("    Bluetooth: "); printmAh(pw, bs.totalPowerMah);
3498                        pw.println();
3499                        break;
3500                    case SCREEN:
3501                        pw.print(prefix); pw.print("    Screen: "); printmAh(pw, bs.totalPowerMah);
3502                        pw.println();
3503                        break;
3504                    case FLASHLIGHT:
3505                        pw.print(prefix); pw.print("    Flashlight: "); printmAh(pw, bs.totalPowerMah);
3506                        pw.println();
3507                        break;
3508                    case APP:
3509                        pw.print(prefix); pw.print("    Uid ");
3510                        UserHandle.formatUid(pw, bs.uidObj.getUid());
3511                        pw.print(": "); printmAh(pw, bs.totalPowerMah); pw.println();
3512                        break;
3513                    case USER:
3514                        pw.print(prefix); pw.print("    User "); pw.print(bs.userId);
3515                        pw.print(": "); printmAh(pw, bs.totalPowerMah); pw.println();
3516                        break;
3517                    case UNACCOUNTED:
3518                        pw.print(prefix); pw.print("    Unaccounted: "); printmAh(pw, bs.totalPowerMah);
3519                        pw.println();
3520                        break;
3521                    case OVERCOUNTED:
3522                        pw.print(prefix); pw.print("    Over-counted: "); printmAh(pw, bs.totalPowerMah);
3523                        pw.println();
3524                        break;
3525                }
3526            }
3527            pw.println();
3528        }
3529
3530        sippers = helper.getMobilemsppList();
3531        if (sippers != null && sippers.size() > 0) {
3532            pw.print(prefix); pw.println("  Per-app mobile ms per packet:");
3533            long totalTime = 0;
3534            for (int i=0; i<sippers.size(); i++) {
3535                final BatterySipper bs = sippers.get(i);
3536                sb.setLength(0);
3537                sb.append(prefix); sb.append("    Uid ");
3538                UserHandle.formatUid(sb, bs.uidObj.getUid());
3539                sb.append(": "); sb.append(BatteryStatsHelper.makemAh(bs.mobilemspp));
3540                sb.append(" ("); sb.append(bs.mobileRxPackets+bs.mobileTxPackets);
3541                sb.append(" packets over "); formatTimeMsNoSpace(sb, bs.mobileActive);
3542                sb.append(") "); sb.append(bs.mobileActiveCount); sb.append("x");
3543                pw.println(sb.toString());
3544                totalTime += bs.mobileActive;
3545            }
3546            sb.setLength(0);
3547            sb.append(prefix);
3548            sb.append("    TOTAL TIME: ");
3549            formatTimeMs(sb, totalTime);
3550            sb.append("("); sb.append(formatRatioLocked(totalTime, whichBatteryRealtime));
3551            sb.append(")");
3552            pw.println(sb.toString());
3553            pw.println();
3554        }
3555
3556        final Comparator<TimerEntry> timerComparator = new Comparator<TimerEntry>() {
3557            @Override
3558            public int compare(TimerEntry lhs, TimerEntry rhs) {
3559                long lhsTime = lhs.mTime;
3560                long rhsTime = rhs.mTime;
3561                if (lhsTime < rhsTime) {
3562                    return 1;
3563                }
3564                if (lhsTime > rhsTime) {
3565                    return -1;
3566                }
3567                return 0;
3568            }
3569        };
3570
3571        if (reqUid < 0) {
3572            final Map<String, ? extends BatteryStats.Timer> kernelWakelocks
3573                    = getKernelWakelockStats();
3574            if (kernelWakelocks.size() > 0) {
3575                final ArrayList<TimerEntry> ktimers = new ArrayList<>();
3576                for (Map.Entry<String, ? extends BatteryStats.Timer> ent
3577                        : kernelWakelocks.entrySet()) {
3578                    final BatteryStats.Timer timer = ent.getValue();
3579                    final long totalTimeMillis = computeWakeLock(timer, rawRealtime, which);
3580                    if (totalTimeMillis > 0) {
3581                        ktimers.add(new TimerEntry(ent.getKey(), 0, timer, totalTimeMillis));
3582                    }
3583                }
3584                if (ktimers.size() > 0) {
3585                    Collections.sort(ktimers, timerComparator);
3586                    pw.print(prefix); pw.println("  All kernel wake locks:");
3587                    for (int i=0; i<ktimers.size(); i++) {
3588                        final TimerEntry timer = ktimers.get(i);
3589                        String linePrefix = ": ";
3590                        sb.setLength(0);
3591                        sb.append(prefix);
3592                        sb.append("  Kernel Wake lock ");
3593                        sb.append(timer.mName);
3594                        linePrefix = printWakeLock(sb, timer.mTimer, rawRealtime, null,
3595                                which, linePrefix);
3596                        if (!linePrefix.equals(": ")) {
3597                            sb.append(" realtime");
3598                            // Only print out wake locks that were held
3599                            pw.println(sb.toString());
3600                        }
3601                    }
3602                    pw.println();
3603                }
3604            }
3605
3606            if (timers.size() > 0) {
3607                Collections.sort(timers, timerComparator);
3608                pw.print(prefix); pw.println("  All partial wake locks:");
3609                for (int i=0; i<timers.size(); i++) {
3610                    TimerEntry timer = timers.get(i);
3611                    sb.setLength(0);
3612                    sb.append("  Wake lock ");
3613                    UserHandle.formatUid(sb, timer.mId);
3614                    sb.append(" ");
3615                    sb.append(timer.mName);
3616                    printWakeLock(sb, timer.mTimer, rawRealtime, null, which, ": ");
3617                    sb.append(" realtime");
3618                    pw.println(sb.toString());
3619                }
3620                timers.clear();
3621                pw.println();
3622            }
3623
3624            final Map<String, ? extends Timer> wakeupReasons = getWakeupReasonStats();
3625            if (wakeupReasons.size() > 0) {
3626                pw.print(prefix); pw.println("  All wakeup reasons:");
3627                final ArrayList<TimerEntry> reasons = new ArrayList<>();
3628                for (Map.Entry<String, ? extends Timer> ent : wakeupReasons.entrySet()) {
3629                    final Timer timer = ent.getValue();
3630                    reasons.add(new TimerEntry(ent.getKey(), 0, timer,
3631                            timer.getCountLocked(which)));
3632                }
3633                Collections.sort(reasons, timerComparator);
3634                for (int i=0; i<reasons.size(); i++) {
3635                    TimerEntry timer = reasons.get(i);
3636                    String linePrefix = ": ";
3637                    sb.setLength(0);
3638                    sb.append(prefix);
3639                    sb.append("  Wakeup reason ");
3640                    sb.append(timer.mName);
3641                    printWakeLock(sb, timer.mTimer, rawRealtime, null, which, ": ");
3642                    sb.append(" realtime");
3643                    pw.println(sb.toString());
3644                }
3645                pw.println();
3646            }
3647        }
3648
3649        for (int iu=0; iu<NU; iu++) {
3650            final int uid = uidStats.keyAt(iu);
3651            if (reqUid >= 0 && uid != reqUid && uid != Process.SYSTEM_UID) {
3652                continue;
3653            }
3654
3655            final Uid u = uidStats.valueAt(iu);
3656
3657            pw.print(prefix);
3658            pw.print("  ");
3659            UserHandle.formatUid(pw, uid);
3660            pw.println(":");
3661            boolean uidActivity = false;
3662
3663            final long mobileRxBytes = u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
3664            final long mobileTxBytes = u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
3665            final long wifiRxBytes = u.getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
3666            final long wifiTxBytes = u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
3667            final long mobileRxPackets = u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
3668            final long mobileTxPackets = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
3669            final long uidMobileActiveTime = u.getMobileRadioActiveTime(which);
3670            final int uidMobileActiveCount = u.getMobileRadioActiveCount(which);
3671            final long wifiRxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
3672            final long wifiTxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
3673            final long fullWifiLockOnTime = u.getFullWifiLockTime(rawRealtime, which);
3674            final long wifiScanTime = u.getWifiScanTime(rawRealtime, which);
3675            final int wifiScanCount = u.getWifiScanCount(which);
3676            final long uidWifiRunningTime = u.getWifiRunningTime(rawRealtime, which);
3677
3678            if (mobileRxBytes > 0 || mobileTxBytes > 0
3679                    || mobileRxPackets > 0 || mobileTxPackets > 0) {
3680                pw.print(prefix); pw.print("    Mobile network: ");
3681                        pw.print(formatBytesLocked(mobileRxBytes)); pw.print(" received, ");
3682                        pw.print(formatBytesLocked(mobileTxBytes));
3683                        pw.print(" sent (packets "); pw.print(mobileRxPackets);
3684                        pw.print(" received, "); pw.print(mobileTxPackets); pw.println(" sent)");
3685            }
3686            if (uidMobileActiveTime > 0 || uidMobileActiveCount > 0) {
3687                sb.setLength(0);
3688                sb.append(prefix); sb.append("    Mobile radio active: ");
3689                formatTimeMs(sb, uidMobileActiveTime / 1000);
3690                sb.append("(");
3691                sb.append(formatRatioLocked(uidMobileActiveTime, mobileActiveTime));
3692                sb.append(") "); sb.append(uidMobileActiveCount); sb.append("x");
3693                long packets = mobileRxPackets + mobileTxPackets;
3694                if (packets == 0) {
3695                    packets = 1;
3696                }
3697                sb.append(" @ ");
3698                sb.append(BatteryStatsHelper.makemAh(uidMobileActiveTime / 1000 / (double)packets));
3699                sb.append(" mspp");
3700                pw.println(sb.toString());
3701            }
3702
3703            if (wifiRxBytes > 0 || wifiTxBytes > 0 || wifiRxPackets > 0 || wifiTxPackets > 0) {
3704                pw.print(prefix); pw.print("    Wi-Fi network: ");
3705                        pw.print(formatBytesLocked(wifiRxBytes)); pw.print(" received, ");
3706                        pw.print(formatBytesLocked(wifiTxBytes));
3707                        pw.print(" sent (packets "); pw.print(wifiRxPackets);
3708                        pw.print(" received, "); pw.print(wifiTxPackets); pw.println(" sent)");
3709            }
3710
3711            if (fullWifiLockOnTime != 0 || wifiScanTime != 0 || wifiScanCount != 0
3712                    || uidWifiRunningTime != 0) {
3713                sb.setLength(0);
3714                sb.append(prefix); sb.append("    Wifi Running: ");
3715                        formatTimeMs(sb, uidWifiRunningTime / 1000);
3716                        sb.append("("); sb.append(formatRatioLocked(uidWifiRunningTime,
3717                                whichBatteryRealtime)); sb.append(")\n");
3718                sb.append(prefix); sb.append("    Full Wifi Lock: ");
3719                        formatTimeMs(sb, fullWifiLockOnTime / 1000);
3720                        sb.append("("); sb.append(formatRatioLocked(fullWifiLockOnTime,
3721                                whichBatteryRealtime)); sb.append(")\n");
3722                sb.append(prefix); sb.append("    Wifi Scan: ");
3723                        formatTimeMs(sb, wifiScanTime / 1000);
3724                        sb.append("("); sb.append(formatRatioLocked(wifiScanTime,
3725                                whichBatteryRealtime)); sb.append(") ");
3726                                sb.append(wifiScanCount);
3727                                sb.append("x");
3728                pw.println(sb.toString());
3729            }
3730
3731            if (u.hasUserActivity()) {
3732                boolean hasData = false;
3733                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
3734                    final int val = u.getUserActivityCount(i, which);
3735                    if (val != 0) {
3736                        if (!hasData) {
3737                            sb.setLength(0);
3738                            sb.append("    User activity: ");
3739                            hasData = true;
3740                        } else {
3741                            sb.append(", ");
3742                        }
3743                        sb.append(val);
3744                        sb.append(" ");
3745                        sb.append(Uid.USER_ACTIVITY_TYPES[i]);
3746                    }
3747                }
3748                if (hasData) {
3749                    pw.println(sb.toString());
3750                }
3751            }
3752
3753            final ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> wakelocks
3754                    = u.getWakelockStats();
3755            long totalFullWakelock = 0, totalPartialWakelock = 0, totalWindowWakelock = 0;
3756            int countWakelock = 0;
3757            for (int iw=wakelocks.size()-1; iw>=0; iw--) {
3758                final Uid.Wakelock wl = wakelocks.valueAt(iw);
3759                String linePrefix = ": ";
3760                sb.setLength(0);
3761                sb.append(prefix);
3762                sb.append("    Wake lock ");
3763                sb.append(wakelocks.keyAt(iw));
3764                linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_FULL), rawRealtime,
3765                        "full", which, linePrefix);
3766                linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), rawRealtime,
3767                        "partial", which, linePrefix);
3768                linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), rawRealtime,
3769                        "window", which, linePrefix);
3770                if (true || !linePrefix.equals(": ")) {
3771                    sb.append(" realtime");
3772                    // Only print out wake locks that were held
3773                    pw.println(sb.toString());
3774                    uidActivity = true;
3775                    countWakelock++;
3776                }
3777                totalFullWakelock += computeWakeLock(wl.getWakeTime(WAKE_TYPE_FULL),
3778                        rawRealtime, which);
3779                totalPartialWakelock += computeWakeLock(wl.getWakeTime(WAKE_TYPE_PARTIAL),
3780                        rawRealtime, which);
3781                totalWindowWakelock += computeWakeLock(wl.getWakeTime(WAKE_TYPE_WINDOW),
3782                        rawRealtime, which);
3783            }
3784            if (countWakelock > 1) {
3785                if (totalFullWakelock != 0 || totalPartialWakelock != 0
3786                        || totalWindowWakelock != 0) {
3787                    sb.setLength(0);
3788                    sb.append(prefix);
3789                    sb.append("    TOTAL wake: ");
3790                    boolean needComma = false;
3791                    if (totalFullWakelock != 0) {
3792                        needComma = true;
3793                        formatTimeMs(sb, totalFullWakelock);
3794                        sb.append("full");
3795                    }
3796                    if (totalPartialWakelock != 0) {
3797                        if (needComma) {
3798                            sb.append(", ");
3799                        }
3800                        needComma = true;
3801                        formatTimeMs(sb, totalPartialWakelock);
3802                        sb.append("partial");
3803                    }
3804                    if (totalWindowWakelock != 0) {
3805                        if (needComma) {
3806                            sb.append(", ");
3807                        }
3808                        needComma = true;
3809                        formatTimeMs(sb, totalWindowWakelock);
3810                        sb.append("window");
3811                    }
3812                    sb.append(" realtime");
3813                    pw.println(sb.toString());
3814                }
3815            }
3816
3817            final ArrayMap<String, ? extends Timer> syncs = u.getSyncStats();
3818            for (int isy=syncs.size()-1; isy>=0; isy--) {
3819                final Timer timer = syncs.valueAt(isy);
3820                // Convert from microseconds to milliseconds with rounding
3821                final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
3822                final int count = timer.getCountLocked(which);
3823                sb.setLength(0);
3824                sb.append(prefix);
3825                sb.append("    Sync ");
3826                sb.append(syncs.keyAt(isy));
3827                sb.append(": ");
3828                if (totalTime != 0) {
3829                    formatTimeMs(sb, totalTime);
3830                    sb.append("realtime (");
3831                    sb.append(count);
3832                    sb.append(" times)");
3833                } else {
3834                    sb.append("(not used)");
3835                }
3836                pw.println(sb.toString());
3837                uidActivity = true;
3838            }
3839
3840            final ArrayMap<String, ? extends Timer> jobs = u.getJobStats();
3841            for (int ij=jobs.size()-1; ij>=0; ij--) {
3842                final Timer timer = jobs.valueAt(ij);
3843                // Convert from microseconds to milliseconds with rounding
3844                final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
3845                final int count = timer.getCountLocked(which);
3846                sb.setLength(0);
3847                sb.append(prefix);
3848                sb.append("    Job ");
3849                sb.append(jobs.keyAt(ij));
3850                sb.append(": ");
3851                if (totalTime != 0) {
3852                    formatTimeMs(sb, totalTime);
3853                    sb.append("realtime (");
3854                    sb.append(count);
3855                    sb.append(" times)");
3856                } else {
3857                    sb.append("(not used)");
3858                }
3859                pw.println(sb.toString());
3860                uidActivity = true;
3861            }
3862
3863            uidActivity |= printTimer(pw, sb, u.getFlashlightTurnedOnTimer(), rawRealtime, which,
3864                    prefix, "Flashlight");
3865            uidActivity |= printTimer(pw, sb, u.getCameraTurnedOnTimer(), rawRealtime, which,
3866                    prefix, "Camera");
3867            uidActivity |= printTimer(pw, sb, u.getVideoTurnedOnTimer(), rawRealtime, which,
3868                    prefix, "Video");
3869            uidActivity |= printTimer(pw, sb, u.getAudioTurnedOnTimer(), rawRealtime, which,
3870                    prefix, "Audio");
3871
3872            final SparseArray<? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
3873            final int NSE = sensors.size();
3874            for (int ise=0; ise<NSE; ise++) {
3875                final Uid.Sensor se = sensors.valueAt(ise);
3876                final int sensorNumber = sensors.keyAt(ise);
3877                sb.setLength(0);
3878                sb.append(prefix);
3879                sb.append("    Sensor ");
3880                int handle = se.getHandle();
3881                if (handle == Uid.Sensor.GPS) {
3882                    sb.append("GPS");
3883                } else {
3884                    sb.append(handle);
3885                }
3886                sb.append(": ");
3887
3888                final Timer timer = se.getSensorTime();
3889                if (timer != null) {
3890                    // Convert from microseconds to milliseconds with rounding
3891                    final long totalTime = (timer.getTotalTimeLocked(
3892                            rawRealtime, which) + 500) / 1000;
3893                    final int count = timer.getCountLocked(which);
3894                    //timer.logState();
3895                    if (totalTime != 0) {
3896                        formatTimeMs(sb, totalTime);
3897                        sb.append("realtime (");
3898                        sb.append(count);
3899                        sb.append(" times)");
3900                    } else {
3901                        sb.append("(not used)");
3902                    }
3903                } else {
3904                    sb.append("(not used)");
3905                }
3906
3907                pw.println(sb.toString());
3908                uidActivity = true;
3909            }
3910
3911            uidActivity |= printTimer(pw, sb, u.getVibratorOnTimer(), rawRealtime, which, prefix,
3912                    "Vibrator");
3913            uidActivity |= printTimer(pw, sb, u.getForegroundActivityTimer(), rawRealtime, which,
3914                    prefix, "Foreground activities");
3915
3916            long totalStateTime = 0;
3917            for (int ips=0; ips<Uid.NUM_PROCESS_STATE; ips++) {
3918                long time = u.getProcessStateTime(ips, rawRealtime, which);
3919                if (time > 0) {
3920                    totalStateTime += time;
3921                    sb.setLength(0);
3922                    sb.append(prefix);
3923                    sb.append("    ");
3924                    sb.append(Uid.PROCESS_STATE_NAMES[ips]);
3925                    sb.append(" for: ");
3926                    formatTimeMs(sb, (totalStateTime + 500) / 1000);
3927                    pw.println(sb.toString());
3928                    uidActivity = true;
3929                }
3930            }
3931
3932            final long userCpuTimeUs = u.getUserCpuTimeUs(which);
3933            final long systemCpuTimeUs = u.getSystemCpuTimeUs(which);
3934            if (userCpuTimeUs > 0 || systemCpuTimeUs > 0) {
3935                sb.setLength(0);
3936                sb.append(prefix);
3937                sb.append("    Total cpu time: ");
3938                formatTimeMs(sb, (userCpuTimeUs + systemCpuTimeUs) / 1000);
3939                pw.println(sb.toString());
3940            }
3941
3942            final ArrayMap<String, ? extends BatteryStats.Uid.Proc> processStats
3943                    = u.getProcessStats();
3944            for (int ipr=processStats.size()-1; ipr>=0; ipr--) {
3945                final Uid.Proc ps = processStats.valueAt(ipr);
3946                long userTime;
3947                long systemTime;
3948                long foregroundTime;
3949                int starts;
3950                int numExcessive;
3951
3952                userTime = ps.getUserTime(which);
3953                systemTime = ps.getSystemTime(which);
3954                foregroundTime = ps.getForegroundTime(which);
3955                starts = ps.getStarts(which);
3956                final int numCrashes = ps.getNumCrashes(which);
3957                final int numAnrs = ps.getNumAnrs(which);
3958                numExcessive = which == STATS_SINCE_CHARGED
3959                        ? ps.countExcessivePowers() : 0;
3960
3961                if (userTime != 0 || systemTime != 0 || foregroundTime != 0 || starts != 0
3962                        || numExcessive != 0 || numCrashes != 0 || numAnrs != 0) {
3963                    sb.setLength(0);
3964                    sb.append(prefix); sb.append("    Proc ");
3965                            sb.append(processStats.keyAt(ipr)); sb.append(":\n");
3966                    sb.append(prefix); sb.append("      CPU: ");
3967                            formatTimeMs(sb, userTime); sb.append("usr + ");
3968                            formatTimeMs(sb, systemTime); sb.append("krn ; ");
3969                            formatTimeMs(sb, foregroundTime); sb.append("fg");
3970                    if (starts != 0 || numCrashes != 0 || numAnrs != 0) {
3971                        sb.append("\n"); sb.append(prefix); sb.append("      ");
3972                        boolean hasOne = false;
3973                        if (starts != 0) {
3974                            hasOne = true;
3975                            sb.append(starts); sb.append(" starts");
3976                        }
3977                        if (numCrashes != 0) {
3978                            if (hasOne) {
3979                                sb.append(", ");
3980                            }
3981                            hasOne = true;
3982                            sb.append(numCrashes); sb.append(" crashes");
3983                        }
3984                        if (numAnrs != 0) {
3985                            if (hasOne) {
3986                                sb.append(", ");
3987                            }
3988                            sb.append(numAnrs); sb.append(" anrs");
3989                        }
3990                    }
3991                    pw.println(sb.toString());
3992                    for (int e=0; e<numExcessive; e++) {
3993                        Uid.Proc.ExcessivePower ew = ps.getExcessivePower(e);
3994                        if (ew != null) {
3995                            pw.print(prefix); pw.print("      * Killed for ");
3996                                    if (ew.type == Uid.Proc.ExcessivePower.TYPE_WAKE) {
3997                                        pw.print("wake lock");
3998                                    } else if (ew.type == Uid.Proc.ExcessivePower.TYPE_CPU) {
3999                                        pw.print("cpu");
4000                                    } else {
4001                                        pw.print("unknown");
4002                                    }
4003                                    pw.print(" use: ");
4004                                    TimeUtils.formatDuration(ew.usedTime, pw);
4005                                    pw.print(" over ");
4006                                    TimeUtils.formatDuration(ew.overTime, pw);
4007                                    if (ew.overTime != 0) {
4008                                        pw.print(" (");
4009                                        pw.print((ew.usedTime*100)/ew.overTime);
4010                                        pw.println("%)");
4011                                    }
4012                        }
4013                    }
4014                    uidActivity = true;
4015                }
4016            }
4017
4018            final ArrayMap<String, ? extends BatteryStats.Uid.Pkg> packageStats
4019                    = u.getPackageStats();
4020            for (int ipkg=packageStats.size()-1; ipkg>=0; ipkg--) {
4021                pw.print(prefix); pw.print("    Apk "); pw.print(packageStats.keyAt(ipkg));
4022                pw.println(":");
4023                boolean apkActivity = false;
4024                final Uid.Pkg ps = packageStats.valueAt(ipkg);
4025                final ArrayMap<String, ? extends Counter> alarms = ps.getWakeupAlarmStats();
4026                for (int iwa=alarms.size()-1; iwa>=0; iwa--) {
4027                    pw.print(prefix); pw.print("      Wakeup alarm ");
4028                            pw.print(alarms.keyAt(iwa)); pw.print(": ");
4029                            pw.print(alarms.valueAt(iwa).getCountLocked(which));
4030                            pw.println(" times");
4031                    apkActivity = true;
4032                }
4033                final ArrayMap<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
4034                for (int isvc=serviceStats.size()-1; isvc>=0; isvc--) {
4035                    final BatteryStats.Uid.Pkg.Serv ss = serviceStats.valueAt(isvc);
4036                    final long startTime = ss.getStartTime(batteryUptime, which);
4037                    final int starts = ss.getStarts(which);
4038                    final int launches = ss.getLaunches(which);
4039                    if (startTime != 0 || starts != 0 || launches != 0) {
4040                        sb.setLength(0);
4041                        sb.append(prefix); sb.append("      Service ");
4042                                sb.append(serviceStats.keyAt(isvc)); sb.append(":\n");
4043                        sb.append(prefix); sb.append("        Created for: ");
4044                                formatTimeMs(sb, startTime / 1000);
4045                                sb.append("uptime\n");
4046                        sb.append(prefix); sb.append("        Starts: ");
4047                                sb.append(starts);
4048                                sb.append(", launches: "); sb.append(launches);
4049                        pw.println(sb.toString());
4050                        apkActivity = true;
4051                    }
4052                }
4053                if (!apkActivity) {
4054                    pw.print(prefix); pw.println("      (nothing executed)");
4055                }
4056                uidActivity = true;
4057            }
4058            if (!uidActivity) {
4059                pw.print(prefix); pw.println("    (nothing executed)");
4060            }
4061        }
4062    }
4063
4064    static void printBitDescriptions(PrintWriter pw, int oldval, int newval, HistoryTag wakelockTag,
4065            BitDescription[] descriptions, boolean longNames) {
4066        int diff = oldval ^ newval;
4067        if (diff == 0) return;
4068        boolean didWake = false;
4069        for (int i=0; i<descriptions.length; i++) {
4070            BitDescription bd = descriptions[i];
4071            if ((diff&bd.mask) != 0) {
4072                pw.print(longNames ? " " : ",");
4073                if (bd.shift < 0) {
4074                    pw.print((newval&bd.mask) != 0 ? "+" : "-");
4075                    pw.print(longNames ? bd.name : bd.shortName);
4076                    if (bd.mask == HistoryItem.STATE_WAKE_LOCK_FLAG && wakelockTag != null) {
4077                        didWake = true;
4078                        pw.print("=");
4079                        if (longNames) {
4080                            UserHandle.formatUid(pw, wakelockTag.uid);
4081                            pw.print(":\"");
4082                            pw.print(wakelockTag.string);
4083                            pw.print("\"");
4084                        } else {
4085                            pw.print(wakelockTag.poolIdx);
4086                        }
4087                    }
4088                } else {
4089                    pw.print(longNames ? bd.name : bd.shortName);
4090                    pw.print("=");
4091                    int val = (newval&bd.mask)>>bd.shift;
4092                    if (bd.values != null && val >= 0 && val < bd.values.length) {
4093                        pw.print(longNames? bd.values[val] : bd.shortValues[val]);
4094                    } else {
4095                        pw.print(val);
4096                    }
4097                }
4098            }
4099        }
4100        if (!didWake && wakelockTag != null) {
4101            pw.print(longNames ? " wake_lock=" : ",w=");
4102            if (longNames) {
4103                UserHandle.formatUid(pw, wakelockTag.uid);
4104                pw.print(":\"");
4105                pw.print(wakelockTag.string);
4106                pw.print("\"");
4107            } else {
4108                pw.print(wakelockTag.poolIdx);
4109            }
4110        }
4111    }
4112
4113    public void prepareForDumpLocked() {
4114    }
4115
4116    public static class HistoryPrinter {
4117        int oldState = 0;
4118        int oldState2 = 0;
4119        int oldLevel = -1;
4120        int oldStatus = -1;
4121        int oldHealth = -1;
4122        int oldPlug = -1;
4123        int oldTemp = -1;
4124        int oldVolt = -1;
4125        long lastTime = -1;
4126
4127        void reset() {
4128            oldState = oldState2 = 0;
4129            oldLevel = -1;
4130            oldStatus = -1;
4131            oldHealth = -1;
4132            oldPlug = -1;
4133            oldTemp = -1;
4134            oldVolt = -1;
4135        }
4136
4137        public void printNextItem(PrintWriter pw, HistoryItem rec, long baseTime, boolean checkin,
4138                boolean verbose) {
4139            if (!checkin) {
4140                pw.print("  ");
4141                TimeUtils.formatDuration(rec.time - baseTime, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
4142                pw.print(" (");
4143                pw.print(rec.numReadInts);
4144                pw.print(") ");
4145            } else {
4146                pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
4147                pw.print(HISTORY_DATA); pw.print(',');
4148                if (lastTime < 0) {
4149                    pw.print(rec.time - baseTime);
4150                } else {
4151                    pw.print(rec.time - lastTime);
4152                }
4153                lastTime = rec.time;
4154            }
4155            if (rec.cmd == HistoryItem.CMD_START) {
4156                if (checkin) {
4157                    pw.print(":");
4158                }
4159                pw.println("START");
4160                reset();
4161            } else if (rec.cmd == HistoryItem.CMD_CURRENT_TIME
4162                    || rec.cmd == HistoryItem.CMD_RESET) {
4163                if (checkin) {
4164                    pw.print(":");
4165                }
4166                if (rec.cmd == HistoryItem.CMD_RESET) {
4167                    pw.print("RESET:");
4168                    reset();
4169                }
4170                pw.print("TIME:");
4171                if (checkin) {
4172                    pw.println(rec.currentTime);
4173                } else {
4174                    pw.print(" ");
4175                    pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss",
4176                            rec.currentTime).toString());
4177                }
4178            } else if (rec.cmd == HistoryItem.CMD_SHUTDOWN) {
4179                if (checkin) {
4180                    pw.print(":");
4181                }
4182                pw.println("SHUTDOWN");
4183            } else if (rec.cmd == HistoryItem.CMD_OVERFLOW) {
4184                if (checkin) {
4185                    pw.print(":");
4186                }
4187                pw.println("*OVERFLOW*");
4188            } else {
4189                if (!checkin) {
4190                    if (rec.batteryLevel < 10) pw.print("00");
4191                    else if (rec.batteryLevel < 100) pw.print("0");
4192                    pw.print(rec.batteryLevel);
4193                    if (verbose) {
4194                        pw.print(" ");
4195                        if (rec.states < 0) ;
4196                        else if (rec.states < 0x10) pw.print("0000000");
4197                        else if (rec.states < 0x100) pw.print("000000");
4198                        else if (rec.states < 0x1000) pw.print("00000");
4199                        else if (rec.states < 0x10000) pw.print("0000");
4200                        else if (rec.states < 0x100000) pw.print("000");
4201                        else if (rec.states < 0x1000000) pw.print("00");
4202                        else if (rec.states < 0x10000000) pw.print("0");
4203                        pw.print(Integer.toHexString(rec.states));
4204                    }
4205                } else {
4206                    if (oldLevel != rec.batteryLevel) {
4207                        oldLevel = rec.batteryLevel;
4208                        pw.print(",Bl="); pw.print(rec.batteryLevel);
4209                    }
4210                }
4211                if (oldStatus != rec.batteryStatus) {
4212                    oldStatus = rec.batteryStatus;
4213                    pw.print(checkin ? ",Bs=" : " status=");
4214                    switch (oldStatus) {
4215                        case BatteryManager.BATTERY_STATUS_UNKNOWN:
4216                            pw.print(checkin ? "?" : "unknown");
4217                            break;
4218                        case BatteryManager.BATTERY_STATUS_CHARGING:
4219                            pw.print(checkin ? "c" : "charging");
4220                            break;
4221                        case BatteryManager.BATTERY_STATUS_DISCHARGING:
4222                            pw.print(checkin ? "d" : "discharging");
4223                            break;
4224                        case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
4225                            pw.print(checkin ? "n" : "not-charging");
4226                            break;
4227                        case BatteryManager.BATTERY_STATUS_FULL:
4228                            pw.print(checkin ? "f" : "full");
4229                            break;
4230                        default:
4231                            pw.print(oldStatus);
4232                            break;
4233                    }
4234                }
4235                if (oldHealth != rec.batteryHealth) {
4236                    oldHealth = rec.batteryHealth;
4237                    pw.print(checkin ? ",Bh=" : " health=");
4238                    switch (oldHealth) {
4239                        case BatteryManager.BATTERY_HEALTH_UNKNOWN:
4240                            pw.print(checkin ? "?" : "unknown");
4241                            break;
4242                        case BatteryManager.BATTERY_HEALTH_GOOD:
4243                            pw.print(checkin ? "g" : "good");
4244                            break;
4245                        case BatteryManager.BATTERY_HEALTH_OVERHEAT:
4246                            pw.print(checkin ? "h" : "overheat");
4247                            break;
4248                        case BatteryManager.BATTERY_HEALTH_DEAD:
4249                            pw.print(checkin ? "d" : "dead");
4250                            break;
4251                        case BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE:
4252                            pw.print(checkin ? "v" : "over-voltage");
4253                            break;
4254                        case BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE:
4255                            pw.print(checkin ? "f" : "failure");
4256                            break;
4257                        case BatteryManager.BATTERY_HEALTH_COLD:
4258                            pw.print(checkin ? "c" : "cold");
4259                            break;
4260                        default:
4261                            pw.print(oldHealth);
4262                            break;
4263                    }
4264                }
4265                if (oldPlug != rec.batteryPlugType) {
4266                    oldPlug = rec.batteryPlugType;
4267                    pw.print(checkin ? ",Bp=" : " plug=");
4268                    switch (oldPlug) {
4269                        case 0:
4270                            pw.print(checkin ? "n" : "none");
4271                            break;
4272                        case BatteryManager.BATTERY_PLUGGED_AC:
4273                            pw.print(checkin ? "a" : "ac");
4274                            break;
4275                        case BatteryManager.BATTERY_PLUGGED_USB:
4276                            pw.print(checkin ? "u" : "usb");
4277                            break;
4278                        case BatteryManager.BATTERY_PLUGGED_WIRELESS:
4279                            pw.print(checkin ? "w" : "wireless");
4280                            break;
4281                        default:
4282                            pw.print(oldPlug);
4283                            break;
4284                    }
4285                }
4286                if (oldTemp != rec.batteryTemperature) {
4287                    oldTemp = rec.batteryTemperature;
4288                    pw.print(checkin ? ",Bt=" : " temp=");
4289                    pw.print(oldTemp);
4290                }
4291                if (oldVolt != rec.batteryVoltage) {
4292                    oldVolt = rec.batteryVoltage;
4293                    pw.print(checkin ? ",Bv=" : " volt=");
4294                    pw.print(oldVolt);
4295                }
4296                printBitDescriptions(pw, oldState, rec.states, rec.wakelockTag,
4297                        HISTORY_STATE_DESCRIPTIONS, !checkin);
4298                printBitDescriptions(pw, oldState2, rec.states2, null,
4299                        HISTORY_STATE2_DESCRIPTIONS, !checkin);
4300                if (rec.wakeReasonTag != null) {
4301                    if (checkin) {
4302                        pw.print(",wr=");
4303                        pw.print(rec.wakeReasonTag.poolIdx);
4304                    } else {
4305                        pw.print(" wake_reason=");
4306                        pw.print(rec.wakeReasonTag.uid);
4307                        pw.print(":\"");
4308                        pw.print(rec.wakeReasonTag.string);
4309                        pw.print("\"");
4310                    }
4311                }
4312                if (rec.eventCode != HistoryItem.EVENT_NONE) {
4313                    pw.print(checkin ? "," : " ");
4314                    if ((rec.eventCode&HistoryItem.EVENT_FLAG_START) != 0) {
4315                        pw.print("+");
4316                    } else if ((rec.eventCode&HistoryItem.EVENT_FLAG_FINISH) != 0) {
4317                        pw.print("-");
4318                    }
4319                    String[] eventNames = checkin ? HISTORY_EVENT_CHECKIN_NAMES
4320                            : HISTORY_EVENT_NAMES;
4321                    int idx = rec.eventCode & ~(HistoryItem.EVENT_FLAG_START
4322                            | HistoryItem.EVENT_FLAG_FINISH);
4323                    if (idx >= 0 && idx < eventNames.length) {
4324                        pw.print(eventNames[idx]);
4325                    } else {
4326                        pw.print(checkin ? "Ev" : "event");
4327                        pw.print(idx);
4328                    }
4329                    pw.print("=");
4330                    if (checkin) {
4331                        pw.print(rec.eventTag.poolIdx);
4332                    } else {
4333                        UserHandle.formatUid(pw, rec.eventTag.uid);
4334                        pw.print(":\"");
4335                        pw.print(rec.eventTag.string);
4336                        pw.print("\"");
4337                    }
4338                }
4339                pw.println();
4340                if (rec.stepDetails != null) {
4341                    if (!checkin) {
4342                        pw.print("                 Details: cpu=");
4343                        pw.print(rec.stepDetails.userTime);
4344                        pw.print("u+");
4345                        pw.print(rec.stepDetails.systemTime);
4346                        pw.print("s");
4347                        if (rec.stepDetails.appCpuUid1 >= 0) {
4348                            pw.print(" (");
4349                            printStepCpuUidDetails(pw, rec.stepDetails.appCpuUid1,
4350                                    rec.stepDetails.appCpuUTime1, rec.stepDetails.appCpuSTime1);
4351                            if (rec.stepDetails.appCpuUid2 >= 0) {
4352                                pw.print(", ");
4353                                printStepCpuUidDetails(pw, rec.stepDetails.appCpuUid2,
4354                                        rec.stepDetails.appCpuUTime2, rec.stepDetails.appCpuSTime2);
4355                            }
4356                            if (rec.stepDetails.appCpuUid3 >= 0) {
4357                                pw.print(", ");
4358                                printStepCpuUidDetails(pw, rec.stepDetails.appCpuUid3,
4359                                        rec.stepDetails.appCpuUTime3, rec.stepDetails.appCpuSTime3);
4360                            }
4361                            pw.print(')');
4362                        }
4363                        pw.println();
4364                        pw.print("                          /proc/stat=");
4365                        pw.print(rec.stepDetails.statUserTime);
4366                        pw.print(" usr, ");
4367                        pw.print(rec.stepDetails.statSystemTime);
4368                        pw.print(" sys, ");
4369                        pw.print(rec.stepDetails.statIOWaitTime);
4370                        pw.print(" io, ");
4371                        pw.print(rec.stepDetails.statIrqTime);
4372                        pw.print(" irq, ");
4373                        pw.print(rec.stepDetails.statSoftIrqTime);
4374                        pw.print(" sirq, ");
4375                        pw.print(rec.stepDetails.statIdlTime);
4376                        pw.print(" idle");
4377                        int totalRun = rec.stepDetails.statUserTime + rec.stepDetails.statSystemTime
4378                                + rec.stepDetails.statIOWaitTime + rec.stepDetails.statIrqTime
4379                                + rec.stepDetails.statSoftIrqTime;
4380                        int total = totalRun + rec.stepDetails.statIdlTime;
4381                        if (total > 0) {
4382                            pw.print(" (");
4383                            float perc = ((float)totalRun) / ((float)total) * 100;
4384                            pw.print(String.format("%.1f%%", perc));
4385                            pw.print(" of ");
4386                            StringBuilder sb = new StringBuilder(64);
4387                            formatTimeMsNoSpace(sb, total*10);
4388                            pw.print(sb);
4389                            pw.print(")");
4390                        }
4391                        pw.println();
4392                    } else {
4393                        pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
4394                        pw.print(HISTORY_DATA); pw.print(",0,Dcpu=");
4395                        pw.print(rec.stepDetails.userTime);
4396                        pw.print(":");
4397                        pw.print(rec.stepDetails.systemTime);
4398                        if (rec.stepDetails.appCpuUid1 >= 0) {
4399                            printStepCpuUidCheckinDetails(pw, rec.stepDetails.appCpuUid1,
4400                                    rec.stepDetails.appCpuUTime1, rec.stepDetails.appCpuSTime1);
4401                            if (rec.stepDetails.appCpuUid2 >= 0) {
4402                                printStepCpuUidCheckinDetails(pw, rec.stepDetails.appCpuUid2,
4403                                        rec.stepDetails.appCpuUTime2, rec.stepDetails.appCpuSTime2);
4404                            }
4405                            if (rec.stepDetails.appCpuUid3 >= 0) {
4406                                printStepCpuUidCheckinDetails(pw, rec.stepDetails.appCpuUid3,
4407                                        rec.stepDetails.appCpuUTime3, rec.stepDetails.appCpuSTime3);
4408                            }
4409                        }
4410                        pw.println();
4411                        pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
4412                        pw.print(HISTORY_DATA); pw.print(",0,Dpst=");
4413                        pw.print(rec.stepDetails.statUserTime);
4414                        pw.print(',');
4415                        pw.print(rec.stepDetails.statSystemTime);
4416                        pw.print(',');
4417                        pw.print(rec.stepDetails.statIOWaitTime);
4418                        pw.print(',');
4419                        pw.print(rec.stepDetails.statIrqTime);
4420                        pw.print(',');
4421                        pw.print(rec.stepDetails.statSoftIrqTime);
4422                        pw.print(',');
4423                        pw.print(rec.stepDetails.statIdlTime);
4424                        pw.println();
4425                    }
4426                }
4427                oldState = rec.states;
4428                oldState2 = rec.states2;
4429            }
4430        }
4431
4432        private void printStepCpuUidDetails(PrintWriter pw, int uid, int utime, int stime) {
4433            UserHandle.formatUid(pw, uid);
4434            pw.print("=");
4435            pw.print(utime);
4436            pw.print("u+");
4437            pw.print(stime);
4438            pw.print("s");
4439        }
4440
4441        private void printStepCpuUidCheckinDetails(PrintWriter pw, int uid, int utime, int stime) {
4442            pw.print('/');
4443            pw.print(uid);
4444            pw.print(":");
4445            pw.print(utime);
4446            pw.print(":");
4447            pw.print(stime);
4448        }
4449    }
4450
4451    private void printSizeValue(PrintWriter pw, long size) {
4452        float result = size;
4453        String suffix = "";
4454        if (result >= 10*1024) {
4455            suffix = "KB";
4456            result = result / 1024;
4457        }
4458        if (result >= 10*1024) {
4459            suffix = "MB";
4460            result = result / 1024;
4461        }
4462        if (result >= 10*1024) {
4463            suffix = "GB";
4464            result = result / 1024;
4465        }
4466        if (result >= 10*1024) {
4467            suffix = "TB";
4468            result = result / 1024;
4469        }
4470        if (result >= 10*1024) {
4471            suffix = "PB";
4472            result = result / 1024;
4473        }
4474        pw.print((int)result);
4475        pw.print(suffix);
4476    }
4477
4478    private static boolean dumpTimeEstimate(PrintWriter pw, String label1, String label2,
4479            String label3, long estimatedTime) {
4480        if (estimatedTime < 0) {
4481            return false;
4482        }
4483        pw.print(label1);
4484        pw.print(label2);
4485        pw.print(label3);
4486        StringBuilder sb = new StringBuilder(64);
4487        formatTimeMs(sb, estimatedTime);
4488        pw.print(sb);
4489        pw.println();
4490        return true;
4491    }
4492
4493    private static boolean dumpDurationSteps(PrintWriter pw, String prefix, String header,
4494            LevelStepTracker steps, boolean checkin) {
4495        if (steps == null) {
4496            return false;
4497        }
4498        int count = steps.mNumStepDurations;
4499        if (count <= 0) {
4500            return false;
4501        }
4502        if (!checkin) {
4503            pw.println(header);
4504        }
4505        String[] lineArgs = new String[5];
4506        for (int i=0; i<count; i++) {
4507            long duration = steps.getDurationAt(i);
4508            int level = steps.getLevelAt(i);
4509            long initMode = steps.getInitModeAt(i);
4510            long modMode = steps.getModModeAt(i);
4511            if (checkin) {
4512                lineArgs[0] = Long.toString(duration);
4513                lineArgs[1] = Integer.toString(level);
4514                if ((modMode&STEP_LEVEL_MODE_SCREEN_STATE) == 0) {
4515                    switch ((int)(initMode&STEP_LEVEL_MODE_SCREEN_STATE) + 1) {
4516                        case Display.STATE_OFF: lineArgs[2] = "s-"; break;
4517                        case Display.STATE_ON: lineArgs[2] = "s+"; break;
4518                        case Display.STATE_DOZE: lineArgs[2] = "sd"; break;
4519                        case Display.STATE_DOZE_SUSPEND: lineArgs[2] = "sds"; break;
4520                        default: lineArgs[2] = "?"; break;
4521                    }
4522                } else {
4523                    lineArgs[2] = "";
4524                }
4525                if ((modMode&STEP_LEVEL_MODE_POWER_SAVE) == 0) {
4526                    lineArgs[3] = (initMode&STEP_LEVEL_MODE_POWER_SAVE) != 0 ? "p+" : "p-";
4527                } else {
4528                    lineArgs[3] = "";
4529                }
4530                if ((modMode&STEP_LEVEL_MODE_DEVICE_IDLE) == 0) {
4531                    lineArgs[4] = (initMode&STEP_LEVEL_MODE_DEVICE_IDLE) != 0 ? "i+" : "i-";
4532                } else {
4533                    lineArgs[4] = "";
4534                }
4535                dumpLine(pw, 0 /* uid */, "i" /* category */, header, (Object[])lineArgs);
4536            } else {
4537                pw.print(prefix);
4538                pw.print("#"); pw.print(i); pw.print(": ");
4539                TimeUtils.formatDuration(duration, pw);
4540                pw.print(" to "); pw.print(level);
4541                boolean haveModes = false;
4542                if ((modMode&STEP_LEVEL_MODE_SCREEN_STATE) == 0) {
4543                    pw.print(" (");
4544                    switch ((int)(initMode&STEP_LEVEL_MODE_SCREEN_STATE) + 1) {
4545                        case Display.STATE_OFF: pw.print("screen-off"); break;
4546                        case Display.STATE_ON: pw.print("screen-on"); break;
4547                        case Display.STATE_DOZE: pw.print("screen-doze"); break;
4548                        case Display.STATE_DOZE_SUSPEND: pw.print("screen-doze-suspend"); break;
4549                        default: pw.print("screen-?"); break;
4550                    }
4551                    haveModes = true;
4552                }
4553                if ((modMode&STEP_LEVEL_MODE_POWER_SAVE) == 0) {
4554                    pw.print(haveModes ? ", " : " (");
4555                    pw.print((initMode&STEP_LEVEL_MODE_POWER_SAVE) != 0
4556                            ? "power-save-on" : "power-save-off");
4557                    haveModes = true;
4558                }
4559                if ((modMode&STEP_LEVEL_MODE_DEVICE_IDLE) == 0) {
4560                    pw.print(haveModes ? ", " : " (");
4561                    pw.print((initMode&STEP_LEVEL_MODE_DEVICE_IDLE) != 0
4562                            ? "device-idle-on" : "device-idle-off");
4563                    haveModes = true;
4564                }
4565                if (haveModes) {
4566                    pw.print(")");
4567                }
4568                pw.println();
4569            }
4570        }
4571        return true;
4572    }
4573
4574    public static final int DUMP_CHARGED_ONLY = 1<<1;
4575    public static final int DUMP_DAILY_ONLY = 1<<2;
4576    public static final int DUMP_HISTORY_ONLY = 1<<3;
4577    public static final int DUMP_INCLUDE_HISTORY = 1<<4;
4578    public static final int DUMP_VERBOSE = 1<<5;
4579    public static final int DUMP_DEVICE_WIFI_ONLY = 1<<6;
4580
4581    private void dumpHistoryLocked(PrintWriter pw, int flags, long histStart, boolean checkin) {
4582        final HistoryPrinter hprinter = new HistoryPrinter();
4583        final HistoryItem rec = new HistoryItem();
4584        long lastTime = -1;
4585        long baseTime = -1;
4586        boolean printed = false;
4587        HistoryEventTracker tracker = null;
4588        while (getNextHistoryLocked(rec)) {
4589            lastTime = rec.time;
4590            if (baseTime < 0) {
4591                baseTime = lastTime;
4592            }
4593            if (rec.time >= histStart) {
4594                if (histStart >= 0 && !printed) {
4595                    if (rec.cmd == HistoryItem.CMD_CURRENT_TIME
4596                            || rec.cmd == HistoryItem.CMD_RESET
4597                            || rec.cmd == HistoryItem.CMD_START
4598                            || rec.cmd == HistoryItem.CMD_SHUTDOWN) {
4599                        printed = true;
4600                        hprinter.printNextItem(pw, rec, baseTime, checkin,
4601                                (flags&DUMP_VERBOSE) != 0);
4602                        rec.cmd = HistoryItem.CMD_UPDATE;
4603                    } else if (rec.currentTime != 0) {
4604                        printed = true;
4605                        byte cmd = rec.cmd;
4606                        rec.cmd = HistoryItem.CMD_CURRENT_TIME;
4607                        hprinter.printNextItem(pw, rec, baseTime, checkin,
4608                                (flags&DUMP_VERBOSE) != 0);
4609                        rec.cmd = cmd;
4610                    }
4611                    if (tracker != null) {
4612                        if (rec.cmd != HistoryItem.CMD_UPDATE) {
4613                            hprinter.printNextItem(pw, rec, baseTime, checkin,
4614                                    (flags&DUMP_VERBOSE) != 0);
4615                            rec.cmd = HistoryItem.CMD_UPDATE;
4616                        }
4617                        int oldEventCode = rec.eventCode;
4618                        HistoryTag oldEventTag = rec.eventTag;
4619                        rec.eventTag = new HistoryTag();
4620                        for (int i=0; i<HistoryItem.EVENT_COUNT; i++) {
4621                            HashMap<String, SparseIntArray> active
4622                                    = tracker.getStateForEvent(i);
4623                            if (active == null) {
4624                                continue;
4625                            }
4626                            for (HashMap.Entry<String, SparseIntArray> ent
4627                                    : active.entrySet()) {
4628                                SparseIntArray uids = ent.getValue();
4629                                for (int j=0; j<uids.size(); j++) {
4630                                    rec.eventCode = i;
4631                                    rec.eventTag.string = ent.getKey();
4632                                    rec.eventTag.uid = uids.keyAt(j);
4633                                    rec.eventTag.poolIdx = uids.valueAt(j);
4634                                    hprinter.printNextItem(pw, rec, baseTime, checkin,
4635                                            (flags&DUMP_VERBOSE) != 0);
4636                                    rec.wakeReasonTag = null;
4637                                    rec.wakelockTag = null;
4638                                }
4639                            }
4640                        }
4641                        rec.eventCode = oldEventCode;
4642                        rec.eventTag = oldEventTag;
4643                        tracker = null;
4644                    }
4645                }
4646                hprinter.printNextItem(pw, rec, baseTime, checkin,
4647                        (flags&DUMP_VERBOSE) != 0);
4648            } else if (false && rec.eventCode != HistoryItem.EVENT_NONE) {
4649                // This is an attempt to aggregate the previous state and generate
4650                // fake events to reflect that state at the point where we start
4651                // printing real events.  It doesn't really work right, so is turned off.
4652                if (tracker == null) {
4653                    tracker = new HistoryEventTracker();
4654                }
4655                tracker.updateState(rec.eventCode, rec.eventTag.string,
4656                        rec.eventTag.uid, rec.eventTag.poolIdx);
4657            }
4658        }
4659        if (histStart >= 0) {
4660            commitCurrentHistoryBatchLocked();
4661            pw.print(checkin ? "NEXT: " : "  NEXT: "); pw.println(lastTime+1);
4662        }
4663    }
4664
4665    private void dumpDailyLevelStepSummary(PrintWriter pw, String prefix, String label,
4666            LevelStepTracker steps, StringBuilder tmpSb, int[] tmpOutInt) {
4667        if (steps == null) {
4668            return;
4669        }
4670        long timeRemaining = steps.computeTimeEstimate(0, 0, tmpOutInt);
4671        if (timeRemaining >= 0) {
4672            pw.print(prefix); pw.print(label); pw.print(" total time: ");
4673            tmpSb.setLength(0);
4674            formatTimeMs(tmpSb, timeRemaining);
4675            pw.print(tmpSb);
4676            pw.print(" (from "); pw.print(tmpOutInt[0]);
4677            pw.println(" steps)");
4678        }
4679        for (int i=0; i< STEP_LEVEL_MODES_OF_INTEREST.length; i++) {
4680            long estimatedTime = steps.computeTimeEstimate(STEP_LEVEL_MODES_OF_INTEREST[i],
4681                    STEP_LEVEL_MODE_VALUES[i], tmpOutInt);
4682            if (estimatedTime > 0) {
4683                pw.print(prefix); pw.print(label); pw.print(" ");
4684                pw.print(STEP_LEVEL_MODE_LABELS[i]);
4685                pw.print(" time: ");
4686                tmpSb.setLength(0);
4687                formatTimeMs(tmpSb, estimatedTime);
4688                pw.print(tmpSb);
4689                pw.print(" (from "); pw.print(tmpOutInt[0]);
4690                pw.println(" steps)");
4691            }
4692        }
4693    }
4694
4695    private void dumpDailyPackageChanges(PrintWriter pw, String prefix,
4696            ArrayList<PackageChange> changes) {
4697        if (changes == null) {
4698            return;
4699        }
4700        pw.print(prefix); pw.println("Package changes:");
4701        for (int i=0; i<changes.size(); i++) {
4702            PackageChange pc = changes.get(i);
4703            if (pc.mUpdate) {
4704                pw.print(prefix); pw.print("  Update "); pw.print(pc.mPackageName);
4705                pw.print(" vers="); pw.println(pc.mVersionCode);
4706            } else {
4707                pw.print(prefix); pw.print("  Uninstall "); pw.println(pc.mPackageName);
4708            }
4709        }
4710    }
4711
4712    /**
4713     * Dumps a human-readable summary of the battery statistics to the given PrintWriter.
4714     *
4715     * @param pw a Printer to receive the dump output.
4716     */
4717    @SuppressWarnings("unused")
4718    public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
4719        prepareForDumpLocked();
4720
4721        final boolean filtering = (flags
4722                & (DUMP_HISTORY_ONLY|DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) != 0;
4723
4724        if ((flags&DUMP_HISTORY_ONLY) != 0 || !filtering) {
4725            final long historyTotalSize = getHistoryTotalSize();
4726            final long historyUsedSize = getHistoryUsedSize();
4727            if (startIteratingHistoryLocked()) {
4728                try {
4729                    pw.print("Battery History (");
4730                    pw.print((100*historyUsedSize)/historyTotalSize);
4731                    pw.print("% used, ");
4732                    printSizeValue(pw, historyUsedSize);
4733                    pw.print(" used of ");
4734                    printSizeValue(pw, historyTotalSize);
4735                    pw.print(", ");
4736                    pw.print(getHistoryStringPoolSize());
4737                    pw.print(" strings using ");
4738                    printSizeValue(pw, getHistoryStringPoolBytes());
4739                    pw.println("):");
4740                    dumpHistoryLocked(pw, flags, histStart, false);
4741                    pw.println();
4742                } finally {
4743                    finishIteratingHistoryLocked();
4744                }
4745            }
4746
4747            if (startIteratingOldHistoryLocked()) {
4748                try {
4749                    final HistoryItem rec = new HistoryItem();
4750                    pw.println("Old battery History:");
4751                    HistoryPrinter hprinter = new HistoryPrinter();
4752                    long baseTime = -1;
4753                    while (getNextOldHistoryLocked(rec)) {
4754                        if (baseTime < 0) {
4755                            baseTime = rec.time;
4756                        }
4757                        hprinter.printNextItem(pw, rec, baseTime, false, (flags&DUMP_VERBOSE) != 0);
4758                    }
4759                    pw.println();
4760                } finally {
4761                    finishIteratingOldHistoryLocked();
4762                }
4763            }
4764        }
4765
4766        if (filtering && (flags&(DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) == 0) {
4767            return;
4768        }
4769
4770        if (!filtering) {
4771            SparseArray<? extends Uid> uidStats = getUidStats();
4772            final int NU = uidStats.size();
4773            boolean didPid = false;
4774            long nowRealtime = SystemClock.elapsedRealtime();
4775            for (int i=0; i<NU; i++) {
4776                Uid uid = uidStats.valueAt(i);
4777                SparseArray<? extends Uid.Pid> pids = uid.getPidStats();
4778                if (pids != null) {
4779                    for (int j=0; j<pids.size(); j++) {
4780                        Uid.Pid pid = pids.valueAt(j);
4781                        if (!didPid) {
4782                            pw.println("Per-PID Stats:");
4783                            didPid = true;
4784                        }
4785                        long time = pid.mWakeSumMs + (pid.mWakeNesting > 0
4786                                ? (nowRealtime - pid.mWakeStartMs) : 0);
4787                        pw.print("  PID "); pw.print(pids.keyAt(j));
4788                                pw.print(" wake time: ");
4789                                TimeUtils.formatDuration(time, pw);
4790                                pw.println("");
4791                    }
4792                }
4793            }
4794            if (didPid) {
4795                pw.println();
4796            }
4797        }
4798
4799        if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
4800            if (dumpDurationSteps(pw, "  ", "Discharge step durations:",
4801                    getDischargeLevelStepTracker(), false)) {
4802                long timeRemaining = computeBatteryTimeRemaining(SystemClock.elapsedRealtime());
4803                if (timeRemaining >= 0) {
4804                    pw.print("  Estimated discharge time remaining: ");
4805                    TimeUtils.formatDuration(timeRemaining / 1000, pw);
4806                    pw.println();
4807                }
4808                final LevelStepTracker steps = getDischargeLevelStepTracker();
4809                for (int i=0; i< STEP_LEVEL_MODES_OF_INTEREST.length; i++) {
4810                    dumpTimeEstimate(pw, "  Estimated ", STEP_LEVEL_MODE_LABELS[i], " time: ",
4811                            steps.computeTimeEstimate(STEP_LEVEL_MODES_OF_INTEREST[i],
4812                                    STEP_LEVEL_MODE_VALUES[i], null));
4813                }
4814                pw.println();
4815            }
4816            if (dumpDurationSteps(pw, "  ", "Charge step durations:",
4817                    getChargeLevelStepTracker(), false)) {
4818                long timeRemaining = computeChargeTimeRemaining(SystemClock.elapsedRealtime());
4819                if (timeRemaining >= 0) {
4820                    pw.print("  Estimated charge time remaining: ");
4821                    TimeUtils.formatDuration(timeRemaining / 1000, pw);
4822                    pw.println();
4823                }
4824                pw.println();
4825            }
4826        }
4827        if (!filtering || (flags&(DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) != 0) {
4828            pw.println("Daily stats:");
4829            pw.print("  Current start time: ");
4830            pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss",
4831                    getCurrentDailyStartTime()).toString());
4832            pw.print("  Next min deadline: ");
4833            pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss",
4834                    getNextMinDailyDeadline()).toString());
4835            pw.print("  Next max deadline: ");
4836            pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss",
4837                    getNextMaxDailyDeadline()).toString());
4838            StringBuilder sb = new StringBuilder(64);
4839            int[] outInt = new int[1];
4840            LevelStepTracker dsteps = getDailyDischargeLevelStepTracker();
4841            LevelStepTracker csteps = getDailyChargeLevelStepTracker();
4842            ArrayList<PackageChange> pkgc = getDailyPackageChanges();
4843            if (dsteps.mNumStepDurations > 0 || csteps.mNumStepDurations > 0 || pkgc != null) {
4844                if ((flags&DUMP_DAILY_ONLY) != 0 || !filtering) {
4845                    if (dumpDurationSteps(pw, "    ", "  Current daily discharge step durations:",
4846                            dsteps, false)) {
4847                        dumpDailyLevelStepSummary(pw, "      ", "Discharge", dsteps,
4848                                sb, outInt);
4849                    }
4850                    if (dumpDurationSteps(pw, "    ", "  Current daily charge step durations:",
4851                            csteps, false)) {
4852                        dumpDailyLevelStepSummary(pw, "      ", "Charge", csteps,
4853                                sb, outInt);
4854                    }
4855                    dumpDailyPackageChanges(pw, "    ", pkgc);
4856                } else {
4857                    pw.println("  Current daily steps:");
4858                    dumpDailyLevelStepSummary(pw, "    ", "Discharge", dsteps,
4859                            sb, outInt);
4860                    dumpDailyLevelStepSummary(pw, "    ", "Charge", csteps,
4861                            sb, outInt);
4862                }
4863            }
4864            DailyItem dit;
4865            int curIndex = 0;
4866            while ((dit=getDailyItemLocked(curIndex)) != null) {
4867                curIndex++;
4868                if ((flags&DUMP_DAILY_ONLY) != 0) {
4869                    pw.println();
4870                }
4871                pw.print("  Daily from ");
4872                pw.print(DateFormat.format("yyyy-MM-dd-HH-mm-ss", dit.mStartTime).toString());
4873                pw.print(" to ");
4874                pw.print(DateFormat.format("yyyy-MM-dd-HH-mm-ss", dit.mEndTime).toString());
4875                pw.println(":");
4876                if ((flags&DUMP_DAILY_ONLY) != 0 || !filtering) {
4877                    if (dumpDurationSteps(pw, "      ",
4878                            "    Discharge step durations:", dit.mDischargeSteps, false)) {
4879                        dumpDailyLevelStepSummary(pw, "        ", "Discharge", dit.mDischargeSteps,
4880                                sb, outInt);
4881                    }
4882                    if (dumpDurationSteps(pw, "      ",
4883                            "    Charge step durations:", dit.mChargeSteps, false)) {
4884                        dumpDailyLevelStepSummary(pw, "        ", "Charge", dit.mChargeSteps,
4885                                sb, outInt);
4886                    }
4887                    dumpDailyPackageChanges(pw, "    ", dit.mPackageChanges);
4888                } else {
4889                    dumpDailyLevelStepSummary(pw, "    ", "Discharge", dit.mDischargeSteps,
4890                            sb, outInt);
4891                    dumpDailyLevelStepSummary(pw, "    ", "Charge", dit.mChargeSteps,
4892                            sb, outInt);
4893                }
4894            }
4895            pw.println();
4896        }
4897        if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
4898            pw.println("Statistics since last charge:");
4899            pw.println("  System starts: " + getStartCount()
4900                    + ", currently on battery: " + getIsOnBattery());
4901            dumpLocked(context, pw, "", STATS_SINCE_CHARGED, reqUid,
4902                    (flags&DUMP_DEVICE_WIFI_ONLY) != 0);
4903            pw.println();
4904        }
4905    }
4906
4907    @SuppressWarnings("unused")
4908    public void dumpCheckinLocked(Context context, PrintWriter pw,
4909            List<ApplicationInfo> apps, int flags, long histStart) {
4910        prepareForDumpLocked();
4911
4912        dumpLine(pw, 0 /* uid */, "i" /* category */, VERSION_DATA,
4913                CHECKIN_VERSION, getParcelVersion(), getStartPlatformVersion(),
4914                getEndPlatformVersion());
4915
4916        long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
4917
4918        final boolean filtering = (flags &
4919                (DUMP_HISTORY_ONLY|DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) != 0;
4920
4921        if ((flags&DUMP_INCLUDE_HISTORY) != 0 || (flags&DUMP_HISTORY_ONLY) != 0) {
4922            if (startIteratingHistoryLocked()) {
4923                try {
4924                    for (int i=0; i<getHistoryStringPoolSize(); i++) {
4925                        pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
4926                        pw.print(HISTORY_STRING_POOL); pw.print(',');
4927                        pw.print(i);
4928                        pw.print(",");
4929                        pw.print(getHistoryTagPoolUid(i));
4930                        pw.print(",\"");
4931                        String str = getHistoryTagPoolString(i);
4932                        str = str.replace("\\", "\\\\");
4933                        str = str.replace("\"", "\\\"");
4934                        pw.print(str);
4935                        pw.print("\"");
4936                        pw.println();
4937                    }
4938                    dumpHistoryLocked(pw, flags, histStart, true);
4939                } finally {
4940                    finishIteratingHistoryLocked();
4941                }
4942            }
4943        }
4944
4945        if (filtering && (flags&(DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) == 0) {
4946            return;
4947        }
4948
4949        if (apps != null) {
4950            SparseArray<ArrayList<String>> uids = new SparseArray<ArrayList<String>>();
4951            for (int i=0; i<apps.size(); i++) {
4952                ApplicationInfo ai = apps.get(i);
4953                ArrayList<String> pkgs = uids.get(ai.uid);
4954                if (pkgs == null) {
4955                    pkgs = new ArrayList<String>();
4956                    uids.put(ai.uid, pkgs);
4957                }
4958                pkgs.add(ai.packageName);
4959            }
4960            SparseArray<? extends Uid> uidStats = getUidStats();
4961            final int NU = uidStats.size();
4962            String[] lineArgs = new String[2];
4963            for (int i=0; i<NU; i++) {
4964                int uid = uidStats.keyAt(i);
4965                ArrayList<String> pkgs = uids.get(uid);
4966                if (pkgs != null) {
4967                    for (int j=0; j<pkgs.size(); j++) {
4968                        lineArgs[0] = Integer.toString(uid);
4969                        lineArgs[1] = pkgs.get(j);
4970                        dumpLine(pw, 0 /* uid */, "i" /* category */, UID_DATA,
4971                                (Object[])lineArgs);
4972                    }
4973                }
4974            }
4975        }
4976        if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
4977            dumpDurationSteps(pw, "", DISCHARGE_STEP_DATA, getDischargeLevelStepTracker(), true);
4978            String[] lineArgs = new String[1];
4979            long timeRemaining = computeBatteryTimeRemaining(SystemClock.elapsedRealtime());
4980            if (timeRemaining >= 0) {
4981                lineArgs[0] = Long.toString(timeRemaining);
4982                dumpLine(pw, 0 /* uid */, "i" /* category */, DISCHARGE_TIME_REMAIN_DATA,
4983                        (Object[])lineArgs);
4984            }
4985            dumpDurationSteps(pw, "", CHARGE_STEP_DATA, getChargeLevelStepTracker(), true);
4986            timeRemaining = computeChargeTimeRemaining(SystemClock.elapsedRealtime());
4987            if (timeRemaining >= 0) {
4988                lineArgs[0] = Long.toString(timeRemaining);
4989                dumpLine(pw, 0 /* uid */, "i" /* category */, CHARGE_TIME_REMAIN_DATA,
4990                        (Object[])lineArgs);
4991            }
4992            dumpCheckinLocked(context, pw, STATS_SINCE_CHARGED, -1,
4993                    (flags&DUMP_DEVICE_WIFI_ONLY) != 0);
4994        }
4995    }
4996}
4997