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