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