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