BatteryStats.java revision 0348ba2e2303d9dce57a6b5d19cc47ecc5089afe
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 becoming active taking us out of idle mode.
1169        public static final int EVENT_ACTIVE = 0x000a;
1170        // Event for a package being installed.
1171        public static final int EVENT_PACKAGE_INSTALLED = 0x000b;
1172        // Event for a package being uninstalled.
1173        public static final int EVENT_PACKAGE_UNINSTALLED = 0x000c;
1174        // Event for a package being uninstalled.
1175        public static final int EVENT_ALARM = 0x000d;
1176        // Record that we have decided we need to collect new stats data.
1177        public static final int EVENT_COLLECT_EXTERNAL_STATS = 0x000e;
1178        // Event for a package becoming inactive due to being unused for a period of time.
1179        public static final int EVENT_PACKAGE_INACTIVE = 0x000f;
1180        // Event for a package becoming active due to an interaction.
1181        public static final int EVENT_PACKAGE_ACTIVE = 0x0010;
1182
1183        // Number of event types.
1184        public static final int EVENT_COUNT = 0x0011;
1185        // Mask to extract out only the type part of the event.
1186        public static final int EVENT_TYPE_MASK = ~(EVENT_FLAG_START|EVENT_FLAG_FINISH);
1187
1188        public static final int EVENT_PROC_START = EVENT_PROC | EVENT_FLAG_START;
1189        public static final int EVENT_PROC_FINISH = EVENT_PROC | EVENT_FLAG_FINISH;
1190        public static final int EVENT_FOREGROUND_START = EVENT_FOREGROUND | EVENT_FLAG_START;
1191        public static final int EVENT_FOREGROUND_FINISH = EVENT_FOREGROUND | EVENT_FLAG_FINISH;
1192        public static final int EVENT_TOP_START = EVENT_TOP | EVENT_FLAG_START;
1193        public static final int EVENT_TOP_FINISH = EVENT_TOP | EVENT_FLAG_FINISH;
1194        public static final int EVENT_SYNC_START = EVENT_SYNC | EVENT_FLAG_START;
1195        public static final int EVENT_SYNC_FINISH = EVENT_SYNC | EVENT_FLAG_FINISH;
1196        public static final int EVENT_WAKE_LOCK_START = EVENT_WAKE_LOCK | EVENT_FLAG_START;
1197        public static final int EVENT_WAKE_LOCK_FINISH = EVENT_WAKE_LOCK | EVENT_FLAG_FINISH;
1198        public static final int EVENT_JOB_START = EVENT_JOB | EVENT_FLAG_START;
1199        public static final int EVENT_JOB_FINISH = EVENT_JOB | EVENT_FLAG_FINISH;
1200        public static final int EVENT_USER_RUNNING_START = EVENT_USER_RUNNING | EVENT_FLAG_START;
1201        public static final int EVENT_USER_RUNNING_FINISH = EVENT_USER_RUNNING | EVENT_FLAG_FINISH;
1202        public static final int EVENT_USER_FOREGROUND_START =
1203                EVENT_USER_FOREGROUND | EVENT_FLAG_START;
1204        public static final int EVENT_USER_FOREGROUND_FINISH =
1205                EVENT_USER_FOREGROUND | EVENT_FLAG_FINISH;
1206        public static final int EVENT_ALARM_START = EVENT_ALARM | EVENT_FLAG_START;
1207        public static final int EVENT_ALARM_FINISH = EVENT_ALARM | EVENT_FLAG_FINISH;
1208
1209        // For CMD_EVENT.
1210        public int eventCode;
1211        public HistoryTag eventTag;
1212
1213        // Only set for CMD_CURRENT_TIME or CMD_RESET, as per System.currentTimeMillis().
1214        public long currentTime;
1215
1216        // Meta-data when reading.
1217        public int numReadInts;
1218
1219        // Pre-allocated objects.
1220        public final HistoryTag localWakelockTag = new HistoryTag();
1221        public final HistoryTag localWakeReasonTag = new HistoryTag();
1222        public final HistoryTag localEventTag = new HistoryTag();
1223
1224        public HistoryItem() {
1225        }
1226
1227        public HistoryItem(long time, Parcel src) {
1228            this.time = time;
1229            numReadInts = 2;
1230            readFromParcel(src);
1231        }
1232
1233        public int describeContents() {
1234            return 0;
1235        }
1236
1237        public void writeToParcel(Parcel dest, int flags) {
1238            dest.writeLong(time);
1239            int bat = (((int)cmd)&0xff)
1240                    | ((((int)batteryLevel)<<8)&0xff00)
1241                    | ((((int)batteryStatus)<<16)&0xf0000)
1242                    | ((((int)batteryHealth)<<20)&0xf00000)
1243                    | ((((int)batteryPlugType)<<24)&0xf000000)
1244                    | (wakelockTag != null ? 0x10000000 : 0)
1245                    | (wakeReasonTag != null ? 0x20000000 : 0)
1246                    | (eventCode != EVENT_NONE ? 0x40000000 : 0);
1247            dest.writeInt(bat);
1248            bat = (((int)batteryTemperature)&0xffff)
1249                    | ((((int)batteryVoltage)<<16)&0xffff0000);
1250            dest.writeInt(bat);
1251            dest.writeInt(states);
1252            dest.writeInt(states2);
1253            if (wakelockTag != null) {
1254                wakelockTag.writeToParcel(dest, flags);
1255            }
1256            if (wakeReasonTag != null) {
1257                wakeReasonTag.writeToParcel(dest, flags);
1258            }
1259            if (eventCode != EVENT_NONE) {
1260                dest.writeInt(eventCode);
1261                eventTag.writeToParcel(dest, flags);
1262            }
1263            if (cmd == CMD_CURRENT_TIME || cmd == CMD_RESET) {
1264                dest.writeLong(currentTime);
1265            }
1266        }
1267
1268        public void readFromParcel(Parcel src) {
1269            int start = src.dataPosition();
1270            int bat = src.readInt();
1271            cmd = (byte)(bat&0xff);
1272            batteryLevel = (byte)((bat>>8)&0xff);
1273            batteryStatus = (byte)((bat>>16)&0xf);
1274            batteryHealth = (byte)((bat>>20)&0xf);
1275            batteryPlugType = (byte)((bat>>24)&0xf);
1276            int bat2 = src.readInt();
1277            batteryTemperature = (short)(bat2&0xffff);
1278            batteryVoltage = (char)((bat2>>16)&0xffff);
1279            states = src.readInt();
1280            states2 = src.readInt();
1281            if ((bat&0x10000000) != 0) {
1282                wakelockTag = localWakelockTag;
1283                wakelockTag.readFromParcel(src);
1284            } else {
1285                wakelockTag = null;
1286            }
1287            if ((bat&0x20000000) != 0) {
1288                wakeReasonTag = localWakeReasonTag;
1289                wakeReasonTag.readFromParcel(src);
1290            } else {
1291                wakeReasonTag = null;
1292            }
1293            if ((bat&0x40000000) != 0) {
1294                eventCode = src.readInt();
1295                eventTag = localEventTag;
1296                eventTag.readFromParcel(src);
1297            } else {
1298                eventCode = EVENT_NONE;
1299                eventTag = null;
1300            }
1301            if (cmd == CMD_CURRENT_TIME || cmd == CMD_RESET) {
1302                currentTime = src.readLong();
1303            } else {
1304                currentTime = 0;
1305            }
1306            numReadInts += (src.dataPosition()-start)/4;
1307        }
1308
1309        public void clear() {
1310            time = 0;
1311            cmd = CMD_NULL;
1312            batteryLevel = 0;
1313            batteryStatus = 0;
1314            batteryHealth = 0;
1315            batteryPlugType = 0;
1316            batteryTemperature = 0;
1317            batteryVoltage = 0;
1318            states = 0;
1319            states2 = 0;
1320            wakelockTag = null;
1321            wakeReasonTag = null;
1322            eventCode = EVENT_NONE;
1323            eventTag = null;
1324        }
1325
1326        public void setTo(HistoryItem o) {
1327            time = o.time;
1328            cmd = o.cmd;
1329            setToCommon(o);
1330        }
1331
1332        public void setTo(long time, byte cmd, HistoryItem o) {
1333            this.time = time;
1334            this.cmd = cmd;
1335            setToCommon(o);
1336        }
1337
1338        private void setToCommon(HistoryItem o) {
1339            batteryLevel = o.batteryLevel;
1340            batteryStatus = o.batteryStatus;
1341            batteryHealth = o.batteryHealth;
1342            batteryPlugType = o.batteryPlugType;
1343            batteryTemperature = o.batteryTemperature;
1344            batteryVoltage = o.batteryVoltage;
1345            states = o.states;
1346            states2 = o.states2;
1347            if (o.wakelockTag != null) {
1348                wakelockTag = localWakelockTag;
1349                wakelockTag.setTo(o.wakelockTag);
1350            } else {
1351                wakelockTag = null;
1352            }
1353            if (o.wakeReasonTag != null) {
1354                wakeReasonTag = localWakeReasonTag;
1355                wakeReasonTag.setTo(o.wakeReasonTag);
1356            } else {
1357                wakeReasonTag = null;
1358            }
1359            eventCode = o.eventCode;
1360            if (o.eventTag != null) {
1361                eventTag = localEventTag;
1362                eventTag.setTo(o.eventTag);
1363            } else {
1364                eventTag = null;
1365            }
1366            currentTime = o.currentTime;
1367        }
1368
1369        public boolean sameNonEvent(HistoryItem o) {
1370            return batteryLevel == o.batteryLevel
1371                    && batteryStatus == o.batteryStatus
1372                    && batteryHealth == o.batteryHealth
1373                    && batteryPlugType == o.batteryPlugType
1374                    && batteryTemperature == o.batteryTemperature
1375                    && batteryVoltage == o.batteryVoltage
1376                    && states == o.states
1377                    && states2 == o.states2
1378                    && currentTime == o.currentTime;
1379        }
1380
1381        public boolean same(HistoryItem o) {
1382            if (!sameNonEvent(o) || eventCode != o.eventCode) {
1383                return false;
1384            }
1385            if (wakelockTag != o.wakelockTag) {
1386                if (wakelockTag == null || o.wakelockTag == null) {
1387                    return false;
1388                }
1389                if (!wakelockTag.equals(o.wakelockTag)) {
1390                    return false;
1391                }
1392            }
1393            if (wakeReasonTag != o.wakeReasonTag) {
1394                if (wakeReasonTag == null || o.wakeReasonTag == null) {
1395                    return false;
1396                }
1397                if (!wakeReasonTag.equals(o.wakeReasonTag)) {
1398                    return false;
1399                }
1400            }
1401            if (eventTag != o.eventTag) {
1402                if (eventTag == null || o.eventTag == null) {
1403                    return false;
1404                }
1405                if (!eventTag.equals(o.eventTag)) {
1406                    return false;
1407                }
1408            }
1409            return true;
1410        }
1411    }
1412
1413    public final static class HistoryEventTracker {
1414        private final HashMap<String, SparseIntArray>[] mActiveEvents
1415                = (HashMap<String, SparseIntArray>[]) new HashMap[HistoryItem.EVENT_COUNT];
1416
1417        public boolean updateState(int code, String name, int uid, int poolIdx) {
1418            if ((code&HistoryItem.EVENT_FLAG_START) != 0) {
1419                int idx = code&HistoryItem.EVENT_TYPE_MASK;
1420                HashMap<String, SparseIntArray> active = mActiveEvents[idx];
1421                if (active == null) {
1422                    active = new HashMap<>();
1423                    mActiveEvents[idx] = active;
1424                }
1425                SparseIntArray uids = active.get(name);
1426                if (uids == null) {
1427                    uids = new SparseIntArray();
1428                    active.put(name, uids);
1429                }
1430                if (uids.indexOfKey(uid) >= 0) {
1431                    // Already set, nothing to do!
1432                    return false;
1433                }
1434                uids.put(uid, poolIdx);
1435            } else if ((code&HistoryItem.EVENT_FLAG_FINISH) != 0) {
1436                int idx = code&HistoryItem.EVENT_TYPE_MASK;
1437                HashMap<String, SparseIntArray> active = mActiveEvents[idx];
1438                if (active == null) {
1439                    // not currently active, nothing to do.
1440                    return false;
1441                }
1442                SparseIntArray uids = active.get(name);
1443                if (uids == null) {
1444                    // not currently active, nothing to do.
1445                    return false;
1446                }
1447                idx = uids.indexOfKey(uid);
1448                if (idx < 0) {
1449                    // not currently active, nothing to do.
1450                    return false;
1451                }
1452                uids.removeAt(idx);
1453                if (uids.size() <= 0) {
1454                    active.remove(name);
1455                }
1456            }
1457            return true;
1458        }
1459
1460        public void removeEvents(int code) {
1461            int idx = code&HistoryItem.EVENT_TYPE_MASK;
1462            mActiveEvents[idx] = null;
1463        }
1464
1465        public HashMap<String, SparseIntArray> getStateForEvent(int code) {
1466            return mActiveEvents[code];
1467        }
1468    }
1469
1470    public static final class BitDescription {
1471        public final int mask;
1472        public final int shift;
1473        public final String name;
1474        public final String shortName;
1475        public final String[] values;
1476        public final String[] shortValues;
1477
1478        public BitDescription(int mask, String name, String shortName) {
1479            this.mask = mask;
1480            this.shift = -1;
1481            this.name = name;
1482            this.shortName = shortName;
1483            this.values = null;
1484            this.shortValues = null;
1485        }
1486
1487        public BitDescription(int mask, int shift, String name, String shortName,
1488                String[] values, String[] shortValues) {
1489            this.mask = mask;
1490            this.shift = shift;
1491            this.name = name;
1492            this.shortName = shortName;
1493            this.values = values;
1494            this.shortValues = shortValues;
1495        }
1496    }
1497
1498    /**
1499     * Don't allow any more batching in to the current history event.  This
1500     * is called when printing partial histories, so to ensure that the next
1501     * history event will go in to a new batch after what was printed in the
1502     * last partial history.
1503     */
1504    public abstract void commitCurrentHistoryBatchLocked();
1505
1506    public abstract int getHistoryTotalSize();
1507
1508    public abstract int getHistoryUsedSize();
1509
1510    public abstract boolean startIteratingHistoryLocked();
1511
1512    public abstract int getHistoryStringPoolSize();
1513
1514    public abstract int getHistoryStringPoolBytes();
1515
1516    public abstract String getHistoryTagPoolString(int index);
1517
1518    public abstract int getHistoryTagPoolUid(int index);
1519
1520    public abstract boolean getNextHistoryLocked(HistoryItem out);
1521
1522    public abstract void finishIteratingHistoryLocked();
1523
1524    public abstract boolean startIteratingOldHistoryLocked();
1525
1526    public abstract boolean getNextOldHistoryLocked(HistoryItem out);
1527
1528    public abstract void finishIteratingOldHistoryLocked();
1529
1530    /**
1531     * Return the base time offset for the battery history.
1532     */
1533    public abstract long getHistoryBaseTime();
1534
1535    /**
1536     * Returns the number of times the device has been started.
1537     */
1538    public abstract int getStartCount();
1539
1540    /**
1541     * Returns the time in microseconds that the screen has been on while the device was
1542     * running on battery.
1543     *
1544     * {@hide}
1545     */
1546    public abstract long getScreenOnTime(long elapsedRealtimeUs, int which);
1547
1548    /**
1549     * Returns the number of times the screen was turned on.
1550     *
1551     * {@hide}
1552     */
1553    public abstract int getScreenOnCount(int which);
1554
1555    public abstract long getInteractiveTime(long elapsedRealtimeUs, int which);
1556
1557    public static final int SCREEN_BRIGHTNESS_DARK = 0;
1558    public static final int SCREEN_BRIGHTNESS_DIM = 1;
1559    public static final int SCREEN_BRIGHTNESS_MEDIUM = 2;
1560    public static final int SCREEN_BRIGHTNESS_LIGHT = 3;
1561    public static final int SCREEN_BRIGHTNESS_BRIGHT = 4;
1562
1563    static final String[] SCREEN_BRIGHTNESS_NAMES = {
1564        "dark", "dim", "medium", "light", "bright"
1565    };
1566
1567    static final String[] SCREEN_BRIGHTNESS_SHORT_NAMES = {
1568        "0", "1", "2", "3", "4"
1569    };
1570
1571    public static final int NUM_SCREEN_BRIGHTNESS_BINS = 5;
1572
1573    /**
1574     * Returns the time in microseconds that the screen has been on with
1575     * the given brightness
1576     *
1577     * {@hide}
1578     */
1579    public abstract long getScreenBrightnessTime(int brightnessBin,
1580            long elapsedRealtimeUs, int which);
1581
1582    /**
1583     * Returns the time in microseconds that power save mode has been enabled while the device was
1584     * running on battery.
1585     *
1586     * {@hide}
1587     */
1588    public abstract long getPowerSaveModeEnabledTime(long elapsedRealtimeUs, int which);
1589
1590    /**
1591     * Returns the number of times that power save mode was enabled.
1592     *
1593     * {@hide}
1594     */
1595    public abstract int getPowerSaveModeEnabledCount(int which);
1596
1597    /**
1598     * Returns the time in microseconds that device has been in idle mode while
1599     * running on battery.
1600     *
1601     * {@hide}
1602     */
1603    public abstract long getDeviceIdleModeEnabledTime(long elapsedRealtimeUs, int which);
1604
1605    /**
1606     * Returns the number of times that the devie has gone in to idle mode.
1607     *
1608     * {@hide}
1609     */
1610    public abstract int getDeviceIdleModeEnabledCount(int which);
1611
1612    /**
1613     * Returns the time in microseconds that device has been in idling while on
1614     * battery.  This is broader than {@link #getDeviceIdleModeEnabledTime} -- it
1615     * counts all of the time that we consider the device to be idle, whether or not
1616     * it is currently in the actual device idle mode.
1617     *
1618     * {@hide}
1619     */
1620    public abstract long getDeviceIdlingTime(long elapsedRealtimeUs, int which);
1621
1622    /**
1623     * Returns the number of times that the devie has started idling.
1624     *
1625     * {@hide}
1626     */
1627    public abstract int getDeviceIdlingCount(int which);
1628
1629    /**
1630     * Returns the number of times that connectivity state changed.
1631     *
1632     * {@hide}
1633     */
1634    public abstract int getNumConnectivityChange(int which);
1635
1636    /**
1637     * Returns the time in microseconds that the phone has been on while the device was
1638     * running on battery.
1639     *
1640     * {@hide}
1641     */
1642    public abstract long getPhoneOnTime(long elapsedRealtimeUs, int which);
1643
1644    /**
1645     * Returns the number of times a phone call was activated.
1646     *
1647     * {@hide}
1648     */
1649    public abstract int getPhoneOnCount(int which);
1650
1651    /**
1652     * Returns the time in microseconds that the phone has been running with
1653     * the given signal strength.
1654     *
1655     * {@hide}
1656     */
1657    public abstract long getPhoneSignalStrengthTime(int strengthBin,
1658            long elapsedRealtimeUs, int which);
1659
1660    /**
1661     * Returns the time in microseconds that the phone has been trying to
1662     * acquire a signal.
1663     *
1664     * {@hide}
1665     */
1666    public abstract long getPhoneSignalScanningTime(
1667            long elapsedRealtimeUs, int which);
1668
1669    /**
1670     * Returns the number of times the phone has entered the given signal strength.
1671     *
1672     * {@hide}
1673     */
1674    public abstract int getPhoneSignalStrengthCount(int strengthBin, int which);
1675
1676    /**
1677     * Returns the time in microseconds that the mobile network has been active
1678     * (in a high power state).
1679     *
1680     * {@hide}
1681     */
1682    public abstract long getMobileRadioActiveTime(long elapsedRealtimeUs, int which);
1683
1684    /**
1685     * Returns the number of times that the mobile network has transitioned to the
1686     * active state.
1687     *
1688     * {@hide}
1689     */
1690    public abstract int getMobileRadioActiveCount(int which);
1691
1692    /**
1693     * Returns the time in microseconds that is the difference between the mobile radio
1694     * time we saw based on the elapsed timestamp when going down vs. the given time stamp
1695     * from the radio.
1696     *
1697     * {@hide}
1698     */
1699    public abstract long getMobileRadioActiveAdjustedTime(int which);
1700
1701    /**
1702     * Returns the time in microseconds that the mobile network has been active
1703     * (in a high power state) but not being able to blame on an app.
1704     *
1705     * {@hide}
1706     */
1707    public abstract long getMobileRadioActiveUnknownTime(int which);
1708
1709    /**
1710     * Return count of number of times radio was up that could not be blamed on apps.
1711     *
1712     * {@hide}
1713     */
1714    public abstract int getMobileRadioActiveUnknownCount(int which);
1715
1716    public static final int DATA_CONNECTION_NONE = 0;
1717    public static final int DATA_CONNECTION_GPRS = 1;
1718    public static final int DATA_CONNECTION_EDGE = 2;
1719    public static final int DATA_CONNECTION_UMTS = 3;
1720    public static final int DATA_CONNECTION_CDMA = 4;
1721    public static final int DATA_CONNECTION_EVDO_0 = 5;
1722    public static final int DATA_CONNECTION_EVDO_A = 6;
1723    public static final int DATA_CONNECTION_1xRTT = 7;
1724    public static final int DATA_CONNECTION_HSDPA = 8;
1725    public static final int DATA_CONNECTION_HSUPA = 9;
1726    public static final int DATA_CONNECTION_HSPA = 10;
1727    public static final int DATA_CONNECTION_IDEN = 11;
1728    public static final int DATA_CONNECTION_EVDO_B = 12;
1729    public static final int DATA_CONNECTION_LTE = 13;
1730    public static final int DATA_CONNECTION_EHRPD = 14;
1731    public static final int DATA_CONNECTION_HSPAP = 15;
1732    public static final int DATA_CONNECTION_OTHER = 16;
1733
1734    static final String[] DATA_CONNECTION_NAMES = {
1735        "none", "gprs", "edge", "umts", "cdma", "evdo_0", "evdo_A",
1736        "1xrtt", "hsdpa", "hsupa", "hspa", "iden", "evdo_b", "lte",
1737        "ehrpd", "hspap", "other"
1738    };
1739
1740    public static final int NUM_DATA_CONNECTION_TYPES = DATA_CONNECTION_OTHER+1;
1741
1742    /**
1743     * Returns the time in microseconds that the phone has been running with
1744     * the given data connection.
1745     *
1746     * {@hide}
1747     */
1748    public abstract long getPhoneDataConnectionTime(int dataType,
1749            long elapsedRealtimeUs, int which);
1750
1751    /**
1752     * Returns the number of times the phone has entered the given data
1753     * connection type.
1754     *
1755     * {@hide}
1756     */
1757    public abstract int getPhoneDataConnectionCount(int dataType, int which);
1758
1759    public static final int WIFI_SUPPL_STATE_INVALID = 0;
1760    public static final int WIFI_SUPPL_STATE_DISCONNECTED = 1;
1761    public static final int WIFI_SUPPL_STATE_INTERFACE_DISABLED = 2;
1762    public static final int WIFI_SUPPL_STATE_INACTIVE = 3;
1763    public static final int WIFI_SUPPL_STATE_SCANNING = 4;
1764    public static final int WIFI_SUPPL_STATE_AUTHENTICATING = 5;
1765    public static final int WIFI_SUPPL_STATE_ASSOCIATING = 6;
1766    public static final int WIFI_SUPPL_STATE_ASSOCIATED = 7;
1767    public static final int WIFI_SUPPL_STATE_FOUR_WAY_HANDSHAKE = 8;
1768    public static final int WIFI_SUPPL_STATE_GROUP_HANDSHAKE = 9;
1769    public static final int WIFI_SUPPL_STATE_COMPLETED = 10;
1770    public static final int WIFI_SUPPL_STATE_DORMANT = 11;
1771    public static final int WIFI_SUPPL_STATE_UNINITIALIZED = 12;
1772
1773    public static final int NUM_WIFI_SUPPL_STATES = WIFI_SUPPL_STATE_UNINITIALIZED+1;
1774
1775    static final String[] WIFI_SUPPL_STATE_NAMES = {
1776        "invalid", "disconn", "disabled", "inactive", "scanning",
1777        "authenticating", "associating", "associated", "4-way-handshake",
1778        "group-handshake", "completed", "dormant", "uninit"
1779    };
1780
1781    static final String[] WIFI_SUPPL_STATE_SHORT_NAMES = {
1782        "inv", "dsc", "dis", "inact", "scan",
1783        "auth", "ascing", "asced", "4-way",
1784        "group", "compl", "dorm", "uninit"
1785    };
1786
1787    public static final BitDescription[] HISTORY_STATE_DESCRIPTIONS
1788            = new BitDescription[] {
1789        new BitDescription(HistoryItem.STATE_CPU_RUNNING_FLAG, "running", "r"),
1790        new BitDescription(HistoryItem.STATE_WAKE_LOCK_FLAG, "wake_lock", "w"),
1791        new BitDescription(HistoryItem.STATE_SENSOR_ON_FLAG, "sensor", "s"),
1792        new BitDescription(HistoryItem.STATE_GPS_ON_FLAG, "gps", "g"),
1793        new BitDescription(HistoryItem.STATE_WIFI_FULL_LOCK_FLAG, "wifi_full_lock", "Wl"),
1794        new BitDescription(HistoryItem.STATE_WIFI_SCAN_FLAG, "wifi_scan", "Ws"),
1795        new BitDescription(HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG, "wifi_multicast", "Wm"),
1796        new BitDescription(HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG, "wifi_radio", "Wr"),
1797        new BitDescription(HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG, "mobile_radio", "Pr"),
1798        new BitDescription(HistoryItem.STATE_PHONE_SCANNING_FLAG, "phone_scanning", "Psc"),
1799        new BitDescription(HistoryItem.STATE_AUDIO_ON_FLAG, "audio", "a"),
1800        new BitDescription(HistoryItem.STATE_SCREEN_ON_FLAG, "screen", "S"),
1801        new BitDescription(HistoryItem.STATE_BATTERY_PLUGGED_FLAG, "plugged", "BP"),
1802        new BitDescription(HistoryItem.STATE_DATA_CONNECTION_MASK,
1803                HistoryItem.STATE_DATA_CONNECTION_SHIFT, "data_conn", "Pcn",
1804                DATA_CONNECTION_NAMES, DATA_CONNECTION_NAMES),
1805        new BitDescription(HistoryItem.STATE_PHONE_STATE_MASK,
1806                HistoryItem.STATE_PHONE_STATE_SHIFT, "phone_state", "Pst",
1807                new String[] {"in", "out", "emergency", "off"},
1808                new String[] {"in", "out", "em", "off"}),
1809        new BitDescription(HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_MASK,
1810                HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_SHIFT, "phone_signal_strength", "Pss",
1811                SignalStrength.SIGNAL_STRENGTH_NAMES,
1812                new String[] { "0", "1", "2", "3", "4" }),
1813        new BitDescription(HistoryItem.STATE_BRIGHTNESS_MASK,
1814                HistoryItem.STATE_BRIGHTNESS_SHIFT, "brightness", "Sb",
1815                SCREEN_BRIGHTNESS_NAMES, SCREEN_BRIGHTNESS_SHORT_NAMES),
1816    };
1817
1818    public static final BitDescription[] HISTORY_STATE2_DESCRIPTIONS
1819            = new BitDescription[] {
1820        new BitDescription(HistoryItem.STATE2_POWER_SAVE_FLAG, "power_save", "ps"),
1821        new BitDescription(HistoryItem.STATE2_VIDEO_ON_FLAG, "video", "v"),
1822        new BitDescription(HistoryItem.STATE2_WIFI_RUNNING_FLAG, "wifi_running", "Ww"),
1823        new BitDescription(HistoryItem.STATE2_WIFI_ON_FLAG, "wifi", "W"),
1824        new BitDescription(HistoryItem.STATE2_FLASHLIGHT_FLAG, "flashlight", "fl"),
1825        new BitDescription(HistoryItem.STATE2_DEVICE_IDLE_FLAG, "device_idle", "di"),
1826        new BitDescription(HistoryItem.STATE2_CHARGING_FLAG, "charging", "ch"),
1827        new BitDescription(HistoryItem.STATE2_PHONE_IN_CALL_FLAG, "phone_in_call", "Pcl"),
1828        new BitDescription(HistoryItem.STATE2_BLUETOOTH_ON_FLAG, "bluetooth", "b"),
1829        new BitDescription(HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_MASK,
1830                HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_SHIFT, "wifi_signal_strength", "Wss",
1831                new String[] { "0", "1", "2", "3", "4" },
1832                new String[] { "0", "1", "2", "3", "4" }),
1833        new BitDescription(HistoryItem.STATE2_WIFI_SUPPL_STATE_MASK,
1834                HistoryItem.STATE2_WIFI_SUPPL_STATE_SHIFT, "wifi_suppl", "Wsp",
1835                WIFI_SUPPL_STATE_NAMES, WIFI_SUPPL_STATE_SHORT_NAMES),
1836        new BitDescription(HistoryItem.STATE2_CAMERA_FLAG, "camera", "ca"),
1837    };
1838
1839    public static final String[] HISTORY_EVENT_NAMES = new String[] {
1840            "null", "proc", "fg", "top", "sync", "wake_lock_in", "job", "user", "userfg", "conn",
1841            "active", "pkginst", "pkgunin", "alarm", "stats", "inactive", "active"
1842    };
1843
1844    public static final String[] HISTORY_EVENT_CHECKIN_NAMES = new String[] {
1845            "Enl", "Epr", "Efg", "Etp", "Esy", "Ewl", "Ejb", "Eur", "Euf", "Ecn",
1846            "Eac", "Epi", "Epu", "Eal", "Est", "Eai", "Eaa"
1847    };
1848
1849    /**
1850     * Returns the time in microseconds that wifi has been on while the device was
1851     * running on battery.
1852     *
1853     * {@hide}
1854     */
1855    public abstract long getWifiOnTime(long elapsedRealtimeUs, int which);
1856
1857    /**
1858     * Returns the time in microseconds that wifi has been on and the driver has
1859     * been in the running state while the device was running on battery.
1860     *
1861     * {@hide}
1862     */
1863    public abstract long getGlobalWifiRunningTime(long elapsedRealtimeUs, int which);
1864
1865    public static final int WIFI_STATE_OFF = 0;
1866    public static final int WIFI_STATE_OFF_SCANNING = 1;
1867    public static final int WIFI_STATE_ON_NO_NETWORKS = 2;
1868    public static final int WIFI_STATE_ON_DISCONNECTED = 3;
1869    public static final int WIFI_STATE_ON_CONNECTED_STA = 4;
1870    public static final int WIFI_STATE_ON_CONNECTED_P2P = 5;
1871    public static final int WIFI_STATE_ON_CONNECTED_STA_P2P = 6;
1872    public static final int WIFI_STATE_SOFT_AP = 7;
1873
1874    static final String[] WIFI_STATE_NAMES = {
1875        "off", "scanning", "no_net", "disconn",
1876        "sta", "p2p", "sta_p2p", "soft_ap"
1877    };
1878
1879    public static final int NUM_WIFI_STATES = WIFI_STATE_SOFT_AP+1;
1880
1881    /**
1882     * Returns the time in microseconds that WiFi has been running in the given state.
1883     *
1884     * {@hide}
1885     */
1886    public abstract long getWifiStateTime(int wifiState,
1887            long elapsedRealtimeUs, int which);
1888
1889    /**
1890     * Returns the number of times that WiFi has entered the given state.
1891     *
1892     * {@hide}
1893     */
1894    public abstract int getWifiStateCount(int wifiState, int which);
1895
1896    /**
1897     * Returns the time in microseconds that the wifi supplicant has been
1898     * in a given state.
1899     *
1900     * {@hide}
1901     */
1902    public abstract long getWifiSupplStateTime(int state, long elapsedRealtimeUs, int which);
1903
1904    /**
1905     * Returns the number of times that the wifi supplicant has transitioned
1906     * to a given state.
1907     *
1908     * {@hide}
1909     */
1910    public abstract int getWifiSupplStateCount(int state, int which);
1911
1912    public static final int NUM_WIFI_SIGNAL_STRENGTH_BINS = 5;
1913
1914    /**
1915     * Returns the time in microseconds that WIFI has been running with
1916     * the given signal strength.
1917     *
1918     * {@hide}
1919     */
1920    public abstract long getWifiSignalStrengthTime(int strengthBin,
1921            long elapsedRealtimeUs, int which);
1922
1923    /**
1924     * Returns the number of times WIFI has entered the given signal strength.
1925     *
1926     * {@hide}
1927     */
1928    public abstract int getWifiSignalStrengthCount(int strengthBin, int which);
1929
1930    /**
1931     * Returns the time in microseconds that the flashlight has been on while the device was
1932     * running on battery.
1933     *
1934     * {@hide}
1935     */
1936    public abstract long getFlashlightOnTime(long elapsedRealtimeUs, int which);
1937
1938    /**
1939     * Returns the number of times that the flashlight has been turned on while the device was
1940     * running on battery.
1941     *
1942     * {@hide}
1943     */
1944    public abstract long getFlashlightOnCount(int which);
1945
1946    /**
1947     * Returns the time in microseconds that the camera has been on while the device was
1948     * running on battery.
1949     *
1950     * {@hide}
1951     */
1952    public abstract long getCameraOnTime(long elapsedRealtimeUs, int which);
1953
1954
1955    public static final int NETWORK_MOBILE_RX_DATA = 0;
1956    public static final int NETWORK_MOBILE_TX_DATA = 1;
1957    public static final int NETWORK_WIFI_RX_DATA = 2;
1958    public static final int NETWORK_WIFI_TX_DATA = 3;
1959    public static final int NUM_NETWORK_ACTIVITY_TYPES = NETWORK_WIFI_TX_DATA + 1;
1960
1961    public abstract long getNetworkActivityBytes(int type, int which);
1962    public abstract long getNetworkActivityPackets(int type, int which);
1963
1964    public static final int CONTROLLER_IDLE_TIME = 0;
1965    public static final int CONTROLLER_RX_TIME = 1;
1966    public static final int CONTROLLER_TX_TIME = 2;
1967    public static final int CONTROLLER_POWER_DRAIN = 3;
1968    public static final int NUM_CONTROLLER_ACTIVITY_TYPES = CONTROLLER_POWER_DRAIN + 1;
1969
1970    /**
1971     * Returns true if the BatteryStats object has detailed bluetooth power reports.
1972     * When true, calling {@link #getBluetoothControllerActivity(int, int)} will yield the
1973     * actual power data.
1974     */
1975    public abstract boolean hasBluetoothActivityReporting();
1976
1977    /**
1978     * For {@link #CONTROLLER_IDLE_TIME}, {@link #CONTROLLER_RX_TIME}, and
1979     * {@link #CONTROLLER_TX_TIME}, returns the time spent (in milliseconds) in the
1980     * respective state.
1981     * For {@link #CONTROLLER_POWER_DRAIN}, returns the power used by the controller in
1982     * milli-ampere-milliseconds (mAms).
1983     */
1984    public abstract long getBluetoothControllerActivity(int type, int which);
1985
1986    /**
1987     * Returns true if the BatteryStats object has detailed WiFi power reports.
1988     * When true, calling {@link #getWifiControllerActivity(int, int)} will yield the
1989     * actual power data.
1990     */
1991    public abstract boolean hasWifiActivityReporting();
1992
1993    /**
1994     * For {@link #CONTROLLER_IDLE_TIME}, {@link #CONTROLLER_RX_TIME}, and
1995     * {@link #CONTROLLER_TX_TIME}, returns the time spent (in milliseconds) in the
1996     * respective state.
1997     * For {@link #CONTROLLER_POWER_DRAIN}, returns the power used by the controller in
1998     * milli-ampere-milliseconds (mAms).
1999     */
2000    public abstract long getWifiControllerActivity(int type, int which);
2001
2002    /**
2003     * Return the wall clock time when battery stats data collection started.
2004     */
2005    public abstract long getStartClockTime();
2006
2007    /**
2008     * Return platform version tag that we were running in when the battery stats started.
2009     */
2010    public abstract String getStartPlatformVersion();
2011
2012    /**
2013     * Return platform version tag that we were running in when the battery stats ended.
2014     */
2015    public abstract String getEndPlatformVersion();
2016
2017    /**
2018     * Return the internal version code of the parcelled format.
2019     */
2020    public abstract int getParcelVersion();
2021
2022    /**
2023     * Return whether we are currently running on battery.
2024     */
2025    public abstract boolean getIsOnBattery();
2026
2027    /**
2028     * Returns a SparseArray containing the statistics for each uid.
2029     */
2030    public abstract SparseArray<? extends Uid> getUidStats();
2031
2032    /**
2033     * Returns the current battery uptime in microseconds.
2034     *
2035     * @param curTime the amount of elapsed realtime in microseconds.
2036     */
2037    public abstract long getBatteryUptime(long curTime);
2038
2039    /**
2040     * Returns the current battery realtime in microseconds.
2041     *
2042     * @param curTime the amount of elapsed realtime in microseconds.
2043     */
2044    public abstract long getBatteryRealtime(long curTime);
2045
2046    /**
2047     * Returns the battery percentage level at the last time the device was unplugged from power, or
2048     * the last time it booted on battery power.
2049     */
2050    public abstract int getDischargeStartLevel();
2051
2052    /**
2053     * Returns the current battery percentage level if we are in a discharge cycle, otherwise
2054     * returns the level at the last plug event.
2055     */
2056    public abstract int getDischargeCurrentLevel();
2057
2058    /**
2059     * Get the amount the battery has discharged since the stats were
2060     * last reset after charging, as a lower-end approximation.
2061     */
2062    public abstract int getLowDischargeAmountSinceCharge();
2063
2064    /**
2065     * Get the amount the battery has discharged since the stats were
2066     * last reset after charging, as an upper-end approximation.
2067     */
2068    public abstract int getHighDischargeAmountSinceCharge();
2069
2070    /**
2071     * Retrieve the discharge amount over the selected discharge period <var>which</var>.
2072     */
2073    public abstract int getDischargeAmount(int which);
2074
2075    /**
2076     * Get the amount the battery has discharged while the screen was on,
2077     * since the last time power was unplugged.
2078     */
2079    public abstract int getDischargeAmountScreenOn();
2080
2081    /**
2082     * Get the amount the battery has discharged while the screen was on,
2083     * since the last time the device was charged.
2084     */
2085    public abstract int getDischargeAmountScreenOnSinceCharge();
2086
2087    /**
2088     * Get the amount the battery has discharged while the screen was off,
2089     * since the last time power was unplugged.
2090     */
2091    public abstract int getDischargeAmountScreenOff();
2092
2093    /**
2094     * Get the amount the battery has discharged while the screen was off,
2095     * since the last time the device was charged.
2096     */
2097    public abstract int getDischargeAmountScreenOffSinceCharge();
2098
2099    /**
2100     * Returns the total, last, or current battery uptime in microseconds.
2101     *
2102     * @param curTime the elapsed realtime in microseconds.
2103     * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
2104     */
2105    public abstract long computeBatteryUptime(long curTime, int which);
2106
2107    /**
2108     * Returns the total, last, or current battery realtime in microseconds.
2109     *
2110     * @param curTime the current elapsed realtime in microseconds.
2111     * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
2112     */
2113    public abstract long computeBatteryRealtime(long curTime, int which);
2114
2115    /**
2116     * Returns the total, last, or current battery screen off uptime in microseconds.
2117     *
2118     * @param curTime the elapsed realtime in microseconds.
2119     * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
2120     */
2121    public abstract long computeBatteryScreenOffUptime(long curTime, int which);
2122
2123    /**
2124     * Returns the total, last, or current battery screen off realtime in microseconds.
2125     *
2126     * @param curTime the current elapsed realtime in microseconds.
2127     * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
2128     */
2129    public abstract long computeBatteryScreenOffRealtime(long curTime, int which);
2130
2131    /**
2132     * Returns the total, last, or current uptime in microseconds.
2133     *
2134     * @param curTime the current elapsed realtime in microseconds.
2135     * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
2136     */
2137    public abstract long computeUptime(long curTime, int which);
2138
2139    /**
2140     * Returns the total, last, or current realtime in microseconds.
2141     *
2142     * @param curTime the current elapsed realtime in microseconds.
2143     * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
2144     */
2145    public abstract long computeRealtime(long curTime, int which);
2146
2147    /**
2148     * Compute an approximation for how much run time (in microseconds) is remaining on
2149     * the battery.  Returns -1 if no time can be computed: either there is not
2150     * enough current data to make a decision, or the battery is currently
2151     * charging.
2152     *
2153     * @param curTime The current elepsed realtime in microseconds.
2154     */
2155    public abstract long computeBatteryTimeRemaining(long curTime);
2156
2157    // The part of a step duration that is the actual time.
2158    public static final long STEP_LEVEL_TIME_MASK = 0x000000ffffffffffL;
2159
2160    // Bits in a step duration that are the new battery level we are at.
2161    public static final long STEP_LEVEL_LEVEL_MASK = 0x0000ff0000000000L;
2162    public static final int STEP_LEVEL_LEVEL_SHIFT = 40;
2163
2164    // Bits in a step duration that are the initial mode we were in at that step.
2165    public static final long STEP_LEVEL_INITIAL_MODE_MASK = 0x00ff000000000000L;
2166    public static final int STEP_LEVEL_INITIAL_MODE_SHIFT = 48;
2167
2168    // Bits in a step duration that indicate which modes changed during that step.
2169    public static final long STEP_LEVEL_MODIFIED_MODE_MASK = 0xff00000000000000L;
2170    public static final int STEP_LEVEL_MODIFIED_MODE_SHIFT = 56;
2171
2172    // Step duration mode: the screen is on, off, dozed, etc; value is Display.STATE_* - 1.
2173    public static final int STEP_LEVEL_MODE_SCREEN_STATE = 0x03;
2174
2175    // Step duration mode: power save is on.
2176    public static final int STEP_LEVEL_MODE_POWER_SAVE = 0x04;
2177
2178    // Step duration mode: device is currently in idle mode.
2179    public static final int STEP_LEVEL_MODE_DEVICE_IDLE = 0x08;
2180
2181    public static final int[] STEP_LEVEL_MODES_OF_INTEREST = new int[] {
2182            STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
2183            STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE|STEP_LEVEL_MODE_DEVICE_IDLE,
2184            STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_DEVICE_IDLE,
2185            STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
2186            STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
2187            STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
2188            STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
2189            STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
2190            STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE|STEP_LEVEL_MODE_DEVICE_IDLE,
2191            STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_DEVICE_IDLE,
2192    };
2193    public static final int[] STEP_LEVEL_MODE_VALUES = new int[] {
2194            (Display.STATE_OFF-1),
2195            (Display.STATE_OFF-1)|STEP_LEVEL_MODE_POWER_SAVE,
2196            (Display.STATE_OFF-1)|STEP_LEVEL_MODE_DEVICE_IDLE,
2197            (Display.STATE_ON-1),
2198            (Display.STATE_ON-1)|STEP_LEVEL_MODE_POWER_SAVE,
2199            (Display.STATE_DOZE-1),
2200            (Display.STATE_DOZE-1)|STEP_LEVEL_MODE_POWER_SAVE,
2201            (Display.STATE_DOZE_SUSPEND-1),
2202            (Display.STATE_DOZE_SUSPEND-1)|STEP_LEVEL_MODE_POWER_SAVE,
2203            (Display.STATE_DOZE_SUSPEND-1)|STEP_LEVEL_MODE_DEVICE_IDLE,
2204    };
2205    public static final String[] STEP_LEVEL_MODE_LABELS = new String[] {
2206            "screen off",
2207            "screen off power save",
2208            "screen off device idle",
2209            "screen on",
2210            "screen on power save",
2211            "screen doze",
2212            "screen doze power save",
2213            "screen doze-suspend",
2214            "screen doze-suspend power save",
2215            "screen doze-suspend device idle",
2216    };
2217
2218    /**
2219     * Return the array of discharge step durations.
2220     */
2221    public abstract LevelStepTracker getDischargeLevelStepTracker();
2222
2223    /**
2224     * Return the array of daily discharge step durations.
2225     */
2226    public abstract LevelStepTracker getDailyDischargeLevelStepTracker();
2227
2228    /**
2229     * Compute an approximation for how much time (in microseconds) remains until the battery
2230     * is fully charged.  Returns -1 if no time can be computed: either there is not
2231     * enough current data to make a decision, or the battery is currently
2232     * discharging.
2233     *
2234     * @param curTime The current elepsed realtime in microseconds.
2235     */
2236    public abstract long computeChargeTimeRemaining(long curTime);
2237
2238    /**
2239     * Return the array of charge step durations.
2240     */
2241    public abstract LevelStepTracker getChargeLevelStepTracker();
2242
2243    /**
2244     * Return the array of daily charge step durations.
2245     */
2246    public abstract LevelStepTracker getDailyChargeLevelStepTracker();
2247
2248    public abstract ArrayList<PackageChange> getDailyPackageChanges();
2249
2250    public abstract Map<String, ? extends Timer> getWakeupReasonStats();
2251
2252    public abstract Map<String, ? extends Timer> getKernelWakelockStats();
2253
2254    /** Returns the number of different speeds that the CPU can run at */
2255    public abstract int getCpuSpeedSteps();
2256
2257    public abstract void writeToParcelWithoutUids(Parcel out, int flags);
2258
2259    private final static void formatTimeRaw(StringBuilder out, long seconds) {
2260        long days = seconds / (60 * 60 * 24);
2261        if (days != 0) {
2262            out.append(days);
2263            out.append("d ");
2264        }
2265        long used = days * 60 * 60 * 24;
2266
2267        long hours = (seconds - used) / (60 * 60);
2268        if (hours != 0 || used != 0) {
2269            out.append(hours);
2270            out.append("h ");
2271        }
2272        used += hours * 60 * 60;
2273
2274        long mins = (seconds-used) / 60;
2275        if (mins != 0 || used != 0) {
2276            out.append(mins);
2277            out.append("m ");
2278        }
2279        used += mins * 60;
2280
2281        if (seconds != 0 || used != 0) {
2282            out.append(seconds-used);
2283            out.append("s ");
2284        }
2285    }
2286
2287    public final static void formatTimeMs(StringBuilder sb, long time) {
2288        long sec = time / 1000;
2289        formatTimeRaw(sb, sec);
2290        sb.append(time - (sec * 1000));
2291        sb.append("ms ");
2292    }
2293
2294    public final static void formatTimeMsNoSpace(StringBuilder sb, long time) {
2295        long sec = time / 1000;
2296        formatTimeRaw(sb, sec);
2297        sb.append(time - (sec * 1000));
2298        sb.append("ms");
2299    }
2300
2301    public final String formatRatioLocked(long num, long den) {
2302        if (den == 0L) {
2303            return "--%";
2304        }
2305        float perc = ((float)num) / ((float)den) * 100;
2306        mFormatBuilder.setLength(0);
2307        mFormatter.format("%.1f%%", perc);
2308        return mFormatBuilder.toString();
2309    }
2310
2311    final String formatBytesLocked(long bytes) {
2312        mFormatBuilder.setLength(0);
2313
2314        if (bytes < BYTES_PER_KB) {
2315            return bytes + "B";
2316        } else if (bytes < BYTES_PER_MB) {
2317            mFormatter.format("%.2fKB", bytes / (double) BYTES_PER_KB);
2318            return mFormatBuilder.toString();
2319        } else if (bytes < BYTES_PER_GB){
2320            mFormatter.format("%.2fMB", bytes / (double) BYTES_PER_MB);
2321            return mFormatBuilder.toString();
2322        } else {
2323            mFormatter.format("%.2fGB", bytes / (double) BYTES_PER_GB);
2324            return mFormatBuilder.toString();
2325        }
2326    }
2327
2328    private static long computeWakeLock(Timer timer, long elapsedRealtimeUs, int which) {
2329        if (timer != null) {
2330            // Convert from microseconds to milliseconds with rounding
2331            long totalTimeMicros = timer.getTotalTimeLocked(elapsedRealtimeUs, which);
2332            long totalTimeMillis = (totalTimeMicros + 500) / 1000;
2333            return totalTimeMillis;
2334        }
2335        return 0;
2336    }
2337
2338    /**
2339     *
2340     * @param sb a StringBuilder object.
2341     * @param timer a Timer object contining the wakelock times.
2342     * @param elapsedRealtimeUs the current on-battery time in microseconds.
2343     * @param name the name of the wakelock.
2344     * @param which which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
2345     * @param linePrefix a String to be prepended to each line of output.
2346     * @return the line prefix
2347     */
2348    private static final String printWakeLock(StringBuilder sb, Timer timer,
2349            long elapsedRealtimeUs, String name, int which, String linePrefix) {
2350
2351        if (timer != null) {
2352            long totalTimeMillis = computeWakeLock(timer, elapsedRealtimeUs, which);
2353
2354            int count = timer.getCountLocked(which);
2355            if (totalTimeMillis != 0) {
2356                sb.append(linePrefix);
2357                formatTimeMs(sb, totalTimeMillis);
2358                if (name != null) {
2359                    sb.append(name);
2360                    sb.append(' ');
2361                }
2362                sb.append('(');
2363                sb.append(count);
2364                sb.append(" times)");
2365                return ", ";
2366            }
2367        }
2368        return linePrefix;
2369    }
2370
2371    /**
2372     *
2373     * @param pw a PrintWriter object to print to.
2374     * @param sb a StringBuilder object.
2375     * @param timer a Timer object contining the wakelock times.
2376     * @param rawRealtime the current on-battery time in microseconds.
2377     * @param which which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
2378     * @param prefix a String to be prepended to each line of output.
2379     * @param type the name of the timer.
2380     */
2381    private static final boolean printTimer(PrintWriter pw, StringBuilder sb, Timer timer,
2382            long rawRealtime, int which, String prefix, String type) {
2383        if (timer != null) {
2384            // Convert from microseconds to milliseconds with rounding
2385            final long totalTime = (timer.getTotalTimeLocked(
2386                    rawRealtime, which) + 500) / 1000;
2387            final int count = timer.getCountLocked(which);
2388            if (totalTime != 0) {
2389                sb.setLength(0);
2390                sb.append(prefix);
2391                sb.append("    ");
2392                sb.append(type);
2393                sb.append(": ");
2394                formatTimeMs(sb, totalTime);
2395                sb.append("realtime (");
2396                sb.append(count);
2397                sb.append(" times)");
2398                pw.println(sb.toString());
2399                return true;
2400            }
2401        }
2402        return false;
2403    }
2404
2405    /**
2406     * Checkin version of wakelock printer. Prints simple comma-separated list.
2407     *
2408     * @param sb a StringBuilder object.
2409     * @param timer a Timer object contining the wakelock times.
2410     * @param elapsedRealtimeUs the current time in microseconds.
2411     * @param name the name of the wakelock.
2412     * @param which which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
2413     * @param linePrefix a String to be prepended to each line of output.
2414     * @return the line prefix
2415     */
2416    private static final String printWakeLockCheckin(StringBuilder sb, Timer timer,
2417            long elapsedRealtimeUs, String name, int which, String linePrefix) {
2418        long totalTimeMicros = 0;
2419        int count = 0;
2420        if (timer != null) {
2421            totalTimeMicros = timer.getTotalTimeLocked(elapsedRealtimeUs, which);
2422            count = timer.getCountLocked(which);
2423        }
2424        sb.append(linePrefix);
2425        sb.append((totalTimeMicros + 500) / 1000); // microseconds to milliseconds with rounding
2426        sb.append(',');
2427        sb.append(name != null ? name + "," : "");
2428        sb.append(count);
2429        return ",";
2430    }
2431
2432    /**
2433     * Dump a comma-separated line of values for terse checkin mode.
2434     *
2435     * @param pw the PageWriter to dump log to
2436     * @param category category of data (e.g. "total", "last", "unplugged", "current" )
2437     * @param type type of data (e.g. "wakelock", "sensor", "process", "apk" ,  "process", "network")
2438     * @param args type-dependent data arguments
2439     */
2440    private static final void dumpLine(PrintWriter pw, int uid, String category, String type,
2441           Object... args ) {
2442        pw.print(BATTERY_STATS_CHECKIN_VERSION);
2443        pw.print(',');
2444        pw.print(uid);
2445        pw.print(',');
2446        pw.print(category);
2447        pw.print(',');
2448        pw.print(type);
2449
2450        for (Object arg : args) {
2451            pw.print(',');
2452            pw.print(arg);
2453        }
2454        pw.println();
2455    }
2456
2457    /**
2458     * Dump a given timer stat for terse checkin mode.
2459     *
2460     * @param pw the PageWriter to dump log to
2461     * @param uid the UID to log
2462     * @param category category of data (e.g. "total", "last", "unplugged", "current" )
2463     * @param type type of data (e.g. "wakelock", "sensor", "process", "apk" ,  "process", "network")
2464     * @param timer a {@link Timer} to dump stats for
2465     * @param rawRealtime the current elapsed realtime of the system in microseconds
2466     * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT
2467     */
2468    private static final void dumpTimer(PrintWriter pw, int uid, String category, String type,
2469                                        Timer timer, long rawRealtime, int which) {
2470        if (timer != null) {
2471            // Convert from microseconds to milliseconds with rounding
2472            final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500)
2473                    / 1000;
2474            final int count = timer.getCountLocked(which);
2475            if (totalTime != 0) {
2476                dumpLine(pw, uid, category, type, totalTime, count);
2477            }
2478        }
2479    }
2480
2481    /**
2482     * Temporary for settings.
2483     */
2484    public final void dumpCheckinLocked(Context context, PrintWriter pw, int which, int reqUid) {
2485        dumpCheckinLocked(context, pw, which, reqUid, BatteryStatsHelper.checkWifiOnly(context));
2486    }
2487
2488    /**
2489     * Checkin server version of dump to produce more compact, computer-readable log.
2490     *
2491     * NOTE: all times are expressed in 'ms'.
2492     */
2493    public final void dumpCheckinLocked(Context context, PrintWriter pw, int which, int reqUid,
2494            boolean wifiOnly) {
2495        final long rawUptime = SystemClock.uptimeMillis() * 1000;
2496        final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
2497        final long batteryUptime = getBatteryUptime(rawUptime);
2498        final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
2499        final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
2500        final long whichBatteryScreenOffUptime = computeBatteryScreenOffUptime(rawUptime, which);
2501        final long whichBatteryScreenOffRealtime = computeBatteryScreenOffRealtime(rawRealtime,
2502                which);
2503        final long totalRealtime = computeRealtime(rawRealtime, which);
2504        final long totalUptime = computeUptime(rawUptime, which);
2505        final long screenOnTime = getScreenOnTime(rawRealtime, which);
2506        final long interactiveTime = getInteractiveTime(rawRealtime, which);
2507        final long powerSaveModeEnabledTime = getPowerSaveModeEnabledTime(rawRealtime, which);
2508        final long deviceIdleModeEnabledTime = getDeviceIdleModeEnabledTime(rawRealtime, which);
2509        final long deviceIdlingTime = getDeviceIdlingTime(rawRealtime, which);
2510        final int connChanges = getNumConnectivityChange(which);
2511        final long phoneOnTime = getPhoneOnTime(rawRealtime, which);
2512
2513        final StringBuilder sb = new StringBuilder(128);
2514
2515        final SparseArray<? extends Uid> uidStats = getUidStats();
2516        final int NU = uidStats.size();
2517
2518        final String category = STAT_NAMES[which];
2519
2520        // Dump "battery" stat
2521        dumpLine(pw, 0 /* uid */, category, BATTERY_DATA,
2522                which == STATS_SINCE_CHARGED ? getStartCount() : "N/A",
2523                whichBatteryRealtime / 1000, whichBatteryUptime / 1000,
2524                totalRealtime / 1000, totalUptime / 1000,
2525                getStartClockTime(),
2526                whichBatteryScreenOffRealtime / 1000, whichBatteryScreenOffUptime / 1000);
2527
2528        // Calculate wakelock times across all uids.
2529        long fullWakeLockTimeTotal = 0;
2530        long partialWakeLockTimeTotal = 0;
2531
2532        for (int iu = 0; iu < NU; iu++) {
2533            final Uid u = uidStats.valueAt(iu);
2534
2535            final ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> wakelocks
2536                    = u.getWakelockStats();
2537            for (int iw=wakelocks.size()-1; iw>=0; iw--) {
2538                final Uid.Wakelock wl = wakelocks.valueAt(iw);
2539
2540                final Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
2541                if (fullWakeTimer != null) {
2542                    fullWakeLockTimeTotal += fullWakeTimer.getTotalTimeLocked(rawRealtime,
2543                            which);
2544                }
2545
2546                final Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
2547                if (partialWakeTimer != null) {
2548                    partialWakeLockTimeTotal += partialWakeTimer.getTotalTimeLocked(
2549                        rawRealtime, which);
2550                }
2551            }
2552        }
2553
2554        // Dump network stats
2555        final long mobileRxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
2556        final long mobileTxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
2557        final long wifiRxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
2558        final long wifiTxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
2559        final long mobileRxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
2560        final long mobileTxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
2561        final long wifiRxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
2562        final long wifiTxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
2563        dumpLine(pw, 0 /* uid */, category, GLOBAL_NETWORK_DATA,
2564                mobileRxTotalBytes, mobileTxTotalBytes, wifiRxTotalBytes, wifiTxTotalBytes,
2565                mobileRxTotalPackets, mobileTxTotalPackets, wifiRxTotalPackets, wifiTxTotalPackets);
2566
2567        // Dump Wifi controller stats
2568        final long wifiOnTime = getWifiOnTime(rawRealtime, which);
2569        final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which);
2570        final long wifiIdleTimeMs = getWifiControllerActivity(CONTROLLER_IDLE_TIME, which);
2571        final long wifiRxTimeMs = getWifiControllerActivity(CONTROLLER_RX_TIME, which);
2572        final long wifiTxTimeMs = getWifiControllerActivity(CONTROLLER_TX_TIME, which);
2573        final long wifiPowerMaMs = getWifiControllerActivity(CONTROLLER_POWER_DRAIN, which);
2574        dumpLine(pw, 0 /* uid */, category, GLOBAL_WIFI_DATA,
2575                wifiOnTime / 1000, wifiRunningTime / 1000,
2576                wifiIdleTimeMs, wifiRxTimeMs, wifiTxTimeMs, wifiPowerMaMs / (1000*60*60));
2577
2578        // Dump Bluetooth controller stats
2579        final long btIdleTimeMs = getBluetoothControllerActivity(CONTROLLER_IDLE_TIME, which);
2580        final long btRxTimeMs = getBluetoothControllerActivity(CONTROLLER_RX_TIME, which);
2581        final long btTxTimeMs = getBluetoothControllerActivity(CONTROLLER_TX_TIME, which);
2582        final long btPowerMaMs = getBluetoothControllerActivity(CONTROLLER_POWER_DRAIN, which);
2583        dumpLine(pw, 0 /* uid */, category, GLOBAL_BLUETOOTH_DATA,
2584                btIdleTimeMs, btRxTimeMs, btTxTimeMs, btPowerMaMs / (1000*60*60));
2585
2586        // Dump misc stats
2587        dumpLine(pw, 0 /* uid */, category, MISC_DATA,
2588                screenOnTime / 1000, phoneOnTime / 1000,
2589                fullWakeLockTimeTotal / 1000, partialWakeLockTimeTotal / 1000,
2590                getMobileRadioActiveTime(rawRealtime, which) / 1000,
2591                getMobileRadioActiveAdjustedTime(which) / 1000, interactiveTime / 1000,
2592                powerSaveModeEnabledTime / 1000, connChanges, deviceIdleModeEnabledTime / 1000,
2593                getDeviceIdleModeEnabledCount(which), deviceIdlingTime / 1000,
2594                getDeviceIdlingCount(which));
2595
2596        // Dump screen brightness stats
2597        Object[] args = new Object[NUM_SCREEN_BRIGHTNESS_BINS];
2598        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
2599            args[i] = getScreenBrightnessTime(i, rawRealtime, which) / 1000;
2600        }
2601        dumpLine(pw, 0 /* uid */, category, SCREEN_BRIGHTNESS_DATA, args);
2602
2603        // Dump signal strength stats
2604        args = new Object[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
2605        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
2606            args[i] = getPhoneSignalStrengthTime(i, rawRealtime, which) / 1000;
2607        }
2608        dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_TIME_DATA, args);
2609        dumpLine(pw, 0 /* uid */, category, SIGNAL_SCANNING_TIME_DATA,
2610                getPhoneSignalScanningTime(rawRealtime, which) / 1000);
2611        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
2612            args[i] = getPhoneSignalStrengthCount(i, which);
2613        }
2614        dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_COUNT_DATA, args);
2615
2616        // Dump network type stats
2617        args = new Object[NUM_DATA_CONNECTION_TYPES];
2618        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
2619            args[i] = getPhoneDataConnectionTime(i, rawRealtime, which) / 1000;
2620        }
2621        dumpLine(pw, 0 /* uid */, category, DATA_CONNECTION_TIME_DATA, args);
2622        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
2623            args[i] = getPhoneDataConnectionCount(i, which);
2624        }
2625        dumpLine(pw, 0 /* uid */, category, DATA_CONNECTION_COUNT_DATA, args);
2626
2627        // Dump wifi state stats
2628        args = new Object[NUM_WIFI_STATES];
2629        for (int i=0; i<NUM_WIFI_STATES; i++) {
2630            args[i] = getWifiStateTime(i, rawRealtime, which) / 1000;
2631        }
2632        dumpLine(pw, 0 /* uid */, category, WIFI_STATE_TIME_DATA, args);
2633        for (int i=0; i<NUM_WIFI_STATES; i++) {
2634            args[i] = getWifiStateCount(i, which);
2635        }
2636        dumpLine(pw, 0 /* uid */, category, WIFI_STATE_COUNT_DATA, args);
2637
2638        // Dump wifi suppl state stats
2639        args = new Object[NUM_WIFI_SUPPL_STATES];
2640        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
2641            args[i] = getWifiSupplStateTime(i, rawRealtime, which) / 1000;
2642        }
2643        dumpLine(pw, 0 /* uid */, category, WIFI_SUPPL_STATE_TIME_DATA, args);
2644        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
2645            args[i] = getWifiSupplStateCount(i, which);
2646        }
2647        dumpLine(pw, 0 /* uid */, category, WIFI_SUPPL_STATE_COUNT_DATA, args);
2648
2649        // Dump wifi signal strength stats
2650        args = new Object[NUM_WIFI_SIGNAL_STRENGTH_BINS];
2651        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
2652            args[i] = getWifiSignalStrengthTime(i, rawRealtime, which) / 1000;
2653        }
2654        dumpLine(pw, 0 /* uid */, category, WIFI_SIGNAL_STRENGTH_TIME_DATA, args);
2655        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
2656            args[i] = getWifiSignalStrengthCount(i, which);
2657        }
2658        dumpLine(pw, 0 /* uid */, category, WIFI_SIGNAL_STRENGTH_COUNT_DATA, args);
2659
2660        if (which == STATS_SINCE_UNPLUGGED) {
2661            dumpLine(pw, 0 /* uid */, category, BATTERY_LEVEL_DATA, getDischargeStartLevel(),
2662                    getDischargeCurrentLevel());
2663        }
2664
2665        if (which == STATS_SINCE_UNPLUGGED) {
2666            dumpLine(pw, 0 /* uid */, category, BATTERY_DISCHARGE_DATA,
2667                    getDischargeStartLevel()-getDischargeCurrentLevel(),
2668                    getDischargeStartLevel()-getDischargeCurrentLevel(),
2669                    getDischargeAmountScreenOn(), getDischargeAmountScreenOff());
2670        } else {
2671            dumpLine(pw, 0 /* uid */, category, BATTERY_DISCHARGE_DATA,
2672                    getLowDischargeAmountSinceCharge(), getHighDischargeAmountSinceCharge(),
2673                    getDischargeAmountScreenOnSinceCharge(),
2674                    getDischargeAmountScreenOffSinceCharge());
2675        }
2676
2677        if (reqUid < 0) {
2678            final Map<String, ? extends Timer> kernelWakelocks = getKernelWakelockStats();
2679            if (kernelWakelocks.size() > 0) {
2680                for (Map.Entry<String, ? extends Timer> ent : kernelWakelocks.entrySet()) {
2681                    sb.setLength(0);
2682                    printWakeLockCheckin(sb, ent.getValue(), rawRealtime, null, which, "");
2683                    dumpLine(pw, 0 /* uid */, category, KERNEL_WAKELOCK_DATA, ent.getKey(),
2684                            sb.toString());
2685                }
2686            }
2687            final Map<String, ? extends Timer> wakeupReasons = getWakeupReasonStats();
2688            if (wakeupReasons.size() > 0) {
2689                for (Map.Entry<String, ? extends Timer> ent : wakeupReasons.entrySet()) {
2690                    // Not doing the regular wake lock formatting to remain compatible
2691                    // with the old checkin format.
2692                    long totalTimeMicros = ent.getValue().getTotalTimeLocked(rawRealtime, which);
2693                    int count = ent.getValue().getCountLocked(which);
2694                    dumpLine(pw, 0 /* uid */, category, WAKEUP_REASON_DATA,
2695                            "\"" + ent.getKey() + "\"", (totalTimeMicros + 500) / 1000, count);
2696                }
2697            }
2698        }
2699
2700        final BatteryStatsHelper helper = new BatteryStatsHelper(context, false, wifiOnly);
2701        helper.create(this);
2702        helper.refreshStats(which, UserHandle.USER_ALL);
2703        final List<BatterySipper> sippers = helper.getUsageList();
2704        if (sippers != null && sippers.size() > 0) {
2705            dumpLine(pw, 0 /* uid */, category, POWER_USE_SUMMARY_DATA,
2706                    BatteryStatsHelper.makemAh(helper.getPowerProfile().getBatteryCapacity()),
2707                    BatteryStatsHelper.makemAh(helper.getComputedPower()),
2708                    BatteryStatsHelper.makemAh(helper.getMinDrainedPower()),
2709                    BatteryStatsHelper.makemAh(helper.getMaxDrainedPower()));
2710            for (int i=0; i<sippers.size(); i++) {
2711                final BatterySipper bs = sippers.get(i);
2712                int uid = 0;
2713                String label;
2714                switch (bs.drainType) {
2715                    case IDLE:
2716                        label="idle";
2717                        break;
2718                    case CELL:
2719                        label="cell";
2720                        break;
2721                    case PHONE:
2722                        label="phone";
2723                        break;
2724                    case WIFI:
2725                        label="wifi";
2726                        break;
2727                    case BLUETOOTH:
2728                        label="blue";
2729                        break;
2730                    case SCREEN:
2731                        label="scrn";
2732                        break;
2733                    case FLASHLIGHT:
2734                        label="flashlight";
2735                        break;
2736                    case APP:
2737                        uid = bs.uidObj.getUid();
2738                        label = "uid";
2739                        break;
2740                    case USER:
2741                        uid = UserHandle.getUid(bs.userId, 0);
2742                        label = "user";
2743                        break;
2744                    case UNACCOUNTED:
2745                        label = "unacc";
2746                        break;
2747                    case OVERCOUNTED:
2748                        label = "over";
2749                        break;
2750                    case CAMERA:
2751                        label = "camera";
2752                        break;
2753                    default:
2754                        label = "???";
2755                }
2756                dumpLine(pw, uid, category, POWER_USE_ITEM_DATA, label,
2757                        BatteryStatsHelper.makemAh(bs.totalPowerMah));
2758            }
2759        }
2760
2761        for (int iu = 0; iu < NU; iu++) {
2762            final int uid = uidStats.keyAt(iu);
2763            if (reqUid >= 0 && uid != reqUid) {
2764                continue;
2765            }
2766            final Uid u = uidStats.valueAt(iu);
2767
2768            // Dump Network stats per uid, if any
2769            final long mobileBytesRx = u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
2770            final long mobileBytesTx = u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
2771            final long wifiBytesRx = u.getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
2772            final long wifiBytesTx = u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
2773            final long mobilePacketsRx = u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
2774            final long mobilePacketsTx = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
2775            final long mobileActiveTime = u.getMobileRadioActiveTime(which);
2776            final int mobileActiveCount = u.getMobileRadioActiveCount(which);
2777            final long wifiPacketsRx = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
2778            final long wifiPacketsTx = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
2779            if (mobileBytesRx > 0 || mobileBytesTx > 0 || wifiBytesRx > 0 || wifiBytesTx > 0
2780                    || mobilePacketsRx > 0 || mobilePacketsTx > 0 || wifiPacketsRx > 0
2781                    || wifiPacketsTx > 0 || mobileActiveTime > 0 || mobileActiveCount > 0) {
2782                dumpLine(pw, uid, category, NETWORK_DATA, mobileBytesRx, mobileBytesTx,
2783                        wifiBytesRx, wifiBytesTx,
2784                        mobilePacketsRx, mobilePacketsTx,
2785                        wifiPacketsRx, wifiPacketsTx,
2786                        mobileActiveTime, mobileActiveCount);
2787            }
2788
2789            final long fullWifiLockOnTime = u.getFullWifiLockTime(rawRealtime, which);
2790            final long wifiScanTime = u.getWifiScanTime(rawRealtime, which);
2791            final int wifiScanCount = u.getWifiScanCount(which);
2792            final long uidWifiRunningTime = u.getWifiRunningTime(rawRealtime, which);
2793            final long uidWifiIdleTimeMs = u.getWifiControllerActivity(CONTROLLER_IDLE_TIME, which);
2794            final long uidWifiRxTimeMs = u.getWifiControllerActivity(CONTROLLER_RX_TIME, which);
2795            final long uidWifiTxTimeMs = u.getWifiControllerActivity(CONTROLLER_TX_TIME, which);
2796            if (fullWifiLockOnTime != 0 || wifiScanTime != 0 || wifiScanCount != 0
2797                    || uidWifiRunningTime != 0 || uidWifiIdleTimeMs != 0 || uidWifiRxTimeMs != 0
2798                    || uidWifiTxTimeMs != 0) {
2799                dumpLine(pw, uid, category, WIFI_DATA,
2800                        fullWifiLockOnTime, wifiScanTime, uidWifiRunningTime, wifiScanCount,
2801                        uidWifiIdleTimeMs, uidWifiRxTimeMs, uidWifiTxTimeMs);
2802            }
2803
2804            if (u.hasUserActivity()) {
2805                args = new Object[Uid.NUM_USER_ACTIVITY_TYPES];
2806                boolean hasData = false;
2807                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
2808                    int val = u.getUserActivityCount(i, which);
2809                    args[i] = val;
2810                    if (val != 0) hasData = true;
2811                }
2812                if (hasData) {
2813                    dumpLine(pw, uid /* uid */, category, USER_ACTIVITY_DATA, args);
2814                }
2815            }
2816
2817            final ArrayMap<String, ? extends Uid.Wakelock> wakelocks = u.getWakelockStats();
2818            for (int iw=wakelocks.size()-1; iw>=0; iw--) {
2819                final Uid.Wakelock wl = wakelocks.valueAt(iw);
2820                String linePrefix = "";
2821                sb.setLength(0);
2822                linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_FULL),
2823                        rawRealtime, "f", which, linePrefix);
2824                linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL),
2825                        rawRealtime, "p", which, linePrefix);
2826                linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_WINDOW),
2827                        rawRealtime, "w", which, linePrefix);
2828
2829                // Only log if we had at lease one wakelock...
2830                if (sb.length() > 0) {
2831                    String name = wakelocks.keyAt(iw);
2832                    if (name.indexOf(',') >= 0) {
2833                        name = name.replace(',', '_');
2834                    }
2835                    dumpLine(pw, uid, category, WAKELOCK_DATA, name, sb.toString());
2836                }
2837            }
2838
2839            final ArrayMap<String, ? extends Timer> syncs = u.getSyncStats();
2840            for (int isy=syncs.size()-1; isy>=0; isy--) {
2841                final Timer timer = syncs.valueAt(isy);
2842                // Convert from microseconds to milliseconds with rounding
2843                final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
2844                final int count = timer.getCountLocked(which);
2845                if (totalTime != 0) {
2846                    dumpLine(pw, uid, category, SYNC_DATA, syncs.keyAt(isy), totalTime, count);
2847                }
2848            }
2849
2850            final ArrayMap<String, ? extends Timer> jobs = u.getJobStats();
2851            for (int ij=jobs.size()-1; ij>=0; ij--) {
2852                final Timer timer = jobs.valueAt(ij);
2853                // Convert from microseconds to milliseconds with rounding
2854                final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
2855                final int count = timer.getCountLocked(which);
2856                if (totalTime != 0) {
2857                    dumpLine(pw, uid, category, JOB_DATA, jobs.keyAt(ij), totalTime, count);
2858                }
2859            }
2860
2861            dumpTimer(pw, uid, category, FLASHLIGHT_DATA, u.getFlashlightTurnedOnTimer(),
2862                    rawRealtime, which);
2863            dumpTimer(pw, uid, category, CAMERA_DATA, u.getCameraTurnedOnTimer(),
2864                    rawRealtime, which);
2865            dumpTimer(pw, uid, category, VIDEO_DATA, u.getVideoTurnedOnTimer(),
2866                    rawRealtime, which);
2867            dumpTimer(pw, uid, category, AUDIO_DATA, u.getAudioTurnedOnTimer(),
2868                    rawRealtime, which);
2869
2870            final SparseArray<? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
2871            final int NSE = sensors.size();
2872            for (int ise=0; ise<NSE; ise++) {
2873                final Uid.Sensor se = sensors.valueAt(ise);
2874                final int sensorNumber = sensors.keyAt(ise);
2875                final Timer timer = se.getSensorTime();
2876                if (timer != null) {
2877                    // Convert from microseconds to milliseconds with rounding
2878                    final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500)
2879                            / 1000;
2880                    final int count = timer.getCountLocked(which);
2881                    if (totalTime != 0) {
2882                        dumpLine(pw, uid, category, SENSOR_DATA, sensorNumber, totalTime, count);
2883                    }
2884                }
2885            }
2886
2887            dumpTimer(pw, uid, category, VIBRATOR_DATA, u.getVibratorOnTimer(),
2888                    rawRealtime, which);
2889
2890            dumpTimer(pw, uid, category, FOREGROUND_DATA, u.getForegroundActivityTimer(),
2891                    rawRealtime, which);
2892
2893            final Object[] stateTimes = new Object[Uid.NUM_PROCESS_STATE];
2894            long totalStateTime = 0;
2895            for (int ips=0; ips<Uid.NUM_PROCESS_STATE; ips++) {
2896                totalStateTime += u.getProcessStateTime(ips, rawRealtime, which);
2897                stateTimes[ips] = (totalStateTime + 500) / 1000;
2898            }
2899            if (totalStateTime > 0) {
2900                dumpLine(pw, uid, category, STATE_TIME_DATA, stateTimes);
2901            }
2902
2903            final ArrayMap<String, ? extends BatteryStats.Uid.Proc> processStats
2904                    = u.getProcessStats();
2905            for (int ipr=processStats.size()-1; ipr>=0; ipr--) {
2906                final Uid.Proc ps = processStats.valueAt(ipr);
2907
2908                final long userMillis = ps.getUserTime(which);
2909                final long systemMillis = ps.getSystemTime(which);
2910                final long foregroundMillis = ps.getForegroundTime(which);
2911                final int starts = ps.getStarts(which);
2912                final int numCrashes = ps.getNumCrashes(which);
2913                final int numAnrs = ps.getNumAnrs(which);
2914
2915                if (userMillis != 0 || systemMillis != 0 || foregroundMillis != 0
2916                        || starts != 0 || numAnrs != 0 || numCrashes != 0) {
2917                    dumpLine(pw, uid, category, PROCESS_DATA, processStats.keyAt(ipr), userMillis,
2918                            systemMillis, foregroundMillis, starts, numAnrs, numCrashes);
2919                }
2920            }
2921
2922            final ArrayMap<String, ? extends BatteryStats.Uid.Pkg> packageStats
2923                    = u.getPackageStats();
2924            for (int ipkg=packageStats.size()-1; ipkg>=0; ipkg--) {
2925                final Uid.Pkg ps = packageStats.valueAt(ipkg);
2926                int wakeups = 0;
2927                final ArrayMap<String, ? extends Counter> alarms = ps.getWakeupAlarmStats();
2928                for (int iwa=alarms.size()-1; iwa>=0; iwa--) {
2929                    wakeups += alarms.valueAt(iwa).getCountLocked(which);
2930                }
2931                final ArrayMap<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
2932                for (int isvc=serviceStats.size()-1; isvc>=0; isvc--) {
2933                    final BatteryStats.Uid.Pkg.Serv ss = serviceStats.valueAt(isvc);
2934                    final long startTime = ss.getStartTime(batteryUptime, which);
2935                    final int starts = ss.getStarts(which);
2936                    final int launches = ss.getLaunches(which);
2937                    if (startTime != 0 || starts != 0 || launches != 0) {
2938                        dumpLine(pw, uid, category, APK_DATA,
2939                                wakeups, // wakeup alarms
2940                                packageStats.keyAt(ipkg), // Apk
2941                                serviceStats.keyAt(isvc), // service
2942                                startTime / 1000, // time spent started, in ms
2943                                starts,
2944                                launches);
2945                    }
2946                }
2947            }
2948        }
2949    }
2950
2951    static final class TimerEntry {
2952        final String mName;
2953        final int mId;
2954        final BatteryStats.Timer mTimer;
2955        final long mTime;
2956        TimerEntry(String name, int id, BatteryStats.Timer timer, long time) {
2957            mName = name;
2958            mId = id;
2959            mTimer = timer;
2960            mTime = time;
2961        }
2962    }
2963
2964    private void printmAh(PrintWriter printer, double power) {
2965        printer.print(BatteryStatsHelper.makemAh(power));
2966    }
2967
2968    /**
2969     * Temporary for settings.
2970     */
2971    public final void dumpLocked(Context context, PrintWriter pw, String prefix, int which,
2972            int reqUid) {
2973        dumpLocked(context, pw, prefix, which, reqUid, BatteryStatsHelper.checkWifiOnly(context));
2974    }
2975
2976    @SuppressWarnings("unused")
2977    public final void dumpLocked(Context context, PrintWriter pw, String prefix, final int which,
2978            int reqUid, boolean wifiOnly) {
2979        final long rawUptime = SystemClock.uptimeMillis() * 1000;
2980        final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
2981        final long batteryUptime = getBatteryUptime(rawUptime);
2982
2983        final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
2984        final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
2985        final long totalRealtime = computeRealtime(rawRealtime, which);
2986        final long totalUptime = computeUptime(rawUptime, which);
2987        final long whichBatteryScreenOffUptime = computeBatteryScreenOffUptime(rawUptime, which);
2988        final long whichBatteryScreenOffRealtime = computeBatteryScreenOffRealtime(rawRealtime,
2989                which);
2990        final long batteryTimeRemaining = computeBatteryTimeRemaining(rawRealtime);
2991        final long chargeTimeRemaining = computeChargeTimeRemaining(rawRealtime);
2992
2993        final StringBuilder sb = new StringBuilder(128);
2994
2995        final SparseArray<? extends Uid> uidStats = getUidStats();
2996        final int NU = uidStats.size();
2997
2998        sb.setLength(0);
2999        sb.append(prefix);
3000                sb.append("  Time on battery: ");
3001                formatTimeMs(sb, whichBatteryRealtime / 1000); sb.append("(");
3002                sb.append(formatRatioLocked(whichBatteryRealtime, totalRealtime));
3003                sb.append(") realtime, ");
3004                formatTimeMs(sb, whichBatteryUptime / 1000);
3005                sb.append("("); sb.append(formatRatioLocked(whichBatteryUptime, totalRealtime));
3006                sb.append(") uptime");
3007        pw.println(sb.toString());
3008        sb.setLength(0);
3009        sb.append(prefix);
3010                sb.append("  Time on battery screen off: ");
3011                formatTimeMs(sb, whichBatteryScreenOffRealtime / 1000); sb.append("(");
3012                sb.append(formatRatioLocked(whichBatteryScreenOffRealtime, totalRealtime));
3013                sb.append(") realtime, ");
3014                formatTimeMs(sb, whichBatteryScreenOffUptime / 1000);
3015                sb.append("(");
3016                sb.append(formatRatioLocked(whichBatteryScreenOffUptime, totalRealtime));
3017                sb.append(") uptime");
3018        pw.println(sb.toString());
3019        sb.setLength(0);
3020        sb.append(prefix);
3021                sb.append("  Total run time: ");
3022                formatTimeMs(sb, totalRealtime / 1000);
3023                sb.append("realtime, ");
3024                formatTimeMs(sb, totalUptime / 1000);
3025                sb.append("uptime");
3026        pw.println(sb.toString());
3027        if (batteryTimeRemaining >= 0) {
3028            sb.setLength(0);
3029            sb.append(prefix);
3030                    sb.append("  Battery time remaining: ");
3031                    formatTimeMs(sb, batteryTimeRemaining / 1000);
3032            pw.println(sb.toString());
3033        }
3034        if (chargeTimeRemaining >= 0) {
3035            sb.setLength(0);
3036            sb.append(prefix);
3037                    sb.append("  Charge time remaining: ");
3038                    formatTimeMs(sb, chargeTimeRemaining / 1000);
3039            pw.println(sb.toString());
3040        }
3041        pw.print("  Start clock time: ");
3042        pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss", getStartClockTime()).toString());
3043
3044        final long screenOnTime = getScreenOnTime(rawRealtime, which);
3045        final long interactiveTime = getInteractiveTime(rawRealtime, which);
3046        final long powerSaveModeEnabledTime = getPowerSaveModeEnabledTime(rawRealtime, which);
3047        final long deviceIdleModeEnabledTime = getDeviceIdleModeEnabledTime(rawRealtime, which);
3048        final long deviceIdlingTime = getDeviceIdlingTime(rawRealtime, which);
3049        final long phoneOnTime = getPhoneOnTime(rawRealtime, which);
3050        final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which);
3051        final long wifiOnTime = getWifiOnTime(rawRealtime, which);
3052        sb.setLength(0);
3053        sb.append(prefix);
3054                sb.append("  Screen on: "); formatTimeMs(sb, screenOnTime / 1000);
3055                sb.append("("); sb.append(formatRatioLocked(screenOnTime, whichBatteryRealtime));
3056                sb.append(") "); sb.append(getScreenOnCount(which));
3057                sb.append("x, Interactive: "); formatTimeMs(sb, interactiveTime / 1000);
3058                sb.append("("); sb.append(formatRatioLocked(interactiveTime, whichBatteryRealtime));
3059                sb.append(")");
3060        pw.println(sb.toString());
3061        sb.setLength(0);
3062        sb.append(prefix);
3063        sb.append("  Screen brightnesses:");
3064        boolean didOne = false;
3065        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
3066            final long time = getScreenBrightnessTime(i, rawRealtime, which);
3067            if (time == 0) {
3068                continue;
3069            }
3070            sb.append("\n    ");
3071            sb.append(prefix);
3072            didOne = true;
3073            sb.append(SCREEN_BRIGHTNESS_NAMES[i]);
3074            sb.append(" ");
3075            formatTimeMs(sb, time/1000);
3076            sb.append("(");
3077            sb.append(formatRatioLocked(time, screenOnTime));
3078            sb.append(")");
3079        }
3080        if (!didOne) sb.append(" (no activity)");
3081        pw.println(sb.toString());
3082        if (powerSaveModeEnabledTime != 0) {
3083            sb.setLength(0);
3084            sb.append(prefix);
3085                    sb.append("  Power save mode enabled: ");
3086                    formatTimeMs(sb, powerSaveModeEnabledTime / 1000);
3087                    sb.append("(");
3088                    sb.append(formatRatioLocked(powerSaveModeEnabledTime, whichBatteryRealtime));
3089                    sb.append(")");
3090            pw.println(sb.toString());
3091        }
3092        if (deviceIdlingTime != 0) {
3093            sb.setLength(0);
3094            sb.append(prefix);
3095                    sb.append("  Device idling: ");
3096                    formatTimeMs(sb, deviceIdlingTime / 1000);
3097                    sb.append("(");
3098                    sb.append(formatRatioLocked(deviceIdlingTime, whichBatteryRealtime));
3099                    sb.append(") "); sb.append(getDeviceIdlingCount(which));
3100                    sb.append("x");
3101            pw.println(sb.toString());
3102        }
3103        if (deviceIdleModeEnabledTime != 0) {
3104            sb.setLength(0);
3105            sb.append(prefix);
3106                    sb.append("  Idle mode time: ");
3107                    formatTimeMs(sb, deviceIdleModeEnabledTime / 1000);
3108                    sb.append("(");
3109                    sb.append(formatRatioLocked(deviceIdleModeEnabledTime, whichBatteryRealtime));
3110                    sb.append(") "); sb.append(getDeviceIdleModeEnabledCount(which));
3111                    sb.append("x");
3112            pw.println(sb.toString());
3113        }
3114        if (phoneOnTime != 0) {
3115            sb.setLength(0);
3116            sb.append(prefix);
3117                    sb.append("  Active phone call: "); formatTimeMs(sb, phoneOnTime / 1000);
3118                    sb.append("("); sb.append(formatRatioLocked(phoneOnTime, whichBatteryRealtime));
3119                    sb.append(") "); sb.append(getPhoneOnCount(which)); sb.append("x");
3120        }
3121        final int connChanges = getNumConnectivityChange(which);
3122        if (connChanges != 0) {
3123            pw.print(prefix);
3124            pw.print("  Connectivity changes: "); pw.println(connChanges);
3125        }
3126
3127        // Calculate wakelock times across all uids.
3128        long fullWakeLockTimeTotalMicros = 0;
3129        long partialWakeLockTimeTotalMicros = 0;
3130
3131        final ArrayList<TimerEntry> timers = new ArrayList<>();
3132
3133        for (int iu = 0; iu < NU; iu++) {
3134            final Uid u = uidStats.valueAt(iu);
3135
3136            final ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> wakelocks
3137                    = u.getWakelockStats();
3138            for (int iw=wakelocks.size()-1; iw>=0; iw--) {
3139                final Uid.Wakelock wl = wakelocks.valueAt(iw);
3140
3141                final Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
3142                if (fullWakeTimer != null) {
3143                    fullWakeLockTimeTotalMicros += fullWakeTimer.getTotalTimeLocked(
3144                            rawRealtime, which);
3145                }
3146
3147                final Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
3148                if (partialWakeTimer != null) {
3149                    final long totalTimeMicros = partialWakeTimer.getTotalTimeLocked(
3150                            rawRealtime, which);
3151                    if (totalTimeMicros > 0) {
3152                        if (reqUid < 0) {
3153                            // Only show the ordered list of all wake
3154                            // locks if the caller is not asking for data
3155                            // about a specific uid.
3156                            timers.add(new TimerEntry(wakelocks.keyAt(iw), u.getUid(),
3157                                    partialWakeTimer, totalTimeMicros));
3158                        }
3159                        partialWakeLockTimeTotalMicros += totalTimeMicros;
3160                    }
3161                }
3162            }
3163        }
3164
3165        final long mobileRxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
3166        final long mobileTxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
3167        final long wifiRxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
3168        final long wifiTxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
3169        final long mobileRxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
3170        final long mobileTxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
3171        final long wifiRxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
3172        final long wifiTxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
3173
3174        if (fullWakeLockTimeTotalMicros != 0) {
3175            sb.setLength(0);
3176            sb.append(prefix);
3177                    sb.append("  Total full wakelock time: "); formatTimeMsNoSpace(sb,
3178                            (fullWakeLockTimeTotalMicros + 500) / 1000);
3179            pw.println(sb.toString());
3180        }
3181
3182        if (partialWakeLockTimeTotalMicros != 0) {
3183            sb.setLength(0);
3184            sb.append(prefix);
3185                    sb.append("  Total partial wakelock time: "); formatTimeMsNoSpace(sb,
3186                            (partialWakeLockTimeTotalMicros + 500) / 1000);
3187            pw.println(sb.toString());
3188        }
3189
3190        pw.print(prefix);
3191                pw.print("  Mobile total received: "); pw.print(formatBytesLocked(mobileRxTotalBytes));
3192                pw.print(", sent: "); pw.print(formatBytesLocked(mobileTxTotalBytes));
3193                pw.print(" (packets received "); pw.print(mobileRxTotalPackets);
3194                pw.print(", sent "); pw.print(mobileTxTotalPackets); pw.println(")");
3195        sb.setLength(0);
3196        sb.append(prefix);
3197        sb.append("  Phone signal levels:");
3198        didOne = false;
3199        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
3200            final long time = getPhoneSignalStrengthTime(i, rawRealtime, which);
3201            if (time == 0) {
3202                continue;
3203            }
3204            sb.append("\n    ");
3205            sb.append(prefix);
3206            didOne = true;
3207            sb.append(SignalStrength.SIGNAL_STRENGTH_NAMES[i]);
3208            sb.append(" ");
3209            formatTimeMs(sb, time/1000);
3210            sb.append("(");
3211            sb.append(formatRatioLocked(time, whichBatteryRealtime));
3212            sb.append(") ");
3213            sb.append(getPhoneSignalStrengthCount(i, which));
3214            sb.append("x");
3215        }
3216        if (!didOne) sb.append(" (no activity)");
3217        pw.println(sb.toString());
3218
3219        sb.setLength(0);
3220        sb.append(prefix);
3221        sb.append("  Signal scanning time: ");
3222        formatTimeMsNoSpace(sb, getPhoneSignalScanningTime(rawRealtime, which) / 1000);
3223        pw.println(sb.toString());
3224
3225        sb.setLength(0);
3226        sb.append(prefix);
3227        sb.append("  Radio types:");
3228        didOne = false;
3229        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
3230            final long time = getPhoneDataConnectionTime(i, rawRealtime, which);
3231            if (time == 0) {
3232                continue;
3233            }
3234            sb.append("\n    ");
3235            sb.append(prefix);
3236            didOne = true;
3237            sb.append(DATA_CONNECTION_NAMES[i]);
3238            sb.append(" ");
3239            formatTimeMs(sb, time/1000);
3240            sb.append("(");
3241            sb.append(formatRatioLocked(time, whichBatteryRealtime));
3242            sb.append(") ");
3243            sb.append(getPhoneDataConnectionCount(i, which));
3244            sb.append("x");
3245        }
3246        if (!didOne) sb.append(" (no activity)");
3247        pw.println(sb.toString());
3248
3249        sb.setLength(0);
3250        sb.append(prefix);
3251        sb.append("  Mobile radio active time: ");
3252        final long mobileActiveTime = getMobileRadioActiveTime(rawRealtime, which);
3253        formatTimeMs(sb, mobileActiveTime / 1000);
3254        sb.append("("); sb.append(formatRatioLocked(mobileActiveTime, whichBatteryRealtime));
3255        sb.append(") "); sb.append(getMobileRadioActiveCount(which));
3256        sb.append("x");
3257        pw.println(sb.toString());
3258
3259        final long mobileActiveUnknownTime = getMobileRadioActiveUnknownTime(which);
3260        if (mobileActiveUnknownTime != 0) {
3261            sb.setLength(0);
3262            sb.append(prefix);
3263            sb.append("  Mobile radio active unknown time: ");
3264            formatTimeMs(sb, mobileActiveUnknownTime / 1000);
3265            sb.append("(");
3266            sb.append(formatRatioLocked(mobileActiveUnknownTime, whichBatteryRealtime));
3267            sb.append(") "); sb.append(getMobileRadioActiveUnknownCount(which));
3268            sb.append("x");
3269            pw.println(sb.toString());
3270        }
3271
3272        final long mobileActiveAdjustedTime = getMobileRadioActiveAdjustedTime(which);
3273        if (mobileActiveAdjustedTime != 0) {
3274            sb.setLength(0);
3275            sb.append(prefix);
3276            sb.append("  Mobile radio active adjusted time: ");
3277            formatTimeMs(sb, mobileActiveAdjustedTime / 1000);
3278            sb.append("(");
3279            sb.append(formatRatioLocked(mobileActiveAdjustedTime, whichBatteryRealtime));
3280            sb.append(")");
3281            pw.println(sb.toString());
3282        }
3283
3284        pw.print(prefix);
3285                pw.print("  Wi-Fi total received: "); pw.print(formatBytesLocked(wifiRxTotalBytes));
3286                pw.print(", sent: "); pw.print(formatBytesLocked(wifiTxTotalBytes));
3287                pw.print(" (packets received "); pw.print(wifiRxTotalPackets);
3288                pw.print(", sent "); pw.print(wifiTxTotalPackets); pw.println(")");
3289        sb.setLength(0);
3290        sb.append(prefix);
3291                sb.append("  Wifi on: "); formatTimeMs(sb, wifiOnTime / 1000);
3292                sb.append("("); sb.append(formatRatioLocked(wifiOnTime, whichBatteryRealtime));
3293                sb.append("), Wifi running: "); formatTimeMs(sb, wifiRunningTime / 1000);
3294                sb.append("("); sb.append(formatRatioLocked(wifiRunningTime, whichBatteryRealtime));
3295                sb.append(")");
3296        pw.println(sb.toString());
3297
3298        sb.setLength(0);
3299        sb.append(prefix);
3300        sb.append("  Wifi states:");
3301        didOne = false;
3302        for (int i=0; i<NUM_WIFI_STATES; i++) {
3303            final long time = getWifiStateTime(i, rawRealtime, which);
3304            if (time == 0) {
3305                continue;
3306            }
3307            sb.append("\n    ");
3308            didOne = true;
3309            sb.append(WIFI_STATE_NAMES[i]);
3310            sb.append(" ");
3311            formatTimeMs(sb, time/1000);
3312            sb.append("(");
3313            sb.append(formatRatioLocked(time, whichBatteryRealtime));
3314            sb.append(") ");
3315            sb.append(getWifiStateCount(i, which));
3316            sb.append("x");
3317        }
3318        if (!didOne) sb.append(" (no activity)");
3319        pw.println(sb.toString());
3320
3321        sb.setLength(0);
3322        sb.append(prefix);
3323        sb.append("  Wifi supplicant states:");
3324        didOne = false;
3325        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
3326            final long time = getWifiSupplStateTime(i, rawRealtime, which);
3327            if (time == 0) {
3328                continue;
3329            }
3330            sb.append("\n    ");
3331            didOne = true;
3332            sb.append(WIFI_SUPPL_STATE_NAMES[i]);
3333            sb.append(" ");
3334            formatTimeMs(sb, time/1000);
3335            sb.append("(");
3336            sb.append(formatRatioLocked(time, whichBatteryRealtime));
3337            sb.append(") ");
3338            sb.append(getWifiSupplStateCount(i, which));
3339            sb.append("x");
3340        }
3341        if (!didOne) sb.append(" (no activity)");
3342        pw.println(sb.toString());
3343
3344        sb.setLength(0);
3345        sb.append(prefix);
3346        sb.append("  Wifi signal levels:");
3347        didOne = false;
3348        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
3349            final long time = getWifiSignalStrengthTime(i, rawRealtime, which);
3350            if (time == 0) {
3351                continue;
3352            }
3353            sb.append("\n    ");
3354            sb.append(prefix);
3355            didOne = true;
3356            sb.append("level(");
3357            sb.append(i);
3358            sb.append(") ");
3359            formatTimeMs(sb, time/1000);
3360            sb.append("(");
3361            sb.append(formatRatioLocked(time, whichBatteryRealtime));
3362            sb.append(") ");
3363            sb.append(getWifiSignalStrengthCount(i, which));
3364            sb.append("x");
3365        }
3366        if (!didOne) sb.append(" (no activity)");
3367        pw.println(sb.toString());
3368
3369        final long wifiIdleTimeMs = getWifiControllerActivity(CONTROLLER_IDLE_TIME, which);
3370        final long wifiRxTimeMs = getWifiControllerActivity(CONTROLLER_RX_TIME, which);
3371        final long wifiTxTimeMs = getWifiControllerActivity(CONTROLLER_TX_TIME, which);
3372        final long wifiPowerDrainMaMs = getWifiControllerActivity(CONTROLLER_POWER_DRAIN, which);
3373        final long wifiTotalTimeMs = wifiIdleTimeMs + wifiRxTimeMs + wifiTxTimeMs;
3374
3375        sb.setLength(0);
3376        sb.append(prefix);
3377        sb.append("  WiFi Idle time: "); formatTimeMs(sb, wifiIdleTimeMs);
3378        sb.append("(");
3379        sb.append(formatRatioLocked(wifiIdleTimeMs, wifiTotalTimeMs));
3380        sb.append(")");
3381        pw.println(sb.toString());
3382
3383        sb.setLength(0);
3384        sb.append(prefix);
3385        sb.append("  WiFi Rx time:   "); formatTimeMs(sb, wifiRxTimeMs);
3386        sb.append("(");
3387        sb.append(formatRatioLocked(wifiRxTimeMs, wifiTotalTimeMs));
3388        sb.append(")");
3389        pw.println(sb.toString());
3390
3391        sb.setLength(0);
3392        sb.append(prefix);
3393        sb.append("  WiFi Tx time:   "); formatTimeMs(sb, wifiTxTimeMs);
3394        sb.append("(");
3395        sb.append(formatRatioLocked(wifiTxTimeMs, wifiTotalTimeMs));
3396        sb.append(")");
3397        pw.println(sb.toString());
3398
3399        sb.setLength(0);
3400        sb.append(prefix);
3401        sb.append("  WiFi Power drain: ").append(
3402                BatteryStatsHelper.makemAh(wifiPowerDrainMaMs / (double) (1000*60*60)));
3403        sb.append("mAh");
3404        pw.println(sb.toString());
3405
3406        final long bluetoothIdleTimeMs =
3407                getBluetoothControllerActivity(CONTROLLER_IDLE_TIME, which);
3408        final long bluetoothRxTimeMs = getBluetoothControllerActivity(CONTROLLER_RX_TIME, which);
3409        final long bluetoothTxTimeMs = getBluetoothControllerActivity(CONTROLLER_TX_TIME, which);
3410        final long bluetoothTotalTimeMs = bluetoothIdleTimeMs + bluetoothRxTimeMs +
3411                bluetoothTxTimeMs;
3412
3413        sb.setLength(0);
3414        sb.append(prefix);
3415        sb.append("  Bluetooth Idle time: "); formatTimeMs(sb, bluetoothIdleTimeMs);
3416        sb.append("(");
3417        sb.append(formatRatioLocked(bluetoothIdleTimeMs, bluetoothTotalTimeMs));
3418        sb.append(")");
3419        pw.println(sb.toString());
3420
3421        sb.setLength(0);
3422        sb.append(prefix);
3423        sb.append("  Bluetooth Rx time:   "); formatTimeMs(sb, bluetoothRxTimeMs);
3424        sb.append("(");
3425        sb.append(formatRatioLocked(bluetoothRxTimeMs, bluetoothTotalTimeMs));
3426        sb.append(")");
3427        pw.println(sb.toString());
3428
3429        sb.setLength(0);
3430        sb.append(prefix);
3431        sb.append("  Bluetooth Tx time:   "); formatTimeMs(sb, bluetoothTxTimeMs);
3432        sb.append("(");
3433        sb.append(formatRatioLocked(bluetoothTxTimeMs, bluetoothTotalTimeMs));
3434        sb.append(")");
3435        pw.println(sb.toString());
3436
3437        sb.setLength(0);
3438        sb.append(prefix);
3439        sb.append("  Bluetooth Power drain: ").append(BatteryStatsHelper.makemAh(
3440                getBluetoothControllerActivity(CONTROLLER_POWER_DRAIN, which) /
3441                        (double)(1000*60*60)));
3442        sb.append("mAh");
3443        pw.println(sb.toString());
3444
3445        pw.println();
3446
3447        if (which == STATS_SINCE_UNPLUGGED) {
3448            if (getIsOnBattery()) {
3449                pw.print(prefix); pw.println("  Device is currently unplugged");
3450                pw.print(prefix); pw.print("    Discharge cycle start level: ");
3451                        pw.println(getDischargeStartLevel());
3452                pw.print(prefix); pw.print("    Discharge cycle current level: ");
3453                        pw.println(getDischargeCurrentLevel());
3454            } else {
3455                pw.print(prefix); pw.println("  Device is currently plugged into power");
3456                pw.print(prefix); pw.print("    Last discharge cycle start level: ");
3457                        pw.println(getDischargeStartLevel());
3458                pw.print(prefix); pw.print("    Last discharge cycle end level: ");
3459                        pw.println(getDischargeCurrentLevel());
3460            }
3461            pw.print(prefix); pw.print("    Amount discharged while screen on: ");
3462                    pw.println(getDischargeAmountScreenOn());
3463            pw.print(prefix); pw.print("    Amount discharged while screen off: ");
3464                    pw.println(getDischargeAmountScreenOff());
3465            pw.println(" ");
3466        } else {
3467            pw.print(prefix); pw.println("  Device battery use since last full charge");
3468            pw.print(prefix); pw.print("    Amount discharged (lower bound): ");
3469                    pw.println(getLowDischargeAmountSinceCharge());
3470            pw.print(prefix); pw.print("    Amount discharged (upper bound): ");
3471                    pw.println(getHighDischargeAmountSinceCharge());
3472            pw.print(prefix); pw.print("    Amount discharged while screen on: ");
3473                    pw.println(getDischargeAmountScreenOnSinceCharge());
3474            pw.print(prefix); pw.print("    Amount discharged while screen off: ");
3475                    pw.println(getDischargeAmountScreenOffSinceCharge());
3476            pw.println();
3477        }
3478
3479        final BatteryStatsHelper helper = new BatteryStatsHelper(context, false, wifiOnly);
3480        helper.create(this);
3481        helper.refreshStats(which, UserHandle.USER_ALL);
3482        List<BatterySipper> sippers = helper.getUsageList();
3483        if (sippers != null && sippers.size() > 0) {
3484            pw.print(prefix); pw.println("  Estimated power use (mAh):");
3485            pw.print(prefix); pw.print("    Capacity: ");
3486                    printmAh(pw, helper.getPowerProfile().getBatteryCapacity());
3487                    pw.print(", Computed drain: "); printmAh(pw, helper.getComputedPower());
3488                    pw.print(", actual drain: "); printmAh(pw, helper.getMinDrainedPower());
3489                    if (helper.getMinDrainedPower() != helper.getMaxDrainedPower()) {
3490                        pw.print("-"); printmAh(pw, helper.getMaxDrainedPower());
3491                    }
3492                    pw.println();
3493            for (int i=0; i<sippers.size(); i++) {
3494                final BatterySipper bs = sippers.get(i);
3495                pw.print(prefix);
3496                switch (bs.drainType) {
3497                    case IDLE:
3498                        pw.print("    Idle: ");
3499                        break;
3500                    case CELL:
3501                        pw.print("    Cell standby: ");
3502                        break;
3503                    case PHONE:
3504                        pw.print("    Phone calls: ");
3505                        break;
3506                    case WIFI:
3507                        pw.print("    Wifi: ");
3508                        break;
3509                    case BLUETOOTH:
3510                        pw.print("    Bluetooth: ");
3511                        break;
3512                    case SCREEN:
3513                        pw.print("    Screen: ");
3514                        break;
3515                    case FLASHLIGHT:
3516                        pw.print("    Flashlight: ");
3517                        break;
3518                    case APP:
3519                        pw.print("    Uid ");
3520                        UserHandle.formatUid(pw, bs.uidObj.getUid());
3521                        pw.print(": ");
3522                        break;
3523                    case USER:
3524                        pw.print("    User "); pw.print(bs.userId);
3525                        pw.print(": ");
3526                        break;
3527                    case UNACCOUNTED:
3528                        pw.print("    Unaccounted: ");
3529                        break;
3530                    case OVERCOUNTED:
3531                        pw.print("    Over-counted: ");
3532                        break;
3533                    case CAMERA:
3534                        pw.print("    Camera: ");
3535                        break;
3536                    default:
3537                        pw.print("    ???: ");
3538                        break;
3539                }
3540                printmAh(pw, bs.totalPowerMah);
3541
3542                if (bs.usagePowerMah != bs.totalPowerMah) {
3543                    // If the usage (generic power) isn't the whole amount, we list out
3544                    // what components are involved in the calculation.
3545
3546                    pw.print(" (");
3547                    if (bs.usagePowerMah != 0) {
3548                        pw.print(" usage=");
3549                        printmAh(pw, bs.usagePowerMah);
3550                    }
3551                    if (bs.cpuPowerMah != 0) {
3552                        pw.print(" cpu=");
3553                        printmAh(pw, bs.cpuPowerMah);
3554                    }
3555                    if (bs.wakeLockPowerMah != 0) {
3556                        pw.print(" wake=");
3557                        printmAh(pw, bs.wakeLockPowerMah);
3558                    }
3559                    if (bs.mobileRadioPowerMah != 0) {
3560                        pw.print(" radio=");
3561                        printmAh(pw, bs.mobileRadioPowerMah);
3562                    }
3563                    if (bs.wifiPowerMah != 0) {
3564                        pw.print(" wifi=");
3565                        printmAh(pw, bs.wifiPowerMah);
3566                    }
3567                    if (bs.gpsPowerMah != 0) {
3568                        pw.print(" gps=");
3569                        printmAh(pw, bs.gpsPowerMah);
3570                    }
3571                    if (bs.sensorPowerMah != 0) {
3572                        pw.print(" sensor=");
3573                        printmAh(pw, bs.sensorPowerMah);
3574                    }
3575                    if (bs.cameraPowerMah != 0) {
3576                        pw.print(" camera=");
3577                        printmAh(pw, bs.cameraPowerMah);
3578                    }
3579                    if (bs.flashlightPowerMah != 0) {
3580                        pw.print(" flash=");
3581                        printmAh(pw, bs.flashlightPowerMah);
3582                    }
3583                    pw.print(" )");
3584                }
3585                pw.println();
3586            }
3587            pw.println();
3588        }
3589
3590        sippers = helper.getMobilemsppList();
3591        if (sippers != null && sippers.size() > 0) {
3592            pw.print(prefix); pw.println("  Per-app mobile ms per packet:");
3593            long totalTime = 0;
3594            for (int i=0; i<sippers.size(); i++) {
3595                final BatterySipper bs = sippers.get(i);
3596                sb.setLength(0);
3597                sb.append(prefix); sb.append("    Uid ");
3598                UserHandle.formatUid(sb, bs.uidObj.getUid());
3599                sb.append(": "); sb.append(BatteryStatsHelper.makemAh(bs.mobilemspp));
3600                sb.append(" ("); sb.append(bs.mobileRxPackets+bs.mobileTxPackets);
3601                sb.append(" packets over "); formatTimeMsNoSpace(sb, bs.mobileActive);
3602                sb.append(") "); sb.append(bs.mobileActiveCount); sb.append("x");
3603                pw.println(sb.toString());
3604                totalTime += bs.mobileActive;
3605            }
3606            sb.setLength(0);
3607            sb.append(prefix);
3608            sb.append("    TOTAL TIME: ");
3609            formatTimeMs(sb, totalTime);
3610            sb.append("("); sb.append(formatRatioLocked(totalTime, whichBatteryRealtime));
3611            sb.append(")");
3612            pw.println(sb.toString());
3613            pw.println();
3614        }
3615
3616        final Comparator<TimerEntry> timerComparator = new Comparator<TimerEntry>() {
3617            @Override
3618            public int compare(TimerEntry lhs, TimerEntry rhs) {
3619                long lhsTime = lhs.mTime;
3620                long rhsTime = rhs.mTime;
3621                if (lhsTime < rhsTime) {
3622                    return 1;
3623                }
3624                if (lhsTime > rhsTime) {
3625                    return -1;
3626                }
3627                return 0;
3628            }
3629        };
3630
3631        if (reqUid < 0) {
3632            final Map<String, ? extends BatteryStats.Timer> kernelWakelocks
3633                    = getKernelWakelockStats();
3634            if (kernelWakelocks.size() > 0) {
3635                final ArrayList<TimerEntry> ktimers = new ArrayList<>();
3636                for (Map.Entry<String, ? extends BatteryStats.Timer> ent
3637                        : kernelWakelocks.entrySet()) {
3638                    final BatteryStats.Timer timer = ent.getValue();
3639                    final long totalTimeMillis = computeWakeLock(timer, rawRealtime, which);
3640                    if (totalTimeMillis > 0) {
3641                        ktimers.add(new TimerEntry(ent.getKey(), 0, timer, totalTimeMillis));
3642                    }
3643                }
3644                if (ktimers.size() > 0) {
3645                    Collections.sort(ktimers, timerComparator);
3646                    pw.print(prefix); pw.println("  All kernel wake locks:");
3647                    for (int i=0; i<ktimers.size(); i++) {
3648                        final TimerEntry timer = ktimers.get(i);
3649                        String linePrefix = ": ";
3650                        sb.setLength(0);
3651                        sb.append(prefix);
3652                        sb.append("  Kernel Wake lock ");
3653                        sb.append(timer.mName);
3654                        linePrefix = printWakeLock(sb, timer.mTimer, rawRealtime, null,
3655                                which, linePrefix);
3656                        if (!linePrefix.equals(": ")) {
3657                            sb.append(" realtime");
3658                            // Only print out wake locks that were held
3659                            pw.println(sb.toString());
3660                        }
3661                    }
3662                    pw.println();
3663                }
3664            }
3665
3666            if (timers.size() > 0) {
3667                Collections.sort(timers, timerComparator);
3668                pw.print(prefix); pw.println("  All partial wake locks:");
3669                for (int i=0; i<timers.size(); i++) {
3670                    TimerEntry timer = timers.get(i);
3671                    sb.setLength(0);
3672                    sb.append("  Wake lock ");
3673                    UserHandle.formatUid(sb, timer.mId);
3674                    sb.append(" ");
3675                    sb.append(timer.mName);
3676                    printWakeLock(sb, timer.mTimer, rawRealtime, null, which, ": ");
3677                    sb.append(" realtime");
3678                    pw.println(sb.toString());
3679                }
3680                timers.clear();
3681                pw.println();
3682            }
3683
3684            final Map<String, ? extends Timer> wakeupReasons = getWakeupReasonStats();
3685            if (wakeupReasons.size() > 0) {
3686                pw.print(prefix); pw.println("  All wakeup reasons:");
3687                final ArrayList<TimerEntry> reasons = new ArrayList<>();
3688                for (Map.Entry<String, ? extends Timer> ent : wakeupReasons.entrySet()) {
3689                    final Timer timer = ent.getValue();
3690                    reasons.add(new TimerEntry(ent.getKey(), 0, timer,
3691                            timer.getCountLocked(which)));
3692                }
3693                Collections.sort(reasons, timerComparator);
3694                for (int i=0; i<reasons.size(); i++) {
3695                    TimerEntry timer = reasons.get(i);
3696                    String linePrefix = ": ";
3697                    sb.setLength(0);
3698                    sb.append(prefix);
3699                    sb.append("  Wakeup reason ");
3700                    sb.append(timer.mName);
3701                    printWakeLock(sb, timer.mTimer, rawRealtime, null, which, ": ");
3702                    sb.append(" realtime");
3703                    pw.println(sb.toString());
3704                }
3705                pw.println();
3706            }
3707        }
3708
3709        for (int iu=0; iu<NU; iu++) {
3710            final int uid = uidStats.keyAt(iu);
3711            if (reqUid >= 0 && uid != reqUid && uid != Process.SYSTEM_UID) {
3712                continue;
3713            }
3714
3715            final Uid u = uidStats.valueAt(iu);
3716
3717            pw.print(prefix);
3718            pw.print("  ");
3719            UserHandle.formatUid(pw, uid);
3720            pw.println(":");
3721            boolean uidActivity = false;
3722
3723            final long mobileRxBytes = u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
3724            final long mobileTxBytes = u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
3725            final long wifiRxBytes = u.getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
3726            final long wifiTxBytes = u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
3727            final long mobileRxPackets = u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
3728            final long mobileTxPackets = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
3729            final long uidMobileActiveTime = u.getMobileRadioActiveTime(which);
3730            final int uidMobileActiveCount = u.getMobileRadioActiveCount(which);
3731            final long wifiRxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
3732            final long wifiTxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
3733            final long fullWifiLockOnTime = u.getFullWifiLockTime(rawRealtime, which);
3734            final long wifiScanTime = u.getWifiScanTime(rawRealtime, which);
3735            final int wifiScanCount = u.getWifiScanCount(which);
3736            final long uidWifiRunningTime = u.getWifiRunningTime(rawRealtime, which);
3737
3738            if (mobileRxBytes > 0 || mobileTxBytes > 0
3739                    || mobileRxPackets > 0 || mobileTxPackets > 0) {
3740                pw.print(prefix); pw.print("    Mobile network: ");
3741                        pw.print(formatBytesLocked(mobileRxBytes)); pw.print(" received, ");
3742                        pw.print(formatBytesLocked(mobileTxBytes));
3743                        pw.print(" sent (packets "); pw.print(mobileRxPackets);
3744                        pw.print(" received, "); pw.print(mobileTxPackets); pw.println(" sent)");
3745            }
3746            if (uidMobileActiveTime > 0 || uidMobileActiveCount > 0) {
3747                sb.setLength(0);
3748                sb.append(prefix); sb.append("    Mobile radio active: ");
3749                formatTimeMs(sb, uidMobileActiveTime / 1000);
3750                sb.append("(");
3751                sb.append(formatRatioLocked(uidMobileActiveTime, mobileActiveTime));
3752                sb.append(") "); sb.append(uidMobileActiveCount); sb.append("x");
3753                long packets = mobileRxPackets + mobileTxPackets;
3754                if (packets == 0) {
3755                    packets = 1;
3756                }
3757                sb.append(" @ ");
3758                sb.append(BatteryStatsHelper.makemAh(uidMobileActiveTime / 1000 / (double)packets));
3759                sb.append(" mspp");
3760                pw.println(sb.toString());
3761            }
3762
3763            if (wifiRxBytes > 0 || wifiTxBytes > 0 || wifiRxPackets > 0 || wifiTxPackets > 0) {
3764                pw.print(prefix); pw.print("    Wi-Fi network: ");
3765                        pw.print(formatBytesLocked(wifiRxBytes)); pw.print(" received, ");
3766                        pw.print(formatBytesLocked(wifiTxBytes));
3767                        pw.print(" sent (packets "); pw.print(wifiRxPackets);
3768                        pw.print(" received, "); pw.print(wifiTxPackets); pw.println(" sent)");
3769            }
3770
3771            if (fullWifiLockOnTime != 0 || wifiScanTime != 0 || wifiScanCount != 0
3772                    || uidWifiRunningTime != 0) {
3773                sb.setLength(0);
3774                sb.append(prefix); sb.append("    Wifi Running: ");
3775                        formatTimeMs(sb, uidWifiRunningTime / 1000);
3776                        sb.append("("); sb.append(formatRatioLocked(uidWifiRunningTime,
3777                                whichBatteryRealtime)); sb.append(")\n");
3778                sb.append(prefix); sb.append("    Full Wifi Lock: ");
3779                        formatTimeMs(sb, fullWifiLockOnTime / 1000);
3780                        sb.append("("); sb.append(formatRatioLocked(fullWifiLockOnTime,
3781                                whichBatteryRealtime)); sb.append(")\n");
3782                sb.append(prefix); sb.append("    Wifi Scan: ");
3783                        formatTimeMs(sb, wifiScanTime / 1000);
3784                        sb.append("("); sb.append(formatRatioLocked(wifiScanTime,
3785                                whichBatteryRealtime)); sb.append(") ");
3786                                sb.append(wifiScanCount);
3787                                sb.append("x");
3788                pw.println(sb.toString());
3789            }
3790
3791            final long uidWifiIdleTimeMs = u.getWifiControllerActivity(CONTROLLER_IDLE_TIME, which);
3792            final long uidWifiRxTimeMs = u.getWifiControllerActivity(CONTROLLER_RX_TIME, which);
3793            final long uidWifiTxTimeMs = u.getWifiControllerActivity(CONTROLLER_TX_TIME, which);
3794            final long uidWifiTotalTimeMs = uidWifiIdleTimeMs + uidWifiRxTimeMs + uidWifiTxTimeMs;
3795            if (uidWifiTotalTimeMs > 0) {
3796                sb.setLength(0);
3797                sb.append(prefix).append("    WiFi Idle time: ");
3798                formatTimeMs(sb, uidWifiIdleTimeMs);
3799                sb.append("(").append(formatRatioLocked(uidWifiIdleTimeMs, uidWifiTotalTimeMs))
3800                        .append(")\n");
3801
3802                sb.append(prefix).append("    WiFi Rx time:   "); formatTimeMs(sb, uidWifiRxTimeMs);
3803                sb.append("(").append(formatRatioLocked(uidWifiRxTimeMs, uidWifiTotalTimeMs))
3804                        .append(")\n");
3805
3806                sb.append(prefix).append("    WiFi Tx time:   "); formatTimeMs(sb, uidWifiTxTimeMs);
3807                sb.append("(").append(formatRatioLocked(uidWifiTxTimeMs, uidWifiTotalTimeMs))
3808                        .append(")");
3809                pw.println(sb.toString());
3810            }
3811
3812            if (u.hasUserActivity()) {
3813                boolean hasData = false;
3814                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
3815                    final int val = u.getUserActivityCount(i, which);
3816                    if (val != 0) {
3817                        if (!hasData) {
3818                            sb.setLength(0);
3819                            sb.append("    User activity: ");
3820                            hasData = true;
3821                        } else {
3822                            sb.append(", ");
3823                        }
3824                        sb.append(val);
3825                        sb.append(" ");
3826                        sb.append(Uid.USER_ACTIVITY_TYPES[i]);
3827                    }
3828                }
3829                if (hasData) {
3830                    pw.println(sb.toString());
3831                }
3832            }
3833
3834            final ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> wakelocks
3835                    = u.getWakelockStats();
3836            long totalFullWakelock = 0, totalPartialWakelock = 0, totalWindowWakelock = 0;
3837            int countWakelock = 0;
3838            for (int iw=wakelocks.size()-1; iw>=0; iw--) {
3839                final Uid.Wakelock wl = wakelocks.valueAt(iw);
3840                String linePrefix = ": ";
3841                sb.setLength(0);
3842                sb.append(prefix);
3843                sb.append("    Wake lock ");
3844                sb.append(wakelocks.keyAt(iw));
3845                linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_FULL), rawRealtime,
3846                        "full", which, linePrefix);
3847                linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), rawRealtime,
3848                        "partial", which, linePrefix);
3849                linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), rawRealtime,
3850                        "window", which, linePrefix);
3851                if (true || !linePrefix.equals(": ")) {
3852                    sb.append(" realtime");
3853                    // Only print out wake locks that were held
3854                    pw.println(sb.toString());
3855                    uidActivity = true;
3856                    countWakelock++;
3857                }
3858                totalFullWakelock += computeWakeLock(wl.getWakeTime(WAKE_TYPE_FULL),
3859                        rawRealtime, which);
3860                totalPartialWakelock += computeWakeLock(wl.getWakeTime(WAKE_TYPE_PARTIAL),
3861                        rawRealtime, which);
3862                totalWindowWakelock += computeWakeLock(wl.getWakeTime(WAKE_TYPE_WINDOW),
3863                        rawRealtime, which);
3864            }
3865            if (countWakelock > 1) {
3866                if (totalFullWakelock != 0 || totalPartialWakelock != 0
3867                        || totalWindowWakelock != 0) {
3868                    sb.setLength(0);
3869                    sb.append(prefix);
3870                    sb.append("    TOTAL wake: ");
3871                    boolean needComma = false;
3872                    if (totalFullWakelock != 0) {
3873                        needComma = true;
3874                        formatTimeMs(sb, totalFullWakelock);
3875                        sb.append("full");
3876                    }
3877                    if (totalPartialWakelock != 0) {
3878                        if (needComma) {
3879                            sb.append(", ");
3880                        }
3881                        needComma = true;
3882                        formatTimeMs(sb, totalPartialWakelock);
3883                        sb.append("partial");
3884                    }
3885                    if (totalWindowWakelock != 0) {
3886                        if (needComma) {
3887                            sb.append(", ");
3888                        }
3889                        needComma = true;
3890                        formatTimeMs(sb, totalWindowWakelock);
3891                        sb.append("window");
3892                    }
3893                    sb.append(" realtime");
3894                    pw.println(sb.toString());
3895                }
3896            }
3897
3898            final ArrayMap<String, ? extends Timer> syncs = u.getSyncStats();
3899            for (int isy=syncs.size()-1; isy>=0; isy--) {
3900                final Timer timer = syncs.valueAt(isy);
3901                // Convert from microseconds to milliseconds with rounding
3902                final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
3903                final int count = timer.getCountLocked(which);
3904                sb.setLength(0);
3905                sb.append(prefix);
3906                sb.append("    Sync ");
3907                sb.append(syncs.keyAt(isy));
3908                sb.append(": ");
3909                if (totalTime != 0) {
3910                    formatTimeMs(sb, totalTime);
3911                    sb.append("realtime (");
3912                    sb.append(count);
3913                    sb.append(" times)");
3914                } else {
3915                    sb.append("(not used)");
3916                }
3917                pw.println(sb.toString());
3918                uidActivity = true;
3919            }
3920
3921            final ArrayMap<String, ? extends Timer> jobs = u.getJobStats();
3922            for (int ij=jobs.size()-1; ij>=0; ij--) {
3923                final Timer timer = jobs.valueAt(ij);
3924                // Convert from microseconds to milliseconds with rounding
3925                final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
3926                final int count = timer.getCountLocked(which);
3927                sb.setLength(0);
3928                sb.append(prefix);
3929                sb.append("    Job ");
3930                sb.append(jobs.keyAt(ij));
3931                sb.append(": ");
3932                if (totalTime != 0) {
3933                    formatTimeMs(sb, totalTime);
3934                    sb.append("realtime (");
3935                    sb.append(count);
3936                    sb.append(" times)");
3937                } else {
3938                    sb.append("(not used)");
3939                }
3940                pw.println(sb.toString());
3941                uidActivity = true;
3942            }
3943
3944            uidActivity |= printTimer(pw, sb, u.getFlashlightTurnedOnTimer(), rawRealtime, which,
3945                    prefix, "Flashlight");
3946            uidActivity |= printTimer(pw, sb, u.getCameraTurnedOnTimer(), rawRealtime, which,
3947                    prefix, "Camera");
3948            uidActivity |= printTimer(pw, sb, u.getVideoTurnedOnTimer(), rawRealtime, which,
3949                    prefix, "Video");
3950            uidActivity |= printTimer(pw, sb, u.getAudioTurnedOnTimer(), rawRealtime, which,
3951                    prefix, "Audio");
3952
3953            final SparseArray<? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
3954            final int NSE = sensors.size();
3955            for (int ise=0; ise<NSE; ise++) {
3956                final Uid.Sensor se = sensors.valueAt(ise);
3957                final int sensorNumber = sensors.keyAt(ise);
3958                sb.setLength(0);
3959                sb.append(prefix);
3960                sb.append("    Sensor ");
3961                int handle = se.getHandle();
3962                if (handle == Uid.Sensor.GPS) {
3963                    sb.append("GPS");
3964                } else {
3965                    sb.append(handle);
3966                }
3967                sb.append(": ");
3968
3969                final Timer timer = se.getSensorTime();
3970                if (timer != null) {
3971                    // Convert from microseconds to milliseconds with rounding
3972                    final long totalTime = (timer.getTotalTimeLocked(
3973                            rawRealtime, which) + 500) / 1000;
3974                    final int count = timer.getCountLocked(which);
3975                    //timer.logState();
3976                    if (totalTime != 0) {
3977                        formatTimeMs(sb, totalTime);
3978                        sb.append("realtime (");
3979                        sb.append(count);
3980                        sb.append(" times)");
3981                    } else {
3982                        sb.append("(not used)");
3983                    }
3984                } else {
3985                    sb.append("(not used)");
3986                }
3987
3988                pw.println(sb.toString());
3989                uidActivity = true;
3990            }
3991
3992            uidActivity |= printTimer(pw, sb, u.getVibratorOnTimer(), rawRealtime, which, prefix,
3993                    "Vibrator");
3994            uidActivity |= printTimer(pw, sb, u.getForegroundActivityTimer(), rawRealtime, which,
3995                    prefix, "Foreground activities");
3996
3997            long totalStateTime = 0;
3998            for (int ips=0; ips<Uid.NUM_PROCESS_STATE; ips++) {
3999                long time = u.getProcessStateTime(ips, rawRealtime, which);
4000                if (time > 0) {
4001                    totalStateTime += time;
4002                    sb.setLength(0);
4003                    sb.append(prefix);
4004                    sb.append("    ");
4005                    sb.append(Uid.PROCESS_STATE_NAMES[ips]);
4006                    sb.append(" for: ");
4007                    formatTimeMs(sb, (totalStateTime + 500) / 1000);
4008                    pw.println(sb.toString());
4009                    uidActivity = true;
4010                }
4011            }
4012
4013            final long userCpuTimeUs = u.getUserCpuTimeUs(which);
4014            final long systemCpuTimeUs = u.getSystemCpuTimeUs(which);
4015            if (userCpuTimeUs > 0 || systemCpuTimeUs > 0) {
4016                sb.setLength(0);
4017                sb.append(prefix);
4018                sb.append("    Total cpu time: u=");
4019                formatTimeMs(sb, userCpuTimeUs / 1000);
4020                sb.append("s=");
4021                formatTimeMs(sb, systemCpuTimeUs / 1000);
4022                pw.println(sb.toString());
4023            }
4024
4025            final ArrayMap<String, ? extends BatteryStats.Uid.Proc> processStats
4026                    = u.getProcessStats();
4027            for (int ipr=processStats.size()-1; ipr>=0; ipr--) {
4028                final Uid.Proc ps = processStats.valueAt(ipr);
4029                long userTime;
4030                long systemTime;
4031                long foregroundTime;
4032                int starts;
4033                int numExcessive;
4034
4035                userTime = ps.getUserTime(which);
4036                systemTime = ps.getSystemTime(which);
4037                foregroundTime = ps.getForegroundTime(which);
4038                starts = ps.getStarts(which);
4039                final int numCrashes = ps.getNumCrashes(which);
4040                final int numAnrs = ps.getNumAnrs(which);
4041                numExcessive = which == STATS_SINCE_CHARGED
4042                        ? ps.countExcessivePowers() : 0;
4043
4044                if (userTime != 0 || systemTime != 0 || foregroundTime != 0 || starts != 0
4045                        || numExcessive != 0 || numCrashes != 0 || numAnrs != 0) {
4046                    sb.setLength(0);
4047                    sb.append(prefix); sb.append("    Proc ");
4048                            sb.append(processStats.keyAt(ipr)); sb.append(":\n");
4049                    sb.append(prefix); sb.append("      CPU: ");
4050                            formatTimeMs(sb, userTime); sb.append("usr + ");
4051                            formatTimeMs(sb, systemTime); sb.append("krn ; ");
4052                            formatTimeMs(sb, foregroundTime); sb.append("fg");
4053                    if (starts != 0 || numCrashes != 0 || numAnrs != 0) {
4054                        sb.append("\n"); sb.append(prefix); sb.append("      ");
4055                        boolean hasOne = false;
4056                        if (starts != 0) {
4057                            hasOne = true;
4058                            sb.append(starts); sb.append(" starts");
4059                        }
4060                        if (numCrashes != 0) {
4061                            if (hasOne) {
4062                                sb.append(", ");
4063                            }
4064                            hasOne = true;
4065                            sb.append(numCrashes); sb.append(" crashes");
4066                        }
4067                        if (numAnrs != 0) {
4068                            if (hasOne) {
4069                                sb.append(", ");
4070                            }
4071                            sb.append(numAnrs); sb.append(" anrs");
4072                        }
4073                    }
4074                    pw.println(sb.toString());
4075                    for (int e=0; e<numExcessive; e++) {
4076                        Uid.Proc.ExcessivePower ew = ps.getExcessivePower(e);
4077                        if (ew != null) {
4078                            pw.print(prefix); pw.print("      * Killed for ");
4079                                    if (ew.type == Uid.Proc.ExcessivePower.TYPE_WAKE) {
4080                                        pw.print("wake lock");
4081                                    } else if (ew.type == Uid.Proc.ExcessivePower.TYPE_CPU) {
4082                                        pw.print("cpu");
4083                                    } else {
4084                                        pw.print("unknown");
4085                                    }
4086                                    pw.print(" use: ");
4087                                    TimeUtils.formatDuration(ew.usedTime, pw);
4088                                    pw.print(" over ");
4089                                    TimeUtils.formatDuration(ew.overTime, pw);
4090                                    if (ew.overTime != 0) {
4091                                        pw.print(" (");
4092                                        pw.print((ew.usedTime*100)/ew.overTime);
4093                                        pw.println("%)");
4094                                    }
4095                        }
4096                    }
4097                    uidActivity = true;
4098                }
4099            }
4100
4101            final ArrayMap<String, ? extends BatteryStats.Uid.Pkg> packageStats
4102                    = u.getPackageStats();
4103            for (int ipkg=packageStats.size()-1; ipkg>=0; ipkg--) {
4104                pw.print(prefix); pw.print("    Apk "); pw.print(packageStats.keyAt(ipkg));
4105                pw.println(":");
4106                boolean apkActivity = false;
4107                final Uid.Pkg ps = packageStats.valueAt(ipkg);
4108                final ArrayMap<String, ? extends Counter> alarms = ps.getWakeupAlarmStats();
4109                for (int iwa=alarms.size()-1; iwa>=0; iwa--) {
4110                    pw.print(prefix); pw.print("      Wakeup alarm ");
4111                            pw.print(alarms.keyAt(iwa)); pw.print(": ");
4112                            pw.print(alarms.valueAt(iwa).getCountLocked(which));
4113                            pw.println(" times");
4114                    apkActivity = true;
4115                }
4116                final ArrayMap<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
4117                for (int isvc=serviceStats.size()-1; isvc>=0; isvc--) {
4118                    final BatteryStats.Uid.Pkg.Serv ss = serviceStats.valueAt(isvc);
4119                    final long startTime = ss.getStartTime(batteryUptime, which);
4120                    final int starts = ss.getStarts(which);
4121                    final int launches = ss.getLaunches(which);
4122                    if (startTime != 0 || starts != 0 || launches != 0) {
4123                        sb.setLength(0);
4124                        sb.append(prefix); sb.append("      Service ");
4125                                sb.append(serviceStats.keyAt(isvc)); sb.append(":\n");
4126                        sb.append(prefix); sb.append("        Created for: ");
4127                                formatTimeMs(sb, startTime / 1000);
4128                                sb.append("uptime\n");
4129                        sb.append(prefix); sb.append("        Starts: ");
4130                                sb.append(starts);
4131                                sb.append(", launches: "); sb.append(launches);
4132                        pw.println(sb.toString());
4133                        apkActivity = true;
4134                    }
4135                }
4136                if (!apkActivity) {
4137                    pw.print(prefix); pw.println("      (nothing executed)");
4138                }
4139                uidActivity = true;
4140            }
4141            if (!uidActivity) {
4142                pw.print(prefix); pw.println("    (nothing executed)");
4143            }
4144        }
4145    }
4146
4147    static void printBitDescriptions(PrintWriter pw, int oldval, int newval, HistoryTag wakelockTag,
4148            BitDescription[] descriptions, boolean longNames) {
4149        int diff = oldval ^ newval;
4150        if (diff == 0) return;
4151        boolean didWake = false;
4152        for (int i=0; i<descriptions.length; i++) {
4153            BitDescription bd = descriptions[i];
4154            if ((diff&bd.mask) != 0) {
4155                pw.print(longNames ? " " : ",");
4156                if (bd.shift < 0) {
4157                    pw.print((newval&bd.mask) != 0 ? "+" : "-");
4158                    pw.print(longNames ? bd.name : bd.shortName);
4159                    if (bd.mask == HistoryItem.STATE_WAKE_LOCK_FLAG && wakelockTag != null) {
4160                        didWake = true;
4161                        pw.print("=");
4162                        if (longNames) {
4163                            UserHandle.formatUid(pw, wakelockTag.uid);
4164                            pw.print(":\"");
4165                            pw.print(wakelockTag.string);
4166                            pw.print("\"");
4167                        } else {
4168                            pw.print(wakelockTag.poolIdx);
4169                        }
4170                    }
4171                } else {
4172                    pw.print(longNames ? bd.name : bd.shortName);
4173                    pw.print("=");
4174                    int val = (newval&bd.mask)>>bd.shift;
4175                    if (bd.values != null && val >= 0 && val < bd.values.length) {
4176                        pw.print(longNames? bd.values[val] : bd.shortValues[val]);
4177                    } else {
4178                        pw.print(val);
4179                    }
4180                }
4181            }
4182        }
4183        if (!didWake && wakelockTag != null) {
4184            pw.print(longNames ? " wake_lock=" : ",w=");
4185            if (longNames) {
4186                UserHandle.formatUid(pw, wakelockTag.uid);
4187                pw.print(":\"");
4188                pw.print(wakelockTag.string);
4189                pw.print("\"");
4190            } else {
4191                pw.print(wakelockTag.poolIdx);
4192            }
4193        }
4194    }
4195
4196    public void prepareForDumpLocked() {
4197    }
4198
4199    public static class HistoryPrinter {
4200        int oldState = 0;
4201        int oldState2 = 0;
4202        int oldLevel = -1;
4203        int oldStatus = -1;
4204        int oldHealth = -1;
4205        int oldPlug = -1;
4206        int oldTemp = -1;
4207        int oldVolt = -1;
4208        long lastTime = -1;
4209
4210        void reset() {
4211            oldState = oldState2 = 0;
4212            oldLevel = -1;
4213            oldStatus = -1;
4214            oldHealth = -1;
4215            oldPlug = -1;
4216            oldTemp = -1;
4217            oldVolt = -1;
4218        }
4219
4220        public void printNextItem(PrintWriter pw, HistoryItem rec, long baseTime, boolean checkin,
4221                boolean verbose) {
4222            if (!checkin) {
4223                pw.print("  ");
4224                TimeUtils.formatDuration(rec.time - baseTime, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
4225                pw.print(" (");
4226                pw.print(rec.numReadInts);
4227                pw.print(") ");
4228            } else {
4229                pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
4230                pw.print(HISTORY_DATA); pw.print(',');
4231                if (lastTime < 0) {
4232                    pw.print(rec.time - baseTime);
4233                } else {
4234                    pw.print(rec.time - lastTime);
4235                }
4236                lastTime = rec.time;
4237            }
4238            if (rec.cmd == HistoryItem.CMD_START) {
4239                if (checkin) {
4240                    pw.print(":");
4241                }
4242                pw.println("START");
4243                reset();
4244            } else if (rec.cmd == HistoryItem.CMD_CURRENT_TIME
4245                    || rec.cmd == HistoryItem.CMD_RESET) {
4246                if (checkin) {
4247                    pw.print(":");
4248                }
4249                if (rec.cmd == HistoryItem.CMD_RESET) {
4250                    pw.print("RESET:");
4251                    reset();
4252                }
4253                pw.print("TIME:");
4254                if (checkin) {
4255                    pw.println(rec.currentTime);
4256                } else {
4257                    pw.print(" ");
4258                    pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss",
4259                            rec.currentTime).toString());
4260                }
4261            } else if (rec.cmd == HistoryItem.CMD_SHUTDOWN) {
4262                if (checkin) {
4263                    pw.print(":");
4264                }
4265                pw.println("SHUTDOWN");
4266            } else if (rec.cmd == HistoryItem.CMD_OVERFLOW) {
4267                if (checkin) {
4268                    pw.print(":");
4269                }
4270                pw.println("*OVERFLOW*");
4271            } else {
4272                if (!checkin) {
4273                    if (rec.batteryLevel < 10) pw.print("00");
4274                    else if (rec.batteryLevel < 100) pw.print("0");
4275                    pw.print(rec.batteryLevel);
4276                    if (verbose) {
4277                        pw.print(" ");
4278                        if (rec.states < 0) ;
4279                        else if (rec.states < 0x10) pw.print("0000000");
4280                        else if (rec.states < 0x100) pw.print("000000");
4281                        else if (rec.states < 0x1000) pw.print("00000");
4282                        else if (rec.states < 0x10000) pw.print("0000");
4283                        else if (rec.states < 0x100000) pw.print("000");
4284                        else if (rec.states < 0x1000000) pw.print("00");
4285                        else if (rec.states < 0x10000000) pw.print("0");
4286                        pw.print(Integer.toHexString(rec.states));
4287                    }
4288                } else {
4289                    if (oldLevel != rec.batteryLevel) {
4290                        oldLevel = rec.batteryLevel;
4291                        pw.print(",Bl="); pw.print(rec.batteryLevel);
4292                    }
4293                }
4294                if (oldStatus != rec.batteryStatus) {
4295                    oldStatus = rec.batteryStatus;
4296                    pw.print(checkin ? ",Bs=" : " status=");
4297                    switch (oldStatus) {
4298                        case BatteryManager.BATTERY_STATUS_UNKNOWN:
4299                            pw.print(checkin ? "?" : "unknown");
4300                            break;
4301                        case BatteryManager.BATTERY_STATUS_CHARGING:
4302                            pw.print(checkin ? "c" : "charging");
4303                            break;
4304                        case BatteryManager.BATTERY_STATUS_DISCHARGING:
4305                            pw.print(checkin ? "d" : "discharging");
4306                            break;
4307                        case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
4308                            pw.print(checkin ? "n" : "not-charging");
4309                            break;
4310                        case BatteryManager.BATTERY_STATUS_FULL:
4311                            pw.print(checkin ? "f" : "full");
4312                            break;
4313                        default:
4314                            pw.print(oldStatus);
4315                            break;
4316                    }
4317                }
4318                if (oldHealth != rec.batteryHealth) {
4319                    oldHealth = rec.batteryHealth;
4320                    pw.print(checkin ? ",Bh=" : " health=");
4321                    switch (oldHealth) {
4322                        case BatteryManager.BATTERY_HEALTH_UNKNOWN:
4323                            pw.print(checkin ? "?" : "unknown");
4324                            break;
4325                        case BatteryManager.BATTERY_HEALTH_GOOD:
4326                            pw.print(checkin ? "g" : "good");
4327                            break;
4328                        case BatteryManager.BATTERY_HEALTH_OVERHEAT:
4329                            pw.print(checkin ? "h" : "overheat");
4330                            break;
4331                        case BatteryManager.BATTERY_HEALTH_DEAD:
4332                            pw.print(checkin ? "d" : "dead");
4333                            break;
4334                        case BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE:
4335                            pw.print(checkin ? "v" : "over-voltage");
4336                            break;
4337                        case BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE:
4338                            pw.print(checkin ? "f" : "failure");
4339                            break;
4340                        case BatteryManager.BATTERY_HEALTH_COLD:
4341                            pw.print(checkin ? "c" : "cold");
4342                            break;
4343                        default:
4344                            pw.print(oldHealth);
4345                            break;
4346                    }
4347                }
4348                if (oldPlug != rec.batteryPlugType) {
4349                    oldPlug = rec.batteryPlugType;
4350                    pw.print(checkin ? ",Bp=" : " plug=");
4351                    switch (oldPlug) {
4352                        case 0:
4353                            pw.print(checkin ? "n" : "none");
4354                            break;
4355                        case BatteryManager.BATTERY_PLUGGED_AC:
4356                            pw.print(checkin ? "a" : "ac");
4357                            break;
4358                        case BatteryManager.BATTERY_PLUGGED_USB:
4359                            pw.print(checkin ? "u" : "usb");
4360                            break;
4361                        case BatteryManager.BATTERY_PLUGGED_WIRELESS:
4362                            pw.print(checkin ? "w" : "wireless");
4363                            break;
4364                        default:
4365                            pw.print(oldPlug);
4366                            break;
4367                    }
4368                }
4369                if (oldTemp != rec.batteryTemperature) {
4370                    oldTemp = rec.batteryTemperature;
4371                    pw.print(checkin ? ",Bt=" : " temp=");
4372                    pw.print(oldTemp);
4373                }
4374                if (oldVolt != rec.batteryVoltage) {
4375                    oldVolt = rec.batteryVoltage;
4376                    pw.print(checkin ? ",Bv=" : " volt=");
4377                    pw.print(oldVolt);
4378                }
4379                printBitDescriptions(pw, oldState, rec.states, rec.wakelockTag,
4380                        HISTORY_STATE_DESCRIPTIONS, !checkin);
4381                printBitDescriptions(pw, oldState2, rec.states2, null,
4382                        HISTORY_STATE2_DESCRIPTIONS, !checkin);
4383                if (rec.wakeReasonTag != null) {
4384                    if (checkin) {
4385                        pw.print(",wr=");
4386                        pw.print(rec.wakeReasonTag.poolIdx);
4387                    } else {
4388                        pw.print(" wake_reason=");
4389                        pw.print(rec.wakeReasonTag.uid);
4390                        pw.print(":\"");
4391                        pw.print(rec.wakeReasonTag.string);
4392                        pw.print("\"");
4393                    }
4394                }
4395                if (rec.eventCode != HistoryItem.EVENT_NONE) {
4396                    pw.print(checkin ? "," : " ");
4397                    if ((rec.eventCode&HistoryItem.EVENT_FLAG_START) != 0) {
4398                        pw.print("+");
4399                    } else if ((rec.eventCode&HistoryItem.EVENT_FLAG_FINISH) != 0) {
4400                        pw.print("-");
4401                    }
4402                    String[] eventNames = checkin ? HISTORY_EVENT_CHECKIN_NAMES
4403                            : HISTORY_EVENT_NAMES;
4404                    int idx = rec.eventCode & ~(HistoryItem.EVENT_FLAG_START
4405                            | HistoryItem.EVENT_FLAG_FINISH);
4406                    if (idx >= 0 && idx < eventNames.length) {
4407                        pw.print(eventNames[idx]);
4408                    } else {
4409                        pw.print(checkin ? "Ev" : "event");
4410                        pw.print(idx);
4411                    }
4412                    pw.print("=");
4413                    if (checkin) {
4414                        pw.print(rec.eventTag.poolIdx);
4415                    } else {
4416                        UserHandle.formatUid(pw, rec.eventTag.uid);
4417                        pw.print(":\"");
4418                        pw.print(rec.eventTag.string);
4419                        pw.print("\"");
4420                    }
4421                }
4422                pw.println();
4423                if (rec.stepDetails != null) {
4424                    if (!checkin) {
4425                        pw.print("                 Details: cpu=");
4426                        pw.print(rec.stepDetails.userTime);
4427                        pw.print("u+");
4428                        pw.print(rec.stepDetails.systemTime);
4429                        pw.print("s");
4430                        if (rec.stepDetails.appCpuUid1 >= 0) {
4431                            pw.print(" (");
4432                            printStepCpuUidDetails(pw, rec.stepDetails.appCpuUid1,
4433                                    rec.stepDetails.appCpuUTime1, rec.stepDetails.appCpuSTime1);
4434                            if (rec.stepDetails.appCpuUid2 >= 0) {
4435                                pw.print(", ");
4436                                printStepCpuUidDetails(pw, rec.stepDetails.appCpuUid2,
4437                                        rec.stepDetails.appCpuUTime2, rec.stepDetails.appCpuSTime2);
4438                            }
4439                            if (rec.stepDetails.appCpuUid3 >= 0) {
4440                                pw.print(", ");
4441                                printStepCpuUidDetails(pw, rec.stepDetails.appCpuUid3,
4442                                        rec.stepDetails.appCpuUTime3, rec.stepDetails.appCpuSTime3);
4443                            }
4444                            pw.print(')');
4445                        }
4446                        pw.println();
4447                        pw.print("                          /proc/stat=");
4448                        pw.print(rec.stepDetails.statUserTime);
4449                        pw.print(" usr, ");
4450                        pw.print(rec.stepDetails.statSystemTime);
4451                        pw.print(" sys, ");
4452                        pw.print(rec.stepDetails.statIOWaitTime);
4453                        pw.print(" io, ");
4454                        pw.print(rec.stepDetails.statIrqTime);
4455                        pw.print(" irq, ");
4456                        pw.print(rec.stepDetails.statSoftIrqTime);
4457                        pw.print(" sirq, ");
4458                        pw.print(rec.stepDetails.statIdlTime);
4459                        pw.print(" idle");
4460                        int totalRun = rec.stepDetails.statUserTime + rec.stepDetails.statSystemTime
4461                                + rec.stepDetails.statIOWaitTime + rec.stepDetails.statIrqTime
4462                                + rec.stepDetails.statSoftIrqTime;
4463                        int total = totalRun + rec.stepDetails.statIdlTime;
4464                        if (total > 0) {
4465                            pw.print(" (");
4466                            float perc = ((float)totalRun) / ((float)total) * 100;
4467                            pw.print(String.format("%.1f%%", perc));
4468                            pw.print(" of ");
4469                            StringBuilder sb = new StringBuilder(64);
4470                            formatTimeMsNoSpace(sb, total*10);
4471                            pw.print(sb);
4472                            pw.print(")");
4473                        }
4474                        pw.println();
4475                    } else {
4476                        pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
4477                        pw.print(HISTORY_DATA); pw.print(",0,Dcpu=");
4478                        pw.print(rec.stepDetails.userTime);
4479                        pw.print(":");
4480                        pw.print(rec.stepDetails.systemTime);
4481                        if (rec.stepDetails.appCpuUid1 >= 0) {
4482                            printStepCpuUidCheckinDetails(pw, rec.stepDetails.appCpuUid1,
4483                                    rec.stepDetails.appCpuUTime1, rec.stepDetails.appCpuSTime1);
4484                            if (rec.stepDetails.appCpuUid2 >= 0) {
4485                                printStepCpuUidCheckinDetails(pw, rec.stepDetails.appCpuUid2,
4486                                        rec.stepDetails.appCpuUTime2, rec.stepDetails.appCpuSTime2);
4487                            }
4488                            if (rec.stepDetails.appCpuUid3 >= 0) {
4489                                printStepCpuUidCheckinDetails(pw, rec.stepDetails.appCpuUid3,
4490                                        rec.stepDetails.appCpuUTime3, rec.stepDetails.appCpuSTime3);
4491                            }
4492                        }
4493                        pw.println();
4494                        pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
4495                        pw.print(HISTORY_DATA); pw.print(",0,Dpst=");
4496                        pw.print(rec.stepDetails.statUserTime);
4497                        pw.print(',');
4498                        pw.print(rec.stepDetails.statSystemTime);
4499                        pw.print(',');
4500                        pw.print(rec.stepDetails.statIOWaitTime);
4501                        pw.print(',');
4502                        pw.print(rec.stepDetails.statIrqTime);
4503                        pw.print(',');
4504                        pw.print(rec.stepDetails.statSoftIrqTime);
4505                        pw.print(',');
4506                        pw.print(rec.stepDetails.statIdlTime);
4507                        pw.println();
4508                    }
4509                }
4510                oldState = rec.states;
4511                oldState2 = rec.states2;
4512            }
4513        }
4514
4515        private void printStepCpuUidDetails(PrintWriter pw, int uid, int utime, int stime) {
4516            UserHandle.formatUid(pw, uid);
4517            pw.print("=");
4518            pw.print(utime);
4519            pw.print("u+");
4520            pw.print(stime);
4521            pw.print("s");
4522        }
4523
4524        private void printStepCpuUidCheckinDetails(PrintWriter pw, int uid, int utime, int stime) {
4525            pw.print('/');
4526            pw.print(uid);
4527            pw.print(":");
4528            pw.print(utime);
4529            pw.print(":");
4530            pw.print(stime);
4531        }
4532    }
4533
4534    private void printSizeValue(PrintWriter pw, long size) {
4535        float result = size;
4536        String suffix = "";
4537        if (result >= 10*1024) {
4538            suffix = "KB";
4539            result = result / 1024;
4540        }
4541        if (result >= 10*1024) {
4542            suffix = "MB";
4543            result = result / 1024;
4544        }
4545        if (result >= 10*1024) {
4546            suffix = "GB";
4547            result = result / 1024;
4548        }
4549        if (result >= 10*1024) {
4550            suffix = "TB";
4551            result = result / 1024;
4552        }
4553        if (result >= 10*1024) {
4554            suffix = "PB";
4555            result = result / 1024;
4556        }
4557        pw.print((int)result);
4558        pw.print(suffix);
4559    }
4560
4561    private static boolean dumpTimeEstimate(PrintWriter pw, String label1, String label2,
4562            String label3, long estimatedTime) {
4563        if (estimatedTime < 0) {
4564            return false;
4565        }
4566        pw.print(label1);
4567        pw.print(label2);
4568        pw.print(label3);
4569        StringBuilder sb = new StringBuilder(64);
4570        formatTimeMs(sb, estimatedTime);
4571        pw.print(sb);
4572        pw.println();
4573        return true;
4574    }
4575
4576    private static boolean dumpDurationSteps(PrintWriter pw, String prefix, String header,
4577            LevelStepTracker steps, boolean checkin) {
4578        if (steps == null) {
4579            return false;
4580        }
4581        int count = steps.mNumStepDurations;
4582        if (count <= 0) {
4583            return false;
4584        }
4585        if (!checkin) {
4586            pw.println(header);
4587        }
4588        String[] lineArgs = new String[5];
4589        for (int i=0; i<count; i++) {
4590            long duration = steps.getDurationAt(i);
4591            int level = steps.getLevelAt(i);
4592            long initMode = steps.getInitModeAt(i);
4593            long modMode = steps.getModModeAt(i);
4594            if (checkin) {
4595                lineArgs[0] = Long.toString(duration);
4596                lineArgs[1] = Integer.toString(level);
4597                if ((modMode&STEP_LEVEL_MODE_SCREEN_STATE) == 0) {
4598                    switch ((int)(initMode&STEP_LEVEL_MODE_SCREEN_STATE) + 1) {
4599                        case Display.STATE_OFF: lineArgs[2] = "s-"; break;
4600                        case Display.STATE_ON: lineArgs[2] = "s+"; break;
4601                        case Display.STATE_DOZE: lineArgs[2] = "sd"; break;
4602                        case Display.STATE_DOZE_SUSPEND: lineArgs[2] = "sds"; break;
4603                        default: lineArgs[2] = "?"; break;
4604                    }
4605                } else {
4606                    lineArgs[2] = "";
4607                }
4608                if ((modMode&STEP_LEVEL_MODE_POWER_SAVE) == 0) {
4609                    lineArgs[3] = (initMode&STEP_LEVEL_MODE_POWER_SAVE) != 0 ? "p+" : "p-";
4610                } else {
4611                    lineArgs[3] = "";
4612                }
4613                if ((modMode&STEP_LEVEL_MODE_DEVICE_IDLE) == 0) {
4614                    lineArgs[4] = (initMode&STEP_LEVEL_MODE_DEVICE_IDLE) != 0 ? "i+" : "i-";
4615                } else {
4616                    lineArgs[4] = "";
4617                }
4618                dumpLine(pw, 0 /* uid */, "i" /* category */, header, (Object[])lineArgs);
4619            } else {
4620                pw.print(prefix);
4621                pw.print("#"); pw.print(i); pw.print(": ");
4622                TimeUtils.formatDuration(duration, pw);
4623                pw.print(" to "); pw.print(level);
4624                boolean haveModes = false;
4625                if ((modMode&STEP_LEVEL_MODE_SCREEN_STATE) == 0) {
4626                    pw.print(" (");
4627                    switch ((int)(initMode&STEP_LEVEL_MODE_SCREEN_STATE) + 1) {
4628                        case Display.STATE_OFF: pw.print("screen-off"); break;
4629                        case Display.STATE_ON: pw.print("screen-on"); break;
4630                        case Display.STATE_DOZE: pw.print("screen-doze"); break;
4631                        case Display.STATE_DOZE_SUSPEND: pw.print("screen-doze-suspend"); break;
4632                        default: pw.print("screen-?"); break;
4633                    }
4634                    haveModes = true;
4635                }
4636                if ((modMode&STEP_LEVEL_MODE_POWER_SAVE) == 0) {
4637                    pw.print(haveModes ? ", " : " (");
4638                    pw.print((initMode&STEP_LEVEL_MODE_POWER_SAVE) != 0
4639                            ? "power-save-on" : "power-save-off");
4640                    haveModes = true;
4641                }
4642                if ((modMode&STEP_LEVEL_MODE_DEVICE_IDLE) == 0) {
4643                    pw.print(haveModes ? ", " : " (");
4644                    pw.print((initMode&STEP_LEVEL_MODE_DEVICE_IDLE) != 0
4645                            ? "device-idle-on" : "device-idle-off");
4646                    haveModes = true;
4647                }
4648                if (haveModes) {
4649                    pw.print(")");
4650                }
4651                pw.println();
4652            }
4653        }
4654        return true;
4655    }
4656
4657    public static final int DUMP_CHARGED_ONLY = 1<<1;
4658    public static final int DUMP_DAILY_ONLY = 1<<2;
4659    public static final int DUMP_HISTORY_ONLY = 1<<3;
4660    public static final int DUMP_INCLUDE_HISTORY = 1<<4;
4661    public static final int DUMP_VERBOSE = 1<<5;
4662    public static final int DUMP_DEVICE_WIFI_ONLY = 1<<6;
4663
4664    private void dumpHistoryLocked(PrintWriter pw, int flags, long histStart, boolean checkin) {
4665        final HistoryPrinter hprinter = new HistoryPrinter();
4666        final HistoryItem rec = new HistoryItem();
4667        long lastTime = -1;
4668        long baseTime = -1;
4669        boolean printed = false;
4670        HistoryEventTracker tracker = null;
4671        while (getNextHistoryLocked(rec)) {
4672            lastTime = rec.time;
4673            if (baseTime < 0) {
4674                baseTime = lastTime;
4675            }
4676            if (rec.time >= histStart) {
4677                if (histStart >= 0 && !printed) {
4678                    if (rec.cmd == HistoryItem.CMD_CURRENT_TIME
4679                            || rec.cmd == HistoryItem.CMD_RESET
4680                            || rec.cmd == HistoryItem.CMD_START
4681                            || rec.cmd == HistoryItem.CMD_SHUTDOWN) {
4682                        printed = true;
4683                        hprinter.printNextItem(pw, rec, baseTime, checkin,
4684                                (flags&DUMP_VERBOSE) != 0);
4685                        rec.cmd = HistoryItem.CMD_UPDATE;
4686                    } else if (rec.currentTime != 0) {
4687                        printed = true;
4688                        byte cmd = rec.cmd;
4689                        rec.cmd = HistoryItem.CMD_CURRENT_TIME;
4690                        hprinter.printNextItem(pw, rec, baseTime, checkin,
4691                                (flags&DUMP_VERBOSE) != 0);
4692                        rec.cmd = cmd;
4693                    }
4694                    if (tracker != null) {
4695                        if (rec.cmd != HistoryItem.CMD_UPDATE) {
4696                            hprinter.printNextItem(pw, rec, baseTime, checkin,
4697                                    (flags&DUMP_VERBOSE) != 0);
4698                            rec.cmd = HistoryItem.CMD_UPDATE;
4699                        }
4700                        int oldEventCode = rec.eventCode;
4701                        HistoryTag oldEventTag = rec.eventTag;
4702                        rec.eventTag = new HistoryTag();
4703                        for (int i=0; i<HistoryItem.EVENT_COUNT; i++) {
4704                            HashMap<String, SparseIntArray> active
4705                                    = tracker.getStateForEvent(i);
4706                            if (active == null) {
4707                                continue;
4708                            }
4709                            for (HashMap.Entry<String, SparseIntArray> ent
4710                                    : active.entrySet()) {
4711                                SparseIntArray uids = ent.getValue();
4712                                for (int j=0; j<uids.size(); j++) {
4713                                    rec.eventCode = i;
4714                                    rec.eventTag.string = ent.getKey();
4715                                    rec.eventTag.uid = uids.keyAt(j);
4716                                    rec.eventTag.poolIdx = uids.valueAt(j);
4717                                    hprinter.printNextItem(pw, rec, baseTime, checkin,
4718                                            (flags&DUMP_VERBOSE) != 0);
4719                                    rec.wakeReasonTag = null;
4720                                    rec.wakelockTag = null;
4721                                }
4722                            }
4723                        }
4724                        rec.eventCode = oldEventCode;
4725                        rec.eventTag = oldEventTag;
4726                        tracker = null;
4727                    }
4728                }
4729                hprinter.printNextItem(pw, rec, baseTime, checkin,
4730                        (flags&DUMP_VERBOSE) != 0);
4731            } else if (false && rec.eventCode != HistoryItem.EVENT_NONE) {
4732                // This is an attempt to aggregate the previous state and generate
4733                // fake events to reflect that state at the point where we start
4734                // printing real events.  It doesn't really work right, so is turned off.
4735                if (tracker == null) {
4736                    tracker = new HistoryEventTracker();
4737                }
4738                tracker.updateState(rec.eventCode, rec.eventTag.string,
4739                        rec.eventTag.uid, rec.eventTag.poolIdx);
4740            }
4741        }
4742        if (histStart >= 0) {
4743            commitCurrentHistoryBatchLocked();
4744            pw.print(checkin ? "NEXT: " : "  NEXT: "); pw.println(lastTime+1);
4745        }
4746    }
4747
4748    private void dumpDailyLevelStepSummary(PrintWriter pw, String prefix, String label,
4749            LevelStepTracker steps, StringBuilder tmpSb, int[] tmpOutInt) {
4750        if (steps == null) {
4751            return;
4752        }
4753        long timeRemaining = steps.computeTimeEstimate(0, 0, tmpOutInt);
4754        if (timeRemaining >= 0) {
4755            pw.print(prefix); pw.print(label); pw.print(" total time: ");
4756            tmpSb.setLength(0);
4757            formatTimeMs(tmpSb, timeRemaining);
4758            pw.print(tmpSb);
4759            pw.print(" (from "); pw.print(tmpOutInt[0]);
4760            pw.println(" steps)");
4761        }
4762        for (int i=0; i< STEP_LEVEL_MODES_OF_INTEREST.length; i++) {
4763            long estimatedTime = steps.computeTimeEstimate(STEP_LEVEL_MODES_OF_INTEREST[i],
4764                    STEP_LEVEL_MODE_VALUES[i], tmpOutInt);
4765            if (estimatedTime > 0) {
4766                pw.print(prefix); pw.print(label); pw.print(" ");
4767                pw.print(STEP_LEVEL_MODE_LABELS[i]);
4768                pw.print(" time: ");
4769                tmpSb.setLength(0);
4770                formatTimeMs(tmpSb, estimatedTime);
4771                pw.print(tmpSb);
4772                pw.print(" (from "); pw.print(tmpOutInt[0]);
4773                pw.println(" steps)");
4774            }
4775        }
4776    }
4777
4778    private void dumpDailyPackageChanges(PrintWriter pw, String prefix,
4779            ArrayList<PackageChange> changes) {
4780        if (changes == null) {
4781            return;
4782        }
4783        pw.print(prefix); pw.println("Package changes:");
4784        for (int i=0; i<changes.size(); i++) {
4785            PackageChange pc = changes.get(i);
4786            if (pc.mUpdate) {
4787                pw.print(prefix); pw.print("  Update "); pw.print(pc.mPackageName);
4788                pw.print(" vers="); pw.println(pc.mVersionCode);
4789            } else {
4790                pw.print(prefix); pw.print("  Uninstall "); pw.println(pc.mPackageName);
4791            }
4792        }
4793    }
4794
4795    /**
4796     * Dumps a human-readable summary of the battery statistics to the given PrintWriter.
4797     *
4798     * @param pw a Printer to receive the dump output.
4799     */
4800    @SuppressWarnings("unused")
4801    public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
4802        prepareForDumpLocked();
4803
4804        final boolean filtering = (flags
4805                & (DUMP_HISTORY_ONLY|DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) != 0;
4806
4807        if ((flags&DUMP_HISTORY_ONLY) != 0 || !filtering) {
4808            final long historyTotalSize = getHistoryTotalSize();
4809            final long historyUsedSize = getHistoryUsedSize();
4810            if (startIteratingHistoryLocked()) {
4811                try {
4812                    pw.print("Battery History (");
4813                    pw.print((100*historyUsedSize)/historyTotalSize);
4814                    pw.print("% used, ");
4815                    printSizeValue(pw, historyUsedSize);
4816                    pw.print(" used of ");
4817                    printSizeValue(pw, historyTotalSize);
4818                    pw.print(", ");
4819                    pw.print(getHistoryStringPoolSize());
4820                    pw.print(" strings using ");
4821                    printSizeValue(pw, getHistoryStringPoolBytes());
4822                    pw.println("):");
4823                    dumpHistoryLocked(pw, flags, histStart, false);
4824                    pw.println();
4825                } finally {
4826                    finishIteratingHistoryLocked();
4827                }
4828            }
4829
4830            if (startIteratingOldHistoryLocked()) {
4831                try {
4832                    final HistoryItem rec = new HistoryItem();
4833                    pw.println("Old battery History:");
4834                    HistoryPrinter hprinter = new HistoryPrinter();
4835                    long baseTime = -1;
4836                    while (getNextOldHistoryLocked(rec)) {
4837                        if (baseTime < 0) {
4838                            baseTime = rec.time;
4839                        }
4840                        hprinter.printNextItem(pw, rec, baseTime, false, (flags&DUMP_VERBOSE) != 0);
4841                    }
4842                    pw.println();
4843                } finally {
4844                    finishIteratingOldHistoryLocked();
4845                }
4846            }
4847        }
4848
4849        if (filtering && (flags&(DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) == 0) {
4850            return;
4851        }
4852
4853        if (!filtering) {
4854            SparseArray<? extends Uid> uidStats = getUidStats();
4855            final int NU = uidStats.size();
4856            boolean didPid = false;
4857            long nowRealtime = SystemClock.elapsedRealtime();
4858            for (int i=0; i<NU; i++) {
4859                Uid uid = uidStats.valueAt(i);
4860                SparseArray<? extends Uid.Pid> pids = uid.getPidStats();
4861                if (pids != null) {
4862                    for (int j=0; j<pids.size(); j++) {
4863                        Uid.Pid pid = pids.valueAt(j);
4864                        if (!didPid) {
4865                            pw.println("Per-PID Stats:");
4866                            didPid = true;
4867                        }
4868                        long time = pid.mWakeSumMs + (pid.mWakeNesting > 0
4869                                ? (nowRealtime - pid.mWakeStartMs) : 0);
4870                        pw.print("  PID "); pw.print(pids.keyAt(j));
4871                                pw.print(" wake time: ");
4872                                TimeUtils.formatDuration(time, pw);
4873                                pw.println("");
4874                    }
4875                }
4876            }
4877            if (didPid) {
4878                pw.println();
4879            }
4880        }
4881
4882        if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
4883            if (dumpDurationSteps(pw, "  ", "Discharge step durations:",
4884                    getDischargeLevelStepTracker(), false)) {
4885                long timeRemaining = computeBatteryTimeRemaining(SystemClock.elapsedRealtime());
4886                if (timeRemaining >= 0) {
4887                    pw.print("  Estimated discharge time remaining: ");
4888                    TimeUtils.formatDuration(timeRemaining / 1000, pw);
4889                    pw.println();
4890                }
4891                final LevelStepTracker steps = getDischargeLevelStepTracker();
4892                for (int i=0; i< STEP_LEVEL_MODES_OF_INTEREST.length; i++) {
4893                    dumpTimeEstimate(pw, "  Estimated ", STEP_LEVEL_MODE_LABELS[i], " time: ",
4894                            steps.computeTimeEstimate(STEP_LEVEL_MODES_OF_INTEREST[i],
4895                                    STEP_LEVEL_MODE_VALUES[i], null));
4896                }
4897                pw.println();
4898            }
4899            if (dumpDurationSteps(pw, "  ", "Charge step durations:",
4900                    getChargeLevelStepTracker(), false)) {
4901                long timeRemaining = computeChargeTimeRemaining(SystemClock.elapsedRealtime());
4902                if (timeRemaining >= 0) {
4903                    pw.print("  Estimated charge time remaining: ");
4904                    TimeUtils.formatDuration(timeRemaining / 1000, pw);
4905                    pw.println();
4906                }
4907                pw.println();
4908            }
4909        }
4910        if (!filtering || (flags&(DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) != 0) {
4911            pw.println("Daily stats:");
4912            pw.print("  Current start time: ");
4913            pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss",
4914                    getCurrentDailyStartTime()).toString());
4915            pw.print("  Next min deadline: ");
4916            pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss",
4917                    getNextMinDailyDeadline()).toString());
4918            pw.print("  Next max deadline: ");
4919            pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss",
4920                    getNextMaxDailyDeadline()).toString());
4921            StringBuilder sb = new StringBuilder(64);
4922            int[] outInt = new int[1];
4923            LevelStepTracker dsteps = getDailyDischargeLevelStepTracker();
4924            LevelStepTracker csteps = getDailyChargeLevelStepTracker();
4925            ArrayList<PackageChange> pkgc = getDailyPackageChanges();
4926            if (dsteps.mNumStepDurations > 0 || csteps.mNumStepDurations > 0 || pkgc != null) {
4927                if ((flags&DUMP_DAILY_ONLY) != 0 || !filtering) {
4928                    if (dumpDurationSteps(pw, "    ", "  Current daily discharge step durations:",
4929                            dsteps, false)) {
4930                        dumpDailyLevelStepSummary(pw, "      ", "Discharge", dsteps,
4931                                sb, outInt);
4932                    }
4933                    if (dumpDurationSteps(pw, "    ", "  Current daily charge step durations:",
4934                            csteps, false)) {
4935                        dumpDailyLevelStepSummary(pw, "      ", "Charge", csteps,
4936                                sb, outInt);
4937                    }
4938                    dumpDailyPackageChanges(pw, "    ", pkgc);
4939                } else {
4940                    pw.println("  Current daily steps:");
4941                    dumpDailyLevelStepSummary(pw, "    ", "Discharge", dsteps,
4942                            sb, outInt);
4943                    dumpDailyLevelStepSummary(pw, "    ", "Charge", csteps,
4944                            sb, outInt);
4945                }
4946            }
4947            DailyItem dit;
4948            int curIndex = 0;
4949            while ((dit=getDailyItemLocked(curIndex)) != null) {
4950                curIndex++;
4951                if ((flags&DUMP_DAILY_ONLY) != 0) {
4952                    pw.println();
4953                }
4954                pw.print("  Daily from ");
4955                pw.print(DateFormat.format("yyyy-MM-dd-HH-mm-ss", dit.mStartTime).toString());
4956                pw.print(" to ");
4957                pw.print(DateFormat.format("yyyy-MM-dd-HH-mm-ss", dit.mEndTime).toString());
4958                pw.println(":");
4959                if ((flags&DUMP_DAILY_ONLY) != 0 || !filtering) {
4960                    if (dumpDurationSteps(pw, "      ",
4961                            "    Discharge step durations:", dit.mDischargeSteps, false)) {
4962                        dumpDailyLevelStepSummary(pw, "        ", "Discharge", dit.mDischargeSteps,
4963                                sb, outInt);
4964                    }
4965                    if (dumpDurationSteps(pw, "      ",
4966                            "    Charge step durations:", dit.mChargeSteps, false)) {
4967                        dumpDailyLevelStepSummary(pw, "        ", "Charge", dit.mChargeSteps,
4968                                sb, outInt);
4969                    }
4970                    dumpDailyPackageChanges(pw, "    ", dit.mPackageChanges);
4971                } else {
4972                    dumpDailyLevelStepSummary(pw, "    ", "Discharge", dit.mDischargeSteps,
4973                            sb, outInt);
4974                    dumpDailyLevelStepSummary(pw, "    ", "Charge", dit.mChargeSteps,
4975                            sb, outInt);
4976                }
4977            }
4978            pw.println();
4979        }
4980        if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
4981            pw.println("Statistics since last charge:");
4982            pw.println("  System starts: " + getStartCount()
4983                    + ", currently on battery: " + getIsOnBattery());
4984            dumpLocked(context, pw, "", STATS_SINCE_CHARGED, reqUid,
4985                    (flags&DUMP_DEVICE_WIFI_ONLY) != 0);
4986            pw.println();
4987        }
4988    }
4989
4990    @SuppressWarnings("unused")
4991    public void dumpCheckinLocked(Context context, PrintWriter pw,
4992            List<ApplicationInfo> apps, int flags, long histStart) {
4993        prepareForDumpLocked();
4994
4995        dumpLine(pw, 0 /* uid */, "i" /* category */, VERSION_DATA,
4996                CHECKIN_VERSION, getParcelVersion(), getStartPlatformVersion(),
4997                getEndPlatformVersion());
4998
4999        long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
5000
5001        final boolean filtering = (flags &
5002                (DUMP_HISTORY_ONLY|DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) != 0;
5003
5004        if ((flags&DUMP_INCLUDE_HISTORY) != 0 || (flags&DUMP_HISTORY_ONLY) != 0) {
5005            if (startIteratingHistoryLocked()) {
5006                try {
5007                    for (int i=0; i<getHistoryStringPoolSize(); i++) {
5008                        pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
5009                        pw.print(HISTORY_STRING_POOL); pw.print(',');
5010                        pw.print(i);
5011                        pw.print(",");
5012                        pw.print(getHistoryTagPoolUid(i));
5013                        pw.print(",\"");
5014                        String str = getHistoryTagPoolString(i);
5015                        str = str.replace("\\", "\\\\");
5016                        str = str.replace("\"", "\\\"");
5017                        pw.print(str);
5018                        pw.print("\"");
5019                        pw.println();
5020                    }
5021                    dumpHistoryLocked(pw, flags, histStart, true);
5022                } finally {
5023                    finishIteratingHistoryLocked();
5024                }
5025            }
5026        }
5027
5028        if (filtering && (flags&(DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) == 0) {
5029            return;
5030        }
5031
5032        if (apps != null) {
5033            SparseArray<ArrayList<String>> uids = new SparseArray<ArrayList<String>>();
5034            for (int i=0; i<apps.size(); i++) {
5035                ApplicationInfo ai = apps.get(i);
5036                ArrayList<String> pkgs = uids.get(ai.uid);
5037                if (pkgs == null) {
5038                    pkgs = new ArrayList<String>();
5039                    uids.put(ai.uid, pkgs);
5040                }
5041                pkgs.add(ai.packageName);
5042            }
5043            SparseArray<? extends Uid> uidStats = getUidStats();
5044            final int NU = uidStats.size();
5045            String[] lineArgs = new String[2];
5046            for (int i=0; i<NU; i++) {
5047                int uid = uidStats.keyAt(i);
5048                ArrayList<String> pkgs = uids.get(uid);
5049                if (pkgs != null) {
5050                    for (int j=0; j<pkgs.size(); j++) {
5051                        lineArgs[0] = Integer.toString(uid);
5052                        lineArgs[1] = pkgs.get(j);
5053                        dumpLine(pw, 0 /* uid */, "i" /* category */, UID_DATA,
5054                                (Object[])lineArgs);
5055                    }
5056                }
5057            }
5058        }
5059        if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
5060            dumpDurationSteps(pw, "", DISCHARGE_STEP_DATA, getDischargeLevelStepTracker(), true);
5061            String[] lineArgs = new String[1];
5062            long timeRemaining = computeBatteryTimeRemaining(SystemClock.elapsedRealtime());
5063            if (timeRemaining >= 0) {
5064                lineArgs[0] = Long.toString(timeRemaining);
5065                dumpLine(pw, 0 /* uid */, "i" /* category */, DISCHARGE_TIME_REMAIN_DATA,
5066                        (Object[])lineArgs);
5067            }
5068            dumpDurationSteps(pw, "", CHARGE_STEP_DATA, getChargeLevelStepTracker(), true);
5069            timeRemaining = computeChargeTimeRemaining(SystemClock.elapsedRealtime());
5070            if (timeRemaining >= 0) {
5071                lineArgs[0] = Long.toString(timeRemaining);
5072                dumpLine(pw, 0 /* uid */, "i" /* category */, CHARGE_TIME_REMAIN_DATA,
5073                        (Object[])lineArgs);
5074            }
5075            dumpCheckinLocked(context, pw, STATS_SINCE_CHARGED, -1,
5076                    (flags&DUMP_DEVICE_WIFI_ONLY) != 0);
5077        }
5078    }
5079}
5080