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