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